diff options
304 files changed, 53780 insertions, 230 deletions
diff --git a/ChangeLog b/ChangeLog index 49ba74f4f0d..d6ae1b1aa8c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +2011-11-07 Aldy Hernandez <aldyh@redhat.com> + Richard Henderson <rth@redhat.com> + + Merged from transactional-memory. + + * Makefile.def (lang_env_dependencies): libitm is c++. + Add libitm target module. + * configure.ac: Likewise. + * config/mmap.m4: New file. + * contrib/gcc_update: Add libitm to touch data. + * Makefile.in, configure: Rebuild. + 2011-11-02 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE> * Makefile.tpl (EXTRA_GCC_FLAGS): Remove LIBGCC2_CFLAGS, diff --git a/Makefile.def b/Makefile.def index 5116341d12f..b94dabfffe9 100644 --- a/Makefile.def +++ b/Makefile.def @@ -139,6 +139,7 @@ target_modules = { module= boehm-gc; }; target_modules = { module= rda; }; target_modules = { module= libada; }; target_modules = { module= libgomp; bootstrap= true; lib_path=.libs; }; +target_modules = { module= libitm; lib_path=.libs; }; // These are (some of) the make targets to be done in each subdirectory. // Not all; these are the ones which don't have special options. @@ -470,6 +471,7 @@ dependencies = { module=all-m4; on=all-build-texinfo; }; // environment (e.g. on libstdc++). By default target modules depend // on libgcc and newlib/libgloss. lang_env_dependencies = { module=libjava; cxx=true; }; +lang_env_dependencies = { module=libitm; cxx=true; }; lang_env_dependencies = { module=newlib; no_c=true; }; lang_env_dependencies = { module=libgloss; no_c=true; }; lang_env_dependencies = { module=libgcc; no_gcc=true; no_c=true; }; diff --git a/Makefile.in b/Makefile.in index 821499d7608..900c325849b 100644 --- a/Makefile.in +++ b/Makefile.in @@ -594,7 +594,7 @@ all: # This is the list of directories that may be needed in RPATH_ENVVAR # so that programs built for the target machine work. -TARGET_LIB_PATH = $(TARGET_LIB_PATH_libstdc++-v3)$(TARGET_LIB_PATH_libmudflap)$(TARGET_LIB_PATH_libssp)$(TARGET_LIB_PATH_libgomp)$(HOST_LIB_PATH_gcc) +TARGET_LIB_PATH = $(TARGET_LIB_PATH_libstdc++-v3)$(TARGET_LIB_PATH_libmudflap)$(TARGET_LIB_PATH_libssp)$(TARGET_LIB_PATH_libgomp)$(TARGET_LIB_PATH_libitm)$(HOST_LIB_PATH_gcc) @if target-libstdc++-v3 TARGET_LIB_PATH_libstdc++-v3 = $$r/$(TARGET_SUBDIR)/libstdc++-v3/src/.libs: @@ -612,6 +612,10 @@ TARGET_LIB_PATH_libssp = $$r/$(TARGET_SUBDIR)/libssp/.libs: TARGET_LIB_PATH_libgomp = $$r/$(TARGET_SUBDIR)/libgomp/.libs: @endif target-libgomp +@if target-libitm +TARGET_LIB_PATH_libitm = $$r/$(TARGET_SUBDIR)/libitm/.libs: +@endif target-libitm + # This is the list of directories that may be needed in RPATH_ENVVAR @@ -947,7 +951,8 @@ configure-target: \ maybe-configure-target-boehm-gc \ maybe-configure-target-rda \ maybe-configure-target-libada \ - maybe-configure-target-libgomp + maybe-configure-target-libgomp \ + maybe-configure-target-libitm # The target built for a native non-bootstrap build. .PHONY: all @@ -1094,6 +1099,7 @@ all-target: maybe-all-target-libada @if target-libgomp-no-bootstrap all-target: maybe-all-target-libgomp @endif target-libgomp-no-bootstrap +all-target: maybe-all-target-libitm # Do a target for all the subdirectories. A ``make do-X'' will do a # ``make X'' in all subdirectories (because, in general, there is a @@ -1176,6 +1182,7 @@ info-target: maybe-info-target-boehm-gc info-target: maybe-info-target-rda info-target: maybe-info-target-libada info-target: maybe-info-target-libgomp +info-target: maybe-info-target-libitm .PHONY: do-dvi do-dvi: @@ -1253,6 +1260,7 @@ dvi-target: maybe-dvi-target-boehm-gc dvi-target: maybe-dvi-target-rda dvi-target: maybe-dvi-target-libada dvi-target: maybe-dvi-target-libgomp +dvi-target: maybe-dvi-target-libitm .PHONY: do-pdf do-pdf: @@ -1330,6 +1338,7 @@ pdf-target: maybe-pdf-target-boehm-gc pdf-target: maybe-pdf-target-rda pdf-target: maybe-pdf-target-libada pdf-target: maybe-pdf-target-libgomp +pdf-target: maybe-pdf-target-libitm .PHONY: do-html do-html: @@ -1407,6 +1416,7 @@ html-target: maybe-html-target-boehm-gc html-target: maybe-html-target-rda html-target: maybe-html-target-libada html-target: maybe-html-target-libgomp +html-target: maybe-html-target-libitm .PHONY: do-TAGS do-TAGS: @@ -1484,6 +1494,7 @@ TAGS-target: maybe-TAGS-target-boehm-gc TAGS-target: maybe-TAGS-target-rda TAGS-target: maybe-TAGS-target-libada TAGS-target: maybe-TAGS-target-libgomp +TAGS-target: maybe-TAGS-target-libitm .PHONY: do-install-info do-install-info: @@ -1561,6 +1572,7 @@ install-info-target: maybe-install-info-target-boehm-gc install-info-target: maybe-install-info-target-rda install-info-target: maybe-install-info-target-libada install-info-target: maybe-install-info-target-libgomp +install-info-target: maybe-install-info-target-libitm .PHONY: do-install-pdf do-install-pdf: @@ -1638,6 +1650,7 @@ install-pdf-target: maybe-install-pdf-target-boehm-gc install-pdf-target: maybe-install-pdf-target-rda install-pdf-target: maybe-install-pdf-target-libada install-pdf-target: maybe-install-pdf-target-libgomp +install-pdf-target: maybe-install-pdf-target-libitm .PHONY: do-install-html do-install-html: @@ -1715,6 +1728,7 @@ install-html-target: maybe-install-html-target-boehm-gc install-html-target: maybe-install-html-target-rda install-html-target: maybe-install-html-target-libada install-html-target: maybe-install-html-target-libgomp +install-html-target: maybe-install-html-target-libitm .PHONY: do-installcheck do-installcheck: @@ -1792,6 +1806,7 @@ installcheck-target: maybe-installcheck-target-boehm-gc installcheck-target: maybe-installcheck-target-rda installcheck-target: maybe-installcheck-target-libada installcheck-target: maybe-installcheck-target-libgomp +installcheck-target: maybe-installcheck-target-libitm .PHONY: do-mostlyclean do-mostlyclean: @@ -1869,6 +1884,7 @@ mostlyclean-target: maybe-mostlyclean-target-boehm-gc mostlyclean-target: maybe-mostlyclean-target-rda mostlyclean-target: maybe-mostlyclean-target-libada mostlyclean-target: maybe-mostlyclean-target-libgomp +mostlyclean-target: maybe-mostlyclean-target-libitm .PHONY: do-clean do-clean: @@ -1946,6 +1962,7 @@ clean-target: maybe-clean-target-boehm-gc clean-target: maybe-clean-target-rda clean-target: maybe-clean-target-libada clean-target: maybe-clean-target-libgomp +clean-target: maybe-clean-target-libitm .PHONY: do-distclean do-distclean: @@ -2023,6 +2040,7 @@ distclean-target: maybe-distclean-target-boehm-gc distclean-target: maybe-distclean-target-rda distclean-target: maybe-distclean-target-libada distclean-target: maybe-distclean-target-libgomp +distclean-target: maybe-distclean-target-libitm .PHONY: do-maintainer-clean do-maintainer-clean: @@ -2100,6 +2118,7 @@ maintainer-clean-target: maybe-maintainer-clean-target-boehm-gc maintainer-clean-target: maybe-maintainer-clean-target-rda maintainer-clean-target: maybe-maintainer-clean-target-libada maintainer-clean-target: maybe-maintainer-clean-target-libgomp +maintainer-clean-target: maybe-maintainer-clean-target-libitm # Here are the targets which correspond to the do-X targets. @@ -2231,7 +2250,8 @@ check-target: \ maybe-check-target-boehm-gc \ maybe-check-target-rda \ maybe-check-target-libada \ - maybe-check-target-libgomp + maybe-check-target-libgomp \ + maybe-check-target-libitm do-check: @: $(MAKE); $(unstage) @@ -2380,7 +2400,8 @@ install-target: \ maybe-install-target-boehm-gc \ maybe-install-target-rda \ maybe-install-target-libada \ - maybe-install-target-libgomp + maybe-install-target-libgomp \ + maybe-install-target-libitm uninstall: @echo "the uninstall target is not supported in this tree" @@ -2476,7 +2497,8 @@ install-strip-target: \ maybe-install-strip-target-boehm-gc \ maybe-install-strip-target-rda \ maybe-install-strip-target-libada \ - maybe-install-strip-target-libgomp + maybe-install-strip-target-libgomp \ + maybe-install-strip-target-libitm ### other supporting targets @@ -40142,6 +40164,463 @@ maintainer-clean-target-libgomp: + + +.PHONY: configure-target-libitm maybe-configure-target-libitm +maybe-configure-target-libitm: +@if gcc-bootstrap +configure-target-libitm: stage_current +@endif gcc-bootstrap +@if target-libitm +maybe-configure-target-libitm: configure-target-libitm +configure-target-libitm: + @: $(MAKE); $(unstage) + @r=`${PWD_COMMAND}`; export r; \ + s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \ + echo "Checking multilib configuration for libitm..."; \ + $(SHELL) $(srcdir)/mkinstalldirs $(TARGET_SUBDIR)/libitm ; \ + $(CC_FOR_TARGET) --print-multi-lib > $(TARGET_SUBDIR)/libitm/multilib.tmp 2> /dev/null ; \ + if test -r $(TARGET_SUBDIR)/libitm/multilib.out; then \ + if cmp -s $(TARGET_SUBDIR)/libitm/multilib.tmp $(TARGET_SUBDIR)/libitm/multilib.out; then \ + rm -f $(TARGET_SUBDIR)/libitm/multilib.tmp; \ + else \ + rm -f $(TARGET_SUBDIR)/libitm/Makefile; \ + mv $(TARGET_SUBDIR)/libitm/multilib.tmp $(TARGET_SUBDIR)/libitm/multilib.out; \ + fi; \ + else \ + mv $(TARGET_SUBDIR)/libitm/multilib.tmp $(TARGET_SUBDIR)/libitm/multilib.out; \ + fi; \ + test ! -f $(TARGET_SUBDIR)/libitm/Makefile || exit 0; \ + $(SHELL) $(srcdir)/mkinstalldirs $(TARGET_SUBDIR)/libitm ; \ + $(NORMAL_TARGET_EXPORTS) \ + echo Configuring in $(TARGET_SUBDIR)/libitm; \ + cd "$(TARGET_SUBDIR)/libitm" || exit 1; \ + case $(srcdir) in \ + /* | [A-Za-z]:[\\/]*) topdir=$(srcdir) ;; \ + *) topdir=`echo $(TARGET_SUBDIR)/libitm/ | \ + sed -e 's,\./,,g' -e 's,[^/]*/,../,g' `$(srcdir) ;; \ + esac; \ + srcdiroption="--srcdir=$${topdir}/libitm"; \ + libsrcdir="$$s/libitm"; \ + rm -f no-such-file || : ; \ + CONFIG_SITE=no-such-file $(SHELL) $${libsrcdir}/configure \ + $(TARGET_CONFIGARGS) --build=${build_alias} --host=${target_alias} \ + --target=${target_alias} $${srcdiroption} \ + || exit 1 +@endif target-libitm + + + + + +.PHONY: all-target-libitm maybe-all-target-libitm +maybe-all-target-libitm: +@if gcc-bootstrap +all-target-libitm: stage_current +@endif gcc-bootstrap +@if target-libitm +TARGET-target-libitm=all +maybe-all-target-libitm: all-target-libitm +all-target-libitm: configure-target-libitm + @: $(MAKE); $(unstage) + @r=`${PWD_COMMAND}`; export r; \ + s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \ + $(NORMAL_TARGET_EXPORTS) \ + (cd $(TARGET_SUBDIR)/libitm && \ + $(MAKE) $(BASE_FLAGS_TO_PASS) $(EXTRA_TARGET_FLAGS) \ + $(TARGET-target-libitm)) +@endif target-libitm + + + + + +.PHONY: check-target-libitm maybe-check-target-libitm +maybe-check-target-libitm: +@if target-libitm +maybe-check-target-libitm: check-target-libitm + +check-target-libitm: + @: $(MAKE); $(unstage) + @r=`${PWD_COMMAND}`; export r; \ + s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \ + $(NORMAL_TARGET_EXPORTS) \ + (cd $(TARGET_SUBDIR)/libitm && \ + $(MAKE) $(TARGET_FLAGS_TO_PASS) check) + +@endif target-libitm + +.PHONY: install-target-libitm maybe-install-target-libitm +maybe-install-target-libitm: +@if target-libitm +maybe-install-target-libitm: install-target-libitm + +install-target-libitm: installdirs + @: $(MAKE); $(unstage) + @r=`${PWD_COMMAND}`; export r; \ + s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \ + $(NORMAL_TARGET_EXPORTS) \ + (cd $(TARGET_SUBDIR)/libitm && \ + $(MAKE) $(TARGET_FLAGS_TO_PASS) install) + +@endif target-libitm + +.PHONY: install-strip-target-libitm maybe-install-strip-target-libitm +maybe-install-strip-target-libitm: +@if target-libitm +maybe-install-strip-target-libitm: install-strip-target-libitm + +install-strip-target-libitm: installdirs + @: $(MAKE); $(unstage) + @r=`${PWD_COMMAND}`; export r; \ + s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \ + $(NORMAL_TARGET_EXPORTS) \ + (cd $(TARGET_SUBDIR)/libitm && \ + $(MAKE) $(TARGET_FLAGS_TO_PASS) install-strip) + +@endif target-libitm + +# Other targets (info, dvi, pdf, etc.) + +.PHONY: maybe-info-target-libitm info-target-libitm +maybe-info-target-libitm: +@if target-libitm +maybe-info-target-libitm: info-target-libitm + +info-target-libitm: \ + configure-target-libitm + @: $(MAKE); $(unstage) + @[ -f $(TARGET_SUBDIR)/libitm/Makefile ] || exit 0 ; \ + r=`${PWD_COMMAND}`; export r; \ + s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \ + $(NORMAL_TARGET_EXPORTS) \ + echo "Doing info in $(TARGET_SUBDIR)/libitm" ; \ + for flag in $(EXTRA_TARGET_FLAGS); do \ + eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \ + done; \ + (cd $(TARGET_SUBDIR)/libitm && \ + $(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \ + "CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \ + "RANLIB=$${RANLIB}" \ + "DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" "WINDMC=$${WINDMC}" \ + info) \ + || exit 1 + +@endif target-libitm + +.PHONY: maybe-dvi-target-libitm dvi-target-libitm +maybe-dvi-target-libitm: +@if target-libitm +maybe-dvi-target-libitm: dvi-target-libitm + +dvi-target-libitm: \ + configure-target-libitm + @: $(MAKE); $(unstage) + @[ -f $(TARGET_SUBDIR)/libitm/Makefile ] || exit 0 ; \ + r=`${PWD_COMMAND}`; export r; \ + s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \ + $(NORMAL_TARGET_EXPORTS) \ + echo "Doing dvi in $(TARGET_SUBDIR)/libitm" ; \ + for flag in $(EXTRA_TARGET_FLAGS); do \ + eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \ + done; \ + (cd $(TARGET_SUBDIR)/libitm && \ + $(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \ + "CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \ + "RANLIB=$${RANLIB}" \ + "DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" "WINDMC=$${WINDMC}" \ + dvi) \ + || exit 1 + +@endif target-libitm + +.PHONY: maybe-pdf-target-libitm pdf-target-libitm +maybe-pdf-target-libitm: +@if target-libitm +maybe-pdf-target-libitm: pdf-target-libitm + +pdf-target-libitm: \ + configure-target-libitm + @: $(MAKE); $(unstage) + @[ -f $(TARGET_SUBDIR)/libitm/Makefile ] || exit 0 ; \ + r=`${PWD_COMMAND}`; export r; \ + s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \ + $(NORMAL_TARGET_EXPORTS) \ + echo "Doing pdf in $(TARGET_SUBDIR)/libitm" ; \ + for flag in $(EXTRA_TARGET_FLAGS); do \ + eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \ + done; \ + (cd $(TARGET_SUBDIR)/libitm && \ + $(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \ + "CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \ + "RANLIB=$${RANLIB}" \ + "DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" "WINDMC=$${WINDMC}" \ + pdf) \ + || exit 1 + +@endif target-libitm + +.PHONY: maybe-html-target-libitm html-target-libitm +maybe-html-target-libitm: +@if target-libitm +maybe-html-target-libitm: html-target-libitm + +html-target-libitm: \ + configure-target-libitm + @: $(MAKE); $(unstage) + @[ -f $(TARGET_SUBDIR)/libitm/Makefile ] || exit 0 ; \ + r=`${PWD_COMMAND}`; export r; \ + s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \ + $(NORMAL_TARGET_EXPORTS) \ + echo "Doing html in $(TARGET_SUBDIR)/libitm" ; \ + for flag in $(EXTRA_TARGET_FLAGS); do \ + eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \ + done; \ + (cd $(TARGET_SUBDIR)/libitm && \ + $(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \ + "CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \ + "RANLIB=$${RANLIB}" \ + "DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" "WINDMC=$${WINDMC}" \ + html) \ + || exit 1 + +@endif target-libitm + +.PHONY: maybe-TAGS-target-libitm TAGS-target-libitm +maybe-TAGS-target-libitm: +@if target-libitm +maybe-TAGS-target-libitm: TAGS-target-libitm + +TAGS-target-libitm: \ + configure-target-libitm + @: $(MAKE); $(unstage) + @[ -f $(TARGET_SUBDIR)/libitm/Makefile ] || exit 0 ; \ + r=`${PWD_COMMAND}`; export r; \ + s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \ + $(NORMAL_TARGET_EXPORTS) \ + echo "Doing TAGS in $(TARGET_SUBDIR)/libitm" ; \ + for flag in $(EXTRA_TARGET_FLAGS); do \ + eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \ + done; \ + (cd $(TARGET_SUBDIR)/libitm && \ + $(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \ + "CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \ + "RANLIB=$${RANLIB}" \ + "DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" "WINDMC=$${WINDMC}" \ + TAGS) \ + || exit 1 + +@endif target-libitm + +.PHONY: maybe-install-info-target-libitm install-info-target-libitm +maybe-install-info-target-libitm: +@if target-libitm +maybe-install-info-target-libitm: install-info-target-libitm + +install-info-target-libitm: \ + configure-target-libitm \ + info-target-libitm + @: $(MAKE); $(unstage) + @[ -f $(TARGET_SUBDIR)/libitm/Makefile ] || exit 0 ; \ + r=`${PWD_COMMAND}`; export r; \ + s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \ + $(NORMAL_TARGET_EXPORTS) \ + echo "Doing install-info in $(TARGET_SUBDIR)/libitm" ; \ + for flag in $(EXTRA_TARGET_FLAGS); do \ + eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \ + done; \ + (cd $(TARGET_SUBDIR)/libitm && \ + $(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \ + "CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \ + "RANLIB=$${RANLIB}" \ + "DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" "WINDMC=$${WINDMC}" \ + install-info) \ + || exit 1 + +@endif target-libitm + +.PHONY: maybe-install-pdf-target-libitm install-pdf-target-libitm +maybe-install-pdf-target-libitm: +@if target-libitm +maybe-install-pdf-target-libitm: install-pdf-target-libitm + +install-pdf-target-libitm: \ + configure-target-libitm \ + pdf-target-libitm + @: $(MAKE); $(unstage) + @[ -f $(TARGET_SUBDIR)/libitm/Makefile ] || exit 0 ; \ + r=`${PWD_COMMAND}`; export r; \ + s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \ + $(NORMAL_TARGET_EXPORTS) \ + echo "Doing install-pdf in $(TARGET_SUBDIR)/libitm" ; \ + for flag in $(EXTRA_TARGET_FLAGS); do \ + eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \ + done; \ + (cd $(TARGET_SUBDIR)/libitm && \ + $(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \ + "CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \ + "RANLIB=$${RANLIB}" \ + "DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" "WINDMC=$${WINDMC}" \ + install-pdf) \ + || exit 1 + +@endif target-libitm + +.PHONY: maybe-install-html-target-libitm install-html-target-libitm +maybe-install-html-target-libitm: +@if target-libitm +maybe-install-html-target-libitm: install-html-target-libitm + +install-html-target-libitm: \ + configure-target-libitm \ + html-target-libitm + @: $(MAKE); $(unstage) + @[ -f $(TARGET_SUBDIR)/libitm/Makefile ] || exit 0 ; \ + r=`${PWD_COMMAND}`; export r; \ + s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \ + $(NORMAL_TARGET_EXPORTS) \ + echo "Doing install-html in $(TARGET_SUBDIR)/libitm" ; \ + for flag in $(EXTRA_TARGET_FLAGS); do \ + eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \ + done; \ + (cd $(TARGET_SUBDIR)/libitm && \ + $(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \ + "CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \ + "RANLIB=$${RANLIB}" \ + "DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" "WINDMC=$${WINDMC}" \ + install-html) \ + || exit 1 + +@endif target-libitm + +.PHONY: maybe-installcheck-target-libitm installcheck-target-libitm +maybe-installcheck-target-libitm: +@if target-libitm +maybe-installcheck-target-libitm: installcheck-target-libitm + +installcheck-target-libitm: \ + configure-target-libitm + @: $(MAKE); $(unstage) + @[ -f $(TARGET_SUBDIR)/libitm/Makefile ] || exit 0 ; \ + r=`${PWD_COMMAND}`; export r; \ + s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \ + $(NORMAL_TARGET_EXPORTS) \ + echo "Doing installcheck in $(TARGET_SUBDIR)/libitm" ; \ + for flag in $(EXTRA_TARGET_FLAGS); do \ + eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \ + done; \ + (cd $(TARGET_SUBDIR)/libitm && \ + $(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \ + "CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \ + "RANLIB=$${RANLIB}" \ + "DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" "WINDMC=$${WINDMC}" \ + installcheck) \ + || exit 1 + +@endif target-libitm + +.PHONY: maybe-mostlyclean-target-libitm mostlyclean-target-libitm +maybe-mostlyclean-target-libitm: +@if target-libitm +maybe-mostlyclean-target-libitm: mostlyclean-target-libitm + +mostlyclean-target-libitm: + @: $(MAKE); $(unstage) + @[ -f $(TARGET_SUBDIR)/libitm/Makefile ] || exit 0 ; \ + r=`${PWD_COMMAND}`; export r; \ + s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \ + $(NORMAL_TARGET_EXPORTS) \ + echo "Doing mostlyclean in $(TARGET_SUBDIR)/libitm" ; \ + for flag in $(EXTRA_TARGET_FLAGS); do \ + eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \ + done; \ + (cd $(TARGET_SUBDIR)/libitm && \ + $(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \ + "CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \ + "RANLIB=$${RANLIB}" \ + "DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" "WINDMC=$${WINDMC}" \ + mostlyclean) \ + || exit 1 + +@endif target-libitm + +.PHONY: maybe-clean-target-libitm clean-target-libitm +maybe-clean-target-libitm: +@if target-libitm +maybe-clean-target-libitm: clean-target-libitm + +clean-target-libitm: + @: $(MAKE); $(unstage) + @[ -f $(TARGET_SUBDIR)/libitm/Makefile ] || exit 0 ; \ + r=`${PWD_COMMAND}`; export r; \ + s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \ + $(NORMAL_TARGET_EXPORTS) \ + echo "Doing clean in $(TARGET_SUBDIR)/libitm" ; \ + for flag in $(EXTRA_TARGET_FLAGS); do \ + eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \ + done; \ + (cd $(TARGET_SUBDIR)/libitm && \ + $(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \ + "CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \ + "RANLIB=$${RANLIB}" \ + "DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" "WINDMC=$${WINDMC}" \ + clean) \ + || exit 1 + +@endif target-libitm + +.PHONY: maybe-distclean-target-libitm distclean-target-libitm +maybe-distclean-target-libitm: +@if target-libitm +maybe-distclean-target-libitm: distclean-target-libitm + +distclean-target-libitm: + @: $(MAKE); $(unstage) + @[ -f $(TARGET_SUBDIR)/libitm/Makefile ] || exit 0 ; \ + r=`${PWD_COMMAND}`; export r; \ + s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \ + $(NORMAL_TARGET_EXPORTS) \ + echo "Doing distclean in $(TARGET_SUBDIR)/libitm" ; \ + for flag in $(EXTRA_TARGET_FLAGS); do \ + eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \ + done; \ + (cd $(TARGET_SUBDIR)/libitm && \ + $(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \ + "CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \ + "RANLIB=$${RANLIB}" \ + "DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" "WINDMC=$${WINDMC}" \ + distclean) \ + || exit 1 + +@endif target-libitm + +.PHONY: maybe-maintainer-clean-target-libitm maintainer-clean-target-libitm +maybe-maintainer-clean-target-libitm: +@if target-libitm +maybe-maintainer-clean-target-libitm: maintainer-clean-target-libitm + +maintainer-clean-target-libitm: + @: $(MAKE); $(unstage) + @[ -f $(TARGET_SUBDIR)/libitm/Makefile ] || exit 0 ; \ + r=`${PWD_COMMAND}`; export r; \ + s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \ + $(NORMAL_TARGET_EXPORTS) \ + echo "Doing maintainer-clean in $(TARGET_SUBDIR)/libitm" ; \ + for flag in $(EXTRA_TARGET_FLAGS); do \ + eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \ + done; \ + (cd $(TARGET_SUBDIR)/libitm && \ + $(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \ + "CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \ + "RANLIB=$${RANLIB}" \ + "DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" "WINDMC=$${WINDMC}" \ + maintainer-clean) \ + || exit 1 + +@endif target-libitm + + + @if target-libmudflap .PHONY: check-target-libmudflap-c++ check-target-libmudflap-c++: @@ -42233,6 +42712,7 @@ configure-stage3-target-libgomp: maybe-all-stage3-gcc configure-stage4-target-libgomp: maybe-all-stage4-gcc configure-stageprofile-target-libgomp: maybe-all-stageprofile-gcc configure-stagefeedback-target-libgomp: maybe-all-stagefeedback-gcc +configure-target-libitm: stage_last @endif gcc-bootstrap @if gcc-no-bootstrap @@ -42255,6 +42735,7 @@ configure-target-boehm-gc: maybe-all-gcc configure-target-rda: maybe-all-gcc configure-target-libada: maybe-all-gcc configure-target-libgomp: maybe-all-gcc +configure-target-libitm: maybe-all-gcc @endif gcc-no-bootstrap @@ -43028,6 +43509,7 @@ configure-target-boehm-gc: maybe-all-target-libgcc configure-target-rda: maybe-all-target-libgcc configure-target-libada: maybe-all-target-libgcc configure-target-libgomp: maybe-all-target-libgcc +configure-target-libitm: maybe-all-target-libgcc @endif gcc-no-bootstrap @@ -43067,6 +43549,9 @@ configure-target-libada: maybe-all-target-newlib maybe-all-target-libgloss configure-target-libgomp: maybe-all-target-newlib maybe-all-target-libgloss +configure-target-libitm: maybe-all-target-newlib maybe-all-target-libgloss +configure-target-libitm: maybe-all-target-libstdc++-v3 + CONFIGURE_GDB_TK = @CONFIGURE_GDB_TK@ GDB_TK = @GDB_TK@ diff --git a/config/mmap.m4 b/config/mmap.m4 new file mode 100644 index 00000000000..39d79afc749 --- /dev/null +++ b/config/mmap.m4 @@ -0,0 +1,97 @@ +dnl ---------------------------------------------------------------------- +dnl This whole bit snagged from gcc + +dnl +dnl mmap(2) blacklisting. Some platforms provide the mmap library routine +dnl but don't support all of the features we need from it. +dnl +AC_DEFUN([GCC_AC_FUNC_MMAP_BLACKLIST], +[ +AC_CHECK_HEADER([sys/mman.h], + [gcc_header_sys_mman_h=yes], [gcc_header_sys_mman_h=no]) +AC_CHECK_FUNC([mmap], [gcc_func_mmap=yes], [gcc_func_mmap=no]) +if test "$gcc_header_sys_mman_h" != yes \ + || test "$gcc_func_mmap" != yes; then + gcc_cv_func_mmap_file=no + gcc_cv_func_mmap_dev_zero=no + gcc_cv_func_mmap_anon=no +else + AC_CACHE_CHECK([whether read-only mmap of a plain file works], + gcc_cv_func_mmap_file, + [# Add a system to this blacklist if + # mmap(0, stat_size, PROT_READ, MAP_PRIVATE, fd, 0) doesn't return a + # memory area containing the same data that you'd get if you applied + # read() to the same fd. The only system known to have a problem here + # is VMS, where text files have record structure. + case "$host_os" in + vms* | ultrix*) + gcc_cv_func_mmap_file=no ;; + *) + gcc_cv_func_mmap_file=yes;; + esac]) + AC_CACHE_CHECK([whether mmap from /dev/zero works], + gcc_cv_func_mmap_dev_zero, + [# Add a system to this blacklist if it has mmap() but /dev/zero + # does not exist, or if mmapping /dev/zero does not give anonymous + # zeroed pages with both the following properties: + # 1. If you map N consecutive pages in with one call, and then + # unmap any subset of those pages, the pages that were not + # explicitly unmapped remain accessible. + # 2. If you map two adjacent blocks of memory and then unmap them + # both at once, they must both go away. + # Systems known to be in this category are Windows (all variants), + # VMS, and Darwin. + case "$host_os" in + vms* | cygwin* | pe | mingw* | darwin* | ultrix* | hpux10* | hpux11.00) + gcc_cv_func_mmap_dev_zero=no ;; + *) + gcc_cv_func_mmap_dev_zero=yes;; + esac]) + + # Unlike /dev/zero, the MAP_ANON(YMOUS) defines can be probed for. + AC_CACHE_CHECK([for MAP_ANON(YMOUS)], gcc_cv_decl_map_anon, + [AC_COMPILE_IFELSE([AC_LANG_PROGRAM( +[#include <sys/types.h> +#include <sys/mman.h> +#include <unistd.h> + +#ifndef MAP_ANONYMOUS +#define MAP_ANONYMOUS MAP_ANON +#endif +], +[int n = MAP_ANONYMOUS;])], + gcc_cv_decl_map_anon=yes, + gcc_cv_decl_map_anon=no)]) + + if test $gcc_cv_decl_map_anon = no; then + gcc_cv_func_mmap_anon=no + else + AC_CACHE_CHECK([whether mmap with MAP_ANON(YMOUS) works], + gcc_cv_func_mmap_anon, + [# Add a system to this blacklist if it has mmap() and MAP_ANON or + # MAP_ANONYMOUS, but using mmap(..., MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) + # doesn't give anonymous zeroed pages with the same properties listed + # above for use of /dev/zero. + # Systems known to be in this category are Windows, VMS, and SCO Unix. + case "$host_os" in + vms* | cygwin* | pe | mingw* | sco* | udk* ) + gcc_cv_func_mmap_anon=no ;; + *) + gcc_cv_func_mmap_anon=yes;; + esac]) + fi +fi + +if test $gcc_cv_func_mmap_file = yes; then + AC_DEFINE(HAVE_MMAP_FILE, 1, + [Define if read-only mmap of a plain file works.]) +fi +if test $gcc_cv_func_mmap_dev_zero = yes; then + AC_DEFINE(HAVE_MMAP_DEV_ZERO, 1, + [Define if mmap of /dev/zero works.]) +fi +if test $gcc_cv_func_mmap_anon = yes; then + AC_DEFINE(HAVE_MMAP_ANON, 1, + [Define if mmap with MAP_ANON(YMOUS) works.]) +fi +]) diff --git a/configure b/configure index eb69f28d59e..03d00483411 100755 --- a/configure +++ b/configure @@ -2681,6 +2681,7 @@ target_libraries="target-libgcc \ target-libgloss \ target-newlib \ target-libgomp \ + target-libitm \ target-libstdc++-v3 \ target-libmudflap \ target-libssp \ @@ -3056,6 +3057,24 @@ if test x$enable_libgomp = x ; then esac fi +# Disable libitm on non POSIX hosted systems. +if test x$enable_libitm = x ; then + # Enable libitm by default on hosted POSIX systems. + case "${target}" in + *-*-linux* | *-*-gnu* | *-*-k*bsd*-gnu) + ;; + *-*-netbsd* | *-*-freebsd* | *-*-openbsd*) + ;; + *-*-solaris2* | *-*-sysv4* | *-*-irix6* | *-*-osf* | *-*-hpux11*) + ;; + *-*-darwin* | *-*-aix*) + ;; + *) + noconfigdirs="$noconfigdirs target-libitm" + ;; + esac +fi + # Disable libssp for some systems. case "${target}" in avr-*-*) diff --git a/configure.ac b/configure.ac index 337e11d202a..4bca6d82f46 100644 --- a/configure.ac +++ b/configure.ac @@ -154,6 +154,7 @@ target_libraries="target-libgcc \ target-libgloss \ target-newlib \ target-libgomp \ + target-libitm \ target-libstdc++-v3 \ target-libmudflap \ target-libssp \ @@ -492,6 +493,24 @@ if test x$enable_libgomp = x ; then esac fi +# Disable libitm on non POSIX hosted systems. +if test x$enable_libitm = x ; then + # Enable libitm by default on hosted POSIX systems. + case "${target}" in + *-*-linux* | *-*-gnu* | *-*-k*bsd*-gnu) + ;; + *-*-netbsd* | *-*-freebsd* | *-*-openbsd*) + ;; + *-*-solaris2* | *-*-sysv4* | *-*-irix6* | *-*-osf* | *-*-hpux11*) + ;; + *-*-darwin* | *-*-aix*) + ;; + *) + noconfigdirs="$noconfigdirs target-libitm" + ;; + esac +fi + # Disable libssp for some systems. case "${target}" in avr-*-*) diff --git a/contrib/ChangeLog b/contrib/ChangeLog index ed2ff363555..b3828975b68 100644 --- a/contrib/ChangeLog +++ b/contrib/ChangeLog @@ -1,3 +1,9 @@ +2011-11-07 Richard Henderson <rth@redhat.com> + + Merged from transactional-memory. + + * gcc_update: Add libitm to touch data. + 2011-11-07 Quentin Neill <quentin.neill@amd.com> * compare_tests: Add ability to compare all .sum diff --git a/contrib/gcc_update b/contrib/gcc_update index c7195023c79..3612880c2a4 100755 --- a/contrib/gcc_update +++ b/contrib/gcc_update @@ -136,6 +136,11 @@ libgomp/Makefile.in: libgomp/Makefile.am libgomp/aclocal.m4 libgomp/testsuite/Makefile.in: libgomp/Makefile.am libgomp/aclocal.m4 libgomp/configure: libgomp/configure.ac libgomp/aclocal.m4 libgomp/config.h.in: libgomp/configure.ac libgomp/aclocal.m4 +libitm/aclocal.m4: libitm/configure.ac libitm/acinclude.m4 +libitm/Makefile.in: libitm/Makefile.am libitm/aclocal.m4 +libitm/testsuite/Makefile.in: libitm/testsuite/Makefile.am libitm/aclocal.m4 +libitm/configure: libitm/configure.ac libitm/aclocal.m4 +libitm/config.h.in: libitm/configure.ac libitm/aclocal.m4 # Top level Makefile.in: Makefile.tpl Makefile.def configure: configure.ac config/acx.m4 diff --git a/gcc/ChangeLog b/gcc/ChangeLog index cfde0b63175..e6816e58628 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,4 +1,202 @@ 2011-11-07 Richard Henderson <rth@redhat.com> + Aldy Hernandez <aldyh@redhat.com> + Andrew MacLeod <amacleod@redhat.com> + Torvald Riegel <triegel@redhat.com> + + Merged from transactional-memory. + + * gtm-builtins.def: New file. + * trans-mem.c: New file. + * trans-mem.h: New file. + + * opts.c (finish_options): Error out when using -flto and + -fgnu-tm. + + * config/i386/i386.c: Define TARGET_VECTORIZE* transactional variants. + (ix86_handle_tm_regparm_attribute, struct bdesc_tm, + ix86_builtin_tm_load, ix86_builtin_tm_store, + ix86_init_tm_builtins): New. + (ix86_init_builtins): Initialize TM builtins. + (struct ix86_attribute_table): Add "*tm regparm". + * config/i386/i386-builtin-types.def (PV2SI): Define. + (PCV2SI): Define. + Define V2SI_FTYPE_PCV2SI. + Define V4SF_FTYPE_PCV4SF. + Define V8SF_FTYPE_PCV8SF. + Define VOID_PV2SI_V2SI. + + * doc/invoke.texi (C Dialect Options): Document -fgnu-tm and + tm-max-aggregate-size. + * doc/tm.texi.in: Add TARGET_VECTORIZE_BUILTIN_TM_LOAD and + TARGET_VECTORIZE_BUILTIN_TM_STORE hooks. + * doc/tm.texi: Regenerate. + + * attribs.c (apply_tm_attr): New. + (init_attributes): Allow '*' prefix for overrides. + (register_attribute): Likewise. + * builtin-attrs.def (ATTR_TM_TMPURE, ATTR_TM_REGPARM): New. + (ATTR_TM_NOTHROW_LIST, ATTR_TM_TMPURE_NOTHROW_LIST, + ATTR_TM_PURE_TMPURE_NOTHROW_LIST, ATTR_TM_NORETURN_NOTHROW_LIST, + ATTR_TM_CONST_NOTHROW_LIST, ATTR_TMPURE_MALLOC_NOTHROW_LIST, + ATTR_TMPURE_NOTHROW_LIST): New. + * builtin-types.def (BT_FN_I[1248]_VPTR, BT_FN_FLOAT_VPTR, + BT_FN_DOUBLE_VPTR, BT_FN_LDOUBLE_VPTR, BT_FN_VOID_VPTR_I[1248], + BT_FN_VOID_VPTR_FLOAT, BT_FN_VOID_VPTR_DOUBLE, + BT_FN_VOID_VPTR_LDOUBLE, BT_FN_VOID_VPTR_SIZE): New. + * builtins.def: Include gtm-builtins.def. Add comments regarding + transactional memory synchronization. + (DEF_TM_BUILTIN): New. + * c-parser.c (struct c_parser): Add in_transaction. + (c_parser_transaction, c_parser_transaction_expression, + c_parser_transaction_cancel, c_parser_transaction_attributes): New. + (c_parser_attribute_any_word): Split out from c_parser_attributes. + (c_parser_statement_after_labels): Handle RID_TRANSACTION*. + (c_parser_unary_expression): Same. + * c-tree.h (c_finish_transaction): Declare. + * c-typeck.c (c_finish_transaction): New. + (build_function_call_vec): Call tm_malloc_replacement. + * calls.c (is_tm_builtin): New. + (flags_from_decl_or_type): Add ECF_TM_BUILTIN and ECF_TM_PURE. + * cfgbuild.c (make_edges): Add edges for REG_TM notes. + * cfgexpand.c (expand_call_stmt): Call + mark_transaction_restart_calls. + (gimple_expand_cfg): Free the tm_restart map. + (mark_transaction_restart_calls): New. + * cfgrtl.c (purge_dead_edges): Look for REG_TM notes. + * cgraph.c (dump_cgraph_node): Handle tm_clone. + * cgraph.h (struct cgraph_node): Add tm_clone field. + (decl_is_tm_clone): New. + (struct cgraph_local_info): Add tm_may_enter_irr. + (cgraph_copy_node_for_versioning): Declare. + * cgraphunit.c (cgraph_copy_node_for_versioning): Export; + copy analyzed from old version. + * combine.c (distribute_notes): Handle REG_TM notes. + * common.opt: Add -fgnu-tm. + * crtstuff.c (__TMC_LIST__, __TMC_END__): New. + (__do_global_dtors_aux): Deregister clone table. + (frame_dummy): Register clone table. + * emit-rtl.c (try_split): Handle REG_TM. Early return if no function + body. + * gimple-low.c (lower_stmt): Handle GIMPLE_EH_ELSE and + GIMPLE_TRANSACTION. + (gimple_stmt_may_fallthru): Handle GIMPLE_EH_ELSE. + * gimple-pretty-print.c: Include trans-mem.h. + (dump_gimple_fmt): Add %x. + (dump_gimple_call): Dump arguments for calls to _ITM_beginTransaction. + (dump_gimple_eh_else, dump_gimple_transaction): New. + (dump_gimple_stmt): Handle GIMPLE_EH_ELSE and GIMPLE_TRANSACTION. + * gimple.c (gimple_build_eh_else, gimple_build_transaction): New. + (walk_gimple_seq): Honor removed_stmt. Document usage of removed_stmt + field. + (walk_gimple_op): Handle GIMPLE_TRANSACTION. + (walk_gimple_stmt): Initialize and honor removed_stmt. + Handle GIMPLE_EH_ELSE and GIMPLE_TRANSACTION. + (gimple_copy): Handle GIMPLE_EH_ELSE and GIMPLE_TRANSACTION. + * gimple.def (GIMPLE_TRANSACTION, GIMPLE_EH_ELSE): New. + * gimple.h (struct gimple_statement_eh_else, + gimple_statement_transaction, GTMA_*): New. + (gimple_statement_d): Add gimple_statement_eh_else and + gimple_transaction. + (gimple_build_eh_else, gimple_build_transaction, + gimple_fold_call, diagnose_tm_safe_errors): Declare. + (get_call_expr_in): Remove prototype. + (gimple_has_substatements): Add GIMPLE_EH_ELSE and GIMPLE_TRANSACTION. + (gimple_eh_else_n_body, gimple_eh_else_e_body, + gimple_eh_else_set_n_body, gimple_eh_else_set_e_body, + gimple_transaction_body, gimple_transaction_label, + gimple_transaction_label_ptr, gimple_transaction_subcode, + gimple_transaction_set_body, gimple_transaction_set_label, + gimple_transaction_set_subcode): New. + (struct walk_stmt_info): Use BOOL_BITFIELD; add removed_stmt. + * gimplify.c (create_tmp_var_name): Use clean_symbol_name. + (voidify_wrapper_expr): Handle TRANSACTION_EXPR. + (gimplify_transaction): New. + (gimplify_expr): Handle TRANSACTION_EXPR. + * gsstruct.def (GSS_EH_ELSE, GSS_TRANSACTION): New. + * ipa-inline.c (can_inline_edge_p): Do not inline TM safe calling + TM pure functions. + * Makefile.in: Add trans-mem.o and dependencies. + (BUILTINS_DEF): Add gtm-builtins.def. + (gimple-pretty-print.o): Depend on TRANS_MEM_H. + (GTFILES): Add trans-mem.c. + * omp-low.c (WALK_SUBSTMTS): Add GIMPLE_TRANSACTION. + * output.h (record_tm_clone_pair, finish_tm_clone_pairs, + get_tm_clone_pair): Declare. + * params.def (PARAM_TM_MAX_AGGREGATE_SIZE): New. + * passes.c (init_optimization_passes): Place transactional memory + passes. + * print-tree.c (print_node): Dump tm-clone. + * recog.c (peep2_attempt): Handle REG_TM. + * reg-notes.def (TM): New. + * rtlanal.c (alloc_reg_note): Handle REG_TM. + * target.def (builtin_tm_load, builtin_tm_store): New. + * targhooks.c (default_builtin_tm_load_store): New. + * targhooks.h (default_builtin_tm_load_store): Declare. + * timevar.def (TV_TRANS_MEM): New. + * toplev.c (compile_file): Call finish_tm_clone_pairs. + * tree-cfg.c (make_edges): Handle GIMPLE_TRANSACTION. + (cleanup_dead_labels): Handle GIMPLE_TRANSACTION. Avoid unnecessary + writes into the statements to update labels. + (is_ctrl_altering_stmt): Add TM ending statements. Handle + GIMPLE_TRANSACTION. + (verify_gimple_transaction): New. + (verify_gimple_stmt): Handle GIMPLE_TRANSACTION. + (verify_gimple_in_seq_2): Handle GIMPLE_EH_ELSE and GIMPLE_TRANSACTION. + (gimple_redirect_edge_and_branch): Handle TM_TRANSACTION. + (dump_function_to_file): Display [tm-clone] if applicable. + * tree-eh.c (struct_ptr_eq): Make inline and move to tree.h. + (struct_ptr_hash): Same. + (collect_finally_tree): Handle GIMPLE_EH_ELSE. + (replace_goto_queue_1): Likewise. + (get_eh_else): New. + (honor_protect_cleanup_actions): Handle GIMPLE_EH_ELSE. + (lower_try_finally_nofallthru): Likewise. + (lower_try_finally_onedest): Likewise. + (lower_try_finally_copy): Likewise. + (lower_try_finally_switch): Likewise. + (lower_try_finally): Likewise. + (decide_copy_try_finally): Likewise. + (lower_eh_constructs_2): Likewise. + (refactor_eh_r): Likewise. + * tree-flow.h (struct gimple_df): Add tm_restart field. + Define tm_restart_node. + * tree-inline.c (remap_gimple_stmt): Handle GIMPLE_TRANSACTION. + (estimate_num_insns): Likewise. + (init_inline_once): Init tm_cost. + * tree-inline.h (struct eni_weights_d): Add tm_cost. + * tree-pass.h (pass_diagnose_tm_blocks, pass_lower_tm, pass_tm_init, + pass_tm_mark, pass_tm_memopt, pass_tm_edges, pass_ipa_tm): Declare. + * tree-pretty-print.c (dump_generic_node): Handle TRANSACTION_EXPR. + * tree-ssa-alias.c (ref_maybe_used_by_call_p_1): Handle + BUILT_IN_TM_MEMSET, BUILT_IN_TM_MEMCPY, BUILT_IN_TM_MEMMOVE. + Add support for TM vector loads. Add support for TM logging builtins. + (call_may_clobber_ref_p_1): Add support for vector stores. + * tree-ssa-structalias.c (find_func_aliases): Add support for TM + vector stores and loads. Handle BUILT_IN_TM_MEMSET, + BUILT_IN_TM_MEMCPY, BUILT_IN_TM_MEMMOVE. + * tree.c (strip_invariant_refs): Moved from gimple.c to here. + (local_define_builtin): Handle ECF_TM_PURE. + (build_common_builtin_nodes): Set __builtin_eh_pointer to ECF_TM_PURE. + * tree.def (TRANSACTION_EXPR): New. + * tree.h (strip_invariant_refs): Moved from gimple.h to here. + (TRANSACTION_EXPR_BODY, TRANSACTION_EXPR_CHECK, + TRANSACTION_EXPR_OUTER, TRANSACTION_EXPR_RELAXED, + BUILTIN_TM_LOAD_STORE_P, BUILTIN_TM_LOAD_P, BUILTIN_TM_STORE_P, + CASE_BUILT_IN_TM_LOAD, CASE_BUILT_IN_TM_STORE): New. + (ECF_TM_PURE, ECF_TM_BUILTIN): New. + (struct tree_function_decl): Add tm_clone_flag. + (struct_ptr_eq, struct_ptr_hash): New. + (apply_tm_attr): Declare. + (is_tm_safe_or_pure): New. + (build_tm_abort_call, is_tm_safe, is_tm_pure, + is_tm_may_cancel_outer, is_tm_ending_fndecl, record_tm_replacement, + tm_malloc_replacement): Declare. + * varasm.c (tm_clone_hash): New. + (record_tm_clone_pair, finish_tm_clone_pairs, get_tm_clone_pair, + dump_tm_clone_to_vec, dump_tm_clone_pairs, tm_alias_pair_cmp): New. + (struct tm_alias_pair): New. Declare VEC types for object. + +2011-11-07 Richard Henderson <rth@redhat.com> * optabs.h (OTI_sync_compare_and_swap, OTI_sync_lock_test_and_set, OTI_sync_old_add, OTI_sync_old_sub, OTI_sync_old_ior, diff --git a/gcc/Makefile.in b/gcc/Makefile.in index 20bb98ae92c..9ec2df1485b 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -856,7 +856,8 @@ RTL_H = $(RTL_BASE_H) genrtl.h vecir.h RTL_ERROR_H = $(RTL_H) $(DIAGNOSTIC_CORE_H) READ_MD_H = $(OBSTACK_H) $(HASHTAB_H) read-md.h PARAMS_H = params.h params.def -BUILTINS_DEF = builtins.def sync-builtins.def omp-builtins.def +BUILTINS_DEF = builtins.def sync-builtins.def omp-builtins.def \ + gtm-builtins.def INTERNAL_FN_DEF = internal-fn.def INTERNAL_FN_H = internal-fn.h $(INTERNAL_FN_DEF) TREE_H = tree.h all-tree.def tree.def c-family/c-common.def \ @@ -869,6 +870,7 @@ BASIC_BLOCK_H = basic-block.h $(PREDICT_H) $(VEC_H) $(FUNCTION_H) cfghooks.h GIMPLE_H = gimple.h gimple.def gsstruct.def pointer-set.h $(VEC_H) \ vecir.h $(GGC_H) $(BASIC_BLOCK_H) $(TARGET_H) tree-ssa-operands.h \ tree-ssa-alias.h $(INTERNAL_FN_H) +TRANS_MEM_H = trans-mem.h GCOV_IO_H = gcov-io.h gcov-iov.h auto-host.h COVERAGE_H = coverage.h $(GCOV_IO_H) DEMANGLE_H = $(srcdir)/../include/demangle.h @@ -1352,6 +1354,7 @@ OBJS = \ timevar.o \ toplev.o \ tracer.o \ + trans-mem.o \ tree-affine.o \ tree-call-cdce.o \ tree-cfg.o \ @@ -2158,6 +2161,12 @@ gtype-desc.o: gtype-desc.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ $(CFGLOOP_H) $(TARGET_H) $(IPA_PROP_H) $(LTO_STREAMER_H) \ target-globals.h +trans-mem.o : trans-mem.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \ + $(TREE_H) $(GIMPLE_H) $(TREE_FLOW_H) $(TREE_PASS_H) $(TREE_INLINE_H) \ + $(DIAGNOSTIC_CORE_H) $(DEMANGLE_H) output.h $(TRANS_MEM_H) \ + $(PARAMS_H) $(TARGET_H) langhooks.h \ + tree-pretty-print.h gimple-pretty-print.h + ggc-common.o: ggc-common.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \ $(GGC_H) $(HASHTAB_H) $(DIAGNOSTIC_CORE_H) $(PARAMS_H) hosthooks.h \ $(HOSTHOOKS_DEF_H) $(VEC_H) $(PLUGIN_H) $(GGC_INTERNAL_H) $(TIMEVAR_H) @@ -2684,6 +2693,7 @@ gimple.o : gimple.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TREE_H) \ gimple-pretty-print.o : gimple-pretty-print.c $(CONFIG_H) $(SYSTEM_H) \ $(TREE_H) $(DIAGNOSTIC_H) $(HASHTAB_H) $(TREE_FLOW_H) \ $(TM_H) coretypes.h $(TREE_PASS_H) $(GIMPLE_H) value-prof.h \ + $(TRANS_MEM_H) \ tree-pretty-print.h gimple-pretty-print.h tree-mudflap.o : $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(TREE_INLINE_H) \ $(GIMPLE_H) $(DIAGNOSTIC_H) $(DEMANGLE_H) $(HASHTAB_H) langhooks.h tree-mudflap.h \ @@ -3733,6 +3743,7 @@ GTFILES = $(CPP_ID_DATA_H) $(srcdir)/input.h $(srcdir)/coretypes.h \ $(srcdir)/lto-symtab.c \ $(srcdir)/tree-ssa-alias.h \ $(srcdir)/ipa-prop.h \ + $(srcdir)/trans-mem.c \ $(srcdir)/lto-streamer.h \ $(srcdir)/target-globals.h \ $(srcdir)/ipa-inline.h \ diff --git a/gcc/attribs.c b/gcc/attribs.c index 9448c0c6beb..0e94fd29cb5 100644 --- a/gcc/attribs.c +++ b/gcc/attribs.c @@ -166,7 +166,8 @@ init_attributes (void) gcc_assert (strcmp (attribute_tables[i][j].name, attribute_tables[i][k].name)); } - /* Check that no name occurs in more than one table. */ + /* Check that no name occurs in more than one table. Names that + begin with '*' are exempt, and may be overridden. */ for (i = 0; i < ARRAY_SIZE (attribute_tables); i++) { size_t j, k, l; @@ -174,8 +175,9 @@ init_attributes (void) for (j = i + 1; j < ARRAY_SIZE (attribute_tables); j++) for (k = 0; attribute_tables[i][k].name != NULL; k++) for (l = 0; attribute_tables[j][l].name != NULL; l++) - gcc_assert (strcmp (attribute_tables[i][k].name, - attribute_tables[j][l].name)); + gcc_assert (attribute_tables[i][k].name[0] == '*' + || strcmp (attribute_tables[i][k].name, + attribute_tables[j][l].name)); } #endif @@ -207,7 +209,7 @@ register_attribute (const struct attribute_spec *attr) slot = htab_find_slot_with_hash (attribute_hash, &str, substring_hash (str.str, str.length), INSERT); - gcc_assert (!*slot); + gcc_assert (!*slot || attr->name[0] == '*'); *slot = (void *) CONST_CAST (struct attribute_spec *, attr); } @@ -484,3 +486,12 @@ decl_attributes (tree *node, tree attributes, int flags) return returned_attrs; } + +/* Subroutine of set_method_tm_attributes. Apply TM attribute ATTR + to the method FNDECL. */ + +void +apply_tm_attr (tree fndecl, tree attr) +{ + decl_attributes (&TREE_TYPE (fndecl), tree_cons (attr, NULL, NULL), 0); +} diff --git a/gcc/builtin-attrs.def b/gcc/builtin-attrs.def index d0c3d9605ea..619794e85c8 100644 --- a/gcc/builtin-attrs.def +++ b/gcc/builtin-attrs.def @@ -96,6 +96,8 @@ DEF_ATTR_IDENT (ATTR_SENTINEL, "sentinel") DEF_ATTR_IDENT (ATTR_STRFMON, "strfmon") DEF_ATTR_IDENT (ATTR_STRFTIME, "strftime") DEF_ATTR_IDENT (ATTR_TYPEGENERIC, "type generic") +DEF_ATTR_IDENT (ATTR_TM_REGPARM, "*tm regparm") +DEF_ATTR_IDENT (ATTR_TM_TMPURE, "transaction_pure") DEF_ATTR_TREE_LIST (ATTR_NOVOPS_LIST, ATTR_NOVOPS, ATTR_NULL, ATTR_NULL) @@ -227,6 +229,26 @@ DEF_FORMAT_ATTRIBUTE_NOTHROW(STRFMON,3,3_4) #undef DEF_FORMAT_ATTRIBUTE_NOTHROW #undef DEF_FORMAT_ATTRIBUTE_BOTH +/* Transactional memory variants of the above. */ + +DEF_ATTR_TREE_LIST (ATTR_TM_NOTHROW_LIST, + ATTR_TM_REGPARM, ATTR_NULL, ATTR_NOTHROW_LIST) +DEF_ATTR_TREE_LIST (ATTR_TM_TMPURE_NOTHROW_LIST, + ATTR_TM_TMPURE, ATTR_NULL, ATTR_TM_NOTHROW_LIST) +DEF_ATTR_TREE_LIST (ATTR_TM_PURE_TMPURE_NOTHROW_LIST, + ATTR_PURE, ATTR_NULL, ATTR_TM_TMPURE_NOTHROW_LIST) +DEF_ATTR_TREE_LIST (ATTR_TM_NORETURN_NOTHROW_LIST, + ATTR_TM_REGPARM, ATTR_NULL, ATTR_NORETURN_NOTHROW_LIST) +DEF_ATTR_TREE_LIST (ATTR_TM_CONST_NOTHROW_LIST, + ATTR_TM_REGPARM, ATTR_NULL, ATTR_CONST_NOTHROW_LIST) + +/* Same attributes used for BUILT_IN_MALLOC except with TM_PURE thrown in. */ +DEF_ATTR_TREE_LIST (ATTR_TMPURE_MALLOC_NOTHROW_LIST, + ATTR_TM_TMPURE, ATTR_NULL, ATTR_MALLOC_NOTHROW_LIST) +/* Same attributes used for BUILT_IN_FREE except with TM_PURE thrown in. */ +DEF_ATTR_TREE_LIST (ATTR_TMPURE_NOTHROW_LIST, + ATTR_TM_TMPURE, ATTR_NULL, ATTR_NOTHROW_LIST) + /* Construct a tree for a format_arg attribute. */ #define DEF_FORMAT_ARG_ATTRIBUTE(FA) \ DEF_ATTR_TREE_LIST (ATTR_FORMAT_ARG_##FA, ATTR_FORMAT_ARG, \ diff --git a/gcc/builtin-types.def b/gcc/builtin-types.def index a6d0127dadc..8edf744461e 100644 --- a/gcc/builtin-types.def +++ b/gcc/builtin-types.def @@ -530,3 +530,24 @@ DEF_FUNCTION_TYPE_VAR_5 (BT_FN_INT_INT_INT_INT_INT_INT_VAR, DEF_POINTER_TYPE (BT_PTR_FN_VOID_VAR, BT_FN_VOID_VAR) DEF_FUNCTION_TYPE_3 (BT_FN_PTR_PTR_FN_VOID_VAR_PTR_SIZE, BT_PTR, BT_PTR_FN_VOID_VAR, BT_PTR, BT_SIZE) + + +DEF_FUNCTION_TYPE_1 (BT_FN_I1_VPTR, BT_I1, BT_VOLATILE_PTR) +DEF_FUNCTION_TYPE_1 (BT_FN_I2_VPTR, BT_I2, BT_VOLATILE_PTR) +DEF_FUNCTION_TYPE_1 (BT_FN_I4_VPTR, BT_I4, BT_VOLATILE_PTR) +DEF_FUNCTION_TYPE_1 (BT_FN_I8_VPTR, BT_I8, BT_VOLATILE_PTR) +DEF_FUNCTION_TYPE_1 (BT_FN_FLOAT_VPTR, BT_FLOAT, BT_VOLATILE_PTR) +DEF_FUNCTION_TYPE_1 (BT_FN_DOUBLE_VPTR, BT_DOUBLE, BT_VOLATILE_PTR) +DEF_FUNCTION_TYPE_1 (BT_FN_LDOUBLE_VPTR, BT_LONGDOUBLE, BT_VOLATILE_PTR) + +DEF_FUNCTION_TYPE_2 (BT_FN_VOID_VPTR_I1, BT_VOID, BT_VOLATILE_PTR, BT_I1) +DEF_FUNCTION_TYPE_2 (BT_FN_VOID_VPTR_I2, BT_VOID, BT_VOLATILE_PTR, BT_I2) +DEF_FUNCTION_TYPE_2 (BT_FN_VOID_VPTR_I4, BT_VOID, BT_VOLATILE_PTR, BT_I4) +DEF_FUNCTION_TYPE_2 (BT_FN_VOID_VPTR_I8, BT_VOID, BT_VOLATILE_PTR, BT_I8) +DEF_FUNCTION_TYPE_2 (BT_FN_VOID_VPTR_FLOAT, BT_VOID, BT_VOLATILE_PTR, BT_FLOAT) +DEF_FUNCTION_TYPE_2 (BT_FN_VOID_VPTR_DOUBLE, BT_VOID, + BT_VOLATILE_PTR, BT_DOUBLE) +DEF_FUNCTION_TYPE_2 (BT_FN_VOID_VPTR_LDOUBLE, BT_VOID, + BT_VOLATILE_PTR, BT_LONGDOUBLE) +DEF_FUNCTION_TYPE_2 (BT_FN_VOID_VPTR_SIZE, BT_VOID, + BT_VOLATILE_PTR, BT_SIZE) diff --git a/gcc/builtins.def b/gcc/builtins.def index 0420b550f3b..616fca73597 100644 --- a/gcc/builtins.def +++ b/gcc/builtins.def @@ -142,6 +142,13 @@ along with GCC; see the file COPYING3. If not see false, true, true, ATTRS, false, \ (flag_openmp || flag_tree_parallelize_loops)) +/* Builtin used by the implementation of GNU TM. These + functions are mapped to the actual implementation of the STM library. */ +#undef DEF_TM_BUILTIN +#define DEF_TM_BUILTIN(ENUM, NAME, TYPE, ATTRS) \ + DEF_BUILTIN (ENUM, "__builtin_" NAME, BUILT_IN_NORMAL, TYPE, TYPE, \ + false, true, true, ATTRS, false, flag_tm) + /* Define an attribute list for math functions that are normally "impure" because some of them may write into global memory for `errno'. If !flag_errno_math they are instead "const". */ @@ -624,6 +631,7 @@ DEF_GCC_BUILTIN (BUILT_IN_APPLY_ARGS, "apply_args", BT_FN_PTR_VAR, ATTR_L DEF_GCC_BUILTIN (BUILT_IN_BSWAP32, "bswap32", BT_FN_UINT32_UINT32, ATTR_CONST_NOTHROW_LEAF_LIST) DEF_GCC_BUILTIN (BUILT_IN_BSWAP64, "bswap64", BT_FN_UINT64_UINT64, ATTR_CONST_NOTHROW_LEAF_LIST) DEF_EXT_LIB_BUILTIN (BUILT_IN_CLEAR_CACHE, "__clear_cache", BT_FN_VOID_PTR_PTR, ATTR_NOTHROW_LEAF_LIST) +/* [trans-mem]: Adjust BUILT_IN_TM_CALLOC if BUILT_IN_CALLOC is changed. */ DEF_LIB_BUILTIN (BUILT_IN_CALLOC, "calloc", BT_FN_PTR_SIZE_SIZE, ATTR_MALLOC_NOTHROW_LEAF_LIST) DEF_GCC_BUILTIN (BUILT_IN_CLASSIFY_TYPE, "classify_type", BT_FN_INT_VAR, ATTR_LEAF_LIST) DEF_GCC_BUILTIN (BUILT_IN_CLZ, "clz", BT_FN_INT_UINT, ATTR_CONST_NOTHROW_LEAF_LIST) @@ -662,6 +670,7 @@ DEF_EXT_LIB_BUILTIN (BUILT_IN_FFSL, "ffsl", BT_FN_INT_LONG, ATTR_CONST_NOTHRO DEF_EXT_LIB_BUILTIN (BUILT_IN_FFSLL, "ffsll", BT_FN_INT_LONGLONG, ATTR_CONST_NOTHROW_LEAF_LIST) DEF_EXT_LIB_BUILTIN (BUILT_IN_FORK, "fork", BT_FN_PID, ATTR_NOTHROW_LIST) DEF_GCC_BUILTIN (BUILT_IN_FRAME_ADDRESS, "frame_address", BT_FN_PTR_UINT, ATTR_NULL) +/* [trans-mem]: Adjust BUILT_IN_TM_FREE if BUILT_IN_FREE is changed. */ DEF_LIB_BUILTIN (BUILT_IN_FREE, "free", BT_FN_VOID_PTR, ATTR_NOTHROW_LIST) DEF_GCC_BUILTIN (BUILT_IN_FROB_RETURN_ADDR, "frob_return_addr", BT_FN_PTR_PTR, ATTR_NULL) DEF_EXT_LIB_BUILTIN (BUILT_IN_GETTEXT, "gettext", BT_FN_STRING_CONST_STRING, ATTR_FORMAT_ARG_1) @@ -698,6 +707,7 @@ DEF_GCC_BUILTIN (BUILT_IN_ISUNORDERED, "isunordered", BT_FN_INT_VAR, ATTR DEF_LIB_BUILTIN (BUILT_IN_LABS, "labs", BT_FN_LONG_LONG, ATTR_CONST_NOTHROW_LEAF_LIST) DEF_C99_BUILTIN (BUILT_IN_LLABS, "llabs", BT_FN_LONGLONG_LONGLONG, ATTR_CONST_NOTHROW_LEAF_LIST) DEF_GCC_BUILTIN (BUILT_IN_LONGJMP, "longjmp", BT_FN_VOID_PTR_INT, ATTR_NORETURN_NOTHROW_LEAF_LIST) +/* [trans-mem]: Adjust BUILT_IN_TM_MALLOC if BUILT_IN_MALLOC is changed. */ DEF_LIB_BUILTIN (BUILT_IN_MALLOC, "malloc", BT_FN_PTR_SIZE, ATTR_MALLOC_NOTHROW_LEAF_LIST) DEF_GCC_BUILTIN (BUILT_IN_NEXT_ARG, "next_arg", BT_FN_PTR_VAR, ATTR_LEAF_LIST) DEF_GCC_BUILTIN (BUILT_IN_PARITY, "parity", BT_FN_INT_UINT, ATTR_CONST_NOTHROW_LEAF_LIST) @@ -793,3 +803,6 @@ DEF_BUILTIN_STUB (BUILT_IN_EH_COPY_VALUES, "__builtin_eh_copy_values") /* OpenMP builtins. */ #include "omp-builtins.def" + +/* GTM builtins. */ +#include "gtm-builtins.def" diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index 04134ec444d..914c9163dc8 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,19 @@ +2011-11-07 Richard Henderson <rth@redhat.com> + Aldy Hernandez <aldyh@redhat.com> + Torvald Riegel <triegel@redhat.com> + + Merged from transactional-memory. + + * c-common.c (handle_tm_wrap_attribute, + handle_tm_attribute, ignore_attribute, parse_tm_stmt_attr): New. + (struct c_common_reswords): Added __transaction* keywords. + (struct c_common_attribute_table): Added transaction* and tm_regparm + attributes. + * c-common.h: Added RID_TRANSACTION*. Added TM_ATTR* and TM_STMT* + masks. + (parse_tm_stmt_attr, tm_attr_to_mask, tm_mask_to_attr, + find_tm_attribute): Declare. + 2011-11-07 Jason Merrill <jason@redhat.com> PR c++/35688 diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c index 0329bc7e01c..a6823311321 100644 --- a/gcc/c-family/c-common.c +++ b/gcc/c-family/c-common.c @@ -357,6 +357,8 @@ static tree handle_returns_twice_attribute (tree *, tree, tree, int, bool *); static tree handle_no_limit_stack_attribute (tree *, tree, tree, int, bool *); static tree handle_pure_attribute (tree *, tree, tree, int, bool *); +static tree handle_tm_attribute (tree *, tree, tree, int, bool *); +static tree handle_tm_wrap_attribute (tree *, tree, tree, int, bool *); static tree handle_novops_attribute (tree *, tree, tree, int, bool *); static tree handle_deprecated_attribute (tree *, tree, tree, int, bool *); @@ -372,6 +374,7 @@ static tree handle_type_generic_attribute (tree *, tree, tree, int, bool *); static tree handle_alloc_size_attribute (tree *, tree, tree, int, bool *); static tree handle_target_attribute (tree *, tree, tree, int, bool *); static tree handle_optimize_attribute (tree *, tree, tree, int, bool *); +static tree ignore_attribute (tree *, tree, tree, int, bool *); static tree handle_no_split_stack_attribute (tree *, tree, tree, int, bool *); static tree handle_fnspec_attribute (tree *, tree, tree, int, bool *); @@ -474,6 +477,9 @@ const struct c_common_resword c_common_reswords[] = { "__signed", RID_SIGNED, 0 }, { "__signed__", RID_SIGNED, 0 }, { "__thread", RID_THREAD, 0 }, + { "__transaction_atomic", RID_TRANSACTION_ATOMIC, 0 }, + { "__transaction_relaxed", RID_TRANSACTION_RELAXED, 0 }, + { "__transaction_cancel", RID_TRANSACTION_CANCEL, 0 }, { "__typeof", RID_TYPEOF, 0 }, { "__typeof__", RID_TYPEOF, 0 }, { "__underlying_type", RID_UNDERLYING_TYPE, D_CXXONLY }, @@ -666,6 +672,20 @@ const struct attribute_spec c_common_attribute_table[] = handle_no_limit_stack_attribute, false }, { "pure", 0, 0, true, false, false, handle_pure_attribute, false }, + { "transaction_callable", 0, 0, false, true, false, + handle_tm_attribute, false }, + { "transaction_unsafe", 0, 0, false, true, false, + handle_tm_attribute, false }, + { "transaction_safe", 0, 0, false, true, false, + handle_tm_attribute, false }, + { "transaction_may_cancel_outer", 0, 0, false, true, false, + handle_tm_attribute, false }, + /* ??? These two attributes didn't make the transition from the + Intel language document to the multi-vendor language document. */ + { "transaction_pure", 0, 0, false, true, false, + handle_tm_attribute, false }, + { "transaction_wrap", 1, 1, true, false, false, + handle_tm_wrap_attribute, false }, /* For internal use (marking of builtins) only. The name contains space to prevent its usage in source code. */ { "no vops", 0, 0, true, false, false, @@ -707,6 +727,10 @@ const struct attribute_spec c_common_attribute_table[] = handle_target_attribute, false }, { "optimize", 1, -1, true, false, false, handle_optimize_attribute, false }, + /* For internal use only. The leading '*' both prevents its usage in + source code and signals that it may be overridden by machine tables. */ + { "*tm regparm", 0, 0, false, true, true, + ignore_attribute, false }, { "no_split_stack", 0, 0, true, false, false, handle_no_split_stack_attribute, false }, /* For internal use (marking of builtins and runtime functions) only. @@ -7315,6 +7339,223 @@ handle_pure_attribute (tree *node, tree name, tree ARG_UNUSED (args), return NULL_TREE; } +/* Digest an attribute list destined for a transactional memory statement. + ALLOWED is the set of attributes that are allowed for this statement; + return the attribute we parsed. Multiple attributes are never allowed. */ + +int +parse_tm_stmt_attr (tree attrs, int allowed) +{ + tree a_seen = NULL; + int m_seen = 0; + + for ( ; attrs ; attrs = TREE_CHAIN (attrs)) + { + tree a = TREE_PURPOSE (attrs); + int m = 0; + + if (is_attribute_p ("outer", a)) + m = TM_STMT_ATTR_OUTER; + + if ((m & allowed) == 0) + { + warning (OPT_Wattributes, "%qE attribute directive ignored", a); + continue; + } + + if (m_seen == 0) + { + a_seen = a; + m_seen = m; + } + else if (m_seen == m) + warning (OPT_Wattributes, "%qE attribute duplicated", a); + else + warning (OPT_Wattributes, "%qE attribute follows %qE", a, a_seen); + } + + return m_seen; +} + +/* Transform a TM attribute name into a maskable integer and back. + Note that NULL (i.e. no attribute) is mapped to UNKNOWN, corresponding + to how the lack of an attribute is treated. */ + +int +tm_attr_to_mask (tree attr) +{ + if (attr == NULL) + return 0; + if (is_attribute_p ("transaction_safe", attr)) + return TM_ATTR_SAFE; + if (is_attribute_p ("transaction_callable", attr)) + return TM_ATTR_CALLABLE; + if (is_attribute_p ("transaction_pure", attr)) + return TM_ATTR_PURE; + if (is_attribute_p ("transaction_unsafe", attr)) + return TM_ATTR_IRREVOCABLE; + if (is_attribute_p ("transaction_may_cancel_outer", attr)) + return TM_ATTR_MAY_CANCEL_OUTER; + return 0; +} + +tree +tm_mask_to_attr (int mask) +{ + const char *str; + switch (mask) + { + case TM_ATTR_SAFE: + str = "transaction_safe"; + break; + case TM_ATTR_CALLABLE: + str = "transaction_callable"; + break; + case TM_ATTR_PURE: + str = "transaction_pure"; + break; + case TM_ATTR_IRREVOCABLE: + str = "transaction_unsafe"; + break; + case TM_ATTR_MAY_CANCEL_OUTER: + str = "transaction_may_cancel_outer"; + break; + default: + gcc_unreachable (); + } + return get_identifier (str); +} + +/* Return the first TM attribute seen in LIST. */ + +tree +find_tm_attribute (tree list) +{ + for (; list ; list = TREE_CHAIN (list)) + { + tree name = TREE_PURPOSE (list); + if (tm_attr_to_mask (name) != 0) + return name; + } + return NULL_TREE; +} + +/* Handle the TM attributes; arguments as in struct attribute_spec.handler. + Here we accept only function types, and verify that none of the other + function TM attributes are also applied. */ +/* ??? We need to accept class types for C++, but not C. This greatly + complicates this function, since we can no longer rely on the extra + processing given by function_type_required. */ + +static tree +handle_tm_attribute (tree *node, tree name, tree args, + int flags, bool *no_add_attrs) +{ + /* Only one path adds the attribute; others don't. */ + *no_add_attrs = true; + + switch (TREE_CODE (*node)) + { + case RECORD_TYPE: + case UNION_TYPE: + /* Only tm_callable and tm_safe apply to classes. */ + if (tm_attr_to_mask (name) & ~(TM_ATTR_SAFE | TM_ATTR_CALLABLE)) + goto ignored; + /* FALLTHRU */ + + case FUNCTION_TYPE: + case METHOD_TYPE: + { + tree old_name = find_tm_attribute (TYPE_ATTRIBUTES (*node)); + if (old_name == name) + ; + else if (old_name != NULL_TREE) + error ("type was previously declared %qE", old_name); + else + *no_add_attrs = false; + } + break; + + case POINTER_TYPE: + { + enum tree_code subcode = TREE_CODE (TREE_TYPE (*node)); + if (subcode == FUNCTION_TYPE || subcode == METHOD_TYPE) + { + tree fn_tmp = TREE_TYPE (*node); + decl_attributes (&fn_tmp, tree_cons (name, args, NULL), 0); + *node = build_pointer_type (fn_tmp); + break; + } + } + /* FALLTHRU */ + + default: + /* If a function is next, pass it on to be tried next. */ + if (flags & (int) ATTR_FLAG_FUNCTION_NEXT) + return tree_cons (name, args, NULL); + + ignored: + warning (OPT_Wattributes, "%qE attribute ignored", name); + break; + } + + return NULL_TREE; +} + +/* Handle the TM_WRAP attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_tm_wrap_attribute (tree *node, tree name, tree args, + int ARG_UNUSED (flags), bool *no_add_attrs) +{ + tree decl = *node; + + /* We don't need the attribute even on success, since we + record the entry in an external table. */ + *no_add_attrs = true; + + if (TREE_CODE (decl) != FUNCTION_DECL) + warning (OPT_Wattributes, "%qE attribute ignored", name); + else + { + tree wrap_decl = TREE_VALUE (args); + if (TREE_CODE (wrap_decl) != IDENTIFIER_NODE + && TREE_CODE (wrap_decl) != VAR_DECL + && TREE_CODE (wrap_decl) != FUNCTION_DECL) + error ("%qE argument not an identifier", name); + else + { + if (TREE_CODE (wrap_decl) == IDENTIFIER_NODE) + wrap_decl = lookup_name (wrap_decl); + if (wrap_decl && TREE_CODE (wrap_decl) == FUNCTION_DECL) + { + if (lang_hooks.types_compatible_p (TREE_TYPE (decl), + TREE_TYPE (wrap_decl))) + record_tm_replacement (wrap_decl, decl); + else + error ("%qD is not compatible with %qD", wrap_decl, decl); + } + else + error ("transaction_wrap argument is not a function"); + } + } + + return NULL_TREE; +} + +/* Ignore the given attribute. Used when this attribute may be usefully + overridden by the target, but is not used generically. */ + +static tree +ignore_attribute (tree * ARG_UNUSED (node), tree ARG_UNUSED (name), + tree ARG_UNUSED (args), int ARG_UNUSED (flags), + bool *no_add_attrs) +{ + *no_add_attrs = true; + return NULL_TREE; +} + /* Handle a "no vops" attribute; arguments as in struct attribute_spec.handler. */ diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h index bff6956cc14..4d65dd1b7f1 100644 --- a/gcc/c-family/c-common.h +++ b/gcc/c-family/c-common.h @@ -113,6 +113,9 @@ enum rid as a normal identifier. */ RID_CXX_COMPAT_WARN, + /* GNU transactional memory extension */ + RID_TRANSACTION_ATOMIC, RID_TRANSACTION_RELAXED, RID_TRANSACTION_CANCEL, + /* Too many ways of getting the name of a function as a string */ RID_FUNCTION_NAME, RID_PRETTY_FUNCTION_NAME, RID_C99_FUNCTION_NAME, @@ -1073,6 +1076,28 @@ c_tree_chain_next (tree t) return NULL; } +/* Mask used by tm_stmt_attr. */ +#define TM_STMT_ATTR_OUTER 2 +#define TM_STMT_ATTR_ATOMIC 4 +#define TM_STMT_ATTR_RELAXED 8 + +extern int parse_tm_stmt_attr (tree, int); + +/* Mask used by tm_attr_to_mask and tm_mask_to_attr. Note that these + are ordered specifically such that more restrictive attributes are + at lower bit positions. This fact is known by the C++ tm attribute + inheritance code such that least bit extraction (mask & -mask) results + in the most restrictive attribute. */ +#define TM_ATTR_SAFE 1 +#define TM_ATTR_CALLABLE 2 +#define TM_ATTR_PURE 4 +#define TM_ATTR_IRREVOCABLE 8 +#define TM_ATTR_MAY_CANCEL_OUTER 16 + +extern int tm_attr_to_mask (tree); +extern tree tm_mask_to_attr (int); +extern tree find_tm_attribute (tree); + /* A suffix-identifier value doublet that represents user-defined literals for C++-0x. */ struct GTY(()) tree_userdef_literal { diff --git a/gcc/c-parser.c b/gcc/c-parser.c index 58bcb0282a1..aed390f31e8 100644 --- a/gcc/c-parser.c +++ b/gcc/c-parser.c @@ -195,6 +195,9 @@ typedef struct GTY(()) c_parser { undesirable to bind an identifier to an Objective-C class, even if a class with that name exists. */ BOOL_BITFIELD objc_need_raw_identifier : 1; + /* Nonzero if we're processing a __transaction statement. The value + is 1 | TM_STMT_ATTR_*. */ + unsigned int in_transaction : 4; /* True if we are in a context where the Objective-C "Property attribute" keywords are valid. */ BOOL_BITFIELD objc_property_attr_context : 1; @@ -1171,6 +1174,9 @@ static struct c_expr c_parser_postfix_expression_after_paren_type (c_parser *, static struct c_expr c_parser_postfix_expression_after_primary (c_parser *, location_t loc, struct c_expr); +static tree c_parser_transaction (c_parser *, enum rid); +static struct c_expr c_parser_transaction_expression (c_parser *, enum rid); +static tree c_parser_transaction_cancel (c_parser *); static struct c_expr c_parser_expression (c_parser *); static struct c_expr c_parser_expression_conv (c_parser *); static VEC(tree,gc) *c_parser_expr_list (c_parser *, bool, bool, @@ -3413,6 +3419,66 @@ c_parser_simple_asm_expr (c_parser *parser) return str; } +static tree +c_parser_attribute_any_word (c_parser *parser) +{ + tree attr_name = NULL_TREE; + + if (c_parser_next_token_is (parser, CPP_KEYWORD)) + { + /* ??? See comment above about what keywords are accepted here. */ + bool ok; + switch (c_parser_peek_token (parser)->keyword) + { + case RID_STATIC: + case RID_UNSIGNED: + case RID_LONG: + case RID_INT128: + case RID_CONST: + case RID_EXTERN: + case RID_REGISTER: + case RID_TYPEDEF: + case RID_SHORT: + case RID_INLINE: + case RID_NORETURN: + case RID_VOLATILE: + case RID_SIGNED: + case RID_AUTO: + case RID_RESTRICT: + case RID_COMPLEX: + case RID_THREAD: + case RID_INT: + case RID_CHAR: + case RID_FLOAT: + case RID_DOUBLE: + case RID_VOID: + case RID_DFLOAT32: + case RID_DFLOAT64: + case RID_DFLOAT128: + case RID_BOOL: + case RID_FRACT: + case RID_ACCUM: + case RID_SAT: + case RID_TRANSACTION_ATOMIC: + case RID_TRANSACTION_CANCEL: + ok = true; + break; + default: + ok = false; + break; + } + if (!ok) + return NULL_TREE; + + /* Accept __attribute__((__const)) as __attribute__((const)) etc. */ + attr_name = ridpointers[(int) c_parser_peek_token (parser)->keyword]; + } + else if (c_parser_next_token_is (parser, CPP_NAME)) + attr_name = c_parser_peek_token (parser)->value; + + return attr_name; +} + /* Parse (possibly empty) attributes. This is a GNU extension. attributes: @@ -3473,57 +3539,10 @@ c_parser_attributes (c_parser *parser) c_parser_consume_token (parser); continue; } - if (c_parser_next_token_is (parser, CPP_KEYWORD)) - { - /* ??? See comment above about what keywords are - accepted here. */ - bool ok; - switch (c_parser_peek_token (parser)->keyword) - { - case RID_STATIC: - case RID_UNSIGNED: - case RID_LONG: - case RID_INT128: - case RID_CONST: - case RID_EXTERN: - case RID_REGISTER: - case RID_TYPEDEF: - case RID_SHORT: - case RID_INLINE: - case RID_NORETURN: - case RID_VOLATILE: - case RID_SIGNED: - case RID_AUTO: - case RID_RESTRICT: - case RID_COMPLEX: - case RID_THREAD: - case RID_INT: - case RID_CHAR: - case RID_FLOAT: - case RID_DOUBLE: - case RID_VOID: - case RID_DFLOAT32: - case RID_DFLOAT64: - case RID_DFLOAT128: - case RID_BOOL: - case RID_FRACT: - case RID_ACCUM: - case RID_SAT: - ok = true; - break; - default: - ok = false; - break; - } - if (!ok) - break; - /* Accept __attribute__((__const)) as __attribute__((const)) - etc. */ - attr_name - = ridpointers[(int) c_parser_peek_token (parser)->keyword]; - } - else - attr_name = c_parser_peek_token (parser)->value; + + attr_name = c_parser_attribute_any_word (parser); + if (attr_name == NULL) + break; c_parser_consume_token (parser); if (c_parser_next_token_is_not (parser, CPP_OPEN_PAREN)) { @@ -4394,7 +4413,14 @@ c_parser_label (c_parser *parser) atomic-directive expression-statement ordered-construct: - ordered-directive structured-block */ + ordered-directive structured-block + + Transactional Memory: + + statement: + transaction-statement + transaction-cancel-statement +*/ static void c_parser_statement (c_parser *parser) @@ -4485,6 +4511,14 @@ c_parser_statement_after_labels (c_parser *parser) case RID_ASM: stmt = c_parser_asm_statement (parser); break; + case RID_TRANSACTION_ATOMIC: + case RID_TRANSACTION_RELAXED: + stmt = c_parser_transaction (parser, + c_parser_peek_token (parser)->keyword); + break; + case RID_TRANSACTION_CANCEL: + stmt = c_parser_transaction_cancel (parser); + goto expect_semicolon; case RID_AT_THROW: gcc_assert (c_dialect_objc ()); c_parser_consume_token (parser); @@ -5812,6 +5846,11 @@ c_parser_cast_expression (c_parser *parser, struct c_expr *after) unary-operator: one of __extension__ __real__ __imag__ + Transactional Memory: + + unary-expression: + transaction-expression + In addition, the GNU syntax treats ++ and -- as unary operators, so they may be applied to cast expressions with errors for non-lvalues given later. */ @@ -5919,6 +5958,10 @@ c_parser_unary_expression (c_parser *parser) op = c_parser_cast_expression (parser, NULL); op = default_function_array_conversion (exp_loc, op); return parser_build_unary_op (op_loc, IMAGPART_EXPR, op); + case RID_TRANSACTION_ATOMIC: + case RID_TRANSACTION_RELAXED: + return c_parser_transaction_expression (parser, + c_parser_peek_token (parser)->keyword); default: return c_parser_postfix_expression (parser); } @@ -10535,6 +10578,212 @@ c_parser_omp_threadprivate (c_parser *parser) c_parser_skip_to_pragma_eol (parser); } +/* Parse a transaction attribute (GCC Extension). + + transaction-attribute: + attributes + [ [ any-word ] ] + + The transactional memory language description is written for C++, + and uses the C++0x attribute syntax. For compatibility, allow the + bracket style for transactions in C as well. */ + +static tree +c_parser_transaction_attributes (c_parser *parser) +{ + tree attr_name, attr = NULL; + + if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE)) + return c_parser_attributes (parser); + + if (!c_parser_next_token_is (parser, CPP_OPEN_SQUARE)) + return NULL_TREE; + c_parser_consume_token (parser); + if (!c_parser_require (parser, CPP_OPEN_SQUARE, "expected %<[%>")) + goto error1; + + attr_name = c_parser_attribute_any_word (parser); + if (attr_name) + { + c_parser_consume_token (parser); + attr = build_tree_list (attr_name, NULL_TREE); + } + else + c_parser_error (parser, "expected identifier"); + + c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, "expected %<]%>"); + error1: + c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, "expected %<]%>"); + return attr; +} + +/* Parse a __transaction_atomic or __transaction_relaxed statement + (GCC Extension). + + transaction-statement: + __transaction_atomic transaction-attribute[opt] compound-statement + __transaction_relaxed compound-statement + + Note that the only valid attribute is: "outer". +*/ + +static tree +c_parser_transaction (c_parser *parser, enum rid keyword) +{ + unsigned int old_in = parser->in_transaction; + unsigned int this_in = 1, new_in; + location_t loc = c_parser_peek_token (parser)->location; + tree stmt, attrs; + + gcc_assert ((keyword == RID_TRANSACTION_ATOMIC + || keyword == RID_TRANSACTION_RELAXED) + && c_parser_next_token_is_keyword (parser, keyword)); + c_parser_consume_token (parser); + + if (keyword == RID_TRANSACTION_RELAXED) + this_in |= TM_STMT_ATTR_RELAXED; + else + { + attrs = c_parser_transaction_attributes (parser); + if (attrs) + this_in |= parse_tm_stmt_attr (attrs, TM_STMT_ATTR_OUTER); + } + + /* Keep track if we're in the lexical scope of an outer transaction. */ + new_in = this_in | (old_in & TM_STMT_ATTR_OUTER); + + parser->in_transaction = new_in; + stmt = c_parser_compound_statement (parser); + parser->in_transaction = old_in; + + if (flag_tm) + stmt = c_finish_transaction (loc, stmt, this_in); + else + error_at (loc, (keyword == RID_TRANSACTION_ATOMIC ? + "%<__transaction_atomic%> without transactional memory support enabled" + : "%<__transaction_relaxed %> " + "without transactional memory support enabled")); + + return stmt; +} + +/* Parse a __transaction_atomic or __transaction_relaxed expression + (GCC Extension). + + transaction-expression: + __transaction_atomic ( expression ) + __transaction_relaxed ( expression ) +*/ + +static struct c_expr +c_parser_transaction_expression (c_parser *parser, enum rid keyword) +{ + struct c_expr ret; + unsigned int old_in = parser->in_transaction; + unsigned int this_in = 1; + location_t loc = c_parser_peek_token (parser)->location; + tree attrs; + + gcc_assert ((keyword == RID_TRANSACTION_ATOMIC + || keyword == RID_TRANSACTION_RELAXED) + && c_parser_next_token_is_keyword (parser, keyword)); + c_parser_consume_token (parser); + + if (keyword == RID_TRANSACTION_RELAXED) + this_in |= TM_STMT_ATTR_RELAXED; + else + { + attrs = c_parser_transaction_attributes (parser); + if (attrs) + this_in |= parse_tm_stmt_attr (attrs, 0); + } + + parser->in_transaction = this_in; + if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)) + { + tree expr = c_parser_expression (parser).value; + ret.original_type = TREE_TYPE (expr); + ret.value = build1 (TRANSACTION_EXPR, ret.original_type, expr); + if (this_in & TM_STMT_ATTR_RELAXED) + TRANSACTION_EXPR_RELAXED (ret.value) = 1; + SET_EXPR_LOCATION (ret.value, loc); + ret.original_code = TRANSACTION_EXPR; + } + else + { + c_parser_error (parser, "expected %<(%>"); + ret.value = error_mark_node; + ret.original_code = ERROR_MARK; + ret.original_type = NULL; + } + parser->in_transaction = old_in; + + if (!flag_tm) + error_at (loc, (keyword == RID_TRANSACTION_ATOMIC ? + "%<__transaction_atomic%> without transactional memory support enabled" + : "%<__transaction_relaxed %> " + "without transactional memory support enabled")); + + return ret; +} + +/* Parse a __transaction_cancel statement (GCC Extension). + + transaction-cancel-statement: + __transaction_cancel transaction-attribute[opt] ; + + Note that the only valid attribute is "outer". +*/ + +static tree +c_parser_transaction_cancel(c_parser *parser) +{ + location_t loc = c_parser_peek_token (parser)->location; + tree attrs; + bool is_outer = false; + + gcc_assert (c_parser_next_token_is_keyword (parser, RID_TRANSACTION_CANCEL)); + c_parser_consume_token (parser); + + attrs = c_parser_transaction_attributes (parser); + if (attrs) + is_outer = (parse_tm_stmt_attr (attrs, TM_STMT_ATTR_OUTER) != 0); + + if (!flag_tm) + { + error_at (loc, "%<__transaction_cancel%> without " + "transactional memory support enabled"); + goto ret_error; + } + else if (parser->in_transaction & TM_STMT_ATTR_RELAXED) + { + error_at (loc, "%<__transaction_cancel%> within a " + "%<__transaction_relaxed%>"); + goto ret_error; + } + else if (is_outer) + { + if ((parser->in_transaction & TM_STMT_ATTR_OUTER) == 0 + && !is_tm_may_cancel_outer (current_function_decl)) + { + error_at (loc, "outer %<__transaction_cancel%> not " + "within outer %<__transaction_atomic%>"); + error_at (loc, " or a %<transaction_may_cancel_outer%> function"); + goto ret_error; + } + } + else if (parser->in_transaction == 0) + { + error_at (loc, "%<__transaction_cancel%> not within " + "%<__transaction_atomic%>"); + goto ret_error; + } + + return add_stmt (build_tm_abort_call (loc, is_outer)); + + ret_error: + return build1 (NOP_EXPR, void_type_node, error_mark_node); +} /* Parse a single source file. */ diff --git a/gcc/c-tree.h b/gcc/c-tree.h index 6801db2b98b..51c660c0346 100644 --- a/gcc/c-tree.h +++ b/gcc/c-tree.h @@ -603,6 +603,7 @@ extern tree c_begin_omp_task (void); extern tree c_finish_omp_task (location_t, tree, tree); extern tree c_finish_omp_clauses (tree); extern tree c_build_va_arg (location_t, tree, tree); +extern tree c_finish_transaction (location_t, tree, int); extern tree c_build_vec_perm_expr (location_t, tree, tree, tree); /* Set to 0 at beginning of a function definition, set to 1 if diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c index 392ac652c0a..4a134b0e524 100644 --- a/gcc/c-typeck.c +++ b/gcc/c-typeck.c @@ -2716,6 +2716,9 @@ build_function_call_vec (location_t loc, tree function, VEC(tree,gc) *params, return tem; name = DECL_NAME (function); + + if (flag_tm) + tm_malloc_replacement (function); fundecl = function; /* Atomic functions have type checking/casting already done. They are often rewritten and don't match the original parameter list. */ @@ -10922,6 +10925,19 @@ c_finish_omp_clauses (tree clauses) return clauses; } +/* Create a transaction node. */ + +tree +c_finish_transaction (location_t loc, tree block, int flags) +{ + tree stmt = build_stmt (loc, TRANSACTION_EXPR, block); + if (flags & TM_STMT_ATTR_OUTER) + TRANSACTION_EXPR_OUTER (stmt) = 1; + if (flags & TM_STMT_ATTR_RELAXED) + TRANSACTION_EXPR_RELAXED (stmt) = 1; + return add_stmt (stmt); +} + /* Make a variant type in the proper way for C/C++, propagating qualifiers down to the element type of an array. */ diff --git a/gcc/calls.c b/gcc/calls.c index eeb6b2ec602..382de7fcdeb 100644 --- a/gcc/calls.c +++ b/gcc/calls.c @@ -611,6 +611,69 @@ alloca_call_p (const_tree exp) return false; } +/* Return TRUE if FNDECL is either a TM builtin or a TM cloned + function. Return FALSE otherwise. */ + +static bool +is_tm_builtin (const_tree fndecl) +{ + if (fndecl == NULL) + return false; + + if (decl_is_tm_clone (fndecl)) + return true; + + if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL) + { + switch (DECL_FUNCTION_CODE (fndecl)) + { + case BUILT_IN_TM_COMMIT: + case BUILT_IN_TM_COMMIT_EH: + case BUILT_IN_TM_ABORT: + case BUILT_IN_TM_IRREVOCABLE: + case BUILT_IN_TM_GETTMCLONE_IRR: + case BUILT_IN_TM_MEMCPY: + case BUILT_IN_TM_MEMMOVE: + case BUILT_IN_TM_MEMSET: + CASE_BUILT_IN_TM_STORE (1): + CASE_BUILT_IN_TM_STORE (2): + CASE_BUILT_IN_TM_STORE (4): + CASE_BUILT_IN_TM_STORE (8): + CASE_BUILT_IN_TM_STORE (FLOAT): + CASE_BUILT_IN_TM_STORE (DOUBLE): + CASE_BUILT_IN_TM_STORE (LDOUBLE): + CASE_BUILT_IN_TM_STORE (M64): + CASE_BUILT_IN_TM_STORE (M128): + CASE_BUILT_IN_TM_STORE (M256): + CASE_BUILT_IN_TM_LOAD (1): + CASE_BUILT_IN_TM_LOAD (2): + CASE_BUILT_IN_TM_LOAD (4): + CASE_BUILT_IN_TM_LOAD (8): + CASE_BUILT_IN_TM_LOAD (FLOAT): + CASE_BUILT_IN_TM_LOAD (DOUBLE): + CASE_BUILT_IN_TM_LOAD (LDOUBLE): + CASE_BUILT_IN_TM_LOAD (M64): + CASE_BUILT_IN_TM_LOAD (M128): + CASE_BUILT_IN_TM_LOAD (M256): + case BUILT_IN_TM_LOG: + case BUILT_IN_TM_LOG_1: + case BUILT_IN_TM_LOG_2: + case BUILT_IN_TM_LOG_4: + case BUILT_IN_TM_LOG_8: + case BUILT_IN_TM_LOG_FLOAT: + case BUILT_IN_TM_LOG_DOUBLE: + case BUILT_IN_TM_LOG_LDOUBLE: + case BUILT_IN_TM_LOG_M64: + case BUILT_IN_TM_LOG_M128: + case BUILT_IN_TM_LOG_M256: + return true; + default: + break; + } + } + return false; +} + /* Detect flags (function attributes) from the function decl or type node. */ int @@ -644,10 +707,28 @@ flags_from_decl_or_type (const_tree exp) if (TREE_NOTHROW (exp)) flags |= ECF_NOTHROW; + if (flag_tm) + { + if (is_tm_builtin (exp)) + flags |= ECF_TM_BUILTIN; + else if ((flags & ECF_CONST) != 0 + || lookup_attribute ("transaction_pure", + TYPE_ATTRIBUTES (TREE_TYPE (exp)))) + flags |= ECF_TM_PURE; + } + flags = special_function_p (exp, flags); } - else if (TYPE_P (exp) && TYPE_READONLY (exp)) - flags |= ECF_CONST; + else if (TYPE_P (exp)) + { + if (TYPE_READONLY (exp)) + flags |= ECF_CONST; + + if (flag_tm + && ((flags & ECF_CONST) != 0 + || lookup_attribute ("transaction_pure", TYPE_ATTRIBUTES (exp)))) + flags |= ECF_TM_PURE; + } if (TREE_THIS_VOLATILE (exp)) { diff --git a/gcc/cfgbuild.c b/gcc/cfgbuild.c index 6f0d69e4523..692fea8a17b 100644 --- a/gcc/cfgbuild.c +++ b/gcc/cfgbuild.c @@ -338,18 +338,30 @@ make_edges (basic_block min, basic_block max, int update_p) /* Add any appropriate EH edges. */ rtl_make_eh_edge (edge_cache, bb, insn); - if (code == CALL_INSN && nonlocal_goto_handler_labels) + if (code == CALL_INSN) { - /* ??? This could be made smarter: in some cases it's possible - to tell that certain calls will not do a nonlocal goto. - For example, if the nested functions that do the nonlocal - gotos do not have their addresses taken, then only calls to - those functions or to other nested functions that use them - could possibly do nonlocal gotos. */ if (can_nonlocal_goto (insn)) - for (x = nonlocal_goto_handler_labels; x; x = XEXP (x, 1)) - make_label_edge (edge_cache, bb, XEXP (x, 0), - EDGE_ABNORMAL | EDGE_ABNORMAL_CALL); + { + /* ??? This could be made smarter: in some cases it's + possible to tell that certain calls will not do a + nonlocal goto. For example, if the nested functions + that do the nonlocal gotos do not have their addresses + taken, then only calls to those functions or to other + nested functions that use them could possibly do + nonlocal gotos. */ + for (x = nonlocal_goto_handler_labels; x; x = XEXP (x, 1)) + make_label_edge (edge_cache, bb, XEXP (x, 0), + EDGE_ABNORMAL | EDGE_ABNORMAL_CALL); + } + + if (flag_tm) + { + rtx note; + for (note = REG_NOTES (insn); note; note = XEXP (note, 1)) + if (REG_NOTE_KIND (note) == REG_TM) + make_label_edge (edge_cache, bb, XEXP (note, 0), + EDGE_ABNORMAL | EDGE_ABNORMAL_CALL); + } } } diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c index 6fb9ee0c5a1..3d733337cff 100644 --- a/gcc/cfgexpand.c +++ b/gcc/cfgexpand.c @@ -1802,6 +1802,38 @@ expand_gimple_cond (basic_block bb, gimple stmt) return new_bb; } +/* Mark all calls that can have a transaction restart. */ + +static void +mark_transaction_restart_calls (gimple stmt) +{ + struct tm_restart_node dummy; + void **slot; + + if (!cfun->gimple_df->tm_restart) + return; + + dummy.stmt = stmt; + slot = htab_find_slot (cfun->gimple_df->tm_restart, &dummy, NO_INSERT); + if (slot) + { + struct tm_restart_node *n = (struct tm_restart_node *) *slot; + tree list = n->label_or_list; + rtx insn; + + for (insn = next_real_insn (get_last_insn ()); + !CALL_P (insn); + insn = next_real_insn (insn)) + continue; + + if (TREE_CODE (list) == LABEL_DECL) + add_reg_note (insn, REG_TM, label_rtx (list)); + else + for (; list ; list = TREE_CHAIN (list)) + add_reg_note (insn, REG_TM, label_rtx (TREE_VALUE (list))); + } +} + /* A subroutine of expand_gimple_stmt_1, expanding one GIMPLE_CALL statement STMT. */ @@ -1888,6 +1920,8 @@ expand_call_stmt (gimple stmt) expand_assignment (lhs, exp, false); else expand_expr_real_1 (exp, const0_rtx, VOIDmode, EXPAND_NORMAL, NULL); + + mark_transaction_restart_calls (stmt); } /* A subroutine of expand_gimple_stmt, expanding one gimple statement @@ -4455,6 +4489,14 @@ gimple_expand_cfg (void) /* After expanding, the return labels are no longer needed. */ return_label = NULL; naked_return_label = NULL; + + /* After expanding, the tm_restart map is no longer needed. */ + if (cfun->gimple_df->tm_restart) + { + htab_delete (cfun->gimple_df->tm_restart); + cfun->gimple_df->tm_restart = NULL; + } + /* Tag the blocks with a depth number so that change_scope can find the common parent easily. */ set_block_levels (DECL_INITIAL (cfun->decl), 0); diff --git a/gcc/cfgrtl.c b/gcc/cfgrtl.c index f06dbc83b1d..6e9f70ed719 100644 --- a/gcc/cfgrtl.c +++ b/gcc/cfgrtl.c @@ -2246,6 +2246,8 @@ purge_dead_edges (basic_block bb) ; else if ((e->flags & EDGE_EH) && can_throw_internal (insn)) ; + else if (flag_tm && find_reg_note (insn, REG_TM, NULL)) + ; else remove = true; } diff --git a/gcc/cgraph.c b/gcc/cgraph.c index f056d3db58e..2d226d49939 100644 --- a/gcc/cgraph.c +++ b/gcc/cgraph.c @@ -1840,6 +1840,8 @@ dump_cgraph_node (FILE *f, struct cgraph_node *node) fprintf (f, " only_called_at_exit"); else if (node->alias) fprintf (f, " alias"); + if (node->tm_clone) + fprintf (f, " tm_clone"); fprintf (f, "\n"); diff --git a/gcc/cgraph.h b/gcc/cgraph.h index 294fb772a5b..9e98ce9e2ef 100644 --- a/gcc/cgraph.h +++ b/gcc/cgraph.h @@ -98,6 +98,9 @@ struct GTY(()) cgraph_local_info { /* True when the function has been originally extern inline, but it is redefined now. */ unsigned redefined_extern_inline : 1; + + /* True if the function may enter serial irrevocable mode. */ + unsigned tm_may_enter_irr : 1; }; /* Information about the function that needs to be computed globally @@ -245,6 +248,11 @@ struct GTY((chain_next ("%h.next"), chain_prev ("%h.previous"))) cgraph_node { unsigned only_called_at_startup : 1; /* True when function can only be called at startup (from static dtor). */ unsigned only_called_at_exit : 1; + /* True when function is the transactional clone of a function which + is called only from inside transactions. */ + /* ?? We should be able to remove this. We have enough bits in + cgraph to calculate it. */ + unsigned tm_clone : 1; }; typedef struct cgraph_node *cgraph_node_ptr; @@ -565,6 +573,8 @@ void verify_cgraph_node (struct cgraph_node *); void cgraph_build_static_cdtor (char which, tree body, int priority); void cgraph_reset_static_var_maps (void); void init_cgraph (void); +struct cgraph_node * cgraph_copy_node_for_versioning (struct cgraph_node *, + tree, VEC(cgraph_edge_p,heap)*, bitmap); struct cgraph_node *cgraph_function_versioning (struct cgraph_node *, VEC(cgraph_edge_p,heap)*, VEC(ipa_replace_map_p,gc)*, @@ -1082,4 +1092,14 @@ cgraph_edge_recursive_p (struct cgraph_edge *e) else return e->caller->decl == callee->decl; } + +/* Return true if the TM_CLONE bit is set for a given FNDECL. */ +static inline bool +decl_is_tm_clone (const_tree fndecl) +{ + struct cgraph_node *n = cgraph_get_node (fndecl); + if (n) + return n->tm_clone; + return false; +} #endif /* GCC_CGRAPH_H */ diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c index 83c47ab66fd..e401b8f2f2b 100644 --- a/gcc/cgraphunit.c +++ b/gcc/cgraphunit.c @@ -2272,7 +2272,7 @@ update_call_expr (struct cgraph_node *new_version) was copied to prevent duplications of calls that are dead in the clone. */ -static struct cgraph_node * +struct cgraph_node * cgraph_copy_node_for_versioning (struct cgraph_node *old_version, tree new_decl, VEC(cgraph_edge_p,heap) *redirect_callers, @@ -2286,7 +2286,7 @@ cgraph_copy_node_for_versioning (struct cgraph_node *old_version, new_version = cgraph_create_node (new_decl); - new_version->analyzed = true; + new_version->analyzed = old_version->analyzed; new_version->local = old_version->local; new_version->local.externally_visible = false; new_version->local.local = true; diff --git a/gcc/combine.c b/gcc/combine.c index 29411149173..ad9aa389871 100644 --- a/gcc/combine.c +++ b/gcc/combine.c @@ -13286,6 +13286,7 @@ distribute_notes (rtx notes, rtx from_insn, rtx i3, rtx i2, rtx elim_i2, case REG_NORETURN: case REG_SETJMP: + case REG_TM: /* These notes must remain with the call. It should not be possible for both I2 and I3 to be a call. */ if (CALL_P (i3)) diff --git a/gcc/common.opt b/gcc/common.opt index 1871054a21c..4eb5b30b1c4 100644 --- a/gcc/common.opt +++ b/gcc/common.opt @@ -1194,6 +1194,10 @@ floop-block Common Report Var(flag_loop_block) Optimization Enable Loop Blocking transformation +fgnu-tm +Common Report Var(flag_tm) +Enable support for GNU transactional memory + floop-flatten Common Report Var(flag_loop_flatten) Optimization Enable Loop Flattening transformation diff --git a/gcc/config/i386/i386-builtin-types.def b/gcc/config/i386/i386-builtin-types.def index 5f64b08505c..5dcb68c2d43 100644 --- a/gcc/config/i386/i386-builtin-types.def +++ b/gcc/config/i386/i386-builtin-types.def @@ -114,6 +114,7 @@ DEF_POINTER_TYPE (PINT, INT) DEF_POINTER_TYPE (PULONGLONG, ULONGLONG) DEF_POINTER_TYPE (PUNSIGNED, UNSIGNED) +DEF_POINTER_TYPE (PV2SI, V2SI) DEF_POINTER_TYPE (PV2DF, V2DF) DEF_POINTER_TYPE (PV2DI, V2DI) DEF_POINTER_TYPE (PV2SF, V2SF) @@ -124,6 +125,7 @@ DEF_POINTER_TYPE (PV8SF, V8SF) DEF_POINTER_TYPE (PV4SI, V4SI) DEF_POINTER_TYPE (PV8SI, V8SI) +DEF_POINTER_TYPE (PCV2SI, V2SI, CONST) DEF_POINTER_TYPE (PCV2DF, V2DF, CONST) DEF_POINTER_TYPE (PCV2SF, V2SF, CONST) DEF_POINTER_TYPE (PCV4DF, V4DF, CONST) @@ -175,6 +177,7 @@ DEF_FUNCTION_TYPE (V2SF, V2SI) DEF_FUNCTION_TYPE (V2SI, V2DF) DEF_FUNCTION_TYPE (V2SI, V2SF) DEF_FUNCTION_TYPE (V2SI, V2SI) +DEF_FUNCTION_TYPE (V2SI, PCV2SI) DEF_FUNCTION_TYPE (V2SI, V4SF) DEF_FUNCTION_TYPE (V32QI, PCCHAR) DEF_FUNCTION_TYPE (V4DF, PCDOUBLE) @@ -188,6 +191,7 @@ DEF_FUNCTION_TYPE (V4SF, PCFLOAT) DEF_FUNCTION_TYPE (V4SF, V2DF) DEF_FUNCTION_TYPE (V4SF, V4DF) DEF_FUNCTION_TYPE (V4SF, V4SF) +DEF_FUNCTION_TYPE (V4SF, PCV4SF) DEF_FUNCTION_TYPE (V4SF, V4SI) DEF_FUNCTION_TYPE (V4SF, V8SF) DEF_FUNCTION_TYPE (V4SF, V8HI) @@ -203,6 +207,7 @@ DEF_FUNCTION_TYPE (V8HI, V8HI) DEF_FUNCTION_TYPE (V8QI, V8QI) DEF_FUNCTION_TYPE (V8SF, PCFLOAT) DEF_FUNCTION_TYPE (V8SF, PCV4SF) +DEF_FUNCTION_TYPE (V8SF, PCV8SF) DEF_FUNCTION_TYPE (V8SF, V4SF) DEF_FUNCTION_TYPE (V8SF, V8SF) DEF_FUNCTION_TYPE (V8SF, V8SI) @@ -353,9 +358,12 @@ DEF_FUNCTION_TYPE (VOID, PFLOAT, V4SF) DEF_FUNCTION_TYPE (VOID, PFLOAT, V8SF) DEF_FUNCTION_TYPE (VOID, PINT, INT) DEF_FUNCTION_TYPE (VOID, PULONGLONG, ULONGLONG) +DEF_FUNCTION_TYPE (VOID, PV2SI, V2SI) DEF_FUNCTION_TYPE (VOID, PV2DI, V2DI) DEF_FUNCTION_TYPE (VOID, PV2SF, V4SF) DEF_FUNCTION_TYPE (VOID, PV4DI, V4DI) +DEF_FUNCTION_TYPE (VOID, PV4SF, V4SF) +DEF_FUNCTION_TYPE (VOID, PV8SF, V8SF) DEF_FUNCTION_TYPE (VOID, UNSIGNED, UNSIGNED) DEF_FUNCTION_TYPE (INT, V16QI, V16QI, INT) diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index bce100a138c..799e12b2b14 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -5028,6 +5028,40 @@ ix86_handle_cconv_attribute (tree *node, tree name, return NULL_TREE; } +/* The transactional memory builtins are implicitly regparm or fastcall + depending on the ABI. Override the generic do-nothing attribute that + these builtins were declared with, and replace it with one of the two + attributes that we expect elsewhere. */ + +static tree +ix86_handle_tm_regparm_attribute (tree *node, tree name ATTRIBUTE_UNUSED, + tree args ATTRIBUTE_UNUSED, + int flags ATTRIBUTE_UNUSED, + bool *no_add_attrs) +{ + tree alt; + + /* In no case do we want to add the placeholder attribute. */ + *no_add_attrs = true; + + /* The 64-bit ABI is unchanged for transactional memory. */ + if (TARGET_64BIT) + return NULL_TREE; + + /* ??? Is there a better way to validate 32-bit windows? We have + cfun->machine->call_abi, but that seems to be set only for 64-bit. */ + if (CHECK_STACK_LIMIT > 0) + alt = tree_cons (get_identifier ("fastcall"), NULL, NULL); + else + { + alt = tree_cons (NULL, build_int_cst (NULL, 2), NULL); + alt = tree_cons (get_identifier ("regparm"), alt, NULL); + } + decl_attributes (node, alt, flags); + + return NULL_TREE; +} + /* This function determines from TYPE the calling-convention. */ unsigned int @@ -26790,6 +26824,154 @@ static const struct builtin_description bdesc_multi_arg[] = { OPTION_MASK_ISA_XOP, CODE_FOR_xop_vpermil2v8sf3, "__builtin_ia32_vpermil2ps256", IX86_BUILTIN_VPERMIL2PS256, UNKNOWN, (int)MULTI_ARG_4_SF2_SI_I1 }, }; + +/* TM vector builtins. */ + +/* Reuse the existing x86-specific `struct builtin_description' cause + we're lazy. Add casts to make them fit. */ +static const struct builtin_description bdesc_tm[] = +{ + { OPTION_MASK_ISA_MMX, CODE_FOR_nothing, "__builtin__ITM_WM64", (enum ix86_builtins) BUILT_IN_TM_STORE_M64, UNKNOWN, VOID_FTYPE_PV2SI_V2SI }, + { OPTION_MASK_ISA_MMX, CODE_FOR_nothing, "__builtin__ITM_WaRM64", (enum ix86_builtins) BUILT_IN_TM_STORE_WAR_M64, UNKNOWN, VOID_FTYPE_PV2SI_V2SI }, + { OPTION_MASK_ISA_MMX, CODE_FOR_nothing, "__builtin__ITM_WaWM64", (enum ix86_builtins) BUILT_IN_TM_STORE_WAW_M64, UNKNOWN, VOID_FTYPE_PV2SI_V2SI }, + { OPTION_MASK_ISA_MMX, CODE_FOR_nothing, "__builtin__ITM_RM64", (enum ix86_builtins) BUILT_IN_TM_LOAD_M64, UNKNOWN, V2SI_FTYPE_PCV2SI }, + { OPTION_MASK_ISA_MMX, CODE_FOR_nothing, "__builtin__ITM_RaRM64", (enum ix86_builtins) BUILT_IN_TM_LOAD_RAR_M64, UNKNOWN, V2SI_FTYPE_PCV2SI }, + { OPTION_MASK_ISA_MMX, CODE_FOR_nothing, "__builtin__ITM_RaWM64", (enum ix86_builtins) BUILT_IN_TM_LOAD_RAW_M64, UNKNOWN, V2SI_FTYPE_PCV2SI }, + { OPTION_MASK_ISA_MMX, CODE_FOR_nothing, "__builtin__ITM_RfWM64", (enum ix86_builtins) BUILT_IN_TM_LOAD_RFW_M64, UNKNOWN, V2SI_FTYPE_PCV2SI }, + + { OPTION_MASK_ISA_SSE, CODE_FOR_nothing, "__builtin__ITM_WM128", (enum ix86_builtins) BUILT_IN_TM_STORE_M128, UNKNOWN, VOID_FTYPE_PV4SF_V4SF }, + { OPTION_MASK_ISA_SSE, CODE_FOR_nothing, "__builtin__ITM_WaRM128", (enum ix86_builtins) BUILT_IN_TM_STORE_WAR_M128, UNKNOWN, VOID_FTYPE_PV4SF_V4SF }, + { OPTION_MASK_ISA_SSE, CODE_FOR_nothing, "__builtin__ITM_WaWM128", (enum ix86_builtins) BUILT_IN_TM_STORE_WAW_M128, UNKNOWN, VOID_FTYPE_PV4SF_V4SF }, + { OPTION_MASK_ISA_SSE, CODE_FOR_nothing, "__builtin__ITM_RM128", (enum ix86_builtins) BUILT_IN_TM_LOAD_M128, UNKNOWN, V4SF_FTYPE_PCV4SF }, + { OPTION_MASK_ISA_SSE, CODE_FOR_nothing, "__builtin__ITM_RaRM128", (enum ix86_builtins) BUILT_IN_TM_LOAD_RAR_M128, UNKNOWN, V4SF_FTYPE_PCV4SF }, + { OPTION_MASK_ISA_SSE, CODE_FOR_nothing, "__builtin__ITM_RaWM128", (enum ix86_builtins) BUILT_IN_TM_LOAD_RAW_M128, UNKNOWN, V4SF_FTYPE_PCV4SF }, + { OPTION_MASK_ISA_SSE, CODE_FOR_nothing, "__builtin__ITM_RfWM128", (enum ix86_builtins) BUILT_IN_TM_LOAD_RFW_M128, UNKNOWN, V4SF_FTYPE_PCV4SF }, + + { OPTION_MASK_ISA_AVX, CODE_FOR_nothing, "__builtin__ITM_WM256", (enum ix86_builtins) BUILT_IN_TM_STORE_M256, UNKNOWN, VOID_FTYPE_PV8SF_V8SF }, + { OPTION_MASK_ISA_AVX, CODE_FOR_nothing, "__builtin__ITM_WaRM256", (enum ix86_builtins) BUILT_IN_TM_STORE_WAR_M256, UNKNOWN, VOID_FTYPE_PV8SF_V8SF }, + { OPTION_MASK_ISA_AVX, CODE_FOR_nothing, "__builtin__ITM_WaWM256", (enum ix86_builtins) BUILT_IN_TM_STORE_WAW_M256, UNKNOWN, VOID_FTYPE_PV8SF_V8SF }, + { OPTION_MASK_ISA_AVX, CODE_FOR_nothing, "__builtin__ITM_RM256", (enum ix86_builtins) BUILT_IN_TM_LOAD_M256, UNKNOWN, V8SF_FTYPE_PCV8SF }, + { OPTION_MASK_ISA_AVX, CODE_FOR_nothing, "__builtin__ITM_RaRM256", (enum ix86_builtins) BUILT_IN_TM_LOAD_RAR_M256, UNKNOWN, V8SF_FTYPE_PCV8SF }, + { OPTION_MASK_ISA_AVX, CODE_FOR_nothing, "__builtin__ITM_RaWM256", (enum ix86_builtins) BUILT_IN_TM_LOAD_RAW_M256, UNKNOWN, V8SF_FTYPE_PCV8SF }, + { OPTION_MASK_ISA_AVX, CODE_FOR_nothing, "__builtin__ITM_RfWM256", (enum ix86_builtins) BUILT_IN_TM_LOAD_RFW_M256, UNKNOWN, V8SF_FTYPE_PCV8SF }, + + { OPTION_MASK_ISA_MMX, CODE_FOR_nothing, "__builtin__ITM_LM64", (enum ix86_builtins) BUILT_IN_TM_LOG_M64, UNKNOWN, VOID_FTYPE_PCVOID }, + { OPTION_MASK_ISA_SSE, CODE_FOR_nothing, "__builtin__ITM_LM128", (enum ix86_builtins) BUILT_IN_TM_LOG_M128, UNKNOWN, VOID_FTYPE_PCVOID }, + { OPTION_MASK_ISA_AVX, CODE_FOR_nothing, "__builtin__ITM_LM256", (enum ix86_builtins) BUILT_IN_TM_LOG_M256, UNKNOWN, VOID_FTYPE_PCVOID }, +}; + +/* TM callbacks. */ + +/* Return the builtin decl needed to load a vector of TYPE. */ + +static tree +ix86_builtin_tm_load (tree type) +{ + if (TREE_CODE (type) == VECTOR_TYPE) + { + switch (tree_low_cst (TYPE_SIZE (type), 1)) + { + case 64: + return builtin_decl_explicit (BUILT_IN_TM_LOAD_M64); + case 128: + return builtin_decl_explicit (BUILT_IN_TM_LOAD_M128); + case 256: + return builtin_decl_explicit (BUILT_IN_TM_LOAD_M256); + } + } + return NULL_TREE; +} + +/* Return the builtin decl needed to store a vector of TYPE. */ + +static tree +ix86_builtin_tm_store (tree type) +{ + if (TREE_CODE (type) == VECTOR_TYPE) + { + switch (tree_low_cst (TYPE_SIZE (type), 1)) + { + case 64: + return builtin_decl_explicit (BUILT_IN_TM_STORE_M64); + case 128: + return builtin_decl_explicit (BUILT_IN_TM_STORE_M128); + case 256: + return builtin_decl_explicit (BUILT_IN_TM_STORE_M256); + } + } + return NULL_TREE; +} + +/* Initialize the transactional memory vector load/store builtins. */ + +static void +ix86_init_tm_builtins (void) +{ + enum ix86_builtin_func_type ftype; + const struct builtin_description *d; + size_t i; + tree decl; + tree attrs_load, attrs_type_load, attrs_store, attrs_type_store; + tree attrs_log, attrs_type_log; + + if (!flag_tm) + return; + + /* Use whatever attributes a normal TM load has. */ + decl = builtin_decl_explicit (BUILT_IN_TM_LOAD_1); + attrs_load = DECL_ATTRIBUTES (decl); + attrs_type_load = TYPE_ATTRIBUTES (TREE_TYPE (decl)); + /* Use whatever attributes a normal TM store has. */ + decl = builtin_decl_explicit (BUILT_IN_TM_STORE_1); + attrs_store = DECL_ATTRIBUTES (decl); + attrs_type_store = TYPE_ATTRIBUTES (TREE_TYPE (decl)); + /* Use whatever attributes a normal TM log has. */ + decl = builtin_decl_explicit (BUILT_IN_TM_LOG); + attrs_log = DECL_ATTRIBUTES (decl); + attrs_type_log = TYPE_ATTRIBUTES (TREE_TYPE (decl)); + + for (i = 0, d = bdesc_tm; + i < ARRAY_SIZE (bdesc_tm); + i++, d++) + { + if ((d->mask & ix86_isa_flags) != 0 + || (lang_hooks.builtin_function + == lang_hooks.builtin_function_ext_scope)) + { + tree type, attrs, attrs_type; + enum built_in_function code = (enum built_in_function) d->code; + + ftype = (enum ix86_builtin_func_type) d->flag; + type = ix86_get_builtin_func_type (ftype); + + if (BUILTIN_TM_LOAD_P (code)) + { + attrs = attrs_load; + attrs_type = attrs_type_load; + } + else if (BUILTIN_TM_STORE_P (code)) + { + attrs = attrs_store; + attrs_type = attrs_type_store; + } + else + { + attrs = attrs_log; + attrs_type = attrs_type_log; + } + decl = add_builtin_function (d->name, type, code, BUILT_IN_NORMAL, + /* The builtin without the prefix for + calling it directly. */ + d->name + strlen ("__builtin_"), + attrs); + /* add_builtin_function() will set the DECL_ATTRIBUTES, now + set the TYPE_ATTRIBUTES. */ + decl_attributes (&TREE_TYPE (decl), attrs_type, ATTR_FLAG_BUILT_IN); + + set_builtin_decl (code, decl, false); + } + } +} /* Set up all the MMX/SSE builtins, even builtins for instructions that are not in the current target ISA to allow the user to compile particular modules @@ -27163,6 +27345,7 @@ ix86_init_builtins (void) TREE_READONLY (t) = 1; ix86_builtins[(int) IX86_BUILTIN_COPYSIGNQ] = t; + ix86_init_tm_builtins (); ix86_init_mmx_sse_builtins (); if (TARGET_LP64) @@ -29921,7 +30104,6 @@ avx_vperm2f128_parallel (rtx par, enum machine_mode mode) return mask + 1; } - /* Store OPERAND to the memory after reload is completed. This means that we can't easily use assign_stack_local. */ rtx @@ -34784,6 +34966,11 @@ static const struct attribute_spec ix86_attribute_table[] = for FP arguments. */ { "sseregparm", 0, 0, false, true, true, ix86_handle_cconv_attribute, true }, + /* The transactional memory builtins are implicitly regparm or fastcall + depending on the ABI. Override the generic do-nothing attribute that + these builtins were declared with. */ + { "*tm regparm", 0, 0, false, true, true, ix86_handle_tm_regparm_attribute, + true }, /* force_align_arg_pointer says this function realigns the stack at entry. */ { (const char *)&ix86_force_align_arg_pointer_string, 0, 0, false, true, true, ix86_handle_cconv_attribute, false }, @@ -37954,6 +38141,12 @@ ix86_autovectorize_vector_sizes (void) #define TARGET_VECTORIZE_BUILTIN_VECTORIZED_FUNCTION \ ix86_builtin_vectorized_function +#undef TARGET_VECTORIZE_BUILTIN_TM_LOAD +#define TARGET_VECTORIZE_BUILTIN_TM_LOAD ix86_builtin_tm_load + +#undef TARGET_VECTORIZE_BUILTIN_TM_STORE +#define TARGET_VECTORIZE_BUILTIN_TM_STORE ix86_builtin_tm_store + #undef TARGET_VECTORIZE_BUILTIN_GATHER #define TARGET_VECTORIZE_BUILTIN_GATHER ix86_vectorize_builtin_gather diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index bcdecdf4cc3..15b44b5cfb8 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,40 @@ +2011-11-07 Richard Henderson <rth@redhat.com> + Aldy Hernandez <aldyh@redhat.com> + Torvald Riegel <triegel@redhat.com> + + Merged from transactional-memory. + + * call.c (build_new_function_call): Call tm_malloc_replacement. + * class.c (check_bases): Compute transaction attributes for the + class based on its base classes. + (look_for_tm_attr_overrides, set_one_vmethod_tm_attributes, + set_method_tm_attributes): New. + (finish_struct_1): Call set_method_tm_attributes. + * cp-tree.h (begin_transaction_stmt, finish_transaction_stmt, + build_transaction_expr): Declare. + (TRANSACTION_EXPR_IS_STMT): New. + * decl.c (push_cp_library_fn): Set attribute to transaction_safe. + * except.c (do_get_exception_ptr): Apply transaction_pure. + (do_begin_catch): Mark _ITM_cxa_begin_catch transaction_pure and + record as transactional-memory wrapper. + (do_end_catch): Similarly for _ITM_cxa_end_catch. + (do_allocate_exception): Similarly for _ITM_cxa_allocate_exception. + (build_throw): Similarly for _ITM_cxa_throw. Make __cxa_rethrow pure. + * parser.h (struct cp_parser): Add in_transaction flag. + * parser.c (enum non_integral_constant): Add NIC_TRANSACTION. + (cp_parser_non_integral_constant_expression): Handle NIC_TRANSACTION. + (enum required_token): Add transaction tokens. + (cp_parser_transaction, cp_parser_transaction_expression, + cp_parser_function_transaction, cp_parser_transaction_cancel, + cp_parser_txn_attribute_opt): New. + (cp_parser_unary_expression): Handle RID_TRANSACTION*. + (cp_parser_statement, cp_parser_function_definition_after_declarator, + cp_parser_token_starts_function_definition_p): Same. + (cp_parser_required_error): Handle RT_TRANSACTION*. + * pt.c (tsubst_expr): Handle TRANSACTION_EXPR. + * semantics.c (begin_transaction_stmt, finish_transaction_stmt, + build_transaction_expr): New. + 2011-11-08 Dodji Seketeli <dodji@redhat.com> Fix context handling of alias-declaration diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 2bf22f96ed8..578905e41e6 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -3826,6 +3826,9 @@ build_new_function_call (tree fn, VEC(tree,gc) **args, bool koenig_p, return error_mark_node; } + if (flag_tm) + tm_malloc_replacement (fn); + /* If this function was found without using argument dependent lookup, then we want to ignore any undeclared friend functions. */ diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 1775868aa8a..be632be64c8 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -1227,13 +1227,12 @@ check_bases (tree t, int* no_const_asn_ref_p) { int i; - int seen_non_virtual_nearly_empty_base_p; + bool seen_non_virtual_nearly_empty_base_p = 0; + int seen_tm_mask = 0; tree base_binfo; tree binfo; tree field = NULL_TREE; - seen_non_virtual_nearly_empty_base_p = 0; - if (!CLASSTYPE_NON_STD_LAYOUT (t)) for (field = TYPE_FIELDS (t); field; field = DECL_CHAIN (field)) if (TREE_CODE (field) == FIELD_DECL) @@ -1338,6 +1337,23 @@ check_bases (tree t, break; } } + + /* Don't bother collecting tm attributes if transactional memory + support is not enabled. */ + if (flag_tm) + { + tree tm_attr = find_tm_attribute (TYPE_ATTRIBUTES (basetype)); + if (tm_attr) + seen_tm_mask |= tm_attr_to_mask (tm_attr); + } + } + + /* If one of the base classes had TM attributes, and the current class + doesn't define its own, then the current class inherits one. */ + if (seen_tm_mask && !find_tm_attribute (TYPE_ATTRIBUTES (t))) + { + tree tm_attr = tm_mask_to_attr (seen_tm_mask & -seen_tm_mask); + TYPE_ATTRIBUTES (t) = tree_cons (tm_attr, NULL, TYPE_ATTRIBUTES (t)); } } @@ -4258,6 +4274,137 @@ clone_constructors_and_destructors (tree t) clone_function_decl (OVL_CURRENT (fns), /*update_method_vec_p=*/1); } +/* Subroutine of set_one_vmethod_tm_attributes. Search base classes + of TYPE for virtual functions which FNDECL overrides. Return a + mask of the tm attributes found therein. */ + +static int +look_for_tm_attr_overrides (tree type, tree fndecl) +{ + tree binfo = TYPE_BINFO (type); + tree base_binfo; + int ix, found = 0; + + for (ix = 0; BINFO_BASE_ITERATE (binfo, ix, base_binfo); ++ix) + { + tree o, basetype = BINFO_TYPE (base_binfo); + + if (!TYPE_POLYMORPHIC_P (basetype)) + continue; + + o = look_for_overrides_here (basetype, fndecl); + if (o) + found |= tm_attr_to_mask (find_tm_attribute + (TYPE_ATTRIBUTES (TREE_TYPE (o)))); + else + found |= look_for_tm_attr_overrides (basetype, fndecl); + } + + return found; +} + +/* Subroutine of set_method_tm_attributes. Handle the checks and + inheritance for one virtual method FNDECL. */ + +static void +set_one_vmethod_tm_attributes (tree type, tree fndecl) +{ + tree tm_attr; + int found, have; + + found = look_for_tm_attr_overrides (type, fndecl); + + /* If FNDECL doesn't actually override anything (i.e. T is the + class that first declares FNDECL virtual), then we're done. */ + if (found == 0) + return; + + tm_attr = find_tm_attribute (TYPE_ATTRIBUTES (TREE_TYPE (fndecl))); + have = tm_attr_to_mask (tm_attr); + + /* Intel STM Language Extension 3.0, Section 4.2 table 4: + tm_pure must match exactly, otherwise no weakening of + tm_safe > tm_callable > nothing. */ + /* ??? The tm_pure attribute didn't make the transition to the + multivendor language spec. */ + if (have == TM_ATTR_PURE) + { + if (found != TM_ATTR_PURE) + { + found &= -found; + goto err_override; + } + } + /* If the overridden function is tm_pure, then FNDECL must be. */ + else if (found == TM_ATTR_PURE && tm_attr) + goto err_override; + /* Look for base class combinations that cannot be satisfied. */ + else if (found != TM_ATTR_PURE && (found & TM_ATTR_PURE)) + { + found &= ~TM_ATTR_PURE; + found &= -found; + error_at (DECL_SOURCE_LOCATION (fndecl), + "method overrides both %<transaction_pure%> and %qE methods", + tm_mask_to_attr (found)); + } + /* If FNDECL did not declare an attribute, then inherit the most + restrictive one. */ + else if (tm_attr == NULL) + { + apply_tm_attr (fndecl, tm_mask_to_attr (found & -found)); + } + /* Otherwise validate that we're not weaker than a function + that is being overridden. */ + else + { + found &= -found; + if (found <= TM_ATTR_CALLABLE && have > found) + goto err_override; + } + return; + + err_override: + error_at (DECL_SOURCE_LOCATION (fndecl), + "method declared %qE overriding %qE method", + tm_attr, tm_mask_to_attr (found)); +} + +/* For each of the methods in T, propagate a class-level tm attribute. */ + +static void +set_method_tm_attributes (tree t) +{ + tree class_tm_attr, fndecl; + + /* Don't bother collecting tm attributes if transactional memory + support is not enabled. */ + if (!flag_tm) + return; + + /* Process virtual methods first, as they inherit directly from the + base virtual function and also require validation of new attributes. */ + if (TYPE_CONTAINS_VPTR_P (t)) + { + tree vchain; + for (vchain = BINFO_VIRTUALS (TYPE_BINFO (t)); vchain; + vchain = TREE_CHAIN (vchain)) + set_one_vmethod_tm_attributes (t, BV_FN (vchain)); + } + + /* If the class doesn't have an attribute, nothing more to do. */ + class_tm_attr = find_tm_attribute (TYPE_ATTRIBUTES (t)); + if (class_tm_attr == NULL) + return; + + /* Any method that does not yet have a tm attribute inherits + the one from the class. */ + for (fndecl = TYPE_METHODS (t); fndecl; fndecl = TREE_CHAIN (fndecl)) + { + if (!find_tm_attribute (TYPE_ATTRIBUTES (TREE_TYPE (fndecl)))) + apply_tm_attr (fndecl, class_tm_attr); + } +} + /* Returns true iff class T has a user-defined constructor other than the default constructor. */ @@ -5841,6 +5988,7 @@ finish_struct_1 (tree t) } finish_struct_bits (t); + set_method_tm_attributes (t); /* Complete the rtl for any static member objects of the type we're working on. */ diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 177f10084af..32d08caf9cc 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -73,6 +73,7 @@ c-common.h, not after. VEC_INIT_EXPR_IS_CONSTEXPR (in VEC_INIT_EXPR) DECL_OVERRIDE_P (in FUNCTION_DECL) IMPLICIT_CONV_EXPR_DIRECT_INIT (in IMPLICIT_CONV_EXPR) + TRANSACTION_EXPR_IS_STMT (in TRANSACTION_EXPR) 1: IDENTIFIER_VIRTUAL_P (in IDENTIFIER_NODE) TI_PENDING_TEMPLATE_FLAG. TEMPLATE_PARMS_FOR_INLINE. @@ -3890,6 +3891,10 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter) TREE_TYPE (OMP_CLAUSE_RANGE_CHECK (NODE, OMP_CLAUSE_PRIVATE, \ OMP_CLAUSE_COPYPRIVATE)) +/* Nonzero if this transaction expression's body contains statements. */ +#define TRANSACTION_EXPR_IS_STMT(NODE) \ + TREE_LANG_FLAG_0 (TRANSACTION_EXPR_CHECK (NODE)) + /* These macros provide convenient access to the various _STMT nodes created when parsing template declarations. */ #define TRY_STMTS(NODE) TREE_OPERAND (TRY_BLOCK_CHECK (NODE), 0) @@ -5556,6 +5561,9 @@ extern void finish_omp_atomic (enum tree_code, enum tree_code, extern void finish_omp_barrier (void); extern void finish_omp_flush (void); extern void finish_omp_taskwait (void); +extern tree begin_transaction_stmt (location_t, tree *, int); +extern void finish_transaction_stmt (tree, tree, int); +extern tree build_transaction_expr (location_t, tree, int); extern void finish_omp_taskyield (void); extern bool cxx_omp_create_clause_info (tree, tree, bool, bool, bool); extern tree baselink_for_fns (tree); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 1c337763110..1c46adf99a1 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -4001,6 +4001,8 @@ push_cp_library_fn (enum tree_code operator_code, tree type) operator_code, type); pushdecl (fn); + if (flag_tm) + apply_tm_attr (fn, get_identifier ("transaction_safe")); return fn; } diff --git a/gcc/cp/except.c b/gcc/cp/except.c index e529685c992..670a66f1611 100644 --- a/gcc/cp/except.c +++ b/gcc/cp/except.c @@ -173,6 +173,9 @@ do_get_exception_ptr (void) { /* Declare void* __cxa_get_exception_ptr (void *) throw(). */ fn = declare_nothrow_library_fn (fn, ptr_type_node, ptr_type_node); + + if (flag_tm) + apply_tm_attr (fn, get_identifier ("transaction_pure")); } return cp_build_function_call_nary (fn, tf_warning_or_error, @@ -192,6 +195,17 @@ do_begin_catch (void) { /* Declare void* __cxa_begin_catch (void *) throw(). */ fn = declare_nothrow_library_fn (fn, ptr_type_node, ptr_type_node); + + /* Create its transactional-memory equivalent. */ + if (flag_tm) + { + tree fn2 = get_identifier ("_ITM_cxa_begin_catch"); + if (!get_global_value_if_present (fn2, &fn2)) + fn2 = declare_nothrow_library_fn (fn2, ptr_type_node, + ptr_type_node); + apply_tm_attr (fn2, get_identifier ("transaction_pure")); + record_tm_replacement (fn, fn2); + } } return cp_build_function_call_nary (fn, tf_warning_or_error, @@ -231,6 +245,19 @@ do_end_catch (tree type) fn = push_void_library_fn (fn, void_list_node); /* This can throw if the destructor for the exception throws. */ TREE_NOTHROW (fn) = 0; + + /* Create its transactional-memory equivalent. */ + if (flag_tm) + { + tree fn2 = get_identifier ("_ITM_cxa_end_catch"); + if (!get_global_value_if_present (fn2, &fn2)) + { + fn2 = push_void_library_fn (fn2, void_list_node); + TREE_NOTHROW (fn2) = 0; + } + apply_tm_attr (fn2, get_identifier ("transaction_pure")); + record_tm_replacement (fn, fn2); + } } cleanup = cp_build_function_call_vec (fn, NULL, tf_warning_or_error); @@ -581,6 +608,16 @@ do_allocate_exception (tree type) { /* Declare void *__cxa_allocate_exception(size_t) throw(). */ fn = declare_nothrow_library_fn (fn, ptr_type_node, size_type_node); + + if (flag_tm) + { + tree fn2 = get_identifier ("_ITM_cxa_allocate_exception"); + if (!get_global_value_if_present (fn2, &fn2)) + fn2 = declare_nothrow_library_fn (fn2, ptr_type_node, + size_type_node); + apply_tm_attr (fn2, get_identifier ("transaction_pure")); + record_tm_replacement (fn, fn2); + } } return cp_build_function_call_nary (fn, tf_warning_or_error, @@ -712,6 +749,15 @@ build_throw (tree exp) ptr_type_node, ptr_type_node, cleanup_type, NULL_TREE); fn = push_throw_library_fn (fn, tmp); + + if (flag_tm) + { + tree fn2 = get_identifier ("_ITM_cxa_throw"); + if (!get_global_value_if_present (fn2, &fn2)) + fn2 = push_throw_library_fn (fn2, tmp); + apply_tm_attr (fn2, get_identifier ("transaction_pure")); + record_tm_replacement (fn, fn2); + } } /* [except.throw] @@ -831,6 +877,9 @@ build_throw (tree exp) (fn, build_function_type_list (void_type_node, NULL_TREE)); } + if (flag_tm) + apply_tm_attr (fn, get_identifier ("transaction_pure")); + /* ??? Indicate that this function call allows exceptions of the type of the enclosing catch block (if known). */ exp = cp_build_function_call_vec (fn, NULL, tf_warning_or_error); diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 3d3587794f2..12f3c4011fa 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -106,7 +106,9 @@ typedef enum non_integral_constant { /* a comma operator */ NIC_COMMA, /* a call to a constructor */ - NIC_CONSTRUCTOR + NIC_CONSTRUCTOR, + /* a transaction expression */ + NIC_TRANSACTION } non_integral_constant; /* The various kinds of errors about name-lookup failing. */ @@ -171,7 +173,10 @@ typedef enum required_token { RT_INTERATION, /* iteration-statement */ RT_JUMP, /* jump-statement */ RT_CLASS_KEY, /* class-key */ - RT_CLASS_TYPENAME_TEMPLATE /* class, typename, or template */ + RT_CLASS_TYPENAME_TEMPLATE, /* class, typename, or template */ + RT_TRANSACTION_ATOMIC, /* __transaction_atomic */ + RT_TRANSACTION_RELAXED, /* __transaction_relaxed */ + RT_TRANSACTION_CANCEL /* __transaction_cancel */ } required_token; /* Prototypes. */ @@ -2106,6 +2111,17 @@ static bool cp_parser_extension_opt static void cp_parser_label_declaration (cp_parser *); +/* Transactional Memory Extensions */ + +static tree cp_parser_transaction + (cp_parser *, enum rid); +static tree cp_parser_transaction_expression + (cp_parser *, enum rid); +static bool cp_parser_function_transaction + (cp_parser *, enum rid); +static tree cp_parser_transaction_cancel + (cp_parser *); + enum pragma_context { pragma_external, pragma_stmt, pragma_compound }; static bool cp_parser_pragma (cp_parser *, enum pragma_context); @@ -2671,6 +2687,10 @@ cp_parser_non_integral_constant_expression (cp_parser *parser, error ("a call to a constructor " "cannot appear in a constant-expression"); return true; + case NIC_TRANSACTION: + error ("a transaction expression " + "cannot appear in a constant-expression"); + return true; case NIC_THIS: msg = "this"; break; @@ -6372,6 +6392,10 @@ cp_parser_unary_expression (cp_parser *parser, bool address_p, bool cast_p, } break; + case RID_TRANSACTION_ATOMIC: + case RID_TRANSACTION_RELAXED: + return cp_parser_transaction_expression (parser, keyword); + case RID_NOEXCEPT: { tree expr; @@ -8506,6 +8530,11 @@ cp_parser_lambda_body (cp_parser* parser, tree lambda_expr) declaration-statement try-block + TM Extension: + + statement: + atomic-statement + IN_COMPOUND is true when the statement is nested inside a cp_parser_compound_statement; this matters for certain pragmas. @@ -8582,6 +8611,14 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr, cp_parser_declaration_statement (parser); return; + case RID_TRANSACTION_ATOMIC: + case RID_TRANSACTION_RELAXED: + statement = cp_parser_transaction (parser, keyword); + break; + case RID_TRANSACTION_CANCEL: + statement = cp_parser_transaction_cancel (parser); + break; + default: /* It might be a keyword like `int' that can start a declaration-statement. */ @@ -15194,6 +15231,11 @@ cp_parser_asm_definition (cp_parser* parser) function-definition: __extension__ function-definition + TM Extension: + + function-definition: + decl-specifier-seq [opt] declarator function-transaction-block + The DECL_SPECIFIERS apply to this declarator. Returns a representation of the entity declared. If MEMBER_P is TRUE, then this declarator appears in a class scope. The new DECL created by @@ -20911,12 +20953,19 @@ cp_parser_function_definition_after_declarator (cp_parser* parser, start_lambda_scope (current_function_decl); - /* If the next token is `try', then we are looking at a - function-try-block. */ - if (cp_lexer_next_token_is_keyword (parser->lexer, RID_TRY)) + /* If the next token is `try', `__transaction_atomic', or + `__transaction_relaxed`, then we are looking at either function-try-block + or function-transaction-block. Note that all of these include the + function-body. */ + if (cp_lexer_next_token_is_keyword (parser->lexer, RID_TRANSACTION_ATOMIC)) + ctor_initializer_p = cp_parser_function_transaction (parser, + RID_TRANSACTION_ATOMIC); + else if (cp_lexer_next_token_is_keyword (parser->lexer, + RID_TRANSACTION_RELAXED)) + ctor_initializer_p = cp_parser_function_transaction (parser, + RID_TRANSACTION_RELAXED); + else if (cp_lexer_next_token_is_keyword (parser->lexer, RID_TRY)) ctor_initializer_p = cp_parser_function_try_block (parser); - /* A function-try-block includes the function-body, so we only do - this next part if we're not processing a function-try-block. */ else ctor_initializer_p = cp_parser_ctor_initializer_opt_and_function_body (parser); @@ -22073,6 +22122,12 @@ cp_parser_required_error (cp_parser *parser, case RT_AT_THROW: cp_parser_error (parser, "expected %<@throw%>"); return; + case RT_TRANSACTION_ATOMIC: + cp_parser_error (parser, "expected %<__transaction_atomic%>"); + return; + case RT_TRANSACTION_RELAXED: + cp_parser_error (parser, "expected %<__transaction_relaxed%>"); + return; default: break; } @@ -22303,6 +22358,10 @@ cp_parser_token_starts_function_definition_p (cp_token* token) || token->type == CPP_COLON /* A function-try-block begins with `try'. */ || token->keyword == RID_TRY + /* A function-transaction-block begins with `__transaction_atomic' + or `__transaction_relaxed'. */ + || token->keyword == RID_TRANSACTION_ATOMIC + || token->keyword == RID_TRANSACTION_RELAXED /* The named return value extension begins with `return'. */ || token->keyword == RID_RETURN); } @@ -26623,6 +26682,272 @@ cp_parser_omp_construct (cp_parser *parser, cp_token *pragma_tok) SET_EXPR_LOCATION (stmt, pragma_tok->location); } +/* Transactional Memory parsing routines. */ + +/* Parse a transaction attribute. + + txn-attribute: + attribute + [ [ identifier ] ] + + ??? Simplify this when C++0x bracket attributes are + implemented properly. */ + +static tree +cp_parser_txn_attribute_opt (cp_parser *parser) +{ + cp_token *token; + tree attr_name, attr = NULL; + + if (cp_lexer_next_token_is_keyword (parser->lexer, RID_ATTRIBUTE)) + return cp_parser_attributes_opt (parser); + + if (cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_SQUARE)) + return NULL_TREE; + cp_lexer_consume_token (parser->lexer); + if (!cp_parser_require (parser, CPP_OPEN_SQUARE, RT_OPEN_SQUARE)) + goto error1; + + token = cp_lexer_peek_token (parser->lexer); + if (token->type == CPP_NAME || token->type == CPP_KEYWORD) + { + token = cp_lexer_consume_token (parser->lexer); + + attr_name = (token->type == CPP_KEYWORD + /* For keywords, use the canonical spelling, + not the parsed identifier. */ + ? ridpointers[(int) token->keyword] + : token->u.value); + attr = build_tree_list (attr_name, NULL_TREE); + } + else + cp_parser_error (parser, "expected identifier"); + + cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE); + error1: + cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE); + return attr; +} + +/* Parse a __transaction_atomic or __transaction_relaxed statement. + + transaction-statement: + __transaction_atomic txn-attribute[opt] txn-exception-spec[opt] + compound-statement + __transaction_relaxed txn-exception-spec[opt] compound-statement + + ??? The exception specification is not yet implemented. +*/ + +static tree +cp_parser_transaction (cp_parser *parser, enum rid keyword) +{ + unsigned char old_in = parser->in_transaction; + unsigned char this_in = 1, new_in; + cp_token *token; + tree stmt, attrs; + + gcc_assert (keyword == RID_TRANSACTION_ATOMIC + || keyword == RID_TRANSACTION_RELAXED); + token = cp_parser_require_keyword (parser, keyword, + (keyword == RID_TRANSACTION_ATOMIC ? RT_TRANSACTION_ATOMIC + : RT_TRANSACTION_RELAXED)); + gcc_assert (token != NULL); + + if (keyword == RID_TRANSACTION_RELAXED) + this_in |= TM_STMT_ATTR_RELAXED; + else + { + attrs = cp_parser_txn_attribute_opt (parser); + if (attrs) + this_in |= parse_tm_stmt_attr (attrs, TM_STMT_ATTR_OUTER); + } + + /* Keep track if we're in the lexical scope of an outer transaction. */ + new_in = this_in | (old_in & TM_STMT_ATTR_OUTER); + + stmt = begin_transaction_stmt (token->location, NULL, this_in); + + parser->in_transaction = new_in; + cp_parser_compound_statement (parser, NULL, false, false); + parser->in_transaction = old_in; + + finish_transaction_stmt (stmt, NULL, this_in); + + return stmt; +} + +/* Parse a __transaction_atomic or __transaction_relaxed expression. + + transaction-expression: + __transaction_atomic txn-exception-spec[opt] ( expression ) + __transaction_relaxed txn-exception-spec[opt] ( expression ) + + ??? The exception specification is not yet implemented. +*/ + +static tree +cp_parser_transaction_expression (cp_parser *parser, enum rid keyword) +{ + unsigned char old_in = parser->in_transaction; + unsigned char this_in = 1; + cp_token *token; + tree ret; + + gcc_assert (keyword == RID_TRANSACTION_ATOMIC + || keyword == RID_TRANSACTION_RELAXED); + + if (!flag_tm) + error (keyword == RID_TRANSACTION_RELAXED + ? G_("%<__transaction_relaxed%> without transactional memory " + "support enabled") + : G_("%<__transaction_atomic%> without transactional memory " + "support enabled")); + + token = cp_parser_require_keyword (parser, keyword, + (keyword == RID_TRANSACTION_ATOMIC ? RT_TRANSACTION_ATOMIC + : RT_TRANSACTION_RELAXED)); + gcc_assert (token != NULL); + + if (keyword == RID_TRANSACTION_RELAXED) + this_in |= TM_STMT_ATTR_RELAXED; + + parser->in_transaction = this_in; + if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN)) + { + tree expr = cp_parser_expression (parser, /*cast_p=*/false, NULL); + ret = build_transaction_expr (token->location, expr, this_in); + } + else + { + cp_parser_error (parser, "expected %<(%>"); + ret = error_mark_node; + } + parser->in_transaction = old_in; + + if (cp_parser_non_integral_constant_expression (parser, NIC_TRANSACTION)) + return error_mark_node; + + return (flag_tm ? ret : error_mark_node); +} + +/* Parse a function-transaction-block. + + function-transaction-block: + __transaction_atomic txn-attribute[opt] ctor-initializer[opt] + function-body + __transaction_atomic txn-attribute[opt] function-try-block + __transaction_relaxed ctor-initializer[opt] function-body + __transaction_relaxed function-try-block +*/ + +static bool +cp_parser_function_transaction (cp_parser *parser, enum rid keyword) +{ + unsigned char old_in = parser->in_transaction; + unsigned char new_in = 1; + tree compound_stmt, stmt, attrs; + bool ctor_initializer_p; + cp_token *token; + + gcc_assert (keyword == RID_TRANSACTION_ATOMIC + || keyword == RID_TRANSACTION_RELAXED); + token = cp_parser_require_keyword (parser, keyword, + (keyword == RID_TRANSACTION_ATOMIC ? RT_TRANSACTION_ATOMIC + : RT_TRANSACTION_RELAXED)); + gcc_assert (token != NULL); + + if (keyword == RID_TRANSACTION_RELAXED) + new_in |= TM_STMT_ATTR_RELAXED; + else + { + attrs = cp_parser_txn_attribute_opt (parser); + if (attrs) + new_in |= parse_tm_stmt_attr (attrs, TM_STMT_ATTR_OUTER); + } + + stmt = begin_transaction_stmt (token->location, &compound_stmt, new_in); + + parser->in_transaction = new_in; + + if (cp_lexer_next_token_is_keyword (parser->lexer, RID_TRY)) + ctor_initializer_p = cp_parser_function_try_block (parser); + else + ctor_initializer_p + = cp_parser_ctor_initializer_opt_and_function_body (parser); + + parser->in_transaction = old_in; + + finish_transaction_stmt (stmt, compound_stmt, new_in); + + return ctor_initializer_p; +} + +/* Parse a __transaction_cancel statement. + + cancel-statement: + __transaction_cancel txn-attribute[opt] ; + __transaction_cancel txn-attribute[opt] throw-expression ; + + ??? Cancel and throw is not yet implemented. */ + +static tree +cp_parser_transaction_cancel (cp_parser *parser) +{ + cp_token *token; + bool is_outer = false; + tree stmt, attrs; + + token = cp_parser_require_keyword (parser, RID_TRANSACTION_CANCEL, + RT_TRANSACTION_CANCEL); + gcc_assert (token != NULL); + + attrs = cp_parser_txn_attribute_opt (parser); + if (attrs) + is_outer = (parse_tm_stmt_attr (attrs, TM_STMT_ATTR_OUTER) != 0); + + /* ??? Parse cancel-and-throw here. */ + + cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON); + + if (!flag_tm) + { + error_at (token->location, "%<__transaction_cancel%> without " + "transactional memory support enabled"); + return error_mark_node; + } + else if (parser->in_transaction & TM_STMT_ATTR_RELAXED) + { + error_at (token->location, "%<__transaction_cancel%> within a " + "%<__transaction_relaxed%>"); + return error_mark_node; + } + else if (is_outer) + { + if ((parser->in_transaction & TM_STMT_ATTR_OUTER) == 0 + && !is_tm_may_cancel_outer (current_function_decl)) + { + error_at (token->location, "outer %<__transaction_cancel%> not " + "within outer %<__transaction_atomic%>"); + error_at (token->location, + " or a %<transaction_may_cancel_outer%> function"); + return error_mark_node; + } + } + else if (parser->in_transaction == 0) + { + error_at (token->location, "%<__transaction_cancel%> not within " + "%<__transaction_atomic%>"); + return error_mark_node; + } + + stmt = build_tm_abort_call (token->location, is_outer); + add_stmt (stmt); + finish_stmt (); + + return stmt; +} + /* The parser. */ static GTY (()) cp_parser *the_parser; diff --git a/gcc/cp/parser.h b/gcc/cp/parser.h index b44d23cd8cd..5b95f0892de 100644 --- a/gcc/cp/parser.h +++ b/gcc/cp/parser.h @@ -329,6 +329,10 @@ typedef struct GTY(()) cp_parser { a local class. */ bool in_function_body; + /* Nonzero if we're processing a __transaction_atomic or + __transaction_relaxed statement. */ + unsigned char in_transaction; + /* TRUE if we can auto-correct a colon to a scope operator. */ bool colon_corrects_to_scope_p; diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index bf2a2c63735..8c91a9ed021 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -13108,6 +13108,28 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl, } break; + case TRANSACTION_EXPR: + { + int flags = 0; + flags |= (TRANSACTION_EXPR_OUTER (t) ? TM_STMT_ATTR_OUTER : 0); + flags |= (TRANSACTION_EXPR_RELAXED (t) ? TM_STMT_ATTR_RELAXED : 0); + + if (TRANSACTION_EXPR_IS_STMT (t)) + { + stmt = begin_transaction_stmt (input_location, NULL, flags); + RECUR (TRANSACTION_EXPR_BODY (t)); + finish_transaction_stmt (stmt, NULL, flags); + } + else + { + stmt = build_transaction_expr (EXPR_LOCATION (t), + RECUR (TRANSACTION_EXPR_BODY (t)), + flags); + return stmt; + } + } + break; + case EXPR_PACK_EXPANSION: error ("invalid use of pack expansion expression"); return error_mark_node; diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 9d6bd316aa1..508e2529fbe 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -4968,6 +4968,64 @@ finish_omp_taskyield (void) finish_expr_stmt (stmt); } +/* Begin a __transaction_atomic or __transaction_relaxed statement. + If PCOMPOUND is non-null, this is for a function-transaction-block, and we + should create an extra compound stmt. */ + +tree +begin_transaction_stmt (location_t loc, tree *pcompound, int flags) +{ + tree r; + + if (pcompound) + *pcompound = begin_compound_stmt (0); + + r = build_stmt (loc, TRANSACTION_EXPR, NULL_TREE); + + /* Only add the statement to the function if support enabled. */ + if (flag_tm) + add_stmt (r); + else + error_at (loc, ((flags & TM_STMT_ATTR_RELAXED) != 0 + ? G_("%<__transaction_relaxed%> without " + "transactional memory support enabled") + : G_("%<__transaction_atomic%> without " + "transactional memory support enabled"))); + + TRANSACTION_EXPR_BODY (r) = push_stmt_list (); + return r; +} + +/* End a __transaction_atomic or __transaction_relaxed statement. + If COMPOUND_STMT is non-null, this is for a function-transaction-block, + and we should end the compound. */ + +void +finish_transaction_stmt (tree stmt, tree compound_stmt, int flags) +{ + TRANSACTION_EXPR_BODY (stmt) = pop_stmt_list (TRANSACTION_EXPR_BODY (stmt)); + TRANSACTION_EXPR_OUTER (stmt) = (flags & TM_STMT_ATTR_OUTER) != 0; + TRANSACTION_EXPR_RELAXED (stmt) = (flags & TM_STMT_ATTR_RELAXED) != 0; + TRANSACTION_EXPR_IS_STMT (stmt) = 1; + + if (compound_stmt) + finish_compound_stmt (compound_stmt); + finish_stmt (); +} + +/* Build a __transaction_atomic or __transaction_relaxed expression. */ + +tree +build_transaction_expr (location_t loc, tree expr, int flags) +{ + tree ret; + ret = build1 (TRANSACTION_EXPR, TREE_TYPE (expr), expr); + if (flags & TM_STMT_ATTR_RELAXED) + TRANSACTION_EXPR_RELAXED (ret) = 1; + SET_EXPR_LOCATION (ret, loc); + return ret; +} + void init_cp_semantics (void) { @@ -8099,6 +8157,7 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags) case STMT_EXPR: case EXPR_STMT: case BIND_EXPR: + case TRANSACTION_EXPR: if (flags & tf_error) error ("expression %qE is not a constant-expression", t); return false; diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index e3fb21b84d7..3a5a3414cd9 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -1723,6 +1723,19 @@ Program Interface v3.0 @w{@uref{http://www.openmp.org/}}. This option implies @option{-pthread}, and thus is only supported on targets that have support for @option{-pthread}. +@item -fgnu-tm +@opindex fgnu-tm +When the option @option{-fgnu-tm} is specified, the compiler will +generate code for the Linux variant of Intel's current Transactional +Memory ABI specification document (Revision 1.1, May 6 2009). This is +an experimental feature whose interface may change in future versions +of GCC, as the official specification changes. Please note that not +all architectures are supported for this feature. + +For more information on GCC's support for transactional memory, +@xref{Enabling libitm,,The GNU Transactional Memory Library,libitm,GNU +Transactional Memory Library}. + @item -fms-extensions @opindex fms-extensions Accept some non-standard constructs used in Microsoft header files. @@ -9113,6 +9126,13 @@ parameters only when their cumulative size is less or equal to @option{ipa-sra-ptr-growth-factor} times the size of the original pointer parameter. +@item tm-max-aggregate-size +When making copies of thread-local variables in a transaction, this +parameter specifies the size in bytes after which variables will be +saved with the logging functions as opposed to save/restore code +sequence pairs. This option only applies when using +@option{-fgnu-tm}. + @item graphite-max-nb-scop-params To avoid exponential effects in the Graphite loop transforms, the number of parameters in a Static Control Part (SCoP) is bounded. The diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index fed770265b9..d96932b4e48 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -5758,6 +5758,14 @@ mode returned by @code{TARGET_VECTORIZE_PREFERRED_SIMD_MODE}. The default is zero which means to not iterate over other vector sizes. @end deftypefn +@deftypefn {Target Hook} tree TARGET_VECTORIZE_BUILTIN_TM_LOAD (tree) +This hook should return the built-in decl needed to load a vector of the given type within a transaction. +@end deftypefn + +@deftypefn {Target Hook} tree TARGET_VECTORIZE_BUILTIN_TM_STORE (tree) +This hook should return the built-in decl needed to store a vector of the given type within a transaction. +@end deftypefn + @deftypefn {Target Hook} tree TARGET_VECTORIZE_BUILTIN_GATHER (const_tree @var{mem_vectype}, const_tree @var{index_type}, int @var{scale}) Target builtin that implements vector gather operation. @var{mem_vectype} is the vector type of the load and @var{index_type} is scalar type of diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in index f0c6ce0a771..146e38a35e1 100644 --- a/gcc/doc/tm.texi.in +++ b/gcc/doc/tm.texi.in @@ -5696,6 +5696,10 @@ mode returned by @code{TARGET_VECTORIZE_PREFERRED_SIMD_MODE}. The default is zero which means to not iterate over other vector sizes. @end deftypefn +@hook TARGET_VECTORIZE_BUILTIN_TM_LOAD + +@hook TARGET_VECTORIZE_BUILTIN_TM_STORE + @hook TARGET_VECTORIZE_BUILTIN_GATHER Target builtin that implements vector gather operation. @var{mem_vectype} is the vector type of the load and @var{index_type} is scalar type of diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c index c2bc56b9758..4a27a058b83 100644 --- a/gcc/emit-rtl.c +++ b/gcc/emit-rtl.c @@ -3595,6 +3595,7 @@ try_split (rtx pat, rtx trial, int last) case REG_NORETURN: case REG_SETJMP: + case REG_TM: for (insn = insn_last; insn != NULL_RTX; insn = PREV_INSN (insn)) { if (CALL_P (insn)) diff --git a/gcc/gimple-low.c b/gcc/gimple-low.c index fd03ba4702b..f6deba17938 100644 --- a/gcc/gimple-low.c +++ b/gcc/gimple-low.c @@ -396,6 +396,11 @@ lower_stmt (gimple_stmt_iterator *gsi, struct lower_data *data) lower_sequence (gimple_eh_filter_failure (stmt), data); break; + case GIMPLE_EH_ELSE: + lower_sequence (gimple_eh_else_n_body (stmt), data); + lower_sequence (gimple_eh_else_e_body (stmt), data); + break; + case GIMPLE_NOP: case GIMPLE_ASM: case GIMPLE_ASSIGN: @@ -446,6 +451,10 @@ lower_stmt (gimple_stmt_iterator *gsi, struct lower_data *data) data->cannot_fallthru = false; return; + case GIMPLE_TRANSACTION: + lower_sequence (gimple_transaction_body (stmt), data); + break; + default: gcc_unreachable (); } @@ -727,6 +736,10 @@ gimple_stmt_may_fallthru (gimple stmt) return (gimple_seq_may_fallthru (gimple_try_eval (stmt)) && gimple_seq_may_fallthru (gimple_try_cleanup (stmt))); + case GIMPLE_EH_ELSE: + return (gimple_seq_may_fallthru (gimple_eh_else_n_body (stmt)) + || gimple_seq_may_fallthru (gimple_eh_else_e_body (stmt))); + case GIMPLE_CALL: /* Functions that do not return do not fall through. */ return (gimple_call_flags (stmt) & ECF_NORETURN) == 0; diff --git a/gcc/gimple-pretty-print.c b/gcc/gimple-pretty-print.c index 981d5b094d9..df703b4ce75 100644 --- a/gcc/gimple-pretty-print.c +++ b/gcc/gimple-pretty-print.c @@ -33,6 +33,7 @@ along with GCC; see the file COPYING3. If not see #include "tree-pass.h" #include "gimple.h" #include "value-prof.h" +#include "trans-mem.h" #define INDENT(SPACE) \ do { int i; for (i = 0; i < SPACE; i++) pp_space (buffer); } while (0) @@ -162,6 +163,7 @@ debug_gimple_seq (gimple_seq seq) 'd' - outputs an int as a decimal, 's' - outputs a string, 'n' - outputs a newline, + 'x' - outputs an int as hexadecimal, '+' - increases indent by 2 then outputs a newline, '-' - decreases indent by 2 then outputs a newline. */ @@ -216,6 +218,10 @@ dump_gimple_fmt (pretty_printer *buffer, int spc, int flags, newline_and_indent (buffer, spc); break; + case 'x': + pp_scalar (buffer, "%x", va_arg (args, int)); + break; + case '+': spc += 2; newline_and_indent (buffer, spc); @@ -622,6 +628,7 @@ static void dump_gimple_call (pretty_printer *buffer, gimple gs, int spc, int flags) { tree lhs = gimple_call_lhs (gs); + tree fn = gimple_call_fn (gs); if (flags & TDF_ALIAS) { @@ -648,8 +655,7 @@ dump_gimple_call (pretty_printer *buffer, gimple gs, int spc, int flags) dump_gimple_fmt (buffer, spc, flags, "%G <%s, %T", gs, internal_fn_name (gimple_call_internal_fn (gs)), lhs); else - dump_gimple_fmt (buffer, spc, flags, "%G <%T, %T", - gs, gimple_call_fn (gs), lhs); + dump_gimple_fmt (buffer, spc, flags, "%G <%T, %T", gs, fn, lhs); if (gimple_call_num_args (gs) > 0) { pp_string (buffer, ", "); @@ -672,7 +678,7 @@ dump_gimple_call (pretty_printer *buffer, gimple gs, int spc, int flags) if (gimple_call_internal_p (gs)) pp_string (buffer, internal_fn_name (gimple_call_internal_fn (gs))); else - print_call_name (buffer, gimple_call_fn (gs), flags); + print_call_name (buffer, fn, flags); pp_string (buffer, " ("); dump_gimple_call_args (buffer, gs, flags); pp_character (buffer, ')'); @@ -689,9 +695,59 @@ dump_gimple_call (pretty_printer *buffer, gimple gs, int spc, int flags) if (gimple_call_return_slot_opt_p (gs)) pp_string (buffer, " [return slot optimization]"); - if (gimple_call_tail_p (gs)) pp_string (buffer, " [tail call]"); + + /* Dump the arguments of _ITM_beginTransaction sanely. */ + if (TREE_CODE (fn) == ADDR_EXPR) + fn = TREE_OPERAND (fn, 0); + if (TREE_CODE (fn) == FUNCTION_DECL && decl_is_tm_clone (fn)) + pp_string (buffer, " [tm-clone]"); + if (TREE_CODE (fn) == FUNCTION_DECL + && DECL_BUILT_IN_CLASS (fn) == BUILT_IN_NORMAL + && DECL_FUNCTION_CODE (fn) == BUILT_IN_TM_START + && gimple_call_num_args (gs) > 0) + { + tree t = gimple_call_arg (gs, 0); + unsigned HOST_WIDE_INT props; + gcc_assert (TREE_CODE (t) == INTEGER_CST); + + pp_string (buffer, " [ "); + + /* Get the transaction code properties. */ + props = TREE_INT_CST_LOW (t); + + if (props & PR_INSTRUMENTEDCODE) + pp_string (buffer, "instrumentedCode "); + if (props & PR_UNINSTRUMENTEDCODE) + pp_string (buffer, "uninstrumentedCode "); + if (props & PR_HASNOXMMUPDATE) + pp_string (buffer, "hasNoXMMUpdate "); + if (props & PR_HASNOABORT) + pp_string (buffer, "hasNoAbort "); + if (props & PR_HASNOIRREVOCABLE) + pp_string (buffer, "hasNoIrrevocable "); + if (props & PR_DOESGOIRREVOCABLE) + pp_string (buffer, "doesGoIrrevocable "); + if (props & PR_HASNOSIMPLEREADS) + pp_string (buffer, "hasNoSimpleReads "); + if (props & PR_AWBARRIERSOMITTED) + pp_string (buffer, "awBarriersOmitted "); + if (props & PR_RARBARRIERSOMITTED) + pp_string (buffer, "RaRBarriersOmitted "); + if (props & PR_UNDOLOGCODE) + pp_string (buffer, "undoLogCode "); + if (props & PR_PREFERUNINSTRUMENTED) + pp_string (buffer, "preferUninstrumented "); + if (props & PR_EXCEPTIONBLOCK) + pp_string (buffer, "exceptionBlock "); + if (props & PR_HASELSE) + pp_string (buffer, "hasElse "); + if (props & PR_READONLY) + pp_string (buffer, "readOnly "); + + pp_string (buffer, "]"); + } } @@ -947,6 +1003,24 @@ dump_gimple_eh_must_not_throw (pretty_printer *buffer, gimple gs, } +/* Dump a GIMPLE_EH_ELSE tuple on the pretty_printer BUFFER, SPC spaces of + indent. FLAGS specifies details to show in the dump (see TDF_* in + tree-pass.h). */ + +static void +dump_gimple_eh_else (pretty_printer *buffer, gimple gs, int spc, int flags) +{ + if (flags & TDF_RAW) + dump_gimple_fmt (buffer, spc, flags, + "%G <%+N_BODY <%S>%nE_BODY <%S>%->", gs, + gimple_eh_else_n_body (gs), gimple_eh_else_e_body (gs)); + else + dump_gimple_fmt (buffer, spc, flags, + "<<<if_normal_exit>>>%+{%S}%-<<<else_eh_exit>>>%+{%S}", + gimple_eh_else_n_body (gs), gimple_eh_else_e_body (gs)); +} + + /* Dump a GIMPLE_RESX tuple on the pretty_printer BUFFER, SPC spaces of indent. FLAGS specifies details to show in the dump (see TDF_* in tree-pass.h). */ @@ -1269,6 +1343,86 @@ dump_gimple_omp_return (pretty_printer *buffer, gimple gs, int spc, int flags) } } +/* Dump a GIMPLE_TRANSACTION tuple on the pretty_printer BUFFER. */ + +static void +dump_gimple_transaction (pretty_printer *buffer, gimple gs, int spc, int flags) +{ + unsigned subcode = gimple_transaction_subcode (gs); + + if (flags & TDF_RAW) + { + dump_gimple_fmt (buffer, spc, flags, + "%G [SUBCODE=%x,LABEL=%T] <%+BODY <%S> >", + gs, subcode, gimple_transaction_label (gs), + gimple_transaction_body (gs)); + } + else + { + if (subcode & GTMA_IS_OUTER) + pp_string (buffer, "__transaction_atomic [[outer]]"); + else if (subcode & GTMA_IS_RELAXED) + pp_string (buffer, "__transaction_relaxed"); + else + pp_string (buffer, "__transaction_atomic"); + subcode &= ~GTMA_DECLARATION_MASK; + + if (subcode || gimple_transaction_label (gs)) + { + pp_string (buffer, " //"); + if (gimple_transaction_label (gs)) + { + pp_string (buffer, " LABEL="); + dump_generic_node (buffer, gimple_transaction_label (gs), + spc, flags, false); + } + if (subcode) + { + pp_string (buffer, " SUBCODE=[ "); + if (subcode & GTMA_HAVE_ABORT) + { + pp_string (buffer, "GTMA_HAVE_ABORT "); + subcode &= ~GTMA_HAVE_ABORT; + } + if (subcode & GTMA_HAVE_LOAD) + { + pp_string (buffer, "GTMA_HAVE_LOAD "); + subcode &= ~GTMA_HAVE_LOAD; + } + if (subcode & GTMA_HAVE_STORE) + { + pp_string (buffer, "GTMA_HAVE_STORE "); + subcode &= ~GTMA_HAVE_STORE; + } + if (subcode & GTMA_MAY_ENTER_IRREVOCABLE) + { + pp_string (buffer, "GTMA_MAY_ENTER_IRREVOCABLE "); + subcode &= ~GTMA_MAY_ENTER_IRREVOCABLE; + } + if (subcode & GTMA_DOES_GO_IRREVOCABLE) + { + pp_string (buffer, "GTMA_DOES_GO_IRREVOCABLE "); + subcode &= ~GTMA_DOES_GO_IRREVOCABLE; + } + if (subcode) + pp_printf (buffer, "0x%x ", subcode); + pp_string (buffer, "]"); + } + } + + if (!gimple_seq_empty_p (gimple_transaction_body (gs))) + { + newline_and_indent (buffer, spc + 2); + pp_character (buffer, '{'); + pp_newline (buffer); + dump_gimple_seq (buffer, gimple_transaction_body (gs), + spc + 4, flags); + newline_and_indent (buffer, spc + 2); + pp_character (buffer, '}'); + } + } +} + /* Dump a GIMPLE_ASM tuple on the pretty_printer BUFFER, SPC spaces of indent. FLAGS specifies details to show in the dump (see TDF_* in tree-pass.h). */ @@ -1855,6 +2009,10 @@ dump_gimple_stmt (pretty_printer *buffer, gimple gs, int spc, int flags) dump_gimple_eh_must_not_throw (buffer, gs, spc, flags); break; + case GIMPLE_EH_ELSE: + dump_gimple_eh_else (buffer, gs, spc, flags); + break; + case GIMPLE_RESX: dump_gimple_resx (buffer, gs, spc, flags); break; @@ -1877,6 +2035,10 @@ dump_gimple_stmt (pretty_printer *buffer, gimple gs, int spc, int flags) pp_string (buffer, " predictor."); break; + case GIMPLE_TRANSACTION: + dump_gimple_transaction (buffer, gs, spc, flags); + break; + default: GIMPLE_NIY; } diff --git a/gcc/gimple.c b/gcc/gimple.c index b2874bb071b..e803f56d0a3 100644 --- a/gcc/gimple.c +++ b/gcc/gimple.c @@ -743,6 +743,17 @@ gimple_build_eh_must_not_throw (tree decl) return p; } +/* Build a GIMPLE_EH_ELSE statement. */ + +gimple +gimple_build_eh_else (gimple_seq n_body, gimple_seq e_body) +{ + gimple p = gimple_alloc (GIMPLE_EH_ELSE, 0); + gimple_eh_else_set_n_body (p, n_body); + gimple_eh_else_set_e_body (p, e_body); + return p; +} + /* Build a GIMPLE_TRY statement. EVAL is the expression to evaluate. @@ -1146,6 +1157,17 @@ gimple_build_omp_atomic_store (tree val) return p; } +/* Build a GIMPLE_TRANSACTION statement. */ + +gimple +gimple_build_transaction (gimple_seq body, tree label) +{ + gimple p = gimple_alloc (GIMPLE_TRANSACTION, 0); + gimple_transaction_set_body (p, body); + gimple_transaction_set_label (p, label); + return p; +} + /* Build a GIMPLE_PREDICT statement. PREDICT is one of the predictors from predict.def, OUTCOME is NOT_TAKEN or TAKEN. */ @@ -1319,9 +1341,11 @@ gimple_seq_copy (gimple_seq src) /* Walk all the statements in the sequence SEQ calling walk_gimple_stmt on each one. WI is as in walk_gimple_stmt. - If walk_gimple_stmt returns non-NULL, the walk is stopped, the - value is stored in WI->CALLBACK_RESULT and the statement that - produced the value is returned. + If walk_gimple_stmt returns non-NULL, the walk is stopped, and the + value is stored in WI->CALLBACK_RESULT. Also, the statement that + produced the value is returned if this statement has not been + removed by a callback (wi->removed_stmt). If the statement has + been removed, NULL is returned. Otherwise, all the statements are walked and NULL returned. */ @@ -1331,7 +1355,7 @@ walk_gimple_seq (gimple_seq seq, walk_stmt_fn callback_stmt, { gimple_stmt_iterator gsi; - for (gsi = gsi_start (seq); !gsi_end_p (gsi); gsi_next (&gsi)) + for (gsi = gsi_start (seq); !gsi_end_p (gsi); ) { tree ret = walk_gimple_stmt (&gsi, callback_stmt, callback_op, wi); if (ret) @@ -1340,8 +1364,12 @@ walk_gimple_seq (gimple_seq seq, walk_stmt_fn callback_stmt, to hold it. */ gcc_assert (wi); wi->callback_result = ret; - return gsi_stmt (gsi); + + return wi->removed_stmt ? NULL : gsi_stmt (gsi); } + + if (!wi->removed_stmt) + gsi_next (&gsi); } if (wi) @@ -1680,6 +1708,13 @@ walk_gimple_op (gimple stmt, walk_tree_fn callback_op, return ret; break; + case GIMPLE_TRANSACTION: + ret = walk_tree (gimple_transaction_label_ptr (stmt), callback_op, + wi, pset); + if (ret) + return ret; + break; + /* Tuples that do not have operands. */ case GIMPLE_NOP: case GIMPLE_RESX: @@ -1730,10 +1765,13 @@ walk_gimple_stmt (gimple_stmt_iterator *gsi, walk_stmt_fn callback_stmt, gimple stmt = gsi_stmt (*gsi); if (wi) - wi->gsi = *gsi; + { + wi->gsi = *gsi; + wi->removed_stmt = false; - if (wi && wi->want_locations && gimple_has_location (stmt)) - input_location = gimple_location (stmt); + if (wi->want_locations && gimple_has_location (stmt)) + input_location = gimple_location (stmt); + } ret = NULL; @@ -1750,6 +1788,9 @@ walk_gimple_stmt (gimple_stmt_iterator *gsi, walk_stmt_fn callback_stmt, a value to return. */ gcc_assert (tree_ret == NULL); + if (wi && wi->removed_stmt) + return NULL; + /* Re-read stmt in case the callback changed it. */ stmt = gsi_stmt (*gsi); } @@ -1786,6 +1827,17 @@ walk_gimple_stmt (gimple_stmt_iterator *gsi, walk_stmt_fn callback_stmt, return wi->callback_result; break; + case GIMPLE_EH_ELSE: + ret = walk_gimple_seq (gimple_eh_else_n_body (stmt), + callback_stmt, callback_op, wi); + if (ret) + return wi->callback_result; + ret = walk_gimple_seq (gimple_eh_else_e_body (stmt), + callback_stmt, callback_op, wi); + if (ret) + return wi->callback_result; + break; + case GIMPLE_TRY: ret = walk_gimple_seq (gimple_try_eval (stmt), callback_stmt, callback_op, wi); @@ -1813,8 +1865,8 @@ walk_gimple_stmt (gimple_stmt_iterator *gsi, walk_stmt_fn callback_stmt, case GIMPLE_OMP_TASK: case GIMPLE_OMP_SECTIONS: case GIMPLE_OMP_SINGLE: - ret = walk_gimple_seq (gimple_omp_body (stmt), callback_stmt, callback_op, - wi); + ret = walk_gimple_seq (gimple_omp_body (stmt), callback_stmt, + callback_op, wi); if (ret) return wi->callback_result; break; @@ -1826,6 +1878,13 @@ walk_gimple_stmt (gimple_stmt_iterator *gsi, walk_stmt_fn callback_stmt, return wi->callback_result; break; + case GIMPLE_TRANSACTION: + ret = walk_gimple_seq (gimple_transaction_body (stmt), + callback_stmt, callback_op, wi); + if (ret) + return wi->callback_result; + break; + default: gcc_assert (!gimple_has_substatements (stmt)); break; @@ -2252,6 +2311,13 @@ gimple_copy (gimple stmt) gimple_eh_filter_set_types (copy, t); break; + case GIMPLE_EH_ELSE: + new_seq = gimple_seq_copy (gimple_eh_else_n_body (stmt)); + gimple_eh_else_set_n_body (copy, new_seq); + new_seq = gimple_seq_copy (gimple_eh_else_e_body (stmt)); + gimple_eh_else_set_e_body (copy, new_seq); + break; + case GIMPLE_TRY: new_seq = gimple_seq_copy (gimple_try_eval (stmt)); gimple_try_set_eval (copy, new_seq); @@ -2327,6 +2393,11 @@ gimple_copy (gimple stmt) gimple_omp_set_body (copy, new_seq); break; + case GIMPLE_TRANSACTION: + new_seq = gimple_seq_copy (gimple_transaction_body (stmt)); + gimple_transaction_set_body (copy, new_seq); + break; + case GIMPLE_WITH_CLEANUP_EXPR: new_seq = gimple_seq_copy (gimple_wce_cleanup (stmt)); gimple_wce_set_cleanup (copy, new_seq); @@ -2782,37 +2853,6 @@ is_gimple_address (const_tree t) } } -/* Strip out all handled components that produce invariant - offsets. */ - -static const_tree -strip_invariant_refs (const_tree op) -{ - while (handled_component_p (op)) - { - switch (TREE_CODE (op)) - { - case ARRAY_REF: - case ARRAY_RANGE_REF: - if (!is_gimple_constant (TREE_OPERAND (op, 1)) - || TREE_OPERAND (op, 2) != NULL_TREE - || TREE_OPERAND (op, 3) != NULL_TREE) - return NULL; - break; - - case COMPONENT_REF: - if (TREE_OPERAND (op, 2) != NULL_TREE) - return NULL; - break; - - default:; - } - op = TREE_OPERAND (op, 0); - } - - return op; -} - /* Return true if T is a gimple invariant address. */ bool @@ -3075,21 +3115,6 @@ is_gimple_mem_ref_addr (tree t) || decl_address_invariant_p (TREE_OPERAND (t, 0))))); } -/* If T makes a function call, return the corresponding CALL_EXPR operand. - Otherwise, return NULL_TREE. */ - -tree -get_call_expr_in (tree t) -{ - if (TREE_CODE (t) == MODIFY_EXPR) - t = TREE_OPERAND (t, 1); - if (TREE_CODE (t) == WITH_SIZE_EXPR) - t = TREE_OPERAND (t, 0); - if (TREE_CODE (t) == CALL_EXPR) - return t; - return NULL_TREE; -} - /* Given a memory reference expression T, return its base address. The base address of a memory reference expression is the main diff --git a/gcc/gimple.def b/gcc/gimple.def index 2b5488ab0b6..5ae97025cb2 100644 --- a/gcc/gimple.def +++ b/gcc/gimple.def @@ -124,6 +124,14 @@ DEFGSCODE(GIMPLE_ASM, "gimple_asm", GSS_ASM) CHAIN is the optional static chain link for nested functions. */ DEFGSCODE(GIMPLE_CALL, "gimple_call", GSS_CALL) +/* GIMPLE_TRANSACTION <BODY, LABEL> represents __transaction_atomic and + __transaction_relaxed blocks. + BODY is the sequence of statements inside the transaction. + LABEL is a label for the statement immediately following the + transaction. This is before RETURN so that it has MEM_OPS, + so that it can clobber global memory. */ +DEFGSCODE(GIMPLE_TRANSACTION, "gimple_transaction", GSS_TRANSACTION) + /* GIMPLE_RETURN <RETVAL> represents return statements. RETVAL is the value to return or NULL. If a value is returned it @@ -151,6 +159,12 @@ DEFGSCODE(GIMPLE_EH_FILTER, "gimple_eh_filter", GSS_EH_FILTER) be invoked if an exception propagates to this point. */ DEFGSCODE(GIMPLE_EH_MUST_NOT_THROW, "gimple_eh_must_not_throw", GSS_EH_MNT) +/* GIMPLE_EH_ELSE <N_BODY, E_BODY> must be the sole contents of + a GIMPLE_TRY_FINALLY node. For all normal exits from the try block, + N_BODY is run; for all exception exits from the try block, + E_BODY is run. */ +DEFGSCODE(GIMPLE_EH_ELSE, "gimple_eh_else", GSS_EH_ELSE) + /* GIMPLE_RESX resumes execution after an exception. */ DEFGSCODE(GIMPLE_RESX, "gimple_resx", GSS_EH_CTRL) diff --git a/gcc/gimple.h b/gcc/gimple.h index 666c44c8591..ffecc2617af 100644 --- a/gcc/gimple.h +++ b/gcc/gimple.h @@ -487,6 +487,15 @@ struct GTY(()) gimple_statement_eh_filter { gimple_seq failure; }; +/* GIMPLE_EH_ELSE */ + +struct GTY(()) gimple_statement_eh_else { + /* [ WORD 1-4 ] */ + struct gimple_statement_base gsbase; + + /* [ WORD 5,6 ] */ + gimple_seq n_body, e_body; +}; /* GIMPLE_EH_MUST_NOT_THROW */ @@ -757,6 +766,43 @@ struct GTY(()) gimple_statement_omp_atomic_store { tree val; }; +/* GIMPLE_TRANSACTION. */ + +/* Bits to be stored in the GIMPLE_TRANSACTION subcode. */ + +/* The __transaction_atomic was declared [[outer]] or it is + __transaction_relaxed. */ +#define GTMA_IS_OUTER (1u << 0) +#define GTMA_IS_RELAXED (1u << 1) +#define GTMA_DECLARATION_MASK (GTMA_IS_OUTER | GTMA_IS_RELAXED) + +/* The transaction is seen to not have an abort. */ +#define GTMA_HAVE_ABORT (1u << 2) +/* The transaction is seen to have loads or stores. */ +#define GTMA_HAVE_LOAD (1u << 3) +#define GTMA_HAVE_STORE (1u << 4) +/* The transaction MAY enter serial irrevocable mode in its dynamic scope. */ +#define GTMA_MAY_ENTER_IRREVOCABLE (1u << 5) +/* The transaction WILL enter serial irrevocable mode. + An irrevocable block post-dominates the entire transaction, such + that all invocations of the transaction will go serial-irrevocable. + In such case, we don't bother instrumenting the transaction, and + tell the runtime that it should begin the transaction in + serial-irrevocable mode. */ +#define GTMA_DOES_GO_IRREVOCABLE (1u << 6) + +struct GTY(()) gimple_statement_transaction +{ + /* [ WORD 1-10 ] */ + struct gimple_statement_with_memory_ops_base gsbase; + + /* [ WORD 11 ] */ + gimple_seq body; + + /* [ WORD 12 ] */ + tree label; +}; + #define DEFGSSTRUCT(SYM, STRUCT, HAS_TREE_OP) SYM, enum gimple_statement_structure_enum { #include "gsstruct.def" @@ -779,6 +825,7 @@ union GTY ((desc ("gimple_statement_structure (&%h)"), variable_size)) gimple_st struct gimple_statement_catch GTY ((tag ("GSS_CATCH"))) gimple_catch; struct gimple_statement_eh_filter GTY ((tag ("GSS_EH_FILTER"))) gimple_eh_filter; struct gimple_statement_eh_mnt GTY ((tag ("GSS_EH_MNT"))) gimple_eh_mnt; + struct gimple_statement_eh_else GTY ((tag ("GSS_EH_ELSE"))) gimple_eh_else; struct gimple_statement_phi GTY ((tag ("GSS_PHI"))) gimple_phi; struct gimple_statement_eh_ctrl GTY ((tag ("GSS_EH_CTRL"))) gimple_eh_ctrl; struct gimple_statement_try GTY ((tag ("GSS_TRY"))) gimple_try; @@ -793,6 +840,7 @@ union GTY ((desc ("gimple_statement_structure (&%h)"), variable_size)) gimple_st struct gimple_statement_omp_continue GTY ((tag ("GSS_OMP_CONTINUE"))) gimple_omp_continue; struct gimple_statement_omp_atomic_load GTY ((tag ("GSS_OMP_ATOMIC_LOAD"))) gimple_omp_atomic_load; struct gimple_statement_omp_atomic_store GTY ((tag ("GSS_OMP_ATOMIC_STORE"))) gimple_omp_atomic_store; + struct gimple_statement_transaction GTY((tag ("GSS_TRANSACTION"))) gimple_transaction; }; /* In gimple.c. */ @@ -846,6 +894,7 @@ gimple gimple_build_asm_vec (const char *, VEC(tree,gc) *, VEC(tree,gc) *, gimple gimple_build_catch (tree, gimple_seq); gimple gimple_build_eh_filter (tree, gimple_seq); gimple gimple_build_eh_must_not_throw (tree); +gimple gimple_build_eh_else (gimple_seq, gimple_seq); gimple gimple_build_try (gimple_seq, gimple_seq, enum gimple_try_flags); gimple gimple_build_wce (gimple_seq); gimple gimple_build_resx (int); @@ -868,6 +917,7 @@ gimple gimple_build_omp_single (gimple_seq, tree); gimple gimple_build_cdt (tree, tree); gimple gimple_build_omp_atomic_load (tree, tree); gimple gimple_build_omp_atomic_store (tree); +gimple gimple_build_transaction (gimple_seq, tree); gimple gimple_build_predict (enum br_predictor, enum prediction); enum gimple_statement_structure_enum gss_for_assign (enum tree_code); void sort_case_labels (VEC(tree,heap) *); @@ -963,8 +1013,6 @@ extern bool is_gimple_non_addressable (tree t); /* Returns true iff T is a valid call address expression. */ extern bool is_gimple_call_addr (tree); -/* If T makes a function call, returns the CALL_EXPR operand. */ -extern tree get_call_expr_in (tree t); extern void recalculate_side_effects (tree); extern bool gimple_compare_field_offset (tree, tree); @@ -1076,6 +1124,9 @@ extern tree canonicalize_cond_expr_cond (tree); /* In omp-low.c. */ extern tree omp_reduction_init (tree, tree); +/* In trans-mem.c. */ +extern void diagnose_tm_safe_errors (tree); + /* In tree-nested.c. */ extern void lower_nested_functions (tree); extern void insert_field_into_struct (tree, tree); @@ -1134,6 +1185,7 @@ gimple_has_substatements (gimple g) case GIMPLE_BIND: case GIMPLE_CATCH: case GIMPLE_EH_FILTER: + case GIMPLE_EH_ELSE: case GIMPLE_TRY: case GIMPLE_OMP_FOR: case GIMPLE_OMP_MASTER: @@ -1145,6 +1197,7 @@ gimple_has_substatements (gimple g) case GIMPLE_OMP_SINGLE: case GIMPLE_OMP_CRITICAL: case GIMPLE_WITH_CLEANUP_EXPR: + case GIMPLE_TRANSACTION: return true; default: @@ -3177,6 +3230,35 @@ gimple_eh_must_not_throw_set_fndecl (gimple gs, tree decl) gs->gimple_eh_mnt.fndecl = decl; } +/* GIMPLE_EH_ELSE accessors. */ + +static inline gimple_seq +gimple_eh_else_n_body (gimple gs) +{ + GIMPLE_CHECK (gs, GIMPLE_EH_ELSE); + return gs->gimple_eh_else.n_body; +} + +static inline gimple_seq +gimple_eh_else_e_body (gimple gs) +{ + GIMPLE_CHECK (gs, GIMPLE_EH_ELSE); + return gs->gimple_eh_else.e_body; +} + +static inline void +gimple_eh_else_set_n_body (gimple gs, gimple_seq seq) +{ + GIMPLE_CHECK (gs, GIMPLE_EH_ELSE); + gs->gimple_eh_else.n_body = seq; +} + +static inline void +gimple_eh_else_set_e_body (gimple gs, gimple_seq seq) +{ + GIMPLE_CHECK (gs, GIMPLE_EH_ELSE); + gs->gimple_eh_else.e_body = seq; +} /* GIMPLE_TRY accessors. */ @@ -4555,6 +4637,67 @@ gimple_omp_continue_set_control_use (gimple g, tree use) g->gimple_omp_continue.control_use = use; } +/* Return the body for the GIMPLE_TRANSACTION statement GS. */ + +static inline gimple_seq +gimple_transaction_body (gimple gs) +{ + GIMPLE_CHECK (gs, GIMPLE_TRANSACTION); + return gs->gimple_transaction.body; +} + +/* Return the label associated with a GIMPLE_TRANSACTION. */ + +static inline tree +gimple_transaction_label (const_gimple gs) +{ + GIMPLE_CHECK (gs, GIMPLE_TRANSACTION); + return gs->gimple_transaction.label; +} + +static inline tree * +gimple_transaction_label_ptr (gimple gs) +{ + GIMPLE_CHECK (gs, GIMPLE_TRANSACTION); + return &gs->gimple_transaction.label; +} + +/* Return the subcode associated with a GIMPLE_TRANSACTION. */ + +static inline unsigned int +gimple_transaction_subcode (const_gimple gs) +{ + GIMPLE_CHECK (gs, GIMPLE_TRANSACTION); + return gs->gsbase.subcode; +} + +/* Set BODY to be the body for the GIMPLE_TRANSACTION statement GS. */ + +static inline void +gimple_transaction_set_body (gimple gs, gimple_seq body) +{ + GIMPLE_CHECK (gs, GIMPLE_TRANSACTION); + gs->gimple_transaction.body = body; +} + +/* Set the label associated with a GIMPLE_TRANSACTION. */ + +static inline void +gimple_transaction_set_label (gimple gs, tree label) +{ + GIMPLE_CHECK (gs, GIMPLE_TRANSACTION); + gs->gimple_transaction.label = label; +} + +/* Set the subcode associated with a GIMPLE_TRANSACTION. */ + +static inline void +gimple_transaction_set_subcode (gimple gs, unsigned int subcode) +{ + GIMPLE_CHECK (gs, GIMPLE_TRANSACTION); + gs->gsbase.subcode = subcode; +} + /* Return a pointer to the return value for GIMPLE_RETURN GS. */ @@ -4981,6 +5124,12 @@ struct walk_stmt_info will be visited more than once. */ struct pointer_set_t *pset; + /* Operand returned by the callbacks. This is set when calling + walk_gimple_seq. If the walk_stmt_fn or walk_tree_fn callback + returns non-NULL, this field will contain the tree returned by + the last callback. */ + tree callback_result; + /* Indicates whether the operand being examined may be replaced with something that matches is_gimple_val (if true) or something slightly more complicated (if false). "Something" technically @@ -4993,23 +5142,20 @@ struct walk_stmt_info statement 'foo (&var)', the flag VAL_ONLY will initially be set to true, however, when walking &var, the operand of that ADDR_EXPR does not need to be a GIMPLE value. */ - bool val_only; + BOOL_BITFIELD val_only : 1; /* True if we are currently walking the LHS of an assignment. */ - bool is_lhs; + BOOL_BITFIELD is_lhs : 1; /* Optional. Set to true by the callback functions if they made any changes. */ - bool changed; + BOOL_BITFIELD changed : 1; /* True if we're interested in location information. */ - bool want_locations; + BOOL_BITFIELD want_locations : 1; - /* Operand returned by the callbacks. This is set when calling - walk_gimple_seq. If the walk_stmt_fn or walk_tree_fn callback - returns non-NULL, this field will contain the tree returned by - the last callback. */ - tree callback_result; + /* True if we've removed the statement that was processed. */ + BOOL_BITFIELD removed_stmt : 1; }; /* Callback for walk_gimple_stmt. Called for every statement found diff --git a/gcc/gimplify.c b/gcc/gimplify.c index 8c2c5ac2c9c..99e0d0dad90 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -413,6 +413,8 @@ create_tmp_var_name (const char *prefix) char *preftmp = ASTRDUP (prefix); remove_suffix (preftmp, strlen (preftmp)); + clean_symbol_name (preftmp); + prefix = preftmp; } @@ -1072,6 +1074,12 @@ voidify_wrapper_expr (tree wrapper, tree temp) } break; + case TRANSACTION_EXPR: + TREE_SIDE_EFFECTS (*p) = 1; + TREE_TYPE (*p) = void_type_node; + p = &TRANSACTION_EXPR_BODY (*p); + break; + default: goto out; } @@ -6527,6 +6535,53 @@ gimplify_omp_atomic (tree *expr_p, gimple_seq *pre_p) return GS_ALL_DONE; } +/* Gimplify a TRANSACTION_EXPR. This involves gimplification of the + body, and adding some EH bits. */ + +static enum gimplify_status +gimplify_transaction (tree *expr_p, gimple_seq *pre_p) +{ + tree expr = *expr_p, temp, tbody = TRANSACTION_EXPR_BODY (expr); + gimple g; + gimple_seq body = NULL; + struct gimplify_ctx gctx; + int subcode = 0; + + /* Wrap the transaction body in a BIND_EXPR so we have a context + where to put decls for OpenMP. */ + if (TREE_CODE (tbody) != BIND_EXPR) + { + tree bind = build3 (BIND_EXPR, void_type_node, NULL, tbody, NULL); + TREE_SIDE_EFFECTS (bind) = 1; + SET_EXPR_LOCATION (bind, EXPR_LOCATION (tbody)); + TRANSACTION_EXPR_BODY (expr) = bind; + } + + push_gimplify_context (&gctx); + temp = voidify_wrapper_expr (*expr_p, NULL); + + g = gimplify_and_return_first (TRANSACTION_EXPR_BODY (expr), &body); + pop_gimplify_context (g); + + g = gimple_build_transaction (body, NULL); + if (TRANSACTION_EXPR_OUTER (expr)) + subcode = GTMA_IS_OUTER; + else if (TRANSACTION_EXPR_RELAXED (expr)) + subcode = GTMA_IS_RELAXED; + gimple_transaction_set_subcode (g, subcode); + + gimplify_seq_add_stmt (pre_p, g); + + if (temp) + { + *expr_p = temp; + return GS_OK; + } + + *expr_p = NULL_TREE; + return GS_ALL_DONE; +} + /* Convert the GENERIC expression tree *EXPR_P to GIMPLE. If the expression produces a value to be used as an operand inside a GIMPLE statement, the value will be stored back in *EXPR_P. This value will @@ -7251,6 +7306,10 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, ret = gimplify_omp_atomic (expr_p, pre_p); break; + case TRANSACTION_EXPR: + ret = gimplify_transaction (expr_p, pre_p); + break; + case TRUTH_AND_EXPR: case TRUTH_OR_EXPR: case TRUTH_XOR_EXPR: diff --git a/gcc/gsstruct.def b/gcc/gsstruct.def index 0b6531e6ca4..0e5727f2d98 100644 --- a/gcc/gsstruct.def +++ b/gcc/gsstruct.def @@ -38,6 +38,7 @@ DEFGSSTRUCT(GSS_CATCH, gimple_statement_catch, false) DEFGSSTRUCT(GSS_EH_FILTER, gimple_statement_eh_filter, false) DEFGSSTRUCT(GSS_EH_MNT, gimple_statement_eh_mnt, false) DEFGSSTRUCT(GSS_EH_CTRL, gimple_statement_eh_ctrl, false) +DEFGSSTRUCT(GSS_EH_ELSE, gimple_statement_eh_else, false) DEFGSSTRUCT(GSS_WCE, gimple_statement_wce, false) DEFGSSTRUCT(GSS_OMP, gimple_statement_omp, false) DEFGSSTRUCT(GSS_OMP_CRITICAL, gimple_statement_omp_critical, false) @@ -49,3 +50,4 @@ DEFGSSTRUCT(GSS_OMP_SINGLE, gimple_statement_omp_single, false) DEFGSSTRUCT(GSS_OMP_CONTINUE, gimple_statement_omp_continue, false) DEFGSSTRUCT(GSS_OMP_ATOMIC_LOAD, gimple_statement_omp_atomic_load, false) DEFGSSTRUCT(GSS_OMP_ATOMIC_STORE, gimple_statement_omp_atomic_store, false) +DEFGSSTRUCT(GSS_TRANSACTION, gimple_statement_transaction, false) diff --git a/gcc/gtm-builtins.def b/gcc/gtm-builtins.def new file mode 100644 index 00000000000..9fcbdb0cc36 --- /dev/null +++ b/gcc/gtm-builtins.def @@ -0,0 +1,208 @@ +DEF_TM_BUILTIN (BUILT_IN_TM_START, "_ITM_beginTransaction", + BT_FN_UINT_UINT, ATTR_TM_NOTHROW_LIST) + +DEF_TM_BUILTIN (BUILT_IN_TM_COMMIT, "_ITM_commitTransaction", + BT_FN_VOID, ATTR_TM_NOTHROW_LIST) +DEF_TM_BUILTIN (BUILT_IN_TM_COMMIT_EH, "_ITM_commitTransactionEH", + BT_FN_VOID_PTR, ATTR_TM_NOTHROW_LIST) +DEF_TM_BUILTIN (BUILT_IN_TM_ABORT, "_ITM_abortTransaction", + BT_FN_INT, ATTR_TM_NORETURN_NOTHROW_LIST) +DEF_TM_BUILTIN (BUILT_IN_TM_IRREVOCABLE, "_ITM_changeTransactionMode", + BT_FN_INT_INT, ATTR_TM_NOTHROW_LIST) + +DEF_TM_BUILTIN (BUILT_IN_TM_MEMCPY, "_ITM_memcpyRtWt", + BT_FN_PTR_PTR_CONST_PTR_SIZE, ATTR_TM_TMPURE_NOTHROW_LIST) +DEF_TM_BUILTIN (BUILT_IN_TM_MEMMOVE, "_ITM_memmoveRtWt", + BT_FN_PTR_PTR_CONST_PTR_SIZE, ATTR_TM_TMPURE_NOTHROW_LIST) +DEF_TM_BUILTIN (BUILT_IN_TM_MEMSET, "_ITM_memsetW", + BT_FN_PTR_PTR_INT_SIZE, ATTR_TM_TMPURE_NOTHROW_LIST) + +DEF_TM_BUILTIN (BUILT_IN_TM_GETTMCLONE_IRR, "_ITM_getTMCloneOrIrrevocable", + BT_FN_PTR_PTR, ATTR_TM_CONST_NOTHROW_LIST) +DEF_TM_BUILTIN (BUILT_IN_TM_GETTMCLONE_SAFE, "_ITM_getTMCloneSafe", + BT_FN_PTR_PTR, ATTR_TM_CONST_NOTHROW_LIST) + +/* Memory allocation builtins. */ +DEF_TM_BUILTIN (BUILT_IN_TM_MALLOC, "_ITM_malloc", + BT_FN_PTR_SIZE, ATTR_TMPURE_MALLOC_NOTHROW_LIST) +DEF_TM_BUILTIN (BUILT_IN_TM_CALLOC, "_ITM_calloc", + BT_FN_PTR_SIZE_SIZE, ATTR_TMPURE_MALLOC_NOTHROW_LIST) +DEF_TM_BUILTIN (BUILT_IN_TM_FREE, "_ITM_free", + BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LIST) + +/* Logging builtins. */ +DEF_TM_BUILTIN (BUILT_IN_TM_LOG_1, "_ITM_LU1", + BT_FN_VOID_VPTR, ATTR_TM_TMPURE_NOTHROW_LIST) +DEF_TM_BUILTIN (BUILT_IN_TM_LOG_2, "_ITM_LU2", + BT_FN_VOID_VPTR, ATTR_TM_TMPURE_NOTHROW_LIST) +DEF_TM_BUILTIN (BUILT_IN_TM_LOG_4, "_ITM_LU4", + BT_FN_VOID_VPTR, ATTR_TM_TMPURE_NOTHROW_LIST) +DEF_TM_BUILTIN (BUILT_IN_TM_LOG_8, "_ITM_LU8", + BT_FN_VOID_VPTR, ATTR_TM_TMPURE_NOTHROW_LIST) +DEF_TM_BUILTIN (BUILT_IN_TM_LOG_FLOAT, "_ITM_LF", + BT_FN_VOID_VPTR, ATTR_TM_TMPURE_NOTHROW_LIST) +DEF_TM_BUILTIN (BUILT_IN_TM_LOG_DOUBLE, "_ITM_LD", + BT_FN_VOID_VPTR, ATTR_TM_TMPURE_NOTHROW_LIST) +DEF_TM_BUILTIN (BUILT_IN_TM_LOG_LDOUBLE, "_ITM_LE", + BT_FN_VOID_VPTR, ATTR_TM_TMPURE_NOTHROW_LIST) +DEF_TM_BUILTIN (BUILT_IN_TM_LOG, "_ITM_LB", + BT_FN_VOID_VPTR_SIZE, ATTR_TM_TMPURE_NOTHROW_LIST) + +/* These stubs should get defined in the backend if applicable. */ +DEF_BUILTIN_STUB (BUILT_IN_TM_LOG_M64, "__builtin__ITM_LM64") +DEF_BUILTIN_STUB (BUILT_IN_TM_LOG_M128, "__builtin__ITM_LM128") +DEF_BUILTIN_STUB (BUILT_IN_TM_LOG_M256, "__builtin__ITM_LM256") + +/* Writes. + + Note: The writes must follow the following order: STORE, WAR, WAW. + The TM optimizations depend on this order. + + BUILT_IN_TM_STORE_1 must be the first builtin. + BUILTIN_TM_LOAD_STORE_P depends on this. */ +DEF_TM_BUILTIN (BUILT_IN_TM_STORE_1, "_ITM_WU1", + BT_FN_VOID_VPTR_I1, ATTR_TM_NOTHROW_LIST) +DEF_TM_BUILTIN (BUILT_IN_TM_STORE_WAR_1, "_ITM_WaRU1", + BT_FN_VOID_VPTR_I1, ATTR_TM_NOTHROW_LIST) +DEF_TM_BUILTIN (BUILT_IN_TM_STORE_WAW_1, "_ITM_WaWU1", + BT_FN_VOID_VPTR_I1, ATTR_TM_NOTHROW_LIST) + +DEF_TM_BUILTIN (BUILT_IN_TM_STORE_2, "_ITM_WU2", + BT_FN_VOID_VPTR_I2, ATTR_TM_NOTHROW_LIST) +DEF_TM_BUILTIN (BUILT_IN_TM_STORE_WAR_2, "_ITM_WaRU2", + BT_FN_VOID_VPTR_I2, ATTR_TM_NOTHROW_LIST) +DEF_TM_BUILTIN (BUILT_IN_TM_STORE_WAW_2, "_ITM_WaWU2", + BT_FN_VOID_VPTR_I2, ATTR_TM_NOTHROW_LIST) + +DEF_TM_BUILTIN (BUILT_IN_TM_STORE_4, "_ITM_WU4", + BT_FN_VOID_VPTR_I4, ATTR_TM_NOTHROW_LIST) +DEF_TM_BUILTIN (BUILT_IN_TM_STORE_WAR_4, "_ITM_WaRU4", + BT_FN_VOID_VPTR_I4, ATTR_TM_NOTHROW_LIST) +DEF_TM_BUILTIN (BUILT_IN_TM_STORE_WAW_4, "_ITM_WaWU4", + BT_FN_VOID_VPTR_I4, ATTR_TM_NOTHROW_LIST) + +DEF_TM_BUILTIN (BUILT_IN_TM_STORE_8, "_ITM_WU8", + BT_FN_VOID_VPTR_I8, ATTR_TM_NOTHROW_LIST) +DEF_TM_BUILTIN (BUILT_IN_TM_STORE_WAR_8, "_ITM_WaRU8", + BT_FN_VOID_VPTR_I8, ATTR_TM_NOTHROW_LIST) +DEF_TM_BUILTIN (BUILT_IN_TM_STORE_WAW_8, "_ITM_WaWU8", + BT_FN_VOID_VPTR_I8, ATTR_TM_NOTHROW_LIST) + +DEF_TM_BUILTIN (BUILT_IN_TM_STORE_FLOAT, "_ITM_WF", + BT_FN_VOID_VPTR_FLOAT, ATTR_TM_NOTHROW_LIST) +DEF_TM_BUILTIN (BUILT_IN_TM_STORE_WAR_FLOAT, "_ITM_WaRF", + BT_FN_VOID_VPTR_FLOAT, ATTR_TM_NOTHROW_LIST) +DEF_TM_BUILTIN (BUILT_IN_TM_STORE_WAW_FLOAT, "_ITM_WaWF", + BT_FN_VOID_VPTR_FLOAT, ATTR_TM_NOTHROW_LIST) + +DEF_TM_BUILTIN (BUILT_IN_TM_STORE_DOUBLE, "_ITM_WD", + BT_FN_VOID_VPTR_DOUBLE, ATTR_TM_NOTHROW_LIST) +DEF_TM_BUILTIN (BUILT_IN_TM_STORE_WAR_DOUBLE, "_ITM_WaRD", + BT_FN_VOID_VPTR_DOUBLE, ATTR_TM_NOTHROW_LIST) +DEF_TM_BUILTIN (BUILT_IN_TM_STORE_WAW_DOUBLE, "_ITM_WaWD", + BT_FN_VOID_VPTR_DOUBLE, ATTR_TM_NOTHROW_LIST) + +/* These stubs should get defined in the backend if applicable. */ +DEF_BUILTIN_STUB (BUILT_IN_TM_STORE_M64, "__builtin__ITM_WM64") +DEF_BUILTIN_STUB (BUILT_IN_TM_STORE_WAR_M64, "__builtin__ITM_WaRM64") +DEF_BUILTIN_STUB (BUILT_IN_TM_STORE_WAW_M64, "__builtin__ITM_WaWM64") +DEF_BUILTIN_STUB (BUILT_IN_TM_STORE_M128, "__builtin__ITM_WM128") +DEF_BUILTIN_STUB (BUILT_IN_TM_STORE_WAR_M128, "__builtin__ITM_WaRM128") +DEF_BUILTIN_STUB (BUILT_IN_TM_STORE_WAW_M128, "__builtin__ITM_WaWM128") +DEF_BUILTIN_STUB (BUILT_IN_TM_STORE_M256, "__builtin__ITM_WM256") +DEF_BUILTIN_STUB (BUILT_IN_TM_STORE_WAR_M256, "__builtin__ITM_WaRM256") +DEF_BUILTIN_STUB (BUILT_IN_TM_STORE_WAW_M256, "__builtin__ITM_WaWM256") + +DEF_TM_BUILTIN (BUILT_IN_TM_STORE_LDOUBLE, "_ITM_WE", + BT_FN_VOID_VPTR_LDOUBLE, ATTR_TM_NOTHROW_LIST) +DEF_TM_BUILTIN (BUILT_IN_TM_STORE_WAR_LDOUBLE, "_ITM_WaRE", + BT_FN_VOID_VPTR_LDOUBLE, ATTR_TM_NOTHROW_LIST) +DEF_TM_BUILTIN (BUILT_IN_TM_STORE_WAW_LDOUBLE, "_ITM_WaWE", + BT_FN_VOID_VPTR_LDOUBLE, ATTR_TM_NOTHROW_LIST) +/* Note: BUILT_IN_TM_STORE_WAW_LDOUBLE must be the last TM store. + BUILTIN_TM_STORE_P depends on this. */ + +/* Reads. + + Note: The reads must follow the following order: LOAD, RAR, RAW, RFW. + The TM optimizations depend on this order. */ +DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_1, "_ITM_RU1", + BT_FN_I1_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST) +DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_RAR_1, "_ITM_RaRU1", + BT_FN_I1_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST) +DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_RAW_1, "_ITM_RaWU1", + BT_FN_I1_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST) +DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_RFW_1, "_ITM_RfWU1", + BT_FN_I1_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST) + +DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_2, "_ITM_RU2", + BT_FN_I2_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST) +DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_RAR_2, "_ITM_RaRU2", + BT_FN_I2_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST) +DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_RAW_2, "_ITM_RaWU2", + BT_FN_I2_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST) +DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_RFW_2, "_ITM_RfWU2", + BT_FN_I2_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST) + +DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_4, "_ITM_RU4", + BT_FN_I4_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST) +DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_RAR_4, "_ITM_RaRU4", + BT_FN_I4_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST) +DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_RAW_4, "_ITM_RaWU4", + BT_FN_I4_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST) +DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_RFW_4, "_ITM_RfWU4", + BT_FN_I4_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST) + +DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_8, "_ITM_RU8", + BT_FN_I8_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST) +DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_RAR_8, "_ITM_RaRU8", + BT_FN_I8_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST) +DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_RAW_8, "_ITM_RaWU8", + BT_FN_I8_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST) +DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_RFW_8, "_ITM_RfWU8", + BT_FN_I8_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST) + +DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_FLOAT, "_ITM_RF", + BT_FN_FLOAT_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST) +DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_RAR_FLOAT, "_ITM_RaRF", + BT_FN_FLOAT_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST) +DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_RAW_FLOAT, "_ITM_RaWF", + BT_FN_FLOAT_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST) +DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_RFW_FLOAT, "_ITM_RfWF", + BT_FN_FLOAT_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST) + +DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_DOUBLE, "_ITM_RD", + BT_FN_DOUBLE_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST) +DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_RAR_DOUBLE, "_ITM_RaRD", + BT_FN_FLOAT_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST) +DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_RAW_DOUBLE, "_ITM_RaWD", + BT_FN_FLOAT_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST) +DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_RFW_DOUBLE, "_ITM_RfWD", + BT_FN_FLOAT_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST) + +/* These stubs should get defined in the backend if applicable. */ +DEF_BUILTIN_STUB (BUILT_IN_TM_LOAD_M64, "__builtin__ITM_RM64") +DEF_BUILTIN_STUB (BUILT_IN_TM_LOAD_RAR_M64, "__builtin__ITM_RaRM64") +DEF_BUILTIN_STUB (BUILT_IN_TM_LOAD_RAW_M64, "__builtin__ITM_RaRM64") +DEF_BUILTIN_STUB (BUILT_IN_TM_LOAD_RFW_M64, "__builtin__ITM_RfWM64") +DEF_BUILTIN_STUB (BUILT_IN_TM_LOAD_M128, "__builtin__ITM_RM128") +DEF_BUILTIN_STUB (BUILT_IN_TM_LOAD_RAR_M128, "__builtin__ITM_RaRM128") +DEF_BUILTIN_STUB (BUILT_IN_TM_LOAD_RAW_M128, "__builtin__ITM_RaRM128") +DEF_BUILTIN_STUB (BUILT_IN_TM_LOAD_RFW_M128, "__builtin__ITM_RfWM128") +DEF_BUILTIN_STUB (BUILT_IN_TM_LOAD_M256, "__builtin__ITM_RM256") +DEF_BUILTIN_STUB (BUILT_IN_TM_LOAD_RAR_M256, "__builtin__ITM_RaRM256") +DEF_BUILTIN_STUB (BUILT_IN_TM_LOAD_RAW_M256, "__builtin__ITM_RaRM256") +DEF_BUILTIN_STUB (BUILT_IN_TM_LOAD_RFW_M256, "__builtin__ITM_RfWM256") + +DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_LDOUBLE, "_ITM_RE", + BT_FN_LDOUBLE_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST) +DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_RAR_LDOUBLE, "_ITM_RaRE", + BT_FN_LDOUBLE_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST) +DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_RAW_LDOUBLE, "_ITM_RaWE", + BT_FN_LDOUBLE_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST) +DEF_TM_BUILTIN (BUILT_IN_TM_LOAD_RFW_LDOUBLE, "_ITM_RfWE", + BT_FN_LDOUBLE_VPTR, ATTR_TM_PURE_TMPURE_NOTHROW_LIST) + +/* Note: BUILT_IN_TM_LOAD_RFW_LDOUBLE must be the last TM load as well + as the last builtin. BUILTIN_TM_LOAD_STORE_P and BUILTIN_TM_LOAD_P + depend on this. */ diff --git a/gcc/ipa-inline.c b/gcc/ipa-inline.c index 31c88e501e7..3dadf8d12d7 100644 --- a/gcc/ipa-inline.c +++ b/gcc/ipa-inline.c @@ -284,6 +284,14 @@ can_inline_edge_p (struct cgraph_edge *e, bool report) e->inline_failed = CIF_EH_PERSONALITY; inlinable = false; } + /* TM pure functions should not get inlined if the outer function is + a TM safe function. */ + else if (is_tm_pure (callee->decl) + && is_tm_safe (e->caller->decl)) + { + e->inline_failed = CIF_UNSPECIFIED; + inlinable = false; + } /* Don't inline if the callee can throw non-call exceptions but the caller cannot. FIXME: this is obviously wrong for LTO where STRUCT_FUNCTION is missing. diff --git a/gcc/omp-low.c b/gcc/omp-low.c index 81459577937..dc61c0bdf54 100644 --- a/gcc/omp-low.c +++ b/gcc/omp-low.c @@ -139,6 +139,7 @@ static tree scan_omp_1_op (tree *, int *, void *); case GIMPLE_TRY: \ case GIMPLE_CATCH: \ case GIMPLE_EH_FILTER: \ + case GIMPLE_TRANSACTION: \ /* The sub-statements for these should be walked. */ \ *handled_ops_p = false; \ break; diff --git a/gcc/opts.c b/gcc/opts.c index 3153fe50274..9fdb22631d0 100644 --- a/gcc/opts.c +++ b/gcc/opts.c @@ -784,6 +784,8 @@ finish_options (struct gcc_options *opts, struct gcc_options *opts_set, #endif if (!opts->x_flag_fat_lto_objects && !HAVE_LTO_PLUGIN) error_at (loc, "-fno-fat-lto-objects are supported only with linker plugin."); + if (opts->x_flag_tm) + error_at (loc, "LTO is currently not supported with transactional memory"); } if ((opts->x_flag_lto_partition_balanced != 0) + (opts->x_flag_lto_partition_1to1 != 0) + (opts->x_flag_lto_partition_none != 0) >= 1) diff --git a/gcc/output.h b/gcc/output.h index 661b623807c..e47eddf2735 100644 --- a/gcc/output.h +++ b/gcc/output.h @@ -606,6 +606,10 @@ extern bool unlikely_text_section_p (section *); extern void switch_to_section (section *); extern void output_section_asm_op (const void *); +extern void record_tm_clone_pair (tree, tree); +extern void finish_tm_clone_pairs (void); +extern tree get_tm_clone_pair (tree); + extern void default_asm_output_source_filename (FILE *, const char *); extern void output_file_directive (FILE *, const char *); diff --git a/gcc/params.def b/gcc/params.def index a7ae0918579..239b684b5fc 100644 --- a/gcc/params.def +++ b/gcc/params.def @@ -872,6 +872,13 @@ DEFPARAM (PARAM_IPA_SRA_PTR_GROWTH_FACTOR, "a pointer to an aggregate with", 2, 0, 0) +DEFPARAM (PARAM_TM_MAX_AGGREGATE_SIZE, + "tm-max-aggregate-size", + "Size in bytes after which thread-local aggregates should be " + "instrumented with the logging functions instead of save/restore " + "pairs", + 9, 0, 0) + DEFPARAM (PARAM_IPA_CP_VALUE_LIST_SIZE, "ipa-cp-value-list-size", "Maximum size of a list of values associated with each parameter for " diff --git a/gcc/passes.c b/gcc/passes.c index 887007f6dde..a3512419ee2 100644 --- a/gcc/passes.c +++ b/gcc/passes.c @@ -1174,9 +1174,11 @@ init_optimization_passes (void) p = &all_lowering_passes; NEXT_PASS (pass_warn_unused_result); NEXT_PASS (pass_diagnose_omp_blocks); + NEXT_PASS (pass_diagnose_tm_blocks); NEXT_PASS (pass_mudflap_1); NEXT_PASS (pass_lower_omp); NEXT_PASS (pass_lower_cf); + NEXT_PASS (pass_lower_tm); NEXT_PASS (pass_refactor_eh); NEXT_PASS (pass_lower_eh); NEXT_PASS (pass_build_cfg); @@ -1241,6 +1243,7 @@ init_optimization_passes (void) } NEXT_PASS (pass_ipa_increase_alignment); NEXT_PASS (pass_ipa_matrix_reorg); + NEXT_PASS (pass_ipa_tm); NEXT_PASS (pass_ipa_lower_emutls); *p = NULL; @@ -1400,6 +1403,13 @@ init_optimization_passes (void) NEXT_PASS (pass_uncprop); NEXT_PASS (pass_local_pure_const); } + NEXT_PASS (pass_tm_init); + { + struct opt_pass **p = &pass_tm_init.pass.sub; + NEXT_PASS (pass_tm_mark); + NEXT_PASS (pass_tm_memopt); + NEXT_PASS (pass_tm_edges); + } NEXT_PASS (pass_lower_complex_O0); NEXT_PASS (pass_cleanup_eh); NEXT_PASS (pass_lower_resx); diff --git a/gcc/print-tree.c b/gcc/print-tree.c index 1a1e33f1342..7fb71d0b475 100644 --- a/gcc/print-tree.c +++ b/gcc/print-tree.c @@ -424,6 +424,8 @@ print_node (FILE *file, const char *prefix, tree node, int indent) fputs (" built-in", file); if (code == FUNCTION_DECL && DECL_STATIC_CHAIN (node)) fputs (" static-chain", file); + if (TREE_CODE (node) == FUNCTION_DECL && decl_is_tm_clone (node)) + fputs (" tm-clone", file); if (code == FIELD_DECL && DECL_PACKED (node)) fputs (" packed", file); diff --git a/gcc/recog.c b/gcc/recog.c index d3ecb73c4e8..ae05204eee5 100644 --- a/gcc/recog.c +++ b/gcc/recog.c @@ -3287,6 +3287,7 @@ peep2_attempt (basic_block bb, rtx insn, int match_len, rtx attempt) { case REG_NORETURN: case REG_SETJMP: + case REG_TM: add_reg_note (new_insn, REG_NOTE_KIND (note), XEXP (note, 0)); break; diff --git a/gcc/reg-notes.def b/gcc/reg-notes.def index d103afee018..f2f097385a6 100644 --- a/gcc/reg-notes.def +++ b/gcc/reg-notes.def @@ -203,6 +203,11 @@ REG_NOTE (CROSSING_JUMP) functions that can return twice. */ REG_NOTE (SETJMP) +/* This kind of note is generated at each transactional memory + builtin, to indicate we need to generate transaction restart + edges for this insn. */ +REG_NOTE (TM) + /* Indicates the cumulative offset of the stack pointer accounting for pushed arguments. This will only be generated when ACCUMULATE_OUTGOING_ARGS is false. */ diff --git a/gcc/rtlanal.c b/gcc/rtlanal.c index 54d9eb1ef67..7c4a49bef09 100644 --- a/gcc/rtlanal.c +++ b/gcc/rtlanal.c @@ -1918,6 +1918,7 @@ alloc_reg_note (enum reg_note kind, rtx datum, rtx list) case REG_CC_USER: case REG_LABEL_TARGET: case REG_LABEL_OPERAND: + case REG_TM: /* These types of register notes use an INSN_LIST rather than an EXPR_LIST, so that copying is done right and dumps look better. */ diff --git a/gcc/target.def b/gcc/target.def index a83088d2900..62bd06e976f 100644 --- a/gcc/target.def +++ b/gcc/target.def @@ -1003,6 +1003,24 @@ DEFHOOK (enum machine_mode mode, const_tree type, int misalignment, bool is_packed), default_builtin_support_vector_misalignment) +/* Return the builtin decl needed to load a vector of TYPE. */ +DEFHOOK +(builtin_tm_load, + "This hook should return the built-in decl needed to load a vector of the " + "given type within a transaction.", + tree, + (tree), + default_builtin_tm_load_store) + +/* Return the builtin decl needed to store a vector of TYPE. */ +DEFHOOK +(builtin_tm_store, + "This hook should return the built-in decl needed to store a vector of the " + "given type within a transaction.", + tree, + (tree), + default_builtin_tm_load_store) + /* Returns the preferred mode for SIMD operations for the specified scalar mode. */ DEFHOOK diff --git a/gcc/targhooks.c b/gcc/targhooks.c index 81fd12f7b78..2b4fd27bdfa 100644 --- a/gcc/targhooks.c +++ b/gcc/targhooks.c @@ -1214,6 +1214,12 @@ default_have_conditional_execution (void) #endif } +tree +default_builtin_tm_load_store (tree ARG_UNUSED (type)) +{ + return NULL_TREE; +} + /* Compute cost of moving registers to/from memory. */ int diff --git a/gcc/targhooks.h b/gcc/targhooks.h index f19fb506bf5..861811543f8 100644 --- a/gcc/targhooks.h +++ b/gcc/targhooks.h @@ -152,6 +152,9 @@ extern bool default_addr_space_subset_p (addr_space_t, addr_space_t); extern rtx default_addr_space_convert (rtx, tree, tree); extern unsigned int default_case_values_threshold (void); extern bool default_have_conditional_execution (void); + +extern tree default_builtin_tm_load_store (tree); + extern int default_memory_move_cost (enum machine_mode, reg_class_t, bool); extern int default_register_move_cost (enum machine_mode, reg_class_t, reg_class_t); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index a62b11cbebf..c095293b347 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,14 @@ +2011-11-07 Richard Henderson <rth@redhat.com> + Aldy Hernandez <aldyh@redhat.com> + Torvald Riegel <triegel@redhat.com> + + Merged from transactional-memory. + + * g++.dg/dg.exp: Run transactional memory tests. + * g++.dg/tm: New directory with new tests. + * gcc.dg/tm: New directory with new tests. + * c-c++-common/tm: New directory with new tests. + 2011-11-08 Dodji Seketeli <dodji@redhat.com> Fix context handling of alias-declaration diff --git a/gcc/testsuite/c-c++-common/tm/20100127.c b/gcc/testsuite/c-c++-common/tm/20100127.c new file mode 100644 index 00000000000..c25336d682a --- /dev/null +++ b/gcc/testsuite/c-c++-common/tm/20100127.c @@ -0,0 +1,36 @@ +/* { dg-do compile } */ +/* { dg-options "-fgnu-tm -O -fdump-tree-tmmark" } */ + +/* Test that `nontrxn' doesn't end up inside the transaction. */ + +typedef struct node { + int * val; + struct node *next; +} node_t; + +node_t *next; +int nontrxn1, nontrxn; + +static int set_remove(int * val) +{ + int result; + int * v; + __transaction_relaxed { + v = next->val; + result = (v == val); + if (result) + result = 2; + } + return result; +} + +void test(void *data) +{ + extern void bark(void); + if (set_remove(0)) + bark(); + nontrxn = 99; /* Should be outside transaction. */ +} + +/* { dg-final { scan-tree-dump-times "_ITM_W.*nontrxn" 0 "tmmark" } } */ +/* { dg-final { cleanup-tree-dump "tmmark" } } */ diff --git a/gcc/testsuite/c-c++-common/tm/abort-1.c b/gcc/testsuite/c-c++-common/tm/abort-1.c new file mode 100644 index 00000000000..90830f41cf3 --- /dev/null +++ b/gcc/testsuite/c-c++-common/tm/abort-1.c @@ -0,0 +1,6 @@ +/* { dg-do compile } */ + +void f(void) +{ + __transaction_cancel; /* { dg-error "without transactional" } */ +} diff --git a/gcc/testsuite/c-c++-common/tm/abort-2.c b/gcc/testsuite/c-c++-common/tm/abort-2.c new file mode 100644 index 00000000000..727c63432ac --- /dev/null +++ b/gcc/testsuite/c-c++-common/tm/abort-2.c @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-options "-fgnu-tm" } */ + +int g; +void f(void) +{ + __transaction_atomic { + if (g == 0) + __transaction_cancel; + } +} diff --git a/gcc/testsuite/c-c++-common/tm/abort-3.c b/gcc/testsuite/c-c++-common/tm/abort-3.c new file mode 100644 index 00000000000..f2cf5b5dc2a --- /dev/null +++ b/gcc/testsuite/c-c++-common/tm/abort-3.c @@ -0,0 +1,8 @@ +/* { dg-do compile } */ + +void f(void) +{ + __transaction_atomic { /* { dg-error "__transaction_atomic. without trans" } */ + __transaction_cancel; /* { dg-error "_cancel. without trans" } */ + } +} diff --git a/gcc/testsuite/c-c++-common/tm/atomic-1.c b/gcc/testsuite/c-c++-common/tm/atomic-1.c new file mode 100644 index 00000000000..e301f1f48cf --- /dev/null +++ b/gcc/testsuite/c-c++-common/tm/atomic-1.c @@ -0,0 +1,9 @@ +/* { dg-do compile } */ + +int g; +void f(void) +{ + __transaction_atomic { /* { dg-error "without transactional memory" } */ + g++; + } +} diff --git a/gcc/testsuite/c-c++-common/tm/atomic-2.c b/gcc/testsuite/c-c++-common/tm/atomic-2.c new file mode 100644 index 00000000000..f232766240a --- /dev/null +++ b/gcc/testsuite/c-c++-common/tm/atomic-2.c @@ -0,0 +1,10 @@ +/* { dg-do compile } */ +/* { dg-options "-fgnu-tm" } */ + +int g; +void f(void) +{ + __transaction_atomic { + g++; + } +} diff --git a/gcc/testsuite/c-c++-common/tm/attrib-1.c b/gcc/testsuite/c-c++-common/tm/attrib-1.c new file mode 100644 index 00000000000..536aeb33fdd --- /dev/null +++ b/gcc/testsuite/c-c++-common/tm/attrib-1.c @@ -0,0 +1,25 @@ +/* { dg-do compile } */ +/* { dg-options "-fgnu-tm" } */ + +#define TC __attribute__((transaction_callable)) +#define TU __attribute__((transaction_unsafe)) +#define TP __attribute__((transaction_pure)) +#define TS __attribute__((transaction_safe)) +extern void f1(void) TC; +extern void f2(void) TU; +extern void f3(void) TP; +extern void f4(void) TS; + +extern void g1(void) TC TS; /* { dg-error "previously declared" } */ + +extern int v1 TP; /* { dg-warning "ignored" } */ + +typedef void t1(void) TC; +typedef void (*t2)(void) TC; +typedef int t3 TC; /* { dg-warning "ignored" } */ + +typedef void u0(void); +typedef u0 u1 TC; +typedef u1 u2 TP; /* { dg-error "previously declared" } */ +typedef u0 *u3 TS; +typedef u3 u4 TU; /* { dg-error "previously declared" } */ diff --git a/gcc/testsuite/c-c++-common/tm/cancel-1.c b/gcc/testsuite/c-c++-common/tm/cancel-1.c new file mode 100644 index 00000000000..6d60f2648c4 --- /dev/null +++ b/gcc/testsuite/c-c++-common/tm/cancel-1.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-options "-fgnu-tm" } */ + +void unsafe(void) __attribute__((transaction_unsafe)); + +void +f(void) +{ + int a; + __transaction_atomic { + a = 1; + __transaction_atomic { + __transaction_cancel; + } + } + unsafe(); +} diff --git a/gcc/testsuite/c-c++-common/tm/freq.c b/gcc/testsuite/c-c++-common/tm/freq.c new file mode 100644 index 00000000000..31df167fae9 --- /dev/null +++ b/gcc/testsuite/c-c++-common/tm/freq.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-options "-fgnu-tm -O" } */ + +extern __attribute__((transaction_safe)) void TMreleaseNode (); + +int global; + +__attribute__((transaction_safe)) +void +TMrbtree_insert () +{ + if (global) + TMreleaseNode(); +} diff --git a/gcc/testsuite/c-c++-common/tm/inline-asm-2.c b/gcc/testsuite/c-c++-common/tm/inline-asm-2.c new file mode 100644 index 00000000000..7d429fbbc85 --- /dev/null +++ b/gcc/testsuite/c-c++-common/tm/inline-asm-2.c @@ -0,0 +1,8 @@ +// { dg-do compile } +// { dg-options "-fgnu-tm" } + +__attribute__((transaction_callable)) +void func() +{ + __asm__ (""); +} diff --git a/gcc/testsuite/c-c++-common/tm/inline-asm.c b/gcc/testsuite/c-c++-common/tm/inline-asm.c new file mode 100644 index 00000000000..eefd347dc8f --- /dev/null +++ b/gcc/testsuite/c-c++-common/tm/inline-asm.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-options "-fgnu-tm -O1" } */ + +static inline void +inline_death () +{ + __asm__ (""); /* { dg-error "asm not allowed" } */ +} + +void +tranfunction () +{ + __transaction_atomic + { + inline_death (); + } +} diff --git a/gcc/testsuite/c-c++-common/tm/ipa-1.c b/gcc/testsuite/c-c++-common/tm/ipa-1.c new file mode 100644 index 00000000000..961f7fe79c0 --- /dev/null +++ b/gcc/testsuite/c-c++-common/tm/ipa-1.c @@ -0,0 +1,23 @@ +/* { dg-do compile } */ +/* { dg-options "-fgnu-tm -O -fdump-ipa-tmipa" } */ + +int val, george; + +extern void func(); + +int set_remove(void) +{ + int result = 8; + __transaction_atomic { + result = george; + if (val) + goto out; + } + out: + func(); + return result; +} + + +/* { dg-final { scan-ipa-dump-not "getTMCloneOrIrrevocable" "tmipa" } } */ +/* { dg-final { cleanup-ipa-dump "tmipa" } } */ diff --git a/gcc/testsuite/c-c++-common/tm/malloc.c b/gcc/testsuite/c-c++-common/tm/malloc.c new file mode 100644 index 00000000000..de7a766e36c --- /dev/null +++ b/gcc/testsuite/c-c++-common/tm/malloc.c @@ -0,0 +1,24 @@ +/* { dg-do compile } */ +/* { dg-options "-fgnu-tm -fdump-tree-tmmark" } */ + +#include <stdlib.h> + +char *z; + +void foobar(void) +{ + char *p, *q; + __transaction_atomic { + p = (char *)malloc(123); + q = (char *)calloc(555,1); + free(q); + free(p); + } + z = (char *)malloc (666); +} + +/* { dg-final { scan-tree-dump-times " malloc .666" 1 "tmmark" } } */ +/* { dg-final { scan-tree-dump-times "__builtin__ITM_malloc" 1 "tmmark" } } */ +/* { dg-final { scan-tree-dump-times "__builtin__ITM_calloc" 1 "tmmark" } } */ +/* { dg-final { scan-tree-dump-times "__builtin__ITM_free" 2 "tmmark" } } */ +/* { dg-final { cleanup-tree-dump "tmmark" } } */ diff --git a/gcc/testsuite/c-c++-common/tm/memcpy-1.c b/gcc/testsuite/c-c++-common/tm/memcpy-1.c new file mode 100644 index 00000000000..fa841b26164 --- /dev/null +++ b/gcc/testsuite/c-c++-common/tm/memcpy-1.c @@ -0,0 +1,9 @@ +/* { dg-do compile } */ +/* { dg-options "-fgnu-tm" } */ +#include <string.h> + +__attribute__((transaction_safe)) +void *wmemcpy(void *dest, const void *src, size_t n) +{ + return memcpy(dest, src, n); +} diff --git a/gcc/testsuite/c-c++-common/tm/omp.c b/gcc/testsuite/c-c++-common/tm/omp.c new file mode 100644 index 00000000000..b9fcc765efc --- /dev/null +++ b/gcc/testsuite/c-c++-common/tm/omp.c @@ -0,0 +1,22 @@ +/* { dg-do compile } */ +/* { dg-options "-fgnu-tm -fopenmp" } */ + +__attribute__ ((transaction_pure)) +unsigned long rdtsc(); + +typedef struct ENTER_EXIT_TIMES +{ + unsigned long enter; +} times_t; + +void ParClassify() +{ + void * Parent; +#pragma omp parallel private(Parent) + { + times_t inside; + __transaction_atomic { + inside.enter = rdtsc(); + } + } +} diff --git a/gcc/testsuite/c-c++-common/tm/outer-1.c b/gcc/testsuite/c-c++-common/tm/outer-1.c new file mode 100644 index 00000000000..7dbf2e8310a --- /dev/null +++ b/gcc/testsuite/c-c++-common/tm/outer-1.c @@ -0,0 +1,31 @@ +/* { dg-do compile } */ +/* { dg-options "-fgnu-tm" } */ + +void mco(void) __attribute__((transaction_may_cancel_outer)); + +void +f(void) +{ + mco(); /* { dg-error "" } */ + __transaction_atomic { + mco(); /* { dg-error "" } */ + } + __transaction_relaxed { + mco(); /* { dg-error "" } */ + } + __transaction_atomic [[outer]] { + mco(); + } +} + +void __attribute__((transaction_may_cancel_outer)) +g(void) +{ + mco(); + __transaction_atomic { + mco(); + } + __transaction_atomic [[outer]] { /* { dg-error "" } */ + mco(); + } +} diff --git a/gcc/testsuite/c-c++-common/tm/safe-1.c b/gcc/testsuite/c-c++-common/tm/safe-1.c new file mode 100644 index 00000000000..b2a43530575 --- /dev/null +++ b/gcc/testsuite/c-c++-common/tm/safe-1.c @@ -0,0 +1,69 @@ +/* { dg-do compile } */ +/* { dg-options "-fgnu-tm" } */ + +void ts(void) __attribute__((transaction_safe)); +void tp(void) __attribute__((transaction_pure)); +void tc(void) __attribute__((transaction_callable)); +void ti(void) __attribute__((transaction_unsafe)); +void tm(void) __attribute__((transaction_may_cancel_outer)); +void tu(void); +int fc(int) __attribute__((const)); + +typedef void (*Fs) (void) __attribute__((transaction_safe)); +typedef void (*Fc) (void) __attribute__((transaction_callable)); +typedef void (*Fi) (void) __attribute__((transaction_unsafe)); +typedef void (*Fm) (void) __attribute__((transaction_may_cancel_outer)); +extern Fs ps; +extern Fc pc; +extern Fi pi; +extern Fm pm; +extern void (*pu)(void); + +int __attribute__((transaction_safe)) +foo(void) +{ + int i; + + ts(); + tp(); + tc(); /* { dg-error "unsafe function call" } */ + ti(); /* { dg-error "unsafe function call" } */ + + /* ??? Direct function calls without markups are handled later + than pass_diagnose_tm_blocks, which means we'll exit with + errors before getting there. This test moved to safe-3.c. */ + /* tu(); */ + + (*ps)(); + (*pc)(); /* { dg-error "unsafe function call" } */ + (*pi)(); /* { dg-error "unsafe function call" } */ + (*pu)(); /* { dg-error "unsafe function call" } */ + + asm(""); /* { dg-error "asm not allowed" } */ + asm("" : "=g"(i)); /* { dg-error "asm not allowed" } */ + + return fc(i); +} + +int __attribute__((transaction_may_cancel_outer)) +bar(void) +{ + int i; + + ts(); + tp(); + tc(); /* { dg-error "unsafe function call" } */ + ti(); /* { dg-error "unsafe function call" } */ + tm(); + + (*ps)(); + (*pc)(); /* { dg-error "unsafe function call" } */ + (*pi)(); /* { dg-error "unsafe function call" } */ + (*pm)(); + (*pu)(); /* { dg-error "unsafe function call" } */ + + asm(""); /* { dg-error "asm not allowed" } */ + asm("" : "=g"(i)); /* { dg-error "asm not allowed" } */ + + return fc(i); +} diff --git a/gcc/testsuite/c-c++-common/tm/safe-2.c b/gcc/testsuite/c-c++-common/tm/safe-2.c new file mode 100644 index 00000000000..a6729ba428b --- /dev/null +++ b/gcc/testsuite/c-c++-common/tm/safe-2.c @@ -0,0 +1,43 @@ +/* { dg-do compile } */ +/* { dg-options "-fgnu-tm" } */ + +void mco(void) __attribute__((transaction_may_cancel_outer)); + +void +f(void) +{ + mco(); /* { dg-error "" } */ + __transaction_atomic { + mco(); /* { dg-error "" } */ + } + __transaction_relaxed { + mco(); /* { dg-error "" } */ + } + __transaction_atomic [[outer]] { + mco(); + } + __transaction_atomic [[outer]] { + __transaction_atomic { + __transaction_atomic { + __transaction_atomic { + mco(); + } + } + } + } +} + +void __attribute__((transaction_may_cancel_outer)) +g(void) +{ + mco(); + __transaction_atomic { + __transaction_atomic { + __transaction_atomic { + __transaction_atomic { + mco(); + } + } + } + } +} diff --git a/gcc/testsuite/c-c++-common/tm/safe-3.c b/gcc/testsuite/c-c++-common/tm/safe-3.c new file mode 100644 index 00000000000..8a883db5ef0 --- /dev/null +++ b/gcc/testsuite/c-c++-common/tm/safe-3.c @@ -0,0 +1,48 @@ +/* { dg-do compile } */ +/* { dg-options "-fgnu-tm" } */ + +void f_extern (void); +void f_first (void); +void f_later (void); + +extern int x; + +void f_first (void) { x++; } + +void __attribute__((transaction_safe)) +test_safe (void) +{ + f_extern (); /* { dg-error "unsafe function call" } */ + f_first (); + f_later (); +} + +void __attribute__((transaction_may_cancel_outer)) +test_mco (void) +{ + f_extern (); /* { dg-error "unsafe function call" } */ + f_first (); + f_later (); +} + +void +test_atomic (void) +{ + __transaction_atomic { + f_extern (); /* { dg-error "unsafe function call" } */ + f_first (); + f_later (); + } + __transaction_relaxed { + f_extern (); + f_first (); + f_later (); + } + __transaction_atomic [[outer]] { + f_extern (); /* { dg-error "unsafe function call" } */ + f_first (); + f_later (); + } +} + +void f_later () { f_first(); test_safe(); } diff --git a/gcc/testsuite/c-c++-common/tm/trxn-expr-2.c b/gcc/testsuite/c-c++-common/tm/trxn-expr-2.c new file mode 100644 index 00000000000..0ef6526db7b --- /dev/null +++ b/gcc/testsuite/c-c++-common/tm/trxn-expr-2.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* Make sure that we don't just crash without -fgnu-tm enabled. */ +/* { dg-options "" } */ + +int x; + +int foo(void) +{ + return __transaction_atomic (x + 1); /* { dg-error "" } */ +} + +int bar(void) +{ + return __transaction_relaxed (x + 1); /* { dg-error "" } */ +} diff --git a/gcc/testsuite/c-c++-common/tm/trxn-expr.c b/gcc/testsuite/c-c++-common/tm/trxn-expr.c new file mode 100644 index 00000000000..53d4677e3e6 --- /dev/null +++ b/gcc/testsuite/c-c++-common/tm/trxn-expr.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-options "-fgnu-tm -fdump-tree-tmmark" } */ + +int y, x, york; + +void foobar(void) +{ + x = y + __transaction_atomic (york); +} + +/* { dg-final { scan-tree-dump-times "_ITM_RU.*york" 1 "tmmark" } } */ +/* { dg-final { scan-tree-dump-times "_ITM_RU" 1 "tmmark" } } */ +/* { dg-final { cleanup-tree-dump "tmmark" } } */ diff --git a/gcc/testsuite/c-c++-common/tm/wrap-1.c b/gcc/testsuite/c-c++-common/tm/wrap-1.c new file mode 100644 index 00000000000..04b5b6f0dcb --- /dev/null +++ b/gcc/testsuite/c-c++-common/tm/wrap-1.c @@ -0,0 +1,10 @@ +/* { dg-do compile } */ +/* { dg-options "-fgnu-tm -fdump-tree-optimized" } */ + +void orig(void); +void xyzzy(void) __attribute__((transaction_wrap (orig))); + +void foo() { __transaction_relaxed { orig (); } } + +/* { dg-final { scan-tree-dump-times "xyzzy" 1 "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/g++.dg/dg.exp b/gcc/testsuite/g++.dg/dg.exp index cee19d68029..ad1f7e23700 100644 --- a/gcc/testsuite/g++.dg/dg.exp +++ b/gcc/testsuite/g++.dg/dg.exp @@ -47,6 +47,7 @@ set tests [prune $tests $srcdir/$subdir/gomp/*] set tests [prune $tests $srcdir/$subdir/tree-prof/*] set tests [prune $tests $srcdir/$subdir/torture/*] set tests [prune $tests $srcdir/$subdir/graphite/*] +set tests [prune $tests $srcdir/$subdir/tm/*] set tests [prune $tests $srcdir/$subdir/guality/*] set tests [prune $tests $srcdir/$subdir/simulate-thread/*] diff --git a/gcc/testsuite/g++.dg/tm/20100429.C b/gcc/testsuite/g++.dg/tm/20100429.C new file mode 100644 index 00000000000..087ce32b2a6 --- /dev/null +++ b/gcc/testsuite/g++.dg/tm/20100429.C @@ -0,0 +1,15 @@ +// { dg-do compile } +// { dg-options "-fgnu-tm" } + +int foo(int a); +int foo(float a); +int +bar(int a) +{ + int r; + __transaction_atomic + { + r = foo(a); // { dg-error "unsafe function call 'int foo\\(int\\)'" } + } + return r; +} diff --git a/gcc/testsuite/g++.dg/tm/20100727.C b/gcc/testsuite/g++.dg/tm/20100727.C new file mode 100644 index 00000000000..bda2df0607c --- /dev/null +++ b/gcc/testsuite/g++.dg/tm/20100727.C @@ -0,0 +1,796 @@ +// { dg-do compile } +// { dg-options "-fgnu-tm" } + +typedef long int ptrdiff_t; +typedef long unsigned int size_t; +namespace std __attribute__ ((__visibility__ ("default"))) +{ + using::ptrdiff_t; + using::size_t; +} + +namespace std __attribute__ ((__visibility__ ("default"))) +{ + struct input_iterator_tag + { + }; + struct output_iterator_tag + { + }; + struct forward_iterator_tag:public input_iterator_tag + { + }; + struct bidirectional_iterator_tag:public forward_iterator_tag + { + }; + struct random_access_iterator_tag:public bidirectional_iterator_tag + { + }; + template < typename _Category, typename _Tp, typename _Distance = + ptrdiff_t, typename _Pointer = _Tp *, typename _Reference = + _Tp & >struct iterator + { + typedef _Category iterator_category; + typedef _Tp value_type; + typedef _Distance difference_type; + typedef _Pointer pointer; + typedef _Reference reference; + }; + template < typename _Iterator > struct iterator_traits + { + typedef typename _Iterator::iterator_category iterator_category; + typedef typename _Iterator::value_type value_type; + typedef typename _Iterator::difference_type difference_type; + typedef typename _Iterator::pointer pointer; + typedef typename _Iterator::reference reference; + }; + template < typename _Tp > struct iterator_traits <_Tp * > + { + typedef random_access_iterator_tag iterator_category; + typedef _Tp value_type; + typedef ptrdiff_t difference_type; + typedef _Tp *pointer; + typedef _Tp & reference; + }; + template < typename _Tp > struct iterator_traits <const _Tp *> + { + typedef random_access_iterator_tag iterator_category; + typedef _Tp value_type; + typedef ptrdiff_t difference_type; + typedef const _Tp *pointer; + typedef const _Tp & reference; + }; + template < typename _Iter > inline typename iterator_traits < + _Iter >::iterator_category __iterator_category (const _Iter &) + { + return typename iterator_traits < _Iter >::iterator_category (); + } +} + +namespace std __attribute__ ((__visibility__ ("default"))) +{ +template < typename _Iterator > class reverse_iterator:public iterator < typename iterator_traits < _Iterator >::iterator_category, + typename iterator_traits < _Iterator >::value_type, + typename iterator_traits < _Iterator >::difference_type, + typename iterator_traits < _Iterator >::pointer, + typename iterator_traits < _Iterator >::reference > + { + protected:_Iterator current; + typedef iterator_traits < _Iterator > __traits_type; + public:typedef _Iterator iterator_type; + typedef typename __traits_type::difference_type difference_type; + typedef typename __traits_type::pointer pointer; + typedef typename __traits_type::reference reference; + reverse_iterator ():current () + { + } explicit reverse_iterator (iterator_type __x):current (__x) + { + } reverse_iterator (const reverse_iterator & __x):current (__x.current) + { + } template < typename _Iter > reverse_iterator (const reverse_iterator < + _Iter > + &__x):current (__x. + base ()) + { + } iterator_type base () const + { + return current; + } + reference operator* () const + { + _Iterator __tmp = current; + return *--__tmp; + } + pointer operator-> () const + { + return &(operator* ()); + } + reverse_iterator & operator++ () + { + --current; + return *this; + } + reverse_iterator operator++ (int) + { + reverse_iterator __tmp = *this; + --current; + return __tmp; + } + reverse_iterator & operator-- () + { + ++current; + return *this; + } + reverse_iterator operator-- (int) + { + reverse_iterator __tmp = *this; + ++current; + return __tmp; + } + reverse_iterator operator+ (difference_type __n) const + { + return reverse_iterator (current - __n); + } + reverse_iterator & operator+= (difference_type __n) + { + current -= __n; + return *this; + } + reverse_iterator operator- (difference_type __n) const + { + return reverse_iterator (current + __n); + } + reverse_iterator & operator-= (difference_type __n) + { + current += __n; + return *this; + } + reference operator[] (difference_type __n) const + { + return *(*this + __n); + } + }; + template < typename _Iterator > + inline bool operator== (const reverse_iterator < _Iterator > &__x, + const reverse_iterator < _Iterator > &__y) + { + return __x.base () == __y.base (); + } + template < typename _Iterator > + inline bool operator< (const reverse_iterator < _Iterator > &__x, + const reverse_iterator < _Iterator > &__y) + { + return __y.base () < __x.base (); + } + template < typename _Iterator > + inline bool operator!= (const reverse_iterator < _Iterator > &__x, + const reverse_iterator < _Iterator > &__y) + { + return !(__x == __y); + } + template < typename _Iterator > + inline bool operator> (const reverse_iterator < _Iterator > &__x, + const reverse_iterator < _Iterator > &__y) + { + return __y < __x; + } + template < typename _Iterator > + inline bool operator<= (const reverse_iterator < _Iterator > &__x, + const reverse_iterator < _Iterator > &__y) + { + return !(__y < __x); + } + template < typename _Iterator > + inline bool operator>= (const reverse_iterator < _Iterator > &__x, + const reverse_iterator < _Iterator > &__y) + { + return !(__x < __y); + } + template < typename _Iterator > inline typename reverse_iterator < + _Iterator >::difference_type operator- (const reverse_iterator < + _Iterator > &__x, + const reverse_iterator < + _Iterator > &__y) + { + return __y.base () - __x.base (); + } + template < typename _Iterator > inline reverse_iterator < _Iterator > + operator+ (typename reverse_iterator < _Iterator >::difference_type __n, + const reverse_iterator < _Iterator > &__x) + { + return reverse_iterator < _Iterator > (__x.base () - __n); + } + template < typename _IteratorL, + typename _IteratorR > inline bool operator== (const reverse_iterator < + _IteratorL > &__x, + const reverse_iterator < + _IteratorR > &__y) + { + return __x.base () == __y.base (); + } + template < typename _IteratorL, + typename _IteratorR > inline bool operator< (const reverse_iterator < + _IteratorL > &__x, + const reverse_iterator < + _IteratorR > &__y) + { + return __y.base () < __x.base (); + } + template < typename _IteratorL, + typename _IteratorR > inline bool operator!= (const reverse_iterator < + _IteratorL > &__x, + const reverse_iterator < + _IteratorR > &__y) + { + return !(__x == __y); + } + template < typename _IteratorL, + typename _IteratorR > inline bool operator> (const reverse_iterator < + _IteratorL > &__x, + const reverse_iterator < + _IteratorR > &__y) + { + return __y < __x; + } + template < typename _IteratorL, + typename _IteratorR > inline bool operator<= (const reverse_iterator < + _IteratorL > &__x, + const reverse_iterator < + _IteratorR > &__y) + { + return !(__y < __x); + } + template < typename _IteratorL, + typename _IteratorR > inline bool operator>= (const reverse_iterator < + _IteratorL > &__x, + const reverse_iterator < + _IteratorR > &__y) + { + return !(__x < __y); + } + template < typename _IteratorL, + typename _IteratorR > inline typename reverse_iterator < + _IteratorL >::difference_type operator- (const reverse_iterator < + _IteratorL > &__x, + const reverse_iterator < + _IteratorR > &__y) + { + return __y.base () - __x.base (); + } +template < typename _Container > class back_insert_iterator:public iterator < output_iterator_tag, void, void, void, + void > + { + protected:_Container * container; + public:typedef _Container container_type; + explicit back_insert_iterator (_Container & __x):container (&__x) + { + } back_insert_iterator & operator= (typename _Container:: + const_reference __value) + { + container->push_back (__value); + return *this; + } + back_insert_iterator & operator* () + { + return *this; + } + back_insert_iterator & operator++ () + { + return *this; + } + back_insert_iterator operator++ (int) + { + return *this; + } + }; + template < typename _Container > inline back_insert_iterator < _Container > + back_inserter (_Container & __x) + { + return back_insert_iterator < _Container > (__x); + } +template < typename _Container > class front_insert_iterator:public iterator < output_iterator_tag, void, void, void, + void > + { + protected:_Container * container; + public:typedef _Container container_type; + explicit front_insert_iterator (_Container & __x):container (&__x) + { + } front_insert_iterator & operator= (typename _Container:: + const_reference __value) + { + container->push_front (__value); + return *this; + } + front_insert_iterator & operator* () + { + return *this; + } + front_insert_iterator & operator++ () + { + return *this; + } + front_insert_iterator operator++ (int) + { + return *this; + } + }; + template < typename _Container > inline front_insert_iterator < _Container > + front_inserter (_Container & __x) + { + return front_insert_iterator < _Container > (__x); + } +template < typename _Container > class insert_iterator:public iterator < output_iterator_tag, void, void, void, + void > + { + protected:_Container * container; + typename _Container::iterator iter; + public:typedef _Container container_type; + insert_iterator (_Container & __x, + typename _Container::iterator __i):container (&__x), + iter (__i) + { + } insert_iterator & operator= (typename _Container:: + const_reference __value) + { + iter = container->insert (iter, __value); + ++iter; + return *this; + } + insert_iterator & operator* () + { + return *this; + } + insert_iterator & operator++ () + { + return *this; + } + insert_iterator & operator++ (int) + { + return *this; + } + }; + template < typename _Container, + typename _Iterator > inline insert_iterator < _Container > + inserter (_Container & __x, _Iterator __i) + { + return insert_iterator < _Container > (__x, + typename _Container:: + iterator (__i)); + } +} + +namespace __gnu_cxx __attribute__ ((__visibility__ ("default"))) +{ + using std::size_t; + using std::ptrdiff_t; + template < typename _Tp > class new_allocator + { + public:typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef _Tp *pointer; + typedef const _Tp *const_pointer; + typedef _Tp & reference; + typedef const _Tp & const_reference; + typedef _Tp value_type; + template < typename _Tp1 > struct rebind + { + typedef new_allocator < _Tp1 > other; + }; + new_allocator ()throw () + { + } new_allocator (const new_allocator &) throw () + { + } template < typename _Tp1 > new_allocator (const new_allocator < _Tp1 > + &) throw () + { + } ~new_allocator ()throw () + { + } pointer address (reference __x) const + { + return &__x; + } + const_pointer address (const_reference __x) const + { + return &__x; + } + pointer allocate (size_type __n, const void * = 0) + { + return static_cast < _Tp * >(::operator new (__n * sizeof (_Tp))); + } + void deallocate (pointer __p, size_type) + { + ::operator delete (__p); + } size_type max_size () const throw () + { + return size_t (-1) / sizeof (_Tp); + } + void construct (pointer __p, const _Tp & __val) + { + ::new ((void *) __p) _Tp (__val); + } void destroy (pointer __p) + { + __p->~_Tp (); + }}; + template < typename _Tp > inline bool operator== (const new_allocator < + _Tp > &, + const new_allocator < + _Tp > &) + { + return true; + } + template < typename _Tp > inline bool operator!= (const new_allocator < + _Tp > &, + const new_allocator < + _Tp > &) + { + return false; + } +} + +namespace std __attribute__ ((__visibility__ ("default"))) +{ + template < typename _Tp > class allocator; + template <> class allocator < void > + { + public:typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef void *pointer; + typedef const void *const_pointer; + typedef void value_type; + template < typename _Tp1 > struct rebind + { + typedef allocator < _Tp1 > other; + }; + }; +template < typename _Tp > class allocator:public __gnu_cxx::new_allocator < + _Tp > + { + public:typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef _Tp *pointer; + typedef const _Tp *const_pointer; + typedef _Tp & reference; + typedef const _Tp & const_reference; + typedef _Tp value_type; + template < typename _Tp1 > struct rebind + { + typedef allocator < _Tp1 > other; + }; + allocator ()throw () + { + } allocator (const allocator & __a) throw ():__gnu_cxx::new_allocator < + _Tp > (__a) + { + } template < typename _Tp1 > allocator (const allocator < _Tp1 > + &) throw () + { + } ~allocator ()throw () + { + }}; + template < typename _T1, + typename _T2 > inline bool operator== (const allocator < _T1 > &, + const allocator < _T2 > &) + { + return true; + } + template < typename _Tp > inline bool operator== (const allocator < _Tp > &, + const allocator < _Tp > &) + { + return true; + } + template < typename _T1, + typename _T2 > inline bool operator!= (const allocator < _T1 > &, + const allocator < _T2 > &) + { + return false; + } + template < typename _Tp > inline bool operator!= (const allocator < _Tp > &, + const allocator < _Tp > &) + { + return false; + } + template < typename _Alloc, bool = __is_empty (_Alloc) > struct __alloc_swap + { + static void _S_do_it (_Alloc &, _Alloc &) + { + }}; + template < typename _Alloc > struct __alloc_swap <_Alloc, false > + { + static void _S_do_it (_Alloc & __one, _Alloc & __two) + { + if (__one != __two) + swap (__one, __two); + } + }; + template < typename _Alloc, bool = __is_empty (_Alloc) > struct __alloc_neq + { + static bool _S_do_it (const _Alloc &, const _Alloc &) + { + return false; + } + }; + template < typename _Alloc > struct __alloc_neq <_Alloc, false > + { + static bool _S_do_it (const _Alloc & __one, const _Alloc & __two) + { + return __one != __two; + } + }; +} + +namespace std __attribute__ ((__visibility__ ("default"))) +{ + struct _List_node_base + { + _List_node_base *_M_next; + _List_node_base *_M_prev; + static void swap (_List_node_base & __x, _List_node_base & __y) throw (); + void _M_transfer (_List_node_base * const __first, + _List_node_base * const __last) throw (); + void _M_reverse () throw (); + void _M_hook (_List_node_base * const __position) throw (); + void _M_unhook () throw (); + }; + template < typename _Tp > struct _List_node:public _List_node_base + { + _Tp _M_data; + }; + template < typename _Tp > struct _List_iterator + { + typedef _List_iterator < _Tp > _Self; + typedef _List_node < _Tp > _Node; + typedef ptrdiff_t difference_type; + typedef std::bidirectional_iterator_tag iterator_category; + typedef _Tp value_type; + typedef _Tp *pointer; + typedef _Tp & reference; + _List_iterator ():_M_node () + { + } explicit _List_iterator (_List_node_base * __x):_M_node (__x) + { + } reference operator* () const + { + return static_cast < _Node * >(_M_node)->_M_data; + } + pointer operator-> () const + { + return &static_cast < _Node * >(_M_node)->_M_data; + } + _Self & operator++ () + { + _M_node = _M_node->_M_next; + return *this; + } + _Self operator++ (int) + { + _Self __tmp = *this; + _M_node = _M_node->_M_next; + return __tmp; + } + _Self & operator-- () + { + _M_node = _M_node->_M_prev; + return *this; + } + _Self operator-- (int) + { + _Self __tmp = *this; + _M_node = _M_node->_M_prev; + return __tmp; + } + bool operator== (const _Self & __x) const + { + return _M_node == __x._M_node; + } + bool operator!= (const _Self & __x) const + { + return _M_node != __x._M_node; + } + _List_node_base *_M_node; + }; + template < typename _Tp > struct _List_const_iterator + { + typedef _List_const_iterator < _Tp > _Self; + typedef const _List_node < _Tp > _Node; + typedef _List_iterator < _Tp > iterator; + typedef ptrdiff_t difference_type; + typedef std::bidirectional_iterator_tag iterator_category; + typedef _Tp value_type; + typedef const _Tp *pointer; + typedef const _Tp & reference; + _List_const_iterator ():_M_node () + { + } explicit _List_const_iterator (const _List_node_base * + __x):_M_node (__x) + { + } _List_const_iterator (const iterator & __x):_M_node (__x._M_node) + { + } reference operator* () const + { + return static_cast < _Node * >(_M_node)->_M_data; + } + pointer operator-> () const + { + return &static_cast < _Node * >(_M_node)->_M_data; + } + _Self & operator++ () + { + _M_node = _M_node->_M_next; + return *this; + } + _Self operator++ (int) + { + _Self __tmp = *this; + _M_node = _M_node->_M_next; + return __tmp; + } + _Self & operator-- () + { + _M_node = _M_node->_M_prev; + return *this; + } + _Self operator-- (int) + { + _Self __tmp = *this; + _M_node = _M_node->_M_prev; + return __tmp; + } + bool operator== (const _Self & __x) const + { + return _M_node == __x._M_node; + } + bool operator!= (const _Self & __x) const + { + return _M_node != __x._M_node; + } + const _List_node_base *_M_node; + }; + template < typename _Tp, typename _Alloc > class _List_base + { + protected:typedef typename _Alloc::template rebind < _List_node < _Tp > + >::other _Node_alloc_type; + typedef typename _Alloc::template rebind < _Tp >::other _Tp_alloc_type; + struct _List_impl:public _Node_alloc_type + { + _List_node_base _M_node; + _List_impl ():_Node_alloc_type (), _M_node () + { + } _List_impl (const _Node_alloc_type & __a):_Node_alloc_type (__a), + _M_node () + { + }}; + _List_impl _M_impl; + _List_node < _Tp > *_M_get_node () + { + return _M_impl._Node_alloc_type::allocate (1); + } + void _M_put_node (_List_node < _Tp > *__p) + { + _M_impl._Node_alloc_type::deallocate (__p, 1); + } public:typedef _Alloc allocator_type; + _Node_alloc_type & _M_get_Node_allocator () + { + return *static_cast < _Node_alloc_type * >(&this->_M_impl); + } + const _Node_alloc_type & _M_get_Node_allocator () const + { + return *static_cast < const _Node_alloc_type *>(&this->_M_impl); + } _Tp_alloc_type _M_get_Tp_allocator () const + { + return _Tp_alloc_type (_M_get_Node_allocator ()); + } + allocator_type get_allocator () const + { + return allocator_type (_M_get_Node_allocator ()); + } + _List_base ():_M_impl () + { + _M_init (); + } + _List_base (const allocator_type & __a):_M_impl (__a) + { + _M_init (); + } ~_List_base () + { + _M_clear (); + } void _M_clear (); + void _M_init () + { + this->_M_impl._M_node._M_next = &this->_M_impl._M_node; + this->_M_impl._M_node._M_prev = &this->_M_impl._M_node; + }}; +template < typename _Tp, typename _Alloc = std::allocator < _Tp > >class list:protected _List_base < _Tp, + _Alloc + > + { + typedef typename _Alloc::value_type _Alloc_value_type; + typedef _List_base < _Tp, _Alloc > _Base; + typedef typename _Base::_Tp_alloc_type _Tp_alloc_type; + public:typedef _Tp value_type; + typedef typename _Tp_alloc_type::pointer pointer; + typedef typename _Tp_alloc_type::const_pointer const_pointer; + typedef typename _Tp_alloc_type::reference reference; + typedef typename _Tp_alloc_type::const_reference const_reference; + typedef _List_iterator < _Tp > iterator; + typedef _List_const_iterator < _Tp > const_iterator; + typedef std::reverse_iterator < const_iterator > const_reverse_iterator; + typedef std::reverse_iterator < iterator > reverse_iterator; + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef _Alloc allocator_type; + protected:typedef _List_node < _Tp > _Node; + using _Base::_M_impl; + using _Base::_M_put_node; + using _Base::_M_get_node; + using _Base::_M_get_Tp_allocator; + using _Base::_M_get_Node_allocator; + public:iterator begin () + { + return iterator (this->_M_impl._M_node._M_next); + } + const_iterator begin () const + { + return const_iterator (this->_M_impl._M_node._M_next); + } + iterator end () + { + return iterator (&this->_M_impl._M_node); + } + void remove (const _Tp & __value); + template < typename _Predicate > void remove_if (_Predicate); + void _M_erase (iterator __position) + { + __position._M_node->_M_unhook (); + _Node *__n = static_cast < _Node * >(__position._M_node); + _M_get_Tp_allocator ().destroy (&__n->_M_data); + _M_put_node (__n); + } void _M_check_equal_allocators (list & __x) + { + if (std::__alloc_neq < + typename _Base::_Node_alloc_type >:: + _S_do_it (_M_get_Node_allocator (), __x._M_get_Node_allocator ())); + } + }; +} + +namespace std __attribute__ ((__visibility__ ("default"))) +{ + template < typename _Tp, typename _Alloc > void list < _Tp, + _Alloc >::remove (const value_type & __value) + { + iterator __first = begin (); + iterator __last = end (); + iterator __extra = __last; + while (__first != __last) + { + iterator __next = __first; + ++__next; + if (*__first == __value) + { + if (&*__first != &__value) + _M_erase (__first); + else + __extra = __first; + } + __first = __next; + } + if (__extra != __last) + _M_erase (__extra); + } +} + +class Unit +{ +public:int dummy; +}; +class Building +{ +public:__attribute__ ((transaction_callable)) void removeUnitFromInside (Unit * + unit); + std::list < Unit * >unitsInside; +}; +void +Building::removeUnitFromInside (Unit * unit) +{ + unitsInside.remove (unit); +} diff --git a/gcc/testsuite/g++.dg/tm/alias.C b/gcc/testsuite/g++.dg/tm/alias.C new file mode 100644 index 00000000000..4459c703bdc --- /dev/null +++ b/gcc/testsuite/g++.dg/tm/alias.C @@ -0,0 +1,20 @@ +// { dg-do compile } +// { dg-options "-fgnu-tm -O0" } + +/* Test that we generate transactional clones for both the base and + the complete dtor for class Itemset. */ + +class Itemset { +public: + __attribute__((transaction_safe)) ~Itemset(); + __attribute__((transaction_safe)) void operator delete(void *); +private: +}; + +__attribute__((transaction_safe)) +Itemset::~Itemset() +{ +} + +// { dg-final { scan-assembler "_ZGTtN7ItemsetD1Ev" } } +// { dg-final { scan-assembler "_ZGTtN7ItemsetD2Ev" } } diff --git a/gcc/testsuite/g++.dg/tm/attrib-2.C b/gcc/testsuite/g++.dg/tm/attrib-2.C new file mode 100644 index 00000000000..6a418e559cf --- /dev/null +++ b/gcc/testsuite/g++.dg/tm/attrib-2.C @@ -0,0 +1,22 @@ +// { dg-do compile } +// { dg-options "-fgnu-tm -fdump-tree-optimized-asmname" } + +struct __attribute__((transaction_safe)) Tsafe +{ + void f(); +}; + +void Tsafe::f() { } + +struct __attribute__((transaction_callable)) Tcall +{ + void f(); +}; + +void Tcall::f() { } + +// { dg-final { scan-tree-dump-times "_ZN5Tsafe1fEv" 1 "optimized" } } +// { dg-final { scan-tree-dump-times "_ZN5Tcall1fEv" 1 "optimized" } } +// { dg-final { scan-tree-dump-times "_ZGTtN5Tsafe1fEv" 1 "optimized" } } +// { dg-final { scan-tree-dump-times "_ZGTtN5Tcall1fEv" 1 "optimized" } } +// { dg-final { cleanup-tree-dump "optimized" } } diff --git a/gcc/testsuite/g++.dg/tm/attrib-3.C b/gcc/testsuite/g++.dg/tm/attrib-3.C new file mode 100644 index 00000000000..a2c9718bc09 --- /dev/null +++ b/gcc/testsuite/g++.dg/tm/attrib-3.C @@ -0,0 +1,33 @@ +// { dg-do compile } +// { dg-options "-fgnu-tm -fdump-tree-optimized-asmname" } + +struct __attribute__((transaction_safe)) A +{ +}; + +struct B : public A +{ + void f(); +}; + +struct C +{ +}; + +struct D : public C +{ +}; + +struct E : public D, public A +{ + void f(); +}; + +void B::f() { } +void E::f() { } + +// { dg-final { scan-tree-dump-times "_ZN1B1fEv" 1 "optimized" } } +// { dg-final { scan-tree-dump-times "_ZGTtN1B1fEv" 1 "optimized" } } +// { dg-final { scan-tree-dump-times "_ZN1E1fEv" 1 "optimized" } } +// { dg-final { scan-tree-dump-times "_ZGTtN1E1fEv" 1 "optimized" } } +// { dg-final { cleanup-tree-dump "optimized" } } diff --git a/gcc/testsuite/g++.dg/tm/attrib-4.C b/gcc/testsuite/g++.dg/tm/attrib-4.C new file mode 100644 index 00000000000..b589b9d41a2 --- /dev/null +++ b/gcc/testsuite/g++.dg/tm/attrib-4.C @@ -0,0 +1,48 @@ +// { dg-do compile } +// { dg-options "-fgnu-tm" } + +#define __ts __attribute__((transaction_safe)) +#define __tc __attribute__((transaction_callable)) +#define __tp __attribute__((transaction_pure)) +#define __tu __attribute__((transaction_unsafe)) + +struct __ts A +{ + virtual void f(); + virtual void g(); +}; + +struct __tc B : public A +{ + void f() __tc; // { dg-error ".transaction_callable. overriding .transaction_safe." } + void g(); + virtual void h(); +}; + +struct C : public B +{ + void g() __tc; // { dg-error ".transaction_callable. overriding .transaction_safe." } +}; + +struct C2 : public B +{ + void g() __ts; + void h() __tu; // { dg-error ".transaction_unsafe. overriding .transaction_callable." } +}; + +struct D +{ + virtual void f() __tp; + virtual void g() __tp; +}; + +struct E : public D +{ + void f() __ts; // { dg-error ".transaction_safe. overriding .transaction_pure." } + void g(); +}; + +struct F : public E +{ + void g() __ts; // { dg-error ".transaction_safe. overriding .transaction_pure." } +}; diff --git a/gcc/testsuite/g++.dg/tm/fatomic-1.C b/gcc/testsuite/g++.dg/tm/fatomic-1.C new file mode 100644 index 00000000000..dac850aac07 --- /dev/null +++ b/gcc/testsuite/g++.dg/tm/fatomic-1.C @@ -0,0 +1,10 @@ +// { dg-do compile } +// { dg-options "-fgnu-tm" } + +struct S +{ + int i, j, k; + S(); +}; + +S::S() __transaction_atomic : i(1), j(2), k(3) { } diff --git a/gcc/testsuite/g++.dg/tm/nested-1.C b/gcc/testsuite/g++.dg/tm/nested-1.C new file mode 100644 index 00000000000..1f4e19e9891 --- /dev/null +++ b/gcc/testsuite/g++.dg/tm/nested-1.C @@ -0,0 +1,22 @@ +// { dg-do compile } +// { dg-options "-fgnu-tm" } + +class HashTree +{ +public: + __attribute__((transaction_safe)) + int add_element2(); +private: + int Count; +}; + + +__attribute__((transaction_safe)) +int HashTree::add_element2() +{ + int tt; + __transaction_atomic { + tt = Count; + } + return tt; +} diff --git a/gcc/testsuite/g++.dg/tm/nested-2.C b/gcc/testsuite/g++.dg/tm/nested-2.C new file mode 100644 index 00000000000..c6d5d98ba7a --- /dev/null +++ b/gcc/testsuite/g++.dg/tm/nested-2.C @@ -0,0 +1,41 @@ +// { dg-do compile } +// { dg-options "-fgnu-tm -O" } + +typedef unsigned long int uint64_t; +extern int *hash_indx; + +typedef struct +{ + uint64_t exit_atomicsec_time; +} ent_ex_times; +class HashTree +{ +public: + __attribute__((transaction_safe)) + void *operator new(__SIZE_TYPE__); + __attribute__((transaction_safe)) + int add_element(); +private: + HashTree **Hash_table; + int Count; +}; + + +__attribute__((transaction_safe)) +int HashTree::add_element() +{ + ent_ex_times enter_exit_times_inside; + int val = hash_indx[5]; + int tt; + if (Hash_table[val] == __null) + { + __transaction_atomic { + Hash_table[val] = new HashTree; + } + } + __transaction_atomic { + tt = Count++; + enter_exit_times_inside.exit_atomicsec_time = 5; + } + return tt; +} diff --git a/gcc/testsuite/g++.dg/tm/nested-3.C b/gcc/testsuite/g++.dg/tm/nested-3.C new file mode 100644 index 00000000000..19718c34a02 --- /dev/null +++ b/gcc/testsuite/g++.dg/tm/nested-3.C @@ -0,0 +1,43 @@ +// { dg-do compile } +// { dg-options "-fgnu-tm -O0" } + +// Same as nested-2.C but with no optimization. + +typedef unsigned long int uint64_t; +extern int *hash_indx; + +typedef struct +{ + uint64_t exit_atomicsec_time; +} ent_ex_times; +class HashTree +{ +public: + __attribute__((transaction_safe)) + void *operator new(__SIZE_TYPE__); + __attribute__((transaction_safe)) + int add_element(); +private: + HashTree **Hash_table; + int Count; +}; + + +__attribute__((transaction_safe)) +int HashTree::add_element() +{ + ent_ex_times enter_exit_times_inside; + int val = hash_indx[5]; + int tt; + if (Hash_table[val] == __null) + { + __transaction_atomic { + Hash_table[val] = new HashTree; + } + } + __transaction_atomic { + tt = Count++; + enter_exit_times_inside.exit_atomicsec_time = 5; + } + return tt; +} diff --git a/gcc/testsuite/g++.dg/tm/opt-1.C b/gcc/testsuite/g++.dg/tm/opt-1.C new file mode 100644 index 00000000000..8dd41a5bfe8 --- /dev/null +++ b/gcc/testsuite/g++.dg/tm/opt-1.C @@ -0,0 +1,9 @@ +// { dg-do compile } +// { dg-options "-fgnu-tm -O" } + +struct S +{ + virtual void f() __attribute__((transaction_safe)); +}; + +void f(S *s) { __transaction_atomic { s->f(); } } diff --git a/gcc/testsuite/g++.dg/tm/pr45940-2.C b/gcc/testsuite/g++.dg/tm/pr45940-2.C new file mode 100644 index 00000000000..ab10c34baaa --- /dev/null +++ b/gcc/testsuite/g++.dg/tm/pr45940-2.C @@ -0,0 +1,30 @@ +// { dg-do compile } +// { dg-options "-fgnu-tm -O1" } + +__attribute__((transaction_pure)) +inline int atomic_exchange_and_add(int dv ) +{ + int r; + __asm__ ("" : "=r"(r)); + return r; +} + +class sp_counted_base +{ +public: + __attribute__((transaction_safe)) + void release() + { + if( atomic_exchange_and_add(-1 ) == 1 ) + { + } + } +}; + +sp_counted_base *base; + +void here(){ + __transaction_atomic { + base->release(); + } +} diff --git a/gcc/testsuite/g++.dg/tm/pr45940-3.C b/gcc/testsuite/g++.dg/tm/pr45940-3.C new file mode 100644 index 00000000000..c8caee6c8b9 --- /dev/null +++ b/gcc/testsuite/g++.dg/tm/pr45940-3.C @@ -0,0 +1,69 @@ +// { dg-do compile } +// { dg-options "-fgnu-tm -O0" } + +__attribute__((transaction_safe)) +void* operator new (__SIZE_TYPE__); + +__attribute__((transaction_pure)) +inline int atomic_exchange_and_add( int * pw, int dv ) +{ + int r; + __asm__ ("" : "=r"(r)); + return r; +} + +class sp_counted_base +{ +protected: + int use_count_; // #shared +public: + __attribute__((transaction_safe)) + virtual void dispose() = 0; // nothrow + + __attribute__((transaction_safe)) + void release() // nothrow + { + if( atomic_exchange_and_add( &use_count_, -1 ) == 1 ) + { + dispose(); + } + } +}; + +class sp_counted_base_x86 : public sp_counted_base +{ +public: + void dispose() + { + release(); + } +}; + +class shared_count +{ +private: + sp_counted_base * pi_; +public: + int j; + __attribute__((transaction_safe)) + shared_count(): pi_(new sp_counted_base_x86()), j(0) + { + } + __attribute__((transaction_safe)) + ~shared_count() // nothrow + { + if( pi_ != 0 ) pi_->release(); + } +}; + +volatile int i = 1; +shared_count * c; +int main() +{ + if ( i == 0) { + __transaction_atomic { + shared_count sc; + } + } + return 0; +} diff --git a/gcc/testsuite/g++.dg/tm/pr45940-4.C b/gcc/testsuite/g++.dg/tm/pr45940-4.C new file mode 100644 index 00000000000..d1cb8d55ae6 --- /dev/null +++ b/gcc/testsuite/g++.dg/tm/pr45940-4.C @@ -0,0 +1,69 @@ +// { dg-do compile } +// { dg-options "-fgnu-tm -O1" } + +__attribute__((transaction_safe)) +void* operator new (__SIZE_TYPE__); + +__attribute__((transaction_pure)) +inline int atomic_exchange_and_add( int * pw, int dv ) +{ + int r; + __asm__ ("" : "=r"(r)); + return r; +} + +class sp_counted_base +{ +protected: + int use_count_; // #shared +public: + __attribute__((transaction_safe)) + virtual void dispose() = 0; // nothrow + + __attribute__((transaction_safe)) + void release() // nothrow + { + if( atomic_exchange_and_add( &use_count_, -1 ) == 1 ) + { + dispose(); + } + } +}; + +class sp_counted_base_x86 : public sp_counted_base +{ +public: + void dispose() + { + release(); + } +}; + +class shared_count +{ +private: + sp_counted_base * pi_; +public: + int j; + __attribute__((transaction_safe)) + shared_count(): pi_(new sp_counted_base_x86()), j(0) + { + } + __attribute__((transaction_safe)) + ~shared_count() // nothrow + { + if( pi_ != 0 ) pi_->release(); + } +}; + +volatile int i = 1; +shared_count * c; +int main() +{ + if ( i == 0) { + __transaction_atomic { + shared_count sc; + } + } + return 0; +} diff --git a/gcc/testsuite/g++.dg/tm/pr45940.C b/gcc/testsuite/g++.dg/tm/pr45940.C new file mode 100644 index 00000000000..3e9a2c3f8da --- /dev/null +++ b/gcc/testsuite/g++.dg/tm/pr45940.C @@ -0,0 +1,30 @@ +// { dg-do compile } +// { dg-options "-fgnu-tm -O0" } + +__attribute__((transaction_pure)) +inline int atomic_exchange_and_add(int dv ) +{ + int r; + __asm__ ("" : "=r"(r)); + return r; +} + +class sp_counted_base +{ +public: + __attribute__((transaction_safe)) + void release() + { + if( atomic_exchange_and_add(-1 ) == 1 ) + { + } + } +}; + +sp_counted_base *base; + +void here(){ + __transaction_atomic { + base->release(); + } +} diff --git a/gcc/testsuite/g++.dg/tm/pr46269.C b/gcc/testsuite/g++.dg/tm/pr46269.C new file mode 100644 index 00000000000..b4b13af5bf1 --- /dev/null +++ b/gcc/testsuite/g++.dg/tm/pr46269.C @@ -0,0 +1,29 @@ +// { dg-do compile } +// { dg-options "-fgnu-tm" } + +static inline void atomic_exchange_and_add() +{ + __asm__ (""); +} + +template<class T> class shared_ptr +{ +public: + shared_ptr( T * p ) + { + atomic_exchange_and_add(); + } +}; + +class BuildingCompletedEvent +{ + public: + __attribute__((transaction_callable)) void updateBuildingSite(void); + __attribute__((transaction_pure)) BuildingCompletedEvent(); +}; + +void BuildingCompletedEvent::updateBuildingSite(void) +{ + shared_ptr<BuildingCompletedEvent> event(new BuildingCompletedEvent()); +} + diff --git a/gcc/testsuite/g++.dg/tm/pr46270.C b/gcc/testsuite/g++.dg/tm/pr46270.C new file mode 100644 index 00000000000..291e620a387 --- /dev/null +++ b/gcc/testsuite/g++.dg/tm/pr46270.C @@ -0,0 +1,27 @@ +// { dg-do compile } +// { dg-options "-fgnu-tm" } + +#include <list> +class Game +{ +public: + struct BuildProject + { + int posX; + }; + std::list<BuildProject> buildProjects; +}; + +static Game game; +static std::list<std::list<Game::BuildProject>::iterator> erasableBuildProjects; + +static void *buildProjectSyncStepConcurrently(int id, int localTeam) +{ + __transaction_relaxed { + std::list<std::list<Game::BuildProject>::iterator>::iterator it + = erasableBuildProjects.begin(); + game.buildProjects.erase( (std::list<Game::BuildProject> + ::iterator) *it); + } + return 0; +} diff --git a/gcc/testsuite/g++.dg/tm/pr46300.C b/gcc/testsuite/g++.dg/tm/pr46300.C new file mode 100644 index 00000000000..7b3c613c3f5 --- /dev/null +++ b/gcc/testsuite/g++.dg/tm/pr46300.C @@ -0,0 +1,8 @@ +// { dg-do compile } +// { dg-options "-fgnu-tm" } + +void foo(){ + __transaction_atomic { + throw 5; + } +} diff --git a/gcc/testsuite/g++.dg/tm/pr46567.C b/gcc/testsuite/g++.dg/tm/pr46567.C new file mode 100644 index 00000000000..2f0ef93f2d4 --- /dev/null +++ b/gcc/testsuite/g++.dg/tm/pr46567.C @@ -0,0 +1,2676 @@ +// { dg-do compile } +// { dg-options "-fgnu-tm -O2" } + +typedef __PTRDIFF_TYPE__ ptrdiff_t; +typedef __SIZE_TYPE__ size_t; +namespace std __attribute__ ((__visibility__ ("default"))) { + using ::ptrdiff_t; + using ::size_t; +} +namespace std __attribute__ ((__visibility__ ("default"))) { + void + __throw_bad_exception(void) __attribute__((__noreturn__)); + void + __throw_bad_alloc(void) __attribute__((__noreturn__)); + void + __throw_bad_cast(void) __attribute__((__noreturn__)); + void + __throw_bad_typeid(void) __attribute__((__noreturn__)); + void + __throw_logic_error(const char*) __attribute__((__noreturn__)); + void + __throw_domain_error(const char*) __attribute__((__noreturn__)); + void + __throw_invalid_argument(const char*) __attribute__((__noreturn__)); + void + __throw_length_error(const char*) __attribute__((__noreturn__)); + void + __throw_out_of_range(const char*) __attribute__((__noreturn__)); + void + __throw_runtime_error(const char*) __attribute__((__noreturn__)); + void + __throw_range_error(const char*) __attribute__((__noreturn__)); + void + __throw_overflow_error(const char*) __attribute__((__noreturn__)); + void + __throw_underflow_error(const char*) __attribute__((__noreturn__)); + void + __throw_ios_failure(const char*) __attribute__((__noreturn__)); + void + __throw_system_error(int) __attribute__((__noreturn__)); +} + +namespace __gnu_cxx __attribute__ ((__visibility__ ("default"))) { + template<typename _Iterator, typename _Container> + class __normal_iterator; +} +namespace std __attribute__ ((__visibility__ ("default"))) { + struct __true_type { }; + struct __false_type { }; + template<bool> + struct __truth_type + { typedef __false_type __type; }; + template<> + struct __truth_type<true> + { typedef __true_type __type; }; + template<class _Sp, class _Tp> + struct __traitor + { + enum { __value = bool(_Sp::__value) || bool(_Tp::__value) }; + typedef typename __truth_type<__value>::__type __type; + }; + template<typename, typename> + struct __are_same + { + enum { __value = 0 }; + typedef __false_type __type; + }; + template<typename _Tp> + struct __are_same<_Tp, _Tp> + { + enum { __value = 1 }; + typedef __true_type __type; + }; + template<typename _Tp> + struct __is_void + { + enum { __value = 0 }; + typedef __false_type __type; + }; + template<> + struct __is_void<void> + { + enum { __value = 1 }; + typedef __true_type __type; + }; + template<typename _Tp> + struct __is_integer + { + enum { __value = 0 }; + typedef __false_type __type; + }; + template<> + struct __is_integer<bool> + { + enum { __value = 1 }; + typedef __true_type __type; + }; + template<> + struct __is_integer<char> + { + enum { __value = 1 }; + typedef __true_type __type; + }; + template<> + struct __is_integer<signed char> + { + enum { __value = 1 }; + typedef __true_type __type; + }; + template<> + struct __is_integer<unsigned char> + { + enum { __value = 1 }; + typedef __true_type __type; + }; + template<> + struct __is_integer<wchar_t> + { + enum { __value = 1 }; + typedef __true_type __type; + }; + template<> + struct __is_integer<short> + { + enum { __value = 1 }; + typedef __true_type __type; + }; + template<> + struct __is_integer<unsigned short> + { + enum { __value = 1 }; + typedef __true_type __type; + }; + template<> + struct __is_integer<int> + { + enum { __value = 1 }; + typedef __true_type __type; + }; + template<> + struct __is_integer<unsigned int> + { + enum { __value = 1 }; + typedef __true_type __type; + }; + template<> + struct __is_integer<long> + { + enum { __value = 1 }; + typedef __true_type __type; + }; + template<> + struct __is_integer<unsigned long> + { + enum { __value = 1 }; + typedef __true_type __type; + }; + template<> + struct __is_integer<long long> + { + enum { __value = 1 }; + typedef __true_type __type; + }; + template<> + struct __is_integer<unsigned long long> + { + enum { __value = 1 }; + typedef __true_type __type; + }; + template<typename _Tp> + struct __is_floating + { + enum { __value = 0 }; + typedef __false_type __type; + }; + template<> + struct __is_floating<float> + { + enum { __value = 1 }; + typedef __true_type __type; + }; + template<> + struct __is_floating<double> + { + enum { __value = 1 }; + typedef __true_type __type; + }; + template<> + struct __is_floating<long double> + { + enum { __value = 1 }; + typedef __true_type __type; + }; + template<typename _Tp> + struct __is_pointer + { + enum { __value = 0 }; + typedef __false_type __type; + }; + template<typename _Tp> + struct __is_pointer<_Tp*> + { + enum { __value = 1 }; + typedef __true_type __type; + }; + template<typename _Tp> + struct __is_normal_iterator + { + enum { __value = 0 }; + typedef __false_type __type; + }; + template<typename _Iterator, typename _Container> + struct __is_normal_iterator< __gnu_cxx::__normal_iterator<_Iterator, + _Container> > + { + enum { __value = 1 }; + typedef __true_type __type; + }; + template<typename _Tp> + struct __is_arithmetic + : public __traitor<__is_integer<_Tp>, __is_floating<_Tp> > + { }; + template<typename _Tp> + struct __is_fundamental + : public __traitor<__is_void<_Tp>, __is_arithmetic<_Tp> > + { }; + template<typename _Tp> + struct __is_scalar + : public __traitor<__is_arithmetic<_Tp>, __is_pointer<_Tp> > + { }; + template<typename _Tp> + struct __is_char + { + enum { __value = 0 }; + typedef __false_type __type; + }; + template<> + struct __is_char<char> + { + enum { __value = 1 }; + typedef __true_type __type; + }; + template<> + struct __is_char<wchar_t> + { + enum { __value = 1 }; + typedef __true_type __type; + }; + template<typename _Tp> + struct __is_byte + { + enum { __value = 0 }; + typedef __false_type __type; + }; + template<> + struct __is_byte<char> + { + enum { __value = 1 }; + typedef __true_type __type; + }; + template<> + struct __is_byte<signed char> + { + enum { __value = 1 }; + typedef __true_type __type; + }; + template<> + struct __is_byte<unsigned char> + { + enum { __value = 1 }; + typedef __true_type __type; + }; + template<typename _Tp> + struct __is_move_iterator + { + enum { __value = 0 }; + typedef __false_type __type; + }; +} + +namespace __gnu_cxx __attribute__ ((__visibility__ ("default"))) { + template<bool, typename> + struct __enable_if + { }; + template<typename _Tp> + struct __enable_if<true, _Tp> + { typedef _Tp __type; }; + template<bool _Cond, typename _Iftrue, typename _Iffalse> + struct __conditional_type + { typedef _Iftrue __type; }; + template<typename _Iftrue, typename _Iffalse> + struct __conditional_type<false, _Iftrue, _Iffalse> + { typedef _Iffalse __type; }; + template<typename _Tp> + struct __add_unsigned + { + private: + typedef __enable_if<std::__is_integer<_Tp>::__value, _Tp> __if_type; + public: + typedef typename __if_type::__type __type; + }; + template<> + struct __add_unsigned<char> + { typedef unsigned char __type; }; + template<> + struct __add_unsigned<signed char> + { typedef unsigned char __type; }; + template<> + struct __add_unsigned<short> + { typedef unsigned short __type; }; + template<> + struct __add_unsigned<int> + { typedef unsigned int __type; }; + template<> + struct __add_unsigned<long> + { typedef unsigned long __type; }; + template<> + struct __add_unsigned<long long> + { typedef unsigned long long __type; }; + template<> + struct __add_unsigned<bool>; + template<> + struct __add_unsigned<wchar_t>; + template<typename _Tp> + struct __remove_unsigned + { + private: + typedef __enable_if<std::__is_integer<_Tp>::__value, _Tp> __if_type; + public: + typedef typename __if_type::__type __type; + }; + template<> + struct __remove_unsigned<char> + { typedef signed char __type; }; + template<> + struct __remove_unsigned<unsigned char> + { typedef signed char __type; }; + template<> + struct __remove_unsigned<unsigned short> + { typedef short __type; }; + template<> + struct __remove_unsigned<unsigned int> + { typedef int __type; }; + template<> + struct __remove_unsigned<unsigned long> + { typedef long __type; }; + template<> + struct __remove_unsigned<unsigned long long> + { typedef long long __type; }; + template<> + struct __remove_unsigned<bool>; + template<> + struct __remove_unsigned<wchar_t>; + template<typename _Type> + inline bool + __is_null_pointer(_Type* __ptr) + { return __ptr == 0; } + template<typename _Type> + inline bool + __is_null_pointer(_Type) + { return false; } + template<typename _Tp, bool = std::__is_integer<_Tp>::__value> + struct __promote + { typedef double __type; }; + template<typename _Tp> + struct __promote<_Tp, false> + { typedef _Tp __type; }; + template<typename _Tp, typename _Up> + struct __promote_2 + { + private: + typedef typename __promote<_Tp>::__type __type1; + typedef typename __promote<_Up>::__type __type2; + public: + typedef __typeof__(__type1() + __type2()) __type; + }; + template<typename _Tp, typename _Up, typename _Vp> + struct __promote_3 + { + private: + typedef typename __promote<_Tp>::__type __type1; + typedef typename __promote<_Up>::__type __type2; + typedef typename __promote<_Vp>::__type __type3; + public: + typedef __typeof__(__type1() + __type2() + __type3()) __type; + }; + template<typename _Tp, typename _Up, typename _Vp, typename _Wp> + struct __promote_4 + { + private: + typedef typename __promote<_Tp>::__type __type1; + typedef typename __promote<_Up>::__type __type2; + typedef typename __promote<_Vp>::__type __type3; + typedef typename __promote<_Wp>::__type __type4; + public: + typedef __typeof__(__type1() + __type2() + __type3() + __type4()) __type; + }; +} + +namespace __gnu_cxx __attribute__ ((__visibility__ ("default"))) { + template<typename _Value> + struct __numeric_traits_integer + { + static const _Value __min = (((_Value)(-1) < 0) ? (_Value)1 << (sizeof(_Value) * 8 - ((_Value)(-1) < 0)) : (_Value)0); + static const _Value __max = (((_Value)(-1) < 0) ? (((((_Value)1 << ((sizeof(_Value) * 8 - ((_Value)(-1) < 0)) - 1)) - 1) << 1) + 1) : ~(_Value)0); + static const bool __is_signed = ((_Value)(-1) < 0); + static const int __digits = (sizeof(_Value) * 8 - ((_Value)(-1) < 0)); + }; + template<typename _Value> + const _Value __numeric_traits_integer<_Value>::__min; + template<typename _Value> + const _Value __numeric_traits_integer<_Value>::__max; + template<typename _Value> + const bool __numeric_traits_integer<_Value>::__is_signed; + template<typename _Value> + const int __numeric_traits_integer<_Value>::__digits; + template<typename _Value> + struct __numeric_traits_floating + { + static const int __max_digits10 = (2 + (std::__are_same<_Value, float>::__value ? 24 : std::__are_same<_Value, double>::__value ? 53 : 64) * 3010 / 10000); + static const bool __is_signed = true; + static const int __digits10 = (std::__are_same<_Value, float>::__value ? 6 : std::__are_same<_Value, double>::__value ? 15 : 18); + static const int __max_exponent10 = (std::__are_same<_Value, float>::__value ? 38 : std::__are_same<_Value, double>::__value ? 308 : 4932); + }; + template<typename _Value> + const int __numeric_traits_floating<_Value>::__max_digits10; + template<typename _Value> + const bool __numeric_traits_floating<_Value>::__is_signed; + template<typename _Value> + const int __numeric_traits_floating<_Value>::__digits10; + template<typename _Value> + const int __numeric_traits_floating<_Value>::__max_exponent10; + template<typename _Value> + struct __numeric_traits + : public __conditional_type<std::__is_integer<_Value>::__value, + __numeric_traits_integer<_Value>, + __numeric_traits_floating<_Value> >::__type + { }; +} + + +namespace std __attribute__ ((__visibility__ ("default"))) { + template<typename _Tp> + inline void + swap(_Tp& __a, _Tp& __b) + { + + _Tp __tmp = (__a); + __a = (__b); + __b = (__tmp); + } + template<typename _Tp, size_t _Nm> + inline void + swap(_Tp (&__a)[_Nm], _Tp (&__b)[_Nm]) + { + for (size_t __n = 0; __n < _Nm; ++__n) + swap(__a[__n], __b[__n]); + } +} +namespace std __attribute__ ((__visibility__ ("default"))) { + template<class _T1, class _T2> + struct pair + { + typedef _T1 first_type; + typedef _T2 second_type; + _T1 first; + _T2 second; + pair() + : first(), second() { } + pair(const _T1& __a, const _T2& __b) + : first(__a), second(__b) { } + template<class _U1, class _U2> + pair(const pair<_U1, _U2>& __p) + : first(__p.first), + second(__p.second) { } + }; + template<class _T1, class _T2> + inline bool + operator==(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y) + { return __x.first == __y.first && __x.second == __y.second; } + template<class _T1, class _T2> + inline bool + operator<(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y) + { return __x.first < __y.first + || (!(__y.first < __x.first) && __x.second < __y.second); } + template<class _T1, class _T2> + inline bool + operator!=(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y) + { return !(__x == __y); } + template<class _T1, class _T2> + inline bool + operator>(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y) + { return __y < __x; } + template<class _T1, class _T2> + inline bool + operator<=(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y) + { return !(__y < __x); } + template<class _T1, class _T2> + inline bool + operator>=(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y) + { return !(__x < __y); } + template<class _T1, class _T2> + inline pair<_T1, _T2> + make_pair(_T1 __x, _T2 __y) + { return pair<_T1, _T2>(__x, __y); } +} + + +namespace std __attribute__ ((__visibility__ ("default"))) { + struct input_iterator_tag { }; + struct output_iterator_tag { }; + struct forward_iterator_tag : public input_iterator_tag { }; + struct bidirectional_iterator_tag : public forward_iterator_tag { }; + struct random_access_iterator_tag : public bidirectional_iterator_tag { }; + template<typename _Category, typename _Tp, typename _Distance = ptrdiff_t, + typename _Pointer = _Tp*, typename _Reference = _Tp&> + struct iterator + { + typedef _Category iterator_category; + typedef _Tp value_type; + typedef _Distance difference_type; + typedef _Pointer pointer; + typedef _Reference reference; + }; + template<typename _Iterator> + struct iterator_traits + { + typedef typename _Iterator::iterator_category iterator_category; + typedef typename _Iterator::value_type value_type; + typedef typename _Iterator::difference_type difference_type; + typedef typename _Iterator::pointer pointer; + typedef typename _Iterator::reference reference; + }; + template<typename _Tp> + struct iterator_traits<_Tp*> + { + typedef random_access_iterator_tag iterator_category; + typedef _Tp value_type; + typedef ptrdiff_t difference_type; + typedef _Tp* pointer; + typedef _Tp& reference; + }; + template<typename _Tp> + struct iterator_traits<const _Tp*> + { + typedef random_access_iterator_tag iterator_category; + typedef _Tp value_type; + typedef ptrdiff_t difference_type; + typedef const _Tp* pointer; + typedef const _Tp& reference; + }; + template<typename _Iter> + inline typename iterator_traits<_Iter>::iterator_category + __iterator_category(const _Iter&) + { return typename iterator_traits<_Iter>::iterator_category(); } +} + +namespace std __attribute__ ((__visibility__ ("default"))) { + template<typename _InputIterator> + inline typename iterator_traits<_InputIterator>::difference_type + __distance(_InputIterator __first, _InputIterator __last, + input_iterator_tag) + { + + typename iterator_traits<_InputIterator>::difference_type __n = 0; + while (__first != __last) + { + ++__first; + ++__n; + } + return __n; + } + template<typename _RandomAccessIterator> + inline typename iterator_traits<_RandomAccessIterator>::difference_type + __distance(_RandomAccessIterator __first, _RandomAccessIterator __last, + random_access_iterator_tag) + { + + return __last - __first; + } + template<typename _InputIterator> + inline typename iterator_traits<_InputIterator>::difference_type + distance(_InputIterator __first, _InputIterator __last) + { + return std::__distance(__first, __last, + std::__iterator_category(__first)); + } + template<typename _InputIterator, typename _Distance> + inline void + __advance(_InputIterator& __i, _Distance __n, input_iterator_tag) + { + + while (__n--) + ++__i; + } + template<typename _BidirectionalIterator, typename _Distance> + inline void + __advance(_BidirectionalIterator& __i, _Distance __n, + bidirectional_iterator_tag) + { + + if (__n > 0) + while (__n--) + ++__i; + else + while (__n++) + --__i; + } + template<typename _RandomAccessIterator, typename _Distance> + inline void + __advance(_RandomAccessIterator& __i, _Distance __n, + random_access_iterator_tag) + { + + __i += __n; + } + template<typename _InputIterator, typename _Distance> + inline void + advance(_InputIterator& __i, _Distance __n) + { + typename iterator_traits<_InputIterator>::difference_type __d = __n; + std::__advance(__i, __d, std::__iterator_category(__i)); + } +} +namespace std __attribute__ ((__visibility__ ("default"))) { + template<typename _Iterator> + class reverse_iterator + : public iterator<typename iterator_traits<_Iterator>::iterator_category, + typename iterator_traits<_Iterator>::value_type, + typename iterator_traits<_Iterator>::difference_type, + typename iterator_traits<_Iterator>::pointer, + typename iterator_traits<_Iterator>::reference> + { + protected: + _Iterator current; + public: + typedef _Iterator iterator_type; + typedef typename iterator_traits<_Iterator>::difference_type + difference_type; + typedef typename iterator_traits<_Iterator>::reference reference; + typedef typename iterator_traits<_Iterator>::pointer pointer; + public: + reverse_iterator() : current() { } + explicit + reverse_iterator(iterator_type __x) : current(__x) { } + reverse_iterator(const reverse_iterator& __x) + : current(__x.current) { } + template<typename _Iter> + reverse_iterator(const reverse_iterator<_Iter>& __x) + : current(__x.base()) { } + iterator_type + base() const + { return current; } + reference + operator*() const + { + _Iterator __tmp = current; + return *--__tmp; + } + pointer + operator->() const + { return &(operator*()); } + reverse_iterator& + operator++() + { + --current; + return *this; + } + reverse_iterator + operator++(int) + { + reverse_iterator __tmp = *this; + --current; + return __tmp; + } + reverse_iterator& + operator--() + { + ++current; + return *this; + } + reverse_iterator + operator--(int) + { + reverse_iterator __tmp = *this; + ++current; + return __tmp; + } + reverse_iterator + operator+(difference_type __n) const + { return reverse_iterator(current - __n); } + reverse_iterator& + operator+=(difference_type __n) + { + current -= __n; + return *this; + } + reverse_iterator + operator-(difference_type __n) const + { return reverse_iterator(current + __n); } + reverse_iterator& + operator-=(difference_type __n) + { + current += __n; + return *this; + } + reference + operator[](difference_type __n) const + { return *(*this + __n); } + }; + template<typename _Iterator> + inline bool + operator==(const reverse_iterator<_Iterator>& __x, + const reverse_iterator<_Iterator>& __y) + { return __x.base() == __y.base(); } + template<typename _Iterator> + inline bool + operator<(const reverse_iterator<_Iterator>& __x, + const reverse_iterator<_Iterator>& __y) + { return __y.base() < __x.base(); } + template<typename _Iterator> + inline bool + operator!=(const reverse_iterator<_Iterator>& __x, + const reverse_iterator<_Iterator>& __y) + { return !(__x == __y); } + template<typename _Iterator> + inline bool + operator>(const reverse_iterator<_Iterator>& __x, + const reverse_iterator<_Iterator>& __y) + { return __y < __x; } + template<typename _Iterator> + inline bool + operator<=(const reverse_iterator<_Iterator>& __x, + const reverse_iterator<_Iterator>& __y) + { return !(__y < __x); } + template<typename _Iterator> + inline bool + operator>=(const reverse_iterator<_Iterator>& __x, + const reverse_iterator<_Iterator>& __y) + { return !(__x < __y); } + template<typename _Iterator> + inline typename reverse_iterator<_Iterator>::difference_type + operator-(const reverse_iterator<_Iterator>& __x, + const reverse_iterator<_Iterator>& __y) + { return __y.base() - __x.base(); } + template<typename _Iterator> + inline reverse_iterator<_Iterator> + operator+(typename reverse_iterator<_Iterator>::difference_type __n, + const reverse_iterator<_Iterator>& __x) + { return reverse_iterator<_Iterator>(__x.base() - __n); } + template<typename _IteratorL, typename _IteratorR> + inline bool + operator==(const reverse_iterator<_IteratorL>& __x, + const reverse_iterator<_IteratorR>& __y) + { return __x.base() == __y.base(); } + template<typename _IteratorL, typename _IteratorR> + inline bool + operator<(const reverse_iterator<_IteratorL>& __x, + const reverse_iterator<_IteratorR>& __y) + { return __y.base() < __x.base(); } + template<typename _IteratorL, typename _IteratorR> + inline bool + operator!=(const reverse_iterator<_IteratorL>& __x, + const reverse_iterator<_IteratorR>& __y) + { return !(__x == __y); } + template<typename _IteratorL, typename _IteratorR> + inline bool + operator>(const reverse_iterator<_IteratorL>& __x, + const reverse_iterator<_IteratorR>& __y) + { return __y < __x; } + template<typename _IteratorL, typename _IteratorR> + inline bool + operator<=(const reverse_iterator<_IteratorL>& __x, + const reverse_iterator<_IteratorR>& __y) + { return !(__y < __x); } + template<typename _IteratorL, typename _IteratorR> + inline bool + operator>=(const reverse_iterator<_IteratorL>& __x, + const reverse_iterator<_IteratorR>& __y) + { return !(__x < __y); } + template<typename _IteratorL, typename _IteratorR> + inline typename reverse_iterator<_IteratorL>::difference_type + operator-(const reverse_iterator<_IteratorL>& __x, + const reverse_iterator<_IteratorR>& __y) + { return __y.base() - __x.base(); } + template<typename _Container> + class back_insert_iterator + : public iterator<output_iterator_tag, void, void, void, void> + { + protected: + _Container* container; + public: + typedef _Container container_type; + explicit + back_insert_iterator(_Container& __x) : container(&__x) { } + back_insert_iterator& + operator=(typename _Container::const_reference __value) + { + container->push_back(__value); + return *this; + } + back_insert_iterator& + operator*() + { return *this; } + back_insert_iterator& + operator++() + { return *this; } + back_insert_iterator + operator++(int) + { return *this; } + }; + template<typename _Container> + inline back_insert_iterator<_Container> + back_inserter(_Container& __x) + { return back_insert_iterator<_Container>(__x); } + template<typename _Container> + class front_insert_iterator + : public iterator<output_iterator_tag, void, void, void, void> + { + protected: + _Container* container; + public: + typedef _Container container_type; + explicit front_insert_iterator(_Container& __x) : container(&__x) { } + front_insert_iterator& + operator=(typename _Container::const_reference __value) + { + container->push_front(__value); + return *this; + } + front_insert_iterator& + operator*() + { return *this; } + front_insert_iterator& + operator++() + { return *this; } + front_insert_iterator + operator++(int) + { return *this; } + }; + template<typename _Container> + inline front_insert_iterator<_Container> + front_inserter(_Container& __x) + { return front_insert_iterator<_Container>(__x); } + template<typename _Container> + class insert_iterator + : public iterator<output_iterator_tag, void, void, void, void> + { + protected: + _Container* container; + typename _Container::iterator iter; + public: + typedef _Container container_type; + insert_iterator(_Container& __x, typename _Container::iterator __i) + : container(&__x), iter(__i) {} + insert_iterator& + operator=(typename _Container::const_reference __value) + { + iter = container->insert(iter, __value); + ++iter; + return *this; + } + insert_iterator& + operator*() + { return *this; } + insert_iterator& + operator++() + { return *this; } + insert_iterator& + operator++(int) + { return *this; } + }; + template<typename _Container, typename _Iterator> + inline insert_iterator<_Container> + inserter(_Container& __x, _Iterator __i) + { + return insert_iterator<_Container>(__x, + typename _Container::iterator(__i)); + } +} +namespace __gnu_cxx __attribute__ ((__visibility__ ("default"))) { + using std::iterator_traits; + using std::iterator; + template<typename _Iterator, typename _Container> + class __normal_iterator + { + protected: + _Iterator _M_current; + public: + typedef _Iterator iterator_type; + typedef typename iterator_traits<_Iterator>::iterator_category + iterator_category; + typedef typename iterator_traits<_Iterator>::value_type value_type; + typedef typename iterator_traits<_Iterator>::difference_type + difference_type; + typedef typename iterator_traits<_Iterator>::reference reference; + typedef typename iterator_traits<_Iterator>::pointer pointer; + __normal_iterator() : _M_current(_Iterator()) { } + explicit + __normal_iterator(const _Iterator& __i) : _M_current(__i) { } + template<typename _Iter> + __normal_iterator(const __normal_iterator<_Iter, + typename __enable_if< + (std::__are_same<_Iter, typename _Container::pointer>::__value), + _Container>::__type>& __i) + : _M_current(__i.base()) { } + reference + operator*() const + { return *_M_current; } + pointer + operator->() const + { return _M_current; } + __normal_iterator& + operator++() + { + ++_M_current; + return *this; + } + __normal_iterator + operator++(int) + { return __normal_iterator(_M_current++); } + __normal_iterator& + operator--() + { + --_M_current; + return *this; + } + __normal_iterator + operator--(int) + { return __normal_iterator(_M_current--); } + reference + operator[](const difference_type& __n) const + { return _M_current[__n]; } + __normal_iterator& + operator+=(const difference_type& __n) + { _M_current += __n; return *this; } + __normal_iterator + operator+(const difference_type& __n) const + { return __normal_iterator(_M_current + __n); } + __normal_iterator& + operator-=(const difference_type& __n) + { _M_current -= __n; return *this; } + __normal_iterator + operator-(const difference_type& __n) const + { return __normal_iterator(_M_current - __n); } + const _Iterator& + base() const + { return _M_current; } + }; + template<typename _IteratorL, typename _IteratorR, typename _Container> + inline bool + operator==(const __normal_iterator<_IteratorL, _Container>& __lhs, + const __normal_iterator<_IteratorR, _Container>& __rhs) + { return __lhs.base() == __rhs.base(); } + template<typename _Iterator, typename _Container> + inline bool + operator==(const __normal_iterator<_Iterator, _Container>& __lhs, + const __normal_iterator<_Iterator, _Container>& __rhs) + { return __lhs.base() == __rhs.base(); } + template<typename _IteratorL, typename _IteratorR, typename _Container> + inline bool + operator!=(const __normal_iterator<_IteratorL, _Container>& __lhs, + const __normal_iterator<_IteratorR, _Container>& __rhs) + { return __lhs.base() != __rhs.base(); } + template<typename _Iterator, typename _Container> + inline bool + operator!=(const __normal_iterator<_Iterator, _Container>& __lhs, + const __normal_iterator<_Iterator, _Container>& __rhs) + { return __lhs.base() != __rhs.base(); } + template<typename _IteratorL, typename _IteratorR, typename _Container> + inline bool + operator<(const __normal_iterator<_IteratorL, _Container>& __lhs, + const __normal_iterator<_IteratorR, _Container>& __rhs) + { return __lhs.base() < __rhs.base(); } + template<typename _Iterator, typename _Container> + inline bool + operator<(const __normal_iterator<_Iterator, _Container>& __lhs, + const __normal_iterator<_Iterator, _Container>& __rhs) + { return __lhs.base() < __rhs.base(); } + template<typename _IteratorL, typename _IteratorR, typename _Container> + inline bool + operator>(const __normal_iterator<_IteratorL, _Container>& __lhs, + const __normal_iterator<_IteratorR, _Container>& __rhs) + { return __lhs.base() > __rhs.base(); } + template<typename _Iterator, typename _Container> + inline bool + operator>(const __normal_iterator<_Iterator, _Container>& __lhs, + const __normal_iterator<_Iterator, _Container>& __rhs) + { return __lhs.base() > __rhs.base(); } + template<typename _IteratorL, typename _IteratorR, typename _Container> + inline bool + operator<=(const __normal_iterator<_IteratorL, _Container>& __lhs, + const __normal_iterator<_IteratorR, _Container>& __rhs) + { return __lhs.base() <= __rhs.base(); } + template<typename _Iterator, typename _Container> + inline bool + operator<=(const __normal_iterator<_Iterator, _Container>& __lhs, + const __normal_iterator<_Iterator, _Container>& __rhs) + { return __lhs.base() <= __rhs.base(); } + template<typename _IteratorL, typename _IteratorR, typename _Container> + inline bool + operator>=(const __normal_iterator<_IteratorL, _Container>& __lhs, + const __normal_iterator<_IteratorR, _Container>& __rhs) + { return __lhs.base() >= __rhs.base(); } + template<typename _Iterator, typename _Container> + inline bool + operator>=(const __normal_iterator<_Iterator, _Container>& __lhs, + const __normal_iterator<_Iterator, _Container>& __rhs) + { return __lhs.base() >= __rhs.base(); } + template<typename _IteratorL, typename _IteratorR, typename _Container> + inline typename __normal_iterator<_IteratorL, _Container>::difference_type + operator-(const __normal_iterator<_IteratorL, _Container>& __lhs, + const __normal_iterator<_IteratorR, _Container>& __rhs) + { return __lhs.base() - __rhs.base(); } + template<typename _Iterator, typename _Container> + inline typename __normal_iterator<_Iterator, _Container>::difference_type + operator-(const __normal_iterator<_Iterator, _Container>& __lhs, + const __normal_iterator<_Iterator, _Container>& __rhs) + { return __lhs.base() - __rhs.base(); } + template<typename _Iterator, typename _Container> + inline __normal_iterator<_Iterator, _Container> + operator+(typename __normal_iterator<_Iterator, _Container>::difference_type + __n, const __normal_iterator<_Iterator, _Container>& __i) + { return __normal_iterator<_Iterator, _Container>(__i.base() + __n); } +} +namespace std +{ + namespace __debug { } +} +namespace __gnu_debug +{ + using namespace std::__debug; +} +namespace std __attribute__ ((__visibility__ ("default"))) { + template<bool _BoolType> + struct __iter_swap + { + template<typename _ForwardIterator1, typename _ForwardIterator2> + static void + iter_swap(_ForwardIterator1 __a, _ForwardIterator2 __b) + { + typedef typename iterator_traits<_ForwardIterator1>::value_type + _ValueType1; + _ValueType1 __tmp = (*__a); + *__a = (*__b); + *__b = (__tmp); + } + }; + template<> + struct __iter_swap<true> + { + template<typename _ForwardIterator1, typename _ForwardIterator2> + static void + iter_swap(_ForwardIterator1 __a, _ForwardIterator2 __b) + { + swap(*__a, *__b); + } + }; + template<typename _ForwardIterator1, typename _ForwardIterator2> + inline void + iter_swap(_ForwardIterator1 __a, _ForwardIterator2 __b) + { + typedef typename iterator_traits<_ForwardIterator1>::value_type + _ValueType1; + typedef typename iterator_traits<_ForwardIterator2>::value_type + _ValueType2; + + + + + typedef typename iterator_traits<_ForwardIterator1>::reference + _ReferenceType1; + typedef typename iterator_traits<_ForwardIterator2>::reference + _ReferenceType2; + std::__iter_swap<__are_same<_ValueType1, _ValueType2>::__value + && __are_same<_ValueType1&, _ReferenceType1>::__value + && __are_same<_ValueType2&, _ReferenceType2>::__value>:: + iter_swap(__a, __b); + } + template<typename _ForwardIterator1, typename _ForwardIterator2> + _ForwardIterator2 + swap_ranges(_ForwardIterator1 __first1, _ForwardIterator1 __last1, + _ForwardIterator2 __first2) + { + + + ; + for (; __first1 != __last1; ++__first1, ++__first2) + std::iter_swap(__first1, __first2); + return __first2; + } + template<typename _Tp> + inline const _Tp& + min(const _Tp& __a, const _Tp& __b) + { + + if (__b < __a) + return __b; + return __a; + } + template<typename _Tp> + inline const _Tp& + max(const _Tp& __a, const _Tp& __b) + { + + if (__a < __b) + return __b; + return __a; + } + template<typename _Tp, typename _Compare> + inline const _Tp& + min(const _Tp& __a, const _Tp& __b, _Compare __comp) + { + if (__comp(__b, __a)) + return __b; + return __a; + } + template<typename _Tp, typename _Compare> + inline const _Tp& + max(const _Tp& __a, const _Tp& __b, _Compare __comp) + { + if (__comp(__a, __b)) + return __b; + return __a; + } + template<typename _Iterator, + bool _IsNormal = __is_normal_iterator<_Iterator>::__value> + struct __niter_base + { + static _Iterator + __b(_Iterator __it) + { return __it; } + }; + template<typename _Iterator> + struct __niter_base<_Iterator, true> + { + static typename _Iterator::iterator_type + __b(_Iterator __it) + { return __it.base(); } + }; + template<typename _Iterator, + bool _IsMove = __is_move_iterator<_Iterator>::__value> + struct __miter_base + { + static _Iterator + __b(_Iterator __it) + { return __it; } + }; + template<typename _Iterator> + struct __miter_base<_Iterator, true> + { + static typename _Iterator::iterator_type + __b(_Iterator __it) + { return __it.base(); } + }; + template<bool, bool, typename> + struct __copy_move + { + template<typename _II, typename _OI> + static _OI + __copy_m(_II __first, _II __last, _OI __result) + { + for (; __first != __last; ++__result, ++__first) + *__result = *__first; + return __result; + } + }; + template<> + struct __copy_move<false, false, random_access_iterator_tag> + { + template<typename _II, typename _OI> + static _OI + __copy_m(_II __first, _II __last, _OI __result) + { + typedef typename iterator_traits<_II>::difference_type _Distance; + for(_Distance __n = __last - __first; __n > 0; --__n) + { + *__result = *__first; + ++__first; + ++__result; + } + return __result; + } + }; + template<bool _IsMove> + struct __copy_move<_IsMove, true, random_access_iterator_tag> + { + template<typename _Tp> + static _Tp* + __copy_m(const _Tp* __first, const _Tp* __last, _Tp* __result) + { + __builtin_memmove(__result, __first, + sizeof(_Tp) * (__last - __first)); + return __result + (__last - __first); + } + }; + template<bool _IsMove, typename _II, typename _OI> + inline _OI + __copy_move_a(_II __first, _II __last, _OI __result) + { + typedef typename iterator_traits<_II>::value_type _ValueTypeI; + typedef typename iterator_traits<_OI>::value_type _ValueTypeO; + typedef typename iterator_traits<_II>::iterator_category _Category; + const bool __simple = (__is_pod(_ValueTypeI) + && __is_pointer<_II>::__value + && __is_pointer<_OI>::__value + && __are_same<_ValueTypeI, _ValueTypeO>::__value); + return std::__copy_move<_IsMove, __simple, + _Category>::__copy_m(__first, __last, __result); + } + template<typename _CharT> + struct char_traits; + template<typename _CharT, typename _Traits> + class istreambuf_iterator; + template<typename _CharT, typename _Traits> + class ostreambuf_iterator; + template<bool _IsMove, typename _CharT> + typename __gnu_cxx::__enable_if<__is_char<_CharT>::__value, + ostreambuf_iterator<_CharT, char_traits<_CharT> > >::__type + __copy_move_a2(_CharT*, _CharT*, + ostreambuf_iterator<_CharT, char_traits<_CharT> >); + template<bool _IsMove, typename _CharT> + typename __gnu_cxx::__enable_if<__is_char<_CharT>::__value, + ostreambuf_iterator<_CharT, char_traits<_CharT> > >::__type + __copy_move_a2(const _CharT*, const _CharT*, + ostreambuf_iterator<_CharT, char_traits<_CharT> >); + template<bool _IsMove, typename _CharT> + typename __gnu_cxx::__enable_if<__is_char<_CharT>::__value, + _CharT*>::__type + __copy_move_a2(istreambuf_iterator<_CharT, char_traits<_CharT> >, + istreambuf_iterator<_CharT, char_traits<_CharT> >, _CharT*); + template<bool _IsMove, typename _II, typename _OI> + inline _OI + __copy_move_a2(_II __first, _II __last, _OI __result) + { + return _OI(std::__copy_move_a<_IsMove> + (std::__niter_base<_II>::__b(__first), + std::__niter_base<_II>::__b(__last), + std::__niter_base<_OI>::__b(__result))); + } + template<typename _II, typename _OI> + inline _OI + copy(_II __first, _II __last, _OI __result) + { + + + ; + return (std::__copy_move_a2<__is_move_iterator<_II>::__value> + (std::__miter_base<_II>::__b(__first), + std::__miter_base<_II>::__b(__last), __result)); + } + template<bool, bool, typename> + struct __copy_move_backward + { + template<typename _BI1, typename _BI2> + static _BI2 + __copy_move_b(_BI1 __first, _BI1 __last, _BI2 __result) + { + while (__first != __last) + *--__result = *--__last; + return __result; + } + }; + template<> + struct __copy_move_backward<false, false, random_access_iterator_tag> + { + template<typename _BI1, typename _BI2> + static _BI2 + __copy_move_b(_BI1 __first, _BI1 __last, _BI2 __result) + { + typename iterator_traits<_BI1>::difference_type __n; + for (__n = __last - __first; __n > 0; --__n) + *--__result = *--__last; + return __result; + } + }; + template<bool _IsMove> + struct __copy_move_backward<_IsMove, true, random_access_iterator_tag> + { + template<typename _Tp> + static _Tp* + __copy_move_b(const _Tp* __first, const _Tp* __last, _Tp* __result) + { + const ptrdiff_t _Num = __last - __first; + __builtin_memmove(__result - _Num, __first, sizeof(_Tp) * _Num); + return __result - _Num; + } + }; + template<bool _IsMove, typename _BI1, typename _BI2> + inline _BI2 + __copy_move_backward_a(_BI1 __first, _BI1 __last, _BI2 __result) + { + typedef typename iterator_traits<_BI1>::value_type _ValueType1; + typedef typename iterator_traits<_BI2>::value_type _ValueType2; + typedef typename iterator_traits<_BI1>::iterator_category _Category; + const bool __simple = (__is_pod(_ValueType1) + && __is_pointer<_BI1>::__value + && __is_pointer<_BI2>::__value + && __are_same<_ValueType1, _ValueType2>::__value); + return std::__copy_move_backward<_IsMove, __simple, + _Category>::__copy_move_b(__first, + __last, + __result); + } + template<bool _IsMove, typename _BI1, typename _BI2> + inline _BI2 + __copy_move_backward_a2(_BI1 __first, _BI1 __last, _BI2 __result) + { + return _BI2(std::__copy_move_backward_a<_IsMove> + (std::__niter_base<_BI1>::__b(__first), + std::__niter_base<_BI1>::__b(__last), + std::__niter_base<_BI2>::__b(__result))); + } + template<typename _BI1, typename _BI2> + inline _BI2 + copy_backward(_BI1 __first, _BI1 __last, _BI2 __result) + { + + + + ; + return (std::__copy_move_backward_a2<__is_move_iterator<_BI1>::__value> + (std::__miter_base<_BI1>::__b(__first), + std::__miter_base<_BI1>::__b(__last), __result)); + } + template<typename _ForwardIterator, typename _Tp> + inline typename + __gnu_cxx::__enable_if<!__is_scalar<_Tp>::__value, void>::__type + __fill_a(_ForwardIterator __first, _ForwardIterator __last, + const _Tp& __value) + { + for (; __first != __last; ++__first) + *__first = __value; + } + template<typename _ForwardIterator, typename _Tp> + inline typename + __gnu_cxx::__enable_if<__is_scalar<_Tp>::__value, void>::__type + __fill_a(_ForwardIterator __first, _ForwardIterator __last, + const _Tp& __value) + { + const _Tp __tmp = __value; + for (; __first != __last; ++__first) + *__first = __tmp; + } + template<typename _Tp> + inline typename + __gnu_cxx::__enable_if<__is_byte<_Tp>::__value, void>::__type + __fill_a(_Tp* __first, _Tp* __last, const _Tp& __c) + { + const _Tp __tmp = __c; + __builtin_memset(__first, static_cast<unsigned char>(__tmp), + __last - __first); + } + template<typename _ForwardIterator, typename _Tp> + inline void + fill(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) + { + + ; + std::__fill_a(std::__niter_base<_ForwardIterator>::__b(__first), + std::__niter_base<_ForwardIterator>::__b(__last), __value); + } + template<typename _OutputIterator, typename _Size, typename _Tp> + inline typename + __gnu_cxx::__enable_if<!__is_scalar<_Tp>::__value, _OutputIterator>::__type + __fill_n_a(_OutputIterator __first, _Size __n, const _Tp& __value) + { + for (; __n > 0; --__n, ++__first) + *__first = __value; + return __first; + } + template<typename _OutputIterator, typename _Size, typename _Tp> + inline typename + __gnu_cxx::__enable_if<__is_scalar<_Tp>::__value, _OutputIterator>::__type + __fill_n_a(_OutputIterator __first, _Size __n, const _Tp& __value) + { + const _Tp __tmp = __value; + for (; __n > 0; --__n, ++__first) + *__first = __tmp; + return __first; + } + template<typename _Size, typename _Tp> + inline typename + __gnu_cxx::__enable_if<__is_byte<_Tp>::__value, _Tp*>::__type + __fill_n_a(_Tp* __first, _Size __n, const _Tp& __c) + { + std::__fill_a(__first, __first + __n, __c); + return __first + __n; + } + template<typename _OI, typename _Size, typename _Tp> + inline _OI + fill_n(_OI __first, _Size __n, const _Tp& __value) + { + + return _OI(std::__fill_n_a(std::__niter_base<_OI>::__b(__first), + __n, __value)); + } + template<bool _BoolType> + struct __equal + { + template<typename _II1, typename _II2> + static bool + equal(_II1 __first1, _II1 __last1, _II2 __first2) + { + for (; __first1 != __last1; ++__first1, ++__first2) + if (!(*__first1 == *__first2)) + return false; + return true; + } + }; + template<> + struct __equal<true> + { + template<typename _Tp> + static bool + equal(const _Tp* __first1, const _Tp* __last1, const _Tp* __first2) + { + return !__builtin_memcmp(__first1, __first2, sizeof(_Tp) + * (__last1 - __first1)); + } + }; + template<typename _II1, typename _II2> + inline bool + __equal_aux(_II1 __first1, _II1 __last1, _II2 __first2) + { + typedef typename iterator_traits<_II1>::value_type _ValueType1; + typedef typename iterator_traits<_II2>::value_type _ValueType2; + const bool __simple = (__is_integer<_ValueType1>::__value + && __is_pointer<_II1>::__value + && __is_pointer<_II2>::__value + && __are_same<_ValueType1, _ValueType2>::__value); + return std::__equal<__simple>::equal(__first1, __last1, __first2); + } + template<typename, typename> + struct __lc_rai + { + template<typename _II1, typename _II2> + static _II1 + __newlast1(_II1, _II1 __last1, _II2, _II2) + { return __last1; } + template<typename _II> + static bool + __cnd2(_II __first, _II __last) + { return __first != __last; } + }; + template<> + struct __lc_rai<random_access_iterator_tag, random_access_iterator_tag> + { + template<typename _RAI1, typename _RAI2> + static _RAI1 + __newlast1(_RAI1 __first1, _RAI1 __last1, + _RAI2 __first2, _RAI2 __last2) + { + const typename iterator_traits<_RAI1>::difference_type + __diff1 = __last1 - __first1; + const typename iterator_traits<_RAI2>::difference_type + __diff2 = __last2 - __first2; + return __diff2 < __diff1 ? __first1 + __diff2 : __last1; + } + template<typename _RAI> + static bool + __cnd2(_RAI, _RAI) + { return true; } + }; + template<bool _BoolType> + struct __lexicographical_compare + { + template<typename _II1, typename _II2> + static bool __lc(_II1, _II1, _II2, _II2); + }; + template<bool _BoolType> + template<typename _II1, typename _II2> + bool + __lexicographical_compare<_BoolType>:: + __lc(_II1 __first1, _II1 __last1, _II2 __first2, _II2 __last2) + { + typedef typename iterator_traits<_II1>::iterator_category _Category1; + typedef typename iterator_traits<_II2>::iterator_category _Category2; + typedef std::__lc_rai<_Category1, _Category2> __rai_type; + __last1 = __rai_type::__newlast1(__first1, __last1, + __first2, __last2); + for (; __first1 != __last1 && __rai_type::__cnd2(__first2, __last2); + ++__first1, ++__first2) + { + if (*__first1 < *__first2) + return true; + if (*__first2 < *__first1) + return false; + } + return __first1 == __last1 && __first2 != __last2; + } + template<> + struct __lexicographical_compare<true> + { + template<typename _Tp, typename _Up> + static bool + __lc(const _Tp* __first1, const _Tp* __last1, + const _Up* __first2, const _Up* __last2) + { + const size_t __len1 = __last1 - __first1; + const size_t __len2 = __last2 - __first2; + const int __result = __builtin_memcmp(__first1, __first2, + std::min(__len1, __len2)); + return __result != 0 ? __result < 0 : __len1 < __len2; + } + }; + template<typename _II1, typename _II2> + inline bool + __lexicographical_compare_aux(_II1 __first1, _II1 __last1, + _II2 __first2, _II2 __last2) + { + typedef typename iterator_traits<_II1>::value_type _ValueType1; + typedef typename iterator_traits<_II2>::value_type _ValueType2; + const bool __simple = + (__is_byte<_ValueType1>::__value && __is_byte<_ValueType2>::__value + && !__gnu_cxx::__numeric_traits<_ValueType1>::__is_signed + && !__gnu_cxx::__numeric_traits<_ValueType2>::__is_signed + && __is_pointer<_II1>::__value + && __is_pointer<_II2>::__value); + return std::__lexicographical_compare<__simple>::__lc(__first1, __last1, + __first2, __last2); + } +} +namespace std __attribute__ ((__visibility__ ("default"))) { + template<typename _II1, typename _II2> + inline bool + equal(_II1 __first1, _II1 __last1, _II2 __first2) + { + + + + ; + return std::__equal_aux(std::__niter_base<_II1>::__b(__first1), + std::__niter_base<_II1>::__b(__last1), + std::__niter_base<_II2>::__b(__first2)); + } + template<typename _IIter1, typename _IIter2, typename _BinaryPredicate> + inline bool + equal(_IIter1 __first1, _IIter1 __last1, + _IIter2 __first2, _BinaryPredicate __binary_pred) + { + + + ; + for (; __first1 != __last1; ++__first1, ++__first2) + if (!bool(__binary_pred(*__first1, *__first2))) + return false; + return true; + } + template<typename _II1, typename _II2> + inline bool + lexicographical_compare(_II1 __first1, _II1 __last1, + _II2 __first2, _II2 __last2) + { + typedef typename iterator_traits<_II1>::value_type _ValueType1; + typedef typename iterator_traits<_II2>::value_type _ValueType2; + + + + + ; + ; + return std::__lexicographical_compare_aux + (std::__niter_base<_II1>::__b(__first1), + std::__niter_base<_II1>::__b(__last1), + std::__niter_base<_II2>::__b(__first2), + std::__niter_base<_II2>::__b(__last2)); + } + template<typename _II1, typename _II2, typename _Compare> + bool + lexicographical_compare(_II1 __first1, _II1 __last1, + _II2 __first2, _II2 __last2, _Compare __comp) + { + typedef typename iterator_traits<_II1>::iterator_category _Category1; + typedef typename iterator_traits<_II2>::iterator_category _Category2; + typedef std::__lc_rai<_Category1, _Category2> __rai_type; + + + ; + ; + __last1 = __rai_type::__newlast1(__first1, __last1, __first2, __last2); + for (; __first1 != __last1 && __rai_type::__cnd2(__first2, __last2); + ++__first1, ++__first2) + { + if (__comp(*__first1, *__first2)) + return true; + if (__comp(*__first2, *__first1)) + return false; + } + return __first1 == __last1 && __first2 != __last2; + } + template<typename _InputIterator1, typename _InputIterator2> + pair<_InputIterator1, _InputIterator2> + mismatch(_InputIterator1 __first1, _InputIterator1 __last1, + _InputIterator2 __first2) + { + + + + ; + while (__first1 != __last1 && *__first1 == *__first2) + { + ++__first1; + ++__first2; + } + return pair<_InputIterator1, _InputIterator2>(__first1, __first2); + } + template<typename _InputIterator1, typename _InputIterator2, + typename _BinaryPredicate> + pair<_InputIterator1, _InputIterator2> + mismatch(_InputIterator1 __first1, _InputIterator1 __last1, + _InputIterator2 __first2, _BinaryPredicate __binary_pred) + { + + + ; + while (__first1 != __last1 && bool(__binary_pred(*__first1, *__first2))) + { + ++__first1; + ++__first2; + } + return pair<_InputIterator1, _InputIterator2>(__first1, __first2); + } +} + +extern "C++" { +namespace std +{ + class exception + { + public: + exception() throw() { } + virtual ~exception() throw(); + virtual const char* what() const throw(); + }; + class bad_exception : public exception + { + public: + bad_exception() throw() { } + virtual ~bad_exception() throw(); + virtual const char* what() const throw(); + }; + typedef void (*terminate_handler) (); + typedef void (*unexpected_handler) (); + terminate_handler set_terminate(terminate_handler) throw(); + void terminate() __attribute__ ((__noreturn__)); + unexpected_handler set_unexpected(unexpected_handler) throw(); + void unexpected() __attribute__ ((__noreturn__)); + bool uncaught_exception() throw(); +} +namespace __gnu_cxx __attribute__ ((__visibility__ ("default"))) { + void __verbose_terminate_handler(); +} +} +extern "C++" { +namespace std +{ + class bad_alloc : public exception + { + public: + bad_alloc() throw() { } + virtual ~bad_alloc() throw(); + virtual const char* what() const throw(); + }; + struct nothrow_t { }; + extern const nothrow_t nothrow; + typedef void (*new_handler)(); + new_handler set_new_handler(new_handler) throw(); +} +void* operator new(std::size_t) throw (std::bad_alloc); +void* operator new[](std::size_t) throw (std::bad_alloc); +void operator delete(void*) throw(); +void operator delete[](void*) throw(); +void* operator new(std::size_t, const std::nothrow_t&) throw(); +void* operator new[](std::size_t, const std::nothrow_t&) throw(); +void operator delete(void*, const std::nothrow_t&) throw(); +void operator delete[](void*, const std::nothrow_t&) throw(); +inline void* operator new(std::size_t, void* __p) throw() { return __p; } +inline void* operator new[](std::size_t, void* __p) throw() { return __p; } +inline void operator delete (void*, void*) throw() { } +inline void operator delete[](void*, void*) throw() { } +} +namespace __gnu_cxx __attribute__ ((__visibility__ ("default"))) { + using std::size_t; + using std::ptrdiff_t; + template<typename _Tp> + class new_allocator + { + public: + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef _Tp* pointer; + typedef const _Tp* const_pointer; + typedef _Tp& reference; + typedef const _Tp& const_reference; + typedef _Tp value_type; + template<typename _Tp1> + struct rebind + { typedef new_allocator<_Tp1> other; }; + new_allocator() throw() { } + new_allocator(const new_allocator&) throw() { } + template<typename _Tp1> + new_allocator(const new_allocator<_Tp1>&) throw() { } + ~new_allocator() throw() { } + pointer + address(reference __x) const { return &__x; } + const_pointer + address(const_reference __x) const { return &__x; } + pointer + allocate(size_type __n, const void* = 0) + { + if (__builtin_expect(__n > this->max_size(), false)) + std::__throw_bad_alloc(); + return static_cast<_Tp*>(::operator new(__n * sizeof(_Tp))); + } + void + deallocate(pointer __p, size_type) + { ::operator delete(__p); } + size_type + max_size() const throw() + { return size_t(-1) / sizeof(_Tp); } + void + construct(pointer __p, const _Tp& __val) + { ::new((void *)__p) _Tp(__val); } + void + destroy(pointer __p) { __p->~_Tp(); } + }; + template<typename _Tp> + inline bool + operator==(const new_allocator<_Tp>&, const new_allocator<_Tp>&) + { return true; } + template<typename _Tp> + inline bool + operator!=(const new_allocator<_Tp>&, const new_allocator<_Tp>&) + { return false; } +} +namespace std __attribute__ ((__visibility__ ("default"))) { + template<typename _Tp> + class allocator; + template<> + class allocator<void> + { + public: + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef void* pointer; + typedef const void* const_pointer; + typedef void value_type; + template<typename _Tp1> + struct rebind + { typedef allocator<_Tp1> other; }; + }; + template<typename _Tp> + class allocator: public __gnu_cxx::new_allocator<_Tp> + { + public: + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef _Tp* pointer; + typedef const _Tp* const_pointer; + typedef _Tp& reference; + typedef const _Tp& const_reference; + typedef _Tp value_type; + template<typename _Tp1> + struct rebind + { typedef allocator<_Tp1> other; }; + allocator() throw() { } + allocator(const allocator& __a) throw() + : __gnu_cxx::new_allocator<_Tp>(__a) { } + template<typename _Tp1> + allocator(const allocator<_Tp1>&) throw() { } + ~allocator() throw() { } + }; + template<typename _T1, typename _T2> + inline bool + operator==(const allocator<_T1>&, const allocator<_T2>&) + { return true; } + template<typename _Tp> + inline bool + operator==(const allocator<_Tp>&, const allocator<_Tp>&) + { return true; } + template<typename _T1, typename _T2> + inline bool + operator!=(const allocator<_T1>&, const allocator<_T2>&) + { return false; } + template<typename _Tp> + inline bool + operator!=(const allocator<_Tp>&, const allocator<_Tp>&) + { return false; } + extern template class allocator<char>; + extern template class allocator<wchar_t>; + template<typename _Alloc, bool = __is_empty(_Alloc)> + struct __alloc_swap + { static void _S_do_it(_Alloc&, _Alloc&) { } }; + template<typename _Alloc> + struct __alloc_swap<_Alloc, false> + { + static void + _S_do_it(_Alloc& __one, _Alloc& __two) + { + if (__one != __two) + swap(__one, __two); + } + }; + template<typename _Alloc, bool = __is_empty(_Alloc)> + struct __alloc_neq + { + static bool + _S_do_it(const _Alloc&, const _Alloc&) + { return false; } + }; + template<typename _Alloc> + struct __alloc_neq<_Alloc, false> + { + static bool + _S_do_it(const _Alloc& __one, const _Alloc& __two) + { return __one != __two; } + }; +} +namespace std __attribute__ ((__visibility__ ("default"))) { + struct _List_node_base + { + _List_node_base* _M_next; + _List_node_base* _M_prev; + static void + swap(_List_node_base& __x, _List_node_base& __y); + void + transfer(_List_node_base * const __first, + _List_node_base * const __last); + void + reverse(); + void + hook(_List_node_base * const __position); + void + unhook(); + }; + template<typename _Tp> + struct _List_node : public _List_node_base + { + _Tp _M_data; + }; + template<typename _Tp> + struct _List_iterator + { + typedef _List_iterator<_Tp> _Self; + typedef _List_node<_Tp> _Node; + typedef ptrdiff_t difference_type; + typedef std::bidirectional_iterator_tag iterator_category; + typedef _Tp value_type; + typedef _Tp* pointer; + typedef _Tp& reference; + _List_iterator() + : _M_node() { } + explicit + _List_iterator(_List_node_base* __x) + : _M_node(__x) { } + reference + operator*() const + { return static_cast<_Node*>(_M_node)->_M_data; } + pointer + operator->() const + { return &static_cast<_Node*>(_M_node)->_M_data; } + _Self& + operator++() + { + _M_node = _M_node->_M_next; + return *this; + } + _Self + operator++(int) + { + _Self __tmp = *this; + _M_node = _M_node->_M_next; + return __tmp; + } + _Self& + operator--() + { + _M_node = _M_node->_M_prev; + return *this; + } + _Self + operator--(int) + { + _Self __tmp = *this; + _M_node = _M_node->_M_prev; + return __tmp; + } + bool + operator==(const _Self& __x) const + { return _M_node == __x._M_node; } + bool + operator!=(const _Self& __x) const + { return _M_node != __x._M_node; } + _List_node_base* _M_node; + }; + template<typename _Tp> + struct _List_const_iterator + { + typedef _List_const_iterator<_Tp> _Self; + typedef const _List_node<_Tp> _Node; + typedef _List_iterator<_Tp> iterator; + typedef ptrdiff_t difference_type; + typedef std::bidirectional_iterator_tag iterator_category; + typedef _Tp value_type; + typedef const _Tp* pointer; + typedef const _Tp& reference; + _List_const_iterator() + : _M_node() { } + explicit + _List_const_iterator(const _List_node_base* __x) + : _M_node(__x) { } + _List_const_iterator(const iterator& __x) + : _M_node(__x._M_node) { } + reference + operator*() const + { return static_cast<_Node*>(_M_node)->_M_data; } + pointer + operator->() const + { return &static_cast<_Node*>(_M_node)->_M_data; } + _Self& + operator++() + { + _M_node = _M_node->_M_next; + return *this; + } + _Self + operator++(int) + { + _Self __tmp = *this; + _M_node = _M_node->_M_next; + return __tmp; + } + _Self& + operator--() + { + _M_node = _M_node->_M_prev; + return *this; + } + _Self + operator--(int) + { + _Self __tmp = *this; + _M_node = _M_node->_M_prev; + return __tmp; + } + bool + operator==(const _Self& __x) const + { return _M_node == __x._M_node; } + bool + operator!=(const _Self& __x) const + { return _M_node != __x._M_node; } + const _List_node_base* _M_node; + }; + template<typename _Val> + inline bool + operator==(const _List_iterator<_Val>& __x, + const _List_const_iterator<_Val>& __y) + { return __x._M_node == __y._M_node; } + template<typename _Val> + inline bool + operator!=(const _List_iterator<_Val>& __x, + const _List_const_iterator<_Val>& __y) + { return __x._M_node != __y._M_node; } + template<typename _Tp, typename _Alloc> + class _List_base + { + protected: + typedef typename _Alloc::template rebind<_List_node<_Tp> >::other + _Node_alloc_type; + typedef typename _Alloc::template rebind<_Tp>::other _Tp_alloc_type; + struct _List_impl + : public _Node_alloc_type + { + _List_node_base _M_node; + _List_impl() + : _Node_alloc_type(), _M_node() + { } + _List_impl(const _Node_alloc_type& __a) + : _Node_alloc_type(__a), _M_node() + { } + }; + _List_impl _M_impl; + _List_node<_Tp>* + _M_get_node() + { return _M_impl._Node_alloc_type::allocate(1); } + void + _M_put_node(_List_node<_Tp>* __p) + { _M_impl._Node_alloc_type::deallocate(__p, 1); } + public: + typedef _Alloc allocator_type; + _Node_alloc_type& + _M_get_Node_allocator() + { return *static_cast<_Node_alloc_type*>(&this->_M_impl); } + const _Node_alloc_type& + _M_get_Node_allocator() const + { return *static_cast<const _Node_alloc_type*>(&this->_M_impl); } + _Tp_alloc_type + _M_get_Tp_allocator() const + { return _Tp_alloc_type(_M_get_Node_allocator()); } + allocator_type + get_allocator() const + { return allocator_type(_M_get_Node_allocator()); } + _List_base() + : _M_impl() + { _M_init(); } + _List_base(const allocator_type& __a) + : _M_impl(__a) + { _M_init(); } + ~_List_base() + { _M_clear(); } + void + _M_clear(); + void + _M_init() + { + this->_M_impl._M_node._M_next = &this->_M_impl._M_node; + this->_M_impl._M_node._M_prev = &this->_M_impl._M_node; + } + }; + template<typename _Tp, typename _Alloc = std::allocator<_Tp> > + class list : protected _List_base<_Tp, _Alloc> + { + typedef typename _Alloc::value_type _Alloc_value_type; + + + typedef _List_base<_Tp, _Alloc> _Base; + typedef typename _Base::_Tp_alloc_type _Tp_alloc_type; + public: + typedef _Tp value_type; + typedef typename _Tp_alloc_type::pointer pointer; + typedef typename _Tp_alloc_type::const_pointer const_pointer; + typedef typename _Tp_alloc_type::reference reference; + typedef typename _Tp_alloc_type::const_reference const_reference; + typedef _List_iterator<_Tp> iterator; + typedef _List_const_iterator<_Tp> const_iterator; + typedef std::reverse_iterator<const_iterator> const_reverse_iterator; + typedef std::reverse_iterator<iterator> reverse_iterator; + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef _Alloc allocator_type; + protected: + typedef _List_node<_Tp> _Node; + using _Base::_M_impl; + using _Base::_M_put_node; + using _Base::_M_get_node; + using _Base::_M_get_Tp_allocator; + using _Base::_M_get_Node_allocator; + _Node* + _M_create_node(const value_type& __x) + { + _Node* __p = this->_M_get_node(); + try + { + _M_get_Tp_allocator().construct(&__p->_M_data, __x); + } + catch(...) + { + _M_put_node(__p); + throw; + } + return __p; + } + public: + list() + : _Base() { } + explicit + list(const allocator_type& __a) + : _Base(__a) { } + explicit + list(size_type __n, const value_type& __value = value_type(), + const allocator_type& __a = allocator_type()) + : _Base(__a) + { _M_fill_initialize(__n, __value); } + list(const list& __x) + : _Base(__x._M_get_Node_allocator()) + { _M_initialize_dispatch(__x.begin(), __x.end(), __false_type()); } + template<typename _InputIterator> + list(_InputIterator __first, _InputIterator __last, + const allocator_type& __a = allocator_type()) + : _Base(__a) + { + typedef typename std::__is_integer<_InputIterator>::__type _Integral; + _M_initialize_dispatch(__first, __last, _Integral()); + } + list& + operator=(const list& __x); + void + assign(size_type __n, const value_type& __val) + { _M_fill_assign(__n, __val); } + template<typename _InputIterator> + void + assign(_InputIterator __first, _InputIterator __last) + { + typedef typename std::__is_integer<_InputIterator>::__type _Integral; + _M_assign_dispatch(__first, __last, _Integral()); + } + allocator_type + get_allocator() const + { return _Base::get_allocator(); } + iterator + begin() + { return iterator(this->_M_impl._M_node._M_next); } + const_iterator + begin() const + { return const_iterator(this->_M_impl._M_node._M_next); } + iterator + end() + { return iterator(&this->_M_impl._M_node); } + const_iterator + end() const + { return const_iterator(&this->_M_impl._M_node); } + reverse_iterator + rbegin() + { return reverse_iterator(end()); } + const_reverse_iterator + rbegin() const + { return const_reverse_iterator(end()); } + reverse_iterator + rend() + { return reverse_iterator(begin()); } + const_reverse_iterator + rend() const + { return const_reverse_iterator(begin()); } + bool + empty() const + { return this->_M_impl._M_node._M_next == &this->_M_impl._M_node; } + size_type + size() const + { return std::distance(begin(), end()); } + size_type + max_size() const + { return _M_get_Node_allocator().max_size(); } + void + resize(size_type __new_size, value_type __x = value_type()); + reference + front() + { return *begin(); } + const_reference + front() const + { return *begin(); } + reference + back() + { + iterator __tmp = end(); + --__tmp; + return *__tmp; + } + const_reference + back() const + { + const_iterator __tmp = end(); + --__tmp; + return *__tmp; + } + void + push_front(const value_type& __x) + { this->_M_insert(begin(), __x); } + void + pop_front() + { this->_M_erase(begin()); } + void + push_back(const value_type& __x) + { this->_M_insert(end(), __x); } + void + pop_back() + { this->_M_erase(iterator(this->_M_impl._M_node._M_prev)); } + iterator + insert(iterator __position, const value_type& __x); + void + insert(iterator __position, size_type __n, const value_type& __x) + { + list __tmp(__n, __x, _M_get_Node_allocator()); + splice(__position, __tmp); + } + template<typename _InputIterator> + void + insert(iterator __position, _InputIterator __first, + _InputIterator __last) + { + list __tmp(__first, __last, _M_get_Node_allocator()); + splice(__position, __tmp); + } + iterator + erase(iterator __position); + iterator + erase(iterator __first, iterator __last) + { + while (__first != __last) + __first = erase(__first); + return __last; + } + void + swap(list& __x) + { + _List_node_base::swap(this->_M_impl._M_node, __x._M_impl._M_node); + std::__alloc_swap<typename _Base::_Node_alloc_type>:: + _S_do_it(_M_get_Node_allocator(), __x._M_get_Node_allocator()); + } + void + clear() + { + _Base::_M_clear(); + _Base::_M_init(); + } + void + splice(iterator __position, list& __x) + { + if (!__x.empty()) + { + _M_check_equal_allocators(__x); + this->_M_transfer(__position, __x.begin(), __x.end()); + } + } + void + splice(iterator __position, list& __x, iterator __i) + { + iterator __j = __i; + ++__j; + if (__position == __i || __position == __j) + return; + if (this != &__x) + _M_check_equal_allocators(__x); + this->_M_transfer(__position, __i, __j); + } + void + splice(iterator __position, list& __x, iterator __first, + iterator __last) + { + if (__first != __last) + { + if (this != &__x) + _M_check_equal_allocators(__x); + this->_M_transfer(__position, __first, __last); + } + } + void + remove(const _Tp& __value); + template<typename _Predicate> + void + remove_if(_Predicate); + void + unique(); + template<typename _BinaryPredicate> + void + unique(_BinaryPredicate); + void + merge(list& __x); + template<typename _StrictWeakOrdering> + void + merge(list&, _StrictWeakOrdering); + void + reverse() + { this->_M_impl._M_node.reverse(); } + void + sort(); + template<typename _StrictWeakOrdering> + void + sort(_StrictWeakOrdering); + protected: + template<typename _Integer> + void + _M_initialize_dispatch(_Integer __n, _Integer __x, __true_type) + { _M_fill_initialize(static_cast<size_type>(__n), __x); } + template<typename _InputIterator> + void + _M_initialize_dispatch(_InputIterator __first, _InputIterator __last, + __false_type) + { + for (; __first != __last; ++__first) + push_back(*__first); + } + void + _M_fill_initialize(size_type __n, const value_type& __x) + { + for (; __n > 0; --__n) + push_back(__x); + } + template<typename _Integer> + void + _M_assign_dispatch(_Integer __n, _Integer __val, __true_type) + { _M_fill_assign(__n, __val); } + template<typename _InputIterator> + void + _M_assign_dispatch(_InputIterator __first, _InputIterator __last, + __false_type); + void + _M_fill_assign(size_type __n, const value_type& __val); + void + _M_transfer(iterator __position, iterator __first, iterator __last) + { __position._M_node->transfer(__first._M_node, __last._M_node); } + void + _M_insert(iterator __position, const value_type& __x) + { + _Node* __tmp = _M_create_node(__x); + __tmp->hook(__position._M_node); + } + void + _M_erase(iterator __position) + { + __position._M_node->unhook(); + _Node* __n = static_cast<_Node*>(__position._M_node); + _M_get_Tp_allocator().destroy(&__n->_M_data); + _M_put_node(__n); + } + void + _M_check_equal_allocators(list& __x) + { + if (std::__alloc_neq<typename _Base::_Node_alloc_type>:: + _S_do_it(_M_get_Node_allocator(), __x._M_get_Node_allocator())) + __throw_runtime_error(("list::_M_check_equal_allocators")); + } + }; + template<typename _Tp, typename _Alloc> + inline bool + operator==(const list<_Tp, _Alloc>& __x, const list<_Tp, _Alloc>& __y) + { + typedef typename list<_Tp, _Alloc>::const_iterator const_iterator; + const_iterator __end1 = __x.end(); + const_iterator __end2 = __y.end(); + const_iterator __i1 = __x.begin(); + const_iterator __i2 = __y.begin(); + while (__i1 != __end1 && __i2 != __end2 && *__i1 == *__i2) + { + ++__i1; + ++__i2; + } + return __i1 == __end1 && __i2 == __end2; + } + template<typename _Tp, typename _Alloc> + inline bool + operator<(const list<_Tp, _Alloc>& __x, const list<_Tp, _Alloc>& __y) + { return std::lexicographical_compare(__x.begin(), __x.end(), + __y.begin(), __y.end()); } + template<typename _Tp, typename _Alloc> + inline bool + operator!=(const list<_Tp, _Alloc>& __x, const list<_Tp, _Alloc>& __y) + { return !(__x == __y); } + template<typename _Tp, typename _Alloc> + inline bool + operator>(const list<_Tp, _Alloc>& __x, const list<_Tp, _Alloc>& __y) + { return __y < __x; } + template<typename _Tp, typename _Alloc> + inline bool + operator<=(const list<_Tp, _Alloc>& __x, const list<_Tp, _Alloc>& __y) + { return !(__y < __x); } + template<typename _Tp, typename _Alloc> + inline bool + operator>=(const list<_Tp, _Alloc>& __x, const list<_Tp, _Alloc>& __y) + { return !(__x < __y); } + template<typename _Tp, typename _Alloc> + inline void + swap(list<_Tp, _Alloc>& __x, list<_Tp, _Alloc>& __y) + { __x.swap(__y); } +} +namespace std __attribute__ ((__visibility__ ("default"))) { + template<typename _Tp, typename _Alloc> + void + _List_base<_Tp, _Alloc>:: + _M_clear() + { + typedef _List_node<_Tp> _Node; + _Node* __cur = static_cast<_Node*>(this->_M_impl._M_node._M_next); + while (__cur != &this->_M_impl._M_node) + { + _Node* __tmp = __cur; + __cur = static_cast<_Node*>(__cur->_M_next); + _M_get_Tp_allocator().destroy(&__tmp->_M_data); + _M_put_node(__tmp); + } + } + template<typename _Tp, typename _Alloc> + typename list<_Tp, _Alloc>::iterator + list<_Tp, _Alloc>:: + insert(iterator __position, const value_type& __x) + { + _Node* __tmp = _M_create_node(__x); + __tmp->hook(__position._M_node); + return iterator(__tmp); + } + template<typename _Tp, typename _Alloc> + typename list<_Tp, _Alloc>::iterator + list<_Tp, _Alloc>:: + erase(iterator __position) + { + iterator __ret = iterator(__position._M_node->_M_next); + _M_erase(__position); + return __ret; + } + template<typename _Tp, typename _Alloc> + void + list<_Tp, _Alloc>:: + resize(size_type __new_size, value_type __x) + { + iterator __i = begin(); + size_type __len = 0; + for (; __i != end() && __len < __new_size; ++__i, ++__len) + ; + if (__len == __new_size) + erase(__i, end()); + else + insert(end(), __new_size - __len, __x); + } + template<typename _Tp, typename _Alloc> + list<_Tp, _Alloc>& + list<_Tp, _Alloc>:: + operator=(const list& __x) + { + if (this != &__x) + { + iterator __first1 = begin(); + iterator __last1 = end(); + const_iterator __first2 = __x.begin(); + const_iterator __last2 = __x.end(); + for (; __first1 != __last1 && __first2 != __last2; + ++__first1, ++__first2) + *__first1 = *__first2; + if (__first2 == __last2) + erase(__first1, __last1); + else + insert(__last1, __first2, __last2); + } + return *this; + } + template<typename _Tp, typename _Alloc> + void + list<_Tp, _Alloc>:: + _M_fill_assign(size_type __n, const value_type& __val) + { + iterator __i = begin(); + for (; __i != end() && __n > 0; ++__i, --__n) + *__i = __val; + if (__n > 0) + insert(end(), __n, __val); + else + erase(__i, end()); + } + template<typename _Tp, typename _Alloc> + template <typename _InputIterator> + void + list<_Tp, _Alloc>:: + _M_assign_dispatch(_InputIterator __first2, _InputIterator __last2, + __false_type) + { + iterator __first1 = begin(); + iterator __last1 = end(); + for (; __first1 != __last1 && __first2 != __last2; + ++__first1, ++__first2) + *__first1 = *__first2; + if (__first2 == __last2) + erase(__first1, __last1); + else + insert(__last1, __first2, __last2); + } + template<typename _Tp, typename _Alloc> + void + list<_Tp, _Alloc>:: + remove(const value_type& __value) + { + iterator __first = begin(); + iterator __last = end(); + iterator __extra = __last; + while (__first != __last) + { + iterator __next = __first; + ++__next; + if (*__first == __value) + { + if (&*__first != &__value) + _M_erase(__first); + else + __extra = __first; + } + __first = __next; + } + if (__extra != __last) + _M_erase(__extra); + } + template<typename _Tp, typename _Alloc> + void + list<_Tp, _Alloc>:: + unique() + { + iterator __first = begin(); + iterator __last = end(); + if (__first == __last) + return; + iterator __next = __first; + while (++__next != __last) + { + if (*__first == *__next) + _M_erase(__next); + else + __first = __next; + __next = __first; + } + } + template<typename _Tp, typename _Alloc> + void + list<_Tp, _Alloc>:: + merge(list& __x) + { + if (this != &__x) + { + _M_check_equal_allocators(__x); + iterator __first1 = begin(); + iterator __last1 = end(); + iterator __first2 = __x.begin(); + iterator __last2 = __x.end(); + while (__first1 != __last1 && __first2 != __last2) + if (*__first2 < *__first1) + { + iterator __next = __first2; + _M_transfer(__first1, __first2, ++__next); + __first2 = __next; + } + else + ++__first1; + if (__first2 != __last2) + _M_transfer(__last1, __first2, __last2); + } + } + template<typename _Tp, typename _Alloc> + template <typename _StrictWeakOrdering> + void + list<_Tp, _Alloc>:: + merge(list& __x, _StrictWeakOrdering __comp) + { + if (this != &__x) + { + _M_check_equal_allocators(__x); + iterator __first1 = begin(); + iterator __last1 = end(); + iterator __first2 = __x.begin(); + iterator __last2 = __x.end(); + while (__first1 != __last1 && __first2 != __last2) + if (__comp(*__first2, *__first1)) + { + iterator __next = __first2; + _M_transfer(__first1, __first2, ++__next); + __first2 = __next; + } + else + ++__first1; + if (__first2 != __last2) + _M_transfer(__last1, __first2, __last2); + } + } + template<typename _Tp, typename _Alloc> + void + list<_Tp, _Alloc>:: + sort() + { + if (this->_M_impl._M_node._M_next != &this->_M_impl._M_node + && this->_M_impl._M_node._M_next->_M_next != &this->_M_impl._M_node) + { + list __carry; + list __tmp[64]; + list * __fill = &__tmp[0]; + list * __counter; + do + { + __carry.splice(__carry.begin(), *this, begin()); + for(__counter = &__tmp[0]; + __counter != __fill && !__counter->empty(); + ++__counter) + { + __counter->merge(__carry); + __carry.swap(*__counter); + } + __carry.swap(*__counter); + if (__counter == __fill) + ++__fill; + } + while ( !empty() ); + for (__counter = &__tmp[1]; __counter != __fill; ++__counter) + __counter->merge(*(__counter - 1)); + swap( *(__fill - 1) ); + } + } + template<typename _Tp, typename _Alloc> + template <typename _Predicate> + void + list<_Tp, _Alloc>:: + remove_if(_Predicate __pred) + { + iterator __first = begin(); + iterator __last = end(); + while (__first != __last) + { + iterator __next = __first; + ++__next; + if (__pred(*__first)) + _M_erase(__first); + __first = __next; + } + } + template<typename _Tp, typename _Alloc> + template <typename _BinaryPredicate> + void + list<_Tp, _Alloc>:: + unique(_BinaryPredicate __binary_pred) + { + iterator __first = begin(); + iterator __last = end(); + if (__first == __last) + return; + iterator __next = __first; + while (++__next != __last) + { + if (__binary_pred(*__first, *__next)) + _M_erase(__next); + else + __first = __next; + __next = __first; + } + } + template<typename _Tp, typename _Alloc> + template <typename _StrictWeakOrdering> + void + list<_Tp, _Alloc>:: + sort(_StrictWeakOrdering __comp) + { + if (this->_M_impl._M_node._M_next != &this->_M_impl._M_node + && this->_M_impl._M_node._M_next->_M_next != &this->_M_impl._M_node) + { + list __carry; + list __tmp[64]; + list * __fill = &__tmp[0]; + list * __counter; + do + { + __carry.splice(__carry.begin(), *this, begin()); + for(__counter = &__tmp[0]; + __counter != __fill && !__counter->empty(); + ++__counter) + { + __counter->merge(__carry, __comp); + __carry.swap(*__counter); + } + __carry.swap(*__counter); + if (__counter == __fill) + ++__fill; + } + while ( !empty() ); + for (__counter = &__tmp[1]; __counter != __fill; ++__counter) + __counter->merge(*(__counter - 1), __comp); + swap(*(__fill - 1)); + } + } +} +extern void foobarit(void); +class Game +{ +public: + struct BuildProject + { + int posX; + }; + std::list<BuildProject> buildProjects; +}; +static Game game; +static std::list<std::list<Game::BuildProject>::iterator> +erasableBuildProjects; +void *buildProjectSyncStepConcurrently(int id, int localTeam) +{ + __transaction_relaxed { + std::list<std::list<Game::BuildProject>::iterator>::iterator it += erasableBuildProjects.begin(); + foobarit(); + game.buildProjects.erase( (std::list<Game::BuildProject> +::iterator) *it); + } + return 0; +} + diff --git a/gcc/testsuite/g++.dg/tm/pr46646.C b/gcc/testsuite/g++.dg/tm/pr46646.C new file mode 100644 index 00000000000..9431615b0fb --- /dev/null +++ b/gcc/testsuite/g++.dg/tm/pr46646.C @@ -0,0 +1,890 @@ +// { dg-do compile } +// { dg-options "-fgnu-tm -O0"} + +namespace std __attribute__ ((__visibility__ ("default"))) { + template<class _T1, class _T2> + struct pair + { + typedef _T1 first_type; + typedef _T2 second_type; + _T1 first; + _T2 second; + pair() + : first(), second() { } + pair(const _T1& __a, const _T2& __b) + : first(__a), second(__b) { } + }; +} + + +typedef long int ptrdiff_t; +typedef __SIZE_TYPE__ size_t; +namespace std __attribute__ ((__visibility__ ("default"))) { + using ::ptrdiff_t; + using ::size_t; +} +namespace std __attribute__ ((__visibility__ ("default"))) { + struct input_iterator_tag { }; + struct output_iterator_tag { }; + struct forward_iterator_tag : public input_iterator_tag { }; + struct bidirectional_iterator_tag : public forward_iterator_tag { }; + struct random_access_iterator_tag : public bidirectional_iterator_tag { }; + template<typename _Category, typename _Tp, typename _Distance = ptrdiff_t, + typename _Pointer = _Tp*, typename _Reference = _Tp&> + struct iterator + { + typedef _Category iterator_category; + typedef _Tp value_type; + typedef _Distance difference_type; + typedef _Pointer pointer; + typedef _Reference reference; + }; + template<typename _Iterator> + struct iterator_traits + { + typedef typename _Iterator::iterator_category iterator_category; + typedef typename _Iterator::value_type value_type; + typedef typename _Iterator::difference_type difference_type; + typedef typename _Iterator::pointer pointer; + typedef typename _Iterator::reference reference; + }; + template<typename _Tp> + struct iterator_traits<_Tp*> + { + typedef random_access_iterator_tag iterator_category; + typedef _Tp value_type; + typedef ptrdiff_t difference_type; + typedef _Tp* pointer; + typedef _Tp& reference; + }; + template<typename _Tp> + struct iterator_traits<const _Tp*> + { + typedef random_access_iterator_tag iterator_category; + typedef _Tp value_type; + typedef ptrdiff_t difference_type; + typedef const _Tp* pointer; + typedef const _Tp& reference; + }; + template<typename _Iter> + inline typename iterator_traits<_Iter>::iterator_category + __iterator_category(const _Iter&) + { return typename iterator_traits<_Iter>::iterator_category(); } +} +namespace std __attribute__ ((__visibility__ ("default"))) { + template<typename _Iterator> + class reverse_iterator + : public iterator<typename iterator_traits<_Iterator>::iterator_category, + typename iterator_traits<_Iterator>::value_type, + typename iterator_traits<_Iterator>::difference_type, + typename iterator_traits<_Iterator>::pointer, + typename iterator_traits<_Iterator>::reference> + { + protected: + _Iterator current; + typedef iterator_traits<_Iterator> __traits_type; + public: + typedef _Iterator iterator_type; + typedef typename __traits_type::difference_type difference_type; + typedef typename __traits_type::pointer pointer; + typedef typename __traits_type::reference reference; + reverse_iterator() : current() { } + explicit + reverse_iterator(iterator_type __x) : current(__x) { } + reverse_iterator(const reverse_iterator& __x) + : current(__x.current) { } + template<typename _Iter> + reverse_iterator(const reverse_iterator<_Iter>& __x) + : current(__x.base()) { } + iterator_type + base() const + { return current; } + reference + operator*() const + { + _Iterator __tmp = current; + return *--__tmp; + } + pointer + operator->() const + { return &(operator*()); } + reverse_iterator& + operator++() + { + --current; + return *this; + } + reverse_iterator + operator++(int) + { + reverse_iterator __tmp = *this; + --current; + return __tmp; + } + reverse_iterator& + operator--() + { + ++current; + return *this; + } + reverse_iterator + operator--(int) + { + reverse_iterator __tmp = *this; + ++current; + return __tmp; + } + reverse_iterator + operator+(difference_type __n) const + { return reverse_iterator(current - __n); } + reverse_iterator& + operator+=(difference_type __n) + { + current -= __n; + return *this; + } + reverse_iterator + operator-(difference_type __n) const + { return reverse_iterator(current + __n); } + reverse_iterator& + operator-=(difference_type __n) + { + current += __n; + return *this; + } + reference + operator[](difference_type __n) const + { return *(*this + __n); } + }; +} + + + +extern "C++" { +namespace std +{ + class exception + { + public: + exception() throw() { } + virtual ~exception() throw(); + virtual const char* what() const throw(); + }; + class bad_exception : public exception + { + public: + bad_exception() throw() { } + virtual ~bad_exception() throw(); + virtual const char* what() const throw(); + }; + typedef void (*terminate_handler) (); + typedef void (*unexpected_handler) (); + terminate_handler set_terminate(terminate_handler) throw(); + void terminate() throw() __attribute__ ((__noreturn__)); + unexpected_handler set_unexpected(unexpected_handler) throw(); + void unexpected() __attribute__ ((__noreturn__)); + bool uncaught_exception() throw() __attribute__ ((__pure__)); +} +namespace __gnu_cxx __attribute__ ((__visibility__ ("default"))) { + void __verbose_terminate_handler(); +} +} +extern "C++" { +namespace std +{ + class bad_alloc : public exception + { + public: + bad_alloc() throw() { } + virtual ~bad_alloc() throw(); + virtual const char* what() const throw(); + }; + struct nothrow_t { }; + extern const nothrow_t nothrow; + typedef void (*new_handler)(); + new_handler set_new_handler(new_handler) throw(); +} + +void* operator new(std::size_t, const std::nothrow_t&) throw(); +void* operator new[](std::size_t, const std::nothrow_t&) throw(); +void operator delete(void*, const std::nothrow_t&) throw(); +void operator delete[](void*, const std::nothrow_t&) throw(); +inline void* operator new(std::size_t, void* __p) throw() { return __p; } +inline void* operator new[](std::size_t, void* __p) throw() { return __p; } +inline void operator delete (void*, void*) throw() { } +inline void operator delete[](void*, void*) throw() { } +} +namespace std __attribute__ ((__visibility__ ("default"))) { + void + __throw_bad_exception(void) __attribute__((__noreturn__)); + __attribute__((transaction_safe)) + void + __throw_bad_alloc(void) __attribute__((__noreturn__)); + void + __throw_bad_cast(void) __attribute__((__noreturn__)); + void + __throw_bad_typeid(void) __attribute__((__noreturn__)); + void + __throw_logic_error(const char*) __attribute__((__noreturn__)); + void + __throw_domain_error(const char*) __attribute__((__noreturn__)); + void + __throw_invalid_argument(const char*) __attribute__((__noreturn__)); + void + __throw_length_error(const char*) __attribute__((__noreturn__)); + void + __throw_out_of_range(const char*) __attribute__((__noreturn__)); + void + __throw_runtime_error(const char*) __attribute__((__noreturn__)); + void + __throw_range_error(const char*) __attribute__((__noreturn__)); + void + __throw_overflow_error(const char*) __attribute__((__noreturn__)); + void + __throw_underflow_error(const char*) __attribute__((__noreturn__)); + void + __throw_ios_failure(const char*) __attribute__((__noreturn__)); + void + __throw_system_error(int) __attribute__((__noreturn__)); + void + __throw_future_error(int) __attribute__((__noreturn__)); + void + __throw_bad_function_call() __attribute__((__noreturn__)); +} + + +namespace std __attribute__ ((__visibility__ ("default"))) { + template<typename _Tp> + inline void + swap(_Tp& __a, _Tp& __b) + { + + _Tp __tmp = (__a); + __a = (__b); + __b = (__tmp); + } + template<typename _Tp, size_t _Nm> + inline void + swap(_Tp (&__a)[_Nm], _Tp (&__b)[_Nm]) + { + for (size_t __n = 0; __n < _Nm; ++__n) + swap(__a[__n], __b[__n]); + } +} +namespace __gnu_cxx __attribute__ ((__visibility__ ("default"))) { + using std::size_t; + using std::ptrdiff_t; + template<typename _Tp> + class new_allocator + { + public: + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef _Tp* pointer; + typedef const _Tp* const_pointer; + typedef _Tp& reference; + typedef const _Tp& const_reference; + typedef _Tp value_type; + template<typename _Tp1> + struct rebind + { typedef new_allocator<_Tp1> other; }; + new_allocator() throw() { } + new_allocator(const new_allocator&) throw() { } + template<typename _Tp1> + new_allocator(const new_allocator<_Tp1>&) throw() { } + ~new_allocator() throw() { } + pointer + address(reference __x) const { return &__x; } + const_pointer + address(const_reference __x) const { return &__x; } + __attribute__((transaction_safe)) + pointer + allocate(size_type __n, const void* = 0) + { + if (__n > this->max_size()) + std::__throw_bad_alloc(); + return static_cast<_Tp*>(::operator new(__n * sizeof(_Tp))); + } +__attribute__((transaction_safe)) +void + deallocate(pointer __p, size_type) + { ::operator delete(__p); } + size_type + max_size() const throw() + { return size_t(-1) / sizeof(_Tp); } + void + construct(pointer __p, const _Tp& __val) + { ::new((void *)__p) _Tp(__val); } + void + destroy(pointer __p) { __p->~_Tp(); } + }; + template<typename _Tp> + inline bool + operator==(const new_allocator<_Tp>&, const new_allocator<_Tp>&) + { return true; } + template<typename _Tp> + inline bool + operator!=(const new_allocator<_Tp>&, const new_allocator<_Tp>&) + { return false; } +} +namespace std __attribute__ ((__visibility__ ("default"))) { + template<typename _Tp> + class allocator; + template<> + class allocator<void> + { + public: + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef void* pointer; + typedef const void* const_pointer; + typedef void value_type; + template<typename _Tp1> + struct rebind + { typedef allocator<_Tp1> other; }; + }; + template<typename _Tp> + class allocator: public __gnu_cxx::new_allocator<_Tp> + { + public: + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef _Tp* pointer; + typedef const _Tp* const_pointer; + typedef _Tp& reference; + typedef const _Tp& const_reference; + typedef _Tp value_type; + template<typename _Tp1> + struct rebind + { typedef allocator<_Tp1> other; }; + allocator() throw() { } + allocator(const allocator& __a) throw() + : __gnu_cxx::new_allocator<_Tp>(__a) { } + template<typename _Tp1> + allocator(const allocator<_Tp1>&) throw() { } + ~allocator() throw() { } + }; + template<typename _T1, typename _T2> + inline bool + operator==(const allocator<_T1>&, const allocator<_T2>&) + { return true; } + template<typename _Tp> + inline bool + operator==(const allocator<_Tp>&, const allocator<_Tp>&) + { return true; } + template<typename _T1, typename _T2> + inline bool + operator!=(const allocator<_T1>&, const allocator<_T2>&) + { return false; } + template<typename _Tp> + inline bool + operator!=(const allocator<_Tp>&, const allocator<_Tp>&) + { return false; } + //extern template class allocator<char>; + // extern template class allocator<wchar_t>; + template<typename _Alloc, bool = __is_empty(_Alloc)> + struct __alloc_swap + { static void _S_do_it(_Alloc&, _Alloc&) { } }; + template<typename _Alloc> + struct __alloc_swap<_Alloc, false> + { + static void + _S_do_it(_Alloc& __one, _Alloc& __two) + { + if (__one != __two) + swap(__one, __two); + } + }; + template<typename _Alloc, bool = __is_empty(_Alloc)> + struct __alloc_neq + { + static bool + _S_do_it(const _Alloc&, const _Alloc&) + { return false; } + }; + template<typename _Alloc> + struct __alloc_neq<_Alloc, false> + { + static bool + _S_do_it(const _Alloc& __one, const _Alloc& __two) + { return __one != __two; } + }; +} +namespace std __attribute__ ((__visibility__ ("default"))) { + template<typename _Arg, typename _Result> + struct unary_function + { + typedef _Arg argument_type; + typedef _Result result_type; + }; + template<typename _Arg1, typename _Arg2, typename _Result> + struct binary_function + { + typedef _Arg1 first_argument_type; + typedef _Arg2 second_argument_type; + typedef _Result result_type; + }; + template<typename _Tp> + struct equal_to : public binary_function<_Tp, _Tp, bool> + { + bool + operator()(const _Tp& __x, const _Tp& __y) const + { return __x == __y; } + }; + template<typename _Tp> + struct not_equal_to : public binary_function<_Tp, _Tp, bool> + { + bool + operator()(const _Tp& __x, const _Tp& __y) const + { return __x != __y; } + }; + template<typename _Tp> + struct greater : public binary_function<_Tp, _Tp, bool> + { + bool + operator()(const _Tp& __x, const _Tp& __y) const + { return __x > __y; } + }; + template<typename _Tp> + struct less : public binary_function<_Tp, _Tp, bool> + { + bool + operator()(const _Tp& __x, const _Tp& __y) const + { return __x < __y; } + }; + template<typename _Tp> + struct _Identity : public unary_function<_Tp,_Tp> + { + _Tp& + operator()(_Tp& __x) const + { return __x; } + const _Tp& + operator()(const _Tp& __x) const + { return __x; } + }; +} +namespace std __attribute__ ((__visibility__ ("default"))) { + enum _Rb_tree_color { _S_red = false, _S_black = true }; + struct _Rb_tree_node_base + { + typedef _Rb_tree_node_base* _Base_ptr; + typedef const _Rb_tree_node_base* _Const_Base_ptr; + _Rb_tree_color _M_color; + _Base_ptr _M_parent; + _Base_ptr _M_left; + _Base_ptr _M_right; + static _Base_ptr + _S_minimum(_Base_ptr __x) + { + while (__x->_M_left != 0) __x = __x->_M_left; + return __x; + } + static _Const_Base_ptr + _S_minimum(_Const_Base_ptr __x) + { + while (__x->_M_left != 0) __x = __x->_M_left; + return __x; + } + static _Base_ptr + _S_maximum(_Base_ptr __x) + { + while (__x->_M_right != 0) __x = __x->_M_right; + return __x; + } + static _Const_Base_ptr + _S_maximum(_Const_Base_ptr __x) + { + while (__x->_M_right != 0) __x = __x->_M_right; + return __x; + } + }; + template<typename _Val> + struct _Rb_tree_node : public _Rb_tree_node_base + { + typedef _Rb_tree_node<_Val>* _Link_type; + _Val _M_value_field; + }; + __attribute__ ((__pure__)) _Rb_tree_node_base* + _Rb_tree_increment(_Rb_tree_node_base* __x) throw (); + __attribute__ ((__pure__)) const _Rb_tree_node_base* + _Rb_tree_increment(const _Rb_tree_node_base* __x) throw (); + __attribute__ ((__pure__)) _Rb_tree_node_base* + _Rb_tree_decrement(_Rb_tree_node_base* __x) throw (); + __attribute__ ((__pure__)) const _Rb_tree_node_base* + _Rb_tree_decrement(const _Rb_tree_node_base* __x) throw (); + template<typename _Tp> + struct _Rb_tree_iterator + { + typedef _Tp value_type; + typedef _Tp& reference; + typedef _Tp* pointer; + typedef bidirectional_iterator_tag iterator_category; + typedef ptrdiff_t difference_type; + typedef _Rb_tree_iterator<_Tp> _Self; + typedef _Rb_tree_node_base::_Base_ptr _Base_ptr; + typedef _Rb_tree_node<_Tp>* _Link_type; + _Rb_tree_iterator() + : _M_node() { } + explicit + _Rb_tree_iterator(_Link_type __x) + : _M_node(__x) { } + reference + operator*() const + { return static_cast<_Link_type>(_M_node)->_M_value_field; } + pointer + operator->() const + { return &static_cast<_Link_type>(_M_node)->_M_value_field; } + _Self& + operator++() + { + _M_node = _Rb_tree_increment(_M_node); + return *this; + } + _Self + operator++(int) + { + _Self __tmp = *this; + _M_node = _Rb_tree_increment(_M_node); + return __tmp; + } + _Self& + operator--() + { + _M_node = _Rb_tree_decrement(_M_node); + return *this; + } + _Self + operator--(int) + { + _Self __tmp = *this; + _M_node = _Rb_tree_decrement(_M_node); + return __tmp; + } + bool + operator==(const _Self& __x) const + { return _M_node == __x._M_node; } + bool + operator!=(const _Self& __x) const + { return _M_node != __x._M_node; } + _Base_ptr _M_node; + }; + template<typename _Tp> + struct _Rb_tree_const_iterator + { + typedef _Tp value_type; + typedef const _Tp& reference; + typedef const _Tp* pointer; + typedef _Rb_tree_iterator<_Tp> iterator; + typedef bidirectional_iterator_tag iterator_category; + typedef ptrdiff_t difference_type; + typedef _Rb_tree_const_iterator<_Tp> _Self; + typedef _Rb_tree_node_base::_Const_Base_ptr _Base_ptr; + typedef const _Rb_tree_node<_Tp>* _Link_type; + _Rb_tree_const_iterator() + : _M_node() { } + explicit + _Rb_tree_const_iterator(_Link_type __x) + : _M_node(__x) { } + _Rb_tree_const_iterator(const iterator& __it) + : _M_node(__it._M_node) { } + reference + operator*() const + { return static_cast<_Link_type>(_M_node)->_M_value_field; } + pointer + operator->() const + { return &static_cast<_Link_type>(_M_node)->_M_value_field; } + _Self& + operator++() + { + _M_node = _Rb_tree_increment(_M_node); + return *this; + } + _Self + operator++(int) + { + _Self __tmp = *this; + _M_node = _Rb_tree_increment(_M_node); + return __tmp; + } + _Self& + operator--() + { + _M_node = _Rb_tree_decrement(_M_node); + return *this; + } + _Self + operator--(int) + { + _Self __tmp = *this; + _M_node = _Rb_tree_decrement(_M_node); + return __tmp; + } + bool + operator==(const _Self& __x) const + { return _M_node == __x._M_node; } + bool + operator!=(const _Self& __x) const + { return _M_node != __x._M_node; } + _Base_ptr _M_node; + }; + void + _Rb_tree_insert_and_rebalance(const bool __insert_left, + _Rb_tree_node_base* __x, + _Rb_tree_node_base* __p, + _Rb_tree_node_base& __header) throw (); + _Rb_tree_node_base* + _Rb_tree_rebalance_for_erase(_Rb_tree_node_base* const __z, + _Rb_tree_node_base& __header) throw (); + template<typename _Key, typename _Val, typename _KeyOfValue, + typename _Compare, typename _Alloc = allocator<_Val> > + class _Rb_tree + { + typedef typename _Alloc::template rebind<_Rb_tree_node<_Val> >::other + _Node_allocator; + protected: + typedef _Rb_tree_node_base* _Base_ptr; + typedef const _Rb_tree_node_base* _Const_Base_ptr; + public: + typedef _Key key_type; + typedef _Val value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef value_type& reference; + typedef const value_type& const_reference; + typedef _Rb_tree_node<_Val>* _Link_type; + typedef const _Rb_tree_node<_Val>* _Const_Link_type; + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef _Alloc allocator_type; + _Node_allocator& + _M_get_Node_allocator() + { return *static_cast<_Node_allocator*>(&this->_M_impl); } + const _Node_allocator& + _M_get_Node_allocator() const + { return *static_cast<const _Node_allocator*>(&this->_M_impl); } + allocator_type + get_allocator() const + { return allocator_type(_M_get_Node_allocator()); } + protected: + _Link_type + _M_get_node() + { return _M_impl._Node_allocator::allocate(1); } + __attribute__((transaction_safe)) + void + _M_put_node(_Link_type __p) + { _M_impl._Node_allocator::deallocate(__p, 1); } + __attribute__((transaction_safe)) + _Link_type + _M_create_node(const value_type& __x) + { + _Link_type __tmp = _M_get_node(); + try + { get_allocator().construct(&__tmp->_M_value_field, __x); } + catch(...) + { + _M_put_node(__tmp); + throw; + } + return __tmp; + } + void + _M_destroy_node(_Link_type __p) + { + get_allocator().destroy(&__p->_M_value_field); + _M_put_node(__p); + } + protected: + template<typename _Key_compare, + bool _Is_pod_comparator = __is_pod(_Key_compare)> + struct _Rb_tree_impl : public _Node_allocator + { + _Key_compare _M_key_compare; + _Rb_tree_node_base _M_header; + size_type _M_node_count; + _Rb_tree_impl() + : _Node_allocator(), _M_key_compare(), _M_header(), + _M_node_count(0) + { _M_initialize(); } + _Rb_tree_impl(const _Key_compare& __comp, const _Node_allocator& __a) + : _Node_allocator(__a), _M_key_compare(__comp), _M_header(), + _M_node_count(0) + { _M_initialize(); } + private: + void + _M_initialize() + { + this->_M_header._M_color = _S_red; + this->_M_header._M_parent = 0; + this->_M_header._M_left = &this->_M_header; + this->_M_header._M_right = &this->_M_header; + } + }; + _Rb_tree_impl<_Compare> _M_impl; + protected: + _Base_ptr& + _M_root() + { return this->_M_impl._M_header._M_parent; } + _Const_Base_ptr + _M_root() const + { return this->_M_impl._M_header._M_parent; } + _Base_ptr& + _M_leftmost() + { return this->_M_impl._M_header._M_left; } + _Const_Base_ptr + _M_leftmost() const + { return this->_M_impl._M_header._M_left; } + _Base_ptr& + _M_rightmost() + { return this->_M_impl._M_header._M_right; } + _Const_Base_ptr + _M_rightmost() const + { return this->_M_impl._M_header._M_right; } + _Link_type + _M_begin() + { return static_cast<_Link_type>(this->_M_impl._M_header._M_parent); } + _Const_Link_type + _M_begin() const + { + return static_cast<_Const_Link_type> + (this->_M_impl._M_header._M_parent); + } + _Link_type + _M_end() + { return static_cast<_Link_type>(&this->_M_impl._M_header); } + _Const_Link_type + _M_end() const + { return static_cast<_Const_Link_type>(&this->_M_impl._M_header); } + static const_reference + _S_value(_Const_Link_type __x) + { return __x->_M_value_field; } + static const _Key& + _S_key(_Const_Link_type __x) + { return _KeyOfValue()(_S_value(__x)); } + static _Link_type + _S_left(_Base_ptr __x) + { return static_cast<_Link_type>(__x->_M_left); } + static _Const_Link_type + _S_left(_Const_Base_ptr __x) + { return static_cast<_Const_Link_type>(__x->_M_left); } + static _Link_type + _S_right(_Base_ptr __x) + { return static_cast<_Link_type>(__x->_M_right); } + static _Const_Link_type + _S_right(_Const_Base_ptr __x) + { return static_cast<_Const_Link_type>(__x->_M_right); } + static const_reference + _S_value(_Const_Base_ptr __x) + { return static_cast<_Const_Link_type>(__x)->_M_value_field; } + static const _Key& + _S_key(_Const_Base_ptr __x) + { return _KeyOfValue()(_S_value(__x)); } + public: + typedef _Rb_tree_iterator<value_type> iterator; + typedef _Rb_tree_const_iterator<value_type> const_iterator; + typedef std::reverse_iterator<iterator> reverse_iterator; + typedef std::reverse_iterator<const_iterator> const_reverse_iterator; + private: + iterator + _M_insert_(_Const_Base_ptr __x, _Const_Base_ptr __y, + const value_type& __v); + public: + _Rb_tree() { } + iterator + begin() + { + return iterator(static_cast<_Link_type> + (this->_M_impl._M_header._M_left)); + } + const_iterator + begin() const + { + return const_iterator(static_cast<_Const_Link_type> + (this->_M_impl._M_header._M_left)); + } + iterator + end() + { return iterator(static_cast<_Link_type>(&this->_M_impl._M_header)); } + const_iterator + end() const + { + return const_iterator(static_cast<_Const_Link_type> + (&this->_M_impl._M_header)); + } + pair<iterator, bool> + _M_insert_unique(const value_type& __x); + }; + template<typename _Key, typename _Val, typename _KeyOfValue, + typename _Compare, typename _Alloc> + typename _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator + _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: + _M_insert_(_Const_Base_ptr __x, _Const_Base_ptr __p, const _Val& __v) + { + _Link_type __z = _M_create_node(__v); + return iterator(__z); + } + template<typename _Key, typename _Val, typename _KeyOfValue, + typename _Compare, typename _Alloc> + pair<typename _Rb_tree<_Key, _Val, _KeyOfValue, + _Compare, _Alloc>::iterator, bool> + _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: + _M_insert_unique(const _Val& __v) + { + _Link_type __x = _M_begin(); + _Link_type __y = _M_end(); + iterator __j = iterator(__y); + return pair<iterator, bool>(_M_insert_(__x, __y, __v), true); + } +} +namespace std __attribute__ ((__visibility__ ("default"))) { + template<typename _Key, typename _Compare = std::less<_Key>, + typename _Alloc = std::allocator<_Key> > + class set + { + public: + typedef _Key key_type; + typedef _Key value_type; + typedef _Compare key_compare; + typedef _Compare value_compare; + typedef _Alloc allocator_type; + private: + typedef typename _Alloc::template rebind<_Key>::other _Key_alloc_type; + typedef _Rb_tree<key_type, value_type, _Identity<value_type>, + key_compare, _Key_alloc_type> _Rep_type; + _Rep_type _M_t; + public: + typedef typename _Key_alloc_type::pointer pointer; + typedef typename _Key_alloc_type::const_pointer const_pointer; + typedef typename _Key_alloc_type::reference reference; + typedef typename _Key_alloc_type::const_reference const_reference; + typedef typename _Rep_type::const_iterator iterator; + typedef typename _Rep_type::const_iterator const_iterator; + typedef typename _Rep_type::const_reverse_iterator reverse_iterator; + typedef typename _Rep_type::const_reverse_iterator const_reverse_iterator; + typedef typename _Rep_type::size_type size_type; + typedef typename _Rep_type::difference_type difference_type; + std::pair<iterator, bool> + insert(const value_type& __x) + { + _M_t._M_insert_unique(__x); + } + }; +} +__attribute__((transaction_pure)) +void* operator new(size_t); +__attribute__((transaction_pure)) +void operator delete(void*); +class Widget +{ +private: +}; +class Screen +{ +protected: +std::set<Widget *> widgets; +public: +void addWidget(Widget* widget); +}; +void Screen::addWidget(Widget* widget) +{ +widgets.insert(widget); +} diff --git a/gcc/testsuite/g++.dg/tm/pr46653.C b/gcc/testsuite/g++.dg/tm/pr46653.C new file mode 100644 index 00000000000..f8f3a1d3117 --- /dev/null +++ b/gcc/testsuite/g++.dg/tm/pr46653.C @@ -0,0 +1,18 @@ +// { dg-do compile } +// { dg-options "-fgnu-tm -O" } + +class shared_count +{ +public: + volatile int j; + shared_count() : j(0) { } +}; + +shared_count * c; +int main() +{ + __transaction_atomic { + shared_count sc; + } + return 0; +} diff --git a/gcc/testsuite/g++.dg/tm/pr46714.C b/gcc/testsuite/g++.dg/tm/pr46714.C new file mode 100644 index 00000000000..130b58cdd99 --- /dev/null +++ b/gcc/testsuite/g++.dg/tm/pr46714.C @@ -0,0 +1,14 @@ +// { dg-do compile } +// { dg-options "-fgnu-tm -O" } + +static int asdf __attribute__ ((__weakref__("funky"))); + +class Building +{ +public: + __attribute__((transaction_safe)) ~Building(void); +}; + +Building::~Building() +{ +} diff --git a/gcc/testsuite/g++.dg/tm/pr46941.C b/gcc/testsuite/g++.dg/tm/pr46941.C new file mode 100644 index 00000000000..eac54383138 --- /dev/null +++ b/gcc/testsuite/g++.dg/tm/pr46941.C @@ -0,0 +1,37 @@ +// { dg-do "compile" } +// { dg-options "-fgnu-tm" } + +class Obj +{ + int dummy; +}; + +__attribute__((transaction_safe)) +Obj* allocate() +{ + return new Obj; +} + +__attribute__((transaction_safe)) +void deallocate(Obj * o) +{ + delete o; +} + +__attribute__((transaction_safe)) +Obj* allocatearray() +{ + return new Obj[2]; +} + +__attribute__((transaction_safe)) +void deallocatearray(Obj *o[]) +{ + delete [] o; +} + +/* The delete/new operators are handled by the libitm runtime. */ +/* { dg-final { scan-assembler "_ZGTtnw\[mj\]" } } */ +/* { dg-final { scan-assembler "_ZGTtna\[mj\]" } } */ +/* { dg-final { scan-assembler "_ZGTtdlPv" } } */ +/* { dg-final { scan-assembler "_ZGTtdaPv" } } */ diff --git a/gcc/testsuite/g++.dg/tm/pr47340.C b/gcc/testsuite/g++.dg/tm/pr47340.C new file mode 100644 index 00000000000..ead3361fae2 --- /dev/null +++ b/gcc/testsuite/g++.dg/tm/pr47340.C @@ -0,0 +1,11 @@ +// { dg-do compile } +// { dg-options "-fgnu-tm" } + +void* operator new(__SIZE_TYPE__) throw (int); + +void *point; + +void funky() +{ + point = new (int); +} diff --git a/gcc/testsuite/g++.dg/tm/pr47530.C b/gcc/testsuite/g++.dg/tm/pr47530.C new file mode 100644 index 00000000000..8e7e27297ce --- /dev/null +++ b/gcc/testsuite/g++.dg/tm/pr47530.C @@ -0,0 +1,79 @@ +// { dg-do compile } +// { dg-options "-fgnu-tm -O2 -fdump-tree-optimized" } + +typedef __SIZE_TYPE__ size_t; +extern void *malloc(size_t); + +namespace bench +{ + class LLNode + { + LLNode* next; + int data; + + public: + __attribute__((transaction_safe)) + LLNode(int val, LLNode* m_next) + { + data = val; + next = m_next; + } + __attribute__((transaction_safe)) + ~LLNode(){} + __attribute__((transaction_safe)) + int get_val() {return data;} + __attribute__((transaction_safe)) + LLNode* get_next() {return next;} + __attribute__((transaction_safe)) + void set_val(int val) {data = val;} + __attribute__((transaction_safe)) + void set_next(LLNode* n) {next = n;} + __attribute__((transaction_safe)) + void *operator new(size_t size); + }; + + class LinkedList + { + LLNode* head; + public: + LinkedList(); + void insert(int val); + }; +} + +using bench::LinkedList; +using bench::LLNode; + + +__attribute__((transaction_safe)) +void* LLNode::operator new(size_t size) +{ + return malloc(size); +} + +LinkedList::LinkedList() : head(new LLNode(-1, 0)) { } + +void LinkedList::insert(int val) +{ + __transaction_atomic { + LLNode* prev = head; + LLNode* curr = head->get_next(); + + while (curr != 0) { + if (curr->get_val() >= val) + break; + prev = curr; + curr = prev->get_next(); + } + + if (!curr || (curr->get_val() > val)){ + LLNode* tmp = new LLNode(val,curr); + prev->set_next(tmp); + } + } +} + +// Make sure we don't do tail optimization on the commit. +// { dg-final { scan-tree-dump-times "commitTransaction...; .tail call" 0 "optimized" } } +// { dg-final { cleanup-tree-dump "optimized" } } + diff --git a/gcc/testsuite/g++.dg/tm/pr47554.C b/gcc/testsuite/g++.dg/tm/pr47554.C new file mode 100644 index 00000000000..28841bb15ad --- /dev/null +++ b/gcc/testsuite/g++.dg/tm/pr47554.C @@ -0,0 +1,27 @@ +// { dg-do compile } +// { dg-options "-fgnu-tm" } + +class list +{ + public: list() + { + } + list(const list&) + { + } + const list& _M_get_Node_allocator() const + { + } + list _M_get_Tp_allocator() const + { + return list(_M_get_Node_allocator()); + } +}; +static list buildProjects; +static void build() +{ + __transaction_relaxed + { + buildProjects._M_get_Tp_allocator(); + } +} diff --git a/gcc/testsuite/g++.dg/tm/pr47573.C b/gcc/testsuite/g++.dg/tm/pr47573.C new file mode 100644 index 00000000000..239d9222e8e --- /dev/null +++ b/gcc/testsuite/g++.dg/tm/pr47573.C @@ -0,0 +1,25 @@ +// { dg-do compile } +// { dg-options "-fgnu-tm" } + +template<typename _Tp> class allocator +{ + public: + allocator() { } +}; +extern template class allocator<char>; + +template<typename _Alloc = allocator<char> > class basic_string +{ + public: + _Alloc _M_dataplus; + + __attribute__((transaction_safe)) + basic_string() : _M_dataplus(_Alloc()) + { + } +}; + +int getStringHeight() +{ + basic_string<> tmp; +} diff --git a/gcc/testsuite/g++.dg/tm/pr47746.C b/gcc/testsuite/g++.dg/tm/pr47746.C new file mode 100644 index 00000000000..7cd9e1006d1 --- /dev/null +++ b/gcc/testsuite/g++.dg/tm/pr47746.C @@ -0,0 +1,27 @@ +// { dg-do compile } +// { dg-options "-fgnu-tm" } + +class InputStream +{ + public: + virtual unsigned int readUint32 () = 0; +}; + +class Building +{ + public: + __attribute__((transaction_safe)) Building (InputStream *stream); + __attribute__((transaction_safe)) void freeGradients (); + void load (InputStream *stream); +}; + +Building::Building (InputStream *stream) +{ + load(stream); +} + +void Building::load (InputStream *stream) +{ + int j = (int)stream->readUint32 (); + freeGradients (); +} diff --git a/gcc/testsuite/g++.dg/tm/template-1.C b/gcc/testsuite/g++.dg/tm/template-1.C new file mode 100644 index 00000000000..b93828a1dc3 --- /dev/null +++ b/gcc/testsuite/g++.dg/tm/template-1.C @@ -0,0 +1,35 @@ +// { dg-do compile } +// { dg-options "-fgnu-tm -O -fdump-tree-tmmark" } + +struct TrueFalse +{ + static bool v() { return true; } +}; + +int global; + +template<typename T> int foo() +{ + __transaction_atomic { global += 2; } + return __transaction_atomic (global + 1); +} + +template<typename T> int bar() __transaction_atomic +{ + return global + 3; +} + +template<typename T> void bar2() __transaction_atomic +{ + global += 4; +} + +int f1() +{ + bar2<TrueFalse>(); + return foo<TrueFalse>() + bar<TrueFalse>(); +} + +/* 4 transactions overall, two of the write to global: */ +/* { dg-final { scan-tree-dump-times "ITM_RU4\\s*\\(&global" 4 "tmmark" } } */ +/* { dg-final { scan-tree-dump-times "ITM_WU4\\s*\\(&global" 2 "tmmark" } } */ diff --git a/gcc/testsuite/g++.dg/tm/tm.exp b/gcc/testsuite/g++.dg/tm/tm.exp new file mode 100644 index 00000000000..d8c76fe1e88 --- /dev/null +++ b/gcc/testsuite/g++.dg/tm/tm.exp @@ -0,0 +1,39 @@ +# Copyright (C) 2009, 2011 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GCC; see the file COPYING3. If not see +# <http://www.gnu.org/licenses/>. + +# GCC testsuite that uses the `dg.exp' driver. + +# Load support procs. +load_lib g++-dg.exp + +# If a testcase doesn't have special options, use these. +global DEFAULT_CXXFLAGS +if ![info exists DEFAULT_CXXFLAGS] then { + set DEFAULT_CXXFLAGS " -ansi -pedantic-errors -Wno-long-long" +} + +# Initialize `dg'. +dg-init + +# Run the tests that are shared with C. +dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/tm/*.c]] \ + "" $DEFAULT_CXXFLAGS +# Run the C++ only tests. +dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.C]] \ + "" $DEFAULT_CXXFLAGS + +# All done. +dg-finish diff --git a/gcc/testsuite/g++.dg/tm/vector-1.C b/gcc/testsuite/g++.dg/tm/vector-1.C new file mode 100644 index 00000000000..2c5bb39f7ed --- /dev/null +++ b/gcc/testsuite/g++.dg/tm/vector-1.C @@ -0,0 +1,15 @@ +// { dg-do compile } +// { dg-options "-fgnu-tm -O3" } + +class HashTree +{ + __attribute__((transaction_safe)) void rehash(); + HashTree **Hash_table; + int Hash_function; +}; + +__attribute__((transaction_safe)) void HashTree::rehash() +{ + for (int i=0; i < Hash_function; i++) + Hash_table[i] = 0; +} diff --git a/gcc/testsuite/g++.dg/tm/wrap-2.C b/gcc/testsuite/g++.dg/tm/wrap-2.C new file mode 100644 index 00000000000..564fbf87e1b --- /dev/null +++ b/gcc/testsuite/g++.dg/tm/wrap-2.C @@ -0,0 +1,16 @@ +/* { dg-do compile } */ +/* { dg-options "-fgnu-tm" } */ + +#define W(X) __attribute__((transaction_wrap(X))) +void f1(void); +void f2(int); +int i3; +int f7(void); + +void g1(void) W(f1); +void g2(void) W(f2); /* { dg-error "is not compatible" } */ +void g3(void) W(i3); /* { dg-error "is not a function" } */ +void g4(void) W(f4); /* { dg-error "not declared in this scope\|not an identifier" } */ +void g5(void) W(1); /* { dg-error "not an identifier" } */ +void g6(void) W("f1"); /* { dg-error "not an identifier" } */ +void g7(void) W(f7); /* { dg-error "is not compatible" } */ diff --git a/gcc/testsuite/gcc.dg/tm/20091013.c b/gcc/testsuite/gcc.dg/tm/20091013.c new file mode 100644 index 00000000000..d9b3b0ed3bc --- /dev/null +++ b/gcc/testsuite/gcc.dg/tm/20091013.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-options "-fgnu-tm -O2" } */ + +extern long ringo(long int); +int g,i; + +f() +{ + __transaction_relaxed { + for (i=0; i < 10; ++i) + ringo(g); + } +} diff --git a/gcc/testsuite/gcc.dg/tm/20091221.c b/gcc/testsuite/gcc.dg/tm/20091221.c new file mode 100644 index 00000000000..1d75d153a2c --- /dev/null +++ b/gcc/testsuite/gcc.dg/tm/20091221.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-options "-fgnu-tm -fdump-tree-tmedge" } */ + +int i; +extern void virgin () __attribute__((transaction_pure)); + +foo() +{ + __transaction_atomic { + virgin(i); + } +} + +/* { dg-final { scan-tree-dump-times "readOnly" 1 "tmedge" } } */ +/* { dg-final { cleanup-tree-dump "tmedge" } } */ diff --git a/gcc/testsuite/gcc.dg/tm/20100125.c b/gcc/testsuite/gcc.dg/tm/20100125.c new file mode 100644 index 00000000000..3f1dd10fea2 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tm/20100125.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-options "-fgnu-tm -O -fdump-tree-tmmark" } */ + +/* Test that the call to george() doesn't end up inside the transaction. */ + +int trxn; + +void set_remove(int * val) +{ + __transaction_atomic { + trxn = 5; + } + george(); +} + +/* { dg-final { scan-tree-dump-times "getTMCloneOrIrrevocable" 0 "tmmark" } } */ +/* { dg-final { cleanup-tree-dump "tmmark" } } */ diff --git a/gcc/testsuite/gcc.dg/tm/20100519.c b/gcc/testsuite/gcc.dg/tm/20100519.c new file mode 100644 index 00000000000..009b7901a39 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tm/20100519.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-options "-fgnu-tm -O" } */ + +typedef struct coordinate { + double x; +} coordinate_t; + +coordinate_t elementPtrC[3]; + +__attribute__((transaction_safe)) +void TMelement_alloc (coordinate_t* coordinates, int numCoordinate) +{ + int i; + for (i = 0; i < numCoordinate; i++) { + elementPtrC[i] = coordinates[i]; + } +} diff --git a/gcc/testsuite/gcc.dg/tm/20100524-2.c b/gcc/testsuite/gcc.dg/tm/20100524-2.c new file mode 100644 index 00000000000..a3578cb2797 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tm/20100524-2.c @@ -0,0 +1,20 @@ +/* { dg-do compile } */ +/* { dg-options "-fgnu-tm -O0" } */ + +typedef struct { + int value[5]; +} type_t; + +__attribute__((transaction_safe)) +type_t func_move (); + +__attribute__((transaction_safe)) +type_t func_push (int type) +{ + type_t trace; + + if (type == 9) + trace = func_move(); + + return trace; +} diff --git a/gcc/testsuite/gcc.dg/tm/20100603.c b/gcc/testsuite/gcc.dg/tm/20100603.c new file mode 100644 index 00000000000..3061063394d --- /dev/null +++ b/gcc/testsuite/gcc.dg/tm/20100603.c @@ -0,0 +1,21 @@ +/* { dg-do compile } */ +/* { dg-options "-fgnu-tm -O -fdump-tree-optimized" } */ + +int jj; + +__attribute__((transaction_safe)) +static void poof () +{ + if (jj) + return; + poof(); +} + +__attribute__((transaction_safe)) +void TMlist_free () +{ + poof(); +} + +/* { dg-final { scan-tree-dump-times "Function poof ._ZGTt4poof" 1 "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tm/20100609.c b/gcc/testsuite/gcc.dg/tm/20100609.c new file mode 100644 index 00000000000..760f81ec6dd --- /dev/null +++ b/gcc/testsuite/gcc.dg/tm/20100609.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-options "-fgnu-tm -O" } */ + +extern void funcNoReturn() __attribute__ ((__noreturn__)); + +int later; + +void MyFunc() +{ + __transaction_relaxed { + funcNoReturn(); + later=8; + } +} diff --git a/gcc/testsuite/gcc.dg/tm/20100610.c b/gcc/testsuite/gcc.dg/tm/20100610.c new file mode 100644 index 00000000000..0985b9ebc23 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tm/20100610.c @@ -0,0 +1,90 @@ +/* { dg-do compile } */ +/* { dg-options "-fgnu-tm -O3" } */ + +/* The function calculateCircumCircle() should get inlined into the TM + clone for TMelement_alloc(), so we don't need to generate a TM + clone for calculateCircumCircle(). We also don't need to put its + entry into the clone table since it's static. */ + +/* { dg-final { scan-assembler-not "ZGTt21calculateCircumCircle" } } */ + +extern double sqrt(double) __attribute__((transaction_pure)); +extern void *xmalloc(int) __attribute__((transaction_safe)); + +typedef struct coordinate { + double x; + double y; +} coordinate_t; +typedef struct element { + coordinate_t coordinates[3]; + long numCoordinate; + coordinate_t circumCenter; + double circumRadius; +} element_t; + +__attribute__((transaction_safe)) +double +coordinate_distance (coordinate_t* coordinatePtr, coordinate_t* aPtr) +{ + return sqrt( coordinatePtr->x ); +} + +__attribute__((transaction_safe)) +static void +calculateCircumCircle (element_t* elementPtr) +{ + long numCoordinate = elementPtr->numCoordinate; + coordinate_t* coordinates = elementPtr->coordinates; + coordinate_t* circumCenterPtr = &elementPtr->circumCenter; + ((void) (0)); + if (numCoordinate == 2) { + circumCenterPtr->x = (coordinates[0].x + coordinates[1].x) / 2.0; + circumCenterPtr->y = (coordinates[0].y + coordinates[1].y) / 2.0; + } + else { + double ax = coordinates[0].x; + double ay = coordinates[0].y; + double bx = coordinates[1].x; + double by = coordinates[1].y; + double cx = coordinates[2].x; + double cy = coordinates[2].y; + double bxDelta = bx - ax; + double byDelta = by - ay; + double cxDelta = cx - ax; + double cyDelta = cy - ay; + double bDistance2 = (bxDelta * bxDelta) + (byDelta * byDelta); + double cDistance2 = (cxDelta * cxDelta) + (cyDelta * cyDelta); + double xNumerator = (byDelta * cDistance2) - (cyDelta * bDistance2); + double yNumerator = (bxDelta * cDistance2) - (cxDelta * bDistance2); + double denominator = 2 * ((bxDelta * cyDelta) - (cxDelta * byDelta)); + double rx = ax - (xNumerator / denominator); + double ry = ay + (yNumerator / denominator); + circumCenterPtr->x = rx; + circumCenterPtr->y = ry; + } + elementPtr->circumRadius = coordinate_distance(circumCenterPtr, + &coordinates[0]); +} + +element_t* +element_alloc (coordinate_t* coordinates, long numCoordinate) +{ + element_t* elementPtr; + elementPtr = (element_t*)xmalloc(sizeof(element_t)); + if (elementPtr) { + calculateCircumCircle(elementPtr); + } + return elementPtr; +} + +__attribute__((transaction_safe)) +element_t* +TMelement_alloc (coordinate_t* coordinates, long numCoordinate) +{ + element_t* elementPtr; + elementPtr = (element_t*)xmalloc(sizeof(element_t)); + if (elementPtr) { + calculateCircumCircle(elementPtr); + } + return elementPtr; +} diff --git a/gcc/testsuite/gcc.dg/tm/20100615-2.c b/gcc/testsuite/gcc.dg/tm/20100615-2.c new file mode 100644 index 00000000000..4341e7d35ea --- /dev/null +++ b/gcc/testsuite/gcc.dg/tm/20100615-2.c @@ -0,0 +1,19 @@ +/* { dg-do compile } */ +/* { dg-options "-fgnu-tm -O" } */ + +__attribute__((transaction_safe)) +void Info_RemoveKey (char *s) +{ + char *o = 0; + while (1) + { + s++; + while (*s) + { + if (!*s) + return; + *o++ = *s++; + } + *o = 0; + } +} diff --git a/gcc/testsuite/gcc.dg/tm/20100615.c b/gcc/testsuite/gcc.dg/tm/20100615.c new file mode 100644 index 00000000000..3d9e4684e5d --- /dev/null +++ b/gcc/testsuite/gcc.dg/tm/20100615.c @@ -0,0 +1,42 @@ +/* { dg-do compile } */ +/* { dg-options "-fgnu-tm -O" } */ + +/* Since the non TM version of new_node() gets optimized away, it + shouldn't appear in the clone table either. */ +/* { dg-final { scan-assembler-not "tm_clone_table" } } */ + +#define NULL 0 +extern void *malloc (__SIZE_TYPE__); + +__attribute__((transaction_pure)) +void exit(int status); + +typedef struct node { +} node_t; + +__attribute__((transaction_safe)) +static node_t *new_node(node_t *next) +{ + node_t *node; + node = (node_t *)malloc(sizeof(node_t)); + if (node == NULL) { + exit(1); + } + return NULL; +} + +static node_t *set_new() +{ + node_t *min, *max; + __transaction_atomic { + max = new_node(NULL); + min = new_node(max); + } + return min; +} + +int main(int argc, char **argv) +{ + set_new(); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/tm/20110216.c b/gcc/testsuite/gcc.dg/tm/20110216.c new file mode 100644 index 00000000000..22edae0fb4c --- /dev/null +++ b/gcc/testsuite/gcc.dg/tm/20110216.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-options "-fgnu-tm" } */ + +int george; + +__attribute__((transaction_callable)) +void q1() +{ + __transaction_atomic { + george=999; + } + q1(); +} + +/* { dg-final { scan-assembler-not "_ITM_getTMCloneOrIrrevocable" } } */ diff --git a/gcc/testsuite/gcc.dg/tm/alias-1.c b/gcc/testsuite/gcc.dg/tm/alias-1.c new file mode 100644 index 00000000000..364aa714086 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tm/alias-1.c @@ -0,0 +1,40 @@ +/* { dg-do compile } */ +/* { dg-options "-fgnu-tm -fdump-tree-ealias -O" } */ + +typedef __UINTPTR_TYPE__ ptrcast; + +#if (__SIZEOF_POINTER__ == 4) +#define TM_LOAD __builtin__ITM_RU4 +#define TM_STORE __builtin__ITM_WU4 +#elif (__SIZEOF_POINTER__ == 8) +#define TM_LOAD __builtin__ITM_RU8 +#define TM_STORE __builtin__ITM_WU8 +#else +#error Add target support here +#endif + +struct mystruct_type { + ptrcast *ptr; +} *mystruct; + +ptrcast *someptr, **pp; +ptrcast ui; + +void f(void) +{ + __transaction_atomic { + ui = TM_LOAD (&mystruct); + mystruct = (struct mystruct_type *) ui; + ui = TM_LOAD (&someptr); + someptr = (ptrcast *) ui; + ui = (ptrcast) someptr; + pp = &mystruct->ptr; + TM_STORE (pp, ui); + } +} + +/* { dg-final { scan-tree-dump-times "mystruct = \{ .*ESCAPED" 1 "ealias" } } */ +/* { dg-final { scan-tree-dump-times "someptr = same as mystruct" 1 "ealias" { xfail *-*-* } } } */ +/* { dg-final { scan-tree-dump-times "ui\..* = same as mystruct" 1 "ealias" { xfail *-*-* } } } */ +/* { dg-final { scan-tree-dump-times "pp\..* = same as mystruct" 1 "ealias" { xfail *-*-* } } } */ +/* { dg-final { cleanup-tree-dump "ealias" } } */ diff --git a/gcc/testsuite/gcc.dg/tm/alias-2.c b/gcc/testsuite/gcc.dg/tm/alias-2.c new file mode 100644 index 00000000000..761a99c2ab0 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tm/alias-2.c @@ -0,0 +1,42 @@ +/* { dg-do compile } */ +/* { dg-options "-fgnu-tm -fdump-tree-ealias -O" } */ + +typedef __UINTPTR_TYPE__ ptrcast; + +#if (__SIZEOF_POINTER__ == 4) +#define TM_LOAD __builtin__ITM_RU4 +#define TM_STORE __builtin__ITM_WU4 +#elif (__SIZEOF_POINTER__ == 8) +#define TM_LOAD __builtin__ITM_RU8 +#define TM_STORE __builtin__ITM_WU8 +#else +#error Add target support here +#endif + +void candy (); + +struct mystruct_type { + ptrcast *ptr; +} *mystruct, *mystruct2; + +ptrcast *someptr, **pp; +ptrcast ui; + +void tootsie_roll () __attribute__((transaction_wrap (candy))); +void tootsie_roll () +{ + ui = TM_LOAD (&mystruct); + mystruct2 = (struct mystruct_type *) ui; + + pp = &mystruct2->ptr; +} + +void foo() +{ + candy(); +} + +/* { dg-final { scan-tree-dump-times "ui\..* = same as mystruct" 1 "ealias" { xfail *-*-* } } } */ +/* { dg-final { scan-tree-dump-times "mystruct.*ESCAPED" 1 "ealias" } } */ +/* { dg-final { scan-tree-dump-times "pp = same as mystruct" 1 "ealias" { xfail *-*-* } } } */ +/* { dg-final { cleanup-tree-dump "ealias" } } */ diff --git a/gcc/testsuite/gcc.dg/tm/data-1.c b/gcc/testsuite/gcc.dg/tm/data-1.c new file mode 100644 index 00000000000..16061476e08 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tm/data-1.c @@ -0,0 +1,48 @@ +/* { dg-do compile } */ +/* { dg-options "-fgnu-tm" } */ +/* Test read and write on all basic types. */ + +static char gc; +static signed char gsc; +static unsigned char guc; + +static short gs; +static unsigned short gus; + +static int gi; +static unsigned int gui; + +static long gl; +static unsigned long gul; + +static long long gll; +static unsigned long long gull; + +static float gf; +static double gd; +static long double gld; + +void f(void) +{ + __transaction_atomic { + gc++; + gsc++; + guc++; + + gs++; + gus++; + + gi++; + gui++; + + gl++; + gul++; + + gll++; + gull++; + + gf++; + gd++; + gld++; + } +} diff --git a/gcc/testsuite/gcc.dg/tm/data-2.c b/gcc/testsuite/gcc.dg/tm/data-2.c new file mode 100644 index 00000000000..3e2a604bfb3 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tm/data-2.c @@ -0,0 +1,22 @@ +/* { dg-do compile } */ +/* { dg-options "-fgnu-tm" } */ +/* Test read and write on all basic types. */ + +struct S +{ + int x[10]; +}; + +static struct S g; + +extern void fill (struct S *); + +void f(void) +{ + struct S l; + fill(&l); + + __transaction_atomic { + g = l; + } +} diff --git a/gcc/testsuite/gcc.dg/tm/debug-1.c b/gcc/testsuite/gcc.dg/tm/debug-1.c new file mode 100644 index 00000000000..fae5d6bed42 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tm/debug-1.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-options "-fgnu-tm -O0 -fdump-tree-tmmark-lineno" } */ + +/* Test that instrumented statements have correct location info. */ + +int a,b, c, z; + +testing(){ + c=9; +} + +main() { + b = 9898; + __transaction_relaxed { + z = c; + a = 888; + testing(); + } + return 0; +} + +/* { dg-final { scan-tree-dump-times ": 13:.*b = 9898" 1 "tmmark" } } */ +/* { dg-final { scan-tree-dump-times ": 14:.*__transaction" 1 "tmmark" } } */ +/* { dg-final { scan-tree-dump-times ": 15:.*ITM_WU. \\(&z" 1 "tmmark" } } */ +/* { dg-final { scan-tree-dump-times ": 16:.*ITM_WU. \\(&a" 1 "tmmark" } } */ +/* { dg-final { cleanup-tree-dump "tmmark" } } */ diff --git a/gcc/testsuite/gcc.dg/tm/indirect-1.c b/gcc/testsuite/gcc.dg/tm/indirect-1.c new file mode 100644 index 00000000000..eade848bd8b --- /dev/null +++ b/gcc/testsuite/gcc.dg/tm/indirect-1.c @@ -0,0 +1,9 @@ +/* { dg-do compile } */ +/* { dg-options "-fgnu-tm" } */ + +void foo(void (*fn)(void)) +{ + __transaction_relaxed { + fn(); + } +} diff --git a/gcc/testsuite/gcc.dg/tm/ipa-1.c b/gcc/testsuite/gcc.dg/tm/ipa-1.c new file mode 100644 index 00000000000..ec1cdca7032 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tm/ipa-1.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-options "-fgnu-tm -fdump-tree-tmmark-asmname" } */ + +void foo(void) __attribute__((transaction_safe)); + +void bar(void) +{ + __transaction_atomic { + foo(); + } +} + +/* { dg-final { scan-tree-dump-times "_ZGTt3foo" 1 "tmmark" } } */ +/* { dg-final { cleanup-tree-dump "tmmark" } } */ diff --git a/gcc/testsuite/gcc.dg/tm/ipa-2.c b/gcc/testsuite/gcc.dg/tm/ipa-2.c new file mode 100644 index 00000000000..e7a02cb1926 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tm/ipa-2.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-options "-fgnu-tm -fdump-tree-tmmark-asmname" } */ + +void foo(void); + +void bar(void) +{ + __transaction_relaxed { + foo(); + } +} + +/* { dg-final { scan-tree-dump-times "_ZGTt3foo" 0 "tmmark" } } */ +/* { dg-final { cleanup-tree-dump "tmmark" } } */ diff --git a/gcc/testsuite/gcc.dg/tm/ipa-3.c b/gcc/testsuite/gcc.dg/tm/ipa-3.c new file mode 100644 index 00000000000..cb1b433bcbd --- /dev/null +++ b/gcc/testsuite/gcc.dg/tm/ipa-3.c @@ -0,0 +1,12 @@ +/* { dg-do compile } */ +/* { dg-options "-fgnu-tm" } */ + +static int x; + +void __attribute__((transaction_callable)) +foo(void) +{ + x++; +} + +/* { dg-final { scan-assembler "_ZGTt3foo" } } */ diff --git a/gcc/testsuite/gcc.dg/tm/irrevocable-1.c b/gcc/testsuite/gcc.dg/tm/irrevocable-1.c new file mode 100644 index 00000000000..60f629133ee --- /dev/null +++ b/gcc/testsuite/gcc.dg/tm/irrevocable-1.c @@ -0,0 +1,16 @@ +/* { dg-do compile } */ +/* { dg-options "-fgnu-tm -O" } */ + +int global; +int george; + +extern crap() __attribute__((transaction_unsafe)); + +foo() +{ + __transaction_relaxed { + global++; + crap(); + george++; + } +} diff --git a/gcc/testsuite/gcc.dg/tm/irrevocable-2.c b/gcc/testsuite/gcc.dg/tm/irrevocable-2.c new file mode 100644 index 00000000000..17ac8a5f0c0 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tm/irrevocable-2.c @@ -0,0 +1,21 @@ +/* { dg-do compile } */ +/* { dg-options "-fgnu-tm -fdump-tree-tmedge" } */ + +/* Test that a direct call to __builtin__ITM_changeTransactionMode() + sets the irrevocable bit. */ + +int global; +int george; + +foo() +{ + __transaction_relaxed { + global++; + __builtin__ITM_changeTransactionMode (0); + george++; + } +} + +/* { dg-final { scan-tree-dump-times "doesGoIrrevocable" 1 "tmedge" } } */ +/* { dg-final { scan-tree-dump-times "hasNoIrrevocable" 0 "tmedge" } } */ +/* { dg-final { cleanup-tree-dump "tmedge" } } */ diff --git a/gcc/testsuite/gcc.dg/tm/irrevocable-3.c b/gcc/testsuite/gcc.dg/tm/irrevocable-3.c new file mode 100644 index 00000000000..c0854794803 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tm/irrevocable-3.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-options "-fgnu-tm -fdump-tree-tmmark" } */ + +extern void bar(void) __attribute__((transaction_callable)); + +foo() +{ + __transaction_relaxed { + bar(); + } +} + +/* { dg-final { scan-tree-dump-times "GTMA_MAY_ENTER_IRREVOCABLE" 1 "tmmark" } } */ +/* { dg-final { cleanup-tree-dump "tmmark" } } */ diff --git a/gcc/testsuite/gcc.dg/tm/irrevocable-4.c b/gcc/testsuite/gcc.dg/tm/irrevocable-4.c new file mode 100644 index 00000000000..ee759b84ef0 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tm/irrevocable-4.c @@ -0,0 +1,16 @@ +/* { dg-do compile } */ +/* { dg-options "-fgnu-tm -fdump-tree-tmmark" } */ + +void orig(void); +void xyz(void) __attribute__((transaction_wrap (orig))); + + +foo() +{ + __transaction_relaxed { + orig(); + } +} + +/* { dg-final { scan-tree-dump-times "GTMA_MAY_ENTER_IRREVOCABLE" 1 "tmmark" } } */ +/* { dg-final { cleanup-tree-dump "tmmark" } } */ diff --git a/gcc/testsuite/gcc.dg/tm/irrevocable-5.c b/gcc/testsuite/gcc.dg/tm/irrevocable-5.c new file mode 100644 index 00000000000..155879f1a21 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tm/irrevocable-5.c @@ -0,0 +1,27 @@ +/* { dg-do compile } */ +/* { dg-options "-fgnu-tm -fdump-ipa-tmipa -O" } */ + +int a; + +void foo(void) __attribute__((transaction_safe)); +void bar(void) __attribute__((transaction_safe)); +void danger(void) __attribute__((transaction_unsafe)); + +void wildthing() +{ + /* All blocks should be propagated as irrevocable. */ + __transaction_relaxed { + if (a) + foo(); + else + bar(); + danger(); + } +} + +/* { dg-final { scan-ipa-dump-times "GTMA_DOES_GO_IRREVOCABLE" 1 "tmipa" } } */ +/* { dg-final { scan-ipa-dump-times "bb 3 goes irr" 1 "tmipa" } } */ +/* { dg-final { scan-ipa-dump-times "bb 4 goes irr" 1 "tmipa" } } */ +/* { dg-final { scan-ipa-dump-times "bb 5 goes irr" 1 "tmipa" } } */ +/* { dg-final { scan-ipa-dump-times "bb 6 goes irr" 1 "tmipa" } } */ +/* { dg-final { cleanup-ipa-dump "tmipa" } } */ diff --git a/gcc/testsuite/gcc.dg/tm/irrevocable-6.c b/gcc/testsuite/gcc.dg/tm/irrevocable-6.c new file mode 100644 index 00000000000..2399131210b --- /dev/null +++ b/gcc/testsuite/gcc.dg/tm/irrevocable-6.c @@ -0,0 +1,34 @@ +/* { dg-do compile } */ +/* { dg-options "-fgnu-tm -fdump-ipa-tmipa -O" } */ + +int a, trxn, eee; + +void foo(void) __attribute__((transaction_safe)); +void bar(void) __attribute__((transaction_safe)); +void danger(void) __attribute__((transaction_unsafe)); + +void wildthing() +{ + /* All blocks should be propagated as irrevocable. */ + __transaction_relaxed { + if (eee) { + if (a) + foo(); + else + bar(); + danger(); + } else { + danger(); + } + } +} + +/* { dg-final { scan-ipa-dump-times "GTMA_DOES_GO_IRREVOCABLE" 1 "tmipa" } } */ +/* { dg-final { scan-ipa-dump-times "bb 3 goes irr" 1 "tmipa" } } */ +/* { dg-final { scan-ipa-dump-times "bb 4 goes irr" 1 "tmipa" } } */ +/* { dg-final { scan-ipa-dump-times "bb 5 goes irr" 1 "tmipa" } } */ +/* { dg-final { scan-ipa-dump-times "bb 6 goes irr" 1 "tmipa" } } */ +/* { dg-final { scan-ipa-dump-times "bb 7 goes irr" 1 "tmipa" } } */ +/* { dg-final { scan-ipa-dump-times "bb 8 goes irr" 1 "tmipa" } } */ +/* { dg-final { scan-ipa-dump-times "bb 9 goes irr" 1 "tmipa" } } */ +/* { dg-final { cleanup-ipa-dump "tmipa" } } */ diff --git a/gcc/testsuite/gcc.dg/tm/irrevocable-7.c b/gcc/testsuite/gcc.dg/tm/irrevocable-7.c new file mode 100644 index 00000000000..ea8a00f0c55 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tm/irrevocable-7.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-options "-fgnu-tm -fdump-ipa-tmipa" } */ + +extern void bark(void); + +__attribute__((transaction_callable)) +int foo() +{ + bark(); +} + +/* { dg-final { scan-ipa-dump-times "changeTransactionMode \\(0\\)" 1 "tmipa" } } */ +/* { dg-final { cleanup-ipa-dump "tmipa" } } */ diff --git a/gcc/testsuite/gcc.dg/tm/memopt-1.c b/gcc/testsuite/gcc.dg/tm/memopt-1.c new file mode 100644 index 00000000000..5388a81e282 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tm/memopt-1.c @@ -0,0 +1,29 @@ +/* { dg-do compile } */ +/* { dg-options "-fgnu-tm -O -fdump-tree-tmmemopt" } */ + +long g, xxx, yyy; +extern george() __attribute__((transaction_callable)); +extern ringo(long int); +int i; + +f() +{ + __transaction_relaxed { + g = 666; + george(); + if (i == 9) + goto bye; + xxx=8; + yyy=9; + for (i=0; i < 10; ++i) + ringo(g); + bye: + ringo(g); + } +} + +/* { dg-final { scan-tree-dump-times "transforming: .*_ITM_RaWU8 \\(&g\\);" 1 "tmmemopt" } } */ +/* { dg-final { scan-tree-dump-times "transforming: .*_ITM_WaRU4 \\(&i," 1 "tmmemopt" } } */ +/* { dg-final { scan-tree-dump-times "transforming: .*_ITM_RaWU4 \\(&i\\);" 1 "tmmemopt" } } */ +/* { dg-final { scan-tree-dump-times "transforming: .*_ITM_WaWU4 \\(&i," 1 "tmmemopt" } } */ +/* { dg-final { cleanup-tree-dump "tmmemopt" } } */ diff --git a/gcc/testsuite/gcc.dg/tm/memopt-10.c b/gcc/testsuite/gcc.dg/tm/memopt-10.c new file mode 100644 index 00000000000..5caa6b53d6b --- /dev/null +++ b/gcc/testsuite/gcc.dg/tm/memopt-10.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-options "-fgnu-tm -O -fdump-tree-tmmark" } */ + +extern int something(void) __attribute__((transaction_safe)); +extern void *malloc (__SIZE_TYPE__) __attribute__((malloc,transaction_safe)); + +int f() +{ + int *p; + + p = malloc (sizeof (*p) * 100); + + __transaction_atomic { + /* p[5] is thread private, but not transaction local since the + malloc is outside of the transaction. We can use the logging + functions for this. */ + p[5] = 123; + + if (something()) + __transaction_cancel; + } + return p[5]; +} + +/* { dg-final { scan-tree-dump-times "ITM_LU" 0 "tmmark" } } */ +/* { dg-final { scan-tree-dump-times "ITM_WU" 0 "tmmark" } } */ +/* { dg-final { scan-tree-dump-times "tm_save" 1 "tmmark" } } */ +/* { dg-final { cleanup-tree-dump "tmmark" } } */ diff --git a/gcc/testsuite/gcc.dg/tm/memopt-11.c b/gcc/testsuite/gcc.dg/tm/memopt-11.c new file mode 100644 index 00000000000..07972a4fd4e --- /dev/null +++ b/gcc/testsuite/gcc.dg/tm/memopt-11.c @@ -0,0 +1,29 @@ +/* { dg-do compile } */ +/* { dg-options "-fgnu-tm -O -fdump-tree-tmmark" } */ + +extern int something(void) __attribute__((transaction_safe)); +extern void *malloc (__SIZE_TYPE__) __attribute__((malloc,transaction_safe)); + +int f() +{ + int *p; + + p = malloc (sizeof (*p) * 100); + foo(p[5]); + + __transaction_atomic { + /* p[5] is thread private, however the SSA_NAME that holds the + address dominates the entire transaction (transaction + invariant) so we can use a save/restore pair. */ + p[5] = 123; + + if (something()) + __transaction_cancel; + } + return p[5]; +} + +/* { dg-final { scan-tree-dump-times "ITM_LU" 0 "tmmark" } } */ +/* { dg-final { scan-tree-dump-times "ITM_WU" 0 "tmmark" } } */ +/* { dg-final { scan-tree-dump-times "tm_save" 1 "tmmark" } } */ +/* { dg-final { cleanup-tree-dump "tmmark" } } */ diff --git a/gcc/testsuite/gcc.dg/tm/memopt-12.c b/gcc/testsuite/gcc.dg/tm/memopt-12.c new file mode 100644 index 00000000000..5520ecef27a --- /dev/null +++ b/gcc/testsuite/gcc.dg/tm/memopt-12.c @@ -0,0 +1,34 @@ +/* { dg-do compile } */ +/* { dg-options "-fgnu-tm -O -fdump-tree-tmmark" } */ + +extern int test(void) __attribute__((transaction_safe)); +extern void *malloc (__SIZE_TYPE__) __attribute__((malloc,transaction_safe)); + +struct large { int foo[500]; }; + +int f() +{ + int *p1, *p2, *p3; + + p1 = malloc (sizeof (*p1)*5000); + __transaction_atomic { + *p1 = 0; + + p2 = malloc (sizeof (*p2)*6000); + *p2 = 1; + + /* p3 = PHI (p1, p2) */ + if (test()) + p3 = p1; + else + p3 = p2; + + /* Since both p1 and p2 are thread-private, we can inherit the + logging already done. No ITM_W* instrumentation necessary. */ + *p3 = 555; + } + return p3[something()]; +} + +/* { dg-final { scan-tree-dump-times "ITM_WU" 0 "tmmark" } } */ +/* { dg-final { cleanup-tree-dump "tmmark" } } */ diff --git a/gcc/testsuite/gcc.dg/tm/memopt-13.c b/gcc/testsuite/gcc.dg/tm/memopt-13.c new file mode 100644 index 00000000000..6e93b7feaea --- /dev/null +++ b/gcc/testsuite/gcc.dg/tm/memopt-13.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-options "-fgnu-tm -O -fdump-tree-tmmark" } */ + +struct large { int x[100]; }; +struct large large_global; +extern struct large function (void) __attribute__((transaction_safe)); + +void f() +{ + __transaction_atomic { + large_global = function(); + } +} + +/* { dg-final { scan-tree-dump-times "memmoveRtWt \\\(&large_global," 1 "tmmark" } } */ diff --git a/gcc/testsuite/gcc.dg/tm/memopt-15.c b/gcc/testsuite/gcc.dg/tm/memopt-15.c new file mode 100644 index 00000000000..975c794337c --- /dev/null +++ b/gcc/testsuite/gcc.dg/tm/memopt-15.c @@ -0,0 +1,30 @@ +/* { dg-do compile { target { x86_64-*-linux* } } } */ +/* { dg-options "-fgnu-tm -O" } */ + +/* Test the TM vector logging functions. */ + +typedef int __attribute__((vector_size (16))) vectype; +extern int something(void) __attribute__((transaction_safe)); +extern void *malloc (__SIZE_TYPE__) __attribute__((malloc,transaction_safe)); + +vectype vecky; + +vectype f() +{ + vectype *p; + + p = malloc (sizeof (*p) * 100); + + __transaction_atomic { + /* p[5] is thread private, but not transaction local since the + malloc is outside of the transaction. We can use the logging + functions for this. */ + p[5] = vecky; + + if (something()) + __transaction_cancel; + } + return p[5]; +} + +/* { dg-final { scan-assembler "_ITM_LM128" } } */ diff --git a/gcc/testsuite/gcc.dg/tm/memopt-2.c b/gcc/testsuite/gcc.dg/tm/memopt-2.c new file mode 100644 index 00000000000..08aa9acdcbc --- /dev/null +++ b/gcc/testsuite/gcc.dg/tm/memopt-2.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-options "-fgnu-tm -O -fdump-tree-tmmemopt" } */ + +char c; + +void f(void) +{ + __transaction_atomic { + ++c; + } +} + +/* { dg-final { scan-tree-dump-times "transforming.*RfWU1 \\(&c" 1 "tmmemopt" } } */ +/* { dg-final { scan-tree-dump-times "transforming.*WaWU1 \\(&c" 1 "tmmemopt" } } */ +/* { dg-final { cleanup-tree-dump "tmmemopt" } } */ diff --git a/gcc/testsuite/gcc.dg/tm/memopt-3.c b/gcc/testsuite/gcc.dg/tm/memopt-3.c new file mode 100644 index 00000000000..62a3e0e9f2a --- /dev/null +++ b/gcc/testsuite/gcc.dg/tm/memopt-3.c @@ -0,0 +1,20 @@ +/* { dg-do compile } */ +/* { dg-options "-fgnu-tm -O -fdump-tree-tmmark" } */ + +struct large { int x[100]; }; +extern int test(void) __attribute__((transaction_safe)); + +int f() +{ + int i = readint(); + struct large lala = { 0 }; + __transaction_atomic { + lala.x[i] = 666; + if (test()) + __transaction_cancel; + } + return lala.x[0]; +} + +/* { dg-final { scan-tree-dump-times "logging: lala.x\\\[i_1\\\]" 1 "tmmark" { xfail *-*-* } } } */ +/* { dg-final { cleanup-tree-dump "tmmark" } } */ diff --git a/gcc/testsuite/gcc.dg/tm/memopt-4.c b/gcc/testsuite/gcc.dg/tm/memopt-4.c new file mode 100644 index 00000000000..92849718441 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tm/memopt-4.c @@ -0,0 +1,24 @@ +/* { dg-do compile } */ +/* { dg-options "-fgnu-tm -O -fdump-tree-tmedge" } */ + +/* Test thread-local memory optimizations: save/restore pairs. */ + +struct large { int x[100]; }; +struct large bark(); +extern int test (void) __attribute__((transaction_safe)); + +int f() +{ + int i = readint(); + struct large lala = bark(); + __transaction_atomic { + lala.x[55] = 666; + if (test()) + __transaction_cancel; + } + return lala.x[i]; +} + +/* { dg-final { scan-tree-dump-times "tm_save.\[0-9_\]+ = lala.x\\\[55\\\]" 1 "tmedge" { xfail *-*-* } } } */ +/* { dg-final { scan-tree-dump-times "lala.x\\\[55\\\] = tm_save" 1 "tmedge" { xfail *-*-* } } } */ +/* { dg-final { cleanup-tree-dump "tmedge" } } */ diff --git a/gcc/testsuite/gcc.dg/tm/memopt-5.c b/gcc/testsuite/gcc.dg/tm/memopt-5.c new file mode 100644 index 00000000000..7b377a58035 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tm/memopt-5.c @@ -0,0 +1,23 @@ +/* { dg-do compile } */ +/* { dg-options "-fgnu-tm -O -fdump-tree-tmedge --param tm-max-aggregate-size=1" } */ + +/* Test thread-local memory optimizations: logging function. */ + +struct large { int x[100]; }; +struct large bark(); +extern int test (void) __attribute__((transaction_safe)); + +int f() +{ + int i = readint(); + struct large lala = bark(); + __transaction_atomic { + lala.x[55] = 666; + if (test()) + __transaction_cancel; + } + return lala.x[i]; +} + +/* { dg-final { scan-tree-dump-times "ITM_LU\[0-9\] \\\(&lala.x\\\[55\\\]" 1 "tmedge" { xfail *-*-* } } } */ +/* { dg-final { cleanup-tree-dump "tmedge" } } */ diff --git a/gcc/testsuite/gcc.dg/tm/memopt-6.c b/gcc/testsuite/gcc.dg/tm/memopt-6.c new file mode 100644 index 00000000000..f4343736772 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tm/memopt-6.c @@ -0,0 +1,20 @@ +/* { dg-do compile } */ +/* { dg-options "-fgnu-tm -O -fdump-tree-tmedge --param tm-max-aggregate-size=1" } */ + +struct large { int x[100]; }; +struct large bark(); +extern int test (void) __attribute__((transaction_safe)); +struct large lacopy; + +int f() +{ + int i = readint(); + struct large lala = bark(); + __transaction_atomic { + lala.x[55] = 666; + lala = lacopy; /* Aggregate instrumentation. */ + } + return lala.x[i]; +} + +/* { dg-final { scan-tree-dump-times "memmoveRtWt \\\(&lala, &lacopy" 1 "tmedge" } } */ diff --git a/gcc/testsuite/gcc.dg/tm/memopt-7.c b/gcc/testsuite/gcc.dg/tm/memopt-7.c new file mode 100644 index 00000000000..f8af2a95e66 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tm/memopt-7.c @@ -0,0 +1,22 @@ +/* { dg-do compile } */ +/* { dg-options "-fgnu-tm -O -fdump-tree-tmedge --param tm-max-aggregate-size=999" } */ + +/* Test save/restore pairs for aggregates. */ + +struct large { int x[100]; }; +extern struct large foobie (void) __attribute__((transaction_safe)); +int asdf; + +int f() +{ + struct large lala; + struct large lacopy = foobie(); + __transaction_atomic { + lala = lacopy; + } + return lala.x[asdf]; +} + +/* { dg-final { scan-tree-dump-times "tm_save.\[0-9_\]+ = lala" 1 "tmedge" { xfail *-*-* } } } */ +/* { dg-final { scan-tree-dump-times "lala = tm_save" 1 "tmedge" { xfail *-*-* } } } */ +/* { dg-final { cleanup-tree-dump "tmedge" } } */ diff --git a/gcc/testsuite/gcc.dg/tm/memopt-8.c b/gcc/testsuite/gcc.dg/tm/memopt-8.c new file mode 100644 index 00000000000..10320e78950 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tm/memopt-8.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-options "-fgnu-tm -O -fdump-tree-tmmark" } */ + +extern int something(void) __attribute__((transaction_safe)); +extern int escape(int *) __attribute__((transaction_safe)); +extern void *malloc (__SIZE_TYPE__) __attribute__((malloc,transaction_safe)); + +int f() +{ + int *p; + + __transaction_atomic { + p = malloc (sizeof (*p) * 100); + escape (p); + + /* This should be instrumented because P escapes. */ + p[5] = 123; + + if (something()) + __transaction_cancel; + } + return p[5]; +} + +/* { dg-final { scan-tree-dump-times "ITM_WU" 1 "tmmark" } } */ +/* { dg-final { cleanup-tree-dump "tmmark" } } */ diff --git a/gcc/testsuite/gcc.dg/tm/memopt-9.c b/gcc/testsuite/gcc.dg/tm/memopt-9.c new file mode 100644 index 00000000000..0c34f20b926 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tm/memopt-9.c @@ -0,0 +1,29 @@ +/* { dg-do compile } */ +/* { dg-options "-fgnu-tm -O -fdump-tree-tmmark" } */ + +extern int something(void) __attribute__((transaction_safe)); +extern void *malloc (__SIZE_TYPE__) __attribute__((malloc,transaction_safe)); + +struct large { int foo[500]; }; + +int f() +{ + int *p; + struct large *lp; + + __transaction_atomic { + p = malloc (sizeof (*p) * 100); + lp = malloc (sizeof (*lp) * 100); + + /* No instrumentation necessary; P and LP are transaction local. */ + p[5] = 123; + lp->foo[66] = 123; + + if (something()) + __transaction_cancel; + } + return p[5]; +} + +/* { dg-final { scan-tree-dump-times "ITM_WU" 0 "tmmark" } } */ +/* { dg-final { cleanup-tree-dump "tmmark" } } */ diff --git a/gcc/testsuite/gcc.dg/tm/memset-2.c b/gcc/testsuite/gcc.dg/tm/memset-2.c new file mode 100644 index 00000000000..743ada13783 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tm/memset-2.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-options "-fgnu-tm -fdump-tree-tmlower" } */ + +char array[4]; + +void *memset(void *s, int c, __SIZE_TYPE__); + +int main() +{ + __transaction_atomic { + memset(array, 'b', sizeof(4)); + } + return 0; +} + +/* { dg-final { scan-tree-dump-times "GTMA_HAVE_STORE" 1 "tmlower" } } */ +/* { dg-final { cleanup-tree-dump "tmlower" } } */ diff --git a/gcc/testsuite/gcc.dg/tm/memset.c b/gcc/testsuite/gcc.dg/tm/memset.c new file mode 100644 index 00000000000..3b73ec6ee74 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tm/memset.c @@ -0,0 +1,24 @@ +/* { dg-do compile } */ +/* { dg-options "-fgnu-tm" } */ + +extern void *memset (void *, int, __SIZE_TYPE__); + +char array[4] = "aaaa"; + +__attribute__((transaction_safe)) +void *my_memset() +{ + return memset(array,'b',4); +} + + +int main() +{ + + __transaction_atomic { + my_memset(); + } + return 0; +} + +/* { dg-final { scan-assembler "_ITM_memsetW" } } */ diff --git a/gcc/testsuite/gcc.dg/tm/nested-1.c b/gcc/testsuite/gcc.dg/tm/nested-1.c new file mode 100644 index 00000000000..afadb83c183 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tm/nested-1.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-options "-fgnu-tm" } */ + +extern int foo(int) __attribute__((transaction_safe)); +void bar(void) +{ + __transaction_atomic { + if (foo(1)) + __transaction_atomic { + if (foo(2)) + __transaction_atomic { + if (foo(3)) + __transaction_atomic { + if (foo(4)) + foo(5); + else + __transaction_cancel; + } + else + __transaction_cancel; + } + else + __transaction_cancel; + } + else + __transaction_cancel; + } +} diff --git a/gcc/testsuite/gcc.dg/tm/nested-2.c b/gcc/testsuite/gcc.dg/tm/nested-2.c new file mode 100644 index 00000000000..205ca8d7eac --- /dev/null +++ b/gcc/testsuite/gcc.dg/tm/nested-2.c @@ -0,0 +1,19 @@ +/* { dg-do compile } */ +/* { dg-options "-fgnu-tm" } */ + +void foobar(void) +{ + __transaction_atomic { + foobar(); + } +} + +void doit(void) __attribute__((transaction_safe)); + +__attribute__((transaction_callable)) +void callable(void) +{ + __transaction_atomic { + doit(); + } +} diff --git a/gcc/testsuite/gcc.dg/tm/opt-1.c b/gcc/testsuite/gcc.dg/tm/opt-1.c new file mode 100644 index 00000000000..87a8c72bd43 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tm/opt-1.c @@ -0,0 +1,43 @@ +/* { dg-do compile } */ +/* { dg-options "-fgnu-tm -O" } */ + +extern void usleep (int) __attribute__((transaction_pure)); +extern int rand(void) __attribute__((pure, transaction_pure)); +extern int printf (const char *, ...); +extern void *malloc (__SIZE_TYPE__) __attribute__((malloc)); +extern void xyzzy (void * (*)(void *)); + +typedef struct +{ + int id; +} parm; + +int gvar; + +void *hello(void *arg) +{ + parm *p=(parm *)arg; + int tmp = p->id; + int tmp3; + printf ("Thread reads %d.\n", tmp); + __transaction_atomic + { + int tmp2 = gvar; + usleep ((int) (10.0*rand()/(10+1.0))/100); + gvar = tmp + tmp2; + tmp3 = gvar; + } + printf("tmp3 = %d\n", tmp3); + return 0; +} + +int +main() +{ + int i, n = rand(); + + for (i=0; i<n; i++) + xyzzy (hello); + + return 0; +} diff --git a/gcc/testsuite/gcc.dg/tm/opt-2.c b/gcc/testsuite/gcc.dg/tm/opt-2.c new file mode 100644 index 00000000000..d9e2b8a6db0 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tm/opt-2.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-options "-fgnu-tm -O2" } */ + +int foo(int *arr, int v) +{ + int r = 0; + int i; + __transaction_atomic { + for (i = 0; i < 10; ++i) + if (arr[i] < 27) + r += arr[i] += v; + } + return r; +} diff --git a/gcc/testsuite/gcc.dg/tm/pr45985.c b/gcc/testsuite/gcc.dg/tm/pr45985.c new file mode 100644 index 00000000000..c8118406776 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tm/pr45985.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-options "-fgnu-tm" } */ + +__attribute__((transaction_unsafe)) +void illegal(); + +static int a = 0; +void func() +{ + __transaction_relaxed { + if( a == 0) + illegal(); + } +} diff --git a/gcc/testsuite/gcc.dg/tm/pr46567-2.c b/gcc/testsuite/gcc.dg/tm/pr46567-2.c new file mode 100644 index 00000000000..bfe0078bfdb --- /dev/null +++ b/gcc/testsuite/gcc.dg/tm/pr46567-2.c @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-options "-fgnu-tm" } */ + +int funky(); +int global; + +void SeqfileGetLine() +{ + funky(); +} + +__attribute__((transaction_callable)) void readLoop() +{ + SeqfileGetLine(); + if (global) + funky(); + +} diff --git a/gcc/testsuite/gcc.dg/tm/pr46567.c b/gcc/testsuite/gcc.dg/tm/pr46567.c new file mode 100644 index 00000000000..bcc59adf509 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tm/pr46567.c @@ -0,0 +1,18 @@ +__attribute__((transaction_callable)) +static void SeqfileGetLine () +{ + SSIGetFilePosition (); +} + +__attribute__((transaction_callable)) +static void readLoop (int addfirst) +{ + if (!addfirst) + { + if (!addfirst) + { + SSIGetFilePosition (); + } + SeqfileGetLine (); + } +} diff --git a/gcc/testsuite/gcc.dg/tm/pr46654.c b/gcc/testsuite/gcc.dg/tm/pr46654.c new file mode 100644 index 00000000000..bb63b685844 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tm/pr46654.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-options "-fgnu-tm" } */ + +extern void baz(int); + +int y; +void foo(volatile int x) +{ + __transaction_atomic { + x = 5; /* { dg-error "invalid volatile use of 'x' inside transaction" } */ + x += y; + y++; + } + baz(x); +} + + +volatile int i = 0; + +void george() +{ + __transaction_atomic { + if (i == 2) /* { dg-error "invalid volatile use of 'i' inside transaction" } */ + i = 1; + } +} diff --git a/gcc/testsuite/gcc.dg/tm/pr47520.c b/gcc/testsuite/gcc.dg/tm/pr47520.c new file mode 100644 index 00000000000..80b976bd4cb --- /dev/null +++ b/gcc/testsuite/gcc.dg/tm/pr47520.c @@ -0,0 +1,29 @@ +/* { dg-do compile } */ +/* { dg-options "-fgnu-tm -O" } */ + +struct ReadSeqVars +{ + int format; + char *ss; +}; + +void rms_feof(struct ReadSeqVars *); + +__attribute__((transaction_callable)) int ReadSeq(struct ReadSeqVars *V) +{ + if (V->format > 1) + { + if ((V->format != 2) && (V->ss != (void*)0) ) + { + V->format = 3; + } + } + else + { + int i = 0; + for (i = 0; i < 1; i++) + { + } + rms_feof(V); + } +} diff --git a/gcc/testsuite/gcc.dg/tm/pr47690.c b/gcc/testsuite/gcc.dg/tm/pr47690.c new file mode 100644 index 00000000000..d18e2e11fb8 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tm/pr47690.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-options "-fgnu-tm" } */ + +int george; + +void q1() +{ + __transaction_atomic { + george=999; + } + q1(); +} + +/* { dg-final { scan-assembler-not "ZGTt2q1" } } */ diff --git a/gcc/testsuite/gcc.dg/tm/pr47905.c b/gcc/testsuite/gcc.dg/tm/pr47905.c new file mode 100644 index 00000000000..c4b254930c1 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tm/pr47905.c @@ -0,0 +1,14 @@ +/* { dg-do compile } + { dg-options "-fgnu-tm" } */ + +void funcA(); +void funcB(); + +void *thread() +{ + __transaction_relaxed + { + funcA(); + }; + funcB(); +} diff --git a/gcc/testsuite/gcc.dg/tm/props-1.c b/gcc/testsuite/gcc.dg/tm/props-1.c new file mode 100644 index 00000000000..89690240486 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tm/props-1.c @@ -0,0 +1,19 @@ +/* { dg-do compile } */ +/* { dg-options "-fgnu-tm -fdump-tree-tmedge -fdump-tree-tmlower" } */ + +int global; + +foo(int local) +{ + __transaction_atomic { + local++; + if (++global == 10) + __transaction_cancel; + } +} + +/* { dg-final { scan-tree-dump-times " instrumentedCode" 1 "tmedge" } } */ +/* { dg-final { scan-tree-dump-times "hasNoAbort" 0 "tmedge" } } */ +/* { dg-final { scan-tree-dump-times "GTMA_HAVE_ABORT" 1 "tmlower" } } */ +/* { dg-final { cleanup-tree-dump "tmedge" } } */ +/* { dg-final { cleanup-tree-dump "tmlower" } } */ diff --git a/gcc/testsuite/gcc.dg/tm/props-2.c b/gcc/testsuite/gcc.dg/tm/props-2.c new file mode 100644 index 00000000000..56a3ffa1367 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tm/props-2.c @@ -0,0 +1,20 @@ +/* { dg-do compile } */ +/* { dg-options "-fgnu-tm -fdump-ipa-tmipa" } */ + +/* Test that irrevocability gets set for the obvious case. */ + +int global; +int george; + +extern crap() __attribute__((transaction_unsafe)); + +foo(){ + __transaction_relaxed { + global++; + crap(); + george++; + } +} + +/* { dg-final { scan-ipa-dump-times "GTMA_MAY_ENTER_IRREVOCABLE" 1 "tmipa" } } */ +/* { dg-final { cleanup-ipa-dump "tmipa" } } */ diff --git a/gcc/testsuite/gcc.dg/tm/props-3.c b/gcc/testsuite/gcc.dg/tm/props-3.c new file mode 100644 index 00000000000..48f2230cdd2 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tm/props-3.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-options "-fgnu-tm -fdump-ipa-tmipa" } */ + +/* Test that indirect calls set the irrevocable bit. */ + +void (*indirect)(void); + +foo(){ + __transaction_relaxed { + (*indirect)(); + } +} + +/* { dg-final { scan-ipa-dump-times "GTMA_MAY_ENTER_IRREVOCABLE" 1 "tmipa" } } */ +/* { dg-final { cleanup-ipa-dump "tmipa" } } */ diff --git a/gcc/testsuite/gcc.dg/tm/props-4.c b/gcc/testsuite/gcc.dg/tm/props-4.c new file mode 100644 index 00000000000..c9d0c2b2887 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tm/props-4.c @@ -0,0 +1,27 @@ +/* { dg-do compile } */ +/* { dg-options "-fgnu-tm -fdump-tree-tmedge -fdump-tree-tmmark" } */ + +int a, b; + +void __attribute((transaction_may_cancel_outer,noinline)) cancel1() +{ + __transaction_cancel [[outer]]; +} + +void +foo(void) +{ + __transaction_atomic [[outer]] { + a = 2; + __transaction_atomic { + b = 2; + cancel1(); + } + } +} + +/* { dg-final { scan-tree-dump-times " instrumentedCode" 1 "tmedge" } } */ +/* { dg-final { scan-tree-dump-times "hasNoAbort" 0 "tmedge" } } */ +/* { dg-final { scan-tree-dump-times "LABEL=<L0>" 1 "tmmark" } } */ +/* { dg-final { cleanup-tree-dump "tmedge" } } */ +/* { dg-final { cleanup-tree-dump "tmmark" } } */ diff --git a/gcc/testsuite/gcc.dg/tm/tm.exp b/gcc/testsuite/gcc.dg/tm/tm.exp new file mode 100644 index 00000000000..3d24481d5a8 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tm/tm.exp @@ -0,0 +1,39 @@ +# Copyright (C) 2009, 2011 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GCC; see the file COPYING3. If not see +# <http://www.gnu.org/licenses/>. + +# GCC testsuite that uses the `dg.exp' driver. + +# Load support procs. +load_lib gcc-dg.exp + +# If a testcase doesn't have special options, use these. +global DEFAULT_CFLAGS +if ![info exists DEFAULT_CFLAGS] then { + set DEFAULT_CFLAGS " -ansi -pedantic-errors" +} + +# Initialize `dg'. +dg-init + +# Run the tests that are shared with C++ testing. +dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/tm/*c]] \ + "" $DEFAULT_CFLAGS +# Run the C-only tests. +dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.\[cS\]]] \ + "" $DEFAULT_CFLAGS + +# All done. +dg-finish diff --git a/gcc/testsuite/gcc.dg/tm/unsafe.c b/gcc/testsuite/gcc.dg/tm/unsafe.c new file mode 100644 index 00000000000..824368a1a34 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tm/unsafe.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-options "-fgnu-tm" } */ + +__attribute__((transaction_callable)) +static int func () +{ + return 12345; +} + +int main() +{ + __transaction_atomic { return func(); } /* { dg-error "unsafe function call .func. " } */ +} diff --git a/gcc/testsuite/gcc.dg/tm/unused.c b/gcc/testsuite/gcc.dg/tm/unused.c new file mode 100644 index 00000000000..7c8aa3e778d --- /dev/null +++ b/gcc/testsuite/gcc.dg/tm/unused.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-options "-fgnu-tm -Wall" } */ + +__attribute__((transaction_safe)) +static int unused_func () /* { dg-warning "defined but not used" } */ +{ + return 12345; +} + +int main() +{ + return 0; +} + +/* { dg-final { scan-assembler "_ZGTt11unused_func:" } } */ diff --git a/gcc/testsuite/gcc.dg/tm/vector-1.c b/gcc/testsuite/gcc.dg/tm/vector-1.c new file mode 100644 index 00000000000..2dc43b0a517 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tm/vector-1.c @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-options "-fgnu-tm -O3" } */ + +/* On x86-64, the vectorizer creates V2DI uses which we must handle. + Similarly for other vector architectures. */ + +void ** newElements; + +__attribute__((transaction_safe)) +long +TMqueue_push (void** queuePtr) +{ + long src; + for (src = 1; src < 9; src++) { + newElements[src+1] = queuePtr[src]; + } + return 1; +} diff --git a/gcc/testsuite/gcc.dg/tm/wrap-2.c b/gcc/testsuite/gcc.dg/tm/wrap-2.c new file mode 100644 index 00000000000..29486335a44 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tm/wrap-2.c @@ -0,0 +1,16 @@ +/* { dg-do compile } */ +/* { dg-options "-fgnu-tm" } */ + +#define W(X) __attribute__((transaction_wrap(X))) +void f1(void); +void f2(int); +int i3; +int f7(void); + +void g1(void) W(f1); +void g2(void) W(f2); /* { dg-error "is not compatible" } */ +void g3(void) W(i3); /* { dg-error "is not a function" } */ +void g4(void) W(f4); /* { dg-error "is not a function" } */ +void g5(void) W(1); /* { dg-error "not an identifier" } */ +void g6(void) W("f1"); /* { dg-error "not an identifier" } */ +void g7(void) W(f7); /* { dg-error "is not compatible" } */ diff --git a/gcc/testsuite/gcc.dg/tm/wrap-3.c b/gcc/testsuite/gcc.dg/tm/wrap-3.c new file mode 100644 index 00000000000..0734436809f --- /dev/null +++ b/gcc/testsuite/gcc.dg/tm/wrap-3.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-options "-fgnu-tm -fdump-tree-optimized" } */ + +void free (void *); +void wrapper (void *) __attribute__((transaction_wrap (free))); +void *p; + +void foo() +{ + __transaction_relaxed { free (p); } +} + +/* { dg-final { scan-tree-dump-times "free" 0 "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tm/wrap-4.c b/gcc/testsuite/gcc.dg/tm/wrap-4.c new file mode 100644 index 00000000000..9e1e70c544f --- /dev/null +++ b/gcc/testsuite/gcc.dg/tm/wrap-4.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-options "-fgnu-tm -fdump-tree-optimized -O2" } */ + +static void candy() { candycane(); } + +static void tootsie_roll () __attribute__((transaction_wrap (candy))); +static void tootsie_roll () { bark(); } + +void foo() +{ + __transaction_relaxed { candy(); } +} + +/* { dg-final { scan-tree-dump-times "candy" 0 "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/timevar.def b/gcc/timevar.def index 5ad0f9dd08c..d4a60fceefa 100644 --- a/gcc/timevar.def +++ b/gcc/timevar.def @@ -184,6 +184,7 @@ DEFTIMEVAR (TV_TREE_COPY_RENAME , "tree rename SSA copies") DEFTIMEVAR (TV_TREE_SSA_VERIFY , "tree SSA verifier") DEFTIMEVAR (TV_TREE_STMT_VERIFY , "tree STMT verifier") DEFTIMEVAR (TV_TREE_SWITCH_CONVERSION, "tree switch initialization conversion") +DEFTIMEVAR (TV_TRANS_MEM , "transactional memory") DEFTIMEVAR (TV_TREE_STRLEN , "tree strlen optimization") DEFTIMEVAR (TV_CGRAPH_VERIFY , "callgraph verifier") DEFTIMEVAR (TV_DOM_FRONTIERS , "dominance frontiers") diff --git a/gcc/toplev.c b/gcc/toplev.c index 86eed5d63a8..de255b4c3f7 100644 --- a/gcc/toplev.c +++ b/gcc/toplev.c @@ -599,6 +599,7 @@ compile_file (void) output_shared_constant_pool (); output_object_blocks (); + finish_tm_clone_pairs (); /* Write out any pending weak symbol declarations. */ weak_finish (); diff --git a/gcc/trans-mem.c b/gcc/trans-mem.c new file mode 100644 index 00000000000..3c0bd600943 --- /dev/null +++ b/gcc/trans-mem.c @@ -0,0 +1,4914 @@ +/* Passes for transactional memory support. + Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free + Software Foundation; either version 3, or (at your option) any later + version. + + GCC is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with GCC; see the file COPYING3. If not see + <http://www.gnu.org/licenses/>. */ + +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "tree.h" +#include "gimple.h" +#include "tree-flow.h" +#include "tree-pass.h" +#include "tree-inline.h" +#include "diagnostic-core.h" +#include "demangle.h" +#include "output.h" +#include "trans-mem.h" +#include "params.h" +#include "target.h" +#include "langhooks.h" +#include "tree-pretty-print.h" +#include "gimple-pretty-print.h" + + +#define PROB_VERY_UNLIKELY (REG_BR_PROB_BASE / 2000 - 1) +#define PROB_ALWAYS (REG_BR_PROB_BASE) + +#define A_RUNINSTRUMENTEDCODE 0x0001 +#define A_RUNUNINSTRUMENTEDCODE 0x0002 +#define A_SAVELIVEVARIABLES 0x0004 +#define A_RESTORELIVEVARIABLES 0x0008 +#define A_ABORTTRANSACTION 0x0010 + +#define AR_USERABORT 0x0001 +#define AR_USERRETRY 0x0002 +#define AR_TMCONFLICT 0x0004 +#define AR_EXCEPTIONBLOCKABORT 0x0008 +#define AR_OUTERABORT 0x0010 + +#define MODE_SERIALIRREVOCABLE 0x0000 + + +/* The representation of a transaction changes several times during the + lowering process. In the beginning, in the front-end we have the + GENERIC tree TRANSACTION_EXPR. For example, + + __transaction { + local++; + if (++global == 10) + __tm_abort; + } + + During initial gimplification (gimplify.c) the TRANSACTION_EXPR node is + trivially replaced with a GIMPLE_TRANSACTION node. + + During pass_lower_tm, we examine the body of transactions looking + for aborts. Transactions that do not contain an abort may be + merged into an outer transaction. We also add a TRY-FINALLY node + to arrange for the transaction to be committed on any exit. + + [??? Think about how this arrangement affects throw-with-commit + and throw-with-abort operations. In this case we want the TRY to + handle gotos, but not to catch any exceptions because the transaction + will already be closed.] + + GIMPLE_TRANSACTION [label=NULL] { + try { + local = local + 1; + t0 = global; + t1 = t0 + 1; + global = t1; + if (t1 == 10) + __builtin___tm_abort (); + } finally { + __builtin___tm_commit (); + } + } + + During pass_lower_eh, we create EH regions for the transactions, + intermixed with the regular EH stuff. This gives us a nice persistent + mapping (all the way through rtl) from transactional memory operation + back to the transaction, which allows us to get the abnormal edges + correct to model transaction aborts and restarts: + + GIMPLE_TRANSACTION [label=over] + local = local + 1; + t0 = global; + t1 = t0 + 1; + global = t1; + if (t1 == 10) + __builtin___tm_abort (); + __builtin___tm_commit (); + over: + + This is the end of all_lowering_passes, and so is what is present + during the IPA passes, and through all of the optimization passes. + + During pass_ipa_tm, we examine all GIMPLE_TRANSACTION blocks in all + functions and mark functions for cloning. + + At the end of gimple optimization, before exiting SSA form, + pass_tm_edges replaces statements that perform transactional + memory operations with the appropriate TM builtins, and swap + out function calls with their transactional clones. At this + point we introduce the abnormal transaction restart edges and + complete lowering of the GIMPLE_TRANSACTION node. + + x = __builtin___tm_start (MAY_ABORT); + eh_label: + if (x & abort_transaction) + goto over; + local = local + 1; + t0 = __builtin___tm_load (global); + t1 = t0 + 1; + __builtin___tm_store (&global, t1); + if (t1 == 10) + __builtin___tm_abort (); + __builtin___tm_commit (); + over: +*/ + + +/* Return the attributes we want to examine for X, or NULL if it's not + something we examine. We look at function types, but allow pointers + to function types and function decls and peek through. */ + +static tree +get_attrs_for (const_tree x) +{ + switch (TREE_CODE (x)) + { + case FUNCTION_DECL: + return TYPE_ATTRIBUTES (TREE_TYPE (x)); + break; + + default: + if (TYPE_P (x)) + return NULL; + x = TREE_TYPE (x); + if (TREE_CODE (x) != POINTER_TYPE) + return NULL; + /* FALLTHRU */ + + case POINTER_TYPE: + x = TREE_TYPE (x); + if (TREE_CODE (x) != FUNCTION_TYPE && TREE_CODE (x) != METHOD_TYPE) + return NULL; + /* FALLTHRU */ + + case FUNCTION_TYPE: + case METHOD_TYPE: + return TYPE_ATTRIBUTES (x); + } +} + +/* Return true if X has been marked TM_PURE. */ + +bool +is_tm_pure (const_tree x) +{ + unsigned flags; + + switch (TREE_CODE (x)) + { + case FUNCTION_DECL: + case FUNCTION_TYPE: + case METHOD_TYPE: + break; + + default: + if (TYPE_P (x)) + return false; + x = TREE_TYPE (x); + if (TREE_CODE (x) != POINTER_TYPE) + return false; + /* FALLTHRU */ + + case POINTER_TYPE: + x = TREE_TYPE (x); + if (TREE_CODE (x) != FUNCTION_TYPE && TREE_CODE (x) != METHOD_TYPE) + return false; + break; + } + + flags = flags_from_decl_or_type (x); + return (flags & ECF_TM_PURE) != 0; +} + +/* Return true if X has been marked TM_IRREVOCABLE. */ + +static bool +is_tm_irrevocable (tree x) +{ + tree attrs = get_attrs_for (x); + + if (attrs && lookup_attribute ("transaction_unsafe", attrs)) + return true; + + /* A call to the irrevocable builtin is by definition, + irrevocable. */ + if (TREE_CODE (x) == ADDR_EXPR) + x = TREE_OPERAND (x, 0); + if (TREE_CODE (x) == FUNCTION_DECL + && DECL_BUILT_IN_CLASS (x) == BUILT_IN_NORMAL + && DECL_FUNCTION_CODE (x) == BUILT_IN_TM_IRREVOCABLE) + return true; + + return false; +} + +/* Return true if X has been marked TM_SAFE. */ + +bool +is_tm_safe (const_tree x) +{ + if (flag_tm) + { + tree attrs = get_attrs_for (x); + if (attrs) + { + if (lookup_attribute ("transaction_safe", attrs)) + return true; + if (lookup_attribute ("transaction_may_cancel_outer", attrs)) + return true; + } + } + return false; +} + +/* Return true if CALL is const, or tm_pure. */ + +static bool +is_tm_pure_call (gimple call) +{ + tree fn = gimple_call_fn (call); + + if (TREE_CODE (fn) == ADDR_EXPR) + { + fn = TREE_OPERAND (fn, 0); + gcc_assert (TREE_CODE (fn) == FUNCTION_DECL); + } + else + fn = TREE_TYPE (fn); + + return is_tm_pure (fn); +} + +/* Return true if X has been marked TM_CALLABLE. */ + +static bool +is_tm_callable (tree x) +{ + tree attrs = get_attrs_for (x); + if (attrs) + { + if (lookup_attribute ("transaction_callable", attrs)) + return true; + if (lookup_attribute ("transaction_safe", attrs)) + return true; + if (lookup_attribute ("transaction_may_cancel_outer", attrs)) + return true; + } + return false; +} + +/* Return true if X has been marked TRANSACTION_MAY_CANCEL_OUTER. */ + +bool +is_tm_may_cancel_outer (tree x) +{ + tree attrs = get_attrs_for (x); + if (attrs) + return lookup_attribute ("transaction_may_cancel_outer", attrs) != NULL; + return false; +} + +/* Return true for built in functions that "end" a transaction. */ + +bool +is_tm_ending_fndecl (tree fndecl) +{ + if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL) + switch (DECL_FUNCTION_CODE (fndecl)) + { + case BUILT_IN_TM_COMMIT: + case BUILT_IN_TM_COMMIT_EH: + case BUILT_IN_TM_ABORT: + case BUILT_IN_TM_IRREVOCABLE: + return true; + default: + break; + } + + return false; +} + +/* Return true if STMT is a TM load. */ + +static bool +is_tm_load (gimple stmt) +{ + tree fndecl; + + if (gimple_code (stmt) != GIMPLE_CALL) + return false; + + fndecl = gimple_call_fndecl (stmt); + return (fndecl && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL + && BUILTIN_TM_LOAD_P (DECL_FUNCTION_CODE (fndecl))); +} + +/* Same as above, but for simple TM loads, that is, not the + after-write, after-read, etc optimized variants. */ + +static bool +is_tm_simple_load (gimple stmt) +{ + tree fndecl; + + if (gimple_code (stmt) != GIMPLE_CALL) + return false; + + fndecl = gimple_call_fndecl (stmt); + if (fndecl && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL) + { + enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl); + return (fcode == BUILT_IN_TM_LOAD_1 + || fcode == BUILT_IN_TM_LOAD_2 + || fcode == BUILT_IN_TM_LOAD_4 + || fcode == BUILT_IN_TM_LOAD_8 + || fcode == BUILT_IN_TM_LOAD_FLOAT + || fcode == BUILT_IN_TM_LOAD_DOUBLE + || fcode == BUILT_IN_TM_LOAD_LDOUBLE + || fcode == BUILT_IN_TM_LOAD_M64 + || fcode == BUILT_IN_TM_LOAD_M128 + || fcode == BUILT_IN_TM_LOAD_M256); + } + return false; +} + +/* Return true if STMT is a TM store. */ + +static bool +is_tm_store (gimple stmt) +{ + tree fndecl; + + if (gimple_code (stmt) != GIMPLE_CALL) + return false; + + fndecl = gimple_call_fndecl (stmt); + return (fndecl && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL + && BUILTIN_TM_STORE_P (DECL_FUNCTION_CODE (fndecl))); +} + +/* Same as above, but for simple TM stores, that is, not the + after-write, after-read, etc optimized variants. */ + +static bool +is_tm_simple_store (gimple stmt) +{ + tree fndecl; + + if (gimple_code (stmt) != GIMPLE_CALL) + return false; + + fndecl = gimple_call_fndecl (stmt); + if (fndecl && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL) + { + enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl); + return (fcode == BUILT_IN_TM_STORE_1 + || fcode == BUILT_IN_TM_STORE_2 + || fcode == BUILT_IN_TM_STORE_4 + || fcode == BUILT_IN_TM_STORE_8 + || fcode == BUILT_IN_TM_STORE_FLOAT + || fcode == BUILT_IN_TM_STORE_DOUBLE + || fcode == BUILT_IN_TM_STORE_LDOUBLE + || fcode == BUILT_IN_TM_STORE_M64 + || fcode == BUILT_IN_TM_STORE_M128 + || fcode == BUILT_IN_TM_STORE_M256); + } + return false; +} + +/* Return true if FNDECL is BUILT_IN_TM_ABORT. */ + +static bool +is_tm_abort (tree fndecl) +{ + return (fndecl + && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL + && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_TM_ABORT); +} + +/* Build a GENERIC tree for a user abort. This is called by front ends + while transforming the __tm_abort statement. */ + +tree +build_tm_abort_call (location_t loc, bool is_outer) +{ + return build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_TM_ABORT), 1, + build_int_cst (integer_type_node, + AR_USERABORT + | (is_outer ? AR_OUTERABORT : 0))); +} + +/* Common gateing function for several of the TM passes. */ + +static bool +gate_tm (void) +{ + return flag_tm; +} + +/* Map for aribtrary function replacement under TM, as created + by the tm_wrap attribute. */ + +static GTY((if_marked ("tree_map_marked_p"), param_is (struct tree_map))) + htab_t tm_wrap_map; + +void +record_tm_replacement (tree from, tree to) +{ + struct tree_map **slot, *h; + + /* Do not inline wrapper functions that will get replaced in the TM + pass. + + Suppose you have foo() that will get replaced into tmfoo(). Make + sure the inliner doesn't try to outsmart us and inline foo() + before we get a chance to do the TM replacement. */ + DECL_UNINLINABLE (from) = 1; + + if (tm_wrap_map == NULL) + tm_wrap_map = htab_create_ggc (32, tree_map_hash, tree_map_eq, 0); + + h = ggc_alloc_tree_map (); + h->hash = htab_hash_pointer (from); + h->base.from = from; + h->to = to; + + slot = (struct tree_map **) + htab_find_slot_with_hash (tm_wrap_map, h, h->hash, INSERT); + *slot = h; +} + +/* Return a TM-aware replacement function for DECL. */ + +static tree +find_tm_replacement_function (tree fndecl) +{ + if (tm_wrap_map) + { + struct tree_map *h, in; + + in.base.from = fndecl; + in.hash = htab_hash_pointer (fndecl); + h = (struct tree_map *) htab_find_with_hash (tm_wrap_map, &in, in.hash); + if (h) + return h->to; + } + + /* ??? We may well want TM versions of most of the common <string.h> + functions. For now, we've already these two defined. */ + /* Adjust expand_call_tm() attributes as necessary for the cases + handled here: */ + if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL) + switch (DECL_FUNCTION_CODE (fndecl)) + { + case BUILT_IN_MEMCPY: + return builtin_decl_explicit (BUILT_IN_TM_MEMCPY); + case BUILT_IN_MEMMOVE: + return builtin_decl_explicit (BUILT_IN_TM_MEMMOVE); + case BUILT_IN_MEMSET: + return builtin_decl_explicit (BUILT_IN_TM_MEMSET); + default: + return NULL; + } + + return NULL; +} + +/* When appropriate, record TM replacement for memory allocation functions. + + FROM is the FNDECL to wrap. */ +void +tm_malloc_replacement (tree from) +{ + const char *str; + tree to; + + if (TREE_CODE (from) != FUNCTION_DECL) + return; + + /* If we have a previous replacement, the user must be explicitly + wrapping malloc/calloc/free. They better know what they're + doing... */ + if (find_tm_replacement_function (from)) + return; + + str = IDENTIFIER_POINTER (DECL_NAME (from)); + + if (!strcmp (str, "malloc")) + to = builtin_decl_explicit (BUILT_IN_TM_MALLOC); + else if (!strcmp (str, "calloc")) + to = builtin_decl_explicit (BUILT_IN_TM_CALLOC); + else if (!strcmp (str, "free")) + to = builtin_decl_explicit (BUILT_IN_TM_FREE); + else + return; + + TREE_NOTHROW (to) = 0; + + record_tm_replacement (from, to); +} + +/* Diagnostics for tm_safe functions/regions. Called by the front end + once we've lowered the function to high-gimple. */ + +/* Subroutine of diagnose_tm_safe_errors, called through walk_gimple_seq. + Process exactly one statement. WI->INFO is set to non-null when in + the context of a tm_safe function, and null for a __transaction block. */ + +#define DIAG_TM_OUTER 1 +#define DIAG_TM_SAFE 2 +#define DIAG_TM_RELAXED 4 + +struct diagnose_tm +{ + unsigned int summary_flags : 8; + unsigned int block_flags : 8; + unsigned int func_flags : 8; + unsigned int saw_unsafe : 1; + unsigned int saw_volatile : 1; + gimple stmt; +}; + +/* Tree callback function for diagnose_tm pass. */ + +static tree +diagnose_tm_1_op (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED, + void *data) +{ + struct walk_stmt_info *wi = (struct walk_stmt_info *) data; + struct diagnose_tm *d = (struct diagnose_tm *) wi->info; + enum tree_code code = TREE_CODE (*tp); + + if ((code == VAR_DECL + || code == RESULT_DECL + || code == PARM_DECL) + && d->block_flags & (DIAG_TM_SAFE | DIAG_TM_RELAXED) + && TREE_THIS_VOLATILE (TREE_TYPE (*tp)) + && !d->saw_volatile) + { + d->saw_volatile = 1; + error_at (gimple_location (d->stmt), + "invalid volatile use of %qD inside transaction", + *tp); + } + + return NULL_TREE; +} + +static tree +diagnose_tm_1 (gimple_stmt_iterator *gsi, bool *handled_ops_p, + struct walk_stmt_info *wi) +{ + gimple stmt = gsi_stmt (*gsi); + struct diagnose_tm *d = (struct diagnose_tm *) wi->info; + + /* Save stmt for use in leaf analysis. */ + d->stmt = stmt; + + switch (gimple_code (stmt)) + { + case GIMPLE_CALL: + { + tree fn = gimple_call_fn (stmt); + + if ((d->summary_flags & DIAG_TM_OUTER) == 0 + && is_tm_may_cancel_outer (fn)) + error_at (gimple_location (stmt), + "%<transaction_may_cancel_outer%> function call not within" + " outer transaction or %<transaction_may_cancel_outer%>"); + + if (d->summary_flags & DIAG_TM_SAFE) + { + bool is_safe, direct_call_p; + tree replacement; + + if (TREE_CODE (fn) == ADDR_EXPR + && TREE_CODE (TREE_OPERAND (fn, 0)) == FUNCTION_DECL) + { + direct_call_p = true; + replacement = TREE_OPERAND (fn, 0); + replacement = find_tm_replacement_function (replacement); + if (replacement) + fn = replacement; + } + else + { + direct_call_p = false; + replacement = NULL_TREE; + } + + if (is_tm_safe_or_pure (fn)) + is_safe = true; + else if (is_tm_callable (fn) || is_tm_irrevocable (fn)) + { + /* A function explicitly marked transaction_callable as + opposed to transaction_safe is being defined to be + unsafe as part of its ABI, regardless of its contents. */ + is_safe = false; + } + else if (direct_call_p) + { + if (flags_from_decl_or_type (fn) & ECF_TM_BUILTIN) + is_safe = true; + else if (replacement) + { + /* ??? At present we've been considering replacements + merely transaction_callable, and therefore might + enter irrevocable. The tm_wrap attribute has not + yet made it into the new language spec. */ + is_safe = false; + } + else + { + /* ??? Diagnostics for unmarked direct calls moved into + the IPA pass. Section 3.2 of the spec details how + functions not marked should be considered "implicitly + safe" based on having examined the function body. */ + is_safe = true; + } + } + else + { + /* An unmarked indirect call. Consider it unsafe even + though optimization may yet figure out how to inline. */ + is_safe = false; + } + + if (!is_safe) + { + if (TREE_CODE (fn) == ADDR_EXPR) + fn = TREE_OPERAND (fn, 0); + if (d->block_flags & DIAG_TM_SAFE) + error_at (gimple_location (stmt), + "unsafe function call %qD within " + "atomic transaction", fn); + else + error_at (gimple_location (stmt), + "unsafe function call %qD within " + "%<transaction_safe%> function", fn); + } + } + } + break; + + case GIMPLE_ASM: + /* ??? We ought to come up with a way to add attributes to + asm statements, and then add "transaction_safe" to it. + Either that or get the language spec to resurrect __tm_waiver. */ + if (d->block_flags & DIAG_TM_SAFE) + error_at (gimple_location (stmt), + "asm not allowed in atomic transaction"); + else if (d->func_flags & DIAG_TM_SAFE) + error_at (gimple_location (stmt), + "asm not allowed in %<transaction_safe%> function"); + else + d->saw_unsafe = true; + break; + + case GIMPLE_TRANSACTION: + { + unsigned char inner_flags = DIAG_TM_SAFE; + + if (gimple_transaction_subcode (stmt) & GTMA_IS_RELAXED) + { + if (d->block_flags & DIAG_TM_SAFE) + error_at (gimple_location (stmt), + "relaxed transaction in atomic transaction"); + else if (d->func_flags & DIAG_TM_SAFE) + error_at (gimple_location (stmt), + "relaxed transaction in %<transaction_safe%> function"); + else + d->saw_unsafe = true; + inner_flags = DIAG_TM_RELAXED; + } + else if (gimple_transaction_subcode (stmt) & GTMA_IS_OUTER) + { + if (d->block_flags) + error_at (gimple_location (stmt), + "outer transaction in transaction"); + else if (d->func_flags & DIAG_TM_OUTER) + error_at (gimple_location (stmt), + "outer transaction in " + "%<transaction_may_cancel_outer%> function"); + else if (d->func_flags & DIAG_TM_SAFE) + error_at (gimple_location (stmt), + "outer transaction in %<transaction_safe%> function"); + else + d->saw_unsafe = true; + inner_flags |= DIAG_TM_OUTER; + } + + *handled_ops_p = true; + if (gimple_transaction_body (stmt)) + { + struct walk_stmt_info wi_inner; + struct diagnose_tm d_inner; + + memset (&d_inner, 0, sizeof (d_inner)); + d_inner.func_flags = d->func_flags; + d_inner.block_flags = d->block_flags | inner_flags; + d_inner.summary_flags = d_inner.func_flags | d_inner.block_flags; + + memset (&wi_inner, 0, sizeof (wi_inner)); + wi_inner.info = &d_inner; + + walk_gimple_seq (gimple_transaction_body (stmt), + diagnose_tm_1, diagnose_tm_1_op, &wi_inner); + + d->saw_unsafe |= d_inner.saw_unsafe; + } + } + break; + + default: + break; + } + + return NULL_TREE; +} + +static unsigned int +diagnose_tm_blocks (void) +{ + struct walk_stmt_info wi; + struct diagnose_tm d; + + memset (&d, 0, sizeof (d)); + if (is_tm_may_cancel_outer (current_function_decl)) + d.func_flags = DIAG_TM_OUTER | DIAG_TM_SAFE; + else if (is_tm_safe (current_function_decl)) + d.func_flags = DIAG_TM_SAFE; + d.summary_flags = d.func_flags; + + memset (&wi, 0, sizeof (wi)); + wi.info = &d; + + walk_gimple_seq (gimple_body (current_function_decl), + diagnose_tm_1, diagnose_tm_1_op, &wi); + + /* If we saw something other than a call that makes this function + unsafe, remember it so that the IPA pass only needs to scan calls. */ + if (d.saw_unsafe && !is_tm_safe_or_pure (current_function_decl)) + cgraph_local_info (current_function_decl)->tm_may_enter_irr = 1; + + return 0; +} + +struct gimple_opt_pass pass_diagnose_tm_blocks = +{ + { + GIMPLE_PASS, + "*diagnose_tm_blocks", /* name */ + gate_tm, /* gate */ + diagnose_tm_blocks, /* execute */ + NULL, /* sub */ + NULL, /* next */ + 0, /* static_pass_number */ + TV_TRANS_MEM, /* tv_id */ + PROP_gimple_any, /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ + 0, /* todo_flags_finish */ + } +}; + +/* Instead of instrumenting thread private memory, we save the + addresses in a log which we later use to save/restore the addresses + upon transaction start/restart. + + The log is keyed by address, where each element contains individual + statements among different code paths that perform the store. + + This log is later used to generate either plain save/restore of the + addresses upon transaction start/restart, or calls to the ITM_L* + logging functions. + + So for something like: + + struct large { int x[1000]; }; + struct large lala = { 0 }; + __transaction { + lala.x[i] = 123; + ... + } + + We can either save/restore: + + lala = { 0 }; + trxn = _ITM_startTransaction (); + if (trxn & a_saveLiveVariables) + tmp_lala1 = lala.x[i]; + else if (a & a_restoreLiveVariables) + lala.x[i] = tmp_lala1; + + or use the logging functions: + + lala = { 0 }; + trxn = _ITM_startTransaction (); + _ITM_LU4 (&lala.x[i]); + + Obviously, if we use _ITM_L* to log, we prefer to call _ITM_L* as + far up the dominator tree to shadow all of the writes to a given + location (thus reducing the total number of logging calls), but not + so high as to be called on a path that does not perform a + write. */ + +/* One individual log entry. We may have multiple statements for the + same location if neither dominate each other (on different + execution paths). */ +typedef struct tm_log_entry +{ + /* Address to save. */ + tree addr; + /* Entry block for the transaction this address occurs in. */ + basic_block entry_block; + /* Dominating statements the store occurs in. */ + gimple_vec stmts; + /* Initially, while we are building the log, we place a nonzero + value here to mean that this address *will* be saved with a + save/restore sequence. Later, when generating the save sequence + we place the SSA temp generated here. */ + tree save_var; +} *tm_log_entry_t; + +/* The actual log. */ +static htab_t tm_log; + +/* Addresses to log with a save/restore sequence. These should be in + dominator order. */ +static VEC(tree,heap) *tm_log_save_addresses; + +/* Map for an SSA_NAME originally pointing to a non aliased new piece + of memory (malloc, alloc, etc). */ +static htab_t tm_new_mem_hash; + +enum thread_memory_type + { + mem_non_local = 0, + mem_thread_local, + mem_transaction_local, + mem_max + }; + +typedef struct tm_new_mem_map +{ + /* SSA_NAME being dereferenced. */ + tree val; + enum thread_memory_type local_new_memory; +} tm_new_mem_map_t; + +/* Htab support. Return hash value for a `tm_log_entry'. */ +static hashval_t +tm_log_hash (const void *p) +{ + const struct tm_log_entry *log = (const struct tm_log_entry *) p; + return iterative_hash_expr (log->addr, 0); +} + +/* Htab support. Return true if two log entries are the same. */ +static int +tm_log_eq (const void *p1, const void *p2) +{ + const struct tm_log_entry *log1 = (const struct tm_log_entry *) p1; + const struct tm_log_entry *log2 = (const struct tm_log_entry *) p2; + + /* FIXME: + + rth: I suggest that we get rid of the component refs etc. + I.e. resolve the reference to base + offset. + + We may need to actually finish a merge with mainline for this, + since we'd like to be presented with Richi's MEM_REF_EXPRs more + often than not. But in the meantime your tm_log_entry could save + the results of get_inner_reference. + + See: g++.dg/tm/pr46653.C + */ + + /* Special case plain equality because operand_equal_p() below will + return FALSE if the addresses are equal but they have + side-effects (e.g. a volatile address). */ + if (log1->addr == log2->addr) + return true; + + return operand_equal_p (log1->addr, log2->addr, 0); +} + +/* Htab support. Free one tm_log_entry. */ +static void +tm_log_free (void *p) +{ + struct tm_log_entry *lp = (struct tm_log_entry *) p; + VEC_free (gimple, heap, lp->stmts); + free (lp); +} + +/* Initialize logging data structures. */ +static void +tm_log_init (void) +{ + tm_log = htab_create (10, tm_log_hash, tm_log_eq, tm_log_free); + tm_new_mem_hash = htab_create (5, struct_ptr_hash, struct_ptr_eq, free); + tm_log_save_addresses = VEC_alloc (tree, heap, 5); +} + +/* Free logging data structures. */ +static void +tm_log_delete (void) +{ + htab_delete (tm_log); + htab_delete (tm_new_mem_hash); + VEC_free (tree, heap, tm_log_save_addresses); +} + +/* Return true if MEM is a transaction invariant memory for the TM + region starting at REGION_ENTRY_BLOCK. */ +static bool +transaction_invariant_address_p (const_tree mem, basic_block region_entry_block) +{ + if ((TREE_CODE (mem) == INDIRECT_REF || TREE_CODE (mem) == MEM_REF) + && TREE_CODE (TREE_OPERAND (mem, 0)) == SSA_NAME) + { + basic_block def_bb; + + def_bb = gimple_bb (SSA_NAME_DEF_STMT (TREE_OPERAND (mem, 0))); + return def_bb != region_entry_block + && dominated_by_p (CDI_DOMINATORS, region_entry_block, def_bb); + } + + mem = strip_invariant_refs (mem); + return mem && (CONSTANT_CLASS_P (mem) || decl_address_invariant_p (mem)); +} + +/* Given an address ADDR in STMT, find it in the memory log or add it, + making sure to keep only the addresses highest in the dominator + tree. + + ENTRY_BLOCK is the entry_block for the transaction. + + If we find the address in the log, make sure it's either the same + address, or an equivalent one that dominates ADDR. + + If we find the address, but neither ADDR dominates the found + address, nor the found one dominates ADDR, we're on different + execution paths. Add it. + + If known, ENTRY_BLOCK is the entry block for the region, otherwise + NULL. */ +static void +tm_log_add (basic_block entry_block, tree addr, gimple stmt) +{ + void **slot; + struct tm_log_entry l, *lp; + + l.addr = addr; + slot = htab_find_slot (tm_log, &l, INSERT); + if (!*slot) + { + tree type = TREE_TYPE (addr); + + lp = XNEW (struct tm_log_entry); + lp->addr = addr; + *slot = lp; + + /* Small invariant addresses can be handled as save/restores. */ + if (entry_block + && transaction_invariant_address_p (lp->addr, entry_block) + && TYPE_SIZE_UNIT (type) != NULL + && host_integerp (TYPE_SIZE_UNIT (type), 1) + && (tree_low_cst (TYPE_SIZE_UNIT (type), 1) + < PARAM_VALUE (PARAM_TM_MAX_AGGREGATE_SIZE)) + /* We must be able to copy this type normally. I.e., no + special constructors and the like. */ + && !TREE_ADDRESSABLE (type)) + { + lp->save_var = create_tmp_var (TREE_TYPE (lp->addr), "tm_save"); + add_referenced_var (lp->save_var); + lp->stmts = NULL; + lp->entry_block = entry_block; + /* Save addresses separately in dominator order so we don't + get confused by overlapping addresses in the save/restore + sequence. */ + VEC_safe_push (tree, heap, tm_log_save_addresses, lp->addr); + } + else + { + /* Use the logging functions. */ + lp->stmts = VEC_alloc (gimple, heap, 5); + VEC_quick_push (gimple, lp->stmts, stmt); + lp->save_var = NULL; + } + } + else + { + size_t i; + gimple oldstmt; + + lp = (struct tm_log_entry *) *slot; + + /* If we're generating a save/restore sequence, we don't care + about statements. */ + if (lp->save_var) + return; + + for (i = 0; VEC_iterate (gimple, lp->stmts, i, oldstmt); ++i) + { + if (stmt == oldstmt) + return; + /* We already have a store to the same address, higher up the + dominator tree. Nothing to do. */ + if (dominated_by_p (CDI_DOMINATORS, + gimple_bb (stmt), gimple_bb (oldstmt))) + return; + /* We should be processing blocks in dominator tree order. */ + gcc_assert (!dominated_by_p (CDI_DOMINATORS, + gimple_bb (oldstmt), gimple_bb (stmt))); + } + /* Store is on a different code path. */ + VEC_safe_push (gimple, heap, lp->stmts, stmt); + } +} + +/* Gimplify the address of a TARGET_MEM_REF. Return the SSA_NAME + result, insert the new statements before GSI. */ + +static tree +gimplify_addr (gimple_stmt_iterator *gsi, tree x) +{ + if (TREE_CODE (x) == TARGET_MEM_REF) + x = tree_mem_ref_addr (build_pointer_type (TREE_TYPE (x)), x); + else + x = build_fold_addr_expr (x); + return force_gimple_operand_gsi (gsi, x, true, NULL, true, GSI_SAME_STMT); +} + +/* Instrument one address with the logging functions. + ADDR is the address to save. + STMT is the statement before which to place it. */ +static void +tm_log_emit_stmt (tree addr, gimple stmt) +{ + tree type = TREE_TYPE (addr); + tree size = TYPE_SIZE_UNIT (type); + gimple_stmt_iterator gsi = gsi_for_stmt (stmt); + gimple log; + enum built_in_function code = BUILT_IN_TM_LOG; + + if (type == float_type_node) + code = BUILT_IN_TM_LOG_FLOAT; + else if (type == double_type_node) + code = BUILT_IN_TM_LOG_DOUBLE; + else if (type == long_double_type_node) + code = BUILT_IN_TM_LOG_LDOUBLE; + else if (host_integerp (size, 1)) + { + unsigned int n = tree_low_cst (size, 1); + switch (n) + { + case 1: + code = BUILT_IN_TM_LOG_1; + break; + case 2: + code = BUILT_IN_TM_LOG_2; + break; + case 4: + code = BUILT_IN_TM_LOG_4; + break; + case 8: + code = BUILT_IN_TM_LOG_8; + break; + default: + code = BUILT_IN_TM_LOG; + if (TREE_CODE (type) == VECTOR_TYPE) + { + if (n == 8 && builtin_decl_explicit (BUILT_IN_TM_LOG_M64)) + code = BUILT_IN_TM_LOG_M64; + else if (n == 16 && builtin_decl_explicit (BUILT_IN_TM_LOG_M128)) + code = BUILT_IN_TM_LOG_M128; + else if (n == 32 && builtin_decl_explicit (BUILT_IN_TM_LOG_M256)) + code = BUILT_IN_TM_LOG_M256; + } + break; + } + } + + addr = gimplify_addr (&gsi, addr); + if (code == BUILT_IN_TM_LOG) + log = gimple_build_call (builtin_decl_explicit (code), 2, addr, size); + else + log = gimple_build_call (builtin_decl_explicit (code), 1, addr); + gsi_insert_before (&gsi, log, GSI_SAME_STMT); +} + +/* Go through the log and instrument address that must be instrumented + with the logging functions. Leave the save/restore addresses for + later. */ +static void +tm_log_emit (void) +{ + htab_iterator hi; + struct tm_log_entry *lp; + + FOR_EACH_HTAB_ELEMENT (tm_log, lp, tm_log_entry_t, hi) + { + size_t i; + gimple stmt; + + if (dump_file) + { + fprintf (dump_file, "TM thread private mem logging: "); + print_generic_expr (dump_file, lp->addr, 0); + fprintf (dump_file, "\n"); + } + + if (lp->save_var) + { + if (dump_file) + fprintf (dump_file, "DUMPING to variable\n"); + continue; + } + else + { + if (dump_file) + fprintf (dump_file, "DUMPING with logging functions\n"); + for (i = 0; VEC_iterate (gimple, lp->stmts, i, stmt); ++i) + tm_log_emit_stmt (lp->addr, stmt); + } + } +} + +/* Emit the save sequence for the corresponding addresses in the log. + ENTRY_BLOCK is the entry block for the transaction. + BB is the basic block to insert the code in. */ +static void +tm_log_emit_saves (basic_block entry_block, basic_block bb) +{ + size_t i; + gimple_stmt_iterator gsi = gsi_last_bb (bb); + gimple stmt; + struct tm_log_entry l, *lp; + + for (i = 0; i < VEC_length (tree, tm_log_save_addresses); ++i) + { + l.addr = VEC_index (tree, tm_log_save_addresses, i); + lp = (struct tm_log_entry *) *htab_find_slot (tm_log, &l, NO_INSERT); + gcc_assert (lp->save_var != NULL); + + /* We only care about variables in the current transaction. */ + if (lp->entry_block != entry_block) + continue; + + stmt = gimple_build_assign (lp->save_var, unshare_expr (lp->addr)); + + /* Make sure we can create an SSA_NAME for this type. For + instance, aggregates aren't allowed, in which case the system + will create a VOP for us and everything will just work. */ + if (is_gimple_reg_type (TREE_TYPE (lp->save_var))) + { + lp->save_var = make_ssa_name (lp->save_var, stmt); + gimple_assign_set_lhs (stmt, lp->save_var); + } + + gsi_insert_before (&gsi, stmt, GSI_SAME_STMT); + } +} + +/* Emit the restore sequence for the corresponding addresses in the log. + ENTRY_BLOCK is the entry block for the transaction. + BB is the basic block to insert the code in. */ +static void +tm_log_emit_restores (basic_block entry_block, basic_block bb) +{ + int i; + struct tm_log_entry l, *lp; + gimple_stmt_iterator gsi; + gimple stmt; + + for (i = VEC_length (tree, tm_log_save_addresses) - 1; i >= 0; i--) + { + l.addr = VEC_index (tree, tm_log_save_addresses, i); + lp = (struct tm_log_entry *) *htab_find_slot (tm_log, &l, NO_INSERT); + gcc_assert (lp->save_var != NULL); + + /* We only care about variables in the current transaction. */ + if (lp->entry_block != entry_block) + continue; + + /* Restores are in LIFO order from the saves in case we have + overlaps. */ + gsi = gsi_start_bb (bb); + + stmt = gimple_build_assign (unshare_expr (lp->addr), lp->save_var); + gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING); + } +} + +/* Emit the checks for performing either a save or a restore sequence. + + TRXN_PROP is either A_SAVELIVEVARIABLES or A_RESTORELIVEVARIABLES. + + The code sequence is inserted in a new basic block created in + END_BB which is inserted between BEFORE_BB and the destination of + FALLTHRU_EDGE. + + STATUS is the return value from _ITM_beginTransaction. + ENTRY_BLOCK is the entry block for the transaction. + EMITF is a callback to emit the actual save/restore code. + + The basic block containing the conditional checking for TRXN_PROP + is returned. */ +static basic_block +tm_log_emit_save_or_restores (basic_block entry_block, + unsigned trxn_prop, + tree status, + void (*emitf)(basic_block, basic_block), + basic_block before_bb, + edge fallthru_edge, + basic_block *end_bb) +{ + basic_block cond_bb, code_bb; + gimple cond_stmt, stmt; + gimple_stmt_iterator gsi; + tree t1, t2; + int old_flags = fallthru_edge->flags; + + cond_bb = create_empty_bb (before_bb); + code_bb = create_empty_bb (cond_bb); + *end_bb = create_empty_bb (code_bb); + redirect_edge_pred (fallthru_edge, *end_bb); + fallthru_edge->flags = EDGE_FALLTHRU; + make_edge (before_bb, cond_bb, old_flags); + + set_immediate_dominator (CDI_DOMINATORS, cond_bb, before_bb); + set_immediate_dominator (CDI_DOMINATORS, code_bb, cond_bb); + + gsi = gsi_last_bb (cond_bb); + + /* t1 = status & A_{property}. */ + t1 = make_rename_temp (TREE_TYPE (status), NULL); + t2 = build_int_cst (TREE_TYPE (status), trxn_prop); + stmt = gimple_build_assign_with_ops (BIT_AND_EXPR, t1, status, t2); + gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING); + + /* if (t1). */ + t2 = build_int_cst (TREE_TYPE (status), 0); + cond_stmt = gimple_build_cond (NE_EXPR, t1, t2, NULL, NULL); + gsi_insert_after (&gsi, cond_stmt, GSI_CONTINUE_LINKING); + + emitf (entry_block, code_bb); + + make_edge (cond_bb, code_bb, EDGE_TRUE_VALUE); + make_edge (cond_bb, *end_bb, EDGE_FALSE_VALUE); + make_edge (code_bb, *end_bb, EDGE_FALLTHRU); + + return cond_bb; +} + +static tree lower_sequence_tm (gimple_stmt_iterator *, bool *, + struct walk_stmt_info *); +static tree lower_sequence_no_tm (gimple_stmt_iterator *, bool *, + struct walk_stmt_info *); + +/* Evaluate an address X being dereferenced and determine if it + originally points to a non aliased new chunk of memory (malloc, + alloca, etc). + + Return MEM_THREAD_LOCAL if it points to a thread-local address. + Return MEM_TRANSACTION_LOCAL if it points to a transaction-local address. + Return MEM_NON_LOCAL otherwise. + + ENTRY_BLOCK is the entry block to the transaction containing the + dereference of X. */ +static enum thread_memory_type +thread_private_new_memory (basic_block entry_block, tree x) +{ + gimple stmt = NULL; + enum tree_code code; + void **slot; + tm_new_mem_map_t elt, *elt_p; + tree val = x; + enum thread_memory_type retval = mem_transaction_local; + + if (!entry_block + || TREE_CODE (x) != SSA_NAME + /* Possible uninitialized use, or a function argument. In + either case, we don't care. */ + || SSA_NAME_IS_DEFAULT_DEF (x)) + return mem_non_local; + + /* Look in cache first. */ + elt.val = x; + slot = htab_find_slot (tm_new_mem_hash, &elt, INSERT); + elt_p = (tm_new_mem_map_t *) *slot; + if (elt_p) + return elt_p->local_new_memory; + + /* Optimistically assume the memory is transaction local during + processing. This catches recursion into this variable. */ + *slot = elt_p = XNEW (tm_new_mem_map_t); + elt_p->val = val; + elt_p->local_new_memory = mem_transaction_local; + + /* Search DEF chain to find the original definition of this address. */ + do + { + if (ptr_deref_may_alias_global_p (x)) + { + /* Address escapes. This is not thread-private. */ + retval = mem_non_local; + goto new_memory_ret; + } + + stmt = SSA_NAME_DEF_STMT (x); + + /* If the malloc call is outside the transaction, this is + thread-local. */ + if (retval != mem_thread_local + && !dominated_by_p (CDI_DOMINATORS, gimple_bb (stmt), entry_block)) + retval = mem_thread_local; + + if (is_gimple_assign (stmt)) + { + code = gimple_assign_rhs_code (stmt); + /* x = foo ==> foo */ + if (code == SSA_NAME) + x = gimple_assign_rhs1 (stmt); + /* x = foo + n ==> foo */ + else if (code == POINTER_PLUS_EXPR) + x = gimple_assign_rhs1 (stmt); + /* x = (cast*) foo ==> foo */ + else if (code == VIEW_CONVERT_EXPR || code == NOP_EXPR) + x = gimple_assign_rhs1 (stmt); + else + { + retval = mem_non_local; + goto new_memory_ret; + } + } + else + { + if (gimple_code (stmt) == GIMPLE_PHI) + { + unsigned int i; + enum thread_memory_type mem; + tree phi_result = gimple_phi_result (stmt); + + /* If any of the ancestors are non-local, we are sure to + be non-local. Otherwise we can avoid doing anything + and inherit what has already been generated. */ + retval = mem_max; + for (i = 0; i < gimple_phi_num_args (stmt); ++i) + { + tree op = PHI_ARG_DEF (stmt, i); + + /* Exclude self-assignment. */ + if (phi_result == op) + continue; + + mem = thread_private_new_memory (entry_block, op); + if (mem == mem_non_local) + { + retval = mem; + goto new_memory_ret; + } + retval = MIN (retval, mem); + } + goto new_memory_ret; + } + break; + } + } + while (TREE_CODE (x) == SSA_NAME); + + if (stmt && is_gimple_call (stmt) && gimple_call_flags (stmt) & ECF_MALLOC) + /* Thread-local or transaction-local. */ + ; + else + retval = mem_non_local; + + new_memory_ret: + elt_p->local_new_memory = retval; + return retval; +} + +/* Determine whether X has to be instrumented using a read + or write barrier. + + ENTRY_BLOCK is the entry block for the region where stmt resides + in. NULL if unknown. + + STMT is the statement in which X occurs in. It is used for thread + private memory instrumentation. If no TPM instrumentation is + desired, STMT should be null. */ +static bool +requires_barrier (basic_block entry_block, tree x, gimple stmt) +{ + tree orig = x; + while (handled_component_p (x)) + x = TREE_OPERAND (x, 0); + + switch (TREE_CODE (x)) + { + case INDIRECT_REF: + case MEM_REF: + { + enum thread_memory_type ret; + + ret = thread_private_new_memory (entry_block, TREE_OPERAND (x, 0)); + if (ret == mem_non_local) + return true; + if (stmt && ret == mem_thread_local) + /* ?? Should we pass `orig', or the INDIRECT_REF X. ?? */ + tm_log_add (entry_block, orig, stmt); + + /* Transaction-locals require nothing at all. For malloc, a + transaction restart frees the memory and we reallocate. + For alloca, the stack pointer gets reset by the retry and + we reallocate. */ + return false; + } + + case TARGET_MEM_REF: + if (TREE_CODE (TMR_BASE (x)) != ADDR_EXPR) + return true; + x = TREE_OPERAND (TMR_BASE (x), 0); + if (TREE_CODE (x) == PARM_DECL) + return false; + gcc_assert (TREE_CODE (x) == VAR_DECL); + /* FALLTHRU */ + + case PARM_DECL: + case RESULT_DECL: + case VAR_DECL: + if (DECL_BY_REFERENCE (x)) + { + /* ??? This value is a pointer, but aggregate_value_p has been + jigged to return true which confuses needs_to_live_in_memory. + This ought to be cleaned up generically. + + FIXME: Verify this still happens after the next mainline + merge. Testcase ie g++.dg/tm/pr47554.C. + */ + return false; + } + + if (is_global_var (x)) + return !TREE_READONLY (x); + if (/* FIXME: This condition should actually go below in the + tm_log_add() call, however is_call_clobbered() depends on + aliasing info which is not available during + gimplification. Since requires_barrier() gets called + during lower_sequence_tm/gimplification, leave the call + to needs_to_live_in_memory until we eliminate + lower_sequence_tm altogether. */ + needs_to_live_in_memory (x) + /* X escapes. */ + || ptr_deref_may_alias_global_p (x)) + return true; + else + { + /* For local memory that doesn't escape (aka thread private + memory), we can either save the value at the beginning of + the transaction and restore on restart, or call a tm + function to dynamically save and restore on restart + (ITM_L*). */ + if (stmt) + tm_log_add (entry_block, orig, stmt); + return false; + } + + default: + return false; + } +} + +/* Mark the GIMPLE_ASSIGN statement as appropriate for being inside + a transaction region. */ + +static void +examine_assign_tm (unsigned *state, gimple_stmt_iterator *gsi) +{ + gimple stmt = gsi_stmt (*gsi); + + if (requires_barrier (/*entry_block=*/NULL, gimple_assign_rhs1 (stmt), NULL)) + *state |= GTMA_HAVE_LOAD; + if (requires_barrier (/*entry_block=*/NULL, gimple_assign_lhs (stmt), NULL)) + *state |= GTMA_HAVE_STORE; +} + +/* Mark a GIMPLE_CALL as appropriate for being inside a transaction. */ + +static void +examine_call_tm (unsigned *state, gimple_stmt_iterator *gsi) +{ + gimple stmt = gsi_stmt (*gsi); + tree fn; + + if (is_tm_pure_call (stmt)) + return; + + /* Check if this call is a transaction abort. */ + fn = gimple_call_fndecl (stmt); + if (is_tm_abort (fn)) + *state |= GTMA_HAVE_ABORT; + + /* Note that something may happen. */ + *state |= GTMA_HAVE_LOAD | GTMA_HAVE_STORE; +} + +/* Lower a GIMPLE_TRANSACTION statement. */ + +static void +lower_transaction (gimple_stmt_iterator *gsi, struct walk_stmt_info *wi) +{ + gimple g, stmt = gsi_stmt (*gsi); + unsigned int *outer_state = (unsigned int *) wi->info; + unsigned int this_state = 0; + struct walk_stmt_info this_wi; + + /* First, lower the body. The scanning that we do inside gives + us some idea of what we're dealing with. */ + memset (&this_wi, 0, sizeof (this_wi)); + this_wi.info = (void *) &this_state; + walk_gimple_seq (gimple_transaction_body (stmt), + lower_sequence_tm, NULL, &this_wi); + + /* If there was absolutely nothing transaction related inside the + transaction, we may elide it. Likewise if this is a nested + transaction and does not contain an abort. */ + if (this_state == 0 + || (!(this_state & GTMA_HAVE_ABORT) && outer_state != NULL)) + { + if (outer_state) + *outer_state |= this_state; + + gsi_insert_seq_before (gsi, gimple_transaction_body (stmt), + GSI_SAME_STMT); + gimple_transaction_set_body (stmt, NULL); + + gsi_remove (gsi, true); + wi->removed_stmt = true; + return; + } + + /* Wrap the body of the transaction in a try-finally node so that + the commit call is always properly called. */ + g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TM_COMMIT), 0); + if (flag_exceptions) + { + tree ptr; + gimple_seq n_seq, e_seq; + + n_seq = gimple_seq_alloc_with_stmt (g); + e_seq = gimple_seq_alloc (); + + g = gimple_build_call (builtin_decl_explicit (BUILT_IN_EH_POINTER), + 1, integer_zero_node); + ptr = create_tmp_var (ptr_type_node, NULL); + gimple_call_set_lhs (g, ptr); + gimple_seq_add_stmt (&e_seq, g); + + g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TM_COMMIT_EH), + 1, ptr); + gimple_seq_add_stmt (&e_seq, g); + + g = gimple_build_eh_else (n_seq, e_seq); + } + + g = gimple_build_try (gimple_transaction_body (stmt), + gimple_seq_alloc_with_stmt (g), GIMPLE_TRY_FINALLY); + gsi_insert_after (gsi, g, GSI_CONTINUE_LINKING); + + gimple_transaction_set_body (stmt, NULL); + + /* If the transaction calls abort or if this is an outer transaction, + add an "over" label afterwards. */ + if ((this_state & (GTMA_HAVE_ABORT)) + || (gimple_transaction_subcode(stmt) & GTMA_IS_OUTER)) + { + tree label = create_artificial_label (UNKNOWN_LOCATION); + gimple_transaction_set_label (stmt, label); + gsi_insert_after (gsi, gimple_build_label (label), GSI_CONTINUE_LINKING); + } + + /* Record the set of operations found for use later. */ + this_state |= gimple_transaction_subcode (stmt) & GTMA_DECLARATION_MASK; + gimple_transaction_set_subcode (stmt, this_state); +} + +/* Iterate through the statements in the sequence, lowering them all + as appropriate for being in a transaction. */ + +static tree +lower_sequence_tm (gimple_stmt_iterator *gsi, bool *handled_ops_p, + struct walk_stmt_info *wi) +{ + unsigned int *state = (unsigned int *) wi->info; + gimple stmt = gsi_stmt (*gsi); + + *handled_ops_p = true; + switch (gimple_code (stmt)) + { + case GIMPLE_ASSIGN: + /* Only memory reads/writes need to be instrumented. */ + if (gimple_assign_single_p (stmt)) + examine_assign_tm (state, gsi); + break; + + case GIMPLE_CALL: + examine_call_tm (state, gsi); + break; + + case GIMPLE_ASM: + *state |= GTMA_MAY_ENTER_IRREVOCABLE; + break; + + case GIMPLE_TRANSACTION: + lower_transaction (gsi, wi); + break; + + default: + *handled_ops_p = !gimple_has_substatements (stmt); + break; + } + + return NULL_TREE; +} + +/* Iterate through the statements in the sequence, lowering them all + as appropriate for being outside of a transaction. */ + +static tree +lower_sequence_no_tm (gimple_stmt_iterator *gsi, bool *handled_ops_p, + struct walk_stmt_info * wi) +{ + gimple stmt = gsi_stmt (*gsi); + + if (gimple_code (stmt) == GIMPLE_TRANSACTION) + { + *handled_ops_p = true; + lower_transaction (gsi, wi); + } + else + *handled_ops_p = !gimple_has_substatements (stmt); + + return NULL_TREE; +} + +/* Main entry point for flattening GIMPLE_TRANSACTION constructs. After + this, GIMPLE_TRANSACTION nodes still exist, but the nested body has + been moved out, and all the data required for constructing a proper + CFG has been recorded. */ + +static unsigned int +execute_lower_tm (void) +{ + struct walk_stmt_info wi; + + /* Transactional clones aren't created until a later pass. */ + gcc_assert (!decl_is_tm_clone (current_function_decl)); + + memset (&wi, 0, sizeof (wi)); + walk_gimple_seq (gimple_body (current_function_decl), + lower_sequence_no_tm, NULL, &wi); + + return 0; +} + +struct gimple_opt_pass pass_lower_tm = +{ + { + GIMPLE_PASS, + "tmlower", /* name */ + gate_tm, /* gate */ + execute_lower_tm, /* execute */ + NULL, /* sub */ + NULL, /* next */ + 0, /* static_pass_number */ + TV_TRANS_MEM, /* tv_id */ + PROP_gimple_lcf, /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ + TODO_dump_func /* todo_flags_finish */ + } +}; + +/* Collect region information for each transaction. */ + +struct tm_region +{ + /* Link to the next unnested transaction. */ + struct tm_region *next; + + /* Link to the next inner transaction. */ + struct tm_region *inner; + + /* Link to the next outer transaction. */ + struct tm_region *outer; + + /* The GIMPLE_TRANSACTION statement beginning this transaction. */ + gimple transaction_stmt; + + /* The entry block to this region. */ + basic_block entry_block; + + /* The set of all blocks that end the region; NULL if only EXIT_BLOCK. + These blocks are still a part of the region (i.e., the border is + inclusive). Note that this set is only complete for paths in the CFG + starting at ENTRY_BLOCK, and that there is no exit block recorded for + the edge to the "over" label. */ + bitmap exit_blocks; + + /* The set of all blocks that have an TM_IRREVOCABLE call. */ + bitmap irr_blocks; +}; + +/* True if there are pending edge statements to be committed for the + current function being scanned in the tmmark pass. */ +bool pending_edge_inserts_p; + +static struct tm_region *all_tm_regions; +static bitmap_obstack tm_obstack; + + +/* A subroutine of tm_region_init. Record the existance of the + GIMPLE_TRANSACTION statement in a tree of tm_region elements. */ + +static struct tm_region * +tm_region_init_0 (struct tm_region *outer, basic_block bb, gimple stmt) +{ + struct tm_region *region; + + region = (struct tm_region *) + obstack_alloc (&tm_obstack.obstack, sizeof (struct tm_region)); + + if (outer) + { + region->next = outer->inner; + outer->inner = region; + } + else + { + region->next = all_tm_regions; + all_tm_regions = region; + } + region->inner = NULL; + region->outer = outer; + + region->transaction_stmt = stmt; + + /* There are either one or two edges out of the block containing + the GIMPLE_TRANSACTION, one to the actual region and one to the + "over" label if the region contains an abort. The former will + always be the one marked FALLTHRU. */ + region->entry_block = FALLTHRU_EDGE (bb)->dest; + + region->exit_blocks = BITMAP_ALLOC (&tm_obstack); + region->irr_blocks = BITMAP_ALLOC (&tm_obstack); + + return region; +} + +/* A subroutine of tm_region_init. Record all the exit and + irrevocable blocks in BB into the region's exit_blocks and + irr_blocks bitmaps. Returns the new region being scanned. */ + +static struct tm_region * +tm_region_init_1 (struct tm_region *region, basic_block bb) +{ + gimple_stmt_iterator gsi; + gimple g; + + if (!region + || (!region->irr_blocks && !region->exit_blocks)) + return region; + + /* Check to see if this is the end of a region by seeing if it + contains a call to __builtin_tm_commit{,_eh}. Note that the + outermost region for DECL_IS_TM_CLONE need not collect this. */ + for (gsi = gsi_last_bb (bb); !gsi_end_p (gsi); gsi_prev (&gsi)) + { + g = gsi_stmt (gsi); + if (gimple_code (g) == GIMPLE_CALL) + { + tree fn = gimple_call_fndecl (g); + if (fn && DECL_BUILT_IN_CLASS (fn) == BUILT_IN_NORMAL) + { + if ((DECL_FUNCTION_CODE (fn) == BUILT_IN_TM_COMMIT + || DECL_FUNCTION_CODE (fn) == BUILT_IN_TM_COMMIT_EH) + && region->exit_blocks) + { + bitmap_set_bit (region->exit_blocks, bb->index); + region = region->outer; + break; + } + if (DECL_FUNCTION_CODE (fn) == BUILT_IN_TM_IRREVOCABLE) + bitmap_set_bit (region->irr_blocks, bb->index); + } + } + } + return region; +} + +/* Collect all of the transaction regions within the current function + and record them in ALL_TM_REGIONS. The REGION parameter may specify + an "outermost" region for use by tm clones. */ + +static void +tm_region_init (struct tm_region *region) +{ + gimple g; + edge_iterator ei; + edge e; + basic_block bb; + VEC(basic_block, heap) *queue = NULL; + bitmap visited_blocks = BITMAP_ALLOC (NULL); + struct tm_region *old_region; + + all_tm_regions = region; + bb = single_succ (ENTRY_BLOCK_PTR); + + VEC_safe_push (basic_block, heap, queue, bb); + gcc_assert (!bb->aux); /* FIXME: Remove me. */ + bb->aux = region; + do + { + bb = VEC_pop (basic_block, queue); + region = (struct tm_region *)bb->aux; + bb->aux = NULL; + + /* Record exit and irrevocable blocks. */ + region = tm_region_init_1 (region, bb); + + /* Check for the last statement in the block beginning a new region. */ + g = last_stmt (bb); + old_region = region; + if (g && gimple_code (g) == GIMPLE_TRANSACTION) + region = tm_region_init_0 (region, bb, g); + + /* Process subsequent blocks. */ + FOR_EACH_EDGE (e, ei, bb->succs) + if (!bitmap_bit_p (visited_blocks, e->dest->index)) + { + bitmap_set_bit (visited_blocks, e->dest->index); + VEC_safe_push (basic_block, heap, queue, e->dest); + gcc_assert (!e->dest->aux); /* FIXME: Remove me. */ + + /* If the current block started a new region, make sure that only + the entry block of the new region is associated with this region. + Other successors are still part of the old region. */ + if (old_region != region && e->dest != region->entry_block) + e->dest->aux = old_region; + else + e->dest->aux = region; + } + } + while (!VEC_empty (basic_block, queue)); + VEC_free (basic_block, heap, queue); + BITMAP_FREE (visited_blocks); +} + +/* The "gate" function for all transactional memory expansion and optimization + passes. We collect region information for each top-level transaction, and + if we don't find any, we skip all of the TM passes. Each region will have + all of the exit blocks recorded, and the originating statement. */ + +static bool +gate_tm_init (void) +{ + if (!flag_tm) + return false; + + calculate_dominance_info (CDI_DOMINATORS); + bitmap_obstack_initialize (&tm_obstack); + + /* If the function is a TM_CLONE, then the entire function is the region. */ + if (decl_is_tm_clone (current_function_decl)) + { + struct tm_region *region = (struct tm_region *) + obstack_alloc (&tm_obstack.obstack, sizeof (struct tm_region)); + memset (region, 0, sizeof (*region)); + region->entry_block = single_succ (ENTRY_BLOCK_PTR); + /* For a clone, the entire function is the region. But even if + we don't need to record any exit blocks, we may need to + record irrevocable blocks. */ + region->irr_blocks = BITMAP_ALLOC (&tm_obstack); + + tm_region_init (region); + } + else + { + tm_region_init (NULL); + + /* If we didn't find any regions, cleanup and skip the whole tree + of tm-related optimizations. */ + if (all_tm_regions == NULL) + { + bitmap_obstack_release (&tm_obstack); + return false; + } + } + + return true; +} + +struct gimple_opt_pass pass_tm_init = +{ + { + GIMPLE_PASS, + "*tminit", /* name */ + gate_tm_init, /* gate */ + NULL, /* execute */ + NULL, /* sub */ + NULL, /* next */ + 0, /* static_pass_number */ + TV_TRANS_MEM, /* tv_id */ + PROP_ssa | PROP_cfg, /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ + 0, /* todo_flags_finish */ + } +}; + +/* Add FLAGS to the GIMPLE_TRANSACTION subcode for the transaction region + represented by STATE. */ + +static inline void +transaction_subcode_ior (struct tm_region *region, unsigned flags) +{ + if (region && region->transaction_stmt) + { + flags |= gimple_transaction_subcode (region->transaction_stmt); + gimple_transaction_set_subcode (region->transaction_stmt, flags); + } +} + +/* Construct a memory load in a transactional context. Return the + gimple statement performing the load, or NULL if there is no + TM_LOAD builtin of the appropriate size to do the load. + + LOC is the location to use for the new statement(s). */ + +static gimple +build_tm_load (location_t loc, tree lhs, tree rhs, gimple_stmt_iterator *gsi) +{ + enum built_in_function code = END_BUILTINS; + tree t, type = TREE_TYPE (rhs), decl; + gimple gcall; + + if (type == float_type_node) + code = BUILT_IN_TM_LOAD_FLOAT; + else if (type == double_type_node) + code = BUILT_IN_TM_LOAD_DOUBLE; + else if (type == long_double_type_node) + code = BUILT_IN_TM_LOAD_LDOUBLE; + else if (TYPE_SIZE_UNIT (type) != NULL + && host_integerp (TYPE_SIZE_UNIT (type), 1)) + { + switch (tree_low_cst (TYPE_SIZE_UNIT (type), 1)) + { + case 1: + code = BUILT_IN_TM_LOAD_1; + break; + case 2: + code = BUILT_IN_TM_LOAD_2; + break; + case 4: + code = BUILT_IN_TM_LOAD_4; + break; + case 8: + code = BUILT_IN_TM_LOAD_8; + break; + } + } + + if (code == END_BUILTINS) + { + decl = targetm.vectorize.builtin_tm_load (type); + if (!decl) + return NULL; + } + else + decl = builtin_decl_explicit (code); + + t = gimplify_addr (gsi, rhs); + gcall = gimple_build_call (decl, 1, t); + gimple_set_location (gcall, loc); + + t = TREE_TYPE (TREE_TYPE (decl)); + if (useless_type_conversion_p (type, t)) + { + gimple_call_set_lhs (gcall, lhs); + gsi_insert_before (gsi, gcall, GSI_SAME_STMT); + } + else + { + gimple g; + tree temp; + + temp = make_rename_temp (t, NULL); + gimple_call_set_lhs (gcall, temp); + gsi_insert_before (gsi, gcall, GSI_SAME_STMT); + + t = fold_build1 (VIEW_CONVERT_EXPR, type, temp); + g = gimple_build_assign (lhs, t); + gsi_insert_before (gsi, g, GSI_SAME_STMT); + } + + return gcall; +} + + +/* Similarly for storing TYPE in a transactional context. */ + +static gimple +build_tm_store (location_t loc, tree lhs, tree rhs, gimple_stmt_iterator *gsi) +{ + enum built_in_function code = END_BUILTINS; + tree t, fn, type = TREE_TYPE (rhs), simple_type; + gimple gcall; + + if (type == float_type_node) + code = BUILT_IN_TM_STORE_FLOAT; + else if (type == double_type_node) + code = BUILT_IN_TM_STORE_DOUBLE; + else if (type == long_double_type_node) + code = BUILT_IN_TM_STORE_LDOUBLE; + else if (TYPE_SIZE_UNIT (type) != NULL + && host_integerp (TYPE_SIZE_UNIT (type), 1)) + { + switch (tree_low_cst (TYPE_SIZE_UNIT (type), 1)) + { + case 1: + code = BUILT_IN_TM_STORE_1; + break; + case 2: + code = BUILT_IN_TM_STORE_2; + break; + case 4: + code = BUILT_IN_TM_STORE_4; + break; + case 8: + code = BUILT_IN_TM_STORE_8; + break; + } + } + + if (code == END_BUILTINS) + { + fn = targetm.vectorize.builtin_tm_store (type); + if (!fn) + return NULL; + } + else + fn = builtin_decl_explicit (code); + + simple_type = TREE_VALUE (TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (fn)))); + + if (TREE_CODE (rhs) == CONSTRUCTOR) + { + /* Handle the easy initialization to zero. */ + if (CONSTRUCTOR_ELTS (rhs) == 0) + rhs = build_int_cst (simple_type, 0); + else + { + /* ...otherwise punt to the caller and probably use + BUILT_IN_TM_MEMMOVE, because we can't wrap a + VIEW_CONVERT_EXPR around a CONSTRUCTOR (below) and produce + valid gimple. */ + return NULL; + } + } + else if (!useless_type_conversion_p (simple_type, type)) + { + gimple g; + tree temp; + + temp = make_rename_temp (simple_type, NULL); + t = fold_build1 (VIEW_CONVERT_EXPR, simple_type, rhs); + g = gimple_build_assign (temp, t); + gimple_set_location (g, loc); + gsi_insert_before (gsi, g, GSI_SAME_STMT); + + rhs = temp; + } + + t = gimplify_addr (gsi, lhs); + gcall = gimple_build_call (fn, 2, t, rhs); + gimple_set_location (gcall, loc); + gsi_insert_before (gsi, gcall, GSI_SAME_STMT); + + return gcall; +} + + +/* Expand an assignment statement into transactional builtins. */ + +static void +expand_assign_tm (struct tm_region *region, gimple_stmt_iterator *gsi) +{ + gimple stmt = gsi_stmt (*gsi); + location_t loc = gimple_location (stmt); + tree lhs = gimple_assign_lhs (stmt); + tree rhs = gimple_assign_rhs1 (stmt); + bool store_p = requires_barrier (region->entry_block, lhs, NULL); + bool load_p = requires_barrier (region->entry_block, rhs, NULL); + gimple gcall = NULL; + + if (!load_p && !store_p) + { + /* Add thread private addresses to log if applicable. */ + requires_barrier (region->entry_block, lhs, stmt); + gsi_next (gsi); + return; + } + + gsi_remove (gsi, true); + + if (load_p && !store_p) + { + transaction_subcode_ior (region, GTMA_HAVE_LOAD); + gcall = build_tm_load (loc, lhs, rhs, gsi); + } + else if (store_p && !load_p) + { + transaction_subcode_ior (region, GTMA_HAVE_STORE); + gcall = build_tm_store (loc, lhs, rhs, gsi); + } + if (!gcall) + { + tree lhs_addr, rhs_addr; + + if (load_p) + transaction_subcode_ior (region, GTMA_HAVE_LOAD); + if (store_p) + transaction_subcode_ior (region, GTMA_HAVE_STORE); + + /* ??? Figure out if there's any possible overlap between the LHS + and the RHS and if not, use MEMCPY. */ + lhs_addr = gimplify_addr (gsi, lhs); + rhs_addr = gimplify_addr (gsi, rhs); + gcall = gimple_build_call (builtin_decl_explicit (BUILT_IN_TM_MEMMOVE), + 3, lhs_addr, rhs_addr, + TYPE_SIZE_UNIT (TREE_TYPE (lhs))); + gimple_set_location (gcall, loc); + gsi_insert_before (gsi, gcall, GSI_SAME_STMT); + } + + /* Now that we have the load/store in its instrumented form, add + thread private addresses to the log if applicable. */ + if (!store_p) + requires_barrier (region->entry_block, lhs, gcall); + + /* add_stmt_to_tm_region (region, gcall); */ +} + + +/* Expand a call statement as appropriate for a transaction. That is, + either verify that the call does not affect the transaction, or + redirect the call to a clone that handles transactions, or change + the transaction state to IRREVOCABLE. Return true if the call is + one of the builtins that end a transaction. */ + +static bool +expand_call_tm (struct tm_region *region, + gimple_stmt_iterator *gsi) +{ + gimple stmt = gsi_stmt (*gsi); + tree lhs = gimple_call_lhs (stmt); + tree fn_decl; + struct cgraph_node *node; + bool retval = false; + + fn_decl = gimple_call_fndecl (stmt); + + if (fn_decl == builtin_decl_explicit (BUILT_IN_TM_MEMCPY) + || fn_decl == builtin_decl_explicit (BUILT_IN_TM_MEMMOVE)) + transaction_subcode_ior (region, GTMA_HAVE_STORE | GTMA_HAVE_LOAD); + if (fn_decl == builtin_decl_explicit (BUILT_IN_TM_MEMSET)) + transaction_subcode_ior (region, GTMA_HAVE_STORE); + + if (is_tm_pure_call (stmt)) + return false; + + if (fn_decl) + retval = is_tm_ending_fndecl (fn_decl); + if (!retval) + { + /* Assume all non-const/pure calls write to memory, except + transaction ending builtins. */ + transaction_subcode_ior (region, GTMA_HAVE_STORE); + } + + /* For indirect calls, we already generated a call into the runtime. */ + if (!fn_decl) + { + tree fn = gimple_call_fn (stmt); + + /* We are guaranteed never to go irrevocable on a safe or pure + call, and the pure call was handled above. */ + if (is_tm_safe (fn)) + return false; + else + transaction_subcode_ior (region, GTMA_MAY_ENTER_IRREVOCABLE); + + return false; + } + + node = cgraph_get_node (fn_decl); + if (node->local.tm_may_enter_irr) + transaction_subcode_ior (region, GTMA_MAY_ENTER_IRREVOCABLE); + + if (is_tm_abort (fn_decl)) + { + transaction_subcode_ior (region, GTMA_HAVE_ABORT); + return true; + } + + /* Instrument the store if needed. + + If the assignment happens inside the function call (return slot + optimization), there is no instrumentation to be done, since + the callee should have done the right thing. */ + if (lhs && requires_barrier (region->entry_block, lhs, stmt) + && !gimple_call_return_slot_opt_p (stmt)) + { + tree tmp = make_rename_temp (TREE_TYPE (lhs), NULL); + location_t loc = gimple_location (stmt); + edge fallthru_edge = NULL; + + /* Remember if the call was going to throw. */ + if (stmt_can_throw_internal (stmt)) + { + edge_iterator ei; + edge e; + basic_block bb = gimple_bb (stmt); + + FOR_EACH_EDGE (e, ei, bb->succs) + if (e->flags & EDGE_FALLTHRU) + { + fallthru_edge = e; + break; + } + } + + gimple_call_set_lhs (stmt, tmp); + update_stmt (stmt); + stmt = gimple_build_assign (lhs, tmp); + gimple_set_location (stmt, loc); + + /* We cannot throw in the middle of a BB. If the call was going + to throw, place the instrumentation on the fallthru edge, so + the call remains the last statement in the block. */ + if (fallthru_edge) + { + gimple_seq fallthru_seq = gimple_seq_alloc_with_stmt (stmt); + gimple_stmt_iterator fallthru_gsi = gsi_start (fallthru_seq); + expand_assign_tm (region, &fallthru_gsi); + gsi_insert_seq_on_edge (fallthru_edge, fallthru_seq); + pending_edge_inserts_p = true; + } + else + { + gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING); + expand_assign_tm (region, gsi); + } + + transaction_subcode_ior (region, GTMA_HAVE_STORE); + } + + return retval; +} + + +/* Expand all statements in BB as appropriate for being inside + a transaction. */ + +static void +expand_block_tm (struct tm_region *region, basic_block bb) +{ + gimple_stmt_iterator gsi; + + for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); ) + { + gimple stmt = gsi_stmt (gsi); + switch (gimple_code (stmt)) + { + case GIMPLE_ASSIGN: + /* Only memory reads/writes need to be instrumented. */ + if (gimple_assign_single_p (stmt)) + { + expand_assign_tm (region, &gsi); + continue; + } + break; + + case GIMPLE_CALL: + if (expand_call_tm (region, &gsi)) + return; + break; + + case GIMPLE_ASM: + gcc_unreachable (); + + default: + break; + } + if (!gsi_end_p (gsi)) + gsi_next (&gsi); + } +} + +/* Return the list of basic-blocks in REGION. + + STOP_AT_IRREVOCABLE_P is true if caller is uninterested in blocks + following a TM_IRREVOCABLE call. */ + +static VEC (basic_block, heap) * +get_tm_region_blocks (basic_block entry_block, + bitmap exit_blocks, + bitmap irr_blocks, + bitmap all_region_blocks, + bool stop_at_irrevocable_p) +{ + VEC(basic_block, heap) *bbs = NULL; + unsigned i; + edge e; + edge_iterator ei; + bitmap visited_blocks = BITMAP_ALLOC (NULL); + + i = 0; + VEC_safe_push (basic_block, heap, bbs, entry_block); + bitmap_set_bit (visited_blocks, entry_block->index); + + do + { + basic_block bb = VEC_index (basic_block, bbs, i++); + + if (exit_blocks && + bitmap_bit_p (exit_blocks, bb->index)) + continue; + + if (stop_at_irrevocable_p + && irr_blocks + && bitmap_bit_p (irr_blocks, bb->index)) + continue; + + FOR_EACH_EDGE (e, ei, bb->succs) + if (!bitmap_bit_p (visited_blocks, e->dest->index)) + { + bitmap_set_bit (visited_blocks, e->dest->index); + VEC_safe_push (basic_block, heap, bbs, e->dest); + } + } + while (i < VEC_length (basic_block, bbs)); + + if (all_region_blocks) + bitmap_ior_into (all_region_blocks, visited_blocks); + + BITMAP_FREE (visited_blocks); + return bbs; +} + +/* Entry point to the MARK phase of TM expansion. Here we replace + transactional memory statements with calls to builtins, and function + calls with their transactional clones (if available). But we don't + yet lower GIMPLE_TRANSACTION or add the transaction restart back-edges. */ + +static unsigned int +execute_tm_mark (void) +{ + struct tm_region *region; + basic_block bb; + VEC (basic_block, heap) *queue; + size_t i; + + queue = VEC_alloc (basic_block, heap, 10); + pending_edge_inserts_p = false; + + for (region = all_tm_regions; region ; region = region->next) + { + tm_log_init (); + /* If we have a transaction... */ + if (region->exit_blocks) + { + unsigned int subcode + = gimple_transaction_subcode (region->transaction_stmt); + + /* Collect a new SUBCODE set, now that optimizations are done... */ + if (subcode & GTMA_DOES_GO_IRREVOCABLE) + subcode &= (GTMA_DECLARATION_MASK | GTMA_DOES_GO_IRREVOCABLE + | GTMA_MAY_ENTER_IRREVOCABLE); + else + subcode &= GTMA_DECLARATION_MASK; + gimple_transaction_set_subcode (region->transaction_stmt, subcode); + } + + queue = get_tm_region_blocks (region->entry_block, + region->exit_blocks, + region->irr_blocks, + NULL, + /*stop_at_irr_p=*/true); + for (i = 0; VEC_iterate (basic_block, queue, i, bb); ++i) + expand_block_tm (region, bb); + VEC_free (basic_block, heap, queue); + + tm_log_emit (); + } + + if (pending_edge_inserts_p) + gsi_commit_edge_inserts (); + return 0; +} + +struct gimple_opt_pass pass_tm_mark = +{ + { + GIMPLE_PASS, + "tmmark", /* name */ + NULL, /* gate */ + execute_tm_mark, /* execute */ + NULL, /* sub */ + NULL, /* next */ + 0, /* static_pass_number */ + TV_TRANS_MEM, /* tv_id */ + PROP_ssa | PROP_cfg, /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ + TODO_update_ssa + | TODO_verify_ssa + | TODO_dump_func, /* todo_flags_finish */ + } +}; + +/* Create an abnormal call edge from BB to the first block of the region + represented by STATE. Also record the edge in the TM_RESTART map. */ + +static inline void +make_tm_edge (gimple stmt, basic_block bb, struct tm_region *region) +{ + void **slot; + struct tm_restart_node *n, dummy; + + if (cfun->gimple_df->tm_restart == NULL) + cfun->gimple_df->tm_restart = htab_create_ggc (31, struct_ptr_hash, + struct_ptr_eq, ggc_free); + + dummy.stmt = stmt; + dummy.label_or_list = gimple_block_label (region->entry_block); + slot = htab_find_slot (cfun->gimple_df->tm_restart, &dummy, INSERT); + n = (struct tm_restart_node *) *slot; + if (n == NULL) + { + n = ggc_alloc_tm_restart_node (); + *n = dummy; + } + else + { + tree old = n->label_or_list; + if (TREE_CODE (old) == LABEL_DECL) + old = tree_cons (NULL, old, NULL); + n->label_or_list = tree_cons (NULL, dummy.label_or_list, old); + } + + make_edge (bb, region->entry_block, EDGE_ABNORMAL | EDGE_ABNORMAL_CALL); +} + + +/* Split block BB as necessary for every builtin function we added, and + wire up the abnormal back edges implied by the transaction restart. */ + +static void +expand_block_edges (struct tm_region *region, basic_block bb) +{ + gimple_stmt_iterator gsi; + + for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); ) + { + gimple stmt = gsi_stmt (gsi); + + /* ??? TM_COMMIT (and any other tm builtin function) in a nested + transaction has an abnormal edge back to the outer-most transaction + (there are no nested retries), while a TM_ABORT also has an abnormal + backedge to the inner-most transaction. We haven't actually saved + the inner-most transaction here. We should be able to get to it + via the region_nr saved on STMT, and read the transaction_stmt from + that, and find the first region block from there. */ + /* ??? Shouldn't we split for any non-pure, non-irrevocable function? */ + if (gimple_code (stmt) == GIMPLE_CALL + && (gimple_call_flags (stmt) & ECF_TM_BUILTIN) != 0) + { + if (gsi_one_before_end_p (gsi)) + make_tm_edge (stmt, bb, region); + else + { + edge e = split_block (bb, stmt); + make_tm_edge (stmt, bb, region); + bb = e->dest; + gsi = gsi_start_bb (bb); + } + + /* Delete any tail-call annotation that may have been added. + The tail-call pass may have mis-identified the commit as being + a candidate because we had not yet added this restart edge. */ + gimple_call_set_tail (stmt, false); + } + + gsi_next (&gsi); + } +} + +/* Expand the GIMPLE_TRANSACTION statement into the STM library call. */ + +static void +expand_transaction (struct tm_region *region) +{ + tree status, tm_start; + basic_block atomic_bb, slice_bb; + gimple_stmt_iterator gsi; + tree t1, t2; + gimple g; + int flags, subcode; + + tm_start = builtin_decl_explicit (BUILT_IN_TM_START); + status = make_rename_temp (TREE_TYPE (TREE_TYPE (tm_start)), "tm_state"); + + /* ??? There are plenty of bits here we're not computing. */ + subcode = gimple_transaction_subcode (region->transaction_stmt); + if (subcode & GTMA_DOES_GO_IRREVOCABLE) + flags = PR_DOESGOIRREVOCABLE | PR_UNINSTRUMENTEDCODE; + else + flags = PR_INSTRUMENTEDCODE; + if ((subcode & GTMA_MAY_ENTER_IRREVOCABLE) == 0) + flags |= PR_HASNOIRREVOCABLE; + /* If the transaction does not have an abort in lexical scope and is not + marked as an outer transaction, then it will never abort. */ + if ((subcode & GTMA_HAVE_ABORT) == 0 + && (subcode & GTMA_IS_OUTER) == 0) + flags |= PR_HASNOABORT; + if ((subcode & GTMA_HAVE_STORE) == 0) + flags |= PR_READONLY; + t2 = build_int_cst (TREE_TYPE (status), flags); + g = gimple_build_call (tm_start, 1, t2); + gimple_call_set_lhs (g, status); + gimple_set_location (g, gimple_location (region->transaction_stmt)); + + atomic_bb = gimple_bb (region->transaction_stmt); + + if (!VEC_empty (tree, tm_log_save_addresses)) + tm_log_emit_saves (region->entry_block, atomic_bb); + + gsi = gsi_last_bb (atomic_bb); + gsi_insert_before (&gsi, g, GSI_SAME_STMT); + gsi_remove (&gsi, true); + + if (!VEC_empty (tree, tm_log_save_addresses)) + region->entry_block = + tm_log_emit_save_or_restores (region->entry_block, + A_RESTORELIVEVARIABLES, + status, + tm_log_emit_restores, + atomic_bb, + FALLTHRU_EDGE (atomic_bb), + &slice_bb); + else + slice_bb = atomic_bb; + + /* If we have an ABORT statement, create a test following the start + call to perform the abort. */ + if (gimple_transaction_label (region->transaction_stmt)) + { + edge e; + basic_block test_bb; + + test_bb = create_empty_bb (slice_bb); + if (VEC_empty (tree, tm_log_save_addresses)) + region->entry_block = test_bb; + gsi = gsi_last_bb (test_bb); + + t1 = make_rename_temp (TREE_TYPE (status), NULL); + t2 = build_int_cst (TREE_TYPE (status), A_ABORTTRANSACTION); + g = gimple_build_assign_with_ops (BIT_AND_EXPR, t1, status, t2); + gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING); + + t2 = build_int_cst (TREE_TYPE (status), 0); + g = gimple_build_cond (NE_EXPR, t1, t2, NULL, NULL); + gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING); + + e = FALLTHRU_EDGE (slice_bb); + redirect_edge_pred (e, test_bb); + e->flags = EDGE_FALSE_VALUE; + e->probability = PROB_ALWAYS - PROB_VERY_UNLIKELY; + + e = BRANCH_EDGE (atomic_bb); + redirect_edge_pred (e, test_bb); + e->flags = EDGE_TRUE_VALUE; + e->probability = PROB_VERY_UNLIKELY; + + e = make_edge (slice_bb, test_bb, EDGE_FALLTHRU); + } + + /* If we've no abort, but we do have PHIs at the beginning of the atomic + region, that means we've a loop at the beginning of the atomic region + that shares the first block. This can cause problems with the abnormal + edges we're about to add for the transaction restart. Solve this by + adding a new empty block to receive the abnormal edges. */ + else if (phi_nodes (region->entry_block)) + { + edge e; + basic_block empty_bb; + + region->entry_block = empty_bb = create_empty_bb (atomic_bb); + + e = FALLTHRU_EDGE (atomic_bb); + redirect_edge_pred (e, empty_bb); + + e = make_edge (atomic_bb, empty_bb, EDGE_FALLTHRU); + } + + /* The GIMPLE_TRANSACTION statement no longer exists. */ + region->transaction_stmt = NULL; +} + +static void expand_regions (struct tm_region *); + +/* Helper function for expand_regions. Expand REGION and recurse to + the inner region. */ + +static void +expand_regions_1 (struct tm_region *region) +{ + if (region->exit_blocks) + { + unsigned int i; + basic_block bb; + VEC (basic_block, heap) *queue; + + /* Collect the set of blocks in this region. Do this before + splitting edges, so that we don't have to play with the + dominator tree in the middle. */ + queue = get_tm_region_blocks (region->entry_block, + region->exit_blocks, + region->irr_blocks, + NULL, + /*stop_at_irr_p=*/false); + expand_transaction (region); + for (i = 0; VEC_iterate (basic_block, queue, i, bb); ++i) + expand_block_edges (region, bb); + VEC_free (basic_block, heap, queue); + } + if (region->inner) + expand_regions (region->inner); +} + +/* Expand regions starting at REGION. */ + +static void +expand_regions (struct tm_region *region) +{ + while (region) + { + expand_regions_1 (region); + region = region->next; + } +} + +/* Entry point to the final expansion of transactional nodes. */ + +static unsigned int +execute_tm_edges (void) +{ + expand_regions (all_tm_regions); + tm_log_delete (); + + /* We've got to release the dominance info now, to indicate that it + must be rebuilt completely. Otherwise we'll crash trying to update + the SSA web in the TODO section following this pass. */ + free_dominance_info (CDI_DOMINATORS); + bitmap_obstack_release (&tm_obstack); + all_tm_regions = NULL; + + return 0; +} + +struct gimple_opt_pass pass_tm_edges = +{ + { + GIMPLE_PASS, + "tmedge", /* name */ + NULL, /* gate */ + execute_tm_edges, /* execute */ + NULL, /* sub */ + NULL, /* next */ + 0, /* static_pass_number */ + TV_TRANS_MEM, /* tv_id */ + PROP_ssa | PROP_cfg, /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ + TODO_update_ssa + | TODO_verify_ssa + | TODO_dump_func, /* todo_flags_finish */ + } +}; + +/* A unique TM memory operation. */ +typedef struct tm_memop +{ + /* Unique ID that all memory operations to the same location have. */ + unsigned int value_id; + /* Address of load/store. */ + tree addr; +} *tm_memop_t; + +/* Sets for solving data flow equations in the memory optimization pass. */ +struct tm_memopt_bitmaps +{ + /* Stores available to this BB upon entry. Basically, stores that + dominate this BB. */ + bitmap store_avail_in; + /* Stores available at the end of this BB. */ + bitmap store_avail_out; + bitmap store_antic_in; + bitmap store_antic_out; + /* Reads available to this BB upon entry. Basically, reads that + dominate this BB. */ + bitmap read_avail_in; + /* Reads available at the end of this BB. */ + bitmap read_avail_out; + /* Reads performed in this BB. */ + bitmap read_local; + /* Writes performed in this BB. */ + bitmap store_local; + + /* Temporary storage for pass. */ + /* Is the current BB in the worklist? */ + bool avail_in_worklist_p; + /* Have we visited this BB? */ + bool visited_p; +}; + +static bitmap_obstack tm_memopt_obstack; + +/* Unique counter for TM loads and stores. Loads and stores of the + same address get the same ID. */ +static unsigned int tm_memopt_value_id; +static htab_t tm_memopt_value_numbers; + +#define STORE_AVAIL_IN(BB) \ + ((struct tm_memopt_bitmaps *) ((BB)->aux))->store_avail_in +#define STORE_AVAIL_OUT(BB) \ + ((struct tm_memopt_bitmaps *) ((BB)->aux))->store_avail_out +#define STORE_ANTIC_IN(BB) \ + ((struct tm_memopt_bitmaps *) ((BB)->aux))->store_antic_in +#define STORE_ANTIC_OUT(BB) \ + ((struct tm_memopt_bitmaps *) ((BB)->aux))->store_antic_out +#define READ_AVAIL_IN(BB) \ + ((struct tm_memopt_bitmaps *) ((BB)->aux))->read_avail_in +#define READ_AVAIL_OUT(BB) \ + ((struct tm_memopt_bitmaps *) ((BB)->aux))->read_avail_out +#define READ_LOCAL(BB) \ + ((struct tm_memopt_bitmaps *) ((BB)->aux))->read_local +#define STORE_LOCAL(BB) \ + ((struct tm_memopt_bitmaps *) ((BB)->aux))->store_local +#define AVAIL_IN_WORKLIST_P(BB) \ + ((struct tm_memopt_bitmaps *) ((BB)->aux))->avail_in_worklist_p +#define BB_VISITED_P(BB) \ + ((struct tm_memopt_bitmaps *) ((BB)->aux))->visited_p + +/* Htab support. Return a hash value for a `tm_memop'. */ +static hashval_t +tm_memop_hash (const void *p) +{ + const struct tm_memop *mem = (const struct tm_memop *) p; + tree addr = mem->addr; + /* We drill down to the SSA_NAME/DECL for the hash, but equality is + actually done with operand_equal_p (see tm_memop_eq). */ + if (TREE_CODE (addr) == ADDR_EXPR) + addr = TREE_OPERAND (addr, 0); + return iterative_hash_expr (addr, 0); +} + +/* Htab support. Return true if two tm_memop's are the same. */ +static int +tm_memop_eq (const void *p1, const void *p2) +{ + const struct tm_memop *mem1 = (const struct tm_memop *) p1; + const struct tm_memop *mem2 = (const struct tm_memop *) p2; + + return operand_equal_p (mem1->addr, mem2->addr, 0); +} + +/* Given a TM load/store in STMT, return the value number for the address + it accesses. */ + +static unsigned int +tm_memopt_value_number (gimple stmt, enum insert_option op) +{ + struct tm_memop tmpmem, *mem; + void **slot; + + gcc_assert (is_tm_load (stmt) || is_tm_store (stmt)); + tmpmem.addr = gimple_call_arg (stmt, 0); + slot = htab_find_slot (tm_memopt_value_numbers, &tmpmem, op); + if (*slot) + mem = (struct tm_memop *) *slot; + else if (op == INSERT) + { + mem = XNEW (struct tm_memop); + *slot = mem; + mem->value_id = tm_memopt_value_id++; + mem->addr = tmpmem.addr; + } + else + gcc_unreachable (); + return mem->value_id; +} + +/* Accumulate TM memory operations in BB into STORE_LOCAL and READ_LOCAL. */ + +static void +tm_memopt_accumulate_memops (basic_block bb) +{ + gimple_stmt_iterator gsi; + + for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) + { + gimple stmt = gsi_stmt (gsi); + bitmap bits; + unsigned int loc; + + if (is_tm_store (stmt)) + bits = STORE_LOCAL (bb); + else if (is_tm_load (stmt)) + bits = READ_LOCAL (bb); + else + continue; + + loc = tm_memopt_value_number (stmt, INSERT); + bitmap_set_bit (bits, loc); + if (dump_file) + { + fprintf (dump_file, "TM memopt (%s): value num=%d, BB=%d, addr=", + is_tm_load (stmt) ? "LOAD" : "STORE", loc, + gimple_bb (stmt)->index); + print_generic_expr (dump_file, gimple_call_arg (stmt, 0), 0); + fprintf (dump_file, "\n"); + } + } +} + +/* Prettily dump one of the memopt sets. BITS is the bitmap to dump. */ + +static void +dump_tm_memopt_set (const char *set_name, bitmap bits) +{ + unsigned i; + bitmap_iterator bi; + const char *comma = ""; + + fprintf (dump_file, "TM memopt: %s: [", set_name); + EXECUTE_IF_SET_IN_BITMAP (bits, 0, i, bi) + { + htab_iterator hi; + struct tm_memop *mem; + + /* Yeah, yeah, yeah. Whatever. This is just for debugging. */ + FOR_EACH_HTAB_ELEMENT (tm_memopt_value_numbers, mem, tm_memop_t, hi) + if (mem->value_id == i) + break; + gcc_assert (mem->value_id == i); + fprintf (dump_file, "%s", comma); + comma = ", "; + print_generic_expr (dump_file, mem->addr, 0); + } + fprintf (dump_file, "]\n"); +} + +/* Prettily dump all of the memopt sets in BLOCKS. */ + +static void +dump_tm_memopt_sets (VEC (basic_block, heap) *blocks) +{ + size_t i; + basic_block bb; + + for (i = 0; VEC_iterate (basic_block, blocks, i, bb); ++i) + { + fprintf (dump_file, "------------BB %d---------\n", bb->index); + dump_tm_memopt_set ("STORE_LOCAL", STORE_LOCAL (bb)); + dump_tm_memopt_set ("READ_LOCAL", READ_LOCAL (bb)); + dump_tm_memopt_set ("STORE_AVAIL_IN", STORE_AVAIL_IN (bb)); + dump_tm_memopt_set ("STORE_AVAIL_OUT", STORE_AVAIL_OUT (bb)); + dump_tm_memopt_set ("READ_AVAIL_IN", READ_AVAIL_IN (bb)); + dump_tm_memopt_set ("READ_AVAIL_OUT", READ_AVAIL_OUT (bb)); + } +} + +/* Compute {STORE,READ}_AVAIL_IN for the basic block BB. */ + +static void +tm_memopt_compute_avin (basic_block bb) +{ + edge e; + unsigned ix; + + /* Seed with the AVOUT of any predecessor. */ + for (ix = 0; ix < EDGE_COUNT (bb->preds); ix++) + { + e = EDGE_PRED (bb, ix); + /* Make sure we have already visited this BB, and is thus + initialized. + + If e->src->aux is NULL, this predecessor is actually on an + enclosing transaction. We only care about the current + transaction, so ignore it. */ + if (e->src->aux && BB_VISITED_P (e->src)) + { + bitmap_copy (STORE_AVAIL_IN (bb), STORE_AVAIL_OUT (e->src)); + bitmap_copy (READ_AVAIL_IN (bb), READ_AVAIL_OUT (e->src)); + break; + } + } + + for (; ix < EDGE_COUNT (bb->preds); ix++) + { + e = EDGE_PRED (bb, ix); + if (e->src->aux && BB_VISITED_P (e->src)) + { + bitmap_and_into (STORE_AVAIL_IN (bb), STORE_AVAIL_OUT (e->src)); + bitmap_and_into (READ_AVAIL_IN (bb), READ_AVAIL_OUT (e->src)); + } + } + + BB_VISITED_P (bb) = true; +} + +/* Compute the STORE_ANTIC_IN for the basic block BB. */ + +static void +tm_memopt_compute_antin (basic_block bb) +{ + edge e; + unsigned ix; + + /* Seed with the ANTIC_OUT of any successor. */ + for (ix = 0; ix < EDGE_COUNT (bb->succs); ix++) + { + e = EDGE_SUCC (bb, ix); + /* Make sure we have already visited this BB, and is thus + initialized. */ + if (BB_VISITED_P (e->dest)) + { + bitmap_copy (STORE_ANTIC_IN (bb), STORE_ANTIC_OUT (e->dest)); + break; + } + } + + for (; ix < EDGE_COUNT (bb->succs); ix++) + { + e = EDGE_SUCC (bb, ix); + if (BB_VISITED_P (e->dest)) + bitmap_and_into (STORE_ANTIC_IN (bb), STORE_ANTIC_OUT (e->dest)); + } + + BB_VISITED_P (bb) = true; +} + +/* Compute the AVAIL sets for every basic block in BLOCKS. + + We compute {STORE,READ}_AVAIL_{OUT,IN} as follows: + + AVAIL_OUT[bb] = union (AVAIL_IN[bb], LOCAL[bb]) + AVAIL_IN[bb] = intersect (AVAIL_OUT[predecessors]) + + This is basically what we do in lcm's compute_available(), but here + we calculate two sets of sets (one for STOREs and one for READs), + and we work on a region instead of the entire CFG. + + REGION is the TM region. + BLOCKS are the basic blocks in the region. */ + +static void +tm_memopt_compute_available (struct tm_region *region, + VEC (basic_block, heap) *blocks) +{ + edge e; + basic_block *worklist, *qin, *qout, *qend, bb; + unsigned int qlen, i; + edge_iterator ei; + bool changed; + + /* Allocate a worklist array/queue. Entries are only added to the + list if they were not already on the list. So the size is + bounded by the number of basic blocks in the region. */ + qlen = VEC_length (basic_block, blocks) - 1; + qin = qout = worklist = + XNEWVEC (basic_block, qlen); + + /* Put every block in the region on the worklist. */ + for (i = 0; VEC_iterate (basic_block, blocks, i, bb); ++i) + { + /* Seed AVAIL_OUT with the LOCAL set. */ + bitmap_ior_into (STORE_AVAIL_OUT (bb), STORE_LOCAL (bb)); + bitmap_ior_into (READ_AVAIL_OUT (bb), READ_LOCAL (bb)); + + AVAIL_IN_WORKLIST_P (bb) = true; + /* No need to insert the entry block, since it has an AVIN of + null, and an AVOUT that has already been seeded in. */ + if (bb != region->entry_block) + *qin++ = bb; + } + + /* The entry block has been initialized with the local sets. */ + BB_VISITED_P (region->entry_block) = true; + + qin = worklist; + qend = &worklist[qlen]; + + /* Iterate until the worklist is empty. */ + while (qlen) + { + /* Take the first entry off the worklist. */ + bb = *qout++; + qlen--; + + if (qout >= qend) + qout = worklist; + + /* This block can be added to the worklist again if necessary. */ + AVAIL_IN_WORKLIST_P (bb) = false; + tm_memopt_compute_avin (bb); + + /* Note: We do not add the LOCAL sets here because we already + seeded the AVAIL_OUT sets with them. */ + changed = bitmap_ior_into (STORE_AVAIL_OUT (bb), STORE_AVAIL_IN (bb)); + changed |= bitmap_ior_into (READ_AVAIL_OUT (bb), READ_AVAIL_IN (bb)); + if (changed + && (region->exit_blocks == NULL + || !bitmap_bit_p (region->exit_blocks, bb->index))) + /* If the out state of this block changed, then we need to add + its successors to the worklist if they are not already in. */ + FOR_EACH_EDGE (e, ei, bb->succs) + if (!AVAIL_IN_WORKLIST_P (e->dest) && e->dest != EXIT_BLOCK_PTR) + { + *qin++ = e->dest; + AVAIL_IN_WORKLIST_P (e->dest) = true; + qlen++; + + if (qin >= qend) + qin = worklist; + } + } + + free (worklist); + + if (dump_file) + dump_tm_memopt_sets (blocks); +} + +/* Compute ANTIC sets for every basic block in BLOCKS. + + We compute STORE_ANTIC_OUT as follows: + + STORE_ANTIC_OUT[bb] = union(STORE_ANTIC_IN[bb], STORE_LOCAL[bb]) + STORE_ANTIC_IN[bb] = intersect(STORE_ANTIC_OUT[successors]) + + REGION is the TM region. + BLOCKS are the basic blocks in the region. */ + +static void +tm_memopt_compute_antic (struct tm_region *region, + VEC (basic_block, heap) *blocks) +{ + edge e; + basic_block *worklist, *qin, *qout, *qend, bb; + unsigned int qlen; + int i; + edge_iterator ei; + + /* Allocate a worklist array/queue. Entries are only added to the + list if they were not already on the list. So the size is + bounded by the number of basic blocks in the region. */ + qin = qout = worklist = + XNEWVEC (basic_block, VEC_length (basic_block, blocks)); + + for (qlen = 0, i = VEC_length (basic_block, blocks) - 1; i >= 0; --i) + { + bb = VEC_index (basic_block, blocks, i); + + /* Seed ANTIC_OUT with the LOCAL set. */ + bitmap_ior_into (STORE_ANTIC_OUT (bb), STORE_LOCAL (bb)); + + /* Put every block in the region on the worklist. */ + AVAIL_IN_WORKLIST_P (bb) = true; + /* No need to insert exit blocks, since their ANTIC_IN is NULL, + and their ANTIC_OUT has already been seeded in. */ + if (region->exit_blocks + && !bitmap_bit_p (region->exit_blocks, bb->index)) + { + qlen++; + *qin++ = bb; + } + } + + /* The exit blocks have been initialized with the local sets. */ + if (region->exit_blocks) + { + unsigned int i; + bitmap_iterator bi; + EXECUTE_IF_SET_IN_BITMAP (region->exit_blocks, 0, i, bi) + BB_VISITED_P (BASIC_BLOCK (i)) = true; + } + + qin = worklist; + qend = &worklist[qlen]; + + /* Iterate until the worklist is empty. */ + while (qlen) + { + /* Take the first entry off the worklist. */ + bb = *qout++; + qlen--; + + if (qout >= qend) + qout = worklist; + + /* This block can be added to the worklist again if necessary. */ + AVAIL_IN_WORKLIST_P (bb) = false; + tm_memopt_compute_antin (bb); + + /* Note: We do not add the LOCAL sets here because we already + seeded the ANTIC_OUT sets with them. */ + if (bitmap_ior_into (STORE_ANTIC_OUT (bb), STORE_ANTIC_IN (bb)) + && bb != region->entry_block) + /* If the out state of this block changed, then we need to add + its predecessors to the worklist if they are not already in. */ + FOR_EACH_EDGE (e, ei, bb->preds) + if (!AVAIL_IN_WORKLIST_P (e->src)) + { + *qin++ = e->src; + AVAIL_IN_WORKLIST_P (e->src) = true; + qlen++; + + if (qin >= qend) + qin = worklist; + } + } + + free (worklist); + + if (dump_file) + dump_tm_memopt_sets (blocks); +} + +/* Offsets of load variants from TM_LOAD. For example, + BUILT_IN_TM_LOAD_RAR* is an offset of 1 from BUILT_IN_TM_LOAD*. + See gtm-builtins.def. */ +#define TRANSFORM_RAR 1 +#define TRANSFORM_RAW 2 +#define TRANSFORM_RFW 3 +/* Offsets of store variants from TM_STORE. */ +#define TRANSFORM_WAR 1 +#define TRANSFORM_WAW 2 + +/* Inform about a load/store optimization. */ + +static void +dump_tm_memopt_transform (gimple stmt) +{ + if (dump_file) + { + fprintf (dump_file, "TM memopt: transforming: "); + print_gimple_stmt (dump_file, stmt, 0, 0); + fprintf (dump_file, "\n"); + } +} + +/* Perform a read/write optimization. Replaces the TM builtin in STMT + by a builtin that is OFFSET entries down in the builtins table in + gtm-builtins.def. */ + +static void +tm_memopt_transform_stmt (unsigned int offset, + gimple stmt, + gimple_stmt_iterator *gsi) +{ + tree fn = gimple_call_fn (stmt); + gcc_assert (TREE_CODE (fn) == ADDR_EXPR); + TREE_OPERAND (fn, 0) + = builtin_decl_explicit ((enum built_in_function) + (DECL_FUNCTION_CODE (TREE_OPERAND (fn, 0)) + + offset)); + gimple_call_set_fn (stmt, fn); + gsi_replace (gsi, stmt, true); + dump_tm_memopt_transform (stmt); +} + +/* Perform the actual TM memory optimization transformations in the + basic blocks in BLOCKS. */ + +static void +tm_memopt_transform_blocks (VEC (basic_block, heap) *blocks) +{ + size_t i; + basic_block bb; + gimple_stmt_iterator gsi; + + for (i = 0; VEC_iterate (basic_block, blocks, i, bb); ++i) + { + for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) + { + gimple stmt = gsi_stmt (gsi); + bitmap read_avail = READ_AVAIL_IN (bb); + bitmap store_avail = STORE_AVAIL_IN (bb); + bitmap store_antic = STORE_ANTIC_OUT (bb); + unsigned int loc; + + if (is_tm_simple_load (stmt)) + { + loc = tm_memopt_value_number (stmt, NO_INSERT); + if (store_avail && bitmap_bit_p (store_avail, loc)) + tm_memopt_transform_stmt (TRANSFORM_RAW, stmt, &gsi); + else if (store_antic && bitmap_bit_p (store_antic, loc)) + { + tm_memopt_transform_stmt (TRANSFORM_RFW, stmt, &gsi); + bitmap_set_bit (store_avail, loc); + } + else if (read_avail && bitmap_bit_p (read_avail, loc)) + tm_memopt_transform_stmt (TRANSFORM_RAR, stmt, &gsi); + else + bitmap_set_bit (read_avail, loc); + } + else if (is_tm_simple_store (stmt)) + { + loc = tm_memopt_value_number (stmt, NO_INSERT); + if (store_avail && bitmap_bit_p (store_avail, loc)) + tm_memopt_transform_stmt (TRANSFORM_WAW, stmt, &gsi); + else + { + if (read_avail && bitmap_bit_p (read_avail, loc)) + tm_memopt_transform_stmt (TRANSFORM_WAR, stmt, &gsi); + bitmap_set_bit (store_avail, loc); + } + } + } + } +} + +/* Return a new set of bitmaps for a BB. */ + +static struct tm_memopt_bitmaps * +tm_memopt_init_sets (void) +{ + struct tm_memopt_bitmaps *b + = XOBNEW (&tm_memopt_obstack.obstack, struct tm_memopt_bitmaps); + b->store_avail_in = BITMAP_ALLOC (&tm_memopt_obstack); + b->store_avail_out = BITMAP_ALLOC (&tm_memopt_obstack); + b->store_antic_in = BITMAP_ALLOC (&tm_memopt_obstack); + b->store_antic_out = BITMAP_ALLOC (&tm_memopt_obstack); + b->store_avail_out = BITMAP_ALLOC (&tm_memopt_obstack); + b->read_avail_in = BITMAP_ALLOC (&tm_memopt_obstack); + b->read_avail_out = BITMAP_ALLOC (&tm_memopt_obstack); + b->read_local = BITMAP_ALLOC (&tm_memopt_obstack); + b->store_local = BITMAP_ALLOC (&tm_memopt_obstack); + return b; +} + +/* Free sets computed for each BB. */ + +static void +tm_memopt_free_sets (VEC (basic_block, heap) *blocks) +{ + size_t i; + basic_block bb; + + for (i = 0; VEC_iterate (basic_block, blocks, i, bb); ++i) + bb->aux = NULL; +} + +/* Clear the visited bit for every basic block in BLOCKS. */ + +static void +tm_memopt_clear_visited (VEC (basic_block, heap) *blocks) +{ + size_t i; + basic_block bb; + + for (i = 0; VEC_iterate (basic_block, blocks, i, bb); ++i) + BB_VISITED_P (bb) = false; +} + +/* Replace TM load/stores with hints for the runtime. We handle + things like read-after-write, write-after-read, read-after-read, + read-for-write, etc. */ + +static unsigned int +execute_tm_memopt (void) +{ + struct tm_region *region; + VEC (basic_block, heap) *bbs; + + tm_memopt_value_id = 0; + tm_memopt_value_numbers = htab_create (10, tm_memop_hash, tm_memop_eq, free); + + for (region = all_tm_regions; region; region = region->next) + { + /* All the TM stores/loads in the current region. */ + size_t i; + basic_block bb; + + bitmap_obstack_initialize (&tm_memopt_obstack); + + /* Save all BBs for the current region. */ + bbs = get_tm_region_blocks (region->entry_block, + region->exit_blocks, + region->irr_blocks, + NULL, + false); + + /* Collect all the memory operations. */ + for (i = 0; VEC_iterate (basic_block, bbs, i, bb); ++i) + { + bb->aux = tm_memopt_init_sets (); + tm_memopt_accumulate_memops (bb); + } + + /* Solve data flow equations and transform each block accordingly. */ + tm_memopt_clear_visited (bbs); + tm_memopt_compute_available (region, bbs); + tm_memopt_clear_visited (bbs); + tm_memopt_compute_antic (region, bbs); + tm_memopt_transform_blocks (bbs); + + tm_memopt_free_sets (bbs); + VEC_free (basic_block, heap, bbs); + bitmap_obstack_release (&tm_memopt_obstack); + htab_empty (tm_memopt_value_numbers); + } + + htab_delete (tm_memopt_value_numbers); + return 0; +} + +static bool +gate_tm_memopt (void) +{ + return flag_tm && optimize > 0; +} + +struct gimple_opt_pass pass_tm_memopt = +{ + { + GIMPLE_PASS, + "tmmemopt", /* name */ + gate_tm_memopt, /* gate */ + execute_tm_memopt, /* execute */ + NULL, /* sub */ + NULL, /* next */ + 0, /* static_pass_number */ + TV_TRANS_MEM, /* tv_id */ + PROP_ssa | PROP_cfg, /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ + TODO_dump_func, /* todo_flags_finish */ + } +}; + + +/* Interprocedual analysis for the creation of transactional clones. + The aim of this pass is to find which functions are referenced in + a non-irrevocable transaction context, and for those over which + we have control (or user directive), create a version of the + function which uses only the transactional interface to reference + protected memories. This analysis proceeds in several steps: + + (1) Collect the set of all possible transactional clones: + + (a) For all local public functions marked tm_callable, push + it onto the tm_callee queue. + + (b) For all local functions, scan for calls in transaction blocks. + Push the caller and callee onto the tm_caller and tm_callee + queues. Count the number of callers for each callee. + + (c) For each local function on the callee list, assume we will + create a transactional clone. Push *all* calls onto the + callee queues; count the number of clone callers separately + to the number of original callers. + + (2) Propagate irrevocable status up the dominator tree: + + (a) Any external function on the callee list that is not marked + tm_callable is irrevocable. Push all callers of such onto + a worklist. + + (b) For each function on the worklist, mark each block that + contains an irrevocable call. Use the AND operator to + propagate that mark up the dominator tree. + + (c) If we reach the entry block for a possible transactional + clone, then the transactional clone is irrevocable, and + we should not create the clone after all. Push all + callers onto the worklist. + + (d) Place tm_irrevocable calls at the beginning of the relevant + blocks. Special case here is the entry block for the entire + transaction region; there we mark it GTMA_DOES_GO_IRREVOCABLE for + the library to begin the region in serial mode. Decrement + the call count for all callees in the irrevocable region. + + (3) Create the transactional clones: + + Any tm_callee that still has a non-zero call count is cloned. +*/ + +/* This structure is stored in the AUX field of each cgraph_node. */ +struct tm_ipa_cg_data +{ + /* The clone of the function that got created. */ + struct cgraph_node *clone; + + /* The tm regions in the normal function. */ + struct tm_region *all_tm_regions; + + /* The blocks of the normal/clone functions that contain irrevocable + calls, or blocks that are post-dominated by irrevocable calls. */ + bitmap irrevocable_blocks_normal; + bitmap irrevocable_blocks_clone; + + /* The blocks of the normal function that are involved in transactions. */ + bitmap transaction_blocks_normal; + + /* The number of callers to the transactional clone of this function + from normal and transactional clones respectively. */ + unsigned tm_callers_normal; + unsigned tm_callers_clone; + + /* True if all calls to this function's transactional clone + are irrevocable. Also automatically true if the function + has no transactional clone. */ + bool is_irrevocable; + + /* Flags indicating the presence of this function in various queues. */ + bool in_callee_queue; + bool in_worklist; + + /* Flags indicating the kind of scan desired while in the worklist. */ + bool want_irr_scan_normal; +}; + +typedef struct cgraph_node *cgraph_node_p; + +DEF_VEC_P (cgraph_node_p); +DEF_VEC_ALLOC_P (cgraph_node_p, heap); + +typedef VEC (cgraph_node_p, heap) *cgraph_node_queue; + +/* Return the ipa data associated with NODE, allocating zeroed memory + if necessary. */ + +static struct tm_ipa_cg_data * +get_cg_data (struct cgraph_node *node) +{ + struct tm_ipa_cg_data *d = (struct tm_ipa_cg_data *) node->aux; + + if (d == NULL) + { + d = (struct tm_ipa_cg_data *) + obstack_alloc (&tm_obstack.obstack, sizeof (*d)); + node->aux = (void *) d; + memset (d, 0, sizeof (*d)); + } + + return d; +} + +/* Add NODE to the end of QUEUE, unless IN_QUEUE_P indicates that + it is already present. */ + +static void +maybe_push_queue (struct cgraph_node *node, + cgraph_node_queue *queue_p, bool *in_queue_p) +{ + if (!*in_queue_p) + { + *in_queue_p = true; + VEC_safe_push (cgraph_node_p, heap, *queue_p, node); + } +} + +/* A subroutine of ipa_tm_scan_calls_transaction and ipa_tm_scan_calls_clone. + Queue all callees within block BB. */ + +static void +ipa_tm_scan_calls_block (cgraph_node_queue *callees_p, + basic_block bb, bool for_clone) +{ + gimple_stmt_iterator gsi; + + for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) + { + gimple stmt = gsi_stmt (gsi); + if (is_gimple_call (stmt) && !is_tm_pure_call (stmt)) + { + tree fndecl = gimple_call_fndecl (stmt); + if (fndecl) + { + struct tm_ipa_cg_data *d; + unsigned *pcallers; + struct cgraph_node *node; + + if (is_tm_ending_fndecl (fndecl)) + continue; + if (find_tm_replacement_function (fndecl)) + continue; + + node = cgraph_get_node (fndecl); + gcc_assert (node != NULL); + d = get_cg_data (node); + + pcallers = (for_clone ? &d->tm_callers_clone + : &d->tm_callers_normal); + *pcallers += 1; + + maybe_push_queue (node, callees_p, &d->in_callee_queue); + } + } + } +} + +/* Scan all calls in NODE that are within a transaction region, + and push the resulting nodes into the callee queue. */ + +static void +ipa_tm_scan_calls_transaction (struct tm_ipa_cg_data *d, + cgraph_node_queue *callees_p) +{ + struct tm_region *r; + + d->transaction_blocks_normal = BITMAP_ALLOC (&tm_obstack); + d->all_tm_regions = all_tm_regions; + + for (r = all_tm_regions; r; r = r->next) + { + VEC (basic_block, heap) *bbs; + basic_block bb; + unsigned i; + + bbs = get_tm_region_blocks (r->entry_block, r->exit_blocks, NULL, + d->transaction_blocks_normal, false); + + FOR_EACH_VEC_ELT (basic_block, bbs, i, bb) + ipa_tm_scan_calls_block (callees_p, bb, false); + + VEC_free (basic_block, heap, bbs); + } +} + +/* Scan all calls in NODE as if this is the transactional clone, + and push the destinations into the callee queue. */ + +static void +ipa_tm_scan_calls_clone (struct cgraph_node *node, + cgraph_node_queue *callees_p) +{ + struct function *fn = DECL_STRUCT_FUNCTION (node->decl); + basic_block bb; + + FOR_EACH_BB_FN (bb, fn) + ipa_tm_scan_calls_block (callees_p, bb, true); +} + +/* The function NODE has been detected to be irrevocable. Push all + of its callers onto WORKLIST for the purpose of re-scanning them. */ + +static void +ipa_tm_note_irrevocable (struct cgraph_node *node, + cgraph_node_queue *worklist_p) +{ + struct tm_ipa_cg_data *d = get_cg_data (node); + struct cgraph_edge *e; + + d->is_irrevocable = true; + + for (e = node->callers; e ; e = e->next_caller) + { + basic_block bb; + + /* Don't examine recursive calls. */ + if (e->caller == node) + continue; + /* Even if we think we can go irrevocable, believe the user + above all. */ + if (is_tm_safe_or_pure (e->caller->decl)) + continue; + + d = get_cg_data (e->caller); + + /* Check if the callee is in a transactional region. If so, + schedule the function for normal re-scan as well. */ + bb = gimple_bb (e->call_stmt); + gcc_assert (bb != NULL); + if (d->transaction_blocks_normal + && bitmap_bit_p (d->transaction_blocks_normal, bb->index)) + d->want_irr_scan_normal = true; + + maybe_push_queue (e->caller, worklist_p, &d->in_worklist); + } +} + +/* A subroutine of ipa_tm_scan_irr_blocks; return true iff any statement + within the block is irrevocable. */ + +static bool +ipa_tm_scan_irr_block (basic_block bb) +{ + gimple_stmt_iterator gsi; + tree fn; + + for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) + { + gimple stmt = gsi_stmt (gsi); + switch (gimple_code (stmt)) + { + case GIMPLE_CALL: + if (is_tm_pure_call (stmt)) + break; + + fn = gimple_call_fn (stmt); + + /* Functions with the attribute are by definition irrevocable. */ + if (is_tm_irrevocable (fn)) + return true; + + /* For direct function calls, go ahead and check for replacement + functions, or transitive irrevocable functions. For indirect + functions, we'll ask the runtime. */ + if (TREE_CODE (fn) == ADDR_EXPR) + { + struct tm_ipa_cg_data *d; + + fn = TREE_OPERAND (fn, 0); + if (is_tm_ending_fndecl (fn)) + break; + if (find_tm_replacement_function (fn)) + break; + + d = get_cg_data (cgraph_get_node (fn)); + if (d->is_irrevocable) + return true; + } + break; + + case GIMPLE_ASM: + /* ??? The Approved Method of indicating that an inline + assembly statement is not relevant to the transaction + is to wrap it in a __tm_waiver block. This is not + yet implemented, so we can't check for it. */ + return true; + + default: + break; + } + } + + return false; +} + +/* For each of the blocks seeded witin PQUEUE, walk the CFG looking + for new irrevocable blocks, marking them in NEW_IRR. Don't bother + scanning past OLD_IRR or EXIT_BLOCKS. */ + +static bool +ipa_tm_scan_irr_blocks (VEC (basic_block, heap) **pqueue, bitmap new_irr, + bitmap old_irr, bitmap exit_blocks) +{ + bool any_new_irr = false; + edge e; + edge_iterator ei; + bitmap visited_blocks = BITMAP_ALLOC (NULL); + + do + { + basic_block bb = VEC_pop (basic_block, *pqueue); + + /* Don't re-scan blocks we know already are irrevocable. */ + if (old_irr && bitmap_bit_p (old_irr, bb->index)) + continue; + + if (ipa_tm_scan_irr_block (bb)) + { + bitmap_set_bit (new_irr, bb->index); + any_new_irr = true; + } + else if (exit_blocks == NULL || !bitmap_bit_p (exit_blocks, bb->index)) + { + FOR_EACH_EDGE (e, ei, bb->succs) + if (!bitmap_bit_p (visited_blocks, e->dest->index)) + { + bitmap_set_bit (visited_blocks, e->dest->index); + VEC_safe_push (basic_block, heap, *pqueue, e->dest); + } + } + } + while (!VEC_empty (basic_block, *pqueue)); + + BITMAP_FREE (visited_blocks); + + return any_new_irr; +} + +/* Propagate the irrevocable property both up and down the dominator tree. + BB is the current block being scanned; EXIT_BLOCKS are the edges of the + TM regions; OLD_IRR are the results of a previous scan of the dominator + tree which has been fully propagated; NEW_IRR is the set of new blocks + which are gaining the irrevocable property during the current scan. */ + +static void +ipa_tm_propagate_irr (basic_block entry_block, bitmap new_irr, + bitmap old_irr, bitmap exit_blocks) +{ + VEC (basic_block, heap) *bbs; + bitmap all_region_blocks; + + /* If this block is in the old set, no need to rescan. */ + if (old_irr && bitmap_bit_p (old_irr, entry_block->index)) + return; + + all_region_blocks = BITMAP_ALLOC (&tm_obstack); + bbs = get_tm_region_blocks (entry_block, exit_blocks, NULL, + all_region_blocks, false); + do + { + basic_block bb = VEC_pop (basic_block, bbs); + bool this_irr = bitmap_bit_p (new_irr, bb->index); + bool all_son_irr = false; + edge_iterator ei; + edge e; + + /* Propagate up. If my children are, I am too, but we must have + at least one child that is. */ + if (!this_irr) + { + FOR_EACH_EDGE (e, ei, bb->succs) + { + if (!bitmap_bit_p (new_irr, e->dest->index)) + { + all_son_irr = false; + break; + } + else + all_son_irr = true; + } + if (all_son_irr) + { + /* Add block to new_irr if it hasn't already been processed. */ + if (!old_irr || !bitmap_bit_p (old_irr, bb->index)) + { + bitmap_set_bit (new_irr, bb->index); + this_irr = true; + } + } + } + + /* Propagate down to everyone we immediately dominate. */ + if (this_irr) + { + basic_block son; + for (son = first_dom_son (CDI_DOMINATORS, bb); + son; + son = next_dom_son (CDI_DOMINATORS, son)) + { + /* Make sure block is actually in a TM region, and it + isn't already in old_irr. */ + if ((!old_irr || !bitmap_bit_p (old_irr, son->index)) + && bitmap_bit_p (all_region_blocks, son->index)) + bitmap_set_bit (new_irr, son->index); + } + } + } + while (!VEC_empty (basic_block, bbs)); + + BITMAP_FREE (all_region_blocks); + VEC_free (basic_block, heap, bbs); +} + +static void +ipa_tm_decrement_clone_counts (basic_block bb, bool for_clone) +{ + gimple_stmt_iterator gsi; + + for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) + { + gimple stmt = gsi_stmt (gsi); + if (is_gimple_call (stmt) && !is_tm_pure_call (stmt)) + { + tree fndecl = gimple_call_fndecl (stmt); + if (fndecl) + { + struct tm_ipa_cg_data *d; + unsigned *pcallers; + + if (is_tm_ending_fndecl (fndecl)) + continue; + if (find_tm_replacement_function (fndecl)) + continue; + + d = get_cg_data (cgraph_get_node (fndecl)); + pcallers = (for_clone ? &d->tm_callers_clone + : &d->tm_callers_normal); + + gcc_assert (*pcallers > 0); + *pcallers -= 1; + } + } + } +} + +/* (Re-)Scan the transaction blocks in NODE for calls to irrevocable functions, + as well as other irrevocable actions such as inline assembly. Mark all + such blocks as irrevocable and decrement the number of calls to + transactional clones. Return true if, for the transactional clone, the + entire function is irrevocable. */ + +static bool +ipa_tm_scan_irr_function (struct cgraph_node *node, bool for_clone) +{ + struct tm_ipa_cg_data *d; + bitmap new_irr, old_irr; + VEC (basic_block, heap) *queue; + bool ret = false; + + current_function_decl = node->decl; + push_cfun (DECL_STRUCT_FUNCTION (node->decl)); + calculate_dominance_info (CDI_DOMINATORS); + + d = get_cg_data (node); + queue = VEC_alloc (basic_block, heap, 10); + new_irr = BITMAP_ALLOC (&tm_obstack); + + /* Scan each tm region, propagating irrevocable status through the tree. */ + if (for_clone) + { + old_irr = d->irrevocable_blocks_clone; + VEC_quick_push (basic_block, queue, single_succ (ENTRY_BLOCK_PTR)); + if (ipa_tm_scan_irr_blocks (&queue, new_irr, old_irr, NULL)) + { + ipa_tm_propagate_irr (single_succ (ENTRY_BLOCK_PTR), new_irr, + old_irr, NULL); + ret = bitmap_bit_p (new_irr, single_succ (ENTRY_BLOCK_PTR)->index); + } + } + else + { + struct tm_region *region; + + old_irr = d->irrevocable_blocks_normal; + for (region = d->all_tm_regions; region; region = region->next) + { + VEC_quick_push (basic_block, queue, region->entry_block); + if (ipa_tm_scan_irr_blocks (&queue, new_irr, old_irr, + region->exit_blocks)) + ipa_tm_propagate_irr (region->entry_block, new_irr, old_irr, + region->exit_blocks); + } + } + + /* If we found any new irrevocable blocks, reduce the call count for + transactional clones within the irrevocable blocks. Save the new + set of irrevocable blocks for next time. */ + if (!bitmap_empty_p (new_irr)) + { + bitmap_iterator bmi; + unsigned i; + + EXECUTE_IF_SET_IN_BITMAP (new_irr, 0, i, bmi) + ipa_tm_decrement_clone_counts (BASIC_BLOCK (i), for_clone); + + if (old_irr) + { + bitmap_ior_into (old_irr, new_irr); + BITMAP_FREE (new_irr); + } + else if (for_clone) + d->irrevocable_blocks_clone = new_irr; + else + d->irrevocable_blocks_normal = new_irr; + + if (dump_file && new_irr) + { + const char *dname; + bitmap_iterator bmi; + unsigned i; + + dname = lang_hooks.decl_printable_name (current_function_decl, 2); + EXECUTE_IF_SET_IN_BITMAP (new_irr, 0, i, bmi) + fprintf (dump_file, "%s: bb %d goes irrevocable\n", dname, i); + } + } + else + BITMAP_FREE (new_irr); + + VEC_free (basic_block, heap, queue); + pop_cfun (); + current_function_decl = NULL; + + return ret; +} + +/* Return true if, for the transactional clone of NODE, any call + may enter irrevocable mode. */ + +static bool +ipa_tm_mayenterirr_function (struct cgraph_node *node) +{ + struct tm_ipa_cg_data *d = get_cg_data (node); + tree decl = node->decl; + unsigned flags = flags_from_decl_or_type (decl); + + /* Handle some TM builtins. Ordinarily these aren't actually generated + at this point, but handling these functions when written in by the + user makes it easier to build unit tests. */ + if (flags & ECF_TM_BUILTIN) + return false; + + /* Filter out all functions that are marked. */ + if (flags & ECF_TM_PURE) + return false; + if (is_tm_safe (decl)) + return false; + if (is_tm_irrevocable (decl)) + return true; + if (is_tm_callable (decl)) + return true; + if (find_tm_replacement_function (decl)) + return true; + + /* If we aren't seeing the final version of the function we don't + know what it will contain at runtime. */ + if (cgraph_function_body_availability (node) < AVAIL_AVAILABLE) + return true; + + /* If the function must go irrevocable, then of course true. */ + if (d->is_irrevocable) + return true; + + /* If there are any blocks marked irrevocable, then the function + as a whole may enter irrevocable. */ + if (d->irrevocable_blocks_clone) + return true; + + /* We may have previously marked this function as tm_may_enter_irr; + see pass_diagnose_tm_blocks. */ + if (node->local.tm_may_enter_irr) + return true; + + /* Recurse on the main body for aliases. In general, this will + result in one of the bits above being set so that we will not + have to recurse next time. */ + if (node->alias) + return ipa_tm_mayenterirr_function (cgraph_get_node (node->thunk.alias)); + + /* What remains is unmarked local functions without items that force + the function to go irrevocable. */ + return false; +} + +/* Diagnose calls from transaction_safe functions to unmarked + functions that are determined to not be safe. */ + +static void +ipa_tm_diagnose_tm_safe (struct cgraph_node *node) +{ + struct cgraph_edge *e; + + for (e = node->callees; e ; e = e->next_callee) + if (!is_tm_callable (e->callee->decl) + && e->callee->local.tm_may_enter_irr) + error_at (gimple_location (e->call_stmt), + "unsafe function call %qD within " + "%<transaction_safe%> function", e->callee->decl); +} + +/* Diagnose call from atomic transactions to unmarked functions + that are determined to not be safe. */ + +static void +ipa_tm_diagnose_transaction (struct cgraph_node *node, + struct tm_region *all_tm_regions) +{ + struct tm_region *r; + + for (r = all_tm_regions; r ; r = r->next) + if (gimple_transaction_subcode (r->transaction_stmt) & GTMA_IS_RELAXED) + { + /* Atomic transactions can be nested inside relaxed. */ + if (r->inner) + ipa_tm_diagnose_transaction (node, r->inner); + } + else + { + VEC (basic_block, heap) *bbs; + gimple_stmt_iterator gsi; + basic_block bb; + size_t i; + + bbs = get_tm_region_blocks (r->entry_block, r->exit_blocks, + r->irr_blocks, NULL, false); + + for (i = 0; VEC_iterate (basic_block, bbs, i, bb); ++i) + for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) + { + gimple stmt = gsi_stmt (gsi); + tree fndecl; + + if (gimple_code (stmt) == GIMPLE_ASM) + { + error_at (gimple_location (stmt), + "asm not allowed in atomic transaction"); + continue; + } + + if (!is_gimple_call (stmt)) + continue; + fndecl = gimple_call_fndecl (stmt); + + /* Indirect function calls have been diagnosed already. */ + if (!fndecl) + continue; + + /* Stop at the end of the transaction. */ + if (is_tm_ending_fndecl (fndecl)) + { + if (bitmap_bit_p (r->exit_blocks, bb->index)) + break; + continue; + } + + /* Marked functions have been diagnosed already. */ + if (is_tm_pure_call (stmt)) + continue; + if (is_tm_callable (fndecl)) + continue; + + if (cgraph_local_info (fndecl)->tm_may_enter_irr) + error_at (gimple_location (stmt), + "unsafe function call %qD within " + "atomic transaction", fndecl); + } + + VEC_free (basic_block, heap, bbs); + } +} + +/* Return a transactional mangled name for the DECL_ASSEMBLER_NAME in + OLD_DECL. The returned value is a freshly malloced pointer that + should be freed by the caller. */ + +static tree +tm_mangle (tree old_asm_id) +{ + const char *old_asm_name; + char *tm_name; + void *alloc = NULL; + struct demangle_component *dc; + tree new_asm_id; + + /* Determine if the symbol is already a valid C++ mangled name. Do this + even for C, which might be interfacing with C++ code via appropriately + ugly identifiers. */ + /* ??? We could probably do just as well checking for "_Z" and be done. */ + old_asm_name = IDENTIFIER_POINTER (old_asm_id); + dc = cplus_demangle_v3_components (old_asm_name, DMGL_NO_OPTS, &alloc); + + if (dc == NULL) + { + char length[8]; + + do_unencoded: + sprintf (length, "%u", IDENTIFIER_LENGTH (old_asm_id)); + tm_name = concat ("_ZGTt", length, old_asm_name, NULL); + } + else + { + old_asm_name += 2; /* Skip _Z */ + + switch (dc->type) + { + case DEMANGLE_COMPONENT_TRANSACTION_CLONE: + case DEMANGLE_COMPONENT_NONTRANSACTION_CLONE: + /* Don't play silly games, you! */ + goto do_unencoded; + + case DEMANGLE_COMPONENT_HIDDEN_ALIAS: + /* I'd really like to know if we can ever be passed one of + these from the C++ front end. The Logical Thing would + seem that hidden-alias should be outer-most, so that we + get hidden-alias of a transaction-clone and not vice-versa. */ + old_asm_name += 2; + break; + + default: + break; + } + + tm_name = concat ("_ZGTt", old_asm_name, NULL); + } + free (alloc); + + new_asm_id = get_identifier (tm_name); + free (tm_name); + + return new_asm_id; +} + +static inline void +ipa_tm_mark_needed_node (struct cgraph_node *node) +{ + cgraph_mark_needed_node (node); + /* ??? function_and_variable_visibility will reset + the needed bit, without actually checking. */ + node->analyzed = 1; +} + +/* Callback data for ipa_tm_create_version_alias. */ +struct create_version_alias_info +{ + struct cgraph_node *old_node; + tree new_decl; +}; + +/* A subrontine of ipa_tm_create_version, called via + cgraph_for_node_and_aliases. Create new tm clones for each of + the existing aliases. */ +static bool +ipa_tm_create_version_alias (struct cgraph_node *node, void *data) +{ + struct create_version_alias_info *info + = (struct create_version_alias_info *)data; + tree old_decl, new_decl, tm_name; + struct cgraph_node *new_node; + + if (!node->same_body_alias) + return false; + + old_decl = node->decl; + tm_name = tm_mangle (DECL_ASSEMBLER_NAME (old_decl)); + new_decl = build_decl (DECL_SOURCE_LOCATION (old_decl), + TREE_CODE (old_decl), tm_name, + TREE_TYPE (old_decl)); + + SET_DECL_ASSEMBLER_NAME (new_decl, tm_name); + SET_DECL_RTL (new_decl, NULL); + + /* Based loosely on C++'s make_alias_for(). */ + TREE_PUBLIC (new_decl) = TREE_PUBLIC (old_decl); + DECL_CONTEXT (new_decl) = NULL; + TREE_READONLY (new_decl) = TREE_READONLY (old_decl); + DECL_EXTERNAL (new_decl) = 0; + DECL_ARTIFICIAL (new_decl) = 1; + TREE_ADDRESSABLE (new_decl) = 1; + TREE_USED (new_decl) = 1; + TREE_SYMBOL_REFERENCED (tm_name) = 1; + + /* Perform the same remapping to the comdat group. */ + if (DECL_COMDAT (new_decl)) + DECL_COMDAT_GROUP (new_decl) = tm_mangle (DECL_COMDAT_GROUP (old_decl)); + + new_node = cgraph_same_body_alias (NULL, new_decl, info->new_decl); + new_node->tm_clone = true; + get_cg_data (node)->clone = new_node; + + record_tm_clone_pair (old_decl, new_decl); + + if (info->old_node->needed) + ipa_tm_mark_needed_node (new_node); + return false; +} + +/* Create a copy of the function (possibly declaration only) of OLD_NODE, + appropriate for the transactional clone. */ + +static void +ipa_tm_create_version (struct cgraph_node *old_node) +{ + tree new_decl, old_decl, tm_name; + struct cgraph_node *new_node; + + old_decl = old_node->decl; + new_decl = copy_node (old_decl); + + /* DECL_ASSEMBLER_NAME needs to be set before we call + cgraph_copy_node_for_versioning below, because cgraph_node will + fill the assembler_name_hash. */ + tm_name = tm_mangle (DECL_ASSEMBLER_NAME (old_decl)); + SET_DECL_ASSEMBLER_NAME (new_decl, tm_name); + SET_DECL_RTL (new_decl, NULL); + TREE_SYMBOL_REFERENCED (tm_name) = 1; + + /* Perform the same remapping to the comdat group. */ + if (DECL_COMDAT (new_decl)) + DECL_COMDAT_GROUP (new_decl) = tm_mangle (DECL_COMDAT_GROUP (old_decl)); + + new_node = cgraph_copy_node_for_versioning (old_node, new_decl, NULL, NULL); + new_node->lowered = true; + new_node->tm_clone = 1; + get_cg_data (old_node)->clone = new_node; + + if (cgraph_function_body_availability (old_node) >= AVAIL_OVERWRITABLE) + { + /* Remap extern inline to static inline. */ + /* ??? Is it worth trying to use make_decl_one_only? */ + if (DECL_DECLARED_INLINE_P (new_decl) && DECL_EXTERNAL (new_decl)) + { + DECL_EXTERNAL (new_decl) = 0; + TREE_PUBLIC (new_decl) = 0; + } + + tree_function_versioning (old_decl, new_decl, NULL, false, NULL, + NULL, NULL); + } + + record_tm_clone_pair (old_decl, new_decl); + + cgraph_call_function_insertion_hooks (new_node); + if (old_node->needed) + ipa_tm_mark_needed_node (new_node); + + /* Do the same thing, but for any aliases of the original node. */ + { + struct create_version_alias_info data; + data.old_node = old_node; + data.new_decl = new_decl; + cgraph_for_node_and_aliases (old_node, ipa_tm_create_version_alias, + &data, true); + } +} + +/* Construct a call to TM_IRREVOCABLE and insert it at the beginning of BB. */ + +static void +ipa_tm_insert_irr_call (struct cgraph_node *node, struct tm_region *region, + basic_block bb) +{ + gimple_stmt_iterator gsi; + gimple g; + + transaction_subcode_ior (region, GTMA_MAY_ENTER_IRREVOCABLE); + + g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TM_IRREVOCABLE), + 1, build_int_cst (NULL_TREE, MODE_SERIALIRREVOCABLE)); + + split_block_after_labels (bb); + gsi = gsi_after_labels (bb); + gsi_insert_before (&gsi, g, GSI_SAME_STMT); + + cgraph_create_edge (node, + cgraph_get_create_node + (builtin_decl_explicit (BUILT_IN_TM_IRREVOCABLE)), + g, 0, + compute_call_stmt_bb_frequency (node->decl, + gimple_bb (g))); +} + +/* Construct a call to TM_GETTMCLONE and insert it before GSI. */ + +static bool +ipa_tm_insert_gettmclone_call (struct cgraph_node *node, + struct tm_region *region, + gimple_stmt_iterator *gsi, gimple stmt) +{ + tree gettm_fn, ret, old_fn, callfn; + gimple g, g2; + bool safe; + + old_fn = gimple_call_fn (stmt); + + if (TREE_CODE (old_fn) == ADDR_EXPR) + { + tree fndecl = TREE_OPERAND (old_fn, 0); + tree clone = get_tm_clone_pair (fndecl); + + /* By transforming the call into a TM_GETTMCLONE, we are + technically taking the address of the original function and + its clone. Explain this so inlining will know this function + is needed. */ + cgraph_mark_address_taken_node (cgraph_get_node (fndecl)); + if (clone) + cgraph_mark_address_taken_node (cgraph_get_node (clone)); + } + + safe = is_tm_safe (TREE_TYPE (old_fn)); + gettm_fn = builtin_decl_explicit (safe ? BUILT_IN_TM_GETTMCLONE_SAFE + : BUILT_IN_TM_GETTMCLONE_IRR); + ret = create_tmp_var (ptr_type_node, NULL); + add_referenced_var (ret); + + if (!safe) + transaction_subcode_ior (region, GTMA_MAY_ENTER_IRREVOCABLE); + + /* Discard OBJ_TYPE_REF, since we weren't able to fold it. */ + if (TREE_CODE (old_fn) == OBJ_TYPE_REF) + old_fn = OBJ_TYPE_REF_EXPR (old_fn); + + g = gimple_build_call (gettm_fn, 1, old_fn); + ret = make_ssa_name (ret, g); + gimple_call_set_lhs (g, ret); + + gsi_insert_before (gsi, g, GSI_SAME_STMT); + + cgraph_create_edge (node, cgraph_get_create_node (gettm_fn), g, 0, + compute_call_stmt_bb_frequency (node->decl, + gimple_bb(g))); + + /* Cast return value from tm_gettmclone* into appropriate function + pointer. */ + callfn = create_tmp_var (TREE_TYPE (old_fn), NULL); + add_referenced_var (callfn); + g2 = gimple_build_assign (callfn, + fold_build1 (NOP_EXPR, TREE_TYPE (callfn), ret)); + callfn = make_ssa_name (callfn, g2); + gimple_assign_set_lhs (g2, callfn); + gsi_insert_before (gsi, g2, GSI_SAME_STMT); + + /* ??? This is a hack to preserve the NOTHROW bit on the call, + which we would have derived from the decl. Failure to save + this bit means we might have to split the basic block. */ + if (gimple_call_nothrow_p (stmt)) + gimple_call_set_nothrow (stmt, true); + + gimple_call_set_fn (stmt, callfn); + + /* Discarding OBJ_TYPE_REF above may produce incompatible LHS and RHS + for a call statement. Fix it. */ + { + tree lhs = gimple_call_lhs (stmt); + tree rettype = TREE_TYPE (gimple_call_fntype (stmt)); + if (lhs + && !useless_type_conversion_p (TREE_TYPE (lhs), rettype)) + { + tree temp; + + temp = make_rename_temp (rettype, 0); + gimple_call_set_lhs (stmt, temp); + + g2 = gimple_build_assign (lhs, + fold_build1 (VIEW_CONVERT_EXPR, + TREE_TYPE (lhs), temp)); + gsi_insert_after (gsi, g2, GSI_SAME_STMT); + } + } + + update_stmt (stmt); + + return true; +} + +/* Helper function for ipa_tm_transform_calls*. Given a call + statement in GSI which resides inside transaction REGION, redirect + the call to either its wrapper function, or its clone. */ + +static void +ipa_tm_transform_calls_redirect (struct cgraph_node *node, + struct tm_region *region, + gimple_stmt_iterator *gsi, + bool *need_ssa_rename_p) +{ + gimple stmt = gsi_stmt (*gsi); + struct cgraph_node *new_node; + struct cgraph_edge *e = cgraph_edge (node, stmt); + tree fndecl = gimple_call_fndecl (stmt); + + /* For indirect calls, pass the address through the runtime. */ + if (fndecl == NULL) + { + *need_ssa_rename_p |= + ipa_tm_insert_gettmclone_call (node, region, gsi, stmt); + return; + } + + /* Handle some TM builtins. Ordinarily these aren't actually generated + at this point, but handling these functions when written in by the + user makes it easier to build unit tests. */ + if (flags_from_decl_or_type (fndecl) & ECF_TM_BUILTIN) + return; + + /* Fixup recursive calls inside clones. */ + /* ??? Why did cgraph_copy_node_for_versioning update the call edges + for recursion but not update the call statements themselves? */ + if (e->caller == e->callee && decl_is_tm_clone (current_function_decl)) + { + gimple_call_set_fndecl (stmt, current_function_decl); + return; + } + + /* If there is a replacement, use it. */ + fndecl = find_tm_replacement_function (fndecl); + if (fndecl) + { + new_node = cgraph_get_create_node (fndecl); + + /* ??? Mark all transaction_wrap functions tm_may_enter_irr. + + We can't do this earlier in record_tm_replacement because + cgraph_remove_unreachable_nodes is called before we inject + references to the node. Further, we can't do this in some + nice central place in ipa_tm_execute because we don't have + the exact list of wrapper functions that would be used. + Marking more wrappers than necessary results in the creation + of unnecessary cgraph_nodes, which can cause some of the + other IPA passes to crash. + + We do need to mark these nodes so that we get the proper + result in expand_call_tm. */ + /* ??? This seems broken. How is it that we're marking the + CALLEE as may_enter_irr? Surely we should be marking the + CALLER. Also note that find_tm_replacement_function also + contains mappings into the TM runtime, e.g. memcpy. These + we know won't go irrevocable. */ + new_node->local.tm_may_enter_irr = 1; + } + else + { + struct tm_ipa_cg_data *d = get_cg_data (e->callee); + new_node = d->clone; + + /* As we've already skipped pure calls and appropriate builtins, + and we've already marked irrevocable blocks, if we can't come + up with a static replacement, then ask the runtime. */ + if (new_node == NULL) + { + *need_ssa_rename_p |= + ipa_tm_insert_gettmclone_call (node, region, gsi, stmt); + cgraph_remove_edge (e); + return; + } + + fndecl = new_node->decl; + } + + cgraph_redirect_edge_callee (e, new_node); + gimple_call_set_fndecl (stmt, fndecl); +} + +/* Helper function for ipa_tm_transform_calls. For a given BB, + install calls to tm_irrevocable when IRR_BLOCKS are reached, + redirect other calls to the generated transactional clone. */ + +static bool +ipa_tm_transform_calls_1 (struct cgraph_node *node, struct tm_region *region, + basic_block bb, bitmap irr_blocks) +{ + gimple_stmt_iterator gsi; + bool need_ssa_rename = false; + + if (irr_blocks && bitmap_bit_p (irr_blocks, bb->index)) + { + ipa_tm_insert_irr_call (node, region, bb); + return true; + } + + for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) + { + gimple stmt = gsi_stmt (gsi); + + if (!is_gimple_call (stmt)) + continue; + if (is_tm_pure_call (stmt)) + continue; + + /* Redirect edges to the appropriate replacement or clone. */ + ipa_tm_transform_calls_redirect (node, region, &gsi, &need_ssa_rename); + } + + return need_ssa_rename; +} + +/* Walk the CFG for REGION, beginning at BB. Install calls to + tm_irrevocable when IRR_BLOCKS are reached, redirect other calls to + the generated transactional clone. */ + +static bool +ipa_tm_transform_calls (struct cgraph_node *node, struct tm_region *region, + basic_block bb, bitmap irr_blocks) +{ + bool need_ssa_rename = false; + edge e; + edge_iterator ei; + VEC(basic_block, heap) *queue = NULL; + bitmap visited_blocks = BITMAP_ALLOC (NULL); + + VEC_safe_push (basic_block, heap, queue, bb); + do + { + bb = VEC_pop (basic_block, queue); + + need_ssa_rename |= + ipa_tm_transform_calls_1 (node, region, bb, irr_blocks); + + if (irr_blocks && bitmap_bit_p (irr_blocks, bb->index)) + continue; + + if (region && bitmap_bit_p (region->exit_blocks, bb->index)) + continue; + + FOR_EACH_EDGE (e, ei, bb->succs) + if (!bitmap_bit_p (visited_blocks, e->dest->index)) + { + bitmap_set_bit (visited_blocks, e->dest->index); + VEC_safe_push (basic_block, heap, queue, e->dest); + } + } + while (!VEC_empty (basic_block, queue)); + + VEC_free (basic_block, heap, queue); + BITMAP_FREE (visited_blocks); + + return need_ssa_rename; +} + +/* Transform the calls within the TM regions within NODE. */ + +static void +ipa_tm_transform_transaction (struct cgraph_node *node) +{ + struct tm_ipa_cg_data *d = get_cg_data (node); + struct tm_region *region; + bool need_ssa_rename = false; + + current_function_decl = node->decl; + push_cfun (DECL_STRUCT_FUNCTION (node->decl)); + calculate_dominance_info (CDI_DOMINATORS); + + for (region = d->all_tm_regions; region; region = region->next) + { + /* If we're sure to go irrevocable, don't transform anything. */ + if (d->irrevocable_blocks_normal + && bitmap_bit_p (d->irrevocable_blocks_normal, + region->entry_block->index)) + { + transaction_subcode_ior (region, GTMA_DOES_GO_IRREVOCABLE); + transaction_subcode_ior (region, GTMA_MAY_ENTER_IRREVOCABLE); + continue; + } + + need_ssa_rename |= + ipa_tm_transform_calls (node, region, region->entry_block, + d->irrevocable_blocks_normal); + } + + if (need_ssa_rename) + update_ssa (TODO_update_ssa_only_virtuals); + + pop_cfun (); + current_function_decl = NULL; +} + +/* Transform the calls within the transactional clone of NODE. */ + +static void +ipa_tm_transform_clone (struct cgraph_node *node) +{ + struct tm_ipa_cg_data *d = get_cg_data (node); + bool need_ssa_rename; + + /* If this function makes no calls and has no irrevocable blocks, + then there's nothing to do. */ + /* ??? Remove non-aborting top-level transactions. */ + if (!node->callees && !d->irrevocable_blocks_clone) + return; + + current_function_decl = d->clone->decl; + push_cfun (DECL_STRUCT_FUNCTION (current_function_decl)); + calculate_dominance_info (CDI_DOMINATORS); + + need_ssa_rename = + ipa_tm_transform_calls (d->clone, NULL, single_succ (ENTRY_BLOCK_PTR), + d->irrevocable_blocks_clone); + + if (need_ssa_rename) + update_ssa (TODO_update_ssa_only_virtuals); + + pop_cfun (); + current_function_decl = NULL; +} + +/* Main entry point for the transactional memory IPA pass. */ + +static unsigned int +ipa_tm_execute (void) +{ + cgraph_node_queue tm_callees = NULL; + /* List of functions that will go irrevocable. */ + cgraph_node_queue irr_worklist = NULL; + + struct cgraph_node *node; + struct tm_ipa_cg_data *d; + enum availability a; + unsigned int i; + +#ifdef ENABLE_CHECKING + verify_cgraph (); +#endif + + bitmap_obstack_initialize (&tm_obstack); + + /* For all local functions marked tm_callable, queue them. */ + for (node = cgraph_nodes; node; node = node->next) + if (is_tm_callable (node->decl) + && cgraph_function_body_availability (node) >= AVAIL_OVERWRITABLE) + { + d = get_cg_data (node); + maybe_push_queue (node, &tm_callees, &d->in_callee_queue); + } + + /* For all local reachable functions... */ + for (node = cgraph_nodes; node; node = node->next) + if (node->reachable && node->lowered + && cgraph_function_body_availability (node) >= AVAIL_OVERWRITABLE) + { + /* ... marked tm_pure, record that fact for the runtime by + indicating that the pure function is its own tm_callable. + No need to do this if the function's address can't be taken. */ + if (is_tm_pure (node->decl)) + { + if (!node->local.local) + record_tm_clone_pair (node->decl, node->decl); + continue; + } + + current_function_decl = node->decl; + push_cfun (DECL_STRUCT_FUNCTION (node->decl)); + calculate_dominance_info (CDI_DOMINATORS); + + tm_region_init (NULL); + if (all_tm_regions) + { + d = get_cg_data (node); + + /* Scan for calls that are in each transaction. */ + ipa_tm_scan_calls_transaction (d, &tm_callees); + + /* If we saw something that will make us go irrevocable, put it + in the worklist so we can scan the function later + (ipa_tm_scan_irr_function) and mark the irrevocable blocks. */ + if (node->local.tm_may_enter_irr) + { + maybe_push_queue (node, &irr_worklist, &d->in_worklist); + d->want_irr_scan_normal = true; + } + } + + pop_cfun (); + current_function_decl = NULL; + } + + /* For every local function on the callee list, scan as if we will be + creating a transactional clone, queueing all new functions we find + along the way. */ + for (i = 0; i < VEC_length (cgraph_node_p, tm_callees); ++i) + { + node = VEC_index (cgraph_node_p, tm_callees, i); + a = cgraph_function_body_availability (node); + d = get_cg_data (node); + + /* If we saw something that will make us go irrevocable, put it + in the worklist so we can scan the function later + (ipa_tm_scan_irr_function) and mark the irrevocable blocks. */ + if (node->local.tm_may_enter_irr) + maybe_push_queue (node, &irr_worklist, &d->in_worklist); + + /* Some callees cannot be arbitrarily cloned. These will always be + irrevocable. Mark these now, so that we need not scan them. */ + if (is_tm_irrevocable (node->decl)) + ipa_tm_note_irrevocable (node, &irr_worklist); + else if (a <= AVAIL_NOT_AVAILABLE + && !is_tm_safe_or_pure (node->decl)) + ipa_tm_note_irrevocable (node, &irr_worklist); + else if (a >= AVAIL_OVERWRITABLE) + { + if (!tree_versionable_function_p (node->decl)) + ipa_tm_note_irrevocable (node, &irr_worklist); + else if (!d->is_irrevocable) + { + /* If this is an alias, make sure its base is queued as well. + we need not scan the callees now, as the base will do. */ + if (node->alias) + { + node = cgraph_get_node (node->thunk.alias); + d = get_cg_data (node); + maybe_push_queue (node, &tm_callees, &d->in_callee_queue); + continue; + } + + /* Add all nodes called by this function into + tm_callees as well. */ + ipa_tm_scan_calls_clone (node, &tm_callees); + } + } + } + + /* Iterate scans until no more work to be done. Prefer not to use + VEC_pop because the worklist tends to follow a breadth-first + search of the callgraph, which should allow convergance with a + minimum number of scans. But we also don't want the worklist + array to grow without bound, so we shift the array up periodically. */ + for (i = 0; i < VEC_length (cgraph_node_p, irr_worklist); ++i) + { + if (i > 256 && i == VEC_length (cgraph_node_p, irr_worklist) / 8) + { + VEC_block_remove (cgraph_node_p, irr_worklist, 0, i); + i = 0; + } + + node = VEC_index (cgraph_node_p, irr_worklist, i); + d = get_cg_data (node); + d->in_worklist = false; + + if (d->want_irr_scan_normal) + { + d->want_irr_scan_normal = false; + ipa_tm_scan_irr_function (node, false); + } + if (d->in_callee_queue && ipa_tm_scan_irr_function (node, true)) + ipa_tm_note_irrevocable (node, &irr_worklist); + } + + /* For every function on the callee list, collect the tm_may_enter_irr + bit on the node. */ + VEC_truncate (cgraph_node_p, irr_worklist, 0); + for (i = 0; i < VEC_length (cgraph_node_p, tm_callees); ++i) + { + node = VEC_index (cgraph_node_p, tm_callees, i); + if (ipa_tm_mayenterirr_function (node)) + { + d = get_cg_data (node); + gcc_assert (d->in_worklist == false); + maybe_push_queue (node, &irr_worklist, &d->in_worklist); + } + } + + /* Propagate the tm_may_enter_irr bit to callers until stable. */ + for (i = 0; i < VEC_length (cgraph_node_p, irr_worklist); ++i) + { + struct cgraph_node *caller; + struct cgraph_edge *e; + struct ipa_ref *ref; + unsigned j; + + if (i > 256 && i == VEC_length (cgraph_node_p, irr_worklist) / 8) + { + VEC_block_remove (cgraph_node_p, irr_worklist, 0, i); + i = 0; + } + + node = VEC_index (cgraph_node_p, irr_worklist, i); + d = get_cg_data (node); + d->in_worklist = false; + node->local.tm_may_enter_irr = true; + + /* Propagate back to normal callers. */ + for (e = node->callers; e ; e = e->next_caller) + { + caller = e->caller; + if (!is_tm_safe_or_pure (caller->decl) + && !caller->local.tm_may_enter_irr) + { + d = get_cg_data (caller); + maybe_push_queue (caller, &irr_worklist, &d->in_worklist); + } + } + + /* Propagate back to referring aliases as well. */ + for (j = 0; ipa_ref_list_refering_iterate (&node->ref_list, j, ref); j++) + { + caller = ref->refering.cgraph_node; + if (ref->use == IPA_REF_ALIAS + && !caller->local.tm_may_enter_irr) + { + d = get_cg_data (caller); + maybe_push_queue (caller, &irr_worklist, &d->in_worklist); + } + } + } + + /* Now validate all tm_safe functions, and all atomic regions in + other functions. */ + for (node = cgraph_nodes; node; node = node->next) + if (node->reachable && node->lowered + && cgraph_function_body_availability (node) >= AVAIL_OVERWRITABLE) + { + d = get_cg_data (node); + if (is_tm_safe (node->decl)) + ipa_tm_diagnose_tm_safe (node); + else if (d->all_tm_regions) + ipa_tm_diagnose_transaction (node, d->all_tm_regions); + } + + /* Create clones. Do those that are not irrevocable and have a + positive call count. Do those publicly visible functions that + the user directed us to clone. */ + for (i = 0; i < VEC_length (cgraph_node_p, tm_callees); ++i) + { + bool doit = false; + + node = VEC_index (cgraph_node_p, tm_callees, i); + if (node->same_body_alias) + continue; + + a = cgraph_function_body_availability (node); + d = get_cg_data (node); + + if (a <= AVAIL_NOT_AVAILABLE) + doit = is_tm_callable (node->decl); + else if (a <= AVAIL_AVAILABLE && is_tm_callable (node->decl)) + doit = true; + else if (!d->is_irrevocable + && d->tm_callers_normal + d->tm_callers_clone > 0) + doit = true; + + if (doit) + ipa_tm_create_version (node); + } + + /* Redirect calls to the new clones, and insert irrevocable marks. */ + for (i = 0; i < VEC_length (cgraph_node_p, tm_callees); ++i) + { + node = VEC_index (cgraph_node_p, tm_callees, i); + if (node->analyzed) + { + d = get_cg_data (node); + if (d->clone) + ipa_tm_transform_clone (node); + } + } + for (node = cgraph_nodes; node; node = node->next) + if (node->reachable && node->lowered + && cgraph_function_body_availability (node) >= AVAIL_OVERWRITABLE) + { + d = get_cg_data (node); + if (d->all_tm_regions) + ipa_tm_transform_transaction (node); + } + + /* Free and clear all data structures. */ + VEC_free (cgraph_node_p, heap, tm_callees); + VEC_free (cgraph_node_p, heap, irr_worklist); + bitmap_obstack_release (&tm_obstack); + + for (node = cgraph_nodes; node; node = node->next) + node->aux = NULL; + +#ifdef ENABLE_CHECKING + verify_cgraph (); +#endif + + return 0; +} + +struct simple_ipa_opt_pass pass_ipa_tm = +{ + { + SIMPLE_IPA_PASS, + "tmipa", /* name */ + gate_tm, /* gate */ + ipa_tm_execute, /* execute */ + NULL, /* sub */ + NULL, /* next */ + 0, /* static_pass_number */ + TV_TRANS_MEM, /* tv_id */ + PROP_ssa | PROP_cfg, /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ + TODO_dump_func, /* todo_flags_finish */ + }, +}; + +#include "gt-trans-mem.h" diff --git a/gcc/trans-mem.h b/gcc/trans-mem.h new file mode 100644 index 00000000000..95e9e7e5f00 --- /dev/null +++ b/gcc/trans-mem.h @@ -0,0 +1,35 @@ +/* Miscellaneous transactional memory support definitions. + Copyright (C) 2009, 2011 Free Software Foundation, Inc. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free + Software Foundation; either version 3, or (at your option) any later + version. + + GCC is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with GCC; see the file COPYING3. If not see + <http://www.gnu.org/licenses/>. */ + + +/* These defines must match the enumerations in libitm.h. */ +#define PR_INSTRUMENTEDCODE 0x0001 +#define PR_UNINSTRUMENTEDCODE 0x0002 +#define PR_HASNOXMMUPDATE 0x0004 +#define PR_HASNOABORT 0x0008 +#define PR_HASNOIRREVOCABLE 0x0020 +#define PR_DOESGOIRREVOCABLE 0x0040 +#define PR_HASNOSIMPLEREADS 0x0080 +#define PR_AWBARRIERSOMITTED 0x0100 +#define PR_RARBARRIERSOMITTED 0x0200 +#define PR_UNDOLOGCODE 0x0400 +#define PR_PREFERUNINSTRUMENTED 0x0800 +#define PR_EXCEPTIONBLOCK 0x1000 +#define PR_HASELSE 0x2000 +#define PR_READONLY 0x4000 diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c index 7ec50dbabd4..d81cc670bf4 100644 --- a/gcc/tree-cfg.c +++ b/gcc/tree-cfg.c @@ -117,6 +117,7 @@ static int gimple_verify_flow_info (void); static void gimple_make_forwarder_block (edge); static void gimple_cfg2vcg (FILE *); static gimple first_non_label_stmt (basic_block); +static bool verify_gimple_transaction (gimple); /* Flowgraph optimization and cleanup. */ static void gimple_merge_blocks (basic_block, basic_block); @@ -666,6 +667,15 @@ make_edges (void) } break; + case GIMPLE_TRANSACTION: + { + tree abort_label = gimple_transaction_label (last); + if (abort_label) + make_edge (bb, label_to_block (abort_label), 0); + fallthru = true; + } + break; + default: gcc_assert (!stmt_ends_bb_p (last)); fallthru = true; @@ -1196,22 +1206,30 @@ cleanup_dead_labels (void) FOR_EACH_BB (bb) { gimple stmt = last_stmt (bb); + tree label, new_label; + if (!stmt) continue; switch (gimple_code (stmt)) { case GIMPLE_COND: - { - tree true_label = gimple_cond_true_label (stmt); - tree false_label = gimple_cond_false_label (stmt); + label = gimple_cond_true_label (stmt); + if (label) + { + new_label = main_block_label (label); + if (new_label != label) + gimple_cond_set_true_label (stmt, new_label); + } - if (true_label) - gimple_cond_set_true_label (stmt, main_block_label (true_label)); - if (false_label) - gimple_cond_set_false_label (stmt, main_block_label (false_label)); - break; - } + label = gimple_cond_false_label (stmt); + if (label) + { + new_label = main_block_label (label); + if (new_label != label) + gimple_cond_set_false_label (stmt, new_label); + } + break; case GIMPLE_SWITCH: { @@ -1221,8 +1239,10 @@ cleanup_dead_labels (void) for (i = 0; i < n; ++i) { tree case_label = gimple_switch_label (stmt, i); - tree label = main_block_label (CASE_LABEL (case_label)); - CASE_LABEL (case_label) = label; + label = CASE_LABEL (case_label); + new_label = main_block_label (label); + if (new_label != label) + CASE_LABEL (case_label) = new_label; } break; } @@ -1243,13 +1263,27 @@ cleanup_dead_labels (void) /* We have to handle gotos until they're removed, and we don't remove them until after we've created the CFG edges. */ case GIMPLE_GOTO: - if (!computed_goto_p (stmt)) + if (!computed_goto_p (stmt)) { - tree new_dest = main_block_label (gimple_goto_dest (stmt)); - gimple_goto_set_dest (stmt, new_dest); + label = gimple_goto_dest (stmt); + new_label = main_block_label (label); + if (new_label != label) + gimple_goto_set_dest (stmt, new_label); } break; + case GIMPLE_TRANSACTION: + { + tree label = gimple_transaction_label (stmt); + if (label) + { + tree new_label = main_block_label (label); + if (new_label != label) + gimple_transaction_set_label (stmt, new_label); + } + } + break; + default: break; } @@ -2272,6 +2306,13 @@ is_ctrl_altering_stmt (gimple t) if (flags & ECF_NORETURN) return true; + /* TM ending statements have backedges out of the transaction. + Return true so we split the basic block containing them. + Note that the TM_BUILTIN test is merely an optimization. */ + if ((flags & ECF_TM_BUILTIN) + && is_tm_ending_fndecl (gimple_call_fndecl (t))) + return true; + /* BUILT_IN_RETURN call is same as return statement. */ if (gimple_call_builtin_p (t, BUILT_IN_RETURN)) return true; @@ -2293,6 +2334,10 @@ is_ctrl_altering_stmt (gimple t) /* OpenMP directives alter control flow. */ return true; + case GIMPLE_TRANSACTION: + /* A transaction start alters control flow. */ + return true; + default: break; } @@ -4063,7 +4108,6 @@ verify_gimple_switch (gimple stmt) return false; } - /* Verify a gimple debug statement STMT. Returns true if anything is wrong. */ @@ -4164,6 +4208,9 @@ verify_gimple_stmt (gimple stmt) case GIMPLE_ASM: return false; + case GIMPLE_TRANSACTION: + return verify_gimple_transaction (stmt); + /* Tuples that do not have tree operands. */ case GIMPLE_NOP: case GIMPLE_PREDICT: @@ -4280,10 +4327,19 @@ verify_gimple_in_seq_2 (gimple_seq stmts) err |= verify_gimple_in_seq_2 (gimple_eh_filter_failure (stmt)); break; + case GIMPLE_EH_ELSE: + err |= verify_gimple_in_seq_2 (gimple_eh_else_n_body (stmt)); + err |= verify_gimple_in_seq_2 (gimple_eh_else_e_body (stmt)); + break; + case GIMPLE_CATCH: err |= verify_gimple_in_seq_2 (gimple_catch_handler (stmt)); break; + case GIMPLE_TRANSACTION: + err |= verify_gimple_transaction (stmt); + break; + default: { bool err2 = verify_gimple_stmt (stmt); @@ -4297,6 +4353,18 @@ verify_gimple_in_seq_2 (gimple_seq stmts) return err; } +/* Verify the contents of a GIMPLE_TRANSACTION. Returns true if there + is a problem, otherwise false. */ + +static bool +verify_gimple_transaction (gimple stmt) +{ + tree lab = gimple_transaction_label (stmt); + if (lab != NULL && TREE_CODE (lab) != LABEL_DECL) + return true; + return verify_gimple_in_seq_2 (gimple_transaction_body (stmt)); +} + /* Verify the GIMPLE statements inside the statement list STMTS. */ @@ -5061,6 +5129,13 @@ gimple_redirect_edge_and_branch (edge e, basic_block dest) redirect_eh_dispatch_edge (stmt, e, dest); break; + case GIMPLE_TRANSACTION: + /* The ABORT edge has a stored label associated with it, otherwise + the edges are simply redirectable. */ + if (e->flags == 0) + gimple_transaction_set_label (stmt, gimple_block_label (dest)); + break; + default: /* Otherwise it must be a fallthru edge, and we don't need to do anything besides redirecting it. */ @@ -6443,8 +6518,10 @@ dump_function_to_file (tree fn, FILE *file, int flags) bool ignore_topmost_bind = false, any_var = false; basic_block bb; tree chain; + bool tmclone = TREE_CODE (fn) == FUNCTION_DECL && decl_is_tm_clone (fn); - fprintf (file, "%s (", lang_hooks.decl_printable_name (fn, 2)); + fprintf (file, "%s %s(", lang_hooks.decl_printable_name (fn, 2), + tmclone ? "[tm-clone] " : ""); arg = DECL_ARGUMENTS (fn); while (arg) diff --git a/gcc/tree-eh.c b/gcc/tree-eh.c index fbc444ca716..440ac0f4082 100644 --- a/gcc/tree-eh.c +++ b/gcc/tree-eh.c @@ -54,26 +54,6 @@ using_eh_for_cleanups (void) /* Misc functions used in this file. */ -/* Compare and hash for any structure which begins with a canonical - pointer. Assumes all pointers are interchangeable, which is sort - of already assumed by gcc elsewhere IIRC. */ - -static int -struct_ptr_eq (const void *a, const void *b) -{ - const void * const * x = (const void * const *) a; - const void * const * y = (const void * const *) b; - return *x == *y; -} - -static hashval_t -struct_ptr_hash (const void *a) -{ - const void * const * x = (const void * const *) a; - return (size_t)*x >> 4; -} - - /* Remember and lookup EH landing pad data for arbitrary statements. Really this means any statement that could_throw_p. We could stuff this information into the stmt_ann data structure, but: @@ -284,6 +264,11 @@ collect_finally_tree (gimple stmt, gimple region) collect_finally_tree_1 (gimple_eh_filter_failure (stmt), region); break; + case GIMPLE_EH_ELSE: + collect_finally_tree_1 (gimple_eh_else_n_body (stmt), region); + collect_finally_tree_1 (gimple_eh_else_e_body (stmt), region); + break; + default: /* A type, a decl, or some kind of statement that we're not interested in. Don't walk them. */ @@ -534,6 +519,10 @@ replace_goto_queue_1 (gimple stmt, struct leh_tf_state *tf, case GIMPLE_EH_FILTER: replace_goto_queue_stmt_list (gimple_eh_filter_failure (stmt), tf); break; + case GIMPLE_EH_ELSE: + replace_goto_queue_stmt_list (gimple_eh_else_n_body (stmt), tf); + replace_goto_queue_stmt_list (gimple_eh_else_e_body (stmt), tf); + break; default: /* These won't have gotos in them. */ @@ -921,6 +910,21 @@ lower_try_finally_fallthru_label (struct leh_tf_state *tf) return label; } +/* A subroutine of lower_try_finally. If FINALLY consits of a + GIMPLE_EH_ELSE node, return it. */ + +static inline gimple +get_eh_else (gimple_seq finally) +{ + gimple x = gimple_seq_first_stmt (finally); + if (gimple_code (x) == GIMPLE_EH_ELSE) + { + gcc_assert (gimple_seq_singleton_p (finally)); + return x; + } + return NULL; +} + /* A subroutine of lower_try_finally. If the eh_protect_cleanup_actions langhook returns non-null, then the language requires that the exception path out of a try_finally be treated specially. To wit: the code within @@ -950,7 +954,7 @@ honor_protect_cleanup_actions (struct leh_state *outer_state, gimple_stmt_iterator gsi; bool finally_may_fallthru; gimple_seq finally; - gimple x; + gimple x, eh_else; /* First check for nothing to do. */ if (lang_hooks.eh_protect_cleanup_actions == NULL) @@ -960,12 +964,18 @@ honor_protect_cleanup_actions (struct leh_state *outer_state, return; finally = gimple_try_cleanup (tf->top_p); - finally_may_fallthru = gimple_seq_may_fallthru (finally); + eh_else = get_eh_else (finally); /* Duplicate the FINALLY block. Only need to do this for try-finally, - and not for cleanups. */ - if (this_state) + and not for cleanups. If we've got an EH_ELSE, extract it now. */ + if (eh_else) + { + finally = gimple_eh_else_e_body (eh_else); + gimple_try_set_cleanup (tf->top_p, gimple_eh_else_n_body (eh_else)); + } + else if (this_state) finally = lower_try_finally_dup_block (finally, outer_state); + finally_may_fallthru = gimple_seq_may_fallthru (finally); /* If this cleanup consists of a TRY_CATCH_EXPR with TRY_CATCH_IS_CLEANUP set, the handler of the TRY_CATCH_EXPR is another cleanup which ought @@ -1011,7 +1021,7 @@ lower_try_finally_nofallthru (struct leh_state *state, struct leh_tf_state *tf) { tree lab; - gimple x; + gimple x, eh_else; gimple_seq finally; struct goto_queue_node *q, *qe; @@ -1034,15 +1044,35 @@ lower_try_finally_nofallthru (struct leh_state *state, replace_goto_queue (tf); - lower_eh_constructs_1 (state, finally); - gimple_seq_add_seq (&tf->top_p_seq, finally); + /* Emit the finally block into the stream. Lower EH_ELSE at this time. */ + eh_else = get_eh_else (finally); + if (eh_else) + { + finally = gimple_eh_else_n_body (eh_else); + lower_eh_constructs_1 (state, finally); + gimple_seq_add_seq (&tf->top_p_seq, finally); - if (tf->may_throw) + if (tf->may_throw) + { + finally = gimple_eh_else_e_body (eh_else); + lower_eh_constructs_1 (state, finally); + + emit_post_landing_pad (&eh_seq, tf->region); + gimple_seq_add_seq (&eh_seq, finally); + } + } + else { - emit_post_landing_pad (&eh_seq, tf->region); + lower_eh_constructs_1 (state, finally); + gimple_seq_add_seq (&tf->top_p_seq, finally); - x = gimple_build_goto (lab); - gimple_seq_add_stmt (&eh_seq, x); + if (tf->may_throw) + { + emit_post_landing_pad (&eh_seq, tf->region); + + x = gimple_build_goto (lab); + gimple_seq_add_stmt (&eh_seq, x); + } } } @@ -1062,6 +1092,18 @@ lower_try_finally_onedest (struct leh_state *state, struct leh_tf_state *tf) finally = gimple_try_cleanup (tf->top_p); tf->top_p_seq = gimple_try_eval (tf->top_p); + /* Since there's only one destination, and the destination edge can only + either be EH or non-EH, that implies that all of our incoming edges + are of the same type. Therefore we can lower EH_ELSE immediately. */ + x = get_eh_else (finally); + if (x) + { + if (tf->may_throw) + finally = gimple_eh_else_e_body (x); + else + finally = gimple_eh_else_n_body (x); + } + lower_eh_constructs_1 (state, finally); if (tf->may_throw) @@ -1132,11 +1174,18 @@ lower_try_finally_copy (struct leh_state *state, struct leh_tf_state *tf) gimple_seq finally; gimple_seq new_stmt; gimple_seq seq; - gimple x; + gimple x, eh_else; tree tmp; location_t tf_loc = gimple_location (tf->try_finally_expr); finally = gimple_try_cleanup (tf->top_p); + + /* Notice EH_ELSE, and simplify some of the remaining code + by considering FINALLY to be the normal return path only. */ + eh_else = get_eh_else (finally); + if (eh_else) + finally = gimple_eh_else_n_body (eh_else); + tf->top_p_seq = gimple_try_eval (tf->top_p); new_stmt = NULL; @@ -1153,7 +1202,12 @@ lower_try_finally_copy (struct leh_state *state, struct leh_tf_state *tf) if (tf->may_throw) { - seq = lower_try_finally_dup_block (finally, state); + /* We don't need to copy the EH path of EH_ELSE, + since it is only emitted once. */ + if (eh_else) + seq = gimple_eh_else_e_body (eh_else); + else + seq = lower_try_finally_dup_block (finally, state); lower_eh_constructs_1 (state, seq); emit_post_landing_pad (&eh_seq, tf->region); @@ -1252,7 +1306,7 @@ lower_try_finally_switch (struct leh_state *state, struct leh_tf_state *tf) tree last_case; VEC (tree,heap) *case_label_vec; gimple_seq switch_body; - gimple x; + gimple x, eh_else; tree tmp; gimple switch_stmt; gimple_seq finally; @@ -1263,9 +1317,10 @@ lower_try_finally_switch (struct leh_state *state, struct leh_tf_state *tf) location_t finally_loc; switch_body = gimple_seq_alloc (); + finally = gimple_try_cleanup (tf->top_p); + eh_else = get_eh_else (finally); /* Mash the TRY block to the head of the chain. */ - finally = gimple_try_cleanup (tf->top_p); tf->top_p_seq = gimple_try_eval (tf->top_p); /* The location of the finally is either the last stmt in the finally @@ -1281,7 +1336,7 @@ lower_try_finally_switch (struct leh_state *state, struct leh_tf_state *tf) nlabels = VEC_length (tree, tf->dest_array); return_index = nlabels; eh_index = return_index + tf->may_return; - fallthru_index = eh_index + tf->may_throw; + fallthru_index = eh_index + (tf->may_throw && !eh_else); ndests = fallthru_index + tf->may_fallthru; finally_tmp = create_tmp_var (integer_type_node, "finally_tmp"); @@ -1319,7 +1374,23 @@ lower_try_finally_switch (struct leh_state *state, struct leh_tf_state *tf) gimple_seq_add_stmt (&switch_body, x); } - if (tf->may_throw) + /* For EH_ELSE, emit the exception path (plus resx) now, then + subsequently we only need consider the normal path. */ + if (eh_else) + { + if (tf->may_throw) + { + finally = gimple_eh_else_e_body (eh_else); + lower_eh_constructs_1 (state, finally); + + emit_post_landing_pad (&eh_seq, tf->region); + gimple_seq_add_seq (&eh_seq, finally); + emit_resx (&eh_seq, tf->region); + } + + finally = gimple_eh_else_n_body (eh_else); + } + else if (tf->may_throw) { emit_post_landing_pad (&eh_seq, tf->region); @@ -1452,12 +1523,22 @@ lower_try_finally_switch (struct leh_state *state, struct leh_tf_state *tf) the estimate of the size of the switch machinery we'd have to add. */ static bool -decide_copy_try_finally (int ndests, gimple_seq finally) +decide_copy_try_finally (int ndests, bool may_throw, gimple_seq finally) { int f_estimate, sw_estimate; + gimple eh_else; + + /* If there's an EH_ELSE involved, the exception path is separate + and really doesn't come into play for this computation. */ + eh_else = get_eh_else (finally); + if (eh_else) + { + ndests -= may_throw; + finally = gimple_eh_else_n_body (eh_else); + } if (!optimize) - return false; + return ndests == 1; /* Finally estimate N times, plus N gotos. */ f_estimate = count_insns_seq (finally, &eni_size_weights); @@ -1563,7 +1644,8 @@ lower_try_finally (struct leh_state *state, gimple tp) /* We can easily special-case redirection to a single destination. */ else if (ndests == 1) lower_try_finally_onedest (state, &this_tf); - else if (decide_copy_try_finally (ndests, gimple_try_cleanup (tp))) + else if (decide_copy_try_finally (ndests, this_tf.may_throw, + gimple_try_cleanup (tp))) lower_try_finally_copy (state, &this_tf); else lower_try_finally_switch (state, &this_tf); @@ -1928,6 +2010,9 @@ lower_eh_constructs_2 (struct leh_state *state, gimple_stmt_iterator *gsi) case GIMPLE_EH_MUST_NOT_THROW: replace = lower_eh_must_not_throw (state, stmt); break; + case GIMPLE_EH_ELSE: + /* This code is only valid with GIMPLE_TRY_FINALLY. */ + gcc_unreachable (); default: replace = lower_cleanup (state, stmt); break; @@ -1942,6 +2027,10 @@ lower_eh_constructs_2 (struct leh_state *state, gimple_stmt_iterator *gsi) /* Return since we don't want gsi_next () */ return; + case GIMPLE_EH_ELSE: + /* We should be eliminating this in lower_try_finally et al. */ + gcc_unreachable (); + default: /* A type, a decl, or some kind of statement that we're not interested in. Don't walk them. */ @@ -2832,6 +2921,10 @@ refactor_eh_r (gimple_seq seq) case GIMPLE_EH_FILTER: refactor_eh_r (gimple_eh_filter_failure (one)); break; + case GIMPLE_EH_ELSE: + refactor_eh_r (gimple_eh_else_n_body (one)); + refactor_eh_r (gimple_eh_else_e_body (one)); + break; default: break; } diff --git a/gcc/tree-flow.h b/gcc/tree-flow.h index dcfbb9da628..211c1079f3c 100644 --- a/gcc/tree-flow.h +++ b/gcc/tree-flow.h @@ -33,6 +33,14 @@ along with GCC; see the file COPYING3. If not see #include "tree-ssa-alias.h" +/* This structure is used to map a gimple statement to a label, + or list of labels to represent transaction restart. */ + +struct GTY(()) tm_restart_node { + gimple stmt; + tree label_or_list; +}; + /* Gimple dataflow datastructure. All publicly available fields shall have gimple_ accessor defined in tree-flow-inline.h, all publicly modifiable fields should have gimple_set accessor. */ @@ -80,6 +88,10 @@ struct GTY(()) gimple_df { unsigned int ipa_pta : 1; struct ssa_operands ssa_operands; + + /* Map gimple stmt to tree label (or list of labels) for transaction + restart and abort. */ + htab_t GTY ((param_is (struct tm_restart_node))) tm_restart; }; /* Accessors for internal use only. Generic code should use abstraction diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c index 11be8d0791f..4ca4fa464f9 100644 --- a/gcc/tree-inline.c +++ b/gcc/tree-inline.c @@ -1365,6 +1365,12 @@ remap_gimple_stmt (gimple stmt, copy_body_data *id) = gimple_build_omp_critical (s1, gimple_omp_critical_name (stmt)); break; + case GIMPLE_TRANSACTION: + s1 = remap_gimple_seq (gimple_transaction_body (stmt), id); + copy = gimple_build_transaction (s1, gimple_transaction_label (stmt)); + gimple_transaction_set_subcode (copy, gimple_transaction_subcode (stmt)); + break; + default: gcc_unreachable (); } @@ -3600,6 +3606,11 @@ estimate_num_insns (gimple stmt, eni_weights *weights) return (weights->omp_cost + estimate_num_insns_seq (gimple_omp_body (stmt), weights)); + case GIMPLE_TRANSACTION: + return (weights->tm_cost + + estimate_num_insns_seq (gimple_transaction_body (stmt), + weights)); + default: gcc_unreachable (); } @@ -3639,6 +3650,7 @@ init_inline_once (void) eni_size_weights.target_builtin_call_cost = 1; eni_size_weights.div_mod_cost = 1; eni_size_weights.omp_cost = 40; + eni_size_weights.tm_cost = 10; eni_size_weights.time_based = false; eni_size_weights.return_cost = 1; @@ -3650,6 +3662,7 @@ init_inline_once (void) eni_time_weights.target_builtin_call_cost = 1; eni_time_weights.div_mod_cost = 10; eni_time_weights.omp_cost = 40; + eni_time_weights.tm_cost = 40; eni_time_weights.time_based = true; eni_time_weights.return_cost = 2; } @@ -4041,9 +4054,7 @@ expand_call_inline (basic_block bb, gimple stmt, copy_body_data *id) /* Expand call statements reachable from STMT_P. We can only have CALL_EXPRs as the "toplevel" tree code or nested - in a MODIFY_EXPR. See gimple.c:get_call_expr_in(). We can - unfortunately not use that function here because we need a pointer - to the CALL_EXPR, not the tree itself. */ + in a MODIFY_EXPR. */ static bool gimple_expand_calls_inline (basic_block bb, copy_body_data *id) diff --git a/gcc/tree-inline.h b/gcc/tree-inline.h index fb039e3194c..2aac5f8b9d3 100644 --- a/gcc/tree-inline.h +++ b/gcc/tree-inline.h @@ -144,6 +144,9 @@ typedef struct eni_weights_d /* Cost for omp construct. */ unsigned omp_cost; + /* Cost for tm transaction. */ + unsigned tm_cost; + /* Cost of return. */ unsigned return_cost; diff --git a/gcc/tree-pass.h b/gcc/tree-pass.h index df1e24c7906..cc8847e8dff 100644 --- a/gcc/tree-pass.h +++ b/gcc/tree-pass.h @@ -447,6 +447,12 @@ extern struct gimple_opt_pass pass_build_cgraph_edges; extern struct gimple_opt_pass pass_local_pure_const; extern struct gimple_opt_pass pass_tracer; extern struct gimple_opt_pass pass_warn_unused_result; +extern struct gimple_opt_pass pass_diagnose_tm_blocks; +extern struct gimple_opt_pass pass_lower_tm; +extern struct gimple_opt_pass pass_tm_init; +extern struct gimple_opt_pass pass_tm_mark; +extern struct gimple_opt_pass pass_tm_memopt; +extern struct gimple_opt_pass pass_tm_edges; extern struct gimple_opt_pass pass_split_functions; extern struct gimple_opt_pass pass_feedback_split_functions; @@ -469,6 +475,7 @@ extern struct ipa_opt_pass_d pass_ipa_pure_const; extern struct simple_ipa_opt_pass pass_ipa_pta; extern struct ipa_opt_pass_d pass_ipa_lto_wpa_fixup; extern struct ipa_opt_pass_d pass_ipa_lto_finish_out; +extern struct simple_ipa_opt_pass pass_ipa_tm; extern struct ipa_opt_pass_d pass_ipa_profile; extern struct ipa_opt_pass_d pass_ipa_cdtor_merge; diff --git a/gcc/tree-pretty-print.c b/gcc/tree-pretty-print.c index 24d70c3ff38..d0546c6c1ca 100644 --- a/gcc/tree-pretty-print.c +++ b/gcc/tree-pretty-print.c @@ -2264,6 +2264,26 @@ dump_generic_node (pretty_printer *buffer, tree node, int spc, int flags, is_expr = false; break; + case TRANSACTION_EXPR: + if (TRANSACTION_EXPR_OUTER (node)) + pp_string (buffer, "__transaction_atomic [[outer]]"); + else if (TRANSACTION_EXPR_RELAXED (node)) + pp_string (buffer, "__transaction_relaxed"); + else + pp_string (buffer, "__transaction_atomic"); + if (!(flags & TDF_SLIM) && TRANSACTION_EXPR_BODY (node)) + { + newline_and_indent (buffer, spc); + pp_character (buffer, '{'); + newline_and_indent (buffer, spc + 2); + dump_generic_node (buffer, TRANSACTION_EXPR_BODY (node), + spc + 2, flags, false); + newline_and_indent (buffer, spc); + pp_character (buffer, '}'); + } + is_expr = false; + break; + case REDUC_MAX_EXPR: pp_string (buffer, " REDUC_MAX_EXPR < "); dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags, false); diff --git a/gcc/tree-ssa-alias.c b/gcc/tree-ssa-alias.c index 57fc7341c54..cd222093579 100644 --- a/gcc/tree-ssa-alias.c +++ b/gcc/tree-ssa-alias.c @@ -1182,6 +1182,8 @@ ref_maybe_used_by_call_p_1 (gimple call, ao_ref *ref) case BUILT_IN_MEMPCPY: case BUILT_IN_STPCPY: case BUILT_IN_STPNCPY: + case BUILT_IN_TM_MEMCPY: + case BUILT_IN_TM_MEMMOVE: { ao_ref dref; tree size = NULL_TREE; @@ -1228,6 +1230,32 @@ ref_maybe_used_by_call_p_1 (gimple call, ao_ref *ref) size); return refs_may_alias_p_1 (&dref, ref, false); } + + /* The following functions read memory pointed to by their + first argument. */ + CASE_BUILT_IN_TM_LOAD (1): + CASE_BUILT_IN_TM_LOAD (2): + CASE_BUILT_IN_TM_LOAD (4): + CASE_BUILT_IN_TM_LOAD (8): + CASE_BUILT_IN_TM_LOAD (FLOAT): + CASE_BUILT_IN_TM_LOAD (DOUBLE): + CASE_BUILT_IN_TM_LOAD (LDOUBLE): + CASE_BUILT_IN_TM_LOAD (M64): + CASE_BUILT_IN_TM_LOAD (M128): + CASE_BUILT_IN_TM_LOAD (M256): + case BUILT_IN_TM_LOG: + case BUILT_IN_TM_LOG_1: + case BUILT_IN_TM_LOG_2: + case BUILT_IN_TM_LOG_4: + case BUILT_IN_TM_LOG_8: + case BUILT_IN_TM_LOG_FLOAT: + case BUILT_IN_TM_LOG_DOUBLE: + case BUILT_IN_TM_LOG_LDOUBLE: + case BUILT_IN_TM_LOG_M64: + case BUILT_IN_TM_LOG_M128: + case BUILT_IN_TM_LOG_M256: + return ptr_deref_may_alias_ref_p_1 (gimple_call_arg (call, 0), ref); + /* These read memory pointed to by the first argument. */ case BUILT_IN_STRDUP: case BUILT_IN_STRNDUP: @@ -1250,6 +1278,7 @@ ref_maybe_used_by_call_p_1 (gimple call, ao_ref *ref) case BUILT_IN_STACK_SAVE: case BUILT_IN_STACK_RESTORE: case BUILT_IN_MEMSET: + case BUILT_IN_TM_MEMSET: case BUILT_IN_MEMSET_CHK: case BUILT_IN_FREXP: case BUILT_IN_FREXPF: @@ -1480,6 +1509,19 @@ call_may_clobber_ref_p_1 (gimple call, ao_ref *ref) case BUILT_IN_STRCAT: case BUILT_IN_STRNCAT: case BUILT_IN_MEMSET: + case BUILT_IN_TM_MEMSET: + CASE_BUILT_IN_TM_STORE (1): + CASE_BUILT_IN_TM_STORE (2): + CASE_BUILT_IN_TM_STORE (4): + CASE_BUILT_IN_TM_STORE (8): + CASE_BUILT_IN_TM_STORE (FLOAT): + CASE_BUILT_IN_TM_STORE (DOUBLE): + CASE_BUILT_IN_TM_STORE (LDOUBLE): + CASE_BUILT_IN_TM_STORE (M64): + CASE_BUILT_IN_TM_STORE (M128): + CASE_BUILT_IN_TM_STORE (M256): + case BUILT_IN_TM_MEMCPY: + case BUILT_IN_TM_MEMMOVE: { ao_ref dref; tree size = NULL_TREE; diff --git a/gcc/tree-ssa-structalias.c b/gcc/tree-ssa-structalias.c index 51f2aa1bf7c..fe0c4e9c389 100644 --- a/gcc/tree-ssa-structalias.c +++ b/gcc/tree-ssa-structalias.c @@ -4024,6 +4024,8 @@ find_func_aliases_for_builtin_call (gimple t) case BUILT_IN_STPCPY_CHK: case BUILT_IN_STRCAT_CHK: case BUILT_IN_STRNCAT_CHK: + case BUILT_IN_TM_MEMCPY: + case BUILT_IN_TM_MEMMOVE: { tree res = gimple_call_lhs (t); tree dest = gimple_call_arg (t, (DECL_FUNCTION_CODE (fndecl) @@ -4056,6 +4058,7 @@ find_func_aliases_for_builtin_call (gimple t) } case BUILT_IN_MEMSET: case BUILT_IN_MEMSET_CHK: + case BUILT_IN_TM_MEMSET: { tree res = gimple_call_lhs (t); tree dest = gimple_call_arg (t, 0); @@ -4197,6 +4200,50 @@ find_func_aliases_for_builtin_call (gimple t) } return true; } + CASE_BUILT_IN_TM_STORE (1): + CASE_BUILT_IN_TM_STORE (2): + CASE_BUILT_IN_TM_STORE (4): + CASE_BUILT_IN_TM_STORE (8): + CASE_BUILT_IN_TM_STORE (FLOAT): + CASE_BUILT_IN_TM_STORE (DOUBLE): + CASE_BUILT_IN_TM_STORE (LDOUBLE): + CASE_BUILT_IN_TM_STORE (M64): + CASE_BUILT_IN_TM_STORE (M128): + CASE_BUILT_IN_TM_STORE (M256): + { + tree addr = gimple_call_arg (t, 0); + tree src = gimple_call_arg (t, 1); + + get_constraint_for (addr, &lhsc); + do_deref (&lhsc); + get_constraint_for (src, &rhsc); + process_all_all_constraints (lhsc, rhsc); + VEC_free (ce_s, heap, lhsc); + VEC_free (ce_s, heap, rhsc); + return true; + } + CASE_BUILT_IN_TM_LOAD (1): + CASE_BUILT_IN_TM_LOAD (2): + CASE_BUILT_IN_TM_LOAD (4): + CASE_BUILT_IN_TM_LOAD (8): + CASE_BUILT_IN_TM_LOAD (FLOAT): + CASE_BUILT_IN_TM_LOAD (DOUBLE): + CASE_BUILT_IN_TM_LOAD (LDOUBLE): + CASE_BUILT_IN_TM_LOAD (M64): + CASE_BUILT_IN_TM_LOAD (M128): + CASE_BUILT_IN_TM_LOAD (M256): + { + tree dest = gimple_call_lhs (t); + tree addr = gimple_call_arg (t, 0); + + get_constraint_for (dest, &lhsc); + get_constraint_for (addr, &rhsc); + do_deref (&rhsc); + process_all_all_constraints (lhsc, rhsc); + VEC_free (ce_s, heap, lhsc); + VEC_free (ce_s, heap, rhsc); + return true; + } /* Variadic argument handling needs to be handled in IPA mode as well. */ case BUILT_IN_VA_START: diff --git a/gcc/tree.c b/gcc/tree.c index 2cbd68b5fd9..ba6c2e1ef8a 100644 --- a/gcc/tree.c +++ b/gcc/tree.c @@ -9428,6 +9428,8 @@ local_define_builtin (const char *name, tree type, enum built_in_function code, if (ecf_flags & ECF_LEAF) DECL_ATTRIBUTES (decl) = tree_cons (get_identifier ("leaf"), NULL, DECL_ATTRIBUTES (decl)); + if ((ecf_flags & ECF_TM_PURE) && flag_tm) + apply_tm_attr (decl, get_identifier ("transaction_pure")); set_builtin_decl (code, decl, true); } @@ -9593,7 +9595,8 @@ build_common_builtin_nodes (void) ftype = build_function_type_list (ptr_type_node, integer_type_node, NULL_TREE); local_define_builtin ("__builtin_eh_pointer", ftype, BUILT_IN_EH_POINTER, - "__builtin_eh_pointer", ECF_PURE | ECF_NOTHROW | ECF_LEAF); + "__builtin_eh_pointer", + ECF_PURE | ECF_NOTHROW | ECF_LEAF | ECF_TM_PURE); tmp = lang_hooks.types.type_for_mode (targetm.eh_return_filter_mode (), 0); ftype = build_function_type_list (tmp, integer_type_node, NULL_TREE); @@ -11142,6 +11145,37 @@ tree_strip_sign_nop_conversions (tree exp) return exp; } +/* Strip out all handled components that produce invariant + offsets. */ + +const_tree +strip_invariant_refs (const_tree op) +{ + while (handled_component_p (op)) + { + switch (TREE_CODE (op)) + { + case ARRAY_REF: + case ARRAY_RANGE_REF: + if (!is_gimple_constant (TREE_OPERAND (op, 1)) + || TREE_OPERAND (op, 2) != NULL_TREE + || TREE_OPERAND (op, 3) != NULL_TREE) + return NULL; + break; + + case COMPONENT_REF: + if (TREE_OPERAND (op, 2) != NULL_TREE) + return NULL; + break; + + default:; + } + op = TREE_OPERAND (op, 0); + } + + return op; +} + static GTY(()) tree gcc_eh_personality_decl; /* Return the GCC personality function decl. */ diff --git a/gcc/tree.def b/gcc/tree.def index 77dc7d7489a..2a2363e7037 100644 --- a/gcc/tree.def +++ b/gcc/tree.def @@ -1076,6 +1076,10 @@ DEFTREECODE (OMP_ATOMIC_CAPTURE_NEW, "omp_atomic_capture_new", tcc_statement, 2) /* OpenMP clauses. */ DEFTREECODE (OMP_CLAUSE, "omp_clause", tcc_exceptional, 0) +/* TRANSACTION_EXPR tree code. + Operand 0: BODY: contains body of the transaction. */ +DEFTREECODE (TRANSACTION_EXPR, "transaction_expr", tcc_expression, 1) + /* Reduction operations. Operations that take a vector of elements and "reduce" it to a scalar result (e.g. summing the elements of the vector, finding the minimum over diff --git a/gcc/tree.h b/gcc/tree.h index 00b663726b8..3e1e225bd4e 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -539,6 +539,9 @@ struct GTY(()) tree_common { ENUM_IS_SCOPED in ENUMERAL_TYPE + TRANSACTION_EXPR_OUTER in + TRANSACTION_EXPR + public_flag: TREE_OVERFLOW in @@ -566,6 +569,9 @@ struct GTY(()) tree_common { OMP_CLAUSE_PRIVATE_DEBUG in OMP_CLAUSE_PRIVATE + TRANSACTION_EXPR_RELAXED in + TRANSACTION_EXPR + private_flag: TREE_PRIVATE in @@ -1809,6 +1815,14 @@ extern void protected_set_expr_location (tree, location_t); #define CALL_EXPR_ARGP(NODE) \ (&(TREE_OPERAND (CALL_EXPR_CHECK (NODE), 0)) + 3) +/* TM directives and accessors. */ +#define TRANSACTION_EXPR_BODY(NODE) \ + TREE_OPERAND (TRANSACTION_EXPR_CHECK (NODE), 0) +#define TRANSACTION_EXPR_OUTER(NODE) \ + (TRANSACTION_EXPR_CHECK (NODE)->base.static_flag) +#define TRANSACTION_EXPR_RELAXED(NODE) \ + (TRANSACTION_EXPR_CHECK (NODE)->base.public_flag) + /* OpenMP directive and clause accessors. */ #define OMP_BODY(NODE) \ @@ -3455,6 +3469,29 @@ struct GTY(()) #define DECL_NO_INLINE_WARNING_P(NODE) \ (FUNCTION_DECL_CHECK (NODE)->function_decl.no_inline_warning_flag) +/* Nonzero if a FUNCTION_CODE is a TM load/store. */ +#define BUILTIN_TM_LOAD_STORE_P(FN) \ + ((FN) >= BUILT_IN_TM_STORE_1 && (FN) <= BUILT_IN_TM_LOAD_RFW_LDOUBLE) + +/* Nonzero if a FUNCTION_CODE is a TM load. */ +#define BUILTIN_TM_LOAD_P(FN) \ + ((FN) >= BUILT_IN_TM_LOAD_1 && (FN) <= BUILT_IN_TM_LOAD_RFW_LDOUBLE) + +/* Nonzero if a FUNCTION_CODE is a TM store. */ +#define BUILTIN_TM_STORE_P(FN) \ + ((FN) >= BUILT_IN_TM_STORE_1 && (FN) <= BUILT_IN_TM_STORE_WAW_LDOUBLE) + +#define CASE_BUILT_IN_TM_LOAD(FN) \ + case BUILT_IN_TM_LOAD_##FN: \ + case BUILT_IN_TM_LOAD_RAR_##FN: \ + case BUILT_IN_TM_LOAD_RAW_##FN: \ + case BUILT_IN_TM_LOAD_RFW_##FN + +#define CASE_BUILT_IN_TM_STORE(FN) \ + case BUILT_IN_TM_STORE_##FN: \ + case BUILT_IN_TM_STORE_WAR_##FN: \ + case BUILT_IN_TM_STORE_WAW_##FN + /* Nonzero in a FUNCTION_DECL that should be always inlined by the inliner disregarding size and cost heuristics. This is equivalent to using the always_inline attribute without the required diagnostics if the @@ -3542,8 +3579,9 @@ struct GTY(()) tree_function_decl { unsigned pure_flag : 1; unsigned looping_const_or_pure_flag : 1; unsigned has_debug_args_flag : 1; + unsigned tm_clone_flag : 1; - /* 2 bits left */ + /* 1 bit left */ }; /* The source language of the translation-unit. */ @@ -5153,6 +5191,7 @@ extern bool auto_var_in_fn_p (const_tree, const_tree); extern tree build_low_bits_mask (tree, unsigned); extern tree tree_strip_nop_conversions (tree); extern tree tree_strip_sign_nop_conversions (tree); +extern const_tree strip_invariant_refs (const_tree); extern tree lhd_gcc_personality (void); extern void assign_assembler_name_if_neeeded (tree); extern void warn_deprecated_use (tree, tree); @@ -5178,6 +5217,25 @@ extern void expand_return (tree); /* In tree-eh.c */ extern void using_eh_for_cleanups (void); +/* Compare and hash for any structure which begins with a canonical + pointer. Assumes all pointers are interchangeable, which is sort + of already assumed by gcc elsewhere IIRC. */ + +static inline int +struct_ptr_eq (const void *a, const void *b) +{ + const void * const * x = (const void * const *) a; + const void * const * y = (const void * const *) b; + return *x == *y; +} + +static inline hashval_t +struct_ptr_hash (const void *a) +{ + const void * const * x = (const void * const *) a; + return (intptr_t)*x >> 4; +} + /* In fold-const.c */ /* Non-zero if we are folding constants inside an initializer; zero @@ -5546,6 +5604,10 @@ extern tree build_duplicate_type (tree); #define ECF_NOVOPS (1 << 9) /* The function does not lead to calls within current function unit. */ #define ECF_LEAF (1 << 10) +/* Nonzero if this call does not affect transactions. */ +#define ECF_TM_PURE (1 << 11) +/* Nonzero if this call is into the transaction runtime library. */ +#define ECF_TM_BUILTIN (1 << 12) extern int flags_from_decl_or_type (const_tree); extern int call_expr_flags (const_tree); @@ -5596,6 +5658,8 @@ extern void init_attributes (void); a decl attribute to the declaration rather than to its type). */ extern tree decl_attributes (tree *, tree, int); +extern void apply_tm_attr (tree, tree); + /* In integrate.c */ extern void set_decl_abstract_flags (tree, int); extern void set_decl_origin_self (tree); @@ -5808,6 +5872,21 @@ extern unsigned HOST_WIDE_INT compute_builtin_object_size (tree, int); extern unsigned HOST_WIDE_INT highest_pow2_factor (const_tree); extern tree build_personality_function (const char *); +/* In trans-mem.c. */ +extern tree build_tm_abort_call (location_t, bool); +extern bool is_tm_safe (const_tree); +extern bool is_tm_pure (const_tree); +extern bool is_tm_may_cancel_outer (tree); +extern bool is_tm_ending_fndecl (tree); +extern void record_tm_replacement (tree, tree); +extern void tm_malloc_replacement (tree); + +static inline bool +is_tm_safe_or_pure (const_tree x) +{ + return is_tm_safe (x) || is_tm_pure (x); +} + /* In tree-inline.c. */ void init_inline_once (void); diff --git a/gcc/varasm.c b/gcc/varasm.c index d0de2136bd8..ed27dce7b0a 100644 --- a/gcc/varasm.c +++ b/gcc/varasm.c @@ -5859,6 +5859,162 @@ assemble_alias (tree decl, tree target) } } +/* Record and output a table of translations from original function + to its transaction aware clone. Note that tm_pure functions are + considered to be their own clone. */ + +static GTY((if_marked ("tree_map_marked_p"), param_is (struct tree_map))) + htab_t tm_clone_hash; + +void +record_tm_clone_pair (tree o, tree n) +{ + struct tree_map **slot, *h; + + if (tm_clone_hash == NULL) + tm_clone_hash = htab_create_ggc (32, tree_map_hash, tree_map_eq, 0); + + h = ggc_alloc_tree_map (); + h->hash = htab_hash_pointer (o); + h->base.from = o; + h->to = n; + + slot = (struct tree_map **) + htab_find_slot_with_hash (tm_clone_hash, h, h->hash, INSERT); + *slot = h; +} + +tree +get_tm_clone_pair (tree o) +{ + if (tm_clone_hash) + { + struct tree_map *h, in; + + in.base.from = o; + in.hash = htab_hash_pointer (o); + h = (struct tree_map *) htab_find_with_hash (tm_clone_hash, + &in, in.hash); + if (h) + return h->to; + } + return NULL_TREE; +} + +typedef struct tm_alias_pair +{ + unsigned int uid; + tree from; + tree to; +} tm_alias_pair; + +DEF_VEC_O(tm_alias_pair); +DEF_VEC_ALLOC_O(tm_alias_pair,heap); + +/* Helper function for finish_tm_clone_pairs. Dump a hash table entry + into a VEC in INFO. */ + +static int +dump_tm_clone_to_vec (void **slot, void *info) +{ + struct tree_map *map = (struct tree_map *) *slot; + VEC(tm_alias_pair,heap) **tm_alias_pairs + = (VEC(tm_alias_pair, heap) **) info; + tm_alias_pair *p; + + p = VEC_safe_push (tm_alias_pair, heap, *tm_alias_pairs, NULL); + p->from = map->base.from; + p->to = map->to; + p->uid = DECL_UID (p->from); + return 1; +} + +/* Dump the actual pairs to the .tm_clone_table section. */ + +static void +dump_tm_clone_pairs (VEC(tm_alias_pair,heap) *tm_alias_pairs) +{ + unsigned i; + tm_alias_pair *p; + bool switched = false; + + FOR_EACH_VEC_ELT (tm_alias_pair, tm_alias_pairs, i, p) + { + tree src = p->from; + tree dst = p->to; + struct cgraph_node *src_n = cgraph_get_node (src); + struct cgraph_node *dst_n = cgraph_get_node (dst); + + /* The function ipa_tm_create_version() marks the clone as needed if + the original function was needed. But we also mark the clone as + needed if we ever called the clone indirectly through + TM_GETTMCLONE. If neither of these are true, we didn't generate + a clone, and we didn't call it indirectly... no sense keeping it + in the clone table. */ + if (!dst_n || !dst_n->needed) + continue; + + /* This covers the case where we have optimized the original + function away, and only access the transactional clone. */ + if (!src_n || !src_n->needed) + continue; + + if (!switched) + { + switch_to_section (get_named_section (NULL, ".tm_clone_table", 3)); + assemble_align (POINTER_SIZE); + switched = true; + } + + assemble_integer (XEXP (DECL_RTL (src), 0), + POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1); + assemble_integer (XEXP (DECL_RTL (dst), 0), + POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1); + } +} + +/* Helper comparison function for qsorting by the DECL_UID stored in + alias_pair->emitted_diags. */ + +static int +tm_alias_pair_cmp (const void *x, const void *y) +{ + const tm_alias_pair *p1 = (const tm_alias_pair *) x; + const tm_alias_pair *p2 = (const tm_alias_pair *) y; + if (p1->uid < p2->uid) + return -1; + if (p1->uid > p2->uid) + return 1; + return 0; +} + +void +finish_tm_clone_pairs (void) +{ + VEC(tm_alias_pair,heap) *tm_alias_pairs = NULL; + + if (tm_clone_hash == NULL) + return; + + /* We need a determenistic order for the .tm_clone_table, otherwise + we will get bootstrap comparison failures, so dump the hash table + to a vector, sort it, and dump the vector. */ + + /* Dump the hashtable to a vector. */ + htab_traverse_noresize (tm_clone_hash, dump_tm_clone_to_vec, + (void *) &tm_alias_pairs); + /* Sort it. */ + VEC_qsort (tm_alias_pair, tm_alias_pairs, tm_alias_pair_cmp); + + /* Dump it. */ + dump_tm_clone_pairs (tm_alias_pairs); + + htab_delete (tm_clone_hash); + tm_clone_hash = NULL; + VEC_free (tm_alias_pair, heap, tm_alias_pairs); +} + + /* Emit an assembler directive to set symbol for DECL visibility to the visibility type VIS, which must not be VISIBILITY_DEFAULT. */ diff --git a/include/ChangeLog b/include/ChangeLog index d5701f40772..df131629f2b 100644 --- a/include/ChangeLog +++ b/include/ChangeLog @@ -1,3 +1,12 @@ +2011-11-07 Richard Henderson <rth@redhat.com> + + Merged from transactional-memory. + + * demangle.h (enum gnu_v3_ctor_kinds): Add gnu_v3_object_ctor_group. + (enum gnu_v3_dtor_kinds): Add gnu_v3_object_dtor_group. + (DEMANGLE_COMPONENT_TRANSACTION_CLONE): New. + (DEMANGLE_COMPONENT_NONTRANSACTION_CLONE): New. + 2011-10-21 Ulrich Drepper <drepper@gmail.com> * obstack.h [!GNUC] (obstack_free): Avoid cast to int. diff --git a/include/demangle.h b/include/demangle.h index 960e88e0f2a..98b11d796f4 100644 --- a/include/demangle.h +++ b/include/demangle.h @@ -172,7 +172,8 @@ ada_demangle (const char *mangled, int options); enum gnu_v3_ctor_kinds { gnu_v3_complete_object_ctor = 1, gnu_v3_base_object_ctor, - gnu_v3_complete_object_allocating_ctor + gnu_v3_complete_object_allocating_ctor, + gnu_v3_object_ctor_group }; /* Return non-zero iff NAME is the mangled form of a constructor name @@ -186,7 +187,8 @@ extern enum gnu_v3_ctor_kinds enum gnu_v3_dtor_kinds { gnu_v3_deleting_dtor = 1, gnu_v3_complete_object_dtor, - gnu_v3_base_object_dtor + gnu_v3_base_object_dtor, + gnu_v3_object_dtor_group }; /* Return non-zero iff NAME is the mangled form of a destructor name @@ -401,6 +403,13 @@ enum demangle_component_type DEMANGLE_COMPONENT_DEFAULT_ARG, /* An unnamed type. */ DEMANGLE_COMPONENT_UNNAMED_TYPE, + /* A transactional clone. This has one subtree, the encoding for + which it is providing alternative linkage. */ + DEMANGLE_COMPONENT_TRANSACTION_CLONE, + /* A non-transactional clone entry point. In the i386/x86_64 abi, + the unmangled symbol of a tm_callable becomes a thunk and the + non-transactional function version is mangled thus. */ + DEMANGLE_COMPONENT_NONTRANSACTION_CLONE, /* A pack expansion. */ DEMANGLE_COMPONENT_PACK_EXPANSION, /* A cloned function. */ diff --git a/libiberty/ChangeLog b/libiberty/ChangeLog index 559f0c97341..a269a0efed8 100644 --- a/libiberty/ChangeLog +++ b/libiberty/ChangeLog @@ -1,3 +1,17 @@ +2011-11-07 Richard Henderson <rth@redhat.com> + + Merged from transactional-memory. + + * cp-demangle.c (cplus_demangle_fill_ctor): Accept + gnu_v3_object_ctor_group. + (cplus_demangle_fill_dtor): Accept gnu_v3_object_dtor_group. + (d_ctor_dtor_name): Recognize gnu_v3_object_ctor_group + and gnu_v3_object_dtor_group. + (d_dump): Handle DEMANGLE_COMPONENT_TRANSACTION_CLONE + and DEMANGLE_COMPONENT_NONTRANSACTION_CLONE. + (d_make_comp, d_print_comp): Likewise. + (d_special_name): Generate them. + 2011-11-04 Jason Merrill <jason@redhat.com> PR c++/48370 diff --git a/libiberty/cp-demangle.c b/libiberty/cp-demangle.c index d0f57b7fcce..0f1166be48c 100644 --- a/libiberty/cp-demangle.c +++ b/libiberty/cp-demangle.c @@ -585,6 +585,12 @@ d_dump (struct demangle_component *dc, int indent) case DEMANGLE_COMPONENT_HIDDEN_ALIAS: printf ("hidden alias\n"); break; + case DEMANGLE_COMPONENT_TRANSACTION_CLONE: + printf ("transaction clone\n"); + break; + case DEMANGLE_COMPONENT_NONTRANSACTION_CLONE: + printf ("non-transaction clone\n"); + break; case DEMANGLE_COMPONENT_RESTRICT: printf ("restrict\n"); break; @@ -732,7 +738,7 @@ cplus_demangle_fill_ctor (struct demangle_component *p, if (p == NULL || name == NULL || (int) kind < gnu_v3_complete_object_ctor - || (int) kind > gnu_v3_complete_object_allocating_ctor) + || (int) kind > gnu_v3_object_ctor_group) return 0; p->type = DEMANGLE_COMPONENT_CTOR; p->u.s_ctor.kind = kind; @@ -751,7 +757,7 @@ cplus_demangle_fill_dtor (struct demangle_component *p, if (p == NULL || name == NULL || (int) kind < gnu_v3_deleting_dtor - || (int) kind > gnu_v3_base_object_dtor) + || (int) kind > gnu_v3_object_dtor_group) return 0; p->type = DEMANGLE_COMPONENT_DTOR; p->u.s_dtor.kind = kind; @@ -823,6 +829,8 @@ d_make_comp (struct d_info *di, enum demangle_component_type type, case DEMANGLE_COMPONENT_GUARD: case DEMANGLE_COMPONENT_REFTEMP: case DEMANGLE_COMPONENT_HIDDEN_ALIAS: + case DEMANGLE_COMPONENT_TRANSACTION_CLONE: + case DEMANGLE_COMPONENT_NONTRANSACTION_CLONE: case DEMANGLE_COMPONENT_POINTER: case DEMANGLE_COMPONENT_REFERENCE: case DEMANGLE_COMPONENT_RVALUE_REFERENCE: @@ -1762,6 +1770,8 @@ d_java_resource (struct d_info *di) ::= GR <name> ::= GA <encoding> ::= Gr <resource name> + ::= GTt <encoding> + ::= GTn <encoding> */ static struct demangle_component * @@ -1856,6 +1866,23 @@ d_special_name (struct d_info *di) return d_make_comp (di, DEMANGLE_COMPONENT_HIDDEN_ALIAS, d_encoding (di, 0), NULL); + case 'T': + switch (d_next_char (di)) + { + case 'n': + return d_make_comp (di, DEMANGLE_COMPONENT_NONTRANSACTION_CLONE, + d_encoding (di, 0), NULL); + default: + /* ??? The proposal is that other letters (such as 'h') stand + for different variants of transaction cloning, such as + compiling directly for hardware transaction support. But + they still should all be transactional clones of some sort + so go ahead and call them that. */ + case 't': + return d_make_comp (di, DEMANGLE_COMPONENT_TRANSACTION_CLONE, + d_encoding (di, 0), NULL); + } + case 'r': return d_java_resource (di); @@ -1939,6 +1966,9 @@ d_ctor_dtor_name (struct d_info *di) case '3': kind = gnu_v3_complete_object_allocating_ctor; break; + case '5': + kind = gnu_v3_object_ctor_group; + break; default: return NULL; } @@ -1961,6 +1991,9 @@ d_ctor_dtor_name (struct d_info *di) case '2': kind = gnu_v3_base_object_dtor; break; + case '5': + kind = gnu_v3_object_dtor_group; + break; default: return NULL; } @@ -3935,6 +3968,16 @@ d_print_comp (struct d_print_info *dpi, int options, d_print_comp (dpi, options, d_left (dc)); return; + case DEMANGLE_COMPONENT_TRANSACTION_CLONE: + d_append_string (dpi, "transaction clone for "); + d_print_comp (dpi, options, d_left (dc)); + return; + + case DEMANGLE_COMPONENT_NONTRANSACTION_CLONE: + d_append_string (dpi, "non-transaction clone for "); + d_print_comp (dpi, options, d_left (dc)); + return; + case DEMANGLE_COMPONENT_SUB_STD: d_append_buffer (dpi, dc->u.s_string.string, dc->u.s_string.len); return; diff --git a/libitm/ChangeLog b/libitm/ChangeLog new file mode 100644 index 00000000000..cd5a723f2bc --- /dev/null +++ b/libitm/ChangeLog @@ -0,0 +1,916 @@ +2011-11-05 Aldy Hernandez <aldyh@redhat.com> + + * method-wbetl.cc: Update copyright notice. + * aatree.cc: Same. + * util.cc: Same. + * libitm.h: Same. + * memset.cc: Same. + * eh_cpp.cc: Same. + * barrier.tpl: Same. + * useraction.cc: Same. + * stmlock.h: Same. + * memcpy.cc: Same. + * common.h: Same. + * config/generic/tls.cc: Same. + * config/generic/cacheline.h: Same. + * config/generic/cachepage.h: Same. + * config/generic/cacheline.cc: Same. + * config/generic/unaligned.h: Same. + * config/x86/cacheline.h: Same. + * config/x86/cacheline.cc: Same. + * config/x86/unaligned.h: Same. + * config/alpha/cacheline.h: Same. + * config/alpha/unaligned.h: Same. + * config/alpha/sjlj.S: Same. + * config/posix/cachepage.cc: Same. + * config/linux/futex.h: Same. + * config/linux/alpha/futex_bits.h: Same. + +2011-11-04 Torvald Riegel <triegel@redhat.com> + + * libitm.texi: No cover text and invariant sections. + +2011-11-03 Richard Henderson <rth@redhat.com> + + * local_type_traits: New file. + * libitm_i.h: Use it. Use C headers, not C++ wrappers. + +2011-11-03 Richard Henderson <rth@redhat.com> + + * configure.ac: Don't test for gfortran. + * configure: Rebuild. + + * testsuite/lib/libitm.exp: Don't include gfortran-dg.exp. + * testsuite/libitm.c++/c++.exp: Don't use gfortran-dg-runtest. + +2011-11-03 Aldy Hernandez <aldyh@redhat.com> + + * testsuite/libitm.c/memcpy-1.c: Add copyright notice. + * testsuite/libitm.c/memset-1.c: Same. + * testsuite/libitm.c/c.exp: Same. + * testsuite/lib/libitm-dg.exp: Same. + * testsuite/lib/libitm.exp: Same. + * testsuite/libitm.c++/c++.exp: Same. + +2011-11-03 Aldy Hernandez <aldyh@redhat.com> + + * testsuite/config/default.exp: Update copyright date. + * configure.ac: Add copyright info. + * configure.tgt: Same. + +2011-11-03 Aldy Hernandez <aldyh@redhat.com> + + * testsuite/libitm.c/reentrant.c: XFAIL. + * testsuite/libitm.c++/static_ctor.C: XFAIL. + +2011-10-29 Torvald Riegel <triegel@redhat.com> + + * beginend.cc (GTM::gtm_thread::rollback): Add aborting flag and + handle aborts. + (_ITM_abortTransaction): Handle aborts of outer transactions. + * libitm_i.h: Same. + * eh_cpp.cc (GTM::gtm_thread::revert_cpp_exceptions): Fix assertion. + * libitm.texi: Document aborts of outer transactions. + * testsuite/libitm.c/cancel.c: New file. + +2011-10-19 Torvald Riegel <triegel@redhat.com> + + * testsuite/*: Change __transaction to __transaction_atomic or + __transaction_relaxed. + +2011-10-19 Torvald Riegel <triegel@redhat.com> + + * config/linux/x86/tls.h (abi_disp): Make TLS slot read volatile. + (gtm_thr): Same. + +2011-10-19 Torvald Riegel <triegel@redhat.com> + + * libitm_i.h: Add gl_wt dispatch. + * retry.cc (parse_default_method): Same. + * method-gl.cc: New file. + * Makefile.am: Use method-gl.cc. + * Makefile.in: Rebuild. + +2011-10-19 Torvald Riegel <triegel@redhat.com> + + * beginend.cc (GTM::gtm_thread::trycommit): Ensure privatization + safety if requested by a TM method. + * dispatch.h (GTM::abi_dispatch::trycommit): Add parameter for + privatization safety. + * method-serial.cc: Same. + +2011-10-19 Torvald Riegel <triegel@redhat.com> + + * libitm_i.h: Renamed gtm_local_undo to gtm_undolog_entry. + (GTM::gtm_thread): Renamed local_undo to undolog. Renamed + undolog-related member functions from *_local to *_undolog. + * local.cc (gtm_thread::commit_undolog): Same. + * beginend.cc (GTM::gtm_thread::trycommit): Same. + (GTM::gtm_thread::rollback): Roll back undolog before + dispatch-specific rollback. + +2011-10-19 Torvald Riegel <triegel@redhat.com> + + * retry.cc (GTM::gtm_thread::decide_retry_strategy): Handle + re-initialization of the current method group. + * libitm_i.h (GTM::gtm_restart_reason): Add restart reason for this. + +2011-10-19 Torvald Riegel <triegel@redhat.com> + + * alloc.cc (commit_allocations_2): Do not free transaction-local + memory when committing a nested transaction. + +2011-10-19 Torvald Riegel <triegel@redhat.com> + + * method-serial.cc (GTM::gtm_thread::serialirr_mode): Fixed: Use + serial-irrevocable dispatch, not serial. + +2011-10-19 Torvald Riegel <triegel@redhat.com> + + * libitm_i.h (GTM::gtm_restart_reason): Re-arrange and clean up + declarations. + * dispatch.h (GTM::abi_dispatch::begin_or_restart): New. + * method-serial.cc: Implement begin_or_restart(). + * beginend.cc (GTM::gtm_thread::begin_transaction): Call + dispatch-specific begin_or_restart(). + (GTM::gtm_thread::restart): Same. + +2011-08-23 Torvald Riegel <triegel@redhat.com> + + * retry.cc (GTM::gtm_thread::decide_retry_strategy): Cleanup. Fix + restarting without switching to serial mode. + (GTM::gtm_thread::decide_begin_dispatch): Let the caller set the + transaction state. Choose closed-nesting alternative if available. + (GTM::gtm_thread::set_default_dispatch): New. + (parse_default_method): New. + (GTM::gtm_thread::number_of_threads_changed): New. + * method-serial.cc (GTM::serial_mg): New method group class. + (GTM::serialirr_dispatch): Belongs to serial_mg. Remove reinit and + fini. + (GTM::serial_dispatch): Same. + (GTM::serialirr_onwrite_dispatch): Same. + (GTM::gtm_thread::serialirr_mode): Remove calls to fini. + * beginend.cc (GTM::gtm_thread::~gtm_thread): Maintain number of + registered threads. + (GTM::gtm_thread::gtm_thread): Same. + (_ITM_abortTransaction): Remove calls to abi_dispatch::fini(). + (GTM::gtm_thread::trycommit): Same. Reset number of restarts. + (GTM::gtm_thread::begin_transaction): Let decide_begin_dispatch() + choose dispatch but set state according to dispatch here. + * dispatch.h (GTM::abi_dispatch::fini): Move to method group. + (GTM::method_group): New class. + (GTM::abi_dispatch): Add comments. Maintain pointer to method_group. + * libitm_i.h (GTM::gtm_thread): Add declarations for new members. + * libitm.texi: Document TM methods, method groups, method life cycle. + Rename method sets to method groups. + +2011-08-23 Torvald Riegel <triegel@redhat.com> + + * config/x86/tls.h: Moved to ... + * config/linux/x86/tls.h: ... here. + +2011-08-23 Torvald Riegel <triegel@redhat.com> + + * config/x86/tls.h: Use __x86_64__ instead of __LP64__. + Add X32 support. + * config/x86/sjlj.S: Same. + +2011-08-19 Torvald Riegel <triegel@redhat.com> + + * config/linux/rwlock.h: New file. + * config/linux/rwlock.c: New file. + * configure.ac: Reenable futex support (undo SVN rev 157758). + * Makefile.am: Same. + * configure.tgt: Same. + * config/linux/alpha/futex_bits.h: Same. + * config/linux/futex.h: Same. Return number of woken processes. + * config/linux/futex.cc: Same. + (futex_wait): Remove spinning. + * config/linux/x86/futex_bits.h: Same. Set futex timeout to zero. + Use __x86_64__ instead of __LP64__. + * aclocal.m4: Include generic futex checks. + * configure: Rebuild. + * Makefile.in: Rebuild. + * testsuite/Makefile.in: Rebuild. + * beginend.cc: Include pthread.h. + * config/posix/cachepage.cc: Same. + +2011-08-12 Torvald Riegel <triegel@redhat.com> + + * config/x86/tls.h (gtm_tx, set_gtm_tx, setup_gtm_thr): Removed. + (abi_disp, set_abi_disp): Move to tx's TLS slot. + (set_gtm_thr): New. + * config/generic/tls.h (gtm_tx, set_gtm_tx, setup_gtm_thr): Removed. + (set_gtm_thr): New. + (GTM::gtm_thread::thread_num): Removed. + (GTM::gtm_thread): Renamed to GTM::gtm_thread_tls. + * libitm_i.h (GTM::gtm_transaction): Renamed to GTM::gtm_thread. More + tx-to-thread renaming. + * beginend.cc: Adapted to tx-to-thread renaming. + (GTM::gtm_thread::~gtm_thread): Extracted from thread_exit_handler(). + (GTM::gtm_thread::gtm_thread): Extracted from begin_transaction(). + * query.cc (_ITM_getTransactionId, _ITM_inTransaction): Renamed + gtm_transaction to gtm_thread. + (_ITM_getThreadnum): Removed. Not supported anymore. + * testsuite/libitm.c/notx.c (main): Removed _ITM_getThreadnum call. + * libitm.texi: Documented that _ITM_getThreadnum is not supported. + * useraction.cc: Renamed gtm_transaction to gtm_thread. Adapted to + gtm_tx-to-gtm_thr renaming if necessary. + * eh_cpp.cc: Same. + * local.cc: Same. + * retry.cc: Same. + * clone.cc: Same. + * alloc.cc: Same. + * alloc_c.cc: Same. + * alloc_cpp.cc: Same. + * method-serial.cc: Same. + * config/generic/tls.cc: Same. + * config/posix/rwlock.h (gtm_rwlock): Same. + * config/posix/rwlock.cc: Same. Adapted to more tx-to-thread renaming. + +2011-08-12 Torvald Riegel <triegel@redhat.com> + + * config/posix/rwlock.cc (gtm_rwlock::read_lock): Changed locking + implementation. + (gtm_rwlock::read_unlock): Same. + (gtm_rwlock::write_lock_generic): New. Generalized from ... + (gtm_rwlock::write_lock, gtm_rwlock::write_upgrade): ... these. + * libitm_i.h (GTM::gtm_transaction): Added shared_state. + * config/posix/rwlock.h (GTM::gtm_rwlock): Removed a_reader and + w_upgrade. Replaced by per-transaction flags (in shared_state). + Added c_confirmed_writers. + (GTM::gtm_rwlock::read_lock, GTM::gtm_rwlock::read_unlock, + GTM::gtm_rwlock::write_upgrade): Add tx parameter. + * retry.cc (GTM::gtm_transaction::decide_retry_strategy): Same. + * method-serial.cc (GTM::gtm_transaction::serialirr_mode): Same. + * beginend.cc (GTM::gtm_transaction::begin_transaction, + _ITM_abortTransaction, GTM::gtm_transaction::trycommit): Same. + * libitm.texi: Document locking conventions and implementations in + libitm. + +2011-08-12 Torvald Riegel <triegel@redhat.com> + + * libitm_i.h (next_tx): Add list of all threads' transaction. + * beginend.cc (GTM::gtm_transaction::begin_transaction): Register + transaction with list of transactions and ... + (thread_exit_handler): ... deregister here. + * config/alpha/target.h: Add HW_CACHELINE_SIZE setting. + * config/x86/target.h: Same. + +2011-08-12 Torvald Riegel <triegel@redhat.com> + + * testsuite/libitm.c++/static_ctor.C: New file. + +2011-08-12 Torvald Riegel <triegel@redhat.com> + + * testsuite/libitm.c/reentrant.c: New file. + +2011-08-12 Torvald Riegel <triegel@redhat.com> + + * config/generic/tls.h: Remove the free list for transactions and ... + * beginend.cc (GTM::gtm_transaction::operator new): ... allocate ... + (GTM::gtm_transaction::operator delete): ... and release here. + (thread_exit_handler): New. Delete tx when thread terminates. + (thread_exit_init): New. + (GTM::gtm_transaction::begin_transaction): Set up on-exit handler. + * testsuite/libitm.c/txrelease.c: New file. + +2011-08-12 Torvald Riegel <triegel@redhat.com> + + * query.cc (_ITM_getThreadnum): Set up gtm_thread if necessary. + * testsuite/libitm.c/notx.c: New file. + +2011-08-12 Torvald Riegel <triegel@redhat.com> + + * config/generic/tls.h (gtm_thread): Move local_tid from here ... + * libitm_i.h (local_tid): ... to here. + * beginend.cc (GTM::gtm_transaction::begin_transaction): Same. + (GTM::gtm_transaction::operator new): Set up gtm_thread if necessary. + +2011-08-12 Torvald Riegel <triegel@redhat.com> + + * retry.cc (GTM::gtm_transaction::decide_begin_dispatch): Use + serialirr_onwrite_dispatch as new default for now. + * method-serial.cc (serialirr_onwrite_dispatch): New. + (GTM::dispatch_serialirr_onwrite): New. + * libitm_i.h: Same. + +2011-08-12 Torvald Riegel <triegel@redhat.com> + + * beginend.cc (GTM::gtm_transaction::rollback): Roll back tx id as well. + * query.cc (_ITM_getTransactionId): There is no active transaction if + the current nesting level is zero. + +2011-07-28 Torvald Riegel <triegel@redhat.com> + + * beginend.cc (GTM::gtm_transaction::rollback): Fix nesting level + rollback. + +2011-07-28 Torvald Riegel <triegel@redhat.com> + + * retry.cc (GTM::gtm_transaction::decide_begin_dispatch): Get + transaction properties from the caller instead of from the + transaction object. + * libitm_i.h: Same. + * beginend.cc (GTM::gtm_transaction::begin_transaction): Same. + +2011-07-28 Torvald Riegel <triegel@redhat.com> + + * local.cc (gtm_transaction::rollback_local): Support closed nesting. + * eh_cpp.cc (GTM::gtm_transaction::revert_cpp_exceptions): Same. + * dispatch.h: Same. + * method-serial.cc: Same. + * beginend.cc (GTM::gtm_transaction::begin_transaction): Change to + flat nesting as default, and closed nesting on demand. + (GTM::gtm_transaction::rollback): Same. + (_ITM_abortTransaction): Same. + (GTM::gtm_transaction::restart): Same. + (GTM::gtm_transaction::trycommit): Same. + (GTM::gtm_transaction::trycommit_and_finalize): Removed. + (choose_code_path): New. + (GTM::gtm_transaction_cp::save): New. + (GTM::gtm_transaction_cp::commit): New. + * query.cc (_ITM_inTransaction): Support flat nesting. + * libitm_i.h (GTM::gtm_transaction_cp): New helper struct for nesting. + (GTM::gtm_transaction): Support flat and closed nesting. + * alloc.cc (commit_allocations_2): New. + (commit_cb_data): New helper struct. + (GTM::gtm_transaction::commit_allocations): Handle nested + commits/rollbacks. + * libitm.texi: Update user action section, add description of nesting. + +2011-07-28 Torvald Riegel <triegel@redhat.com> + + * libitm_i.h: Add closed nesting as restart reason. + * retry.cc (GTM::gtm_transaction::decide_retry_strategy): Same. + +2011-07-28 Torvald Riegel <triegel@redhat.com> + + * useraction.cc: Use vector instead of list to store actions. + Also support partial rollbacks for closed nesting. + * libitm_i.h (GTM::gtm_transaction::user_action): Same. + * beginend.cc: Same. + +2011-07-28 Torvald Riegel <triegel@redhat.com> + + * dispatch.h (GTM::abi_dispatch): Add can_run_uninstrumented_code and + closed_nesting flags, as well as a closed nesting alternative. + * method-serial.cc: Same. + (serial_dispatch): Renamed to serialirr_dispatch. + (GTM::dispatch_serialirr): Same. + (serial_dispatch_ul): Renamed to serial_dispatch. + (GTM::dispatch_serial): Same. + +2011-07-28 Torvald Riegel <triegel@redhat.com> + + * libitm.h (_ITM_codeProperties): Change pr_hasElse to the ABI's value. + +2011-07-28 Torvald Riegel <triegel@redhat.com> + + * aatree.h (aa_tree::remove): New. + (aa_tree::operator new): Add placement new. + +2011-07-02 Torvald Riegel <triegel@redhat.com> + + * containers.h: New file. + * util.cc (xmalloc, xrealloc): Accept cacheline-alloc flag. + * libitm_i.h (xmalloc, xrealloc): Moved declarations from here ... + * common.h: ... to here. + (local_undo): Use GTM::vector for gtm_transaction::local_undo. + * local.cc: Same. + +2011-06-30 Torvald Riegel <triegel@redhat.com> + + * libitm_i.h (STATE_ABORTING): Remove. + * beginend.cc (_ITM_abortTransaction): Same. + (GTM::gtm_transaction::trycommit_and_finalize): Same. + * libitm.h (_ITM_registerThrownObject, _ITM_tryCommitTransaction): Remove. + (_ITM_rollbackTransaction): Remove. + * beginend.cc: Same. + * libitm.map: Same. + * libitm.texi: Document these ABI changes. + +2011-06-30 Torvald Riegel <triegel@redhat.com> + + * libitm.texi: New file. + * Makefile.am: Add libitm.texi. + * Makefile.in: Rebuild. + +2011-06-30 Torvald Riegel <triegel@redhat.com> + + * libitm_i.h: Move parts to common.h and dispatch.h. + * common.h: New file. + * dispatch.h: New file, new dispatch class. + Rename GTM::abi_dispatch::lock_type to ls_modifier. + RenameGTM::abi_dispatch::NOLOCK to NONTXNAL. + * beginend.cc (GTM::gtm_transaction::begin_transaction): Delegate mode + decision to retry.cc. + * retry.cc (GTM::gtm_transaction::decide_retry_strategy): Use serial mode + only. + (GTM::gtm_transaction::decide_begin_dispatch): Same. + * method-serial.cc: Adapt to new dispatch. Add serial mode with undo + logging. + * barrier.cc: Use new barriers definitions. + (abi_dispatch::memmove_overlap_check): New. + * config/x86/x86_sse.cc: Same. + * config/x86/x86_avx.cc: Same. + * Makefile.am: Don't build readonly and wbetl methods, memset.cc and + memcpy.cc. + * Makefile.in: Rebuild. + * method-readonly.cc: Remove. + * method-wbetl.cc: Rename GTM::abi_dispatch::lock_type to ls_modifier. + Rename GTM::abi_dispatch::NOLOCK to NONTXNAL. + +2011-06-30 Torvald Riegel <triegel@redhat.com> + + * alloc_c.cc (_ITM_dropReferences): Don't support it anymore. + * testsuite/libitm.c++/dropref.C: _ITM_dropReferences is expected to fail. + * testsuite/libitm.c/dropref-2.c: Same. + * testsuite/libitm.c/dropref.c: Same. + +2011-06-30 Torvald Riegel <triegel@redhat.com> + + * config/generic/tls.h (gtm_disp): Rename to abi_disp. + * config/generic/tls.h (set_gtm_disp): Rename to set_abi_disp. + * libitm_i.h: Rename gtm_dispatch to abi_dispatch. + * alloc_c.cc: Same. + * barrier.tpl: Same. + * beginend.c: Same. + * config/generic/tls.h: Same. + * config/x86/tls.h: Same. + * libitm_i.h: Same. + * memcpy.cc: Same. + * memset.cc: Same. + * method-readonly.cc: Same. + * method-serial.cc: Same. + * method-wbetl.cc: Same. + * retry.cc: Same. + +2011-03-03 Richard Henderson <rth@redhat.com> + + * config/posix/rwlock.cc (write_upgrade): Add missing case. + From Patrik Marlier <patrick.marlier@unine.ch>. + +2011-02-03 Richard Henderson <rth@redhat.com> + + * acinclude.m4 (LIBITM_CHECK_SIZE_T_MANGLING): New. + * configure.ac: Use it. + * configure, config.h.in: Rebuild. + * alloc_cpp.cc (_ZnwX): Use MANGLE_SIZE_T in constructing the name. + (_ZnaX, _ZnwXRKSt9nothrow_t, _ZnaXRKSt9nothrow_t, _ZGTtnwX, + _ZGTtnaX, _ZGTtnwXRKSt9nothrow_t, _ZGTtnaXRKSt9nothrow_t): Likewise. + * libitm.map: Use wildcards to match size_t mangling. + +2010-12-14 Richard Henderson <rth@redhat.com> + + * beginend.cc (GTM::gtm_transaction::begin_transaction): Allocate + blocks of TIDs per thread. + * config/generic/tls.h (struct gtm_thread): Add local_tid member. + (setup_gtm_thr): Return the thread structure. + * config/x86/tls.h (setup_gtm_thr): Likewise. + +2010-12-14 Richard Henderson <rth@redhat.com> + + * clone.cc (table_lock): Remove. + (find_clone): Don't take it. + (ExcludeTransaction): New helper class. + (_ITM_registerTMCloneTable): Use it. + (_ITM_deregisterTMCloneTable): Likewise. + +2010-12-14 Richard Henderson <rth@redhat.com> + + * config/x86/tls.h: New file. + +2010-07-15 Richard Henderson <rth@redhat.com> + + * Makefile.am (AM_CXXFLAGS): Add -funwind-tables. + * Makefile.in: Rebuild. + +2010-07-13 Aldy Hernandez <aldyh@redhat.com> + + * method-wbetl.cc (trydropreference): Fix source line. + +2010-07-13 Aldy Hernandez <aldyh@redhat.com> + + * libitm.h: Add comment. + * libitm_i.h (begin_transaction): Add ITM_REGPARM. + +2010-07-07 Aldy Hernandez <aldyh@redhat.com> + + * configure.ac: Call LIBITM_CHECK_64BIT_SYNC_BUILTINS. + * beginend.cc (begin_transaction): If 64-bit sync builtins are not + available, use pthread mutexes. + * acinclude.m4 (LIBITM_CHECK_64BIT_SYNC_BUILTINS): New. + * config.h.in: Regenerate. + * configure: Regenerate. + +2010-07-06 Aldy Hernandez <aldyh@redhat.com> + + * libitm.h (ITM_PURE): Define. + Declare _ITM_malloc, _ITM_calloc, and _ITM_free. + +2010-06-28 Aldy Hernandez <aldyh@redhat.com> + + * method-wbetl.cc (class wbetl_dispatch): Add trydropreference. + (validate): Add comment. + (trydropreference): New. + * method-readonly.cc (class readonly_dispatch): Add + trydropreference. + * alloc_c.cc (_ITM_dropReferences): Remove const attribute. + Call trydropreference(). + * libitm.h (_ITM_dropReferences): Remove const attribute. + * method-serial.cc (class serial_dispatch): Add trydropreference. + * libitm_i.h (struct gtm_dispatch): Add trydropreference. + +2010-06-28 Aldy Hernandez <aldyh@redhat.com> + + * memcpy.cc (do_memcpy): Comment. + +2010-06-25 Aldy Hernandez <aldyh@redhat.com> + + * barrier.tpl: Add comments throughout. + +2010-06-24 Aldy Hernandez <aldyh@redhat.com> + + * method-wbetl.cc (struct w_entry): Add comments. + (trycommit): Same. + (rollback): Same. + +2010-06-24 Aldy Hernandez <aldyh@redhat.com> + + * alloc_c.cc (_ITM_dropReferences): New. + * libitm.map (_ITM_dropReferences): Add. + * libitm.h (_ITM_dropReferences): Add transaction_pure attribute. + * libitm_i.h (struct gtm_transaction): Declare + drop_references_allocations and drop_references_local. + * local.cc (rollback_local): Ignore memory when applicable. + (drop_references_local): New. + +2010-06-23 Richard Henderson <rth@redhat.com> + + * barrier.tpl, beginend.cc, clone.cc, tls.h, memcpy.cc, + memset.cc, method-serial.cc: Revert the 2010-06-16 change. + * config/x86/target.h (struct gtm_jmpbuf): Change CFA type to void*. + * config/alpha/target.h: Likewise. + * config/generic/tls.cc (gtm_mask_stack): Use it. + +2010-06-23 Richard Henderson <rth@redhat.com> + + * config/posix/cachepage.cc (gtm_cacheline_page::operator new): Use + a mutex instead of trying a lock-free compare-and-swap on the list. + (gtm_cacheline_page::operator delete): Likewise. + +2010-06-16 Richard Henderson <rth@redhat.com> + + * method-wbetl.cc (wbetl_dispatch::trycommit): Discard changes + that overlap the libitm stack. + * barrier.tpl: Mark incoming stack. + * beginend.cc (_ITM_rollbackTransaction, _ITM_abortTransaction, + _ITM_commitTransaction, _ITM_commitTransactionEH): Likewise. + * clone.cc (_ITM_getTMCloneOrIrrevocable): Likewise. + * memcpy.cc, memset.cc: Likewise. + * method-serial.cc (_ITM_changeTransactionMode): Likewise. + * config/generic/tls.h (gtm_thread): Add stack_top member. + (gtm_stack_top, set_gtm_stack_top, struct gtm_stack_marker): New. + * libitm_i.h (gtm_mask_stack): Declare. + * config/generic/tls.cc: New file. + * Makefile.am (libitm_la_SOURCES): Add it. + (AM_CXXFLAGS): Turn off exceptions. + * Makefile.in: Rebuild. + +2010-06-16 Richard Henderson <rth@redhat.com> + + * alloc.cc (struct gtm_alloc_action): Move definition ... + * libitm_i.h: ... here. + (class gtm_transaction): Declare new and delete. + * beginend.cc (alloc_tx): Reformulate as operator new. + (free_tx): Reformulate as operator delete. + * config/generic/tls.h (gtm_thread): Change free_tx member to void *. + +2010-06-11 Richard Henderson <rth@redhat.com> + + * clone.cc (clone_entry_compare): Fix typo. + From Patrik Marlier <patrick.marlier@unine.ch>. + +2010-05-13 Richard Henderson <rth@redhat.com> + + * alloc_c.cc (_ITM_malloc, _ITM_calloc, _ITM_free): Wrap functions + in extern "C". + +2010-05-07 Aldy Hernandez <aldyh@redhat.com> + + * libitm_i.h (struct gtm_transaction): Remove + get_allocation_size. + (record_allocation): Remove size parameter. + * libitm.map (_ITM_realloc): Remove. + * alloc_c.cc (_ITM_realloc): Remove. + (_ITM_malloc): Remove size argument to record_allocation. + (_ITM_calloc): Same. + * alloc_cpp.cc (_ZGTtnwm): Same. + (_ZGTtnwmRKSt9nothrow_t): Same. + (_ZGTtnam): Same. + (_ZGTtnamRKSt9nothrow_t): Same. + * alloc.cc (struct gtm_alloc_action): Remove size. + (get_allocation_size): Remove. + (commit_allocations): Add comment. + (record_allocation): Remove size parameter. + (forget_allocation): Remove set of size. + +2010-04-19 Aldy Hernandez <aldyh@redhat.com> + + * Makefile.am (abi_version): New. + (AM_CXXFLAGS): Pass abi_version. + * Makefile.in: Regenerate. + * config/x86/unaligned.h: Remove always_inline kludge for vectors. + +2010-04-06 Aldy Hernandez <aldyh@redhat.com> + + * clone.cc (_ITM_getTMCloneOrIrrevocable): Rename from + _ITM_getTMCloneOrIrrevokable. + * libitm.h (_ITM_getTMCloneOrIrrevocable): Same. + * libitm.map (_ITM_getTMCloneOrIrrevocable): Same. + +2010-03-26 Aldy Hernandez <aldyh@redhat.com> + + * configure.ac: Remove Linux futex support. + * configure.tgt (config_path): Same. + * Makefile.am: Same. + * config/linux: Remove entire directory. + * configure: Rebuild. + * Makefile.in: Rebuild. + * testsuite/Makefile.in: Rebuild. + +2010-03-09 Aldy Hernandez <aldyh@redhat.com> + + * retry.cc (decide_retry_strategy): Set state to STATE_SERIAL when + switching to serial mode. + * beginend.cc (trycommit_and_finalize): Unlock serial_lock. + +2010-03-03 Aldy Hernandez <aldyh@redhat.com> + + * configure.tgt: Add emacs -*- tags. + * barrier.tpl: Same. + +2010-02-23 Aldy Hernandez <aldyh@redhat.com> + + * Makefile.am: Rename serial.cc to method-serial.cc. + * Makefile.in: Regenerate with automake 1.11.1. + * testsuite/Makefile.in: Same. + * aclocal.m4: Regenerate with aclocal 1.11.1. + * method-serial.cc: Rename from serial.cc. + * libitm_i.h (struct gtm_transaction): Update comment on + serialirr_mode. + +2010-02-22 Aldy Hernandez <aldyh@redhat.com> + + * libitm_i.h (GTM_longjmp): Add ITM_REGPARM. + * config/linux/rwlock.h (class gtm_rwlock): Add comments. + +2010-02-11 Aldy Hernandez <aldyh@redhat.com> + + * configure: Rebuild. + +2009-11-12 Richard Henderson <rth@redhat.com> + + * Rewrite everything in C++. + +2009-11-03 Richard Henderson <rth@redhat.com> + + * config/x86/x86_sse.c, config/x86/x86_avx.c: New files. + * Makefile.am (libitm_la_SOURCES): Add them. + * configure.ac (ARCH_X86): New conditional. + * Makefile.in, configure: Rebuild. + * configure.tgt: Set up ARCH; do cflags setup at the same time. + Move futex setup into "other system configury" case. + * local.c (rollback_local): Merge into ... + (GTM_rollback_local): ... here. + (GTM_LB): Rename from GTM_alloc_local; do the memcpy here. + (_ITM_LB): Define as an alias to GTM_LB. + +2009-11-03 Richard Henderson <rth@redhat.com> + + * method-readonly.c: New file. + * Makefile.am (libitm_la_SOURCES): Add it. + * Makefile.in: Rebuild. + * beginend.c (gtm_stmlock_array, gtm_clock): New. + (GTM_begin_transaction): Use dispatch_readonly for read-only txn. + * libitm_i.h (gtm_stmlock, gtm_version): Move from method-wbetl.c. + (GTM_VERSION_MAX, GTM_VERSION_INVALID, gtm_stmlock_owned_p, + gtm_stmlock_set_owned, gtm_stmlock_get_addr, + gtm_stmlock_get_version, gtm_stmlock_set_version, LOCK_ARRAY_SIZE, + gtm_stmlock_array, gtm_get_stmlock, gtm_clock, RESTART_NOT_READONLY, + gtm_get_clock, gtm_inc_clock): New. + * method-wbetl.c (gtm_version, gtm_stmlock, OWNED_MASK, VERSION_MAX, + LOCK_GET_OWNED, LOCK_SET_ADDR, LOCK_GET_ADDR, LOCK_GET_TIMESTAMP, + LOCK_SET_TIMESTAMP, LOCK_ARRAY_SIZE, LOCK_MASK, LOCK_IDX, GET_LOCK, + locks, gclock, CLOCK, GET_CLOCK, FETCH_AND_INC_CLOCK): Remove and + replace uses with new libitm_i.h symbols. + (dispatch_wbetl): Rename from wbetl_dispatch. + * retry.c (GTM_decide_retry_strategy): If RESTART_NOT_READONLY, move + away from dispatch_readonly; abort if the beginTransaction call + asserted that the transaction was readonly. + +2009-11-03 Richard Henderson <rth@redhat.com> + + * memset.c: New file. + * Makefile.am (libitm_la_SOURCES): Add it. + * Makefile.in: Rebuild. + * testsuite/libitm.c/memset-1.c: New. + +2009-11-03 Richard Henderson <rth@redhat.com> + + * dispatch.c: Remove file. + * useraction.c (struct gtm_user_action): Move from libitm.h. + * serial.c (GTM_null_read_lock, GTM_null_write_lock): New. + (serial_memset, serial_memmove, serial_memcpy): Remove. + (serial_W*, serial_R*): Remove. + (serial_dispatch): Update to match. + * configure.ac: Move Werror down below configure checks. Don't + check for sys/loadavg.h, do check for malloc.h. Don't check for + getloadavg and clock_gettime; do check for memalign, posix_memalign. + Use GCC_AC_FUNC_MMAP_BLACKLIST + * libitm.h: Split out all internal items to... + * libitm_i.h: ... here. New file. + * copymask.c: New file. + * local.c (struct gtm_local_undo): Move from libitm.h. + (GTM_alloc_local): Rename from alloc_local; export. + * memcpy.c: New file. + * alloc_c.c (_ITM_realloc): Use _ITM_memcpyRnWt directly. + * config/posix/page.c: New file. + * config/posix/target_tls.h: Remove file. + * barrier.c: New file. + * Makefile.am (libitm_la_SOURCES): Add barrier.c, memcpy.c, + copymask.c, page.c. + * alloc.c (struct gtm_alloc_action): Move from libitm.h. + * method-wbetl.c: Rewrite for new cacheline methods. + * Makefile.in, configure, testsuite/Makefile.in, config.h.in: Rebuild. + + * config/alpha/sjlj.S: Fix typo. + * config/alpha/target_i.h: Copy functions from alpha/target.h. + * config/alpha/copymask.c: New file. + * config/alpha/target.h (CACHELINE_SIZE): New. + (STRICT_ALIGNMENT, PAGE_SIZE, FIXED_PAGE_SIZE): New. + + * config/x86/target_i.h: Copy functions from x86/target.h. + * config/x86/copymask.c: New file. + * config/x86/target.h (_ITM_ALL_TARGET_TYPES): Remove. + (CACHELINE_SIZE, STRICT_ALIGNMENT): New. + (PAGE_SIZE, FIXED_PAGE_SIZE): New. + * config/x86/target_tls.h: Move contents to target_i.h. + + * testsuite/libitm.c/clone-1.c: Include libitm.h. + * testsuite/libitm.c/memcpy-1.c: New. + +2009-10-22 Richard Henderson <rth@redhat.com> + + * Makefile.am (CCAS, CCASFLAGS, LTCCASCOMPILE): Remove. + (AM_CCASFLAGS): New. + * configure.ac: Add AM_PROG_AS. Use m4_rename_force for + saving/restoring _AC_ARG_VAR_PRECIOUS. + * Makefile.in, aclocal.m4, config.h.in, configure, + testsuite/Makefile.in: Rebuild with automake 1.11; autoconf 2.64. + +2009-10-22 Richard Henderson <rth@redhat.com> + + * testsuite/*: Update for new compiler syntax. + +2009-10-21 Richard Henderson <rth@redhat.com> + + * libitm.h (_ITM_abortReason): Add outerAbort. + +2009-08-03 Richard Henderson <rth@redhat.com> + + * libitm.map (_ITM_commitTransactionEH, _ITM_cxa_allocate_exception, + _ITM_cxa_begin_catch, _ITM_cxa_end_catch, _ITM_cxa_throw): Export. + * method-wbetl.c (struct w_entry): Remove mask. + (wbetl_write, wbetl_load): Return pointer to word containing the data; + adjust all callers. + +2009-07-22 Richard Henderson <rth@redhat.com> + + * eh_cpp.c: New file. + * Makefile.am (libitm_la_SOURCES): Add it. + * Makefile.in: Rebuild. + * beginend.c (GTM_rollback_transaction): Undo exception state. + (GTM_trycommit_transaction): Mark inline. + (GTM_trycommit_and_finalize_transaction): Split out from ... + (_ITM_commitTransaction): ... here. + (_ITM_commitTransactionEH): New function. + * libitm.h (struct gtm_transaction): Add cxa_catch_count, + cxa_unthrown, eh_in_flight; reorder. + + * testsuite/libitm.c++/c++.exp: New. + * testsuite/libitm.c++/eh-1.C: New. + + * aatree.c (aa_free): Remove REGPARM. + * aatree.h: Remove all REGPARM. + +2009-07-18 Richard Henderson <rth@redhat.com> + + * aatree.c, aatree.h, alloc.c, alloc_c.c, alloc_cpp.c: New files. + * Makefile.am (libitm_la_SOURCES): Add them. + * Makefile.in: Rebuild. + * beginend.c (GTM_rollback_transaction): Use GTM_commit_allocations. + (GTM_trycommit_transaction): Likewise. + * libitm.h: Include aatree.h + (struct gtm_alloc_action): New. + (struct gtm_transaction): Add alloc_actions. + (GTM_record_allocation, GTM_forget_allocation): Declare. + (GTM_get_allocation_size, GTM_commit_allocations): Declare. + * libitm.map (_ITM_malloc, _ITM_calloc, _ITM_realloc, _ITM_free, + _ZGTtnwm, _ZGTtnam, _ZGTtdlPv, _ZGTtdaPv, _ZGTtnwmRKSt9nothrow_t, + _ZGTtnamRKSt9nothrow_t, _ZGTtdlPvRKSt9nothrow_t, + _ZGTtdaPvRKSt9nothrow_t): Export. + +2009-07-18 Richard Henderson <rth@redhat.com> + + * target_tls.h: Move ... + * config/posix/target_tls.h: ... here. + +2009-07-07 Richard Henderson <rth@redhat.com> + + * config/x86/target.h (atomic_write_barrier): Use sfence if available. + +2009-07-07 Richard Henderson <rth@redhat.com> + + * Update to GPL3. + +2009-07-07 Richard Henderson <rth@redhat.com> + + * libitm.h (struct gtm_transaction): Widen id to _ITM_transactionId_t. + * beginend.c (global_tid): Widen to _ITM_transactionId_t. + + * configure.tgt: Don't use -ftls-model for x86 linux. + * libitm.h: Include target.h after standard includes. + (_gtm_thr): Rename from gtm_thr. + (setup_gtm_thr, gtm_thr, gtm_tx, set_gtm_tx): New. + (gtm_disp, set_gtm_disp): New. + * beginend.c, dispatch.c, local.c, method-wbetl.c, query.c, + retry.c, serial.c, useraction.c: Use accessor functions throughout. + * config/alpha/target_tls.h, config/x86/target_tls.h: New files. + +2009-07-07 Richard Henderson <rth@redhat.com> + + * config/linux/rwlock.c (EZ): New define. Use it throughout. + +2009-07-06 Richard Henderson <rth@redhat.com> + + * libitm.h (_ITM_SRCLOCATION_DECL_1, _ITM_SRCLOCATION_DECL_2): Remove. + (_ITM_SRCLOCATION_DEFN_1, _ITM_SRCLOCATION_DEFN_2): Remove. + (_ITM_beginTransaction): Take variadic arguments. + (_ITM_registerThrownObject): Declare. + * beginend.c, serial.c: Update. + * libitm.map: Add _ITM_registerThrownObject. + +2009-01-28 Richard Henderson <rth@redhat.com> + + * Makefile.am (libitm_la_SOURCES): Add clone.c. + * Makefile.in: Rebuild. + * beginend.c (_ITM_abortTransaction): Abort if irrevokable. + (GTM_restart_transaction): Fix uninstrumented code check. + * retry.c (GTM_decide_retry_strategy): Add serial check. + * serial.c (GTM_serialmode): Add irrevokable variable. Don't + automatically go irrevokable when in serial mode. + * clone.c: New file. + * libitm.h, libitm.map: Update. + +2009-01-27 Richard Henderson <rth@redhat.com> + + * Makefile.am (LTCCASCOMPILE): Define. + (libitm_la_SOURCES): Add methid-wbetl.c. + * testsuite/Makefile.am: New + * configure.ac: Add testsuite/Makefile. + * Makefile.in, testsuite/Makefile.in, configure: Regenerate. + * beginend.c (GTM_begin_transaction): Install wbetl_dispatch. + (_ITM_abortTransaction): Finalize implementation method; pass + transaction properties to longjmp. + (GTM_restart_transaction): Split out from ... + (_ITM_commitTransaction): ... here. + * config/linux/x86/futex_bits.h (cpu_relax, atomic_write_barrier): + Move to config/x86/target.h. + * config/linux/alpha/futex_bits.h: New. + * config/x86/sjlj.S (GTM_longjmp): Fix 64-bit input register. + * config/x86/target.h: Disable target types for 32-bit. + * config/alpha/sjlj.S, config/alpha/target.h: New. + * libitm.h (struct gtm_dispatch): Add init, fini. + (enum restart_reason): New. + (struct gtm_transaction): Add method and restarts. + * retry.c (GTM_decide_retry_strategy): Implement. + * serial.c (serial_init, serial_fini): New. + (GTM_serialmode): Finialize outgoing method. + * method-wbetl.c: New. + +2008-12-09 Richard Henderson <rth@redhat.com> + + * config/x86/target.h (_ITM_ALL_TARGET_TYPES, _ITM_TYPE_ATTR): New. + * configure.tgt (i386-*, x86_64-*): Don't force SSE. + * dispatch.c (_ITM_##R##T, _ITM_##W##T): Use _ITM_TYPE_ATTR. + * libitm.h (_ITM_ALL_TARGET_TYPES, _ITM_TYPE_ATTR): Provide default. + (_ITM_TYPE_M64, _ITM_TYPE_M128, _ITM_TYPE_M256): Move to x86 header. + (_ITM_ALL_TYPES): Use _ITM_ALL_TARGET_TYPES. + * local.c (_ITM_L##T): Use _ITM_TYPE_ATTR. + * serial.c (serial_R##T, serial_W##T): Likewise. + +2008-11-21 Richard Henderson <rth@redhat.com> + + * Initial commit. diff --git a/libitm/Makefile.am b/libitm/Makefile.am new file mode 100644 index 00000000000..69234099b6c --- /dev/null +++ b/libitm/Makefile.am @@ -0,0 +1,98 @@ +## Process this file with automake to produce Makefile.in + +ACLOCAL_AMFLAGS = -I .. -I ../config +SUBDIRS = testsuite + +## May be used by toolexeclibdir. +gcc_version := $(shell cat $(top_srcdir)/../gcc/BASE-VER) + +abi_version = -fabi-version=4 + +config_path = @config_path@ +search_path = $(addprefix $(top_srcdir)/config/, $(config_path)) $(top_srcdir) + +fincludedir = $(libdir)/gcc/$(target_alias)/$(gcc_version)/finclude +libsubincludedir = $(libdir)/gcc/$(target_alias)/$(gcc_version)/include + +vpath % $(strip $(search_path)) + +AM_CPPFLAGS = $(addprefix -I, $(search_path)) +AM_CFLAGS = $(XCFLAGS) +AM_CXXFLAGS = -std=gnu++0x -funwind-tables -fno-exceptions -fno-rtti \ + $(XCFLAGS) $(abi_version) +AM_CCASFLAGS = $(XCFLAGS) +AM_LDFLAGS = $(XLDFLAGS) $(SECTION_LDFLAGS) $(OPT_LDFLAGS) + +toolexeclib_LTLIBRARIES = libitm.la +nodist_toolexeclib_HEADERS = libitm.spec + +if LIBITM_BUILD_VERSIONED_SHLIB +libitm_version_script = -Wl,--version-script,$(top_srcdir)/libitm.map +else +libitm_version_script = +endif +libitm_version_info = -version-info $(libtool_VERSION) + +# Force link with C, not C++. For now, while we're using C++ we don't +# want or need libstdc++. +libitm_la_LINK = $(LINK) +libitm_la_LDFLAGS = $(libitm_version_info) $(libitm_version_script) \ + -no-undefined + +libitm_la_SOURCES = \ + aatree.cc alloc.cc alloc_c.cc alloc_cpp.cc barrier.cc beginend.cc \ + clone.cc cacheline.cc cachepage.cc eh_cpp.cc local.cc \ + query.cc retry.cc rwlock.cc useraction.cc util.cc \ + sjlj.S tls.cc method-serial.cc method-gl.cc + +if ARCH_X86 +libitm_la_SOURCES += x86_sse.cc x86_avx.cc +x86_sse.lo : XCFLAGS += -msse +x86_avx.lo : XCFLAGS += -mavx +endif + +if ARCH_FUTEX +libitm_la_SOURCES += futex.cc +endif + +# Automake Documentation: +# If your package has Texinfo files in many directories, you can use the +# variable TEXINFO_TEX to tell Automake where to find the canonical +# `texinfo.tex' for your package. The value of this variable should be +# the relative path from the current `Makefile.am' to `texinfo.tex'. +TEXINFO_TEX = ../gcc/doc/include/texinfo.tex + +# Defines info, dvi, pdf and html targets +MAKEINFOFLAGS = -I $(srcdir)/../gcc/doc/include +info_TEXINFOS = libitm.texi + +# AM_CONDITIONAL on configure option --generated-files-in-srcdir +if GENINSRC +STAMP_GENINSRC = stamp-geninsrc +else +STAMP_GENINSRC = +endif + +# AM_CONDITIONAL on configure check ACX_CHECK_PROG_VER([MAKEINFO]) +if BUILD_INFO +STAMP_BUILD_INFO = stamp-build-info +else +STAMP_BUILD_INFO = +endif + + +all-local: $(STAMP_GENINSRC) + +stamp-geninsrc: libitm.info + cp -p $(top_builddir)/libitm.info $(srcdir)/libitm.info + @touch $@ + +libitm.info: $(STAMP_BUILD_INFO) + +stamp-build-info: libitm.texi + $(MAKEINFO) $(AM_MAKEINFOFLAGS) $(MAKEINFOFLAGS) -I $(srcdir) -o libitm.info $(srcdir)/libitm.texi + @touch $@ + + +CLEANFILES = $(STAMP_GENINSRC) $(STAMP_BUILD_INFO) libitm.info +MAINTAINERCLEANFILES = $(srcdir)/libitm.info diff --git a/libitm/Makefile.in b/libitm/Makefile.in new file mode 100644 index 00000000000..7dc864b3087 --- /dev/null +++ b/libitm/Makefile.in @@ -0,0 +1,1283 @@ +# Makefile.in generated by automake 1.11.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, +# Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +@ARCH_X86_TRUE@am__append_1 = x86_sse.cc x86_avx.cc +@ARCH_FUTEX_TRUE@am__append_2 = futex.cc +subdir = . +DIST_COMMON = $(am__configure_deps) $(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)/config.h.in $(srcdir)/libitm.spec.in \ + $(top_srcdir)/configure ChangeLog +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/../config/acx.m4 \ + $(top_srcdir)/../config/depstand.m4 \ + $(top_srcdir)/../config/enable.m4 \ + $(top_srcdir)/../config/futex.m4 \ + $(top_srcdir)/../config/lead-dot.m4 \ + $(top_srcdir)/../config/mmap.m4 \ + $(top_srcdir)/../config/multi.m4 \ + $(top_srcdir)/../config/override.m4 \ + $(top_srcdir)/../config/stdint.m4 \ + $(top_srcdir)/../config/tls.m4 $(top_srcdir)/../ltoptions.m4 \ + $(top_srcdir)/../ltsugar.m4 $(top_srcdir)/../ltversion.m4 \ + $(top_srcdir)/../lt~obsolete.m4 $(top_srcdir)/acinclude.m4 \ + $(top_srcdir)/../libtool.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ + configure.lineno config.status.lineno +mkinstalldirs = $(SHELL) $(top_srcdir)/../mkinstalldirs +CONFIG_HEADER = config.h +CONFIG_CLEAN_FILES = libitm.spec +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__installdirs = "$(DESTDIR)$(toolexeclibdir)" "$(DESTDIR)$(infodir)" \ + "$(DESTDIR)$(toolexeclibdir)" +LTLIBRARIES = $(toolexeclib_LTLIBRARIES) +libitm_la_LIBADD = +am__libitm_la_SOURCES_DIST = aatree.cc alloc.cc alloc_c.cc \ + alloc_cpp.cc barrier.cc beginend.cc clone.cc cacheline.cc \ + cachepage.cc eh_cpp.cc local.cc query.cc retry.cc rwlock.cc \ + useraction.cc util.cc sjlj.S tls.cc method-serial.cc \ + method-gl.cc x86_sse.cc x86_avx.cc futex.cc +@ARCH_X86_TRUE@am__objects_1 = x86_sse.lo x86_avx.lo +@ARCH_FUTEX_TRUE@am__objects_2 = futex.lo +am_libitm_la_OBJECTS = aatree.lo alloc.lo alloc_c.lo alloc_cpp.lo \ + barrier.lo beginend.lo clone.lo cacheline.lo cachepage.lo \ + eh_cpp.lo local.lo query.lo retry.lo rwlock.lo useraction.lo \ + util.lo sjlj.lo tls.lo method-serial.lo method-gl.lo \ + $(am__objects_1) $(am__objects_2) +libitm_la_OBJECTS = $(am_libitm_la_OBJECTS) +DEFAULT_INCLUDES = -I.@am__isrc@ +depcomp = $(SHELL) $(top_srcdir)/../depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +CPPASCOMPILE = $(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CCASFLAGS) $(CCASFLAGS) +LTCPPASCOMPILE = $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CCASFLAGS) $(CCASFLAGS) +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +LTCXXCOMPILE = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +CXXLD = $(CXX) +CXXLINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +SOURCES = $(libitm_la_SOURCES) +DIST_SOURCES = $(am__libitm_la_SOURCES_DIST) +MULTISRCTOP = +MULTIBUILDTOP = +MULTIDIRS = +MULTISUBDIR = +MULTIDO = true +MULTICLEAN = true +INFO_DEPS = libitm.info +am__TEXINFO_TEX_DIR = $(srcdir)/../gcc/doc/include +DVIS = libitm.dvi +PDFS = libitm.pdf +PSS = libitm.ps +HTMLS = libitm.html +TEXINFOS = libitm.texi +TEXI2DVI = texi2dvi +TEXI2PDF = $(TEXI2DVI) --pdf --batch +MAKEINFOHTML = $(MAKEINFO) --html +AM_MAKEINFOHTMLFLAGS = $(AM_MAKEINFOFLAGS) +DVIPS = dvips +RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ + html-recursive info-recursive install-data-recursive \ + install-dvi-recursive install-exec-recursive \ + install-html-recursive install-info-recursive \ + install-pdf-recursive install-ps-recursive install-recursive \ + installcheck-recursive installdirs-recursive pdf-recursive \ + ps-recursive uninstall-recursive +HEADERS = $(nodist_toolexeclib_HEADERS) +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 +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@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCAS = @CCAS@ +CCASDEPMODE = @CCASDEPMODE@ +CCASFLAGS = @CCASFLAGS@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FC = @FC@ +FCFLAGS = @FCFLAGS@ +FGREP = @FGREP@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OPT_LDFLAGS = @OPT_LDFLAGS@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +RANLIB = @RANLIB@ +SECTION_LDFLAGS = @SECTION_LDFLAGS@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +XCFLAGS = @XCFLAGS@ +XLDFLAGS = @XLDFLAGS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +ac_ct_FC = @ac_ct_FC@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +config_path = @config_path@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +enable_shared = @enable_shared@ +enable_static = @enable_static@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +libtool_VERSION = @libtool_VERSION@ +link_itm = @link_itm@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +multi_basedir = @multi_basedir@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +toolexecdir = @toolexecdir@ +toolexeclibdir = @toolexeclibdir@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +ACLOCAL_AMFLAGS = -I .. -I ../config +SUBDIRS = testsuite +gcc_version := $(shell cat $(top_srcdir)/../gcc/BASE-VER) +abi_version = -fabi-version=4 +search_path = $(addprefix $(top_srcdir)/config/, $(config_path)) $(top_srcdir) +fincludedir = $(libdir)/gcc/$(target_alias)/$(gcc_version)/finclude +libsubincludedir = $(libdir)/gcc/$(target_alias)/$(gcc_version)/include +AM_CPPFLAGS = $(addprefix -I, $(search_path)) +AM_CFLAGS = $(XCFLAGS) +AM_CXXFLAGS = -std=gnu++0x -funwind-tables -fno-exceptions -fno-rtti \ + $(XCFLAGS) $(abi_version) + +AM_CCASFLAGS = $(XCFLAGS) +AM_LDFLAGS = $(XLDFLAGS) $(SECTION_LDFLAGS) $(OPT_LDFLAGS) +toolexeclib_LTLIBRARIES = libitm.la +nodist_toolexeclib_HEADERS = libitm.spec +@LIBITM_BUILD_VERSIONED_SHLIB_FALSE@libitm_version_script = +@LIBITM_BUILD_VERSIONED_SHLIB_TRUE@libitm_version_script = -Wl,--version-script,$(top_srcdir)/libitm.map +libitm_version_info = -version-info $(libtool_VERSION) + +# Force link with C, not C++. For now, while we're using C++ we don't +# want or need libstdc++. +libitm_la_LINK = $(LINK) +libitm_la_LDFLAGS = $(libitm_version_info) $(libitm_version_script) \ + -no-undefined + +libitm_la_SOURCES = aatree.cc alloc.cc alloc_c.cc alloc_cpp.cc \ + barrier.cc beginend.cc clone.cc cacheline.cc cachepage.cc \ + eh_cpp.cc local.cc query.cc retry.cc rwlock.cc useraction.cc \ + util.cc sjlj.S tls.cc method-serial.cc method-gl.cc \ + $(am__append_1) $(am__append_2) + +# Automake Documentation: +# If your package has Texinfo files in many directories, you can use the +# variable TEXINFO_TEX to tell Automake where to find the canonical +# `texinfo.tex' for your package. The value of this variable should be +# the relative path from the current `Makefile.am' to `texinfo.tex'. +TEXINFO_TEX = ../gcc/doc/include/texinfo.tex + +# Defines info, dvi, pdf and html targets +MAKEINFOFLAGS = -I $(srcdir)/../gcc/doc/include +info_TEXINFOS = libitm.texi +@GENINSRC_FALSE@STAMP_GENINSRC = + +# AM_CONDITIONAL on configure option --generated-files-in-srcdir +@GENINSRC_TRUE@STAMP_GENINSRC = stamp-geninsrc +@BUILD_INFO_FALSE@STAMP_BUILD_INFO = + +# AM_CONDITIONAL on configure check ACX_CHECK_PROG_VER([MAKEINFO]) +@BUILD_INFO_TRUE@STAMP_BUILD_INFO = stamp-build-info +CLEANFILES = $(STAMP_GENINSRC) $(STAMP_BUILD_INFO) libitm.info +MAINTAINERCLEANFILES = $(srcdir)/libitm.info +all: config.h + $(MAKE) $(AM_MAKEFLAGS) all-recursive + +.SUFFIXES: +.SUFFIXES: .S .cc .dvi .lo .o .obj .ps +am--refresh: + @: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + echo ' cd $(srcdir) && $(AUTOMAKE) --foreign'; \ + $(am__cd) $(srcdir) && $(AUTOMAKE) --foreign \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + echo ' $(SHELL) ./config.status'; \ + $(SHELL) ./config.status;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + $(SHELL) ./config.status --recheck + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + $(am__cd) $(srcdir) && $(AUTOCONF) +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) +$(am__aclocal_m4_deps): + +config.h: stamp-h1 + @if test ! -f $@; then \ + rm -f stamp-h1; \ + $(MAKE) $(AM_MAKEFLAGS) stamp-h1; \ + else :; fi + +stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status + @rm -f stamp-h1 + cd $(top_builddir) && $(SHELL) ./config.status config.h +$(srcdir)/config.h.in: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + ($(am__cd) $(top_srcdir) && $(AUTOHEADER)) + rm -f stamp-h1 + touch $@ + +distclean-hdr: + -rm -f config.h stamp-h1 +libitm.spec: $(top_builddir)/config.status $(srcdir)/libitm.spec.in + cd $(top_builddir) && $(SHELL) ./config.status $@ +install-toolexeclibLTLIBRARIES: $(toolexeclib_LTLIBRARIES) + @$(NORMAL_INSTALL) + test -z "$(toolexeclibdir)" || $(MKDIR_P) "$(DESTDIR)$(toolexeclibdir)" + @list='$(toolexeclib_LTLIBRARIES)'; test -n "$(toolexeclibdir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(toolexeclibdir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(toolexeclibdir)"; \ + } + +uninstall-toolexeclibLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(toolexeclib_LTLIBRARIES)'; test -n "$(toolexeclibdir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(toolexeclibdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(toolexeclibdir)/$$f"; \ + done + +clean-toolexeclibLTLIBRARIES: + -test -z "$(toolexeclib_LTLIBRARIES)" || rm -f $(toolexeclib_LTLIBRARIES) + @list='$(toolexeclib_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +libitm.la: $(libitm_la_OBJECTS) $(libitm_la_DEPENDENCIES) + $(libitm_la_LINK) -rpath $(toolexeclibdir) $(libitm_la_OBJECTS) $(libitm_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/aatree.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/alloc.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/alloc_c.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/alloc_cpp.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/barrier.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/beginend.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cacheline.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cachepage.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clone.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eh_cpp.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/futex.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/local.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/method-gl.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/method-serial.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/query.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/retry.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rwlock.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sjlj.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tls.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/useraction.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/util.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/x86_avx.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/x86_sse.Plo@am__quote@ + +.S.o: +@am__fastdepCCAS_TRUE@ $(CPPASCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCCAS_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ DEPDIR=$(DEPDIR) $(CCASDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCCAS_FALSE@ $(CPPASCOMPILE) -c -o $@ $< + +.S.obj: +@am__fastdepCCAS_TRUE@ $(CPPASCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCCAS_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ DEPDIR=$(DEPDIR) $(CCASDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCCAS_FALSE@ $(CPPASCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.S.lo: +@am__fastdepCCAS_TRUE@ $(LTCPPASCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCCAS_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ DEPDIR=$(DEPDIR) $(CCASDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCCAS_FALSE@ $(LTCPPASCOMPILE) -c -o $@ $< + +.cc.o: +@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $< + +.cc.obj: +@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.cc.lo: +@am__fastdepCXX_TRUE@ $(LTCXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LTCXXCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +distclean-libtool: + -rm -f libtool config.lt + +# GNU Make needs to see an explicit $(MAKE) variable in the command it +# runs to enable its job server during parallel builds. Hence the +# comments below. +all-multi: + $(MULTIDO) $(AM_MAKEFLAGS) DO=all multi-do # $(MAKE) +install-multi: + $(MULTIDO) $(AM_MAKEFLAGS) DO=install multi-do # $(MAKE) + +mostlyclean-multi: + $(MULTICLEAN) $(AM_MAKEFLAGS) DO=mostlyclean multi-clean # $(MAKE) +clean-multi: + $(MULTICLEAN) $(AM_MAKEFLAGS) DO=clean multi-clean # $(MAKE) +distclean-multi: + $(MULTICLEAN) $(AM_MAKEFLAGS) DO=distclean multi-clean # $(MAKE) +maintainer-clean-multi: + $(MULTICLEAN) $(AM_MAKEFLAGS) DO=maintainer-clean multi-clean # $(MAKE) + +libitm.dvi: libitm.texi + TEXINPUTS="$(am__TEXINFO_TEX_DIR)$(PATH_SEPARATOR)$$TEXINPUTS" \ + MAKEINFO='$(MAKEINFO) $(AM_MAKEINFOFLAGS) $(MAKEINFOFLAGS) -I $(srcdir)' \ + $(TEXI2DVI) -o $@ `test -f 'libitm.texi' || echo '$(srcdir)/'`libitm.texi + +libitm.pdf: libitm.texi + TEXINPUTS="$(am__TEXINFO_TEX_DIR)$(PATH_SEPARATOR)$$TEXINPUTS" \ + MAKEINFO='$(MAKEINFO) $(AM_MAKEINFOFLAGS) $(MAKEINFOFLAGS) -I $(srcdir)' \ + $(TEXI2PDF) -o $@ `test -f 'libitm.texi' || echo '$(srcdir)/'`libitm.texi + +libitm.html: libitm.texi + rm -rf $(@:.html=.htp) + if $(MAKEINFOHTML) $(AM_MAKEINFOHTMLFLAGS) $(MAKEINFOFLAGS) -I $(srcdir) \ + -o $(@:.html=.htp) `test -f 'libitm.texi' || echo '$(srcdir)/'`libitm.texi; \ + then \ + rm -rf $@; \ + if test ! -d $(@:.html=.htp) && test -d $(@:.html=); then \ + mv $(@:.html=) $@; else mv $(@:.html=.htp) $@; fi; \ + else \ + if test ! -d $(@:.html=.htp) && test -d $(@:.html=); then \ + rm -rf $(@:.html=); else rm -Rf $(@:.html=.htp) $@; fi; \ + exit 1; \ + fi +.dvi.ps: + TEXINPUTS="$(am__TEXINFO_TEX_DIR)$(PATH_SEPARATOR)$$TEXINPUTS" \ + $(DVIPS) -o $@ $< + +uninstall-dvi-am: + @$(NORMAL_UNINSTALL) + @list='$(DVIS)'; test -n "$(dvidir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " rm -f '$(DESTDIR)$(dvidir)/$$f'"; \ + rm -f "$(DESTDIR)$(dvidir)/$$f"; \ + done + +uninstall-html-am: + @$(NORMAL_UNINSTALL) + @list='$(HTMLS)'; test -n "$(htmldir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " rm -rf '$(DESTDIR)$(htmldir)/$$f'"; \ + rm -rf "$(DESTDIR)$(htmldir)/$$f"; \ + done + +uninstall-info-am: + @$(PRE_UNINSTALL) + @if test -d '$(DESTDIR)$(infodir)' && \ + (install-info --version && \ + install-info --version 2>&1 | sed 1q | grep -i -v debian) >/dev/null 2>&1; then \ + list='$(INFO_DEPS)'; \ + for file in $$list; do \ + relfile=`echo "$$file" | sed 's|^.*/||'`; \ + echo " install-info --info-dir='$(DESTDIR)$(infodir)' --remove '$(DESTDIR)$(infodir)/$$relfile'"; \ + if install-info --info-dir="$(DESTDIR)$(infodir)" --remove "$(DESTDIR)$(infodir)/$$relfile"; \ + then :; else test ! -f "$(DESTDIR)$(infodir)/$$relfile" || exit 1; fi; \ + done; \ + else :; fi + @$(NORMAL_UNINSTALL) + @list='$(INFO_DEPS)'; \ + for file in $$list; do \ + relfile=`echo "$$file" | sed 's|^.*/||'`; \ + relfile_i=`echo "$$relfile" | sed 's|\.info$$||;s|$$|.i|'`; \ + (if test -d "$(DESTDIR)$(infodir)" && cd "$(DESTDIR)$(infodir)"; then \ + echo " cd '$(DESTDIR)$(infodir)' && rm -f $$relfile $$relfile-[0-9] $$relfile-[0-9][0-9] $$relfile_i[0-9] $$relfile_i[0-9][0-9]"; \ + rm -f $$relfile $$relfile-[0-9] $$relfile-[0-9][0-9] $$relfile_i[0-9] $$relfile_i[0-9][0-9]; \ + else :; fi); \ + done + +uninstall-pdf-am: + @$(NORMAL_UNINSTALL) + @list='$(PDFS)'; test -n "$(pdfdir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " rm -f '$(DESTDIR)$(pdfdir)/$$f'"; \ + rm -f "$(DESTDIR)$(pdfdir)/$$f"; \ + done + +uninstall-ps-am: + @$(NORMAL_UNINSTALL) + @list='$(PSS)'; test -n "$(psdir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " rm -f '$(DESTDIR)$(psdir)/$$f'"; \ + rm -f "$(DESTDIR)$(psdir)/$$f"; \ + done + +dist-info: $(INFO_DEPS) + @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ + list='$(INFO_DEPS)'; \ + for base in $$list; do \ + case $$base in \ + $(srcdir)/*) base=`echo "$$base" | sed "s|^$$srcdirstrip/||"`;; \ + esac; \ + if test -f $$base; then d=.; else d=$(srcdir); fi; \ + base_i=`echo "$$base" | sed 's|\.info$$||;s|$$|.i|'`; \ + for file in $$d/$$base $$d/$$base-[0-9] $$d/$$base-[0-9][0-9] $$d/$$base_i[0-9] $$d/$$base_i[0-9][0-9]; do \ + if test -f $$file; then \ + relfile=`expr "$$file" : "$$d/\(.*\)"`; \ + test -f "$(distdir)/$$relfile" || \ + cp -p $$file "$(distdir)/$$relfile"; \ + else :; fi; \ + done; \ + done + +mostlyclean-aminfo: + -rm -rf libitm.aux libitm.cp libitm.cps libitm.fn libitm.fns libitm.ky \ + libitm.kys libitm.log libitm.pg libitm.pgs libitm.tmp \ + libitm.toc libitm.tp libitm.tps libitm.vr libitm.vrs + +clean-aminfo: + -test -z "libitm.dvi libitm.pdf libitm.ps libitm.html" \ + || rm -rf libitm.dvi libitm.pdf libitm.ps libitm.html + +maintainer-clean-aminfo: + @list='$(INFO_DEPS)'; for i in $$list; do \ + i_i=`echo "$$i" | sed 's|\.info$$||;s|$$|.i|'`; \ + echo " rm -f $$i $$i-[0-9] $$i-[0-9][0-9] $$i_i[0-9] $$i_i[0-9][0-9]"; \ + rm -f $$i $$i-[0-9] $$i-[0-9][0-9] $$i_i[0-9] $$i_i[0-9][0-9]; \ + done +install-nodist_toolexeclibHEADERS: $(nodist_toolexeclib_HEADERS) + @$(NORMAL_INSTALL) + test -z "$(toolexeclibdir)" || $(MKDIR_P) "$(DESTDIR)$(toolexeclibdir)" + @list='$(nodist_toolexeclib_HEADERS)'; test -n "$(toolexeclibdir)" || list=; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(toolexeclibdir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(toolexeclibdir)" || exit $$?; \ + done + +uninstall-nodist_toolexeclibHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(nodist_toolexeclib_HEADERS)'; test -n "$(toolexeclibdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + test -n "$$files" || exit 0; \ + echo " ( cd '$(DESTDIR)$(toolexeclibdir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(toolexeclibdir)" && rm -f $$files + +# This directory's subdirectories are mostly independent; you can cd +# into them and run `make' without going through this Makefile. +# To change the values of `make' variables: instead of editing Makefiles, +# (1) if the variable is set in `config.status', edit `config.status' +# (which will cause the Makefiles to be regenerated when you run `make'); +# (2) otherwise, pass the desired values on the `make' command line. +$(RECURSIVE_TARGETS): + @fail= failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +$(RECURSIVE_CLEAN_TARGETS): + @fail= failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + rev=''; for subdir in $$list; do \ + if test "$$subdir" = "."; then :; else \ + rev="$$subdir $$rev"; \ + fi; \ + done; \ + rev="$$rev ."; \ + target=`echo $@ | sed s/-recursive//`; \ + for subdir in $$rev; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done && test -z "$$fail" +tags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ + done +ctags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ + done + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: tags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: ctags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +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 $(HEADERS) \ + config.h all-local +installdirs: installdirs-recursive +installdirs-am: + for dir in "$(DESTDIR)$(toolexeclibdir)" "$(DESTDIR)$(infodir)" "$(DESTDIR)$(toolexeclibdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." + -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) +clean: clean-multi clean-recursive + +clean-am: clean-aminfo clean-generic clean-libtool \ + clean-toolexeclibLTLIBRARIES mostlyclean-am + +distclean: distclean-multi distclean-recursive + -rm -f $(am__CONFIG_DISTCLEAN_FILES) + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-hdr distclean-libtool distclean-tags + +dvi: dvi-recursive + +dvi-am: $(DVIS) + +html: html-recursive + +html-am: $(HTMLS) + +info: info-recursive + +info-am: $(INFO_DEPS) + +install-data-am: install-info-am + +install-dvi: install-dvi-recursive + +install-dvi-am: $(DVIS) + @$(NORMAL_INSTALL) + test -z "$(dvidir)" || $(MKDIR_P) "$(DESTDIR)$(dvidir)" + @list='$(DVIS)'; test -n "$(dvidir)" || list=; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(dvidir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(dvidir)" || exit $$?; \ + done +install-exec-am: install-multi install-nodist_toolexeclibHEADERS \ + install-toolexeclibLTLIBRARIES + +install-html: install-html-recursive + +install-html-am: $(HTMLS) + @$(NORMAL_INSTALL) + test -z "$(htmldir)" || $(MKDIR_P) "$(DESTDIR)$(htmldir)" + @list='$(HTMLS)'; list2=; test -n "$(htmldir)" || list=; \ + for p in $$list; do \ + if test -f "$$p" || test -d "$$p"; then d=; else d="$(srcdir)/"; fi; \ + $(am__strip_dir) \ + if test -d "$$d$$p"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(htmldir)/$$f'"; \ + $(MKDIR_P) "$(DESTDIR)$(htmldir)/$$f" || exit 1; \ + echo " $(INSTALL_DATA) '$$d$$p'/* '$(DESTDIR)$(htmldir)/$$f'"; \ + $(INSTALL_DATA) "$$d$$p"/* "$(DESTDIR)$(htmldir)/$$f" || exit $$?; \ + else \ + list2="$$list2 $$d$$p"; \ + fi; \ + done; \ + test -z "$$list2" || { echo "$$list2" | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(htmldir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(htmldir)" || exit $$?; \ + done; } +install-info: install-info-recursive + +install-info-am: $(INFO_DEPS) + @$(NORMAL_INSTALL) + test -z "$(infodir)" || $(MKDIR_P) "$(DESTDIR)$(infodir)" + @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ + list='$(INFO_DEPS)'; test -n "$(infodir)" || list=; \ + for file in $$list; do \ + case $$file in \ + $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ + esac; \ + if test -f $$file; then d=.; else d=$(srcdir); fi; \ + file_i=`echo "$$file" | sed 's|\.info$$||;s|$$|.i|'`; \ + for ifile in $$d/$$file $$d/$$file-[0-9] $$d/$$file-[0-9][0-9] \ + $$d/$$file_i[0-9] $$d/$$file_i[0-9][0-9] ; do \ + if test -f $$ifile; then \ + echo "$$ifile"; \ + else : ; fi; \ + done; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(infodir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(infodir)" || exit $$?; done + @$(POST_INSTALL) + @if (install-info --version && \ + install-info --version 2>&1 | sed 1q | grep -i -v debian) >/dev/null 2>&1; then \ + list='$(INFO_DEPS)'; test -n "$(infodir)" || list=; \ + for file in $$list; do \ + relfile=`echo "$$file" | sed 's|^.*/||'`; \ + echo " install-info --info-dir='$(DESTDIR)$(infodir)' '$(DESTDIR)$(infodir)/$$relfile'";\ + install-info --info-dir="$(DESTDIR)$(infodir)" "$(DESTDIR)$(infodir)/$$relfile" || :;\ + done; \ + else : ; fi +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: $(PDFS) + @$(NORMAL_INSTALL) + test -z "$(pdfdir)" || $(MKDIR_P) "$(DESTDIR)$(pdfdir)" + @list='$(PDFS)'; test -n "$(pdfdir)" || list=; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pdfdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(pdfdir)" || exit $$?; done +install-ps: install-ps-recursive + +install-ps-am: $(PSS) + @$(NORMAL_INSTALL) + test -z "$(psdir)" || $(MKDIR_P) "$(DESTDIR)$(psdir)" + @list='$(PSS)'; test -n "$(psdir)" || list=; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(psdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(psdir)" || exit $$?; done +installcheck-am: + +maintainer-clean: maintainer-clean-multi maintainer-clean-recursive + -rm -f $(am__CONFIG_DISTCLEAN_FILES) + -rm -rf $(top_srcdir)/autom4te.cache + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-aminfo \ + maintainer-clean-generic + +mostlyclean: mostlyclean-multi mostlyclean-recursive + +mostlyclean-am: mostlyclean-aminfo mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: $(PDFS) + +ps: ps-recursive + +ps-am: $(PSS) + +uninstall-am: uninstall-dvi-am uninstall-html-am uninstall-info-am \ + uninstall-nodist_toolexeclibHEADERS uninstall-pdf-am \ + uninstall-ps-am uninstall-toolexeclibLTLIBRARIES + +.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) all all-multi \ + clean-multi ctags-recursive distclean-multi install-am \ + install-multi install-strip maintainer-clean-multi \ + mostlyclean-multi tags-recursive + +.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \ + all all-am all-local all-multi am--refresh check check-am \ + clean clean-aminfo clean-generic clean-libtool clean-multi \ + 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-nodist_toolexeclibHEADERS 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 \ + maintainer-clean-multi mostlyclean mostlyclean-aminfo \ + mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ + mostlyclean-multi pdf pdf-am ps ps-am tags tags-recursive \ + uninstall uninstall-am uninstall-dvi-am uninstall-html-am \ + uninstall-info-am uninstall-nodist_toolexeclibHEADERS \ + uninstall-pdf-am uninstall-ps-am \ + uninstall-toolexeclibLTLIBRARIES + + +vpath % $(strip $(search_path)) +@ARCH_X86_TRUE@x86_sse.lo : XCFLAGS += -msse +@ARCH_X86_TRUE@x86_avx.lo : XCFLAGS += -mavx + +all-local: $(STAMP_GENINSRC) + +stamp-geninsrc: libitm.info + cp -p $(top_builddir)/libitm.info $(srcdir)/libitm.info + @touch $@ + +libitm.info: $(STAMP_BUILD_INFO) + +stamp-build-info: libitm.texi + $(MAKEINFO) $(AM_MAKEINFOFLAGS) $(MAKEINFOFLAGS) -I $(srcdir) -o libitm.info $(srcdir)/libitm.texi + @touch $@ + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/libitm/aatree.cc b/libitm/aatree.cc new file mode 100644 index 00000000000..da8c27407f4 --- /dev/null +++ b/libitm/aatree.cc @@ -0,0 +1,222 @@ +/* Copyright (C) 2009, 2011 Free Software Foundation, Inc. + Contributed by Richard Henderson <rth@redhat.com>. + + This file is part of the GNU Transactional Memory Library (libitm). + + Libitm is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + Libitm is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + <http://www.gnu.org/licenses/>. */ + +// Implements an AA tree (http://en.wikipedia.org/wiki/AA_tree) with an +// integer key, and data attached to the node via flexible array member. + +#include "libitm_i.h" + +namespace GTM HIDDEN { + +// The code for rebalancing the tree is greatly simplified by never +// having to check for null pointers. Instead, leaf node links point +// to this node, NIL, which points to itself. +const aa_node_base aa_node_base::s_nil(0); + + +// Remove left horizontal links. Swap the pointers of horizontal left links. + +aa_node_base * +aa_node_base::skew () +{ + aa_node_base *l = this->link(L); + if (this->m_level != 0 && l->m_level == this->m_level) + { + this->set_link(L, l->link(R)); + l->set_link(R, this); + return l; + } + return this; +} + + +// Remove consecutive horizontal links. Take the middle node, +// elevate it, and return it. + +aa_node_base * +aa_node_base::split () +{ + aa_node_base *r = this->link(R); + if (this->m_level != 0 && r->link(R)->m_level == this->m_level) + { + this->set_link(R, r->link(L)); + r->set_link(L, this); + r->m_level += 1; + return r; + } + return this; +} + +// Decrease the level of THIS to be one more than the level of its children. + +void +aa_node_base::decrease_level () +{ + aa_node_base *l = this->link(L); + aa_node_base *r = this->link(R); + level_type llev = l->m_level; + level_type rlev = r->m_level; + level_type should_be = (llev < rlev ? llev : rlev) + 1; + + if (should_be < this->m_level) + { + this->m_level = should_be; + if (should_be < rlev) + r->m_level = should_be; + } +} + +// Find and return the node in the tree with key K. + +template<typename KEY> +typename aa_tree_key<KEY>::node_ptr +aa_tree_key<KEY>::find(KEY k) const +{ + node_ptr t = m_tree; + if (t != 0) + do + { + if (t->key == k) + return t; + t = t->link(k > t->key); + } + while (!t->is_nil()); + return 0; +} + +// Insert N into T and rebalance. Return the new balanced tree. + +template<typename KEY> +typename aa_tree_key<KEY>::node_ptr +aa_tree_key<KEY>::insert_1 (node_ptr t, node_ptr n) +{ + bool dir = n->key > t->key; + node_ptr c = t->link(dir); + + // Insert the node, recursively. + if (c->is_nil()) + c = n; + else + c = insert_1 (c, n); + t->set_link(dir, c); + + // Rebalance the tree, as needed. + t = t->skew(); + t = t->split(); + + return t; +} + +template<typename KEY> +void +aa_tree_key<KEY>::insert(node_ptr n) +{ + if (m_tree == 0) + m_tree = n; + else + m_tree = insert_1 (m_tree, n); +} + +// Delete K from T and rebalance. Return the new balanced tree. + +template<typename KEY> +typename aa_tree_key<KEY>::node_ptr +aa_tree_key<KEY>::erase_1 (node_ptr t, KEY k, node_ptr *pfree) +{ + node_ptr r; + bool dir; + + // If this is the node we're looking for, delete it. Else recurse. + if (k == t->key) + { + node_ptr l, sub, end; + + l = t->link(node::L); + r = t->link(node::R); + + if (pfree) + *pfree = t; + + // If this is a leaf node, simply remove the node. Otherwise, + // we have to find either a predecessor or a successor node to + // replace this one. + if (l->is_nil()) + { + if (r->is_nil()) + return r; + sub = r, dir = node::L; + } + else + sub = l, dir = node::R; + + // Find the successor or predecessor. + for (end = sub; !end->link(dir)->is_nil(); end = end->link(dir)) + continue; + + // Remove it (but don't free) from the subtree. + sub = erase_1 (sub, end->key, 0); + + // Replace T with the successor we just extracted. + end->set_link(!dir, sub); + t = end; + } + else + { + dir = k > t->key; + t->set_link(dir, erase_1 (t->link(dir), k, pfree)); + } + + // Rebalance the tree. + t->decrease_level(); + t = t->skew(); + r = t->link(node::R)->skew(); + t->set_link(node::R, r); + r->set_link(node::R, r->link(node::R)->skew()); + t = t->split (); + t->set_link(node::R, t->link(node::R)->split()); + + return t; +} + +template<typename KEY> +typename aa_tree_key<KEY>::node_ptr +aa_tree_key<KEY>::erase (KEY k) +{ + node_ptr t = m_tree; + if (t == 0) + return 0; + + node_ptr do_free = 0; + t = erase_1 (t, k, &do_free); + if (t->is_nil()) + t = 0; + m_tree = t; + return do_free; +} + +// Instantiate key classes. + +template class aa_tree_key<uintptr_t>; + +} // namespace GTM diff --git a/libitm/aatree.h b/libitm/aatree.h new file mode 100644 index 00000000000..a4de8da903d --- /dev/null +++ b/libitm/aatree.h @@ -0,0 +1,215 @@ +/* Copyright (C) 2009, 2011 Free Software Foundation, Inc. + Contributed by Richard Henderson <rth@redhat.com>. + + This file is part of the GNU Transactional Memory Library (libitm). + + Libitm is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + Libitm is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + <http://www.gnu.org/licenses/>. */ + +/* Implements an AA tree (http://en.wikipedia.org/wiki/AA_tree) with an + integer key, and data attached to the node via flexible array member. */ + +#ifndef LIBITM_AATREE_H +#define LIBITM_AATREE_H 1 + +namespace GTM HIDDEN { + +template<typename KEY> class aa_tree_key; + +class aa_node_base +{ + public: + static const bool L = false; + static const bool R = true; + + private: + typedef unsigned int level_type; + + aa_node_base *m_link[2]; + level_type m_level; + + static const aa_node_base s_nil; + + public: + aa_node_base(level_type l = 1) + : m_link { const_cast<aa_node_base *>(&s_nil), + const_cast<aa_node_base *>(&s_nil) }, + m_level(l) + { } + + bool is_nil() const { return this == &s_nil; } + + aa_node_base * link(bool d) { return m_link[d]; } + void set_link(bool d, aa_node_base *val) { m_link[d] = val; } + + aa_node_base *skew(); + aa_node_base *split(); + void decrease_level(); + + static void *operator new (size_t s) { return xmalloc (s); } + static void operator delete (void *p) { free (p); } +}; + +template<typename KEY> +struct aa_node_key : public aa_node_base +{ + typedef aa_node_base base; + + KEY key; + + explicit aa_node_key(KEY k) : key(k) { } + + aa_node_key * link(bool d) + { + return static_cast<aa_node_key *>(base::link(d)); + } + + aa_node_key *skew() { return static_cast<aa_node_key *>(base::skew()); } + aa_node_key *split() { return static_cast<aa_node_key *>(base::split()); } +}; + +template<typename KEY, typename DATA> +struct aa_node : public aa_node_key<KEY> +{ + typedef aa_node_key<KEY> base; + + DATA data; + + explicit aa_node(KEY k) : base(k) { } + + aa_node * link(bool d) + { + return static_cast<aa_node *>(base::link(d)); + } +}; + +template<typename KEY> +class aa_tree_key +{ + public: + typedef aa_node_key<KEY> node; + typedef node *node_ptr; + + protected: + node_ptr m_tree; + + protected: + aa_tree_key() : m_tree(0) { } + + node_ptr find(KEY k) const; + + static node_ptr insert_1 (node_ptr t, node_ptr n); + void insert(node_ptr n); + + static node_ptr erase_1 (node_ptr t, KEY k, node_ptr *pfree); + node_ptr erase(KEY k); +}; + +extern template class aa_tree_key<uintptr_t>; + +template<typename KEY, typename DATA> +class aa_tree : public aa_tree_key<KEY> +{ + public: + typedef aa_tree_key<KEY> base; + typedef aa_node<KEY, DATA> node; + typedef node *node_ptr; + + typedef void (*trav_callback)(KEY, DATA *, void *); + + private: + static void clear_1 (node_ptr); + static void traverse_1 (node_ptr, trav_callback, void *); + + public: + aa_tree() = default; + ~aa_tree() { clear(); } + + static void *operator new (size_t s, aa_tree<KEY, DATA>* p) { return p; } + + DATA *find(KEY k) const + { + node_ptr n = static_cast<node_ptr>(base::find (k)); + return n ? &n->data : 0; + } + + DATA *insert(KEY k) + { + node_ptr n = new node(k); + base::insert(n); + return &n->data; + } + + void erase(KEY k) + { + node_ptr n = static_cast<node_ptr>(base::erase (k)); + delete n; + } + + node_ptr remove(KEY k, DATA** data) + { + node_ptr n = static_cast<node_ptr>(base::erase (k)); + *data = (n ? &n->data : 0); + return n; + } + + void clear() + { + node_ptr n = static_cast<node_ptr>(this->m_tree); + if (n) + { + this->m_tree = 0; + clear_1 (n); + } + } + + void traverse (trav_callback cb, void *cb_data) + { + node_ptr t = static_cast<node_ptr>(this->m_tree); + if (t != 0) + traverse_1 (t, cb, cb_data); + } +}; + + +template<typename KEY, typename DATA> +void +aa_tree<KEY, DATA>::clear_1 (node_ptr t) +{ + if (t->is_nil()) + return; + clear_1 (t->link(node::L)); + clear_1 (t->link(node::R)); + delete t; +} + +template<typename KEY, typename DATA> +void +aa_tree<KEY, DATA>::traverse_1 (node_ptr t, trav_callback cb, void *cb_data) +{ + if (t->is_nil()) + return; + cb (t->key, &t->data, cb_data); + traverse_1 (t->link(node::L), cb, cb_data); + traverse_1 (t->link(node::R), cb, cb_data); +} + +} // namespace GTM + +#endif // LIBITM_AATREE_H diff --git a/libitm/acinclude.m4 b/libitm/acinclude.m4 new file mode 100644 index 00000000000..8fcde4b57ad --- /dev/null +++ b/libitm/acinclude.m4 @@ -0,0 +1,343 @@ +dnl ---------------------------------------------------------------------- +dnl This whole bit snagged from libgfortran. + +dnl Check whether the target supports __sync_*_compare_and_swap. +AC_DEFUN([LIBITM_CHECK_SYNC_BUILTINS], [ + AC_CACHE_CHECK([whether the target supports __sync_*_compare_and_swap], + libitm_cv_have_sync_builtins, [ + AC_TRY_LINK([], [int foo, bar; bar = __sync_val_compare_and_swap(&foo, 0, 1);], + libitm_cv_have_sync_builtins=yes, libitm_cv_have_sync_builtins=no)]) + if test $libitm_cv_have_sync_builtins = yes; then + AC_DEFINE(HAVE_SYNC_BUILTINS, 1, + [Define to 1 if the target supports __sync_*_compare_and_swap]) + fi]) + +dnl Check whether the target supports 64-bit __sync_*_compare_and_swap. +AC_DEFUN([LIBITM_CHECK_64BIT_SYNC_BUILTINS], [ + AC_CACHE_CHECK([whether the target supports 64-bit __sync_*_compare_and_swap], + libitm_cv_have_64bit_sync_builtins, [ + AC_TRY_LINK([#include <stdint.h>], + [uint64_t foo, bar; + bar = __sync_val_compare_and_swap(&foo, 0, 1);], + libitm_cv_have_64bit_sync_builtins=yes, + libitm_cv_have_64bit_sync_builtins=no)]) + if test $libitm_cv_have_64bit_sync_builtins = yes; then + AC_DEFINE(HAVE_64BIT_SYNC_BUILTINS, 1, + [Define to 1 if the target supports 64-bit __sync_*_compare_and_swap]) + fi]) + +dnl Check whether the target supports hidden visibility. +AC_DEFUN([LIBITM_CHECK_ATTRIBUTE_VISIBILITY], [ + AC_CACHE_CHECK([whether the target supports hidden visibility], + libitm_cv_have_attribute_visibility, [ + save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -Werror" + AC_TRY_COMPILE([void __attribute__((visibility("hidden"))) foo(void) { }], + [], libitm_cv_have_attribute_visibility=yes, + libitm_cv_have_attribute_visibility=no) + CFLAGS="$save_CFLAGS"]) + if test $libitm_cv_have_attribute_visibility = yes; then + AC_DEFINE(HAVE_ATTRIBUTE_VISIBILITY, 1, + [Define to 1 if the target supports __attribute__((visibility(...))).]) + fi]) + +dnl Check whether the target supports dllexport +AC_DEFUN([LIBITM_CHECK_ATTRIBUTE_DLLEXPORT], [ + AC_CACHE_CHECK([whether the target supports dllexport], + libitm_cv_have_attribute_dllexport, [ + save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -Werror" + AC_TRY_COMPILE([void __attribute__((dllexport)) foo(void) { }], + [], libitm_cv_have_attribute_dllexport=yes, + libitm_cv_have_attribute_dllexport=no) + CFLAGS="$save_CFLAGS"]) + if test $libitm_cv_have_attribute_dllexport = yes; then + AC_DEFINE(HAVE_ATTRIBUTE_DLLEXPORT, 1, + [Define to 1 if the target supports __attribute__((dllexport)).]) + fi]) + +dnl Check whether the target supports symbol aliases. +AC_DEFUN([LIBITM_CHECK_ATTRIBUTE_ALIAS], [ + AC_CACHE_CHECK([whether the target supports symbol aliases], + libitm_cv_have_attribute_alias, [ + AC_TRY_LINK([ +void foo(void) { } +extern void bar(void) __attribute__((alias("foo")));], + [bar();], libitm_cv_have_attribute_alias=yes, libitm_cv_have_attribute_alias=no)]) + if test $libitm_cv_have_attribute_alias = yes; then + AC_DEFINE(HAVE_ATTRIBUTE_ALIAS, 1, + [Define to 1 if the target supports __attribute__((alias(...))).]) + fi]) + +dnl Check how size_t is mangled. +AC_DEFUN([LIBITM_CHECK_SIZE_T_MANGLING], [ + AC_CACHE_CHECK([how size_t is mangled], + libitm_cv_size_t_mangling, [ + AC_TRY_COMPILE([], [extern __SIZE_TYPE__ x; extern unsigned long x;], + [libitm_cv_size_t_mangling=m], [ + AC_TRY_COMPILE([], [extern __SIZE_TYPE__ x; extern unsigned int x;], + [libitm_cv_size_t_mangling=j], [ + AC_TRY_COMPILE([], + [extern __SIZE_TYPE__ x; extern unsigned long long x;], + [libitm_cv_size_t_mangling=y], [ + AC_TRY_COMPILE([], + [extern __SIZE_TYPE__ x; extern unsigned short x;], + [libitm_cv_size_t_mangling=t], + [libitm_cv_size_t_mangling=x]) + ]) + ]) + ]) + ]) + if test $libitm_cv_size_t_mangling = x; then + AC_MSG_ERROR([Unknown underlying type for size_t]) + fi + AC_DEFINE_UNQUOTED(MANGLE_SIZE_T, [$libitm_cv_size_t_mangling], + [Define to the letter to which size_t is mangled.]) +]) + +sinclude(../libtool.m4) +dnl The lines below arrange for aclocal not to bring an installed +dnl libtool.m4 into aclocal.m4, while still arranging for automake to +dnl add a definition of LIBTOOL to Makefile.in. +ifelse(,,,[AC_SUBST(LIBTOOL) +AC_DEFUN([AM_PROG_LIBTOOL]) +AC_DEFUN([AC_LIBTOOL_DLOPEN]) +AC_DEFUN([AC_PROG_LD]) +]) + +dnl ---------------------------------------------------------------------- +dnl This whole bit snagged from libstdc++-v3. + +dnl +dnl LIBITM_ENABLE +dnl (FEATURE, DEFAULT, HELP-ARG, HELP-STRING) +dnl (FEATURE, DEFAULT, HELP-ARG, HELP-STRING, permit a|b|c) +dnl (FEATURE, DEFAULT, HELP-ARG, HELP-STRING, SHELL-CODE-HANDLER) +dnl +dnl See docs/html/17_intro/configury.html#enable for documentation. +dnl +m4_define([LIBITM_ENABLE],[dnl +m4_define([_g_switch],[--enable-$1])dnl +m4_define([_g_help],[AC_HELP_STRING(_g_switch$3,[$4 @<:@default=$2@:>@])])dnl + AC_ARG_ENABLE($1,_g_help, + m4_bmatch([$5], + [^permit ], + [[ + case "$enableval" in + m4_bpatsubst([$5],[permit ])) ;; + *) AC_MSG_ERROR(Unknown argument to enable/disable $1) ;; + dnl Idea for future: generate a URL pointing to + dnl "onlinedocs/configopts.html#whatever" + esac + ]], + [^$], + [[ + case "$enableval" in + yes|no) ;; + *) AC_MSG_ERROR(Argument to enable/disable $1 must be yes or no) ;; + esac + ]], + [[$5]]), + [enable_]m4_bpatsubst([$1],-,_)[=][$2]) +m4_undefine([_g_switch])dnl +m4_undefine([_g_help])dnl +]) + + +dnl +dnl If GNU ld is in use, check to see if tricky linker opts can be used. If +dnl the native linker is in use, all variables will be defined to something +dnl safe (like an empty string). +dnl +dnl Defines: +dnl SECTION_LDFLAGS='-Wl,--gc-sections' if possible +dnl OPT_LDFLAGS='-Wl,-O1' if possible +dnl LD (as a side effect of testing) +dnl Sets: +dnl with_gnu_ld +dnl libitm_gnu_ld_version (possibly) +dnl +dnl The last will be a single integer, e.g., version 1.23.45.0.67.89 will +dnl set libitm_gnu_ld_version to 12345. Zeros cause problems. +dnl +AC_DEFUN([LIBITM_CHECK_LINKER_FEATURES], [ + # If we're not using GNU ld, then there's no point in even trying these + # tests. Check for that first. We should have already tested for gld + # by now (in libtool), but require it now just to be safe... + test -z "$SECTION_LDFLAGS" && SECTION_LDFLAGS='' + test -z "$OPT_LDFLAGS" && OPT_LDFLAGS='' + AC_REQUIRE([AC_PROG_LD]) + AC_REQUIRE([AC_PROG_AWK]) + + # The name set by libtool depends on the version of libtool. Shame on us + # for depending on an impl detail, but c'est la vie. Older versions used + # ac_cv_prog_gnu_ld, but now it's lt_cv_prog_gnu_ld, and is copied back on + # top of with_gnu_ld (which is also set by --with-gnu-ld, so that actually + # makes sense). We'll test with_gnu_ld everywhere else, so if that isn't + # set (hence we're using an older libtool), then set it. + if test x${with_gnu_ld+set} != xset; then + if test x${ac_cv_prog_gnu_ld+set} != xset; then + # We got through "ac_require(ac_prog_ld)" and still not set? Huh? + with_gnu_ld=no + else + with_gnu_ld=$ac_cv_prog_gnu_ld + fi + fi + + # Start by getting the version number. I think the libtool test already + # does some of this, but throws away the result. + changequote(,) + ldver=`$LD --version 2>/dev/null | head -1 | \ + sed -e 's/GNU ld \(version \)\{0,1\}\(([^)]*) \)\{0,1\}\([0-9.][0-9.]*\).*/\3/'` + changequote([,]) + libitm_gnu_ld_version=`echo $ldver | \ + $AWK -F. '{ if (NF<3) [$]3=0; print ([$]1*100+[$]2)*100+[$]3 }'` + + # Set --gc-sections. + if test "$with_gnu_ld" = "notbroken"; then + # GNU ld it is! Joy and bunny rabbits! + + # All these tests are for C++; save the language and the compiler flags. + # Need to do this so that g++ won't try to link in libstdc++ + ac_test_CFLAGS="${CFLAGS+set}" + ac_save_CFLAGS="$CFLAGS" + CFLAGS='-x c++ -Wl,--gc-sections' + + # Check for -Wl,--gc-sections + # XXX This test is broken at the moment, as symbols required for linking + # are now in libsupc++ (not built yet). In addition, this test has + # cored on solaris in the past. In addition, --gc-sections doesn't + # really work at the moment (keeps on discarding used sections, first + # .eh_frame and now some of the glibc sections for iconv). + # Bzzzzt. Thanks for playing, maybe next time. + AC_MSG_CHECKING([for ld that supports -Wl,--gc-sections]) + AC_TRY_RUN([ + int main(void) + { + try { throw 1; } + catch (...) { }; + return 0; + } + ], [ac_sectionLDflags=yes],[ac_sectionLDflags=no], [ac_sectionLDflags=yes]) + if test "$ac_test_CFLAGS" = set; then + CFLAGS="$ac_save_CFLAGS" + else + # this is the suspicious part + CFLAGS='' + fi + if test "$ac_sectionLDflags" = "yes"; then + SECTION_LDFLAGS="-Wl,--gc-sections $SECTION_LDFLAGS" + fi + AC_MSG_RESULT($ac_sectionLDflags) + fi + + # Set linker optimization flags. + if test x"$with_gnu_ld" = x"yes"; then + OPT_LDFLAGS="-Wl,-O1 $OPT_LDFLAGS" + fi + + AC_SUBST(SECTION_LDFLAGS) + AC_SUBST(OPT_LDFLAGS) +]) + + +dnl +dnl Add version tags to symbols in shared library (or not), additionally +dnl marking other symbols as private/local (or not). +dnl +dnl --enable-symvers=style adds a version script to the linker call when +dnl creating the shared library. The choice of version script is +dnl controlled by 'style'. +dnl --disable-symvers does not. +dnl + Usage: LIBITM_ENABLE_SYMVERS[(DEFAULT)] +dnl Where DEFAULT is either 'yes' or 'no'. Passing `yes' tries to +dnl choose a default style based on linker characteristics. Passing +dnl 'no' disables versioning. +dnl +AC_DEFUN([LIBITM_ENABLE_SYMVERS], [ + +LIBITM_ENABLE(symvers,yes,[=STYLE], + [enables symbol versioning of the shared library], + [permit yes|no|gnu]) + +# If we never went through the LIBITM_CHECK_LINKER_FEATURES macro, then we +# don't know enough about $LD to do tricks... +AC_REQUIRE([LIBITM_CHECK_LINKER_FEATURES]) +# FIXME The following test is too strict, in theory. +if test $enable_shared = no || + test "x$LD" = x || + test x$libitm_gnu_ld_version = x; then + enable_symvers=no +fi + +# Check to see if libgcc_s exists, indicating that shared libgcc is possible. +if test $enable_symvers != no; then + AC_MSG_CHECKING([for shared libgcc]) + ac_save_CFLAGS="$CFLAGS" + CFLAGS=' -lgcc_s' + AC_TRY_LINK(, [return 0;], libitm_shared_libgcc=yes, libitm_shared_libgcc=no) + CFLAGS="$ac_save_CFLAGS" + if test $libitm_shared_libgcc = no; then + cat > conftest.c <<EOF +int main (void) { return 0; } +EOF +changequote(,)dnl + libitm_libgcc_s_suffix=`${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS \ + -shared -shared-libgcc -o conftest.so \ + conftest.c -v 2>&1 >/dev/null \ + | sed -n 's/^.* -lgcc_s\([^ ]*\) .*$/\1/p'` +changequote([,])dnl + rm -f conftest.c conftest.so + if test x${libitm_libgcc_s_suffix+set} = xset; then + CFLAGS=" -lgcc_s$libitm_libgcc_s_suffix" + AC_TRY_LINK(, [return 0;], libitm_shared_libgcc=yes) + CFLAGS="$ac_save_CFLAGS" + fi + fi + AC_MSG_RESULT($libitm_shared_libgcc) +fi + +# For GNU ld, we need at least this version. The format is described in +# LIBITM_CHECK_LINKER_FEATURES above. +libitm_min_gnu_ld_version=21400 +# XXXXXXXXXXX libitm_gnu_ld_version=21390 + +# Check to see if unspecified "yes" value can win, given results above. +# Change "yes" into either "no" or a style name. +if test $enable_symvers = yes; then + if test $with_gnu_ld = yes && + test $libitm_shared_libgcc = yes; + then + if test $libitm_gnu_ld_version -ge $libitm_min_gnu_ld_version ; then + enable_symvers=gnu + else + # The right tools, the right setup, but too old. Fallbacks? + AC_MSG_WARN(=== Linker version $libitm_gnu_ld_version is too old for) + AC_MSG_WARN(=== full symbol versioning support in this release of GCC.) + AC_MSG_WARN(=== You would need to upgrade your binutils to version) + AC_MSG_WARN(=== $libitm_min_gnu_ld_version or later and rebuild GCC.) + if test $libitm_gnu_ld_version -ge 21200 ; then + # Globbing fix is present, proper block support is not. + dnl AC_MSG_WARN([=== Dude, you are soooo close. Maybe we can fake it.]) + dnl enable_symvers=??? + AC_MSG_WARN([=== Symbol versioning will be disabled.]) + enable_symvers=no + else + # 2.11 or older. + AC_MSG_WARN([=== Symbol versioning will be disabled.]) + enable_symvers=no + fi + fi + else + # just fail for now + AC_MSG_WARN([=== You have requested some kind of symbol versioning, but]) + AC_MSG_WARN([=== either you are not using a supported linker, or you are]) + AC_MSG_WARN([=== not building a shared libgcc_s (which is required).]) + AC_MSG_WARN([=== Symbol versioning will be disabled.]) + enable_symvers=no + fi +fi + +AM_CONDITIONAL(LIBITM_BUILD_VERSIONED_SHLIB, test $enable_symvers != no) +AC_MSG_NOTICE(versioning on shared library symbols is $enable_symvers) +]) diff --git a/libitm/aclocal.m4 b/libitm/aclocal.m4 new file mode 100644 index 00000000000..6dcccdfae16 --- /dev/null +++ b/libitm/aclocal.m4 @@ -0,0 +1,1007 @@ +# generated automatically by aclocal 1.11.1 -*- Autoconf -*- + +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, +# 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc. +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +m4_ifndef([AC_AUTOCONF_VERSION], + [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl +m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.64],, +[m4_warning([this file was generated for autoconf 2.64. +You have another version of autoconf. It may work, but is not guaranteed to. +If you have problems, you may need to regenerate the build system entirely. +To do so, use the procedure documented by the package, typically `autoreconf'.])]) + +# Copyright (C) 2002, 2003, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_AUTOMAKE_VERSION(VERSION) +# ---------------------------- +# Automake X.Y traces this macro to ensure aclocal.m4 has been +# generated from the m4 files accompanying Automake X.Y. +# (This private macro should not be called outside this file.) +AC_DEFUN([AM_AUTOMAKE_VERSION], +[am__api_version='1.11' +dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to +dnl require some minimum version. Point them to the right macro. +m4_if([$1], [1.11.1], [], + [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl +]) + +# _AM_AUTOCONF_VERSION(VERSION) +# ----------------------------- +# aclocal traces this macro to find the Autoconf version. +# This is a private macro too. Using m4_define simplifies +# the logic in aclocal, which can simply ignore this definition. +m4_define([_AM_AUTOCONF_VERSION], []) + +# AM_SET_CURRENT_AUTOMAKE_VERSION +# ------------------------------- +# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. +# This function is AC_REQUIREd by AM_INIT_AUTOMAKE. +AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], +[AM_AUTOMAKE_VERSION([1.11.1])dnl +m4_ifndef([AC_AUTOCONF_VERSION], + [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl +_AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) + +# Figure out how to run the assembler. -*- Autoconf -*- + +# Copyright (C) 2001, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 5 + +# AM_PROG_AS +# ---------- +AC_DEFUN([AM_PROG_AS], +[# By default we simply use the C compiler to build assembly code. +AC_REQUIRE([AC_PROG_CC]) +test "${CCAS+set}" = set || CCAS=$CC +test "${CCASFLAGS+set}" = set || CCASFLAGS=$CFLAGS +AC_ARG_VAR([CCAS], [assembler compiler command (defaults to CC)]) +AC_ARG_VAR([CCASFLAGS], [assembler compiler flags (defaults to CFLAGS)]) +_AM_IF_OPTION([no-dependencies],, [_AM_DEPENDENCIES([CCAS])])dnl +]) + +# AM_AUX_DIR_EXPAND -*- Autoconf -*- + +# Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets +# $ac_aux_dir to `$srcdir/foo'. In other projects, it is set to +# `$srcdir', `$srcdir/..', or `$srcdir/../..'. +# +# Of course, Automake must honor this variable whenever it calls a +# tool from the auxiliary directory. The problem is that $srcdir (and +# therefore $ac_aux_dir as well) can be either absolute or relative, +# depending on how configure is run. This is pretty annoying, since +# it makes $ac_aux_dir quite unusable in subdirectories: in the top +# source directory, any form will work fine, but in subdirectories a +# relative path needs to be adjusted first. +# +# $ac_aux_dir/missing +# fails when called from a subdirectory if $ac_aux_dir is relative +# $top_srcdir/$ac_aux_dir/missing +# fails if $ac_aux_dir is absolute, +# fails when called from a subdirectory in a VPATH build with +# a relative $ac_aux_dir +# +# The reason of the latter failure is that $top_srcdir and $ac_aux_dir +# are both prefixed by $srcdir. In an in-source build this is usually +# harmless because $srcdir is `.', but things will broke when you +# start a VPATH build or use an absolute $srcdir. +# +# So we could use something similar to $top_srcdir/$ac_aux_dir/missing, +# iff we strip the leading $srcdir from $ac_aux_dir. That would be: +# am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"` +# and then we would define $MISSING as +# MISSING="\${SHELL} $am_aux_dir/missing" +# This will work as long as MISSING is not called from configure, because +# unfortunately $(top_srcdir) has no meaning in configure. +# However there are other variables, like CC, which are often used in +# configure, and could therefore not use this "fixed" $ac_aux_dir. +# +# Another solution, used here, is to always expand $ac_aux_dir to an +# absolute PATH. The drawback is that using absolute paths prevent a +# configured tree to be moved without reconfiguration. + +AC_DEFUN([AM_AUX_DIR_EXPAND], +[dnl Rely on autoconf to set up CDPATH properly. +AC_PREREQ([2.50])dnl +# expand $ac_aux_dir to an absolute path +am_aux_dir=`cd $ac_aux_dir && pwd` +]) + +# AM_CONDITIONAL -*- Autoconf -*- + +# Copyright (C) 1997, 2000, 2001, 2003, 2004, 2005, 2006, 2008 +# Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 9 + +# AM_CONDITIONAL(NAME, SHELL-CONDITION) +# ------------------------------------- +# Define a conditional. +AC_DEFUN([AM_CONDITIONAL], +[AC_PREREQ(2.52)dnl + ifelse([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])], + [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl +AC_SUBST([$1_TRUE])dnl +AC_SUBST([$1_FALSE])dnl +_AM_SUBST_NOTMAKE([$1_TRUE])dnl +_AM_SUBST_NOTMAKE([$1_FALSE])dnl +m4_define([_AM_COND_VALUE_$1], [$2])dnl +if $2; then + $1_TRUE= + $1_FALSE='#' +else + $1_TRUE='#' + $1_FALSE= +fi +AC_CONFIG_COMMANDS_PRE( +[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then + AC_MSG_ERROR([[conditional "$1" was never defined. +Usually this means the macro was only invoked conditionally.]]) +fi])]) + +# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2009 +# Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 10 + +# There are a few dirty hacks below to avoid letting `AC_PROG_CC' be +# written in clear, in which case automake, when reading aclocal.m4, +# will think it sees a *use*, and therefore will trigger all it's +# C support machinery. Also note that it means that autoscan, seeing +# CC etc. in the Makefile, will ask for an AC_PROG_CC use... + + +# _AM_DEPENDENCIES(NAME) +# ---------------------- +# See how the compiler implements dependency checking. +# NAME is "CC", "CXX", "GCJ", or "OBJC". +# We try a few techniques and use that to set a single cache variable. +# +# We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was +# modified to invoke _AM_DEPENDENCIES(CC); we would have a circular +# dependency, and given that the user is not expected to run this macro, +# just rely on AC_PROG_CC. +AC_DEFUN([_AM_DEPENDENCIES], +[AC_REQUIRE([AM_SET_DEPDIR])dnl +AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl +AC_REQUIRE([AM_MAKE_INCLUDE])dnl +AC_REQUIRE([AM_DEP_TRACK])dnl + +ifelse([$1], CC, [depcc="$CC" am_compiler_list=], + [$1], CXX, [depcc="$CXX" am_compiler_list=], + [$1], OBJC, [depcc="$OBJC" am_compiler_list='gcc3 gcc'], + [$1], UPC, [depcc="$UPC" am_compiler_list=], + [$1], GCJ, [depcc="$GCJ" am_compiler_list='gcc3 gcc'], + [depcc="$$1" am_compiler_list=]) + +AC_CACHE_CHECK([dependency style of $depcc], + [am_cv_$1_dependencies_compiler_type], +[if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named `D' -- because `-MD' means `put the output + # in D'. + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + # We will build objects and dependencies in a subdirectory because + # it helps to detect inapplicable dependency modes. For instance + # both Tru64's cc and ICC support -MD to output dependencies as a + # side effect of compilation, but ICC will put the dependencies in + # the current directory while Tru64 will put them in the object + # directory. + mkdir sub + + am_cv_$1_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp` + fi + am__universal=false + m4_case([$1], [CC], + [case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac], + [CXX], + [case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac]) + + for depmode in $am_compiler_list; do + # Setup a source with many dependencies, because some compilers + # like to wrap large dependency lists on column 80 (with \), and + # we should not choose a depcomp mode which is confused by this. + # + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + : > sub/conftest.c + for i in 1 2 3 4 5 6; do + echo '#include "conftst'$i'.h"' >> sub/conftest.c + # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with + # Solaris 8's {/usr,}/bin/sh. + touch sub/conftst$i.h + done + echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf + + # We check with `-c' and `-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle `-M -o', and we need to detect this. Also, some Intel + # versions had trouble with output in subdirs + am__obj=sub/conftest.${OBJEXT-o} + am__minus_obj="-o $am__obj" + case $depmode in + gcc) + # This depmode causes a compiler race in universal mode. + test "$am__universal" = false || continue + ;; + nosideeffect) + # after this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + msvisualcpp | msvcmsys) + # This compiler won't grok `-c -o', but also, the minuso test has + # not run yet. These depmodes are late enough in the game, and + # so weak that their functioning should not be impacted. + am__obj=conftest.${OBJEXT-o} + am__minus_obj= + ;; + none) break ;; + esac + if depmode=$depmode \ + source=sub/conftest.c object=$am__obj \ + depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ + $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ + >/dev/null 2>conftest.err && + grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && + grep $am__obj sub/conftest.Po > /dev/null 2>&1 && + ${MAKE-make} -s -f confmf > /dev/null 2>&1; then + # icc doesn't choke on unknown options, it will just issue warnings + # or remarks (even with -Werror). So we grep stderr for any message + # that says an option was ignored or not supported. + # When given -MP, icc 7.0 and 7.1 complain thusly: + # icc: Command line warning: ignoring option '-M'; no argument required + # The diagnosis changed in icc 8.0: + # icc: Command line remark: option '-MP' not supported + if (grep 'ignoring option' conftest.err || + grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else + am_cv_$1_dependencies_compiler_type=$depmode + break + fi + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_$1_dependencies_compiler_type=none +fi +]) +AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type]) +AM_CONDITIONAL([am__fastdep$1], [ + test "x$enable_dependency_tracking" != xno \ + && test "$am_cv_$1_dependencies_compiler_type" = gcc3]) +]) + + +# AM_SET_DEPDIR +# ------------- +# Choose a directory name for dependency files. +# This macro is AC_REQUIREd in _AM_DEPENDENCIES +AC_DEFUN([AM_SET_DEPDIR], +[AC_REQUIRE([AM_SET_LEADING_DOT])dnl +AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl +]) + + +# AM_DEP_TRACK +# ------------ +AC_DEFUN([AM_DEP_TRACK], +[AC_ARG_ENABLE(dependency-tracking, +[ --disable-dependency-tracking speeds up one-time build + --enable-dependency-tracking do not reject slow dependency extractors]) +if test "x$enable_dependency_tracking" != xno; then + am_depcomp="$ac_aux_dir/depcomp" + AMDEPBACKSLASH='\' +fi +AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) +AC_SUBST([AMDEPBACKSLASH])dnl +_AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl +]) + +# Generate code to set up dependency tracking. -*- Autoconf -*- + +# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2008 +# Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +#serial 5 + +# _AM_OUTPUT_DEPENDENCY_COMMANDS +# ------------------------------ +AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], +[{ + # Autoconf 2.62 quotes --file arguments for eval, but not when files + # are listed without --file. Let's play safe and only enable the eval + # if we detect the quoting. + case $CONFIG_FILES in + *\'*) eval set x "$CONFIG_FILES" ;; + *) set x $CONFIG_FILES ;; + esac + shift + for mf + do + # Strip MF so we end up with the name of the file. + mf=`echo "$mf" | sed -e 's/:.*$//'` + # Check whether this is an Automake generated Makefile or not. + # We used to match only the files named `Makefile.in', but + # some people rename them; so instead we look at the file content. + # Grep'ing the first line is not enough: some people post-process + # each Makefile.in and add a new line on top of each file to say so. + # Grep'ing the whole file is not good either: AIX grep has a line + # limit of 2048, but all sed's we know have understand at least 4000. + if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then + dirpart=`AS_DIRNAME("$mf")` + else + continue + fi + # Extract the definition of DEPDIR, am__include, and am__quote + # from the Makefile without running `make'. + DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` + test -z "$DEPDIR" && continue + am__include=`sed -n 's/^am__include = //p' < "$mf"` + test -z "am__include" && continue + am__quote=`sed -n 's/^am__quote = //p' < "$mf"` + # When using ansi2knr, U may be empty or an underscore; expand it + U=`sed -n 's/^U = //p' < "$mf"` + # Find all dependency output files, they are included files with + # $(DEPDIR) in their names. We invoke sed twice because it is the + # simplest approach to changing $(DEPDIR) to its actual value in the + # expansion. + for file in `sed -n " + s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ + sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do + # Make sure the directory exists. + test -f "$dirpart/$file" && continue + fdir=`AS_DIRNAME(["$file"])` + AS_MKDIR_P([$dirpart/$fdir]) + # echo "creating $dirpart/$file" + echo '# dummy' > "$dirpart/$file" + done + done +} +])# _AM_OUTPUT_DEPENDENCY_COMMANDS + + +# AM_OUTPUT_DEPENDENCY_COMMANDS +# ----------------------------- +# This macro should only be invoked once -- use via AC_REQUIRE. +# +# This code is only required when automatic dependency tracking +# is enabled. FIXME. This creates each `.P' file that we will +# need in order to bootstrap the dependency handling code. +AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], +[AC_CONFIG_COMMANDS([depfiles], + [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS], + [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"]) +]) + +# Do all the work for Automake. -*- Autoconf -*- + +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, +# 2005, 2006, 2008, 2009 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 16 + +# This macro actually does too much. Some checks are only needed if +# your package does certain things. But this isn't really a big deal. + +# AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE]) +# AM_INIT_AUTOMAKE([OPTIONS]) +# ----------------------------------------------- +# The call with PACKAGE and VERSION arguments is the old style +# call (pre autoconf-2.50), which is being phased out. PACKAGE +# and VERSION should now be passed to AC_INIT and removed from +# the call to AM_INIT_AUTOMAKE. +# We support both call styles for the transition. After +# the next Automake release, Autoconf can make the AC_INIT +# arguments mandatory, and then we can depend on a new Autoconf +# release and drop the old call support. +AC_DEFUN([AM_INIT_AUTOMAKE], +[AC_PREREQ([2.62])dnl +dnl Autoconf wants to disallow AM_ names. We explicitly allow +dnl the ones we care about. +m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl +AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl +AC_REQUIRE([AC_PROG_INSTALL])dnl +if test "`cd $srcdir && pwd`" != "`pwd`"; then + # Use -I$(srcdir) only when $(srcdir) != ., so that make's output + # is not polluted with repeated "-I." + AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl + # test to see if srcdir already configured + if test -f $srcdir/config.status; then + AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) + fi +fi + +# test whether we have cygpath +if test -z "$CYGPATH_W"; then + if (cygpath --version) >/dev/null 2>/dev/null; then + CYGPATH_W='cygpath -w' + else + CYGPATH_W=echo + fi +fi +AC_SUBST([CYGPATH_W]) + +# Define the identity of the package. +dnl Distinguish between old-style and new-style calls. +m4_ifval([$2], +[m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl + AC_SUBST([PACKAGE], [$1])dnl + AC_SUBST([VERSION], [$2])], +[_AM_SET_OPTIONS([$1])dnl +dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT. +m4_if(m4_ifdef([AC_PACKAGE_NAME], 1)m4_ifdef([AC_PACKAGE_VERSION], 1), 11,, + [m4_fatal([AC_INIT should be called with package and version arguments])])dnl + AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl + AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl + +_AM_IF_OPTION([no-define],, +[AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package]) + AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package])])dnl + +# Some tools Automake needs. +AC_REQUIRE([AM_SANITY_CHECK])dnl +AC_REQUIRE([AC_ARG_PROGRAM])dnl +AM_MISSING_PROG(ACLOCAL, aclocal-${am__api_version}) +AM_MISSING_PROG(AUTOCONF, autoconf) +AM_MISSING_PROG(AUTOMAKE, automake-${am__api_version}) +AM_MISSING_PROG(AUTOHEADER, autoheader) +AM_MISSING_PROG(MAKEINFO, makeinfo) +AC_REQUIRE([AM_PROG_INSTALL_SH])dnl +AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl +AC_REQUIRE([AM_PROG_MKDIR_P])dnl +# We need awk for the "check" target. The system "awk" is bad on +# some platforms. +AC_REQUIRE([AC_PROG_AWK])dnl +AC_REQUIRE([AC_PROG_MAKE_SET])dnl +AC_REQUIRE([AM_SET_LEADING_DOT])dnl +_AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])], + [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])], + [_AM_PROG_TAR([v7])])]) +_AM_IF_OPTION([no-dependencies],, +[AC_PROVIDE_IFELSE([AC_PROG_CC], + [_AM_DEPENDENCIES(CC)], + [define([AC_PROG_CC], + defn([AC_PROG_CC])[_AM_DEPENDENCIES(CC)])])dnl +AC_PROVIDE_IFELSE([AC_PROG_CXX], + [_AM_DEPENDENCIES(CXX)], + [define([AC_PROG_CXX], + defn([AC_PROG_CXX])[_AM_DEPENDENCIES(CXX)])])dnl +AC_PROVIDE_IFELSE([AC_PROG_OBJC], + [_AM_DEPENDENCIES(OBJC)], + [define([AC_PROG_OBJC], + defn([AC_PROG_OBJC])[_AM_DEPENDENCIES(OBJC)])])dnl +]) +_AM_IF_OPTION([silent-rules], [AC_REQUIRE([AM_SILENT_RULES])])dnl +dnl The `parallel-tests' driver may need to know about EXEEXT, so add the +dnl `am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This macro +dnl is hooked onto _AC_COMPILER_EXEEXT early, see below. +AC_CONFIG_COMMANDS_PRE(dnl +[m4_provide_if([_AM_COMPILER_EXEEXT], + [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl +]) + +dnl Hook into `_AC_COMPILER_EXEEXT' early to learn its expansion. Do not +dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further +dnl mangled by Autoconf and run in a shell conditional statement. +m4_define([_AC_COMPILER_EXEEXT], +m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])]) + + +# When config.status generates a header, we must update the stamp-h file. +# This file resides in the same directory as the config header +# that is generated. The stamp files are numbered to have different names. + +# Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the +# loop where config.status creates the headers, so we can generate +# our stamp files there. +AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK], +[# Compute $1's index in $config_headers. +_am_arg=$1 +_am_stamp_count=1 +for _am_header in $config_headers :; do + case $_am_header in + $_am_arg | $_am_arg:* ) + break ;; + * ) + _am_stamp_count=`expr $_am_stamp_count + 1` ;; + esac +done +echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count]) + +# Copyright (C) 2001, 2003, 2005, 2008 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_PROG_INSTALL_SH +# ------------------ +# Define $install_sh. +AC_DEFUN([AM_PROG_INSTALL_SH], +[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +if test x"${install_sh}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; + *) + install_sh="\${SHELL} $am_aux_dir/install-sh" + esac +fi +AC_SUBST(install_sh)]) + +# Add --enable-maintainer-mode option to configure. -*- Autoconf -*- +# From Jim Meyering + +# Copyright (C) 1996, 1998, 2000, 2001, 2002, 2003, 2004, 2005, 2008 +# Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 5 + +# AM_MAINTAINER_MODE([DEFAULT-MODE]) +# ---------------------------------- +# Control maintainer-specific portions of Makefiles. +# Default is to disable them, unless `enable' is passed literally. +# For symmetry, `disable' may be passed as well. Anyway, the user +# can override the default with the --enable/--disable switch. +AC_DEFUN([AM_MAINTAINER_MODE], +[m4_case(m4_default([$1], [disable]), + [enable], [m4_define([am_maintainer_other], [disable])], + [disable], [m4_define([am_maintainer_other], [enable])], + [m4_define([am_maintainer_other], [enable]) + m4_warn([syntax], [unexpected argument to AM@&t@_MAINTAINER_MODE: $1])]) +AC_MSG_CHECKING([whether to am_maintainer_other maintainer-specific portions of Makefiles]) + dnl maintainer-mode's default is 'disable' unless 'enable' is passed + AC_ARG_ENABLE([maintainer-mode], +[ --][am_maintainer_other][-maintainer-mode am_maintainer_other make rules and dependencies not useful + (and sometimes confusing) to the casual installer], + [USE_MAINTAINER_MODE=$enableval], + [USE_MAINTAINER_MODE=]m4_if(am_maintainer_other, [enable], [no], [yes])) + AC_MSG_RESULT([$USE_MAINTAINER_MODE]) + AM_CONDITIONAL([MAINTAINER_MODE], [test $USE_MAINTAINER_MODE = yes]) + MAINT=$MAINTAINER_MODE_TRUE + AC_SUBST([MAINT])dnl +] +) + +AU_DEFUN([jm_MAINTAINER_MODE], [AM_MAINTAINER_MODE]) + +# Check to see how 'make' treats includes. -*- Autoconf -*- + +# Copyright (C) 2001, 2002, 2003, 2005, 2009 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 4 + +# AM_MAKE_INCLUDE() +# ----------------- +# Check to see how make treats includes. +AC_DEFUN([AM_MAKE_INCLUDE], +[am_make=${MAKE-make} +cat > confinc << 'END' +am__doit: + @echo this is the am__doit target +.PHONY: am__doit +END +# If we don't find an include directive, just comment out the code. +AC_MSG_CHECKING([for style of include used by $am_make]) +am__include="#" +am__quote= +_am_result=none +# First try GNU make style include. +echo "include confinc" > confmf +# Ignore all kinds of additional output from `make'. +case `$am_make -s -f confmf 2> /dev/null` in #( +*the\ am__doit\ target*) + am__include=include + am__quote= + _am_result=GNU + ;; +esac +# Now try BSD make style include. +if test "$am__include" = "#"; then + echo '.include "confinc"' > confmf + case `$am_make -s -f confmf 2> /dev/null` in #( + *the\ am__doit\ target*) + am__include=.include + am__quote="\"" + _am_result=BSD + ;; + esac +fi +AC_SUBST([am__include]) +AC_SUBST([am__quote]) +AC_MSG_RESULT([$_am_result]) +rm -f confinc confmf +]) + +# Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- + +# Copyright (C) 1997, 1999, 2000, 2001, 2003, 2004, 2005, 2008 +# Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 6 + +# AM_MISSING_PROG(NAME, PROGRAM) +# ------------------------------ +AC_DEFUN([AM_MISSING_PROG], +[AC_REQUIRE([AM_MISSING_HAS_RUN]) +$1=${$1-"${am_missing_run}$2"} +AC_SUBST($1)]) + + +# AM_MISSING_HAS_RUN +# ------------------ +# Define MISSING if not defined so far and test if it supports --run. +# If it does, set am_missing_run to use it, otherwise, to nothing. +AC_DEFUN([AM_MISSING_HAS_RUN], +[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +AC_REQUIRE_AUX_FILE([missing])dnl +if test x"${MISSING+set}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; + *) + MISSING="\${SHELL} $am_aux_dir/missing" ;; + esac +fi +# Use eval to expand $SHELL +if eval "$MISSING --run true"; then + am_missing_run="$MISSING --run " +else + am_missing_run= + AC_MSG_WARN([`missing' script is too old or missing]) +fi +]) + +# Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_PROG_MKDIR_P +# --------------- +# Check for `mkdir -p'. +AC_DEFUN([AM_PROG_MKDIR_P], +[AC_PREREQ([2.60])dnl +AC_REQUIRE([AC_PROG_MKDIR_P])dnl +dnl Automake 1.8 to 1.9.6 used to define mkdir_p. We now use MKDIR_P, +dnl while keeping a definition of mkdir_p for backward compatibility. +dnl @MKDIR_P@ is magic: AC_OUTPUT adjusts its value for each Makefile. +dnl However we cannot define mkdir_p as $(MKDIR_P) for the sake of +dnl Makefile.ins that do not define MKDIR_P, so we do our own +dnl adjustment using top_builddir (which is defined more often than +dnl MKDIR_P). +AC_SUBST([mkdir_p], ["$MKDIR_P"])dnl +case $mkdir_p in + [[\\/$]]* | ?:[[\\/]]*) ;; + */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;; +esac +]) + +# Helper functions for option handling. -*- Autoconf -*- + +# Copyright (C) 2001, 2002, 2003, 2005, 2008 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 4 + +# _AM_MANGLE_OPTION(NAME) +# ----------------------- +AC_DEFUN([_AM_MANGLE_OPTION], +[[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])]) + +# _AM_SET_OPTION(NAME) +# ------------------------------ +# Set option NAME. Presently that only means defining a flag for this option. +AC_DEFUN([_AM_SET_OPTION], +[m4_define(_AM_MANGLE_OPTION([$1]), 1)]) + +# _AM_SET_OPTIONS(OPTIONS) +# ---------------------------------- +# OPTIONS is a space-separated list of Automake options. +AC_DEFUN([_AM_SET_OPTIONS], +[m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])]) + +# _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET]) +# ------------------------------------------- +# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. +AC_DEFUN([_AM_IF_OPTION], +[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) + +# Check to make sure that the build environment is sane. -*- Autoconf -*- + +# Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005, 2008 +# Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 5 + +# AM_SANITY_CHECK +# --------------- +AC_DEFUN([AM_SANITY_CHECK], +[AC_MSG_CHECKING([whether build environment is sane]) +# Just in case +sleep 1 +echo timestamp > conftest.file +# Reject unsafe characters in $srcdir or the absolute working directory +# name. Accept space and tab only in the latter. +am_lf=' +' +case `pwd` in + *[[\\\"\#\$\&\'\`$am_lf]]*) + AC_MSG_ERROR([unsafe absolute working directory name]);; +esac +case $srcdir in + *[[\\\"\#\$\&\'\`$am_lf\ \ ]]*) + AC_MSG_ERROR([unsafe srcdir value: `$srcdir']);; +esac + +# Do `set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` + if test "$[*]" = "X"; then + # -L didn't work. + set X `ls -t "$srcdir/configure" conftest.file` + fi + rm -f conftest.file + if test "$[*]" != "X $srcdir/configure conftest.file" \ + && test "$[*]" != "X conftest.file $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken +alias in your environment]) + fi + + test "$[2]" = conftest.file + ) +then + # Ok. + : +else + AC_MSG_ERROR([newly created file is older than distributed files! +Check your system clock]) +fi +AC_MSG_RESULT(yes)]) + +# Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_PROG_INSTALL_STRIP +# --------------------- +# One issue with vendor `install' (even GNU) is that you can't +# specify the program used to strip binaries. This is especially +# annoying in cross-compiling environments, where the build's strip +# is unlikely to handle the host's binaries. +# Fortunately install-sh will honor a STRIPPROG variable, so we +# always use install-sh in `make install-strip', and initialize +# STRIPPROG with the value of the STRIP variable (set by the user). +AC_DEFUN([AM_PROG_INSTALL_STRIP], +[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl +# Installed binaries are usually stripped using `strip' when the user +# run `make install-strip'. However `strip' might not be the right +# tool to use in cross-compilation environments, therefore Automake +# will honor the `STRIP' environment variable to overrule this program. +dnl Don't test for $cross_compiling = yes, because it might be `maybe'. +if test "$cross_compiling" != no; then + AC_CHECK_TOOL([STRIP], [strip], :) +fi +INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" +AC_SUBST([INSTALL_STRIP_PROGRAM])]) + +# Copyright (C) 2006, 2008 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 2 + +# _AM_SUBST_NOTMAKE(VARIABLE) +# --------------------------- +# Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in. +# This macro is traced by Automake. +AC_DEFUN([_AM_SUBST_NOTMAKE]) + +# AM_SUBST_NOTMAKE(VARIABLE) +# --------------------------- +# Public sister of _AM_SUBST_NOTMAKE. +AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)]) + +# Check how to create a tarball. -*- Autoconf -*- + +# Copyright (C) 2004, 2005 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 2 + +# _AM_PROG_TAR(FORMAT) +# -------------------- +# Check how to create a tarball in format FORMAT. +# FORMAT should be one of `v7', `ustar', or `pax'. +# +# Substitute a variable $(am__tar) that is a command +# writing to stdout a FORMAT-tarball containing the directory +# $tardir. +# tardir=directory && $(am__tar) > result.tar +# +# Substitute a variable $(am__untar) that extract such +# a tarball read from stdin. +# $(am__untar) < result.tar +AC_DEFUN([_AM_PROG_TAR], +[# Always define AMTAR for backward compatibility. +AM_MISSING_PROG([AMTAR], [tar]) +m4_if([$1], [v7], + [am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'], + [m4_case([$1], [ustar],, [pax],, + [m4_fatal([Unknown tar format])]) +AC_MSG_CHECKING([how to create a $1 tar archive]) +# Loop over all known methods to create a tar archive until one works. +_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none' +_am_tools=${am_cv_prog_tar_$1-$_am_tools} +# Do not fold the above two line into one, because Tru64 sh and +# Solaris sh will not grok spaces in the rhs of `-'. +for _am_tool in $_am_tools +do + case $_am_tool in + gnutar) + for _am_tar in tar gnutar gtar; + do + AM_RUN_LOG([$_am_tar --version]) && break + done + am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"' + am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"' + am__untar="$_am_tar -xf -" + ;; + plaintar) + # Must skip GNU tar: if it does not support --format= it doesn't create + # ustar tarball either. + (tar --version) >/dev/null 2>&1 && continue + am__tar='tar chf - "$$tardir"' + am__tar_='tar chf - "$tardir"' + am__untar='tar xf -' + ;; + pax) + am__tar='pax -L -x $1 -w "$$tardir"' + am__tar_='pax -L -x $1 -w "$tardir"' + am__untar='pax -r' + ;; + cpio) + am__tar='find "$$tardir" -print | cpio -o -H $1 -L' + am__tar_='find "$tardir" -print | cpio -o -H $1 -L' + am__untar='cpio -i -H $1 -d' + ;; + none) + am__tar=false + am__tar_=false + am__untar=false + ;; + esac + + # If the value was cached, stop now. We just wanted to have am__tar + # and am__untar set. + test -n "${am_cv_prog_tar_$1}" && break + + # tar/untar a dummy directory, and stop if the command works + rm -rf conftest.dir + mkdir conftest.dir + echo GrepMe > conftest.dir/file + AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar]) + rm -rf conftest.dir + if test -s conftest.tar; then + AM_RUN_LOG([$am__untar <conftest.tar]) + grep GrepMe conftest.dir/file >/dev/null 2>&1 && break + fi +done +rm -rf conftest.dir + +AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool]) +AC_MSG_RESULT([$am_cv_prog_tar_$1])]) +AC_SUBST([am__tar]) +AC_SUBST([am__untar]) +]) # _AM_PROG_TAR + +m4_include([../config/acx.m4]) +m4_include([../config/depstand.m4]) +m4_include([../config/enable.m4]) +m4_include([../config/futex.m4]) +m4_include([../config/lead-dot.m4]) +m4_include([../config/mmap.m4]) +m4_include([../config/multi.m4]) +m4_include([../config/override.m4]) +m4_include([../config/stdint.m4]) +m4_include([../config/tls.m4]) +m4_include([../ltoptions.m4]) +m4_include([../ltsugar.m4]) +m4_include([../ltversion.m4]) +m4_include([../lt~obsolete.m4]) +m4_include([acinclude.m4]) diff --git a/libitm/alloc.cc b/libitm/alloc.cc new file mode 100644 index 00000000000..ec36269e6c8 --- /dev/null +++ b/libitm/alloc.cc @@ -0,0 +1,129 @@ +/* Copyright (C) 2009, 2011 Free Software Foundation, Inc. + Contributed by Richard Henderson <rth@redhat.com>. + + This file is part of the GNU Transactional Memory Library (libitm). + + Libitm is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + Libitm is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + <http://www.gnu.org/licenses/>. */ + +#include "libitm_i.h" + +namespace GTM HIDDEN { + +void +gtm_thread::record_allocation (void *ptr, void (*free_fn)(void *)) +{ + uintptr_t iptr = (uintptr_t) ptr; + + gtm_alloc_action *a = this->alloc_actions.find(iptr); + if (a == 0) + a = this->alloc_actions.insert(iptr); + + a->free_fn = free_fn; + a->allocated = true; +} + +void +gtm_thread::forget_allocation (void *ptr, void (*free_fn)(void *)) +{ + uintptr_t iptr = (uintptr_t) ptr; + + gtm_alloc_action *a = this->alloc_actions.find(iptr); + if (a == 0) + a = this->alloc_actions.insert(iptr); + + a->free_fn = free_fn; + a->allocated = false; +} + +namespace { +struct commit_cb_data { + aa_tree<uintptr_t, gtm_alloc_action>* parent; + bool revert_p; +}; +} + +static void +commit_allocations_2 (uintptr_t key, gtm_alloc_action *a, void *data) +{ + void *ptr = (void *)key; + commit_cb_data *cb_data = static_cast<commit_cb_data *>(data); + + if (cb_data->revert_p) + { + // Roll back nested allocations. + if (a->allocated) + a->free_fn (ptr); + } + else + { + if (a->allocated) + { + // Add nested allocations to parent transaction. + gtm_alloc_action* a_parent = cb_data->parent->insert(key); + *a_parent = *a; + } + else + { + // ??? We could eliminate a parent allocation that matches this + // memory release, if we had support for removing all accesses + // to this allocation from the transaction's undo and redo logs + // (otherwise, the parent transaction's undo or redo might write to + // data that is already shared again because of calling free()). + // We don't have this support currently, and the benefit of this + // optimization is unknown, so just add it to the parent. + gtm_alloc_action* a_parent; + a_parent = cb_data->parent->insert(key); + *a_parent = *a; + } + } +} + +static void +commit_allocations_1 (uintptr_t key, gtm_alloc_action *a, void *cb_data) +{ + void *ptr = (void *)key; + uintptr_t revert_p = (uintptr_t) cb_data; + + if (a->allocated == revert_p) + a->free_fn (ptr); +} + +/* Permanently commit allocated memory during transaction. + + REVERT_P is true if instead of committing the allocations, we want + to roll them back (and vice versa). */ +void +gtm_thread::commit_allocations (bool revert_p, + aa_tree<uintptr_t, gtm_alloc_action>* parent) +{ + if (parent) + { + commit_cb_data cb_data; + cb_data.parent = parent; + cb_data.revert_p = revert_p; + this->alloc_actions.traverse (commit_allocations_2, &cb_data); + } + else + this->alloc_actions.traverse (commit_allocations_1, + (void *)(uintptr_t)revert_p); + this->alloc_actions.clear (); +} + +} // namespace GTM diff --git a/libitm/alloc_c.cc b/libitm/alloc_c.cc new file mode 100644 index 00000000000..c0cf263a053 --- /dev/null +++ b/libitm/alloc_c.cc @@ -0,0 +1,72 @@ +/* Copyright (C) 2009, 2011 Free Software Foundation, Inc. + Contributed by Richard Henderson <rth@redhat.com>. + + This file is part of the GNU Transactional Memory Library (libitm). + + Libitm is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + Libitm is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + <http://www.gnu.org/licenses/>. */ + +#include "libitm_i.h" + + +using namespace GTM; + +extern "C" { + +/* Wrap: malloc (size_t sz) */ +void * +_ITM_malloc (size_t sz) +{ + void *r = malloc (sz); + if (r) + gtm_thr()->record_allocation (r, free); + return r; +} + +/* Wrap: calloc (size_t nm, size_t sz) */ +void * +_ITM_calloc (size_t nm, size_t sz) +{ + void *r = calloc (nm, sz); + if (r) + gtm_thr()->record_allocation (r, free); + return r; +} + +/* Wrap: free (void *ptr) */ +void +_ITM_free (void *ptr) +{ + if (ptr) + gtm_thr()->forget_allocation (ptr, free); +} + +/* Forget any internal references to PTR. */ + +__attribute__((transaction_pure)) +void ITM_REGPARM +_ITM_dropReferences (void *ptr, size_t len) +{ + // The semantics of _ITM_dropReferences are not sufficiently defined in the + // ABI specification, so it does not make sense to support it right now. See + // the libitm documentation for details. + GTM_fatal("_ITM_dropReferences is not supported"); +} + +} // extern "C" diff --git a/libitm/alloc_cpp.cc b/libitm/alloc_cpp.cc new file mode 100644 index 00000000000..59d8b7374eb --- /dev/null +++ b/libitm/alloc_cpp.cc @@ -0,0 +1,152 @@ +/* Copyright (C) 2009, 2011 Free Software Foundation, Inc. + Contributed by Richard Henderson <rth@redhat.com>. + + This file is part of the GNU Transactional Memory Library (libitm). + + Libitm is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + Libitm is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + <http://www.gnu.org/licenses/>. */ + +#include "libitm_i.h" + +using namespace GTM; + +/* Mangling the names by hand requires that we know how size_t is handled. + We've gotten the letter from autoconf, now substitute it into the names. + Everything below uses X as a placeholder for clarity. */ + +#define S1(x,y) x##y +#define S(x,y) S1(x,y) + +#define _ZnwX S(_Znw,MANGLE_SIZE_T) +#define _ZnaX S(_Zna,MANGLE_SIZE_T) +#define _ZnwXRKSt9nothrow_t S(S(_Znw,MANGLE_SIZE_T),RKSt9nothrow_t) +#define _ZnaXRKSt9nothrow_t S(S(_Zna,MANGLE_SIZE_T),RKSt9nothrow_t) + +#define _ZGTtnwX S(_ZGTtnw,MANGLE_SIZE_T) +#define _ZGTtnaX S(_ZGTtna,MANGLE_SIZE_T) +#define _ZGTtnwXRKSt9nothrow_t S(S(_ZGTtnw,MANGLE_SIZE_T),RKSt9nothrow_t) +#define _ZGTtnaXRKSt9nothrow_t S(S(_ZGTtna,MANGLE_SIZE_T),RKSt9nothrow_t) + +/* Everything from libstdc++ is weak, to avoid requiring that library + to be linked into plain C applications using libitm.so. */ + +extern "C" { + +extern void *_ZnwX (size_t) __attribute__((weak)); +extern void _ZdlPv (void *) __attribute__((weak)); +extern void *_ZnaX (size_t) __attribute__((weak)); +extern void _ZdaPv (void *) __attribute__((weak)); + +typedef const struct nothrow_t { } *c_nothrow_p; + +extern void *_ZnwXRKSt9nothrow_t (size_t, c_nothrow_p) __attribute__((weak)); +extern void _ZdlPvRKSt9nothrow_t (void *, c_nothrow_p) __attribute__((weak)); +extern void *_ZnaXRKSt9nothrow_t (size_t, c_nothrow_p) __attribute__((weak)); +extern void _ZdaPvRKSt9nothrow_t (void *, c_nothrow_p) __attribute__((weak)); + +/* Wrap the delete nothrow symbols for usage with a single argument. + Perhaps should have a configure type check for this, because the + std::nothrow_t reference argument is unused (empty class), and most + targets don't actually need that second argument. So we _could_ + invoke these functions as if they were a single argument free. */ +static void +del_opnt (void *ptr) +{ + _ZdlPvRKSt9nothrow_t (ptr, NULL); +} + +static void +del_opvnt (void *ptr) +{ + _ZdaPvRKSt9nothrow_t (ptr, NULL); +} + +/* Wrap: operator new (std::size_t sz) */ +void * +_ZGTtnwX (size_t sz) +{ + void *r = _ZnwX (sz); + if (r) + gtm_thr()->record_allocation (r, _ZdlPv); + return r; +} + +/* Wrap: operator new (std::size_t sz, const std::nothrow_t&) */ +void * +_ZGTtnwXRKSt9nothrow_t (size_t sz, c_nothrow_p nt) +{ + void *r = _ZnwXRKSt9nothrow_t (sz, nt); + if (r) + gtm_thr()->record_allocation (r, del_opnt); + return r; +} + +/* Wrap: operator new[] (std::size_t sz) */ +void * +_ZGTtnaX (size_t sz) +{ + void *r = _ZnaX (sz); + if (r) + gtm_thr()->record_allocation (r, _ZdaPv); + return r; +} + +/* Wrap: operator new[] (std::size_t sz, const std::nothrow_t& nothrow) */ +void * +_ZGTtnaXRKSt9nothrow_t (size_t sz, c_nothrow_p nt) +{ + void *r = _ZnaXRKSt9nothrow_t (sz, nt); + if (r) + gtm_thr()->record_allocation (r, del_opvnt); + return r; +} + +/* Wrap: operator delete(void* ptr) */ +void +_ZGTtdlPv (void *ptr) +{ + if (ptr) + gtm_thr()->forget_allocation (ptr, _ZdlPv); +} + +/* Wrap: operator delete (void *ptr, const std::nothrow_t&) */ +void +_ZGTtdlPvRKSt9nothrow_t (void *ptr, c_nothrow_p nt UNUSED) +{ + if (ptr) + gtm_thr()->forget_allocation (ptr, del_opnt); +} + +/* Wrap: operator delete[] (void *ptr) */ +void +_ZGTtdaPv (void *ptr) +{ + if (ptr) + gtm_thr()->forget_allocation (ptr, _ZdaPv); +} + +/* Wrap: operator delete[] (void *ptr, const std::nothrow_t&) */ +void +_ZGTtdaPvRKSt9nothrow_t (void *ptr, c_nothrow_p nt UNUSED) +{ + if (ptr) + gtm_thr()->forget_allocation (ptr, del_opvnt); +} + +} // extern "C" diff --git a/libitm/barrier.cc b/libitm/barrier.cc new file mode 100644 index 00000000000..a536d0f862f --- /dev/null +++ b/libitm/barrier.cc @@ -0,0 +1,44 @@ +/* Copyright (C) 2008, 2009, 2011 Free Software Foundation, Inc. + Contributed by Richard Henderson <rth@redhat.com>. + + This file is part of the GNU Transactional Memory Library (libitm). + + Libitm is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + Libitm is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + <http://www.gnu.org/licenses/>. */ + +#include "libitm_i.h" + +using namespace GTM; + +bool abi_dispatch::memmove_overlap_check(void *dst, const void *src, + size_t size, ls_modifier dst_mod, ls_modifier src_mod) +{ + if (dst_mod == NONTXNAL || src_mod == NONTXNAL) + { + if (((uintptr_t)dst <= (uintptr_t)src ? + (uintptr_t)dst + size > (uintptr_t)src : + (uintptr_t)src + size > (uintptr_t)dst)) + GTM::GTM_fatal("_ITM_memmove overlapping and t/nt is not allowed"); + return false; + } + return true; +} + +CREATE_DISPATCH_FUNCTIONS(GTM::abi_disp()->, ) + diff --git a/libitm/barrier.tpl b/libitm/barrier.tpl new file mode 100644 index 00000000000..dcf101356e6 --- /dev/null +++ b/libitm/barrier.tpl @@ -0,0 +1,170 @@ +/* -*- c++ -*- */ +/* Copyright (C) 2008, 2009, 2011 Free Software Foundation, Inc. + Contributed by Richard Henderson <rth@redhat.com>. + + This file is part of the GNU Transactional Memory Library (libitm). + + Libitm is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + Libitm is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + <http://www.gnu.org/licenses/>. */ + +#include "unaligned.h" + +namespace { + +using namespace GTM; + +template<typename T> +T do_read (const T *ptr, abi_dispatch::lock_type lock) +{ + // + // Find the cacheline that holds the current value of *PTR. + // + abi_dispatch *disp = abi_disp(); + uintptr_t iptr = reinterpret_cast<uintptr_t>(ptr); + // Normalize PTR by chopping off the bottom bits so we can search + // for PTR in the cacheline hash. + uintptr_t iline = iptr & -CACHELINE_SIZE; + // The position in the resulting cacheline where *PTR is actually stored. + uintptr_t iofs = iptr & (CACHELINE_SIZE - 1); + const gtm_cacheline *pline = reinterpret_cast<const gtm_cacheline *>(iline); + // Search for the actual cacheline that holds the current value of *PTR. + const gtm_cacheline *line = disp->read_lock(pline, lock); + + // Point to the position in the cacheline where *PTR is stored. + ptr = reinterpret_cast<const T *>(&line->b[iofs]); + + // Straight up loads, because we're either aligned, or we don't care + // about alignment. + // + // If we require alignment on type T, do a straight load if we're + // aligned. Otherwise do a straight load IFF the load fits entirely + // in this cacheline. That is, it won't span multiple cachelines. + if (__builtin_expect (strict_alignment<T>::value + ? (iofs & (sizeof (T) - 1)) == 0 + : iofs + sizeof(T) <= CACHELINE_SIZE, 1)) + { + do_normal_load: + return *ptr; + } + // If alignment on T is necessary, but we're unaligned, yet we fit + // entirely in this cacheline... do the unaligned load dance. + else if (__builtin_expect (strict_alignment<T>::value + && iofs + sizeof(T) <= CACHELINE_SIZE, 1)) + { + do_unaligned_load: + return unaligned_load<T>(ptr); + } + // Otherwise, this load will span multiple cachelines. + else + { + // Get the following cacheline for the rest of the data. + const gtm_cacheline *line2 = disp->read_lock(pline + 1, lock); + + // If the two cachelines are adjacent, just load it all in one + // swoop. + if (line2 == line + 1) + { + if (!strict_alignment<T>::value) + goto do_normal_load; + else + goto do_unaligned_load; + } + else + { + // Otherwise, ask the backend to load from two different + // cachelines. + return unaligned_load2<T>(line, line2, iofs); + } + } +} + +template<typename T> +void do_write (T *ptr, T val, abi_dispatch::lock_type lock) +{ + // Note: See comments for do_read() above for hints on this + // function. Ideally we should abstract out a lot out of these two + // functions, and avoid all this duplication. + + abi_dispatch *disp = abi_disp(); + uintptr_t iptr = reinterpret_cast<uintptr_t>(ptr); + uintptr_t iline = iptr & -CACHELINE_SIZE; + uintptr_t iofs = iptr & (CACHELINE_SIZE - 1); + gtm_cacheline *pline = reinterpret_cast<gtm_cacheline *>(iline); + gtm_cacheline_mask m = ((gtm_cacheline_mask)2 << (sizeof(T) - 1)) - 1; + abi_dispatch::mask_pair pair = disp->write_lock(pline, lock); + + ptr = reinterpret_cast<T *>(&pair.line->b[iofs]); + + if (__builtin_expect (strict_alignment<T>::value + ? (iofs & (sizeof (val) - 1)) == 0 + : iofs + sizeof(val) <= CACHELINE_SIZE, 1)) + { + *pair.mask |= m << iofs; + do_normal_store: + *ptr = val; + } + else if (__builtin_expect (strict_alignment<T>::value + && iofs + sizeof(val) <= CACHELINE_SIZE, 1)) + { + *pair.mask |= m << iofs; + do_unaligned_store: + unaligned_store<T>(ptr, val); + } + else + { + *pair.mask |= m << iofs; + abi_dispatch::mask_pair pair2 = disp->write_lock(pline + 1, lock); + + uintptr_t ileft = CACHELINE_SIZE - iofs; + *pair2.mask |= m >> ileft; + + if (pair2.line == pair.line + 1) + { + if (!strict_alignment<T>::value) + goto do_normal_store; + else + goto do_unaligned_store; + } + else + unaligned_store2<T>(pair.line, pair2.line, iofs, val); + } +} + +} /* anonymous namespace */ + +#define ITM_READ(T, LOCK) \ + _ITM_TYPE_##T ITM_REGPARM _ITM_##LOCK##T (const _ITM_TYPE_##T *ptr) \ + { \ + return do_read (ptr, abi_dispatch::LOCK); \ + } + +#define ITM_WRITE(T, LOCK) \ + void ITM_REGPARM _ITM_##LOCK##T (_ITM_TYPE_##T *ptr, _ITM_TYPE_##T val) \ + { \ + do_write (ptr, val, abi_dispatch::LOCK); \ + } + +#define ITM_BARRIERS(T) \ + ITM_READ(T, R) \ + ITM_READ(T, RaR) \ + ITM_READ(T, RaW) \ + ITM_READ(T, RfW) \ + ITM_WRITE(T, W) \ + ITM_WRITE(T, WaR) \ + ITM_WRITE(T, WaW) diff --git a/libitm/beginend.cc b/libitm/beginend.cc new file mode 100644 index 00000000000..a26697567a3 --- /dev/null +++ b/libitm/beginend.cc @@ -0,0 +1,536 @@ +/* Copyright (C) 2008, 2009, 2011 Free Software Foundation, Inc. + Contributed by Richard Henderson <rth@redhat.com>. + + This file is part of the GNU Transactional Memory Library (libitm). + + Libitm is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + Libitm is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + <http://www.gnu.org/licenses/>. */ + +#include "libitm_i.h" +#include <pthread.h> + + +using namespace GTM; + +#if !defined(HAVE_ARCH_GTM_THREAD) || !defined(HAVE_ARCH_GTM_THREAD_DISP) +extern __thread gtm_thread_tls _gtm_thr_tls; +#endif + +gtm_rwlock GTM::gtm_thread::serial_lock; +gtm_thread *GTM::gtm_thread::list_of_threads = 0; +unsigned GTM::gtm_thread::number_of_threads = 0; + +gtm_stmlock GTM::gtm_stmlock_array[LOCK_ARRAY_SIZE]; +gtm_version GTM::gtm_clock; + +/* ??? Move elsewhere when we figure out library initialization. */ +uint64_t GTM::gtm_spin_count_var = 1000; + +static _ITM_transactionId_t global_tid; + +// Provides a on-thread-exit callback used to release per-thread data. +static pthread_key_t thr_release_key; +static pthread_once_t thr_release_once = PTHREAD_ONCE_INIT; + + +/* Allocate a transaction structure. */ +void * +GTM::gtm_thread::operator new (size_t s) +{ + void *tx; + + assert(s == sizeof(gtm_thread)); + + tx = xmalloc (sizeof (gtm_thread), true); + memset (tx, 0, sizeof (gtm_thread)); + + return tx; +} + +/* Free the given transaction. Raises an error if the transaction is still + in use. */ +void +GTM::gtm_thread::operator delete(void *tx) +{ + free(tx); +} + +static void +thread_exit_handler(void *) +{ + gtm_thread *thr = gtm_thr(); + if (thr) + delete thr; + set_gtm_thr(0); +} + +static void +thread_exit_init() +{ + if (pthread_key_create(&thr_release_key, thread_exit_handler)) + GTM_fatal("Creating thread release TLS key failed."); +} + + +GTM::gtm_thread::~gtm_thread() +{ + if (nesting > 0) + GTM_fatal("Thread exit while a transaction is still active."); + + // Deregister this transaction. + serial_lock.write_lock (); + gtm_thread **prev = &list_of_threads; + for (; *prev; prev = &(*prev)->next_thread) + { + if (*prev == this) + { + *prev = (*prev)->next_thread; + break; + } + } + number_of_threads--; + number_of_threads_changed(number_of_threads + 1, number_of_threads); + serial_lock.write_unlock (); +} + +GTM::gtm_thread::gtm_thread () +{ + // This object's memory has been set to zero by operator new, so no need + // to initialize any of the other primitive-type members that do not have + // constructors. + shared_state = ~(typeof shared_state)0; + + // Register this transaction with the list of all threads' transactions. + serial_lock.write_lock (); + next_thread = list_of_threads; + list_of_threads = this; + number_of_threads++; + number_of_threads_changed(number_of_threads - 1, number_of_threads); + serial_lock.write_unlock (); + + if (pthread_once(&thr_release_once, thread_exit_init)) + GTM_fatal("Initializing thread release TLS key failed."); + // Any non-null value is sufficient to trigger destruction of this + // transaction when the current thread terminates. + if (pthread_setspecific(thr_release_key, this)) + GTM_fatal("Setting thread release TLS key failed."); +} + + + +#ifndef HAVE_64BIT_SYNC_BUILTINS +static pthread_mutex_t global_tid_lock = PTHREAD_MUTEX_INITIALIZER; +#endif + +static inline uint32_t choose_code_path(uint32_t prop, abi_dispatch *disp) +{ + if ((prop & pr_uninstrumentedCode) && disp->can_run_uninstrumented_code()) + return a_runUninstrumentedCode; + else + return a_runInstrumentedCode; +} + +uint32_t +GTM::gtm_thread::begin_transaction (uint32_t prop, const gtm_jmpbuf *jb) +{ + static const _ITM_transactionId_t tid_block_size = 1 << 16; + + gtm_thread *tx; + abi_dispatch *disp; + uint32_t ret; + + // ??? pr_undoLogCode is not properly defined in the ABI. Are barriers + // omitted because they are not necessary (e.g., a transaction on thread- + // local data) or because the compiler thinks that some kind of global + // synchronization might perform better? + if (unlikely(prop & pr_undoLogCode)) + GTM_fatal("pr_undoLogCode not supported"); + + tx = gtm_thr(); + if (unlikely(tx == NULL)) + { + // Create the thread object. The constructor will also set up automatic + // deletion on thread termination. + tx = new gtm_thread(); + set_gtm_thr(tx); + } + + if (tx->nesting > 0) + { + // This is a nested transaction. + // Check prop compatibility: + // The ABI requires pr_hasNoFloatUpdate, pr_hasNoVectorUpdate, + // pr_hasNoIrrevocable, pr_aWBarriersOmitted, pr_RaRBarriersOmitted, and + // pr_hasNoSimpleReads to hold for the full dynamic scope of a + // transaction. We could check that these are set for the nested + // transaction if they are also set for the parent transaction, but the + // ABI does not require these flags to be set if they could be set, + // so the check could be too strict. + // ??? For pr_readOnly, lexical or dynamic scope is unspecified. + + if (prop & pr_hasNoAbort) + { + // We can use flat nesting, so elide this transaction. + if (!(prop & pr_instrumentedCode)) + { + if (!(tx->state & STATE_SERIAL) || + !(tx->state & STATE_IRREVOCABLE)) + tx->serialirr_mode(); + } + // Increment nesting level after checking that we have a method that + // allows us to continue. + tx->nesting++; + return choose_code_path(prop, abi_disp()); + } + + // The transaction might abort, so use closed nesting if possible. + // pr_hasNoAbort has lexical scope, so the compiler should really have + // generated an instrumented code path. + assert(prop & pr_instrumentedCode); + + // Create a checkpoint of the current transaction. + gtm_transaction_cp *cp = tx->parent_txns.push(); + cp->save(tx); + new (&tx->alloc_actions) aa_tree<uintptr_t, gtm_alloc_action>(); + + // Check whether the current method actually supports closed nesting. + // If we can switch to another one, do so. + // If not, we assume that actual aborts are infrequent, and rather + // restart in _ITM_abortTransaction when we really have to. + disp = abi_disp(); + if (!disp->closed_nesting()) + { + // ??? Should we elide the transaction if there is no alternative + // method that supports closed nesting? If we do, we need to set + // some flag to prevent _ITM_abortTransaction from aborting the + // wrong transaction (i.e., some parent transaction). + abi_dispatch *cn_disp = disp->closed_nesting_alternative(); + if (cn_disp) + { + disp = cn_disp; + set_abi_disp(disp); + } + } + } + else + { + // Outermost transaction + disp = tx->decide_begin_dispatch (prop); + if (disp == dispatch_serialirr() || disp == dispatch_serial()) + { + tx->state = STATE_SERIAL; + if (disp == dispatch_serialirr()) + tx->state |= STATE_IRREVOCABLE; + serial_lock.write_lock (); + } + else + serial_lock.read_lock (tx); + + set_abi_disp (disp); + } + + // Initialization that is common for outermost and nested transactions. + tx->prop = prop; + tx->nesting++; + + tx->jb = *jb; + + // As long as we have not exhausted a previously allocated block of TIDs, + // we can avoid an atomic operation on a shared cacheline. + if (tx->local_tid & (tid_block_size - 1)) + tx->id = tx->local_tid++; + else + { +#ifdef HAVE_64BIT_SYNC_BUILTINS + tx->id = __sync_add_and_fetch (&global_tid, tid_block_size); + tx->local_tid = tx->id + 1; +#else + pthread_mutex_lock (&global_tid_lock); + global_tid += tid_block_size; + tx->id = global_tid; + tx->local_tid = tx->id + 1; + pthread_mutex_unlock (&global_tid_lock); +#endif + } + + // Run dispatch-specific restart code. Retry until we succeed. + GTM::gtm_restart_reason rr; + while ((rr = disp->begin_or_restart()) != NO_RESTART) + { + tx->decide_retry_strategy(rr); + disp = abi_disp(); + } + + // Determine the code path to run. Only irrevocable transactions cannot be + // restarted, so all other transactions need to save live variables. + ret = choose_code_path(prop, disp); + if (!(tx->state & STATE_IRREVOCABLE)) + ret |= a_saveLiveVariables; + return ret; +} + + +void +GTM::gtm_transaction_cp::save(gtm_thread* tx) +{ + // Save everything that we might have to restore on restarts or aborts. + jb = tx->jb; + undolog_size = tx->undolog.size(); + memcpy(&alloc_actions, &tx->alloc_actions, sizeof(alloc_actions)); + user_actions_size = tx->user_actions.size(); + id = tx->id; + prop = tx->prop; + cxa_catch_count = tx->cxa_catch_count; + cxa_unthrown = tx->cxa_unthrown; + disp = abi_disp(); + nesting = tx->nesting; +} + +void +GTM::gtm_transaction_cp::commit(gtm_thread* tx) +{ + // Restore state that is not persistent across commits. Exception handling, + // information, nesting level, and any logs do not need to be restored on + // commits of nested transactions. Allocation actions must be committed + // before committing the snapshot. + tx->jb = jb; + memcpy(&tx->alloc_actions, &alloc_actions, sizeof(alloc_actions)); + tx->id = id; + tx->prop = prop; +} + + +void +GTM::gtm_thread::rollback (gtm_transaction_cp *cp, bool aborting) +{ + // The undo log is special in that it used for both thread-local and shared + // data. Because of the latter, we have to roll it back before any + // dispatch-specific rollback (which handles synchronization with other + // transactions). + rollback_undolog (cp ? cp->undolog_size : 0); + + // Perform dispatch-specific rollback. + abi_disp()->rollback (cp); + + // Roll back all actions that are supposed to happen around the transaction. + rollback_user_actions (cp ? cp->user_actions_size : 0); + commit_allocations (true, (cp ? &cp->alloc_actions : 0)); + revert_cpp_exceptions (cp); + + if (cp) + { + // We do not yet handle restarts of nested transactions. To do that, we + // would have to restore some state (jb, id, prop, nesting) not to the + // checkpoint but to the transaction that was started from this + // checkpoint (e.g., nesting = cp->nesting + 1); + assert(aborting); + // Roll back the rest of the state to the checkpoint. + jb = cp->jb; + id = cp->id; + prop = cp->prop; + if (cp->disp != abi_disp()) + set_abi_disp(cp->disp); + memcpy(&alloc_actions, &cp->alloc_actions, sizeof(alloc_actions)); + nesting = cp->nesting; + } + else + { + // Roll back to the outermost transaction. + // Restore the jump buffer and transaction properties, which we will + // need for the longjmp used to restart or abort the transaction. + if (parent_txns.size() > 0) + { + jb = parent_txns[0].jb; + id = parent_txns[0].id; + prop = parent_txns[0].prop; + } + // Reset the transaction. Do not reset this->state, which is handled by + // the callers. Note that if we are not aborting, we reset the + // transaction to the point after having executed begin_transaction + // (we will return from it), so the nesting level must be one, not zero. + nesting = (aborting ? 0 : 1); + parent_txns.clear(); + } + + if (this->eh_in_flight) + { + _Unwind_DeleteException ((_Unwind_Exception *) this->eh_in_flight); + this->eh_in_flight = NULL; + } +} + +void ITM_REGPARM +_ITM_abortTransaction (_ITM_abortReason reason) +{ + gtm_thread *tx = gtm_thr(); + + assert (reason == userAbort || reason == (userAbort | outerAbort)); + assert ((tx->prop & pr_hasNoAbort) == 0); + + if (tx->state & gtm_thread::STATE_IRREVOCABLE) + abort (); + + // Roll back to innermost transaction. + if (tx->parent_txns.size() > 0 && !(reason & outerAbort)) + { + // If the current method does not support closed nesting but we are + // nested and must only roll back the innermost transaction, then + // restart with a method that supports closed nesting. + abi_dispatch *disp = abi_disp(); + if (!disp->closed_nesting()) + tx->restart(RESTART_CLOSED_NESTING); + + // The innermost transaction is a closed nested transaction. + gtm_transaction_cp *cp = tx->parent_txns.pop(); + uint32_t longjmp_prop = tx->prop; + gtm_jmpbuf longjmp_jb = tx->jb; + + tx->rollback (cp, true); + + // Jump to nested transaction (use the saved jump buffer). + GTM_longjmp (&longjmp_jb, a_abortTransaction | a_restoreLiveVariables, + longjmp_prop); + } + else + { + // There is no nested transaction or an abort of the outermost + // transaction was requested, so roll back to the outermost transaction. + tx->rollback (0, true); + + // Aborting an outermost transaction finishes execution of the whole + // transaction. Therefore, reset transaction state. + if (tx->state & gtm_thread::STATE_SERIAL) + gtm_thread::serial_lock.write_unlock (); + else + gtm_thread::serial_lock.read_unlock (tx); + tx->state = 0; + + GTM_longjmp (&tx->jb, a_abortTransaction | a_restoreLiveVariables, + tx->prop); + } +} + +bool +GTM::gtm_thread::trycommit () +{ + nesting--; + + // Skip any real commit for elided transactions. + if (nesting > 0 && (parent_txns.size() == 0 || + nesting > parent_txns[parent_txns.size() - 1].nesting)) + return true; + + if (nesting > 0) + { + // Commit of a closed-nested transaction. Remove one checkpoint and add + // any effects of this transaction to the parent transaction. + gtm_transaction_cp *cp = parent_txns.pop(); + commit_allocations(false, &cp->alloc_actions); + cp->commit(this); + return true; + } + + // Commit of an outermost transaction. + gtm_word priv_time = 0; + if (abi_disp()->trycommit (priv_time)) + { + // The transaction is now inactive. Everything that we still have to do + // will not synchronize with other transactions anymore. + if (state & gtm_thread::STATE_SERIAL) + gtm_thread::serial_lock.write_unlock (); + else + gtm_thread::serial_lock.read_unlock (this); + state = 0; + + // We can commit the undo log after dispatch-specific commit and after + // making the transaction inactive because we only have to reset + // gtm_thread state. + commit_undolog (); + // Reset further transaction state. + cxa_catch_count = 0; + cxa_unthrown = NULL; + restart_total = 0; + + // Ensure privatization safety, if necessary. + if (priv_time) + { + // TODO Don't just spin but also block using cond vars / futexes + // here. Should probably be integrated with the serial lock code. + // TODO For C++0x atomics, the loads of other threads' shared_state + // should have acquire semantics (together with releases for the + // respective updates). But is this unnecessary overhead because + // weaker barriers are sufficient? + for (gtm_thread *it = gtm_thread::list_of_threads; it != 0; + it = it->next_thread) + { + if (it == this) continue; + while (it->shared_state < priv_time) + cpu_relax(); + } + } + + // After ensuring privatization safety, we execute potentially + // privatizing actions (e.g., calling free()). User actions are first. + commit_user_actions (); + commit_allocations (false, 0); + + return true; + } + return false; +} + +void ITM_NORETURN +GTM::gtm_thread::restart (gtm_restart_reason r) +{ + // Roll back to outermost transaction. Do not reset transaction state because + // we will continue executing this transaction. + rollback (); + decide_retry_strategy (r); + + // Run dispatch-specific restart code. Retry until we succeed. + abi_dispatch* disp = abi_disp(); + GTM::gtm_restart_reason rr; + while ((rr = disp->begin_or_restart()) != NO_RESTART) + { + decide_retry_strategy(rr); + disp = abi_disp(); + } + + GTM_longjmp (&jb, + choose_code_path(prop, disp) | a_restoreLiveVariables, prop); +} + +void ITM_REGPARM +_ITM_commitTransaction(void) +{ + gtm_thread *tx = gtm_thr(); + if (!tx->trycommit ()) + tx->restart (RESTART_VALIDATE_COMMIT); +} + +void ITM_REGPARM +_ITM_commitTransactionEH(void *exc_ptr) +{ + gtm_thread *tx = gtm_thr(); + if (!tx->trycommit ()) + { + tx->eh_in_flight = exc_ptr; + tx->restart (RESTART_VALIDATE_COMMIT); + } +} diff --git a/libitm/clone.cc b/libitm/clone.cc new file mode 100644 index 00000000000..cfb7f40850f --- /dev/null +++ b/libitm/clone.cc @@ -0,0 +1,184 @@ +/* Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc. + Contributed by Richard Henderson <rth@redhat.com>. + + This file is part of the GNU Transactional Memory Library (libitm). + + Libitm is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + Libitm is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + <http://www.gnu.org/licenses/>. */ + +#include "libitm_i.h" + +using namespace GTM; + +struct clone_entry +{ + void *orig, *clone; +}; + +struct clone_table +{ + clone_entry *table; + size_t size; + clone_table *next; +}; + +static clone_table *all_tables; + +static void * +find_clone (void *ptr) +{ + clone_table *table; + + for (table = all_tables; table ; table = table->next) + { + clone_entry *t = table->table; + size_t lo = 0, hi = table->size, i; + + /* Quick test for whether PTR is present in this table. */ + if (ptr < t[0].orig || ptr > t[hi - 1].orig) + continue; + + /* Otherwise binary search. */ + while (lo < hi) + { + i = (lo + hi) / 2; + if (ptr < t[i].orig) + hi = i; + else if (ptr > t[i].orig) + lo = i + 1; + else + return t[i].clone; + } + + /* Given the quick test above, if we don't find the entry in + this table then it doesn't exist. */ + break; + } + + return NULL; +} + + +void * ITM_REGPARM +_ITM_getTMCloneOrIrrevocable (void *ptr) +{ + void *ret = find_clone (ptr); + if (ret) + return ret; + + gtm_thr()->serialirr_mode (); + + return ptr; +} + +void * ITM_REGPARM +_ITM_getTMCloneSafe (void *ptr) +{ + void *ret = find_clone (ptr); + if (ret == NULL) + abort (); + return ret; +} + +static int +clone_entry_compare (const void *a, const void *b) +{ + const clone_entry *aa = (const clone_entry *)a; + const clone_entry *bb = (const clone_entry *)b; + + if (aa->orig < bb->orig) + return -1; + else if (aa->orig > bb->orig) + return 1; + else + return 0; +} + +namespace { + +// Within find_clone, we know that we are inside a transaction. Because +// of that, we have already synchronized with serial_lock. By taking the +// serial_lock for write, we exclude all transactions while we make this +// change to the clone tables, without having to synchronize on a separate +// lock. Do be careful not to attempt a recursive write lock. + +class ExcludeTransaction +{ + bool do_lock; + + public: + ExcludeTransaction() + { + gtm_thread *tx = gtm_thr(); + do_lock = !(tx && (tx->state & gtm_thread::STATE_SERIAL)); + + if (do_lock) + gtm_thread::serial_lock.write_lock (); + } + + ~ExcludeTransaction() + { + if (do_lock) + gtm_thread::serial_lock.write_unlock (); + } +}; + +} // end anon namespace + + +void +_ITM_registerTMCloneTable (void *xent, size_t size) +{ + clone_entry *ent = static_cast<clone_entry *>(xent); + clone_table *table; + + table = (clone_table *) xmalloc (sizeof (clone_table)); + table->table = ent; + table->size = size; + + qsort (ent, size, sizeof (clone_entry), clone_entry_compare); + + // Hold the serial_lock while we update the ALL_TABLES datastructure. + { + ExcludeTransaction exclude; + table->next = all_tables; + all_tables = table; + } +} + +void +_ITM_deregisterTMCloneTable (void *xent) +{ + clone_entry *ent = static_cast<clone_entry *>(xent); + clone_table *tab; + + // Hold the serial_lock while we update the ALL_TABLES datastructure. + { + ExcludeTransaction exclude; + clone_table **pprev; + + for (pprev = &all_tables; + tab = *pprev, tab->table != ent; + pprev = &tab->next) + continue; + *pprev = tab->next; + } + + free (tab); +} diff --git a/libitm/common.h b/libitm/common.h new file mode 100644 index 00000000000..14d0efb40ba --- /dev/null +++ b/libitm/common.h @@ -0,0 +1,63 @@ +/* Copyright (C) 2008, 2009, 2011 Free Software Foundation, Inc. + Contributed by Richard Henderson <rth@redhat.com>. + + This file is part of the GNU Transactional Memory Library (libitm). + + Libitm is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + Libitm is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + <http://www.gnu.org/licenses/>. */ + +/* The following are internal implementation functions and definitions. + To distinguish them from those defined by the Intel ABI, they all + begin with GTM/gtm. */ + +#ifndef COMMON_H +#define COMMON_H 1 + +#define UNUSED __attribute__((unused)) +#define ALWAYS_INLINE __attribute__((always_inline)) +#ifdef HAVE_ATTRIBUTE_VISIBILITY +# define HIDDEN __attribute__((visibility("hidden"))) +#else +# define HIDDEN +#endif + +#define likely(X) __builtin_expect((X) != 0, 1) +#define unlikely(X) __builtin_expect((X), 0) + +namespace GTM HIDDEN { + +// Locally defined protected allocation functions. +// +// To avoid dependency on libstdc++ new/delete, as well as to not +// interfere with the wrapping of the global new/delete we wrap for +// the user in alloc_cpp.cc, use class-local versions that defer +// to malloc/free. Recall that operator new/delete does not go through +// normal lookup and so we cannot simply inject a version into the +// GTM namespace. +// If separate_cl is true, the allocator will try to return memory that is on +// cache lines that are not shared with any object used by another thread. +extern void * xmalloc (size_t s, bool separate_cl = false) + __attribute__((malloc, nothrow)); +extern void * xrealloc (void *p, size_t s, bool separate_cl = false) + __attribute__((malloc, nothrow)); + +} // namespace GTM + + +#endif // COMMON_H diff --git a/libitm/config.h.in b/libitm/config.h.in new file mode 100644 index 00000000000..af13264db69 --- /dev/null +++ b/libitm/config.h.in @@ -0,0 +1,159 @@ +/* config.h.in. Generated from configure.ac by autoheader. */ + +/* Define if building universal (internal helper macro) */ +#undef AC_APPLE_UNIVERSAL_BUILD + +/* Define to 1 if the target supports 64-bit __sync_*_compare_and_swap */ +#undef HAVE_64BIT_SYNC_BUILTINS + +/* Define to 1 if the target supports __attribute__((alias(...))). */ +#undef HAVE_ATTRIBUTE_ALIAS + +/* Define to 1 if the target supports __attribute__((dllexport)). */ +#undef HAVE_ATTRIBUTE_DLLEXPORT + +/* Define to 1 if the target supports __attribute__((visibility(...))). */ +#undef HAVE_ATTRIBUTE_VISIBILITY + +/* Define if the POSIX Semaphores do not work on your system. */ +#undef HAVE_BROKEN_POSIX_SEMAPHORES + +/* Define to 1 if the target assembler supports thread-local storage. */ +#undef HAVE_CC_TLS + +/* Define to 1 if you have the <dlfcn.h> header file. */ +#undef HAVE_DLFCN_H + +/* Define to 1 if you have the <inttypes.h> header file. */ +#undef HAVE_INTTYPES_H + +/* Define to 1 if you have the <malloc.h> header file. */ +#undef HAVE_MALLOC_H + +/* Define to 1 if you have the `memalign' function. */ +#undef HAVE_MEMALIGN + +/* Define to 1 if you have the <memory.h> header file. */ +#undef HAVE_MEMORY_H + +/* Define if mmap with MAP_ANON(YMOUS) works. */ +#undef HAVE_MMAP_ANON + +/* Define if mmap of /dev/zero works. */ +#undef HAVE_MMAP_DEV_ZERO + +/* Define if read-only mmap of a plain file works. */ +#undef HAVE_MMAP_FILE + +/* Define to 1 if you have the `posix_memalign' function. */ +#undef HAVE_POSIX_MEMALIGN + +/* Define to 1 if you have the <semaphore.h> header file. */ +#undef HAVE_SEMAPHORE_H + +/* Define to 1 if you have the <stdint.h> header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the <stdlib.h> header file. */ +#undef HAVE_STDLIB_H + +/* Define to 1 if you have the <strings.h> header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the <string.h> header file. */ +#undef HAVE_STRING_H + +/* Define to 1 if you have the `strtoull' function. */ +#undef HAVE_STRTOULL + +/* Define to 1 if the target supports __sync_*_compare_and_swap */ +#undef HAVE_SYNC_BUILTINS + +/* Define to 1 if you have the <sys/stat.h> header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the <sys/time.h> header file. */ +#undef HAVE_SYS_TIME_H + +/* Define to 1 if you have the <sys/types.h> header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define to 1 if the target supports thread-local storage. */ +#undef HAVE_TLS + +/* Define to 1 if you have the <unistd.h> header file. */ +#undef HAVE_UNISTD_H + +/* Define to 1 if GNU symbol versioning is used for libitm. */ +#undef LIBITM_GNU_SYMBOL_VERSIONING + +/* Define to the sub-directory in which libtool stores uninstalled libraries. + */ +#undef LT_OBJDIR + +/* Define to the letter to which size_t is mangled. */ +#undef MANGLE_SIZE_T + +/* Name of package */ +#undef PACKAGE + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the home page for this package. */ +#undef PACKAGE_URL + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION + +/* The size of `char', as computed by sizeof. */ +#undef SIZEOF_CHAR + +/* The size of `int', as computed by sizeof. */ +#undef SIZEOF_INT + +/* The size of `long', as computed by sizeof. */ +#undef SIZEOF_LONG + +/* The size of `short', as computed by sizeof. */ +#undef SIZEOF_SHORT + +/* The size of `void *', as computed by sizeof. */ +#undef SIZEOF_VOID_P + +/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Define if you can safely include both <string.h> and <strings.h>. */ +#undef STRING_WITH_STRINGS + +/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */ +#undef TIME_WITH_SYS_TIME + +/* Version number of package */ +#undef VERSION + +/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most + significant byte first (like Motorola and SPARC, unlike Intel). */ +#if defined AC_APPLE_UNIVERSAL_BUILD +# if defined __BIG_ENDIAN__ +# define WORDS_BIGENDIAN 1 +# endif +#else +# ifndef WORDS_BIGENDIAN +# undef WORDS_BIGENDIAN +# endif +#endif + +#ifndef WORDS_BIGENDIAN +#define WORDS_BIGENDIAN 0 +#endif diff --git a/libitm/config/alpha/cacheline.h b/libitm/config/alpha/cacheline.h new file mode 100644 index 00000000000..5e38486b713 --- /dev/null +++ b/libitm/config/alpha/cacheline.h @@ -0,0 +1,122 @@ +/* Copyright (C) 2009, 2011 Free Software Foundation, Inc. + Contributed by Richard Henderson <rth@redhat.com>. + + This file is part of the GNU Transactional Memory Library (libitm). + + Libitm is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + Libitm is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + <http://www.gnu.org/licenses/>. */ + +#ifndef LIBITM_ALPHA_CACHELINE_H +#define LIBITM_ALPHA_CACHELINE_H 1 + +// A cacheline is the smallest unit with which locks are associated. +// The current implementation of the _ITM_[RW] barriers assumes that +// all data types can fit (aligned) within a cachline, which means +// in practice sizeof(complex long double) is the smallest cacheline size. +// It ought to be small enough for efficient manipulation of the +// modification mask, below. +#define CACHELINE_SIZE 64 + +#ifdef __alpha_bwx__ +# include "config/generic/cacheline.h" +#else +// If we don't have byte-word stores, then we'll never be able to +// adjust *all* of the byte loads/stores to be truely atomic. So +// only guarantee 4-byte aligned values atomicly stored, exactly +// like the native system. Use byte zap instructions to accelerate +// sub-word masked stores. + +namespace GTM HIDDEN { + +// A gtm_cacheline_mask stores a modified bit for every modified byte +// in the cacheline with which it is associated. +typedef sized_integral<CACHELINE_SIZE / 8>::type gtm_cacheline_mask; + +union gtm_cacheline +{ + // Byte access to the cacheline. + unsigned char b[CACHELINE_SIZE] __attribute__((aligned(CACHELINE_SIZE))); + + // Larger sized access to the cacheline. + uint16_t u16[CACHELINE_SIZE / sizeof(uint16_t)]; + uint32_t u32[CACHELINE_SIZE / sizeof(uint32_t)]; + uint64_t u64[CACHELINE_SIZE / sizeof(uint64_t)]; + gtm_word w[CACHELINE_SIZE / sizeof(gtm_word)]; + + // Store S into D, but only the bytes specified by M. + static void store_mask(uint32_t *d, uint32_t s, uint8_t m); + static void store_mask(uint64_t *d, uint64_t s, uint8_t m); + + // Copy S to D, but only the bytes specified by M. + static void copy_mask (gtm_cacheline * __restrict d, + const gtm_cacheline * __restrict s, + gtm_cacheline_mask m); + + // A write barrier to emit after (a series of) copy_mask. + static void copy_mask_wb () { atomic_write_barrier(); } +}; + +inline void ALWAYS_INLINE +gtm_cacheline::store_mask (uint32_t *d, uint32_t s, uint8_t m) +{ + const uint8_t tm = (1 << sizeof(uint32_t)) - 1; + + m &= tm; + if (__builtin_expect (m, tm)) + { + if (__builtin_expect (m == tm, 1)) + *d = s; + else + *d = __builtin_alpha_zap (*d, m) | __builtin_alpha_zapnot (s, m); + } +} + +inline void ALWAYS_INLINE +gtm_cacheline::store_mask (uint64_t *d, uint64_t s, uint8_t m) +{ + if (__builtin_expect (m, 0xff)) + { + if (__builtin_expect (m == 0xff, 1)) + *d = s; + else + { + typedef uint32_t *p32 __attribute__((may_alias)); + p32 d32 = reinterpret_cast<p32>(d); + + if ((m & 0x0f) == 0x0f) + { + d32[0] = s; + m &= 0xf0; + } + else if ((m & 0xf0) == 0xf0) + { + d32[1] = s >> 32; + m &= 0x0f; + } + + if (m) + *d = __builtin_alpha_zap (*d, m) | __builtin_alpha_zapnot (s, m); + } + } +} + +} // namespace GTM + +#endif // __alpha_bwx__ +#endif // LIBITM_ALPHA_CACHELINE_H diff --git a/libitm/config/alpha/sjlj.S b/libitm/config/alpha/sjlj.S new file mode 100644 index 00000000000..d60a82df62b --- /dev/null +++ b/libitm/config/alpha/sjlj.S @@ -0,0 +1,108 @@ +/* Copyright (C) 2009, 2011 Free Software Foundation, Inc. + Contributed by Richard Henderson <rth@redhat.com>. + + This file is part of the GNU Transactional Memory Library (libitm). + + Libitm is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + Libitm is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + <http://www.gnu.org/licenses/>. */ + + .text + .align 4 + .globl _ITM_beginTransaction + .ent _ITM_beginTransaction + +#define FRAME 144 + +_ITM_beginTransaction: + ldgp $29, 0($27) + subq $30, FRAME, $30 + .frame $30, FRAME, $26, 0 + .mask 0x04000000, 0 + stq $26, 0($30) + .prologue 1 + + stq $9, 8($30) + stq $10, 16($30) + addq $30, FRAME, $0 + stq $11, 24($30) + + stq $12, 32($30) + stq $13, 40($30) + stq $14, 48($30) + stq $15, 56($30) + + stq $0, 64($30) + stt $f2, 72($30) + stt $f3, 80($30) + stt $f4, 88($30) + + stt $f5, 96($30) + stt $f6, 104($30) + stt $f7, 112($30) + stt $f8, 120($30) + + stt $f9, 128($30) + mov $30, $17 +#ifdef __PIC__ + unop + bsr $26, GTM_begin_transaction !samegp +#else + jsr $26, GTM_begin_transaction + ldgp $29, 0($26) +#endif + + ldq $26, 0($30) + addq $30, FRAME, $30 + ret +.end _ITM_beginTransaction + + .align 4 + .globl GTM_longjmp + .hidden GTM_longjmp + .ent GTM_longjmp + +GTM_longjmp: + .prologue 0 + ldq $26, 0($16) + ldq $9, 8($16) + ldq $10, 16($16) + ldq $11, 24($16) + + ldq $12, 32($16) + ldq $13, 40($16) + ldq $14, 48($16) + ldq $15, 56($16) + + ldq $1, 64($16) + ldt $f2, 72($16) + ldt $f3, 80($16) + ldt $f4, 88($16) + + ldt $f5, 96($16) + ldt $f6, 104($16) + ldt $f7, 112($16) + ldt $f8, 120($16) + + ldt $f9, 128($16) + mov $17, $0 + mov $1, $30 + ret +.end GTM_longjmp + +.section .note.GNU-stack, "", @progbits diff --git a/libitm/config/alpha/target.h b/libitm/config/alpha/target.h new file mode 100644 index 00000000000..121546f5f52 --- /dev/null +++ b/libitm/config/alpha/target.h @@ -0,0 +1,60 @@ +/* Copyright (C) 2009, 2011 Free Software Foundation, Inc. + Contributed by Richard Henderson <rth@redhat.com>. + + This file is part of the GNU Transactional Memory Library (libitm). + + Libitm is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + Libitm is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + <http://www.gnu.org/licenses/>. */ + +namespace GTM HIDDEN { + +typedef struct gtm_jmpbuf +{ + unsigned long pc; + unsigned long s[7]; + void *cfa; + unsigned long f[8]; +} gtm_jmpbuf; + +/* Alpha generally uses a fixed page size of 8K. */ +#define PAGE_SIZE 8192 +#define FIXED_PAGE_SIZE 1 + +/* The size of one line in hardware caches (in bytes). */ +#define HW_CACHELINE_SIZE 64 + +static inline void +cpu_relax (void) +{ + __asm volatile ("" : : : "memory"); +} + +static inline void +atomic_read_barrier (void) +{ + __sync_synchronize (); +} + +static inline void +atomic_write_barrier (void) +{ + __asm volatile ("wmb" : : : "memory"); +} + +} // namespace GTM diff --git a/libitm/config/alpha/unaligned.h b/libitm/config/alpha/unaligned.h new file mode 100644 index 00000000000..3d091aee228 --- /dev/null +++ b/libitm/config/alpha/unaligned.h @@ -0,0 +1,118 @@ +/* Copyright (C) 2009, 2011 Free Software Foundation, Inc. + Contributed by Richard Henderson <rth@redhat.com>. + + This file is part of the GNU Transactional Memory Library (libitm). + + Libitm is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + Libitm is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + <http://www.gnu.org/licenses/>. */ + +#ifndef LIBITM_ALPHA_UNALIGNED_H +#define LIBITM_ALPHA_UNALIGNED_H 1 + +#define HAVE_ARCH_UNALIGNED_LOAD2_U2 1 +#define HAVE_ARCH_UNALIGNED_LOAD2_U4 1 +#define HAVE_ARCH_UNALIGNED_LOAD2_U8 1 + +#ifndef __alpha_bwx__ +#define HAVE_ARCH_UNALIGNED_STORE2_U2 1 +#endif +#define HAVE_ARCH_UNALIGNED_STORE2_U4 1 +#define HAVE_ARCH_UNALIGNED_STORE2_U8 1 + +#include "config/generic/unaligned.h" + +namespace GTM HIDDEN { + +template<> +inline uint16_t ALWAYS_INLINE +unaligned_load2<uint16_t>(const gtm_cacheline *c1, + const gtm_cacheline *c2, size_t ofs) +{ + uint64_t v1 = c1->u64[CACHELINE_SIZE / sizeof(uint64_t) - 1]; + uint64_t v2 = c2->u64[0]; + + return __builtin_alpha_extwl (v1, ofs) | __builtin_alpha_extwh (v2, ofs); +} + +template<> +inline uint32_t ALWAYS_INLINE +unaligned_load2<uint32_t>(const gtm_cacheline *c1, + const gtm_cacheline *c2, size_t ofs) +{ + uint64_t v1 = c1->u64[CACHELINE_SIZE / sizeof(uint64_t) - 1]; + uint64_t v2 = c2->u64[0]; + + return __builtin_alpha_extll (v1, ofs) + __builtin_alpha_extlh (v2, ofs); +} + +template<> +inline uint64_t ALWAYS_INLINE +unaligned_load2<uint64_t>(const gtm_cacheline *c1, + const gtm_cacheline *c2, size_t ofs) +{ + uint64_t v1 = c1->u64[CACHELINE_SIZE / sizeof(uint64_t) - 1]; + uint64_t v2 = c2->u64[0]; + + return __builtin_alpha_extql (v1, ofs) | __builtin_alpha_extqh (v2, ofs); +} + +#ifndef __alpha_bwx__ +template<> +inline void +unaligned_store2<uint16_t>(gtm_cacheline *c1, gtm_cacheline *c2, + size_t ofs, uint16_t val) +{ + uint32_t vl = (uint32_t)val << 24, vh = val >> 8; + + gtm_cacheline::store_mask (&c1->u32[CACHELINE_SIZE / 4 - 1], vl, 4); + gtm_cacheline::store_mask (&c2->u32[0], vh, 1); +} +#endif + +template<> +inline void +unaligned_store2<uint32_t>(gtm_cacheline *c1, gtm_cacheline *c2, + size_t ofs, uint32_t val) +{ + uint64_t vl = __builtin_alpha_insll (val, ofs); + uint64_t ml = __builtin_alpha_insll (~0u, ofs); + uint64_t vh = __builtin_alpha_inslh (val, ofs); + uint64_t mh = __builtin_alpha_inslh (~0u, ofs); + + gtm_cacheline::store_mask (&c1->u64[CACHELINE_SIZE / 8 - 1], vl, ml); + gtm_cacheline::store_mask (&c2->u64[0], vh, mh); +} + +template<> +inline void +unaligned_store2<uint64_t>(gtm_cacheline *c1, gtm_cacheline *c2, + size_t ofs, uint64_t val) +{ + uint64_t vl = __builtin_alpha_insql (val, ofs); + uint64_t ml = __builtin_alpha_insql (~0u, ofs); + uint64_t vh = __builtin_alpha_insqh (val, ofs); + uint64_t mh = __builtin_alpha_insqh (~0u, ofs); + + gtm_cacheline::store_mask (&c1->u64[CACHELINE_SIZE / 8 - 1], vl, ml); + gtm_cacheline::store_mask (&c2->u64[0], vh, mh); +} + +} // namespace GTM + +#endif // LIBITM_ALPHA_UNALIGNED_H diff --git a/libitm/config/generic/cacheline.cc b/libitm/config/generic/cacheline.cc new file mode 100644 index 00000000000..108ffba3037 --- /dev/null +++ b/libitm/config/generic/cacheline.cc @@ -0,0 +1,49 @@ +/* Copyright (C) 2009, 2011 Free Software Foundation, Inc. + Contributed by Richard Henderson <rth@redhat.com>. + + This file is part of the GNU Transactional Memory Library (libitm). + + Libitm is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + Libitm is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + <http://www.gnu.org/licenses/>. */ + +#include "libitm_i.h" + + +namespace GTM HIDDEN { + +void +gtm_cacheline::copy_mask (gtm_cacheline * __restrict d, + const gtm_cacheline * __restrict s, + gtm_cacheline_mask m) +{ + const size_t n = sizeof (gtm_word); + + if (m == (gtm_cacheline_mask) -1) + { + *d = *s; + return; + } + if (__builtin_expect (m == 0, 0)) + return; + + for (size_t i = 0; i < CACHELINE_SIZE / n; ++i, m >>= n) + store_mask (&d->w[i], s->w[i], m); +} + +} // namespace GTM diff --git a/libitm/config/generic/cacheline.h b/libitm/config/generic/cacheline.h new file mode 100644 index 00000000000..0a5af761d6e --- /dev/null +++ b/libitm/config/generic/cacheline.h @@ -0,0 +1,107 @@ +/* Copyright (C) 2009, 2011 Free Software Foundation, Inc. + Contributed by Richard Henderson <rth@redhat.com>. + + This file is part of the GNU Transactional Memory Library (libitm). + + Libitm is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + Libitm is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + <http://www.gnu.org/licenses/>. */ + +#ifndef LIBITM_CACHELINE_H +#define LIBITM_CACHELINE_H 1 + +namespace GTM HIDDEN { + +// A cacheline is the smallest unit with which locks are associated. +// The current implementation of the _ITM_[RW] barriers assumes that +// all data types can fit (aligned) within a cachline, which means +// in practice sizeof(complex long double) is the smallest cacheline size. +// It ought to be small enough for efficient manipulation of the +// modification mask, below. +#ifndef CACHELINE_SIZE +# define CACHELINE_SIZE 32 +#endif + +// A gtm_cacheline_mask stores a modified bit for every modified byte +// in the cacheline with which it is associated. +typedef sized_integral<CACHELINE_SIZE / 8>::type gtm_cacheline_mask; + +union gtm_cacheline +{ + // Byte access to the cacheline. + unsigned char b[CACHELINE_SIZE] __attribute__((aligned(CACHELINE_SIZE))); + + // Larger sized access to the cacheline. + uint16_t u16[CACHELINE_SIZE / sizeof(uint16_t)]; + uint32_t u32[CACHELINE_SIZE / sizeof(uint32_t)]; + uint64_t u64[CACHELINE_SIZE / sizeof(uint64_t)]; + gtm_word w[CACHELINE_SIZE / sizeof(gtm_word)]; + + // Store S into D, but only the bytes specified by M. + template<typename T> static void store_mask (T *d, T s, uint8_t m); + + // Copy S to D, but only the bytes specified by M. + static void copy_mask (gtm_cacheline * __restrict d, + const gtm_cacheline * __restrict s, + gtm_cacheline_mask m); + + // A write barrier to emit after (a series of) copy_mask. + // When we're emitting non-temporal stores, the normal strong + // ordering of the machine doesn't apply. + static void copy_mask_wb () { atomic_write_barrier(); } +}; + +template<typename T> +inline void +gtm_cacheline::store_mask (T *d, T s, uint8_t m) +{ + const uint8_t tm = (1 << sizeof(T)) - 1; + + if (__builtin_expect (m & tm, tm)) + { + if (__builtin_expect ((m & tm) == tm, 1)) + *d = s; + else + { + const int half = sizeof(T) / 2; + typedef typename sized_integral<half>::type half_t; + half_t *dhalf = reinterpret_cast<half_t *>(d); + half_t s1, s2; + + if (WORDS_BIGENDIAN) + s1 = s >> half*8, s2 = s; + else + s1 = s, s2 = s >> half*8; + + store_mask (dhalf, s1, m); + store_mask (dhalf + 1, s2, m >> half); + } + } +} + +template<> +inline void ALWAYS_INLINE +gtm_cacheline::store_mask<uint8_t> (uint8_t *d, uint8_t s, uint8_t m) +{ + if (m & 1) + *d = s; +} + +} // namespace GTM + +#endif // LIBITM_CACHELINE_H diff --git a/libitm/config/generic/cachepage.h b/libitm/config/generic/cachepage.h new file mode 100644 index 00000000000..a5472f3831b --- /dev/null +++ b/libitm/config/generic/cachepage.h @@ -0,0 +1,77 @@ +/* Copyright (C) 2009, 2011 Free Software Foundation, Inc. + Contributed by Richard Henderson <rth@redhat.com>. + + This file is part of the GNU Transactional Memory Library (libitm). + + Libitm is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + Libitm is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + <http://www.gnu.org/licenses/>. */ + +#ifndef LIBITM_CACHEPAGE_H +#define LIBITM_CACHEPAGE_H 1 + +namespace GTM HIDDEN { + +// A "page" worth of saved cachelines plus modification masks. This +// arrangement is intended to minimize the overhead of alignment. The +// PAGE_SIZE defined by the target must be a constant for this to work, +// which means that this definition may not be the same as the real +// system page size. An additional define of FIXED_PAGE_SIZE by the +// target indicates that PAGE_SIZE exactly matches the system page size. + +#ifndef PAGE_SIZE +#define PAGE_SIZE 4096 +#endif + +struct gtm_cacheline_page +{ + static const size_t LINES + = ((PAGE_SIZE - sizeof(gtm_cacheline_page *)) + / (CACHELINE_SIZE + sizeof(gtm_cacheline_mask))); + + gtm_cacheline lines[LINES] __attribute__((aligned(PAGE_SIZE))); + gtm_cacheline_mask masks[LINES]; + gtm_cacheline_page *prev; + + static gtm_cacheline_page * + page_for_line (gtm_cacheline *c) + { + return (gtm_cacheline_page *)((uintptr_t)c & -PAGE_SIZE); + } + + gtm_cacheline_mask * + mask_for_line (gtm_cacheline *c) + { + size_t index = c - &this->lines[0]; + return &this->masks[index]; + } + + static gtm_cacheline_mask * + mask_for_page_line (gtm_cacheline *c) + { + gtm_cacheline_page *p = page_for_line (c); + return p->mask_for_line (c); + } + + static void *operator new (size_t); + static void operator delete (void *); +}; + +} // namespace GTM + +#endif // LIBITM_CACHEPAGE_H diff --git a/libitm/config/generic/tls.cc b/libitm/config/generic/tls.cc new file mode 100644 index 00000000000..3e82cff0902 --- /dev/null +++ b/libitm/config/generic/tls.cc @@ -0,0 +1,76 @@ +/* Copyright (C) 2010, 2011 Free Software Foundation, Inc. + Contributed by Richard Henderson <rth@redhat.com>. + + This file is part of the GNU Transactional Memory Library (libitm). + + Libitm is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + Libitm is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + <http://www.gnu.org/licenses/>. */ + +#include "libitm_i.h" + +namespace GTM HIDDEN { + +// Filter out any updates that overlap the libitm stack, as defined by +// TOP (entry point to library) and BOT (below current function). This +// definition should be fine for all stack-grows-down architectures. + +gtm_cacheline_mask __attribute__((noinline)) +gtm_mask_stack(gtm_cacheline *line, gtm_cacheline_mask mask) +{ + void *top = gtm_thr()->jb.cfa; + void *bot = __builtin_dwarf_cfa(); + + // We must have come through an entry point that set TOP. + assert (top != NULL); + + if (line + 1 < bot) + { + // Since we don't have the REAL stack boundaries for this thread, + // we cannot know if this is a dead write to a stack address below + // the current function or if it is write to another VMA. In either + // case allowing the write should not affect correctness. + } + else if (line >= top) + { + // A valid write to an address in an outer stack frame, or a write + // to another VMA. + } + else + { + uintptr_t diff = (uintptr_t)top - (uintptr_t)line; + if (diff >= CACHELINE_SIZE) + { + // The write is either fully within the proscribed area, or the tail + // of the cacheline overlaps the proscribed area. Assume that all + // stacks are at least cacheline aligned and declare the head of the + // cacheline dead. + mask = 0; + } + else + { + // The head of the cacheline is within the proscribed area, but the + // tail of the cacheline is live. Eliminate the dead writes. + mask &= (gtm_cacheline_mask)-1 << diff; + } + } + + return mask; +} + +} // namespace GTM diff --git a/libitm/config/generic/tls.h b/libitm/config/generic/tls.h new file mode 100644 index 00000000000..e282e54817b --- /dev/null +++ b/libitm/config/generic/tls.h @@ -0,0 +1,65 @@ +/* Copyright (C) 2008, 2009, 2011 Free Software Foundation, Inc. + Contributed by Richard Henderson <rth@redhat.com>. + + This file is part of the GNU Transactional Memory Library (libitm). + + Libitm is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + Libitm is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + <http://www.gnu.org/licenses/>. */ + +#ifndef LIBITM_TLS_H +#define LIBITM_TLS_H 1 + +namespace GTM HIDDEN { + +#if !defined(HAVE_ARCH_GTM_THREAD) || !defined(HAVE_ARCH_GTM_THREAD_DISP) +// Provides a single place to store all this libraries thread-local data. +struct gtm_thread_tls +{ +#ifndef HAVE_ARCH_GTM_THREAD + // The currently active transaction. Elided if the target provides + // some efficient mechanism for storing this. + gtm_thread *thr; +#endif +#ifndef HAVE_ARCH_GTM_THREAD_DISP + // The dispatch table for the STM implementation currently in use. Elided + // if the target provides some efficient mechanism for storing this. + abi_dispatch *disp; +#endif +}; + +extern __thread gtm_thread_tls _gtm_thr_tls; +#endif + +#ifndef HAVE_ARCH_GTM_THREAD +// If the target does not provide optimized access to the thread-local +// data, simply access the TLS variable defined above. +static inline gtm_thread *gtm_thr() { return &_gtm_thr_tls.thr; } +static inline void set_gtm_thr(gtm_thread *x) { _gtm_thr_tls.thr = x; } +#endif + +#ifndef HAVE_ARCH_GTM_THREAD_DISP +// If the target does not provide optimized access to the currently +// active dispatch table, simply access via GTM_THR. +static inline abi_dispatch * abi_disp() { return _gtm_thr_tls.disp; } +static inline void set_abi_disp(abi_dispatch *x) { _gtm_thr_tls.disp = x; } +#endif + +} // namespace GTM + +#endif // LIBITM_TLS_H diff --git a/libitm/config/generic/unaligned.h b/libitm/config/generic/unaligned.h new file mode 100644 index 00000000000..50cb13bd277 --- /dev/null +++ b/libitm/config/generic/unaligned.h @@ -0,0 +1,228 @@ +/* Copyright (C) 2009, 2011 Free Software Foundation, Inc. + Contributed by Richard Henderson <rth@redhat.com>. + + This file is part of the GNU Transactional Memory Library (libitm). + + Libitm is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + Libitm is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + <http://www.gnu.org/licenses/>. */ + +#ifndef LIBITM_UNALIGNED_H +#define LIBITM_UNALIGNED_H 1 + +namespace GTM HIDDEN { + +#ifndef STRICT_ALIGNMENT +#define STRICT_ALIGNMENT 1 +#endif + +// A type trait for whether type T requires strict alignment. +// The generic types are assumed to all be the same; specializations +// for target-specific types should be done in config/cpu/unaligned.h. +template<typename T> + struct strict_alignment + : public std::integral_constant<bool, STRICT_ALIGNMENT> + { }; + +// A helper template for accessing an integral type the same size as T +template<typename T> + struct make_integral + : public sized_integral<sizeof(T)> + { }; + +// A helper class for accessing T as an unaligned value. +template<typename T> +struct __attribute__((packed)) unaligned_helper + { T x; }; + +// A helper class for view-converting T as an integer. +template<typename T> +union view_convert_helper +{ + typedef T type; + typedef make_integral<T> itype; + + type t; + itype i; +}; + +// Generate an unaligned load sequence. +// The compiler knows how to do this for any specific type. +template<typename T> +inline T ALWAYS_INLINE +unaligned_load(const void *t) +{ + typedef unaligned_helper<T> UT; + const UT *ut = reinterpret_cast<const UT *>(t); + return ut->x; +} + +// Generate an unaligned store sequence. +template<typename T> +inline void ALWAYS_INLINE +unaligned_store(void *t, T val) +{ + typedef unaligned_helper<T> UT; + UT *ut = reinterpret_cast<UT *>(t); + ut->x = val; +} + +// Generate an unaligned load from two different cachelines. +// It is known that OFS + SIZEOF(T) > CACHELINE_SIZE. +template<typename T> +inline T ALWAYS_INLINE +unaligned_load2(const gtm_cacheline *c1, const gtm_cacheline *c2, size_t ofs) +{ + size_t left = CACHELINE_SIZE - ofs; + T ret; + + memcpy (&ret, &c1->b[ofs], left); + memcpy ((char *)&ret + ofs, c2, sizeof(T) - left); + + return ret; +} + +// Generate an unaligned store into two different cachelines. +// It is known that OFS + SIZEOF(T) > CACHELINE_SIZE. +template<typename T> +inline void ALWAYS_INLINE +unaligned_store2(gtm_cacheline *c1, gtm_cacheline *c2, size_t ofs, T val) +{ + size_t left = CACHELINE_SIZE - ofs; + memcpy (&c1->b[ofs], &val, left); + memcpy (c2, (char *)&val + left, sizeof(T) - left); +} + +#ifndef HAVE_ARCH_UNALIGNED_LOAD2_U2 +template<> +inline uint16_t ALWAYS_INLINE +unaligned_load2<uint16_t>(const gtm_cacheline *c1, + const gtm_cacheline *c2, size_t ofs) +{ + uint16_t v1 = c1->b[CACHELINE_SIZE - 1]; + uint16_t v2 = c2->b[0]; + + if (WORDS_BIGENDIAN) + return v1 << 8 | v2; + else + return v2 << 8 | v1; +} +#endif + +#ifndef HAVE_ARCH_UNALIGNED_LOAD2_U4 +template<> +inline uint32_t ALWAYS_INLINE +unaligned_load2<uint32_t>(const gtm_cacheline *c1, + const gtm_cacheline *c2, size_t ofs) +{ + uint32_t v1 = c1->u32[CACHELINE_SIZE / sizeof(uint32_t) - 1]; + uint32_t v2 = c2->u32[0]; + int s2 = (ofs & (sizeof(uint32_t) - 1)) * 8; + int s1 = sizeof(uint32_t) * 8 - s2; + + if (WORDS_BIGENDIAN) + return v1 << s2 | v2 >> s1; + else + return v2 << s2 | v1 >> s1; +} +#endif + +#ifndef HAVE_ARCH_UNALIGNED_LOAD2_U8 +template<> +inline uint64_t ALWAYS_INLINE +unaligned_load2<uint64_t>(const gtm_cacheline *c1, + const gtm_cacheline *c2, size_t ofs) +{ + uint64_t v1 = c1->u64[CACHELINE_SIZE / sizeof(uint64_t) - 1]; + uint64_t v2 = c2->u64[0]; + int s2 = (ofs & (sizeof(uint64_t) - 1)) * 8; + int s1 = sizeof(uint64_t) * 8 - s2; + + if (WORDS_BIGENDIAN) + return v1 << s2 | v2 >> s1; + else + return v2 << s2 | v1 >> s1; +} +#endif + +template<> +inline float ALWAYS_INLINE +unaligned_load2<float>(const gtm_cacheline *c1, + const gtm_cacheline *c2, size_t ofs) +{ + typedef view_convert_helper<float> VC; VC vc; + vc.i = unaligned_load2<VC::itype>(c1, c2, ofs); + return vc.t; +} + +template<> +inline double ALWAYS_INLINE +unaligned_load2<double>(const gtm_cacheline *c1, + const gtm_cacheline *c2, size_t ofs) +{ + typedef view_convert_helper<double> VC; VC vc; + vc.i = unaligned_load2<VC::itype>(c1, c2, ofs); + return vc.t; +} + +#ifndef HAVE_ARCH_UNALIGNED_STORE2_U2 +template<> +inline void ALWAYS_INLINE +unaligned_store2<uint16_t>(gtm_cacheline *c1, gtm_cacheline *c2, + size_t ofs, uint16_t val) +{ + uint8_t vl = val, vh = val >> 8; + + if (WORDS_BIGENDIAN) + { + c1->b[CACHELINE_SIZE - 1] = vh; + c2->b[0] = vl; + } + else + { + c1->b[CACHELINE_SIZE - 1] = vl; + c2->b[0] = vh; + } +} +#endif + +#if 0 +#ifndef HAVE_ARCH_UNALIGNED_STORE2_U4 +template<> +inline void ALWAYS_INLINE +unaligned_store2<uint32_t>(gtm_cacheline *c1, gtm_cacheline *c2, + size_t ofs, uint32_t val) +{ + // ??? We could reuse the store_mask stuff here. +} +#endif + +template<> +inline void ALWAYS_INLINE +unaligned_store2<float>(gtm_cacheline *c1, gtm_cacheline *c2, + size_t ofs, float val) +{ + typedef view_convert_helper<float> VC; VC vc; + vc.t = val; + unaligned_store2(c1, c2, ofs, vc.i); +} +#endif + +} // namespace GTM + +#endif // LIBITM_UNALIGNED_H diff --git a/libitm/config/linux/alpha/futex_bits.h b/libitm/config/linux/alpha/futex_bits.h new file mode 100644 index 00000000000..997bf0b3cff --- /dev/null +++ b/libitm/config/linux/alpha/futex_bits.h @@ -0,0 +1,56 @@ +/* Copyright (C) 2008, 2009, 2011 Free Software Foundation, Inc. + Contributed by Richard Henderson <rth@redhat.com>. + + This file is part of the GNU Transactional Memory Library (libitm). + + Libitm is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + Libitm is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + <http://www.gnu.org/licenses/>. */ + +/* Provide target-specific access to the futex system call. */ + +#ifndef SYS_futex +#define SYS_futex 394 +#endif + +static inline long +sys_futex0 (int *addr, long op, long val) +{ + register long sc_0 __asm__("$0"); + register long sc_16 __asm__("$16"); + register long sc_17 __asm__("$17"); + register long sc_18 __asm__("$18"); + register long sc_19 __asm__("$19"); + long res; + + sc_0 = SYS_futex; + sc_16 = (long) addr; + sc_17 = op; + sc_18 = val; + sc_19 = 0; + __asm volatile ("callsys" + : "=r" (sc_0), "=r"(sc_19) + : "0"(sc_0), "r" (sc_16), "r"(sc_17), "r"(sc_18), "1"(sc_19) + : "$1", "$2", "$3", "$4", "$5", "$6", "$7", "$8", + "$22", "$23", "$24", "$25", "$27", "$28", "memory"); + + res = sc_0; + if (__builtin_expect (sc_19, 0)) + res = -res; + return res; +} diff --git a/libitm/config/linux/futex.cc b/libitm/config/linux/futex.cc new file mode 100644 index 00000000000..45c9db62dbb --- /dev/null +++ b/libitm/config/linux/futex.cc @@ -0,0 +1,82 @@ +/* Copyright (C) 2008, 2009, 2011 Free Software Foundation, Inc. + Contributed by Richard Henderson <rth@redhat.com>. + + This file is part of the GNU Transactional Memory Library (libitm). + + Libitm is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + Libitm is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + <http://www.gnu.org/licenses/>. */ + +/* Provide access to the futex system call. */ + +#include "libitm_i.h" +#include "futex.h" +#include <errno.h> + +namespace GTM HIDDEN { + +#define FUTEX_WAIT 0 +#define FUTEX_WAKE 1 +#define FUTEX_PRIVATE_FLAG 128L + + +static long int gtm_futex_wait = FUTEX_WAIT | FUTEX_PRIVATE_FLAG; +static long int gtm_futex_wake = FUTEX_WAKE | FUTEX_PRIVATE_FLAG; + + +void +futex_wait (int *addr, int val) +{ + long res; + + res = sys_futex0 (addr, gtm_futex_wait, val); + if (__builtin_expect (res == -ENOSYS, 0)) + { + gtm_futex_wait = FUTEX_WAIT; + gtm_futex_wake = FUTEX_WAKE; + res = sys_futex0 (addr, FUTEX_WAIT, val); + } + if (__builtin_expect (res < 0, 0)) + { + if (res == -EWOULDBLOCK || res == -ETIMEDOUT) + ; + else if (res == -EFAULT) + GTM_fatal ("futex failed (EFAULT %p)", addr); + else + GTM_fatal ("futex failed (%s)", strerror(-res)); + } +} + + +long +futex_wake (int *addr, int count) +{ + long res = sys_futex0 (addr, gtm_futex_wake, count); + if (__builtin_expect (res == -ENOSYS, 0)) + { + gtm_futex_wait = FUTEX_WAIT; + gtm_futex_wake = FUTEX_WAKE; + res = sys_futex0 (addr, FUTEX_WAKE, count); + } + if (__builtin_expect (res < 0, 0)) + GTM_fatal ("futex failed (%s)", strerror(-res)); + else + return res; +} + +} // namespace GTM diff --git a/libitm/config/linux/futex.h b/libitm/config/linux/futex.h new file mode 100644 index 00000000000..326c0f56eed --- /dev/null +++ b/libitm/config/linux/futex.h @@ -0,0 +1,39 @@ +/* Copyright (C) 2008, 2009, 2011 Free Software Foundation, Inc. + Contributed by Richard Henderson <rth@redhat.com>. + + This file is part of the GNU Transactional Memory Library (libitm). + + Libitm is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + Libitm is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + <http://www.gnu.org/licenses/>. */ + +/* Provide access to the futex system call. */ + +#ifndef GTM_FUTEX_H +#define GTM_FUTEX_H 1 + +namespace GTM HIDDEN { + +#include "futex_bits.h" + +extern void futex_wait (int *addr, int val); +extern long futex_wake (int *addr, int count); + +} + +#endif /* GTM_FUTEX_H */ diff --git a/libitm/config/linux/rwlock.cc b/libitm/config/linux/rwlock.cc new file mode 100644 index 00000000000..c1e935ea5b2 --- /dev/null +++ b/libitm/config/linux/rwlock.cc @@ -0,0 +1,235 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + Contributed by Torvald Riegel <triegel@redhat.com>. + + This file is part of the GNU Transactional Memory Library (libitm). + + Libitm is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + Libitm is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + <http://www.gnu.org/licenses/>. */ + +#include "libitm_i.h" +#include "futex.h" +#include <limits.h> + +namespace GTM HIDDEN { + +// Acquire a RW lock for reading. + +void +gtm_rwlock::read_lock (gtm_thread *tx) +{ + for (;;) + { + // Fast path: first announce our intent to read, then check for + // conflicting intents to write. The barrier makes sure that this + // happens in exactly this order. + tx->shared_state = 0; + __sync_synchronize(); + if (likely(writers == 0)) + return; + + // There seems to be an active, waiting, or confirmed writer, so enter + // the futex-based slow path. + + // Before waiting, we clear our read intent check whether there are any + // writers that might potentially wait for readers. If so, wake them. + // We need the barrier here for the same reason that we need it in + // read_unlock(). + // TODO Potentially too many wake-ups. See comments in read_unlock(). + tx->shared_state = ~(typeof tx->shared_state)0; + __sync_synchronize(); + if (writer_readers > 0) + { + writer_readers = 0; + futex_wake(&writer_readers, 1); + } + + // Signal that there are waiting readers and wait until there is no + // writer anymore. + // TODO Spin here on writers for a while. Consider whether we woke + // any writers before? + while (writers) + { + // An active writer. Wait until it has finished. To avoid lost + // wake-ups, we need to use Dekker-like synchronization. + // Note that we cannot reset readers to zero when we see that there + // are no writers anymore after the barrier because this pending + // store could then lead to lost wake-ups at other readers. + readers = 1; + __sync_synchronize(); + if (writers) + futex_wait(&readers, 1); + } + + // And we try again to acquire a read lock. + } +} + + +// Acquire a RW lock for writing. Generic version that also works for +// upgrades. +// Note that an upgrade might fail (and thus waste previous work done during +// this transaction) if there is another thread that tried to go into serial +// mode earlier (i.e., upgrades do not have higher priority than pure writers). +// However, this seems rare enough to not consider it further as we need both +// a non-upgrade writer and a writer to happen to switch to serial mode +// concurrently. If we'd want to handle this, a writer waiting for readers +// would have to coordinate with later arriving upgrades and hand over the +// lock to them, including the the reader-waiting state. We can try to support +// this if this will actually happen often enough in real workloads. + +bool +gtm_rwlock::write_lock_generic (gtm_thread *tx) +{ + // Try to acquire the write lock. + unsigned int w; + if (unlikely((w = __sync_val_compare_and_swap(&writers, 0, 1)) != 0)) + { + // If this is an upgrade, we must not wait for other writers or + // upgrades. + if (tx != 0) + return false; + + // There is already a writer. If there are no other waiting writers, + // switch to contended mode. + // Note that this is actually an atomic exchange, not a TAS. Also, + // it's only guaranteed to have acquire semantics, whereas we need a + // full barrier to make the Dekker-style synchronization work. However, + // we rely on the xchg being a full barrier on the architectures that we + // consider here. + // ??? Use C++0x atomics as soon as they are available. + if (w != 2) + w = __sync_lock_test_and_set(&writers, 2); + while (w != 0) + { + futex_wait(&writers, 2); + w = __sync_lock_test_and_set(&writers, 2); + } + } + + // We have acquired the writer side of the R/W lock. Now wait for any + // readers that might still be active. + // We don't need an extra barrier here because the CAS and the xchg + // operations have full barrier semantics already. + + // If this is an upgrade, we are not a reader anymore. This is only safe to + // do after we have acquired the writer lock. + // TODO In the worst case, this requires one wait/wake pair for each + // active reader. Reduce this! + if (tx != 0) + tx->shared_state = ~(typeof tx->shared_state)0; + + for (gtm_thread *it = gtm_thread::list_of_threads; it != 0; + it = it->next_thread) + { + // Use a loop here to check reader flags again after waiting. + while (it->shared_state != ~(typeof it->shared_state)0) + { + // An active reader. Wait until it has finished. To avoid lost + // wake-ups, we need to use Dekker-like synchronization. + // Note that we can reset writer_readers to zero when we see after + // the barrier that the reader has finished in the meantime; + // however, this is only possible because we are the only writer. + // TODO Spin for a while on this reader flag. + writer_readers = 1; + __sync_synchronize(); + if (it->shared_state != ~(typeof it->shared_state)0) + futex_wait(&writer_readers, 1); + else + writer_readers = 0; + } + } + + return true; +} + +// Acquire a RW lock for writing. + +void +gtm_rwlock::write_lock () +{ + write_lock_generic (0); +} + + +// Upgrade a RW lock that has been locked for reading to a writing lock. +// Do this without possibility of another writer incoming. Return false +// if this attempt fails (i.e. another thread also upgraded). + +bool +gtm_rwlock::write_upgrade (gtm_thread *tx) +{ + return write_lock_generic (tx); +} + + +// Release a RW lock from reading. + +void +gtm_rwlock::read_unlock (gtm_thread *tx) +{ + tx->shared_state = ~(typeof tx->shared_state)0; + + // If there is a writer waiting for readers, wake it up. We need the barrier + // to avoid lost wake-ups. + // ??? We might not be the last active reader, so the wake-up might happen + // too early. How do we avoid this without slowing down readers too much? + // Each reader could scan the list of txns for other active readers but + // this can result in many cache misses. Use combining instead? + // TODO Sends out one wake-up for each reader in the worst case. + __sync_synchronize(); + if (unlikely(writer_readers > 0)) + { + writer_readers = 0; + futex_wake(&writer_readers, 1); + } +} + + +// Release a RW lock from writing. + +void +gtm_rwlock::write_unlock () +{ + // This is supposed to be a full barrier. + if (__sync_fetch_and_sub(&writers, 1) == 2) + { + // There might be waiting writers, so wake them. + writers = 0; + if (futex_wake(&writers, 1) == 0) + { + // If we did not wake any waiting writers, we might indeed be the + // last writer (this can happen because write_lock_generic() + // exchanges 0 or 1 to 2 and thus might go to contended mode even if + // no other thread holds the write lock currently). Therefore, we + // have to wake up readers here as well. + futex_wake(&readers, INT_MAX); + } + return; + } + // No waiting writers, so wake up all waiting readers. + // Because the fetch_and_sub is a full barrier already, we don't need + // another barrier here (as in read_unlock()). + if (readers > 0) + { + readers = 0; + futex_wake(&readers, INT_MAX); + } +} + +} // namespace GTM diff --git a/libitm/config/linux/rwlock.h b/libitm/config/linux/rwlock.h new file mode 100644 index 00000000000..7e6229b73f2 --- /dev/null +++ b/libitm/config/linux/rwlock.h @@ -0,0 +1,66 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + Contributed by Torvald Riegel <triegel@redhat.com>. + + This file is part of the GNU Transactional Memory Library (libitm). + + Libitm is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + Libitm is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + <http://www.gnu.org/licenses/>. */ + +#ifndef GTM_RWLOCK_H +#define GTM_RWLOCK_H + +#include "common.h" + +namespace GTM HIDDEN { + +struct gtm_thread; + +// This datastructure is the blocking, futex-based version of the Dekker-style +// reader-writer lock used to provide mutual exclusion between active and +// serial transactions. +// See libitm's documentation for further details. +// +// In this implementation, writers are given highest priority access but +// read-to-write upgrades do not have a higher priority than writers. + +class gtm_rwlock +{ + // TODO Put futexes on different cachelines? + int writers; // Writers' futex. + int writer_readers; // A confirmed writer waits here for readers. + int readers; // Readers wait here for writers (iff true). + + public: + gtm_rwlock() : writers(0), writer_readers(0), readers(0) {}; + + void read_lock (gtm_thread *tx); + void read_unlock (gtm_thread *tx); + + void write_lock (); + void write_unlock (); + + bool write_upgrade (gtm_thread *tx); + + protected: + bool write_lock_generic (gtm_thread *tx); +}; + +} // namespace GTM + +#endif // GTM_RWLOCK_H diff --git a/libitm/config/linux/x86/futex_bits.h b/libitm/config/linux/x86/futex_bits.h new file mode 100644 index 00000000000..9a6b102cd7a --- /dev/null +++ b/libitm/config/linux/x86/futex_bits.h @@ -0,0 +1,82 @@ +/* Copyright (C) 2008, 2009, 2011 Free Software Foundation, Inc. + Contributed by Richard Henderson <rth@redhat.com>. + + This file is part of the GNU Transactional Memory Library (libitm). + + Libitm is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + Libitm is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + <http://www.gnu.org/licenses/>. */ + +#ifdef __x86_64__ +# ifndef SYS_futex +# define SYS_futex 202 +# endif + +static inline long +sys_futex0 (int *addr, long op, long val) +{ + register long r10 __asm__("%r10") = 0; + long res; + + __asm volatile ("syscall" + : "=a" (res) + : "0" (SYS_futex), "D" (addr), "S" (op), "d" (val), "r" (r10) + : "r11", "rcx", "memory"); + + return res; +} + +#else +# ifndef SYS_futex +# define SYS_futex 240 +# endif + +# ifdef __PIC__ + +static inline long +sys_futex0 (int *addr, int op, int val) +{ + long res; + + __asm volatile ("xchgl\t%%ebx, %2\n\t" + "int\t$0x80\n\t" + "xchgl\t%%ebx, %2" + : "=a" (res) + : "0"(SYS_futex), "r" (addr), "c"(op), + "d"(val), "S"(0) + : "memory"); + return res; +} + +# else + +static inline long +sys_futex0 (int *addr, int op, int val) +{ + long res; + + __asm volatile ("int $0x80" + : "=a" (res) + : "0"(SYS_futex), "b" (addr), "c"(op), + "d"(val), "S"(0) + : "memory"); + return res; +} + +# endif /* __PIC__ */ +#endif /* __x86_64__ */ diff --git a/libitm/config/linux/x86/tls.h b/libitm/config/linux/x86/tls.h new file mode 100644 index 00000000000..01f7c27bcb3 --- /dev/null +++ b/libitm/config/linux/x86/tls.h @@ -0,0 +1,105 @@ +/* Copyright (C) 2008, 2009, 2011 Free Software Foundation, Inc. + Contributed by Richard Henderson <rth@redhat.com>. + + This file is part of the GNU Transactional Memory Library (libitm). + + Libitm is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + Libitm is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + <http://www.gnu.org/licenses/>. */ + +#ifndef LIBITM_X86_TLS_H +#define LIBITM_X86_TLS_H 1 + +#if defined(__GLIBC_PREREQ) && __GLIBC_PREREQ(2, 10) +/* Use slots in the TCB head rather than __thread lookups. + GLIBC has reserved words 10 through 13 for TM. */ +#define HAVE_ARCH_GTM_THREAD 1 +#define HAVE_ARCH_GTM_THREAD_DISP 1 +#endif + +#include "config/generic/tls.h" + +#if defined(__GLIBC_PREREQ) && __GLIBC_PREREQ(2, 10) +namespace GTM HIDDEN { + +#ifdef __x86_64__ +#ifdef __LP64__ +# define SEG_READ(OFS) "movq\t%%fs:(" #OFS "*8),%0" +# define SEG_WRITE(OFS) "movq\t%0,%%fs:(" #OFS "*8)" +# define SEG_DECODE_READ(OFS) SEG_READ(OFS) "\n\t" \ + "rorq\t$17,%0\n\t" \ + "xorq\t%%fs:48,%0" +# define SEG_ENCODE_WRITE(OFS) "xorq\t%%fs:48,%0\n\t" \ + "rolq\t$17,%0\n\t" \ + SEG_WRITE(OFS) +#else +// For X32. +# define SEG_READ(OFS) "movl\t%%fs:(" #OFS "*4),%0" +# define SEG_WRITE(OFS) "movl\t%0,%%fs:(" #OFS "*4)" +# define SEG_DECODE_READ(OFS) SEG_READ(OFS) "\n\t" \ + "rorl\t$9,%0\n\t" \ + "xorl\t%%fs:24,%0" +# define SEG_ENCODE_WRITE(OFS) "xorl\t%%fs:24,%0\n\t" \ + "roll\t$9,%0\n\t" \ + SEG_WRITE(OFS) +#endif +#else +# define SEG_READ(OFS) "movl\t%%gs:(" #OFS "*4),%0" +# define SEG_WRITE(OFS) "movl\t%0,%%gs:(" #OFS "*4)" +# define SEG_DECODE_READ(OFS) SEG_READ(OFS) "\n\t" \ + "rorl\t$9,%0\n\t" \ + "xorl\t%%gs:24,%0" +# define SEG_ENCODE_WRITE(OFS) "xorl\t%%gs:24,%0\n\t" \ + "roll\t$9,%0\n\t" \ + SEG_WRITE(OFS) +#endif + +static inline struct gtm_thread *gtm_thr(void) +{ + struct gtm_thread *r; + asm volatile (SEG_READ(10) : "=r"(r)); + return r; +} + +static inline void set_gtm_thr(struct gtm_thread *x) +{ + asm volatile (SEG_WRITE(10) : : "r"(x)); +} + +static inline struct abi_dispatch *abi_disp(void) +{ + struct abi_dispatch *r; + asm volatile (SEG_DECODE_READ(11) : "=r"(r)); + return r; +} + +static inline void set_abi_disp(struct abi_dispatch *x) +{ + void *scratch; + asm volatile (SEG_ENCODE_WRITE(11) : "=r"(scratch) : "0"(x)); +} + +#undef SEG_READ +#undef SEG_WRITE +#undef SEG_DECODE_READ +#undef SEG_ENCODE_WRITE + +} // namespace GTM +#endif /* >= GLIBC 2.10 */ + +#endif // LIBITM_X86_TLS_H diff --git a/libitm/config/posix/cachepage.cc b/libitm/config/posix/cachepage.cc new file mode 100644 index 00000000000..128cd5435ae --- /dev/null +++ b/libitm/config/posix/cachepage.cc @@ -0,0 +1,183 @@ +/* Copyright (C) 2009, 2011 Free Software Foundation, Inc. + Contributed by Richard Henderson <rth@redhat.com>. + + This file is part of the GNU Transactional Memory Library (libitm). + + Libitm is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + Libitm is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + <http://www.gnu.org/licenses/>. */ + +#include "libitm_i.h" +#include <pthread.h> + +// +// We have three possibilities for alloction: mmap, memalign, posix_memalign +// + +#if defined(HAVE_MMAP_ANON) || defined(HAVE_MMAP_DEV_ZERO) +#include <sys/mman.h> +#include <fcntl.h> +#endif +#ifdef HAVE_MALLOC_H +#include <malloc.h> +#endif + +namespace GTM HIDDEN { + +#if defined(HAVE_MMAP_ANON) +# if !defined(MAP_ANONYMOUS) && defined(MAP_ANON) +# define MAP_ANONYMOUS MAP_ANON +# endif +# define dev_zero -1 +#elif defined(HAVE_MMAP_DEV_ZERO) +# ifndef MAP_ANONYMOUS +# define MAP_ANONYMOUS 0 +# endif +static int dev_zero = -1; +#endif + +#if defined(HAVE_MMAP_ANON) || defined(HAVE_MMAP_DEV_ZERO) +/* If we get here, we've already opened /dev/zero and verified that + PAGE_SIZE is valid for the system. */ +static gtm_cacheline_page * alloc_mmap (void) UNUSED; +static gtm_cacheline_page * +alloc_mmap (void) +{ + gtm_cacheline_page *r; + r = (gtm_cacheline_page *) mmap (NULL, PAGE_SIZE, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, dev_zero, 0); + if (r == (gtm_cacheline_page *) MAP_FAILED) + abort (); + return r; +} +#endif /* MMAP_ANON | MMAP_DEV_ZERO */ + +#ifdef HAVE_MEMALIGN +static gtm_cacheline_page * alloc_memalign (void) UNUSED; +static gtm_cacheline_page * +alloc_memalign (void) +{ + gtm_cacheline_page *r; + r = (gtm_cacheline_page *) memalign (PAGE_SIZE, PAGE_SIZE); + if (r == NULL) + abort (); + return r; +} +#endif /* MEMALIGN */ + +#ifdef HAVE_POSIX_MEMALIGN +static gtm_cacheline_page *alloc_posix_memalign (void) UNUSED; +static gtm_cacheline_page * +alloc_posix_memalign (void) +{ + void *r; + if (posix_memalign (&r, PAGE_SIZE, PAGE_SIZE)) + abort (); + return (gtm_cacheline_page *) r; +} +#endif /* POSIX_MEMALIGN */ + +#if defined(HAVE_MMAP_ANON) && defined(FIXED_PAGE_SIZE) +# define alloc_page alloc_mmap +#elif defined(HAVE_MMAP_DEV_ZERO) && defined(FIXED_PAGE_SIZE) +static gtm_cacheline_page * +alloc_page (void) +{ + if (dev_zero < 0) + { + dev_zero = open ("/dev/zero", O_RDWR); + assert (dev_zero >= 0); + } + return alloc_mmap (); +} +#elif defined(HAVE_MMAP_ANON) || defined(HAVE_MMAP_DEV_ZERO) +static gtm_cacheline_page * (*alloc_page) (void); +static void __attribute__((constructor)) +init_alloc_page (void) +{ + size_t page_size = getpagesize (); + if (page_size <= PAGE_SIZE && PAGE_SIZE % page_size == 0) + { +# ifndef HAVE_MMAP_ANON + dev_zero = open ("/dev/zero", O_RDWR); + assert (dev_zero >= 0); +# endif + alloc_page = alloc_mmap; + return; + } +# ifdef HAVE_MEMALIGN + alloc_page = alloc_memalign; +# elif defined(HAVE_POSIX_MEMALIGN) + alloc_page = alloc_posix_memalign; +# else +# error "No fallback aligned memory allocation method" +# endif +} +#elif defined(HAVE_MEMALIGN) +# define alloc_page alloc_memalign +#elif defined(HAVE_POSIX_MEMALIGN) +# define alloc_page alloc_posix_memalign +#else +# error "No aligned memory allocation method" +#endif + +static gtm_cacheline_page *free_pages; +static pthread_mutex_t free_page_lock = PTHREAD_MUTEX_INITIALIZER; + +void * +gtm_cacheline_page::operator new (size_t size) +{ + assert (size == sizeof (gtm_cacheline_page)); + assert (size <= PAGE_SIZE); + + pthread_mutex_lock(&free_page_lock); + + gtm_cacheline_page *r = free_pages; + free_pages = r ? r->prev : NULL; + + pthread_mutex_unlock(&free_page_lock); + + if (r == NULL) + r = alloc_page (); + + return r; +} + +void +gtm_cacheline_page::operator delete (void *xhead) +{ + gtm_cacheline_page *head = static_cast<gtm_cacheline_page *>(xhead); + gtm_cacheline_page *tail; + + if (head == 0) + return; + + /* ??? We should eventually really free some of these. */ + + for (tail = head; tail->prev != 0; tail = tail->prev) + continue; + + pthread_mutex_lock(&free_page_lock); + + tail->prev = free_pages; + free_pages = head; + + pthread_mutex_unlock(&free_page_lock); +} + +} // namespace GTM diff --git a/libitm/config/posix/rwlock.cc b/libitm/config/posix/rwlock.cc new file mode 100644 index 00000000000..f3793830e12 --- /dev/null +++ b/libitm/config/posix/rwlock.cc @@ -0,0 +1,288 @@ +/* Copyright (C) 2008, 2009, 2011 Free Software Foundation, Inc. + Contributed by Richard Henderson <rth@redhat.com>. + + This file is part of the GNU Transactional Memory Library (libitm). + + Libitm is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + Libitm is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + <http://www.gnu.org/licenses/>. */ + +#include "libitm_i.h" + +namespace GTM HIDDEN { + +// Initialize a new RW lock. +// ??? Move this back to the header file when constexpr is implemented. + +gtm_rwlock::gtm_rwlock() + : mutex (PTHREAD_MUTEX_INITIALIZER), + c_readers (PTHREAD_COND_INITIALIZER), + c_writers (PTHREAD_COND_INITIALIZER), + c_confirmed_writers (PTHREAD_COND_INITIALIZER), + summary (0), + a_readers (0), + w_readers (0), + w_writers (0) +{ } + +gtm_rwlock::~gtm_rwlock() +{ + pthread_mutex_destroy (&this->mutex); + pthread_cond_destroy (&this->c_readers); + pthread_cond_destroy (&this->c_writers); +} + +// Acquire a RW lock for reading. + +void +gtm_rwlock::read_lock (gtm_thread *tx) +{ + // Fast path: first announce our intent to read, then check for conflicting + // intents to write. The barrier makes sure that this happens in exactly + // this order. + tx->shared_state = 0; + __sync_synchronize(); + unsigned int sum = this->summary; + if (likely(!(sum & (a_writer | w_writer)))) + return; + + // There seems to be an active, waiting, or confirmed writer, so enter the + // mutex-based slow path. To try to keep the number of readers small that + // the writer will see, we clear our read flag right away before entering + // the critical section. Otherwise, the writer would have to wait for us to + // get into the critical section. (Note that for correctness, this only has + // to happen before we leave the slow path and before we wait for any + // writer). + // ??? Add a barrier to enforce early visibility of this? + tx->shared_state = ~(typeof tx->shared_state)0; + + pthread_mutex_lock (&this->mutex); + + // Read summary again after acquiring the mutex because it might have + // changed during waiting for the mutex to become free. + sum = this->summary; + + // If there is a writer waiting for readers, wake it up. Only do that if we + // might be the last reader that could do the wake-up, otherwise skip the + // wake-up but decrease a_readers to show that we have entered the slow path. + // This has to happen before we wait for any writers or upgraders. + // See write_lock_generic() for further explanations. + if (this->a_readers > 0) + { + this->a_readers--; + if (this->a_readers == 0) + pthread_cond_signal(&this->c_confirmed_writers); + } + + // If there is an active or waiting writer, we must wait. + while (sum & (a_writer | w_writer)) + { + this->summary = sum | w_reader; + this->w_readers++; + pthread_cond_wait (&this->c_readers, &this->mutex); + sum = this->summary; + if (--this->w_readers == 0) + sum &= ~w_reader; + } + + // Otherwise we can acquire the lock for read. + tx->shared_state = 0; + + pthread_mutex_unlock(&this->mutex); +} + + +// Acquire a RW lock for writing. Generic version that also works for +// upgrades. +// Note that an upgrade might fail (and thus waste previous work done during +// this transaction) if there is another thread that tried to go into serial +// mode earlier (i.e., upgrades do not have higher priority than pure writers). +// However, this seems rare enough to not consider it further as we need both +// a non-upgrade writer and a writer to happen to switch to serial mode +// concurrently. If we'd want to handle this, a writer waiting for readers +// would have to coordinate with later arriving upgrades and hand over the +// lock to them, including the the reader-waiting state. We can try to support +// this if this will actually happen often enough in real workloads. + +bool +gtm_rwlock::write_lock_generic (gtm_thread *tx) +{ + pthread_mutex_lock (&this->mutex); + + unsigned int sum = this->summary; + + // If there is an active writer, wait. + while (sum & a_writer) + { + if (tx != 0) + { + // If this is an upgrade, we must not wait for other writers or + // upgrades that already have gone in + pthread_mutex_unlock (&this->mutex); + return false; + } + + this->summary = sum | w_writer; + this->w_writers++; + pthread_cond_wait (&this->c_writers, &this->mutex); + sum = this->summary; + if (--this->w_writers == 0) + sum &= ~w_writer; + } + + // Otherwise we can acquire the lock for write. As a writer, we have + // priority, so we don't need to take this back. + this->summary = sum | a_writer; + + // We still need to wait for active readers to finish. The barrier makes + // sure that we first set our write intent and check for active readers + // after that, in strictly this order (similar to the barrier in the fast + // path of read_lock()). + __sync_synchronize(); + + // If this is an upgrade, we are not a reader anymore. + if (tx != 0) + tx->shared_state = ~(typeof tx->shared_state)0; + + // Count the number of active readers to be able to decrease the number of + // wake-ups and wait calls that are necessary. + // + // This number is an upper bound of the number of readers that actually + // are still active and which we need to wait for: + // - We set our write flag before checking the reader flags, and readers + // check our write flag after clearing their read flags in read_unlock(). + // Therefore, they will enter the slow path whenever we have seen them. + // - Readers will have cleared their read flags before leaving the slow + // path in read_lock() (prevents lost wake-ups), and before waiting for + // any writer (prevents deadlocks). + // + // However, this number is also just a lower bound of the number of readers + // that will actually enter the slow path in read_unlock() or read_lock(): + // - Because the read flag is cleared outside of a critical section, writers + // can see it as cleared while the reader still goes into the slow path. + // + // Therefore, readers can skip (lower bound - 1) wake-ups, but we do need + // the following loop to check that the readers that we wanted to wait for + // are actually those that entered the slow path so far (and either skipped + // or sent a wake-up). + // + // ??? Do we need to optimize further? (The writer could publish a list of + // readers that it suspects to be active. Readers could check this list and + // only decrement a_readers if they are in this list.) + for (;;) + { + // ??? Keep a list of active readers that we saw and update it on the + // next retry instead? This might reduce the number of cache misses that + // we get when checking reader flags. + int readers = 0; + for (gtm_thread *it = gtm_thread::list_of_threads; it != 0; + it = it->next_thread) + { + // Don't count ourself if this is an upgrade. + if (it->shared_state != ~(typeof it->shared_state)0) + readers++; + } + + // If we have not seen any readers, we will not wait. + if (readers == 0) + break; + + // We've seen a number of readers, so we publish this number and wait. + this->a_readers = readers; + pthread_cond_wait (&this->c_confirmed_writers, &this->mutex); + } + + pthread_mutex_unlock (&this->mutex); + return true; +} + +// Acquire a RW lock for writing. + +void +gtm_rwlock::write_lock () +{ + write_lock_generic (0); +} + + +// Upgrade a RW lock that has been locked for reading to a writing lock. +// Do this without possibility of another writer incoming. Return false +// if this attempt fails (i.e. another thread also upgraded). + +bool +gtm_rwlock::write_upgrade (gtm_thread *tx) +{ + return write_lock_generic (tx); +} + + +// Release a RW lock from reading. + +void +gtm_rwlock::read_unlock (gtm_thread *tx) +{ + tx->shared_state = ~(typeof tx->shared_state)0; + __sync_synchronize(); + unsigned int sum = this->summary; + if (likely(!(sum & (a_writer | w_writer)))) + return; + + // There is a writer, either active or waiting for other readers or writers. + // Thus, enter the mutex-based slow path. + pthread_mutex_lock (&this->mutex); + + // If there is a writer waiting for readers, wake it up. Only do that if we + // might be the last reader that could do the wake-up, otherwise skip the + // wake-up and decrease a_readers to publish that we have entered the slow + // path but skipped the wake-up. + if (this->a_readers > 0) + { + this->a_readers--; + if (this->a_readers == 0) + pthread_cond_signal(&this->c_confirmed_writers); + } + + // We don't need to wake up any writers waiting for other writers. Active + // writers will take care of that. + + pthread_mutex_unlock (&this->mutex); +} + + +// Release a RW lock from writing. + +void +gtm_rwlock::write_unlock () +{ + pthread_mutex_lock (&this->mutex); + + unsigned int sum = this->summary; + this->summary = sum & ~a_writer; + + // If there is a waiting writer, wake it. + if (unlikely (sum & w_writer)) + pthread_cond_signal (&this->c_writers); + + // If there are waiting readers, wake them. + else if (unlikely (sum & w_reader)) + pthread_cond_broadcast (&this->c_readers); + + pthread_mutex_unlock (&this->mutex); +} + +} // namespace GTM diff --git a/libitm/config/posix/rwlock.h b/libitm/config/posix/rwlock.h new file mode 100644 index 00000000000..f538bd059a2 --- /dev/null +++ b/libitm/config/posix/rwlock.h @@ -0,0 +1,81 @@ +/* Copyright (C) 2009, 2011 Free Software Foundation, Inc. + Contributed by Richard Henderson <rth@redhat.com>. + + This file is part of the GNU Transactional Memory Library (libitm). + + Libitm is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + Libitm is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + <http://www.gnu.org/licenses/>. */ + +#ifndef GTM_RWLOCK_H +#define GTM_RWLOCK_H + +#include <pthread.h> + +namespace GTM HIDDEN { + +struct gtm_thread; + +// This datastructure is the blocking, mutex-based side of the Dekker-style +// reader-writer lock used to provide mutual exclusion between active and +// serial transactions. It has similarities to POSIX pthread_rwlock_t except +// that we also provide for upgrading a reader->writer lock, with a +// positive indication of failure (another writer acquired the lock +// before we were able to acquire). While the writer flag (a_writer below) is +// global and protected by the mutex, there are per-transaction reader flags, +// which are stored in a transaction's shared state. +// See libitm's documentation for further details. +// +// In this implementation, writers are given highest priority access but +// read-to-write upgrades do not have a higher priority than writers. + +class gtm_rwlock +{ + pthread_mutex_t mutex; // Held if manipulating any field. + pthread_cond_t c_readers; // Readers wait here + pthread_cond_t c_writers; // Writers wait here for writers + pthread_cond_t c_confirmed_writers; // Writers wait here for readers + + static const unsigned a_writer = 1; // An active writer. + static const unsigned w_writer = 2; // The w_writers field != 0 + static const unsigned w_reader = 4; // The w_readers field != 0 + + unsigned int summary; // Bitmask of the above. + unsigned int a_readers; // Nr active readers as observed by a writer + unsigned int w_readers; // Nr waiting readers + unsigned int w_writers; // Nr waiting writers + + public: + gtm_rwlock(); + ~gtm_rwlock(); + + void read_lock (gtm_thread *tx); + void read_unlock (gtm_thread *tx); + + void write_lock (); + void write_unlock (); + + bool write_upgrade (gtm_thread *tx); + + protected: + bool write_lock_generic (gtm_thread *tx); +}; + +} // namespace GTM + +#endif // GTM_RWLOCK_H diff --git a/libitm/config/x86/cacheline.cc b/libitm/config/x86/cacheline.cc new file mode 100644 index 00000000000..2e49a355953 --- /dev/null +++ b/libitm/config/x86/cacheline.cc @@ -0,0 +1,73 @@ +/* Copyright (C) 2009, 2011 Free Software Foundation, Inc. + Contributed by Richard Henderson <rth@redhat.com>. + + This file is part of the GNU Transactional Memory Library (libitm). + + Libitm is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + Libitm is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + <http://www.gnu.org/licenses/>. */ + +#include "libitm_i.h" + +namespace GTM HIDDEN { + +uint32_t const gtm_bit_to_byte_mask[16] = +{ + 0x00000000, + 0x000000ff, + 0x0000ff00, + 0x0000ffff, + 0x00ff0000, + 0x00ff00ff, + 0x00ffff00, + 0x00ffffff, + 0xff000000, + 0xff0000ff, + 0xff00ff00, + 0xff00ffff, + 0xffff0000, + 0xffff00ff, + 0xffffff00, + 0xffffffff +}; + +#ifdef __SSE2__ +# define MEMBER m128i +#else +# define MEMBER w +#endif + +void +gtm_cacheline::copy_mask (gtm_cacheline * __restrict d, + const gtm_cacheline * __restrict s, + gtm_cacheline_mask m) +{ + if (m == (gtm_cacheline_mask)-1) + { + *d = *s; + return; + } + if (__builtin_expect (m == 0, 0)) + return; + + size_t n = sizeof(d->MEMBER[0]); + for (size_t i = 0; i < CACHELINE_SIZE / n; ++i, m >>= n) + store_mask (&d->MEMBER[i], s->MEMBER[i], m); +} + +} // namespace GTM diff --git a/libitm/config/x86/cacheline.h b/libitm/config/x86/cacheline.h new file mode 100644 index 00000000000..15a95b0be5b --- /dev/null +++ b/libitm/config/x86/cacheline.h @@ -0,0 +1,242 @@ +/* Copyright (C) 2009, 2011 Free Software Foundation, Inc. + Contributed by Richard Henderson <rth@redhat.com>. + + This file is part of the GNU Transactional Memory Library (libitm). + + Libitm is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + Libitm is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + <http://www.gnu.org/licenses/>. */ + +#ifndef LIBITM_CACHELINE_H +#define LIBITM_CACHELINE_H 1 + +// Minimum cacheline size is 32, due to both complex long double and __m256. +// There's no requirement that 64-bit use a 64-byte cacheline size, but do +// so for now to make sure everything is parameterized properly. +#ifdef __x86_64__ +# define CACHELINE_SIZE 64 +#else +# define CACHELINE_SIZE 32 +#endif + +namespace GTM HIDDEN { + +// A gtm_cacheline_mask stores a modified bit for every modified byte +// in the cacheline with which it is associated. +typedef sized_integral<CACHELINE_SIZE / 8>::type gtm_cacheline_mask; + +extern uint32_t const gtm_bit_to_byte_mask[16]; + +union gtm_cacheline +{ + // Byte access to the cacheline. + unsigned char b[CACHELINE_SIZE] __attribute__((aligned(CACHELINE_SIZE))); + + // Larger sized access to the cacheline. + uint16_t u16[CACHELINE_SIZE / sizeof(uint16_t)]; + uint32_t u32[CACHELINE_SIZE / sizeof(uint32_t)]; + uint64_t u64[CACHELINE_SIZE / sizeof(uint64_t)]; + gtm_word w[CACHELINE_SIZE / sizeof(gtm_word)]; + +#ifdef __MMX__ + __m64 m64[CACHELINE_SIZE / sizeof(__m64)]; +#endif +#ifdef __SSE__ + __m128 m128[CACHELINE_SIZE / sizeof(__m128)]; +#endif +#ifdef __SSE2__ + __m128i m128i[CACHELINE_SIZE / sizeof(__m128i)]; +#endif +#ifdef __AVX__ + __m256 m256[CACHELINE_SIZE / sizeof(__m256)]; + __m256i m256i[CACHELINE_SIZE / sizeof(__m256i)]; +#endif + + // Store S into D, but only the bytes specified by M. + static void store_mask (uint32_t *d, uint32_t s, uint8_t m); + static void store_mask (uint64_t *d, uint64_t s, uint8_t m); +#ifdef __SSE2__ + static void store_mask (__m128i *d, __m128i s, uint16_t m); +#endif + + // Copy S to D, but only the bytes specified by M. + static void copy_mask (gtm_cacheline * __restrict d, + const gtm_cacheline * __restrict s, + gtm_cacheline_mask m); + + // A write barrier to emit after (a series of) copy_mask. + // When we're emitting non-temporal stores, the normal strong + // ordering of the machine doesn't apply. + static void copy_mask_wb (); + +#if defined(__SSE__) || defined(__AVX__) + // Copy S to D; only bother defining if we can do this more efficiently + // than the compiler-generated default implementation. + gtm_cacheline& operator= (const gtm_cacheline &s); +#endif // SSE, AVX +}; + +inline void +gtm_cacheline::copy_mask_wb () +{ +#ifdef __SSE2__ + _mm_sfence (); +#endif +} + +#if defined(__SSE__) || defined(__AVX__) +inline gtm_cacheline& ALWAYS_INLINE +gtm_cacheline::operator= (const gtm_cacheline & __restrict s) +{ +#ifdef __AVX__ +# define CP m256 +# define TYPE __m256 +#else +# define CP m128 +# define TYPE __m128 +#endif + + TYPE w, x, y, z; + + // ??? Wouldn't it be nice to have a pragma to tell the compiler + // to completely unroll a given loop? + switch (CACHELINE_SIZE / sizeof(TYPE)) + { + case 1: + this->CP[0] = s.CP[0]; + break; + case 2: + x = s.CP[0]; + y = s.CP[1]; + this->CP[0] = x; + this->CP[1] = y; + break; + case 4: + w = s.CP[0]; + x = s.CP[1]; + y = s.CP[2]; + z = s.CP[3]; + this->CP[0] = w; + this->CP[1] = x; + this->CP[2] = y; + this->CP[3] = z; + break; + default: + __builtin_trap (); + } + + return *this; +} +#endif + +// ??? Support masked integer stores more efficiently with an unlocked cmpxchg +// insn. My reasoning is that while we write to locations that we do not wish +// to modify, we do it in an uninterruptable insn, and so we either truely +// write back the original data or the insn fails -- unlike with a +// load/and/or/write sequence which can be interrupted either by a kernel +// task switch or an unlucky cacheline steal by another processor. Avoiding +// the LOCK prefix improves performance by a factor of 10, and we don't need +// the memory barrier semantics implied by that prefix. + +inline void ALWAYS_INLINE +gtm_cacheline::store_mask (uint32_t *d, uint32_t s, uint8_t m) +{ + gtm_cacheline_mask tm = (1 << sizeof (s)) - 1; + if (__builtin_expect (m & tm, tm)) + { + if (__builtin_expect ((m & tm) == tm, 1)) + *d = s; + else + { + gtm_cacheline_mask bm = gtm_bit_to_byte_mask[m & 15]; + gtm_word n, o = *d; + + __asm("\n0:\t" + "mov %[o], %[n]\n\t" + "and %[m], %[n]\n\t" + "or %[s], %[n]\n\t" + "cmpxchg %[n], %[d]\n\t" + "jnz,pn 0b" + : [d] "+m"(*d), [n] "=&r" (n), [o] "+a"(o) + : [s] "r" (s & bm), [m] "r" (~bm)); + } + } +} + +inline void ALWAYS_INLINE +gtm_cacheline::store_mask (uint64_t *d, uint64_t s, uint8_t m) +{ + gtm_cacheline_mask tm = (1 << sizeof (s)) - 1; + if (__builtin_expect (m & tm, tm)) + { + if (__builtin_expect ((m & tm) == tm, 1)) + *d = s; + else + { +#ifdef __x86_64__ + uint32_t bl = gtm_bit_to_byte_mask[m & 15]; + uint32_t bh = gtm_bit_to_byte_mask[(m >> 4) & 15]; + gtm_cacheline_mask bm = bl | ((gtm_cacheline_mask)bh << 31 << 1); + uint64_t n, o = *d; + __asm("\n0:\t" + "mov %[o], %[n]\n\t" + "and %[m], %[n]\n\t" + "or %[s], %[n]\n\t" + "cmpxchg %[n], %[d]\n\t" + "jnz,pn 0b" + : [d] "+m"(*d), [n] "=&r" (n), [o] "+a"(o) + : [s] "r" (s & bm), [m] "r" (~bm)); +#else + /* ??? While it's possible to perform this operation with + cmpxchg8b, the sequence requires all 7 general registers + and thus cannot be performed with -fPIC. Don't even try. */ + uint32_t *d32 = reinterpret_cast<uint32_t *>(d); + store_mask (d32, s, m); + store_mask (d32 + 1, s >> 32, m >> 4); +#endif + } + } +} + +#ifdef __SSE2__ +inline void ALWAYS_INLINE +gtm_cacheline::store_mask (__m128i *d, __m128i s, uint16_t m) +{ + if (__builtin_expect (m == 0, 0)) + return; + if (__builtin_expect (m == 0xffff, 1)) + *d = s; + else + { + __m128i bm0, bm1, bm2, bm3; + bm0 = _mm_set_epi32 (0, 0, 0, gtm_bit_to_byte_mask[m & 15]); m >>= 4; + bm1 = _mm_set_epi32 (0, 0, 0, gtm_bit_to_byte_mask[m & 15]); m >>= 4; + bm2 = _mm_set_epi32 (0, 0, 0, gtm_bit_to_byte_mask[m & 15]); m >>= 4; + bm3 = _mm_set_epi32 (0, 0, 0, gtm_bit_to_byte_mask[m & 15]); m >>= 4; + bm0 = _mm_unpacklo_epi32 (bm0, bm1); + bm2 = _mm_unpacklo_epi32 (bm2, bm3); + bm0 = _mm_unpacklo_epi64 (bm0, bm2); + + _mm_maskmoveu_si128 (s, bm0, (char *)d); + } +} +#endif // SSE2 + +} // namespace GTM + +#endif // LIBITM_CACHELINE_H diff --git a/libitm/config/x86/sjlj.S b/libitm/config/x86/sjlj.S new file mode 100644 index 00000000000..725ffec8057 --- /dev/null +++ b/libitm/config/x86/sjlj.S @@ -0,0 +1,105 @@ +/* Copyright (C) 2008, 2009, 2011 Free Software Foundation, Inc. + Contributed by Richard Henderson <rth@redhat.com>. + + This file is part of the GNU Transactional Memory Library (libitm). + + Libitm is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + Libitm is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + <http://www.gnu.org/licenses/>. */ + + .text + .p2align 4 + .globl _ITM_beginTransaction + .type _ITM_beginTransaction, @function + +_ITM_beginTransaction: + .cfi_startproc +#ifdef __x86_64__ + leaq 8(%rsp), %rax + movq (%rsp), %r8 + subq $72, %rsp + .cfi_def_cfa_offset 80 + movq %rax, (%rsp) + movq %r8, 8(%rsp) + movq %rbx, 16(%rsp) + movq %rbp, 24(%rsp) + movq %r12, 32(%rsp) + movq %r13, 40(%rsp) + movq %r14, 48(%rsp) + movq %r15, 56(%rsp) + movq %rsp, %rsi + call GTM_begin_transaction + addq $72, %rsp + .cfi_def_cfa_offset 8 + ret +#else + leal 4(%esp), %ecx + subl $28, %esp + .cfi_def_cfa_offset 32 + movl %ecx, 8(%esp) + movl %ebx, 12(%esp) + movl %esi, 16(%esp) + movl %edi, 20(%esp) + movl %ebp, 24(%esp) + leal 8(%esp), %edx + call GTM_begin_transaction + addl $28, %esp + .cfi_def_cfa_offset 4 + ret +#endif + .cfi_endproc + .size _ITM_beginTransaction, .-_ITM_beginTransaction + + .p2align 4 + .globl GTM_longjmp + .type GTM_longjmp, @function + .hidden GTM_longjmp + +GTM_longjmp: + .cfi_startproc +#ifdef __x86_64__ + movq (%rdi), %rcx + movq 8(%rdi), %rdx + movq 16(%rdi), %rbx + movq 24(%rdi), %rbp + movq 32(%rdi), %r12 + movq 40(%rdi), %r13 + movq 48(%rdi), %r14 + movq 56(%rdi), %r15 + movl %esi, %eax + .cfi_def_cfa %rcx, 0 + .cfi_register %rip, %rdx + movq %rcx, %rsp + jmp *%rdx +#else + xchgl %eax, %edx + movl (%edx), %ecx + movl 4(%edx), %ebx + movl 8(%edx), %esi + movl 12(%edx), %edi + movl 16(%edx), %ebp + movl 20(%edx), %edx + .cfi_def_cfa %ecx, 0 + .cfi_register %eip, %edx + movl %ecx, %esp + jmp *%edx +#endif + .cfi_endproc + .size GTM_longjmp, .-GTM_longjmp + +.section .note.GNU-stack, "", @progbits diff --git a/libitm/config/x86/target.h b/libitm/config/x86/target.h new file mode 100644 index 00000000000..197faebe2d4 --- /dev/null +++ b/libitm/config/x86/target.h @@ -0,0 +1,98 @@ +/* Copyright (C) 2008, 2009, 2011 Free Software Foundation, Inc. + Contributed by Richard Henderson <rth@redhat.com>. + + This file is part of the GNU Transactional Memory Library (libitm). + + Libitm is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + Libitm is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + <http://www.gnu.org/licenses/>. */ + +namespace GTM HIDDEN { + +#ifdef __x86_64__ +/* ??? This doesn't work for Win64. */ +typedef struct gtm_jmpbuf +{ + void *cfa; + unsigned long rip; + unsigned long rbx; + unsigned long rbp; + unsigned long r12; + unsigned long r13; + unsigned long r14; + unsigned long r15; +} gtm_jmpbuf; +#else +typedef struct gtm_jmpbuf +{ + void *cfa; + unsigned long ebx; + unsigned long esi; + unsigned long edi; + unsigned long ebp; + unsigned long eip; +} gtm_jmpbuf; +#endif + +/* x86 doesn't require strict alignment for the basic types. */ +#define STRICT_ALIGNMENT 0 + +/* x86 uses a fixed page size of 4K. */ +#define PAGE_SIZE 4096 +#define FIXED_PAGE_SIZE 1 + +/* The size of one line in hardware caches (in bytes). */ +#define HW_CACHELINE_SIZE 64 + + +static inline void +cpu_relax (void) +{ + __asm volatile ("rep; nop" : : : "memory"); +} + +static inline void +atomic_read_barrier (void) +{ + /* x86 is a strong memory ordering machine. */ + __asm volatile ("" : : : "memory"); +} + +static inline void +atomic_write_barrier (void) +{ + /* x86 is a strong memory ordering machine. */ + __asm volatile ("" : : : "memory"); +} + +} // namespace GTM + +// We'll be using some of the cpu builtins, and their associated types. +#ifndef __cplusplus +/* ??? It's broken for C++. */ +#include <x86intrin.h> +#else +# ifdef __SSE2__ +# include <emmintrin.h> +# elif defined(__SSE__) +# include <xmmintrin.h> +# endif +# ifdef __AVX__ +# include <immintrin.h> +# endif +#endif diff --git a/libitm/config/x86/unaligned.h b/libitm/config/x86/unaligned.h new file mode 100644 index 00000000000..01abc47dccb --- /dev/null +++ b/libitm/config/x86/unaligned.h @@ -0,0 +1,237 @@ +/* Copyright (C) 2009, 2011 Free Software Foundation, Inc. + Contributed by Richard Henderson <rth@redhat.com>. + + This file is part of the GNU Transactional Memory Library (libitm). + + Libitm is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + Libitm is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + <http://www.gnu.org/licenses/>. */ + +#ifndef LIBITM_X86_UNALIGNED_H +#define LIBITM_X86_UNALIGNED_H 1 + +#define HAVE_ARCH_UNALIGNED_LOAD2_U4 1 +#define HAVE_ARCH_UNALIGNED_LOAD2_U8 1 + +#include "config/generic/unaligned.h" + +namespace GTM HIDDEN { + +template<> +inline uint32_t +unaligned_load2<uint32_t>(const gtm_cacheline *c1, + const gtm_cacheline *c2, size_t ofs) +{ + uint32_t r, lo, hi; + lo = c1->u32[CACHELINE_SIZE / sizeof(uint32_t) - 1]; + hi = c2->u32[0]; + asm("shrd %b2, %1, %0" : "=r"(r) : "r"(hi), "c"((ofs & 3) * 8), "0"(lo)); + return r; +} + +template<> +inline uint64_t +unaligned_load2<uint64_t>(const gtm_cacheline *c1, + const gtm_cacheline *c2, size_t ofs) +{ +#ifdef __x86_64__ + uint64_t r, lo, hi; + lo = c1->u64[CACHELINE_SIZE / sizeof(uint64_t) - 1]; + hi = c2->u64[0]; + asm("shrd %b2, %1, %0" : "=r"(r) : "r"(hi), "c"((ofs & 3) * 8), "0"(lo)); + return r; +#else + uint32_t v0, v1, v2; + uint64_t r; + + if (ofs < CACHELINE_SIZE - 4) + { + v0 = c1->u32[CACHELINE_SIZE / sizeof(uint32_t) - 2]; + v1 = c1->u32[CACHELINE_SIZE / sizeof(uint32_t) - 1]; + v2 = c2->u32[0]; + } + else + { + v0 = c1->u32[CACHELINE_SIZE / sizeof(uint32_t) - 1]; + v1 = c2->u32[0]; + v2 = c2->u32[1]; + } + ofs = (ofs & 3) * 8; + asm("shrd %%cl, %[v1], %[v0]; shrd %%cl, %[v2], %[v1]" + : "=A"(r) : "c"(ofs), [v0] "a"(v0), [v1] "d"(v1), [v2] "r"(v2)); + + return r; +#endif +} + +#if defined(__SSE2__) || defined(__MMX__) +template<> +inline _ITM_TYPE_M64 +unaligned_load2<_ITM_TYPE_M64>(const gtm_cacheline *c1, + const gtm_cacheline *c2, size_t ofs) +{ +# ifdef __x86_64__ + __m128i lo = _mm_movpi64_epi64 (c1->m64[CACHELINE_SIZE / 8 - 1]); + __m128i hi = _mm_movpi64_epi64 (c2->m64[0]); + + ofs = (ofs & 7) * 8; + lo = _mm_srli_epi64 (lo, ofs); + hi = _mm_slli_epi64 (hi, 64 - ofs); + lo = lo | hi; + return _mm_movepi64_pi64 (lo); +# else + // On 32-bit we're about to return the result in an MMX register, so go + // ahead and do the computation in that unit, even if SSE2 is available. + __m64 lo = c1->m64[CACHELINE_SIZE / 8 - 1]; + __m64 hi = c2->m64[0]; + + ofs = (ofs & 7) * 8; + lo = _mm_srli_si64 (lo, ofs); + hi = _mm_slli_si64 (hi, 64 - ofs); + return lo | hi; +# endif +} +#endif // SSE2 or MMX + +// The SSE types are strictly aligned. +#ifdef __SSE__ +template<> + struct strict_alignment<_ITM_TYPE_M128> + : public std::true_type + { }; + +// Expand the unaligned SSE move instructions. +template<> +inline _ITM_TYPE_M128 +unaligned_load<_ITM_TYPE_M128>(const void *t) +{ + return _mm_loadu_ps (static_cast<const float *>(t)); +} + +template<> +inline void +unaligned_store<_ITM_TYPE_M128>(void *t, _ITM_TYPE_M128 val) +{ + _mm_storeu_ps (static_cast<float *>(t), val); +} +#endif // SSE + +#ifdef __AVX__ +// The AVX types are strictly aligned when it comes to vmovaps vs vmovups. +template<> + struct strict_alignment<_ITM_TYPE_M256> + : public std::true_type + { }; + +template<> +inline _ITM_TYPE_M256 +unaligned_load<_ITM_TYPE_M256>(const void *t) +{ + return _mm256_loadu_ps (static_cast<const float *>(t)); +} + +template<> +inline void +unaligned_store<_ITM_TYPE_M256>(void *t, _ITM_TYPE_M256 val) +{ + _mm256_storeu_ps (static_cast<float *>(t), val); +} +#endif // AVX + +#ifdef __XOP__ +# define HAVE_ARCH_REALIGN_M128I 1 +extern const __v16qi GTM_vpperm_shift[16]; +inline __m128i +realign_m128i (__m128i lo, __m128i hi, unsigned byte_count) +{ + return _mm_perm_epi8 (lo, hi, GTM_vpperm_shift[byte_count]); +} +#elif defined(__AVX__) +# define HAVE_ARCH_REALIGN_M128I 1 +extern "C" const uint64_t GTM_vpalignr_table[16]; +inline __m128i +realign_m128i (__m128i lo, __m128i hi, unsigned byte_count) +{ + register __m128i xmm0 __asm__("xmm0") = hi; + register __m128i xmm1 __asm__("xmm1") = lo; + __asm("call *%2" : "+x"(xmm0) : "x"(xmm1), + "r"(>M_vpalignr_table[byte_count])); + return xmm0; +} +#elif defined(__SSSE3__) +# define HAVE_ARCH_REALIGN_M128I 1 +extern "C" const uint64_t GTM_palignr_table[16]; +inline __m128i +realign_m128i (__m128i lo, __m128i hi, unsigned byte_count) +{ + register __m128i xmm0 __asm__("xmm0") = hi; + register __m128i xmm1 __asm__("xmm1") = lo; + __asm("call *%2" : "+x"(xmm0) : "x"(xmm1), + "r"(>M_palignr_table[byte_count])); + return xmm0; +} +#elif defined(__SSE2__) +# define HAVE_ARCH_REALIGN_M128I 1 +extern "C" const char GTM_pshift_table[16 * 16]; +inline __m128i +realign_m128i (__m128i lo, __m128i hi, unsigned byte_count) +{ + register __m128i xmm0 __asm__("xmm0") = lo; + register __m128i xmm1 __asm__("xmm1") = hi; + __asm("call *%2" : "+x"(xmm0), "+x"(xmm1) + : "r"(GTM_pshift_table + byte_count*16)); + return xmm0; +} +#endif // XOP, AVX, SSSE3, SSE2 + +#ifdef HAVE_ARCH_REALIGN_M128I +template<> +inline _ITM_TYPE_M128 +unaligned_load2<_ITM_TYPE_M128>(const gtm_cacheline *c1, + const gtm_cacheline *c2, size_t ofs) +{ + return (_ITM_TYPE_M128) + realign_m128i (c1->m128i[CACHELINE_SIZE / 16 - 1], + c2->m128i[0], ofs & 15); +} +#endif // HAVE_ARCH_REALIGN_M128I + +#ifdef __AVX__ +template<> +inline _ITM_TYPE_M256 +unaligned_load2<_ITM_TYPE_M256>(const gtm_cacheline *c1, + const gtm_cacheline *c2, size_t ofs) +{ + __m128i v0, v1; + __m256i r; + + v0 = (__m128i) unaligned_load2<_ITM_TYPE_M128>(c1, c2, ofs); + if (ofs < CACHELINE_SIZE - 16) + v1 = v0, v0 = _mm_loadu_si128 ((const __m128i *) &c1->b[ofs]); + else + v1 = _mm_loadu_si128((const __m128i *)&c2->b[ofs + 16 - CACHELINE_SIZE]); + + r = _mm256_castsi128_si256 ((__m128i)v0); + r = _mm256_insertf128_si256 (r, (__m128i)v1, 1); + return (_ITM_TYPE_M256) r; +} +#endif // AVX + +} // namespace GTM + +#endif // LIBITM_X86_UNALIGNED_H diff --git a/libitm/config/x86/x86_avx.cc b/libitm/config/x86/x86_avx.cc new file mode 100644 index 00000000000..9d1ddfb3ee8 --- /dev/null +++ b/libitm/config/x86/x86_avx.cc @@ -0,0 +1,95 @@ +/* Copyright (C) 2009, 2011 Free Software Foundation, Inc. + Contributed by Richard Henderson <rth@redhat.com>. + + This file is part of the GNU Transactional Memory Library (libitm). + + Libitm is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + Libitm is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + <http://www.gnu.org/licenses/>. */ + +#include "libitm_i.h" +#include "dispatch.h" + +// ??? Use memcpy for now, until we have figured out how to best instantiate +// these loads/stores. +CREATE_DISPATCH_FUNCTIONS_T_MEMCPY(M256, GTM::abi_disp()->, ) + +void ITM_REGPARM +_ITM_LM256 (const _ITM_TYPE_M256 *ptr) +{ + GTM::GTM_LB (ptr, sizeof (*ptr)); +} + +// Helpers for re-aligning two 128-bit values. +#ifdef __XOP__ +const __v16qi GTM::GTM_vpperm_shift[16] = +{ + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }, + { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 }, + { 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17 }, + { 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18 }, + { 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19 }, + { 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 }, + { 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21 }, + { 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22 }, + { 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23 }, + { 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24 }, + { 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25 }, + { 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26 }, + { 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27 }, + { 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28 }, + { 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29 }, + { 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30 }, +}; +#else +# define INSN0 "movdqa %xmm1, %xmm0" +# define INSN(N) "vpalignr $" #N ", %xmm0, %xmm1, %xmm0" +# define TABLE_ENT_0 INSN0 "\n\tret\n\t" +# define TABLE_ENT(N) ".balign 8\n\t" INSN(N) "\n\tret\n\t" + +asm(".pushsection .text\n\ + .balign 16\n\ + .globl GTM_vpalignr_table\n\ + .hidden GTM_vpalignr_table\n\ + .type GTM_vpalignr_table, @function\n\ +GTM_vpalignr_table:\n\t" + TABLE_ENT_0 + TABLE_ENT(1) + TABLE_ENT(2) + TABLE_ENT(3) + TABLE_ENT(4) + TABLE_ENT(5) + TABLE_ENT(6) + TABLE_ENT(7) + TABLE_ENT(8) + TABLE_ENT(9) + TABLE_ENT(10) + TABLE_ENT(11) + TABLE_ENT(12) + TABLE_ENT(13) + TABLE_ENT(14) + TABLE_ENT(15) + ".balign 8\n\ + .size GTM_vpalignr_table, .-GTM_vpalignr_table\n\ + .popsection"); + +# undef INSN0 +# undef INSN +# undef TABLE_ENT_0 +# undef TABLE_ENT +#endif diff --git a/libitm/config/x86/x86_sse.cc b/libitm/config/x86/x86_sse.cc new file mode 100644 index 00000000000..7440c949cb7 --- /dev/null +++ b/libitm/config/x86/x86_sse.cc @@ -0,0 +1,122 @@ +/* Copyright (C) 2009, 2011 Free Software Foundation, Inc. + Contributed by Richard Henderson <rth@redhat.com>. + + This file is part of the GNU Transactional Memory Library (libitm). + + Libitm is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + Libitm is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + <http://www.gnu.org/licenses/>. */ + +#include "libitm_i.h" +#include "dispatch.h" + +// ??? Use memcpy for now, until we have figured out how to best instantiate +// these loads/stores. +CREATE_DISPATCH_FUNCTIONS_T_MEMCPY(M64, GTM::abi_disp()->, ) +CREATE_DISPATCH_FUNCTIONS_T_MEMCPY(M128, GTM::abi_disp()->, ) + +void ITM_REGPARM +_ITM_LM64 (const _ITM_TYPE_M64 *ptr) +{ + GTM::GTM_LB (ptr, sizeof (*ptr)); +} + +void ITM_REGPARM +_ITM_LM128 (const _ITM_TYPE_M128 *ptr) +{ + GTM::GTM_LB (ptr, sizeof (*ptr)); +} + +// Helpers for re-aligning two 128-bit values. +#ifdef __SSSE3__ +# define INSN0 "movdqa %xmm1, %xmm0" +# define INSN(N) "palignr $" #N ", %xmm1, %xmm0" +# define TABLE_ENT_0 INSN0 "\n\tret\n\t" +# define TABLE_ENT(N) ".balign 8\n\t" INSN(N) "\n\tret\n\t" + +asm(".pushsection .text\n\ + .balign 16\n\ + .globl GTM_palignr_table\n\ + .hidden GTM_palignr_table\n\ + .type GTM_palignr_table, @function\n\ +GTM_palignr_table:\n\t" + TABLE_ENT_0 + TABLE_ENT(1) + TABLE_ENT(2) + TABLE_ENT(3) + TABLE_ENT(4) + TABLE_ENT(5) + TABLE_ENT(6) + TABLE_ENT(7) + TABLE_ENT(8) + TABLE_ENT(9) + TABLE_ENT(10) + TABLE_ENT(11) + TABLE_ENT(12) + TABLE_ENT(13) + TABLE_ENT(14) + TABLE_ENT(15) + ".balign 8\n\ + .size GTM_palignr_table, .-GTM_palignr_table\n\ + .popsection"); + +# undef INSN0 +# undef INSN +# undef TABLE_ENT_0 +# undef TABLE_ENT +#elif defined(__SSE2__) +# define INSNS_8 "punpcklqdq %xmm1, %xmm0" +# define INSNS(N) "psrldq $"#N", %xmm0\n\t" \ + "pslldq $(16-"#N"), %xmm1\n\t" \ + "por %xmm1, %xmm0" +# define TABLE_ENT_0 "ret\n\t" +# define TABLE_ENT_8 ".balign 16\n\t" INSNS_8 "\n\tret\n\t" +# define TABLE_ENT(N) ".balign 16\n\t" INSNS(N) "\n\tret\n\t" + +asm(".pushsection .text\n\ + .balign 16\n\ + .globl GTM_pshift_table\n\ + .hidden GTM_pshift_table\n\ + .type GTM_pshift_table, @function\n\ +GTM_pshift_table:\n\t" + TABLE_ENT_0 + TABLE_ENT(1) + TABLE_ENT(2) + TABLE_ENT(3) + TABLE_ENT(4) + TABLE_ENT(5) + TABLE_ENT(6) + TABLE_ENT(7) + TABLE_ENT_8 + TABLE_ENT(9) + TABLE_ENT(10) + TABLE_ENT(11) + TABLE_ENT(12) + TABLE_ENT(13) + TABLE_ENT(14) + TABLE_ENT(15) + ".balign 8\n\ + .size GTM_pshift_table, .-GTM_pshift_table\n\ + .popsection"); + +# undef INSNS_8 +# undef INSNS +# undef TABLE_ENT_0 +# undef TABLE_ENT_8 +# undef TABLE_ENT +#endif diff --git a/libitm/configure b/libitm/configure new file mode 100644 index 00000000000..08d2993e06e --- /dev/null +++ b/libitm/configure @@ -0,0 +1,20249 @@ +#! /bin/sh +# Guess values for system-dependent variables and create Makefiles. +# Generated by GNU Autoconf 2.64 for GNU TM Runtime Library 1.0. +# +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, +# 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software +# Foundation, Inc. +# +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +if test "x$CONFIG_SHELL" = x; then + as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which + # is contrary to our usage. Disable this feature. + alias -g '\${1+\"\$@\"}'='\"\$@\"' + setopt NO_GLOB_SUBST +else + case \`(set -o) 2>/dev/null\` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi +" + as_required="as_fn_return () { (exit \$1); } +as_fn_success () { as_fn_return 0; } +as_fn_failure () { as_fn_return 1; } +as_fn_ret_success () { return 0; } +as_fn_ret_failure () { return 1; } + +exitcode=0 +as_fn_success || { exitcode=1; echo as_fn_success failed.; } +as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } +as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } +as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } +if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : + +else + exitcode=1; echo positional parameters were not saved. +fi +test x\$exitcode = x0 || exit 1" + as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO + as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO + eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && + test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 + + test -n \"\${ZSH_VERSION+set}\${BASH_VERSION+set}\" || ( + ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' + ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO + ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO + PATH=/empty FPATH=/empty; export PATH FPATH + test \"X\`printf %s \$ECHO\`\" = \"X\$ECHO\" \\ + || test \"X\`print -r -- \$ECHO\`\" = \"X\$ECHO\" ) || exit 1 +test \$(( 1 + 1 )) = 2 || exit 1" + if (eval "$as_required") 2>/dev/null; then : + as_have_required=yes +else + as_have_required=no +fi + if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : + +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +as_found=false +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + as_found=: + case $as_dir in #( + /*) + for as_base in sh bash ksh sh5; do + # Try only shells that exist, to save several forks. + as_shell=$as_dir/$as_base + if { test -f "$as_shell" || test -f "$as_shell.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : + CONFIG_SHELL=$as_shell as_have_required=yes + if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : + break 2 +fi +fi + done;; + esac + as_found=false +done +$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : + CONFIG_SHELL=$SHELL as_have_required=yes +fi; } +IFS=$as_save_IFS + + + if test "x$CONFIG_SHELL" != x; then : + # We cannot yet assume a decent shell, so we have to provide a + # neutralization value for shells without unset; and this also + # works around shells that cannot unset nonexistent variables. + BASH_ENV=/dev/null + ENV=/dev/null + (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV + export CONFIG_SHELL + exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"} +fi + + if test x$as_have_required = xno; then : + $as_echo "$0: This script requires a shell more modern than all" + $as_echo "$0: the shells that I found on your system." + if test x${ZSH_VERSION+set} = xset ; then + $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" + $as_echo "$0: be upgraded to zsh 4.3.4 or later." + else + $as_echo "$0: Please tell bug-autoconf@gnu.org about your system, +$0: including any error possibly output before this +$0: message. Then install a modern shell, or manually run +$0: the script under such a shell if you do have one." + fi + exit 1 +fi +fi +fi +SHELL=${CONFIG_SHELL-/bin/sh} +export SHELL +# Unset more variables known to interfere with behavior of common tools. +CLICOLOR_FORCE= GREP_OPTIONS= +unset CLICOLOR_FORCE GREP_OPTIONS + +## --------------------- ## +## M4sh Shell Functions. ## +## --------------------- ## +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error "cannot create directory $as_dir" + + +} # as_fn_mkdir_p +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +# as_fn_error ERROR [LINENO LOG_FD] +# --------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with status $?, using 1 if that was 0. +as_fn_error () +{ + as_status=$?; test $as_status -eq 0 && as_status=1 + if test "$3"; then + as_lineno=${as_lineno-"$2"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $1" >&$3 + fi + $as_echo "$as_me: error: $1" >&2 + as_fn_exit $as_status +} # as_fn_error + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + + + as_lineno_1=$LINENO as_lineno_1a=$LINENO + as_lineno_2=$LINENO as_lineno_2a=$LINENO + eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && + test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { + # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) + sed -n ' + p + /[$]LINENO/= + ' <$as_myself | + sed ' + s/[$]LINENO.*/&-/ + t lineno + b + :lineno + N + :loop + s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ + t loop + s/-\n.*// + ' >$as_me.lineno && + chmod +x "$as_me.lineno" || + { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } + + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensitive to this). + . "./$as_me.lineno" + # Exit status is that of the last command. + exit +} + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -p'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -p' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -p' + fi +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +if test -x / >/dev/null 2>&1; then + as_test_x='test -x' +else + if ls -dL / >/dev/null 2>&1; then + as_ls_L_option=L + else + as_ls_L_option= + fi + as_test_x=' + eval sh -c '\'' + if test -d "$1"; then + test -d "$1/."; + else + case $1 in #( + -*)set "./$1";; + esac; + case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #(( + ???[sx]*):;;*)false;;esac;fi + '\'' sh + ' +fi +as_executable_p=$as_test_x + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + +SHELL=${CONFIG_SHELL-/bin/sh} + + +exec 7<&0 </dev/null 6>&1 + +# Name of the host. +# hostname on some systems (SVR3.2, Linux) returns a bogus exit status, +# so uname gets run too. +ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` + +# +# Initializations. +# +ac_default_prefix=/usr/local +ac_clean_files= +ac_config_libobj_dir=. +LIBOBJS= +cross_compiling=no +subdirs= +MFLAGS= +MAKEFLAGS= + +# Identity of this package. +PACKAGE_NAME='GNU TM Runtime Library' +PACKAGE_TARNAME='libitm' +PACKAGE_VERSION='1.0' +PACKAGE_STRING='GNU TM Runtime Library 1.0' +PACKAGE_BUGREPORT='' +PACKAGE_URL='http://www.gnu.org/software/libitm/' + +# Factoring default headers for most tests. +ac_includes_default="\ +#include <stdio.h> +#ifdef HAVE_SYS_TYPES_H +# include <sys/types.h> +#endif +#ifdef HAVE_SYS_STAT_H +# include <sys/stat.h> +#endif +#ifdef STDC_HEADERS +# include <stdlib.h> +# include <stddef.h> +#else +# ifdef HAVE_STDLIB_H +# include <stdlib.h> +# endif +#endif +#ifdef HAVE_STRING_H +# if !defined STDC_HEADERS && defined HAVE_MEMORY_H +# include <memory.h> +# endif +# include <string.h> +#endif +#ifdef HAVE_STRINGS_H +# include <strings.h> +#endif +#ifdef HAVE_INTTYPES_H +# include <inttypes.h> +#endif +#ifdef HAVE_STDINT_H +# include <stdint.h> +#endif +#ifdef HAVE_UNISTD_H +# include <unistd.h> +#endif" + +ac_subst_vars='am__EXEEXT_FALSE +am__EXEEXT_TRUE +LTLIBOBJS +LIBOBJS +ARCH_FUTEX_FALSE +ARCH_FUTEX_TRUE +ARCH_X86_FALSE +ARCH_X86_TRUE +link_itm +XLDFLAGS +XCFLAGS +config_path +LIBITM_BUILD_VERSIONED_SHLIB_FALSE +LIBITM_BUILD_VERSIONED_SHLIB_TRUE +OPT_LDFLAGS +SECTION_LDFLAGS +libtool_VERSION +MAINT +MAINTAINER_MODE_FALSE +MAINTAINER_MODE_TRUE +enable_static +enable_shared +CXXCPP +CPP +OTOOL64 +OTOOL +LIPO +NMEDIT +DSYMUTIL +OBJDUMP +LN_S +ac_ct_DUMPBIN +DUMPBIN +LD +FGREP +EGREP +GREP +SED +LIBTOOL +BUILD_INFO_FALSE +BUILD_INFO_TRUE +PERL +RANLIB +NM +AR +am__fastdepCCAS_FALSE +am__fastdepCCAS_TRUE +CCASDEPMODE +CCASFLAGS +CCAS +am__fastdepCXX_FALSE +am__fastdepCXX_TRUE +CXXDEPMODE +ac_ct_CXX +CXXFLAGS +CXX +am__fastdepCC_FALSE +am__fastdepCC_TRUE +CCDEPMODE +AMDEPBACKSLASH +AMDEP_FALSE +AMDEP_TRUE +am__quote +am__include +DEPDIR +OBJEXT +EXEEXT +ac_ct_CC +CPPFLAGS +LDFLAGS +CFLAGS +CC +toolexeclibdir +toolexecdir +multi_basedir +am__untar +am__tar +AMTAR +am__leading_dot +SET_MAKE +AWK +mkdir_p +MKDIR_P +INSTALL_STRIP_PROGRAM +STRIP +install_sh +MAKEINFO +AUTOHEADER +AUTOMAKE +AUTOCONF +ACLOCAL +VERSION +PACKAGE +CYGPATH_W +am__isrc +INSTALL_DATA +INSTALL_SCRIPT +INSTALL_PROGRAM +target_os +target_vendor +target_cpu +target +host_os +host_vendor +host_cpu +host +build_os +build_vendor +build_cpu +build +GENINSRC_FALSE +GENINSRC_TRUE +target_alias +host_alias +build_alias +LIBS +ECHO_T +ECHO_N +ECHO_C +DEFS +mandir +localedir +libdir +psdir +pdfdir +dvidir +htmldir +infodir +docdir +oldincludedir +includedir +localstatedir +sharedstatedir +sysconfdir +datadir +datarootdir +libexecdir +sbindir +bindir +program_transform_name +prefix +exec_prefix +PACKAGE_URL +PACKAGE_BUGREPORT +PACKAGE_STRING +PACKAGE_VERSION +PACKAGE_TARNAME +PACKAGE_NAME +PATH_SEPARATOR +SHELL' +ac_subst_files='' +ac_user_opts=' +enable_option_checking +enable_version_specific_runtime_libs +enable_generated_files_in_srcdir +enable_multilib +enable_dependency_tracking +enable_shared +enable_static +with_pic +enable_fast_install +with_gnu_ld +enable_libtool_lock +enable_maintainer_mode +enable_linux_futex +enable_tls +enable_symvers +' + ac_precious_vars='build_alias +host_alias +target_alias +CPP +CPPFLAGS +CXXCPP' + + +# Initialize some variables set by options. +ac_init_help= +ac_init_version=false +ac_unrecognized_opts= +ac_unrecognized_sep= +# The variables have the same names as the options, with +# dashes changed to underlines. +cache_file=/dev/null +exec_prefix=NONE +no_create= +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +verbose= +x_includes=NONE +x_libraries=NONE + +# Installation directory options. +# These are left unexpanded so users can "make install exec_prefix=/foo" +# and all the variables that are supposed to be based on exec_prefix +# by default will actually change. +# Use braces instead of parens because sh, perl, etc. also accept them. +# (The list follows the same order as the GNU Coding Standards.) +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datarootdir='${prefix}/share' +datadir='${datarootdir}' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +includedir='${prefix}/include' +oldincludedir='/usr/include' +docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' +infodir='${datarootdir}/info' +htmldir='${docdir}' +dvidir='${docdir}' +pdfdir='${docdir}' +psdir='${docdir}' +libdir='${exec_prefix}/lib' +localedir='${datarootdir}/locale' +mandir='${datarootdir}/man' + +ac_prev= +ac_dashdash= +for ac_option +do + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval $ac_prev=\$ac_option + ac_prev= + continue + fi + + case $ac_option in + *=*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; + *) ac_optarg=yes ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case $ac_dashdash$ac_option in + --) + ac_dashdash=yes ;; + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir=$ac_optarg ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build_alias ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build_alias=$ac_optarg ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file=$ac_optarg ;; + + --config-cache | -C) + cache_file=config.cache ;; + + -datadir | --datadir | --datadi | --datad) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=*) + datadir=$ac_optarg ;; + + -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ + | --dataroo | --dataro | --datar) + ac_prev=datarootdir ;; + -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ + | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) + datarootdir=$ac_optarg ;; + + -disable-* | --disable-*) + ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=no ;; + + -docdir | --docdir | --docdi | --doc | --do) + ac_prev=docdir ;; + -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) + docdir=$ac_optarg ;; + + -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) + ac_prev=dvidir ;; + -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) + dvidir=$ac_optarg ;; + + -enable-* | --enable-*) + ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=\$ac_optarg ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix=$ac_optarg ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he | -h) + ac_init_help=long ;; + -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) + ac_init_help=recursive ;; + -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) + ac_init_help=short ;; + + -host | --host | --hos | --ho) + ac_prev=host_alias ;; + -host=* | --host=* | --hos=* | --ho=*) + host_alias=$ac_optarg ;; + + -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) + ac_prev=htmldir ;; + -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ + | --ht=*) + htmldir=$ac_optarg ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir=$ac_optarg ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir=$ac_optarg ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir=$ac_optarg ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir=$ac_optarg ;; + + -localedir | --localedir | --localedi | --localed | --locale) + ac_prev=localedir ;; + -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) + localedir=$ac_optarg ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst | --locals) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) + localstatedir=$ac_optarg ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir=$ac_optarg ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c | -n) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir=$ac_optarg ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix=$ac_optarg ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix=$ac_optarg ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix=$ac_optarg ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name=$ac_optarg ;; + + -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) + ac_prev=pdfdir ;; + -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) + pdfdir=$ac_optarg ;; + + -psdir | --psdir | --psdi | --psd | --ps) + ac_prev=psdir ;; + -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) + psdir=$ac_optarg ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir=$ac_optarg ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir=$ac_optarg ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site=$ac_optarg ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir=$ac_optarg ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir=$ac_optarg ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target_alias ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target_alias=$ac_optarg ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers | -V) + ac_init_version=: ;; + + -with-* | --with-*) + ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=\$ac_optarg ;; + + -without-* | --without-*) + ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=no ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes=$ac_optarg ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries=$ac_optarg ;; + + -*) as_fn_error "unrecognized option: \`$ac_option' +Try \`$0 --help' for more information." + ;; + + *=*) + ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` + # Reject names that are not valid shell variable names. + case $ac_envvar in #( + '' | [0-9]* | *[!_$as_cr_alnum]* ) + as_fn_error "invalid variable name: \`$ac_envvar'" ;; + esac + eval $ac_envvar=\$ac_optarg + export $ac_envvar ;; + + *) + # FIXME: should be removed in autoconf 3.0. + $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 + expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && + $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 + : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option} + ;; + + esac +done + +if test -n "$ac_prev"; then + ac_option=--`echo $ac_prev | sed 's/_/-/g'` + as_fn_error "missing argument to $ac_option" +fi + +if test -n "$ac_unrecognized_opts"; then + case $enable_option_checking in + no) ;; + fatal) as_fn_error "unrecognized options: $ac_unrecognized_opts" ;; + *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; + esac +fi + +# Check all directory arguments for consistency. +for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ + datadir sysconfdir sharedstatedir localstatedir includedir \ + oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ + libdir localedir mandir +do + eval ac_val=\$$ac_var + # Remove trailing slashes. + case $ac_val in + */ ) + ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` + eval $ac_var=\$ac_val;; + esac + # Be sure to have absolute directory names. + case $ac_val in + [\\/$]* | ?:[\\/]* ) continue;; + NONE | '' ) case $ac_var in *prefix ) continue;; esac;; + esac + as_fn_error "expected an absolute directory name for --$ac_var: $ac_val" +done + +# There might be people who depend on the old broken behavior: `$host' +# used to hold the argument of --host etc. +# FIXME: To remove some day. +build=$build_alias +host=$host_alias +target=$target_alias + +# FIXME: To remove some day. +if test "x$host_alias" != x; then + if test "x$build_alias" = x; then + cross_compiling=maybe + $as_echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host. + If a cross compiler is detected then cross compile mode will be used." >&2 + elif test "x$build_alias" != "x$host_alias"; then + cross_compiling=yes + fi +fi + +ac_tool_prefix= +test -n "$host_alias" && ac_tool_prefix=$host_alias- + +test "$silent" = yes && exec 6>/dev/null + + +ac_pwd=`pwd` && test -n "$ac_pwd" && +ac_ls_di=`ls -di .` && +ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || + as_fn_error "working directory cannot be determined" +test "X$ac_ls_di" = "X$ac_pwd_ls_di" || + as_fn_error "pwd does not report name of working directory" + + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then the parent directory. + ac_confdir=`$as_dirname -- "$as_myself" || +$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_myself" : 'X\(//\)[^/]' \| \ + X"$as_myself" : 'X\(//\)$' \| \ + X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_myself" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + srcdir=$ac_confdir + if test ! -r "$srcdir/$ac_unique_file"; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r "$srcdir/$ac_unique_file"; then + test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." + as_fn_error "cannot find sources ($ac_unique_file) in $srcdir" +fi +ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" +ac_abs_confdir=`( + cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error "$ac_msg" + pwd)` +# When building in place, set srcdir=. +if test "$ac_abs_confdir" = "$ac_pwd"; then + srcdir=. +fi +# Remove unnecessary trailing slashes from srcdir. +# Double slashes in file names in object file debugging info +# mess up M-x gdb in Emacs. +case $srcdir in +*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; +esac +for ac_var in $ac_precious_vars; do + eval ac_env_${ac_var}_set=\${${ac_var}+set} + eval ac_env_${ac_var}_value=\$${ac_var} + eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} + eval ac_cv_env_${ac_var}_value=\$${ac_var} +done + +# +# Report the --help message. +# +if test "$ac_init_help" = "long"; then + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat <<_ACEOF +\`configure' configures GNU TM Runtime Library 1.0 to adapt to many kinds of systems. + +Usage: $0 [OPTION]... [VAR=VALUE]... + +To assign environment variables (e.g., CC, CFLAGS...), specify them as +VAR=VALUE. See below for descriptions of some of the useful variables. + +Defaults for the options are specified in brackets. + +Configuration: + -h, --help display this help and exit + --help=short display options specific to this package + --help=recursive display the short help of all the included packages + -V, --version display version information and exit + -q, --quiet, --silent do not print \`checking...' messages + --cache-file=FILE cache test results in FILE [disabled] + -C, --config-cache alias for \`--cache-file=config.cache' + -n, --no-create do not create output files + --srcdir=DIR find the sources in DIR [configure dir or \`..'] + +Installation directories: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [PREFIX] + +By default, \`make install' will install all the files in +\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify +an installation prefix other than \`$ac_default_prefix' using \`--prefix', +for instance \`--prefix=\$HOME'. + +For better control, use the options below. + +Fine tuning of the installation directories: + --bindir=DIR user executables [EPREFIX/bin] + --sbindir=DIR system admin executables [EPREFIX/sbin] + --libexecdir=DIR program executables [EPREFIX/libexec] + --sysconfdir=DIR read-only single-machine data [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] + --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --libdir=DIR object code libraries [EPREFIX/lib] + --includedir=DIR C header files [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc [/usr/include] + --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] + --datadir=DIR read-only architecture-independent data [DATAROOTDIR] + --infodir=DIR info documentation [DATAROOTDIR/info] + --localedir=DIR locale-dependent data [DATAROOTDIR/locale] + --mandir=DIR man documentation [DATAROOTDIR/man] + --docdir=DIR documentation root [DATAROOTDIR/doc/libitm] + --htmldir=DIR html documentation [DOCDIR] + --dvidir=DIR dvi documentation [DOCDIR] + --pdfdir=DIR pdf documentation [DOCDIR] + --psdir=DIR ps documentation [DOCDIR] +_ACEOF + + cat <<\_ACEOF + +Program names: + --program-prefix=PREFIX prepend PREFIX to installed program names + --program-suffix=SUFFIX append SUFFIX to installed program names + --program-transform-name=PROGRAM run sed PROGRAM on installed program names + +System types: + --build=BUILD configure for building on BUILD [guessed] + --host=HOST cross-compile to build programs to run on HOST [BUILD] + --target=TARGET configure for building compilers for TARGET [HOST] +_ACEOF +fi + +if test -n "$ac_init_help"; then + case $ac_init_help in + short | recursive ) echo "Configuration of GNU TM Runtime Library 1.0:";; + esac + cat <<\_ACEOF + +Optional Features: + --disable-option-checking ignore unrecognized --enable/--with options + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --enable-version-specific-runtime-libs + Specify that runtime libraries should be installed + in a compiler-specific directory [default=no] + --enable-generated-files-in-srcdir + put copies of generated files in source dir intended + for creating source tarballs for users without + texinfo bison or flex. [default=no] + --enable-multilib build many library versions (default) + --disable-dependency-tracking speeds up one-time build + --enable-dependency-tracking do not reject slow dependency extractors + --enable-shared[=PKGS] build shared libraries [default=yes] + --enable-static[=PKGS] build static libraries [default=yes] + --enable-fast-install[=PKGS] + optimize for fast installation [default=yes] + --disable-libtool-lock avoid locking (might break parallel builds) + --enable-maintainer-mode enable make rules and dependencies not useful + (and sometimes confusing) to the casual installer + --enable-linux-futex use the Linux futex system call [default=default] + --enable-tls Use thread-local storage [default=yes] + --enable-symvers=STYLE enables symbol versioning of the shared library + [default=yes] + +Optional Packages: + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --with-pic try to use only PIC/non-PIC objects [default=use + both] + --with-gnu-ld assume the C compiler uses GNU ld [default=no] + +Some influential environment variables: + CC C compiler command + CFLAGS C compiler flags + LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a + nonstandard directory <lib dir> + LIBS libraries to pass to the linker, e.g. -l<library> + CPPFLAGS C/C++/Objective C preprocessor flags, e.g. -I<include dir> if + you have headers in a nonstandard directory <include dir> + CXX C++ compiler command + CXXFLAGS C++ compiler flags + CCAS assembler compiler command (defaults to CC) + CCASFLAGS assembler compiler flags (defaults to CFLAGS) + CPP C preprocessor + CXXCPP C++ preprocessor + +Use these variables to override the choices made by `configure' or to help +it to find libraries and programs with nonstandard names/locations. + +Report bugs to the package provider. +GNU TM Runtime Library home page: <http://www.gnu.org/software/libitm/>. +General help using GNU software: <http://www.gnu.org/gethelp/>. +_ACEOF +ac_status=$? +fi + +if test "$ac_init_help" = "recursive"; then + # If there are subdirs, report their specific --help. + for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue + test -d "$ac_dir" || + { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || + continue + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + cd "$ac_dir" || { ac_status=$?; continue; } + # Check for guested configure. + if test -f "$ac_srcdir/configure.gnu"; then + echo && + $SHELL "$ac_srcdir/configure.gnu" --help=recursive + elif test -f "$ac_srcdir/configure"; then + echo && + $SHELL "$ac_srcdir/configure" --help=recursive + else + $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 + fi || ac_status=$? + cd "$ac_pwd" || { ac_status=$?; break; } + done +fi + +test -n "$ac_init_help" && exit $ac_status +if $ac_init_version; then + cat <<\_ACEOF +GNU TM Runtime Library configure 1.0 +generated by GNU Autoconf 2.64 + +Copyright (C) 2009 Free Software Foundation, Inc. +This configure script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it. +_ACEOF + exit +fi + +## ------------------------ ## +## Autoconf initialization. ## +## ------------------------ ## + +# ac_fn_c_try_compile LINENO +# -------------------------- +# Try to compile conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext + if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + return $ac_retval + +} # ac_fn_c_try_compile + +# ac_fn_cxx_try_compile LINENO +# ---------------------------- +# Try to compile conftest.$ac_ext, and return whether this succeeded. +ac_fn_cxx_try_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext + if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_cxx_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + return $ac_retval + +} # ac_fn_cxx_try_compile + +# ac_fn_c_try_link LINENO +# ----------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_link () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext conftest$ac_exeext + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information + # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would + # interfere with the next link command; also delete a directory that is + # left behind by Apple's compiler. We do this before executing the actions. + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + return $ac_retval + +} # ac_fn_c_try_link + +# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES +# ------------------------------------------------------- +# Tests whether HEADER exists and can be compiled using the include files in +# INCLUDES, setting the cache variable VAR accordingly. +ac_fn_c_check_header_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + +} # ac_fn_c_check_header_compile + +# ac_fn_c_try_cpp LINENO +# ---------------------- +# Try to preprocess conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_cpp () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } >/dev/null && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + return $ac_retval + +} # ac_fn_c_try_cpp + +# ac_fn_c_try_run LINENO +# ---------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes +# that executables *can* be run. +ac_fn_c_try_run () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then : + ac_retval=0 +else + $as_echo "$as_me: program exited with status $ac_status" >&5 + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=$ac_status +fi + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + return $ac_retval + +} # ac_fn_c_try_run + +# ac_fn_c_check_func LINENO FUNC VAR +# ---------------------------------- +# Tests whether FUNC exists, setting the cache variable VAR accordingly +ac_fn_c_check_func () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +/* Define $2 to an innocuous variant, in case <limits.h> declares $2. + For example, HP-UX 11i <limits.h> declares gettimeofday. */ +#define $2 innocuous_$2 + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $2 (); below. + Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + <limits.h> exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + +#undef $2 + +/* 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 $2 (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$2 || defined __stub___$2 +choke me +#endif + +int +main () +{ +return $2 (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + +} # ac_fn_c_check_func + +# ac_fn_cxx_try_cpp LINENO +# ------------------------ +# Try to preprocess conftest.$ac_ext, and return whether this succeeded. +ac_fn_cxx_try_cpp () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } >/dev/null && { + test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" || + test ! -s conftest.err + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + return $ac_retval + +} # ac_fn_cxx_try_cpp + +# ac_fn_cxx_try_link LINENO +# ------------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. +ac_fn_cxx_try_link () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext conftest$ac_exeext + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_cxx_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information + # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would + # interfere with the next link command; also delete a directory that is + # left behind by Apple's compiler. We do this before executing the actions. + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + return $ac_retval + +} # ac_fn_cxx_try_link + +# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES +# ------------------------------------------------------- +# Tests whether HEADER exists, giving a warning if it cannot be compiled using +# the include files in INCLUDES and setting the cache variable VAR +# accordingly. +ac_fn_c_check_header_mongrel () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then : + $as_echo_n "(cached) " >&6 +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +else + # Is the header compilable? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 +$as_echo_n "checking $2 usability... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_header_compiler=yes +else + ac_header_compiler=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 +$as_echo "$ac_header_compiler" >&6; } + +# Is the header present? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 +$as_echo_n "checking $2 presence... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <$2> +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + ac_header_preproc=yes +else + ac_header_preproc=no +fi +rm -f conftest.err conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 +$as_echo "$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #(( + yes:no: ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 +$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} + ;; + no:yes:* ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 +$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 +$as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 +$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 +$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} + ;; +esac + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then : + $as_echo_n "(cached) " >&6 +else + eval "$3=\$ac_header_compiler" +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +fi + eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + +} # ac_fn_c_check_header_mongrel + +# ac_fn_c_check_type LINENO TYPE VAR INCLUDES +# ------------------------------------------- +# Tests whether TYPE exists after having included INCLUDES, setting cache +# variable VAR accordingly. +ac_fn_c_check_type () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then : + $as_echo_n "(cached) " >&6 +else + eval "$3=no" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +if (sizeof ($2)) + return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +if (sizeof (($2))) + return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +else + eval "$3=yes" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + +} # ac_fn_c_check_type + +# ac_fn_c_compute_int LINENO EXPR VAR INCLUDES +# -------------------------------------------- +# Tries to find the compile-time value of EXPR in a program that includes +# INCLUDES, setting VAR accordingly. Returns whether the value could be +# computed +ac_fn_c_compute_int () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if test "$cross_compiling" = yes; then + # Depending upon the size, compute the lo and hi bounds. +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +static int test_array [1 - 2 * !(($2) >= 0)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_lo=0 ac_mid=0 + while :; do + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +static int test_array [1 - 2 * !(($2) <= $ac_mid)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_hi=$ac_mid; break +else + as_fn_arith $ac_mid + 1 && ac_lo=$as_val + if test $ac_lo -le $ac_mid; then + ac_lo= ac_hi= + break + fi + as_fn_arith 2 '*' $ac_mid + 1 && ac_mid=$as_val +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + done +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +static int test_array [1 - 2 * !(($2) < 0)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_hi=-1 ac_mid=-1 + while :; do + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +static int test_array [1 - 2 * !(($2) >= $ac_mid)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_lo=$ac_mid; break +else + as_fn_arith '(' $ac_mid ')' - 1 && ac_hi=$as_val + if test $ac_mid -le $ac_hi; then + ac_lo= ac_hi= + break + fi + as_fn_arith 2 '*' $ac_mid && ac_mid=$as_val +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + done +else + ac_lo= ac_hi= +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +# Binary search between lo and hi bounds. +while test "x$ac_lo" != "x$ac_hi"; do + as_fn_arith '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo && ac_mid=$as_val + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +static int test_array [1 - 2 * !(($2) <= $ac_mid)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_hi=$ac_mid +else + as_fn_arith '(' $ac_mid ')' + 1 && ac_lo=$as_val +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +done +case $ac_lo in #(( +?*) eval "$3=\$ac_lo"; ac_retval=0 ;; +'') ac_retval=1 ;; +esac + else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +static long int longval () { return $2; } +static unsigned long int ulongval () { return $2; } +#include <stdio.h> +#include <stdlib.h> +int +main () +{ + + FILE *f = fopen ("conftest.val", "w"); + if (! f) + return 1; + if (($2) < 0) + { + long int i = longval (); + if (i != ($2)) + return 1; + fprintf (f, "%ld", i); + } + else + { + unsigned long int i = ulongval (); + if (i != ($2)) + return 1; + fprintf (f, "%lu", i); + } + /* Do not output a trailing newline, as this causes \r\n confusion + on some platforms. */ + return ferror (f) || fclose (f) != 0; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + echo >>conftest.val; read $3 <conftest.val; ac_retval=0 +else + ac_retval=1 +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +rm -f conftest.val + + fi + eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + return $ac_retval + +} # ac_fn_c_compute_int +cat >config.log <<_ACEOF +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. + +It was created by GNU TM Runtime Library $as_me 1.0, which was +generated by GNU Autoconf 2.64. Invocation command line was + + $ $0 $@ + +_ACEOF +exec 5>>config.log +{ +cat <<_ASUNAME +## --------- ## +## Platform. ## +## --------- ## + +hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` + +/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` +/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` +/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` +/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` + +_ASUNAME + +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + $as_echo "PATH: $as_dir" + done +IFS=$as_save_IFS + +} >&5 + +cat >&5 <<_ACEOF + + +## ----------- ## +## Core tests. ## +## ----------- ## + +_ACEOF + + +# Keep a trace of the command line. +# Strip out --no-create and --no-recursion so they do not pile up. +# Strip out --silent because we don't want to record it for future runs. +# Also quote any args containing shell meta-characters. +# Make two passes to allow for proper duplicate-argument suppression. +ac_configure_args= +ac_configure_args0= +ac_configure_args1= +ac_must_keep_next=false +for ac_pass in 1 2 +do + for ac_arg + do + case $ac_arg in + -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + continue ;; + *\'*) + ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + case $ac_pass in + 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; + 2) + as_fn_append ac_configure_args1 " '$ac_arg'" + if test $ac_must_keep_next = true; then + ac_must_keep_next=false # Got value, back to normal. + else + case $ac_arg in + *=* | --config-cache | -C | -disable-* | --disable-* \ + | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ + | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ + | -with-* | --with-* | -without-* | --without-* | --x) + case "$ac_configure_args0 " in + "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; + esac + ;; + -* ) ac_must_keep_next=true ;; + esac + fi + as_fn_append ac_configure_args " '$ac_arg'" + ;; + esac + done +done +{ ac_configure_args0=; unset ac_configure_args0;} +{ ac_configure_args1=; unset ac_configure_args1;} + +# When interrupted or exit'd, cleanup temporary files, and complete +# config.log. We remove comments because anyway the quotes in there +# would cause problems or look ugly. +# WARNING: Use '\'' to represent an apostrophe within the trap. +# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. +trap 'exit_status=$? + # Save into config.log some information that might help in debugging. + { + echo + + cat <<\_ASBOX +## ---------------- ## +## Cache variables. ## +## ---------------- ## +_ASBOX + echo + # The following way of writing the cache mishandles newlines in values, +( + for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + (set) 2>&1 | + case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + sed -n \ + "s/'\''/'\''\\\\'\'''\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" + ;; #( + *) + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) + echo + + cat <<\_ASBOX +## ----------------- ## +## Output variables. ## +## ----------------- ## +_ASBOX + echo + for ac_var in $ac_subst_vars + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + + if test -n "$ac_subst_files"; then + cat <<\_ASBOX +## ------------------- ## +## File substitutions. ## +## ------------------- ## +_ASBOX + echo + for ac_var in $ac_subst_files + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + fi + + if test -s confdefs.h; then + cat <<\_ASBOX +## ----------- ## +## confdefs.h. ## +## ----------- ## +_ASBOX + echo + cat confdefs.h + echo + fi + test "$ac_signal" != 0 && + $as_echo "$as_me: caught signal $ac_signal" + $as_echo "$as_me: exit $exit_status" + } >&5 + rm -f core *.core core.conftest.* && + rm -f -r conftest* confdefs* conf$$* $ac_clean_files && + exit $exit_status +' 0 +for ac_signal in 1 2 13 15; do + trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal +done +ac_signal=0 + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -f -r conftest* confdefs.h + +$as_echo "/* confdefs.h */" > confdefs.h + +# Predefined preprocessor variables. + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_NAME "$PACKAGE_NAME" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_TARNAME "$PACKAGE_TARNAME" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_VERSION "$PACKAGE_VERSION" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_STRING "$PACKAGE_STRING" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_URL "$PACKAGE_URL" +_ACEOF + + +# Let the site file select an alternate cache file if it wants to. +# Prefer an explicitly selected file to automatically selected ones. +ac_site_file1=NONE +ac_site_file2=NONE +if test -n "$CONFIG_SITE"; then + ac_site_file1=$CONFIG_SITE +elif test "x$prefix" != xNONE; then + ac_site_file1=$prefix/share/config.site + ac_site_file2=$prefix/etc/config.site +else + ac_site_file1=$ac_default_prefix/share/config.site + ac_site_file2=$ac_default_prefix/etc/config.site +fi +for ac_site_file in "$ac_site_file1" "$ac_site_file2" +do + test "x$ac_site_file" = xNONE && continue + if test -r "$ac_site_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 +$as_echo "$as_me: loading site script $ac_site_file" >&6;} + sed 's/^/| /' "$ac_site_file" >&5 + . "$ac_site_file" + fi +done + +if test -r "$cache_file"; then + # Some versions of bash will fail to source /dev/null (special + # files actually), so we avoid doing that. + if test -f "$cache_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 +$as_echo "$as_me: loading cache $cache_file" >&6;} + case $cache_file in + [\\/]* | ?:[\\/]* ) . "$cache_file";; + *) . "./$cache_file";; + esac + fi +else + { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 +$as_echo "$as_me: creating cache $cache_file" >&6;} + >$cache_file +fi + +# Check that the precious variables saved in the cache have kept the same +# value. +ac_cache_corrupted=false +for ac_var in $ac_precious_vars; do + eval ac_old_set=\$ac_cv_env_${ac_var}_set + eval ac_new_set=\$ac_env_${ac_var}_set + eval ac_old_val=\$ac_cv_env_${ac_var}_value + eval ac_new_val=\$ac_env_${ac_var}_value + case $ac_old_set,$ac_new_set in + set,) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,set) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,);; + *) + if test "x$ac_old_val" != "x$ac_new_val"; then + # differences in whitespace do not lead to failure. + ac_old_val_w=`echo x $ac_old_val` + ac_new_val_w=`echo x $ac_new_val` + if test "$ac_old_val_w" != "$ac_new_val_w"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 +$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} + ac_cache_corrupted=: + else + { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 +$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} + eval $ac_var=\$ac_old_val + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 +$as_echo "$as_me: former value: \`$ac_old_val'" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 +$as_echo "$as_me: current value: \`$ac_new_val'" >&2;} + fi;; + esac + # Pass precious variables to config.status. + if test "$ac_new_set" = set; then + case $ac_new_val in + *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; + *) ac_arg=$ac_var=$ac_new_val ;; + esac + case " $ac_configure_args " in + *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. + *) as_fn_append ac_configure_args " '$ac_arg'" ;; + esac + fi +done +if $ac_cache_corrupted; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 +$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} + as_fn_error "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 +fi +## -------------------- ## +## Main body of script. ## +## -------------------- ## + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + + + +ac_config_headers="$ac_config_headers config.h" + + +# ------- +# Options +# ------- + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for --enable-version-specific-runtime-libs" >&5 +$as_echo_n "checking for --enable-version-specific-runtime-libs... " >&6; } + # Check whether --enable-version-specific-runtime-libs was given. +if test "${enable_version_specific_runtime_libs+set}" = set; then : + enableval=$enable_version_specific_runtime_libs; + case "$enableval" in + yes|no) ;; + *) as_fn_error "Unknown argument to enable/disable version-specific-runtime-libs" "$LINENO" 5 ;; + esac + +else + enable_version_specific_runtime_libs=no +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_version_specific_runtime_libs" >&5 +$as_echo "$enable_version_specific_runtime_libs" >&6; } + +# We would like our source tree to be readonly. However when releases or +# pre-releases are generated, the flex/bison generated files as well as the +# various formats of manuals need to be included along with the rest of the +# sources. Therefore we have --enable-generated-files-in-srcdir to do +# just that. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for --enable-generated-files-in-srcdir" >&5 +$as_echo_n "checking for --enable-generated-files-in-srcdir... " >&6; } + # Check whether --enable-generated-files-in-srcdir was given. +if test "${enable_generated_files_in_srcdir+set}" = set; then : + enableval=$enable_generated_files_in_srcdir; + case "$enableval" in + yes|no) ;; + *) as_fn_error "Unknown argument to enable/disable generated-files-in-srcdir" "$LINENO" 5 ;; + esac + +else + enable_generated_files_in_srcdir=no +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_generated_files_in_srcdir" >&5 +$as_echo "$enable_generated_files_in_srcdir" >&6; } + if test "$enable_generated_files_in_srcdir" = yes; then + GENINSRC_TRUE= + GENINSRC_FALSE='#' +else + GENINSRC_TRUE='#' + GENINSRC_FALSE= +fi + + + +# ------- +# ------- + +# Gets build, host, target, *_vendor, *_cpu, *_os, etc. +# +# You will slowly go insane if you do not grok the following fact: when +# building this library, the top-level /target/ becomes the library's /host/. +# +# configure then causes --target to default to --host, exactly like any +# other package using autoconf. Therefore, 'target' and 'host' will +# always be the same. This makes sense both for native and cross compilers +# just think about it for a little while. :-) +# +# Also, if this library is being configured as part of a cross compiler, the +# top-level configure script will pass the "real" host as $with_cross_host. +# +# Do not delete or change the following two lines. For why, see +# http://gcc.gnu.org/ml/libstdc++/2003-07/msg00451.html +ac_aux_dir= +for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do + for ac_t in install-sh install.sh shtool; do + if test -f "$ac_dir/$ac_t"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/$ac_t -c" + break 2 + fi + done +done +if test -z "$ac_aux_dir"; then + as_fn_error "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5 +fi + +# These three variables are undocumented and unsupported, +# and are intended to be withdrawn in a future Autoconf release. +# They can cause serious problems if a builder's source tree is in a directory +# whose full name contains unusual characters. +ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. +ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. +ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. + + +# Make sure we can run config.sub. +$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || + as_fn_error "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5 + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 +$as_echo_n "checking build system type... " >&6; } +if test "${ac_cv_build+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + ac_build_alias=$build_alias +test "x$ac_build_alias" = x && + ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` +test "x$ac_build_alias" = x && + as_fn_error "cannot guess build type; you must specify one" "$LINENO" 5 +ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || + as_fn_error "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5 + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 +$as_echo "$ac_cv_build" >&6; } +case $ac_cv_build in +*-*-*) ;; +*) as_fn_error "invalid value of canonical build" "$LINENO" 5;; +esac +build=$ac_cv_build +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_build +shift +build_cpu=$1 +build_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +build_os=$* +IFS=$ac_save_IFS +case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 +$as_echo_n "checking host system type... " >&6; } +if test "${ac_cv_host+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test "x$host_alias" = x; then + ac_cv_host=$ac_cv_build +else + ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || + as_fn_error "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5 +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 +$as_echo "$ac_cv_host" >&6; } +case $ac_cv_host in +*-*-*) ;; +*) as_fn_error "invalid value of canonical host" "$LINENO" 5;; +esac +host=$ac_cv_host +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_host +shift +host_cpu=$1 +host_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +host_os=$* +IFS=$ac_save_IFS +case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking target system type" >&5 +$as_echo_n "checking target system type... " >&6; } +if test "${ac_cv_target+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test "x$target_alias" = x; then + ac_cv_target=$ac_cv_host +else + ac_cv_target=`$SHELL "$ac_aux_dir/config.sub" $target_alias` || + as_fn_error "$SHELL $ac_aux_dir/config.sub $target_alias failed" "$LINENO" 5 +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_target" >&5 +$as_echo "$ac_cv_target" >&6; } +case $ac_cv_target in +*-*-*) ;; +*) as_fn_error "invalid value of canonical target" "$LINENO" 5;; +esac +target=$ac_cv_target +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_target +shift +target_cpu=$1 +target_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +target_os=$* +IFS=$ac_save_IFS +case $target_os in *\ *) target_os=`echo "$target_os" | sed 's/ /-/g'`;; esac + + +# The aliases save the names the user supplied, while $host etc. +# will get canonicalized. +test -n "$target_alias" && + test "$program_prefix$program_suffix$program_transform_name" = \ + NONENONEs,x,x, && + program_prefix=${target_alias}- + +target_alias=${target_alias-$host_alias} + +# Sets up automake. Must come after AC_CANONICAL_SYSTEM. Each of the +# following is magically included in AUTOMAKE_OPTIONS in each Makefile.am. +# 1.9.0: minimum required version +# no-define: PACKAGE and VERSION will not be #define'd in config.h (a bunch +# of other PACKAGE_* variables will, however, and there's nothing +# we can do about that; they come from AC_INIT). +# foreign: we don't follow the normal rules for GNU packages (no COPYING +# file in the top srcdir, etc, etc), so stop complaining. +# -Wall: turns on all automake warnings... +# -Wno-portability: ...except this one, since GNU make is required. +# -Wno-override: ... and this one, since we do want this in testsuite. +am__api_version='1.11' + +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AmigaOS /C/install, which installs bootblocks on floppy discs +# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# OS/2's system install, which has a completely different semantic +# ./install, which can be erroneously created by make from ./install.sh. +# Reject install programs that cannot install multiple files. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 +$as_echo_n "checking for a BSD-compatible install... " >&6; } +if test -z "$INSTALL"; then +if test "${ac_cv_path_install+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + # Account for people who put trailing slashes in PATH elements. +case $as_dir/ in #(( + ./ | .// | /[cC]/* | \ + /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ + ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \ + /usr/ucb/* ) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + # Don't use installbsd from OSF since it installs stuff as root + # by default. + for ac_prog in ginstall scoinst install; do + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; }; then + if test $ac_prog = install && + grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + : + elif test $ac_prog = install && + grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # program-specific install script used by HP pwplus--don't use. + : + else + rm -rf conftest.one conftest.two conftest.dir + echo one > conftest.one + echo two > conftest.two + mkdir conftest.dir + if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" && + test -s conftest.one && test -s conftest.two && + test -s conftest.dir/conftest.one && + test -s conftest.dir/conftest.two + then + ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" + break 3 + fi + fi + fi + done + done + ;; +esac + + done +IFS=$as_save_IFS + +rm -rf conftest.one conftest.two conftest.dir + +fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL=$ac_cv_path_install + else + # As a last resort, use the slow shell script. Don't cache a + # value for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the value is a relative name. + INSTALL=$ac_install_sh + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5 +$as_echo "$INSTALL" >&6; } + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5 +$as_echo_n "checking whether build environment is sane... " >&6; } +# Just in case +sleep 1 +echo timestamp > conftest.file +# Reject unsafe characters in $srcdir or the absolute working directory +# name. Accept space and tab only in the latter. +am_lf=' +' +case `pwd` in + *[\\\"\#\$\&\'\`$am_lf]*) + as_fn_error "unsafe absolute working directory name" "$LINENO" 5;; +esac +case $srcdir in + *[\\\"\#\$\&\'\`$am_lf\ \ ]*) + as_fn_error "unsafe srcdir value: \`$srcdir'" "$LINENO" 5;; +esac + +# Do `set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` + if test "$*" = "X"; then + # -L didn't work. + set X `ls -t "$srcdir/configure" conftest.file` + fi + rm -f conftest.file + if test "$*" != "X $srcdir/configure conftest.file" \ + && test "$*" != "X conftest.file $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + as_fn_error "ls -t appears to fail. Make sure there is not a broken +alias in your environment" "$LINENO" 5 + fi + + test "$2" = conftest.file + ) +then + # Ok. + : +else + as_fn_error "newly created file is older than distributed files! +Check your system clock" "$LINENO" 5 +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +test "$program_prefix" != NONE && + program_transform_name="s&^&$program_prefix&;$program_transform_name" +# Use a double $ so make ignores it. +test "$program_suffix" != NONE && + program_transform_name="s&\$&$program_suffix&;$program_transform_name" +# Double any \ or $. +# By default was `s,x,x', remove it if useless. +ac_script='s/[\\$]/&&/g;s/;s,x,x,$//' +program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"` + +# expand $ac_aux_dir to an absolute path +am_aux_dir=`cd $ac_aux_dir && pwd` + +if test x"${MISSING+set}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; + *) + MISSING="\${SHELL} $am_aux_dir/missing" ;; + esac +fi +# Use eval to expand $SHELL +if eval "$MISSING --run true"; then + am_missing_run="$MISSING --run " +else + am_missing_run= + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \`missing' script is too old or missing" >&5 +$as_echo "$as_me: WARNING: \`missing' script is too old or missing" >&2;} +fi + +if test x"${install_sh}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; + *) + install_sh="\${SHELL} $am_aux_dir/install-sh" + esac +fi + +# Installed binaries are usually stripped using `strip' when the user +# run `make install-strip'. However `strip' might not be the right +# tool to use in cross-compilation environments, therefore Automake +# will honor the `STRIP' environment variable to overrule this program. +if test "$cross_compiling" != no; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. +set dummy ${ac_tool_prefix}strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_STRIP+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$STRIP"; then + ac_cv_prog_STRIP="$STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_STRIP="${ac_tool_prefix}strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +STRIP=$ac_cv_prog_STRIP +if test -n "$STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 +$as_echo "$STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_STRIP"; then + ac_ct_STRIP=$STRIP + # Extract the first word of "strip", so it can be a program name with args. +set dummy strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_STRIP"; then + ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_STRIP="strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP +if test -n "$ac_ct_STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 +$as_echo "$ac_ct_STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_STRIP" = x; then + STRIP=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + STRIP=$ac_ct_STRIP + fi +else + STRIP="$ac_cv_prog_STRIP" +fi + +fi +INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a thread-safe mkdir -p" >&5 +$as_echo_n "checking for a thread-safe mkdir -p... " >&6; } +if test -z "$MKDIR_P"; then + if test "${ac_cv_path_mkdir+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in mkdir gmkdir; do + for ac_exec_ext in '' $ac_executable_extensions; do + { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; } || continue + case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #( + 'mkdir (GNU coreutils) '* | \ + 'mkdir (coreutils) '* | \ + 'mkdir (fileutils) '4.1*) + ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext + break 3;; + esac + done + done + done +IFS=$as_save_IFS + +fi + + if test "${ac_cv_path_mkdir+set}" = set; then + MKDIR_P="$ac_cv_path_mkdir -p" + else + # As a last resort, use the slow shell script. Don't cache a + # value for MKDIR_P within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the value is a relative name. + test -d ./--version && rmdir ./--version + MKDIR_P="$ac_install_sh -d" + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5 +$as_echo "$MKDIR_P" >&6; } + +mkdir_p="$MKDIR_P" +case $mkdir_p in + [\\/$]* | ?:[\\/]*) ;; + */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;; +esac + +for ac_prog in gawk mawk nawk awk +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_AWK+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$AWK"; then + ac_cv_prog_AWK="$AWK" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_AWK="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +AWK=$ac_cv_prog_AWK +if test -n "$AWK"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 +$as_echo "$AWK" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$AWK" && break +done + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 +$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } +set x ${MAKE-make} +ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` +if { as_var=ac_cv_prog_make_${ac_make}_set; eval "test \"\${$as_var+set}\" = set"; }; then : + $as_echo_n "(cached) " >&6 +else + cat >conftest.make <<\_ACEOF +SHELL = /bin/sh +all: + @echo '@@@%%%=$(MAKE)=@@@%%%' +_ACEOF +# GNU make sometimes prints "make[1]: Entering...", which would confuse us. +case `${MAKE-make} -f conftest.make 2>/dev/null` in + *@@@%%%=?*=@@@%%%*) + eval ac_cv_prog_make_${ac_make}_set=yes;; + *) + eval ac_cv_prog_make_${ac_make}_set=no;; +esac +rm -f conftest.make +fi +if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + SET_MAKE= +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + SET_MAKE="MAKE=${MAKE-make}" +fi + +rm -rf .tst 2>/dev/null +mkdir .tst 2>/dev/null +if test -d .tst; then + am__leading_dot=. +else + am__leading_dot=_ +fi +rmdir .tst 2>/dev/null + +if test "`cd $srcdir && pwd`" != "`pwd`"; then + # Use -I$(srcdir) only when $(srcdir) != ., so that make's output + # is not polluted with repeated "-I." + am__isrc=' -I$(srcdir)' + # test to see if srcdir already configured + if test -f $srcdir/config.status; then + as_fn_error "source directory already configured; run \"make distclean\" there first" "$LINENO" 5 + fi +fi + +# test whether we have cygpath +if test -z "$CYGPATH_W"; then + if (cygpath --version) >/dev/null 2>/dev/null; then + CYGPATH_W='cygpath -w' + else + CYGPATH_W=echo + fi +fi + + +# Define the identity of the package. + PACKAGE='libitm' + VERSION='1.0' + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE "$PACKAGE" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define VERSION "$VERSION" +_ACEOF + +# Some tools Automake needs. + +ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"} + + +AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"} + + +AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"} + + +AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"} + + +MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} + +# We need awk for the "check" target. The system "awk" is bad on +# some platforms. +# Always define AMTAR for backward compatibility. + +AMTAR=${AMTAR-"${am_missing_run}tar"} + +am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -' + + + + + +# Default to --enable-multilib +# Check whether --enable-multilib was given. +if test "${enable_multilib+set}" = set; then : + enableval=$enable_multilib; case "$enableval" in + yes) multilib=yes ;; + no) multilib=no ;; + *) as_fn_error "bad value $enableval for multilib option" "$LINENO" 5 ;; + esac +else + multilib=yes +fi + + +# We may get other options which we leave undocumented: +# --with-target-subdir, --with-multisrctop, --with-multisubdir +# See config-ml.in if you want the gory details. + +if test "$srcdir" = "."; then + if test "$with_target_subdir" != "."; then + multi_basedir="$srcdir/$with_multisrctop../.." + else + multi_basedir="$srcdir/$with_multisrctop.." + fi +else + multi_basedir="$srcdir/.." +fi + + +# Even if the default multilib is not a cross compilation, +# it may be that some of the other multilibs are. +if test $cross_compiling = no && test $multilib = yes \ + && test "x${with_multisubdir}" != x ; then + cross_compiling=maybe +fi + +ac_config_commands="$ac_config_commands default-1" + + +# Calculate toolexeclibdir +# Also toolexecdir, though it's only used in toolexeclibdir +case ${enable_version_specific_runtime_libs} in + yes) + # Need the gcc compiler version to know where to install libraries + # and header files if --enable-version-specific-runtime-libs option + # is selected. + toolexecdir='$(libdir)/gcc/$(target_alias)' + toolexeclibdir='$(toolexecdir)/$(gcc_version)$(MULTISUBDIR)' + ;; + no) + if test -n "$with_cross_host" && + test x"$with_cross_host" != x"no"; then + # Install a library built with a cross compiler in tooldir, not libdir. + toolexecdir='$(exec_prefix)/$(target_alias)' + toolexeclibdir='$(toolexecdir)/lib' + else + toolexecdir='$(libdir)/gcc-lib/$(target_alias)' + toolexeclibdir='$(libdir)' + fi + multi_os_directory=`$CC -print-multi-os-directory` + case $multi_os_directory in + .) ;; # Avoid trailing /. + *) toolexeclibdir=$toolexeclibdir/$multi_os_directory ;; + esac + ;; +esac + + + +# Check the compiler. +# The same as in boehm-gc and libstdc++. Have to borrow it from there. +# We must force CC to /not/ be precious variables; otherwise +# the wrong, non-multilib-adjusted value will be used in multilibs. +# As a side effect, we have to subst CFLAGS ourselves. + + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. +set dummy ${ac_tool_prefix}gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_CC+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CC="${ac_tool_prefix}gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_CC="gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +else + CC="$ac_cv_prog_CC" +fi + +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. +set dummy ${ac_tool_prefix}cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_CC+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CC="${ac_tool_prefix}cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + fi +fi +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_CC+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + ac_prog_rejected=no +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# != 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" + fi +fi +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + for ac_prog in cl.exe + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_CC+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in cl.exe +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_CC="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_CC" && break +done + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +fi + +fi + + +test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error "no acceptable C compiler found in \$PATH +See \`config.log' for more details." "$LINENO" 5; } + +# Provide some information about the compiler. +$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 +set X $ac_compile +ac_compiler=$2 +for ac_option in --version -v -V -qversion; do + { { ac_try="$ac_compiler $ac_option >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compiler $ac_option >&5") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + sed '10a\ +... rest of stderr output deleted ... + 10q' conftest.err >conftest.er1 + cat conftest.er1 >&5 + rm -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +done + +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out conftest.out" +# Try to create an executable without -o first, disregard a.out. +# It will help us diagnose broken compilers, and finding out an intuition +# of exeext. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 +$as_echo_n "checking for C compiler default output file name... " >&6; } +ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` + +# The possible output files: +ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" + +ac_rmfiles= +for ac_file in $ac_files +do + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + * ) ac_rmfiles="$ac_rmfiles $ac_file";; + esac +done +rm -f $ac_rmfiles + +if { { ac_try="$ac_link_default" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link_default") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. +# So ignore a value of `no', otherwise this would lead to `EXEEXT = no' +# in a Makefile. We should not override ac_cv_exeext if it was cached, +# so that the user can short-circuit this test for compilers unknown to +# Autoconf. +for ac_file in $ac_files '' +do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) + ;; + [ab].out ) + # We found the default executable, but exeext='' is most + # certainly right. + break;; + *.* ) + if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; + then :; else + ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + fi + # We set ac_cv_exeext here because the later test for it is not + # safe: cross compilers may not add the suffix if given an `-o' + # argument, so we may need to know it at that point already. + # Even if this section looks crufty: it has the advantage of + # actually working. + break;; + * ) + break;; + esac +done +test "$ac_cv_exeext" = no && ac_cv_exeext= + +else + ac_file='' +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 +$as_echo "$ac_file" >&6; } +if test -z "$ac_file"; then : + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +{ as_fn_set_status 77 +as_fn_error "C compiler cannot create executables +See \`config.log' for more details." "$LINENO" 5; }; } +fi +ac_exeext=$ac_cv_exeext + +# Check that the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 +$as_echo_n "checking whether the C compiler works... " >&6; } +# If not cross compiling, check that we can run a simple program. +if test "$cross_compiling" != yes; then + if { ac_try='./$ac_file' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then + cross_compiling=no + else + if test "$cross_compiling" = maybe; then + cross_compiling=yes + else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error "cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details." "$LINENO" 5; } + fi + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out conftest.out +ac_clean_files=$ac_clean_files_save +# Check that the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 +$as_echo_n "checking whether we are cross compiling... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 +$as_echo "$cross_compiling" >&6; } + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 +$as_echo_n "checking for suffix of executables... " >&6; } +if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + # If both `conftest.exe' and `conftest' are `present' (well, observable) +# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will +# work properly (i.e., refer to `conftest.exe'), while it won't with +# `rm'. +for ac_file in conftest.exe conftest conftest.*; do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + break;; + * ) break;; + esac +done +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error "cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details." "$LINENO" 5; } +fi +rm -f conftest$ac_cv_exeext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 +$as_echo "$ac_cv_exeext" >&6; } + +rm -f conftest.$ac_ext +EXEEXT=$ac_cv_exeext +ac_exeext=$EXEEXT +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 +$as_echo_n "checking for suffix of object files... " >&6; } +if test "${ac_cv_objext+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.o conftest.obj +if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + for ac_file in conftest.o conftest.obj conftest.*; do + test -f "$ac_file" || continue; + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; + *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` + break;; + esac +done +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error "cannot compute suffix of object files: cannot compile +See \`config.log' for more details." "$LINENO" 5; } +fi +rm -f conftest.$ac_cv_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 +$as_echo "$ac_cv_objext" >&6; } +OBJEXT=$ac_cv_objext +ac_objext=$OBJEXT +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 +$as_echo_n "checking whether we are using the GNU C compiler... " >&6; } +if test "${ac_cv_c_compiler_gnu+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_compiler_gnu=yes +else + ac_compiler_gnu=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_c_compiler_gnu=$ac_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 +$as_echo "$ac_cv_c_compiler_gnu" >&6; } +if test $ac_compiler_gnu = yes; then + GCC=yes +else + GCC= +fi +ac_test_CFLAGS=${CFLAGS+set} +ac_save_CFLAGS=$CFLAGS +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 +$as_echo_n "checking whether $CC accepts -g... " >&6; } +if test "${ac_cv_prog_cc_g+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + ac_save_c_werror_flag=$ac_c_werror_flag + ac_c_werror_flag=yes + ac_cv_prog_cc_g=no + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +else + CFLAGS="" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +else + ac_c_werror_flag=$ac_save_c_werror_flag + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_c_werror_flag=$ac_save_c_werror_flag +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 +$as_echo "$ac_cv_prog_cc_g" >&6; } +if test "$ac_test_CFLAGS" = set; then + CFLAGS=$ac_save_CFLAGS +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 +$as_echo_n "checking for $CC option to accept ISO C89... " >&6; } +if test "${ac_cv_prog_cc_c89+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_prog_cc_c89=no +ac_save_CC=$CC +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <stdarg.h> +#include <stdio.h> +#include <sys/types.h> +#include <sys/stat.h> +/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ +struct buf { int x; }; +FILE * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} + +/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has + function prototypes and stuff, but not '\xHH' hex character constants. + These don't provoke an error unfortunately, instead are silently treated + as 'x'. The following induces an error, until -std is added to get + proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an + array size at least. It's necessary to write '\x00'==0 to get something + that's true only with -std. */ +int osf4_cc_array ['\x00' == 0 ? 1 : -1]; + +/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters + inside strings and character constants. */ +#define FOO(x) 'x' +int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; + +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); +int argc; +char **argv; +int +main () +{ +return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; + ; + return 0; +} +_ACEOF +for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ + -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_c89=$ac_arg +fi +rm -f core conftest.err conftest.$ac_objext + test "x$ac_cv_prog_cc_c89" != "xno" && break +done +rm -f conftest.$ac_ext +CC=$ac_save_CC + +fi +# AC_CACHE_VAL +case "x$ac_cv_prog_cc_c89" in + x) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +$as_echo "none needed" >&6; } ;; + xno) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +$as_echo "unsupported" >&6; } ;; + *) + CC="$CC $ac_cv_prog_cc_c89" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 +$as_echo "$ac_cv_prog_cc_c89" >&6; } ;; +esac +if test "x$ac_cv_prog_cc_c89" != xno; then : + +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +DEPDIR="${am__leading_dot}deps" + +ac_config_commands="$ac_config_commands depfiles" + + +am_make=${MAKE-make} +cat > confinc << 'END' +am__doit: + @echo this is the am__doit target +.PHONY: am__doit +END +# If we don't find an include directive, just comment out the code. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for style of include used by $am_make" >&5 +$as_echo_n "checking for style of include used by $am_make... " >&6; } +am__include="#" +am__quote= +_am_result=none +# First try GNU make style include. +echo "include confinc" > confmf +# Ignore all kinds of additional output from `make'. +case `$am_make -s -f confmf 2> /dev/null` in #( +*the\ am__doit\ target*) + am__include=include + am__quote= + _am_result=GNU + ;; +esac +# Now try BSD make style include. +if test "$am__include" = "#"; then + echo '.include "confinc"' > confmf + case `$am_make -s -f confmf 2> /dev/null` in #( + *the\ am__doit\ target*) + am__include=.include + am__quote="\"" + _am_result=BSD + ;; + esac +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $_am_result" >&5 +$as_echo "$_am_result" >&6; } +rm -f confinc confmf + +# Check whether --enable-dependency-tracking was given. +if test "${enable_dependency_tracking+set}" = set; then : + enableval=$enable_dependency_tracking; +fi + +if test "x$enable_dependency_tracking" != xno; then + am_depcomp="$ac_aux_dir/depcomp" + AMDEPBACKSLASH='\' +fi + if test "x$enable_dependency_tracking" != xno; then + AMDEP_TRUE= + AMDEP_FALSE='#' +else + AMDEP_TRUE='#' + AMDEP_FALSE= +fi + + + +depcc="$CC" am_compiler_list= + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 +$as_echo_n "checking dependency style of $depcc... " >&6; } +if test "${am_cv_CC_dependencies_compiler_type+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named `D' -- because `-MD' means `put the output + # in D'. + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + # We will build objects and dependencies in a subdirectory because + # it helps to detect inapplicable dependency modes. For instance + # both Tru64's cc and ICC support -MD to output dependencies as a + # side effect of compilation, but ICC will put the dependencies in + # the current directory while Tru64 will put them in the object + # directory. + mkdir sub + + am_cv_CC_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` + fi + am__universal=false + case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac + + for depmode in $am_compiler_list; do + # Setup a source with many dependencies, because some compilers + # like to wrap large dependency lists on column 80 (with \), and + # we should not choose a depcomp mode which is confused by this. + # + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + : > sub/conftest.c + for i in 1 2 3 4 5 6; do + echo '#include "conftst'$i'.h"' >> sub/conftest.c + # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with + # Solaris 8's {/usr,}/bin/sh. + touch sub/conftst$i.h + done + echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf + + # We check with `-c' and `-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle `-M -o', and we need to detect this. Also, some Intel + # versions had trouble with output in subdirs + am__obj=sub/conftest.${OBJEXT-o} + am__minus_obj="-o $am__obj" + case $depmode in + gcc) + # This depmode causes a compiler race in universal mode. + test "$am__universal" = false || continue + ;; + nosideeffect) + # after this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + msvisualcpp | msvcmsys) + # This compiler won't grok `-c -o', but also, the minuso test has + # not run yet. These depmodes are late enough in the game, and + # so weak that their functioning should not be impacted. + am__obj=conftest.${OBJEXT-o} + am__minus_obj= + ;; + none) break ;; + esac + if depmode=$depmode \ + source=sub/conftest.c object=$am__obj \ + depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ + $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ + >/dev/null 2>conftest.err && + grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && + grep $am__obj sub/conftest.Po > /dev/null 2>&1 && + ${MAKE-make} -s -f confmf > /dev/null 2>&1; then + # icc doesn't choke on unknown options, it will just issue warnings + # or remarks (even with -Werror). So we grep stderr for any message + # that says an option was ignored or not supported. + # When given -MP, icc 7.0 and 7.1 complain thusly: + # icc: Command line warning: ignoring option '-M'; no argument required + # The diagnosis changed in icc 8.0: + # icc: Command line remark: option '-MP' not supported + if (grep 'ignoring option' conftest.err || + grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else + am_cv_CC_dependencies_compiler_type=$depmode + break + fi + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_CC_dependencies_compiler_type=none +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5 +$as_echo "$am_cv_CC_dependencies_compiler_type" >&6; } +CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type + + if + test "x$enable_dependency_tracking" != xno \ + && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then + am__fastdepCC_TRUE= + am__fastdepCC_FALSE='#' +else + am__fastdepCC_TRUE='#' + am__fastdepCC_FALSE= +fi + + +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu +if test -z "$CXX"; then + if test -n "$CCC"; then + CXX=$CCC + else + if test -n "$ac_tool_prefix"; then + for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_CXX+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CXX"; then + ac_cv_prog_CXX="$CXX" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CXX="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CXX=$ac_cv_prog_CXX +if test -n "$CXX"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXX" >&5 +$as_echo "$CXX" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$CXX" && break + done +fi +if test -z "$CXX"; then + ac_ct_CXX=$CXX + for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_ac_ct_CXX+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CXX"; then + ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_CXX="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CXX=$ac_cv_prog_ac_ct_CXX +if test -n "$ac_ct_CXX"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CXX" >&5 +$as_echo "$ac_ct_CXX" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_CXX" && break +done + + if test "x$ac_ct_CXX" = x; then + CXX="g++" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CXX=$ac_ct_CXX + fi +fi + + fi +fi +# Provide some information about the compiler. +$as_echo "$as_me:${as_lineno-$LINENO}: checking for C++ compiler version" >&5 +set X $ac_compile +ac_compiler=$2 +for ac_option in --version -v -V -qversion; do + { { ac_try="$ac_compiler $ac_option >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compiler $ac_option >&5") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + sed '10a\ +... rest of stderr output deleted ... + 10q' conftest.err >conftest.er1 + cat conftest.er1 >&5 + rm -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +done + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C++ compiler" >&5 +$as_echo_n "checking whether we are using the GNU C++ compiler... " >&6; } +if test "${ac_cv_cxx_compiler_gnu+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_compiler_gnu=yes +else + ac_compiler_gnu=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_cxx_compiler_gnu=$ac_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_compiler_gnu" >&5 +$as_echo "$ac_cv_cxx_compiler_gnu" >&6; } +if test $ac_compiler_gnu = yes; then + GXX=yes +else + GXX= +fi +ac_test_CXXFLAGS=${CXXFLAGS+set} +ac_save_CXXFLAGS=$CXXFLAGS +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX accepts -g" >&5 +$as_echo_n "checking whether $CXX accepts -g... " >&6; } +if test "${ac_cv_prog_cxx_g+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + ac_save_cxx_werror_flag=$ac_cxx_werror_flag + ac_cxx_werror_flag=yes + ac_cv_prog_cxx_g=no + CXXFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_cv_prog_cxx_g=yes +else + CXXFLAGS="" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + +else + ac_cxx_werror_flag=$ac_save_cxx_werror_flag + CXXFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_cv_prog_cxx_g=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_cxx_werror_flag=$ac_save_cxx_werror_flag +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_g" >&5 +$as_echo "$ac_cv_prog_cxx_g" >&6; } +if test "$ac_test_CXXFLAGS" = set; then + CXXFLAGS=$ac_save_CXXFLAGS +elif test $ac_cv_prog_cxx_g = yes; then + if test "$GXX" = yes; then + CXXFLAGS="-g -O2" + else + CXXFLAGS="-g" + fi +else + if test "$GXX" = yes; then + CXXFLAGS="-O2" + else + CXXFLAGS= + fi +fi +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +depcc="$CXX" am_compiler_list= + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 +$as_echo_n "checking dependency style of $depcc... " >&6; } +if test "${am_cv_CXX_dependencies_compiler_type+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named `D' -- because `-MD' means `put the output + # in D'. + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + # We will build objects and dependencies in a subdirectory because + # it helps to detect inapplicable dependency modes. For instance + # both Tru64's cc and ICC support -MD to output dependencies as a + # side effect of compilation, but ICC will put the dependencies in + # the current directory while Tru64 will put them in the object + # directory. + mkdir sub + + am_cv_CXX_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` + fi + am__universal=false + case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac + + for depmode in $am_compiler_list; do + # Setup a source with many dependencies, because some compilers + # like to wrap large dependency lists on column 80 (with \), and + # we should not choose a depcomp mode which is confused by this. + # + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + : > sub/conftest.c + for i in 1 2 3 4 5 6; do + echo '#include "conftst'$i'.h"' >> sub/conftest.c + # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with + # Solaris 8's {/usr,}/bin/sh. + touch sub/conftst$i.h + done + echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf + + # We check with `-c' and `-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle `-M -o', and we need to detect this. Also, some Intel + # versions had trouble with output in subdirs + am__obj=sub/conftest.${OBJEXT-o} + am__minus_obj="-o $am__obj" + case $depmode in + gcc) + # This depmode causes a compiler race in universal mode. + test "$am__universal" = false || continue + ;; + nosideeffect) + # after this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + msvisualcpp | msvcmsys) + # This compiler won't grok `-c -o', but also, the minuso test has + # not run yet. These depmodes are late enough in the game, and + # so weak that their functioning should not be impacted. + am__obj=conftest.${OBJEXT-o} + am__minus_obj= + ;; + none) break ;; + esac + if depmode=$depmode \ + source=sub/conftest.c object=$am__obj \ + depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ + $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ + >/dev/null 2>conftest.err && + grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && + grep $am__obj sub/conftest.Po > /dev/null 2>&1 && + ${MAKE-make} -s -f confmf > /dev/null 2>&1; then + # icc doesn't choke on unknown options, it will just issue warnings + # or remarks (even with -Werror). So we grep stderr for any message + # that says an option was ignored or not supported. + # When given -MP, icc 7.0 and 7.1 complain thusly: + # icc: Command line warning: ignoring option '-M'; no argument required + # The diagnosis changed in icc 8.0: + # icc: Command line remark: option '-MP' not supported + if (grep 'ignoring option' conftest.err || + grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else + am_cv_CXX_dependencies_compiler_type=$depmode + break + fi + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_CXX_dependencies_compiler_type=none +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CXX_dependencies_compiler_type" >&5 +$as_echo "$am_cv_CXX_dependencies_compiler_type" >&6; } +CXXDEPMODE=depmode=$am_cv_CXX_dependencies_compiler_type + + if + test "x$enable_dependency_tracking" != xno \ + && test "$am_cv_CXX_dependencies_compiler_type" = gcc3; then + am__fastdepCXX_TRUE= + am__fastdepCXX_FALSE='#' +else + am__fastdepCXX_TRUE='#' + am__fastdepCXX_FALSE= +fi + + +# By default we simply use the C compiler to build assembly code. + +test "${CCAS+set}" = set || CCAS=$CC +test "${CCASFLAGS+set}" = set || CCASFLAGS=$CFLAGS + + + +depcc="$CCAS" am_compiler_list= + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 +$as_echo_n "checking dependency style of $depcc... " >&6; } +if test "${am_cv_CCAS_dependencies_compiler_type+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named `D' -- because `-MD' means `put the output + # in D'. + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + # We will build objects and dependencies in a subdirectory because + # it helps to detect inapplicable dependency modes. For instance + # both Tru64's cc and ICC support -MD to output dependencies as a + # side effect of compilation, but ICC will put the dependencies in + # the current directory while Tru64 will put them in the object + # directory. + mkdir sub + + am_cv_CCAS_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` + fi + am__universal=false + + + for depmode in $am_compiler_list; do + # Setup a source with many dependencies, because some compilers + # like to wrap large dependency lists on column 80 (with \), and + # we should not choose a depcomp mode which is confused by this. + # + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + : > sub/conftest.c + for i in 1 2 3 4 5 6; do + echo '#include "conftst'$i'.h"' >> sub/conftest.c + # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with + # Solaris 8's {/usr,}/bin/sh. + touch sub/conftst$i.h + done + echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf + + # We check with `-c' and `-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle `-M -o', and we need to detect this. Also, some Intel + # versions had trouble with output in subdirs + am__obj=sub/conftest.${OBJEXT-o} + am__minus_obj="-o $am__obj" + case $depmode in + gcc) + # This depmode causes a compiler race in universal mode. + test "$am__universal" = false || continue + ;; + nosideeffect) + # after this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + msvisualcpp | msvcmsys) + # This compiler won't grok `-c -o', but also, the minuso test has + # not run yet. These depmodes are late enough in the game, and + # so weak that their functioning should not be impacted. + am__obj=conftest.${OBJEXT-o} + am__minus_obj= + ;; + none) break ;; + esac + if depmode=$depmode \ + source=sub/conftest.c object=$am__obj \ + depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ + $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ + >/dev/null 2>conftest.err && + grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && + grep $am__obj sub/conftest.Po > /dev/null 2>&1 && + ${MAKE-make} -s -f confmf > /dev/null 2>&1; then + # icc doesn't choke on unknown options, it will just issue warnings + # or remarks (even with -Werror). So we grep stderr for any message + # that says an option was ignored or not supported. + # When given -MP, icc 7.0 and 7.1 complain thusly: + # icc: Command line warning: ignoring option '-M'; no argument required + # The diagnosis changed in icc 8.0: + # icc: Command line remark: option '-MP' not supported + if (grep 'ignoring option' conftest.err || + grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else + am_cv_CCAS_dependencies_compiler_type=$depmode + break + fi + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_CCAS_dependencies_compiler_type=none +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CCAS_dependencies_compiler_type" >&5 +$as_echo "$am_cv_CCAS_dependencies_compiler_type" >&6; } +CCASDEPMODE=depmode=$am_cv_CCAS_dependencies_compiler_type + + if + test "x$enable_dependency_tracking" != xno \ + && test "$am_cv_CCAS_dependencies_compiler_type" = gcc3; then + am__fastdepCCAS_TRUE= + am__fastdepCCAS_FALSE='#' +else + am__fastdepCCAS_TRUE='#' + am__fastdepCCAS_FALSE= +fi + + + + + + +# In order to override CFLAGS_FOR_TARGET, all of our special flags go +# in XCFLAGS. But we need them in CFLAGS during configury. So put them +# in both places for now and restore CFLAGS at the end of config. +save_CFLAGS="$CFLAGS" + +# Find other programs we need. +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args. +set dummy ${ac_tool_prefix}ar; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_AR+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$AR"; then + ac_cv_prog_AR="$AR" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_AR="${ac_tool_prefix}ar" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +AR=$ac_cv_prog_AR +if test -n "$AR"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 +$as_echo "$AR" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_AR"; then + ac_ct_AR=$AR + # Extract the first word of "ar", so it can be a program name with args. +set dummy ar; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_ac_ct_AR+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_AR"; then + ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_AR="ar" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_AR=$ac_cv_prog_ac_ct_AR +if test -n "$ac_ct_AR"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5 +$as_echo "$ac_ct_AR" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_AR" = x; then + AR="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + AR=$ac_ct_AR + fi +else + AR="$ac_cv_prog_AR" +fi + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}nm", so it can be a program name with args. +set dummy ${ac_tool_prefix}nm; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_NM+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$NM"; then + ac_cv_prog_NM="$NM" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_NM="${ac_tool_prefix}nm" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +NM=$ac_cv_prog_NM +if test -n "$NM"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $NM" >&5 +$as_echo "$NM" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_NM"; then + ac_ct_NM=$NM + # Extract the first word of "nm", so it can be a program name with args. +set dummy nm; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_ac_ct_NM+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_NM"; then + ac_cv_prog_ac_ct_NM="$ac_ct_NM" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_NM="nm" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_NM=$ac_cv_prog_ac_ct_NM +if test -n "$ac_ct_NM"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_NM" >&5 +$as_echo "$ac_ct_NM" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_NM" = x; then + NM="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + NM=$ac_ct_NM + fi +else + NM="$ac_cv_prog_NM" +fi + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. +set dummy ${ac_tool_prefix}ranlib; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_RANLIB+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$RANLIB"; then + ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +RANLIB=$ac_cv_prog_RANLIB +if test -n "$RANLIB"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 +$as_echo "$RANLIB" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_RANLIB"; then + ac_ct_RANLIB=$RANLIB + # Extract the first word of "ranlib", so it can be a program name with args. +set dummy ranlib; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_RANLIB"; then + ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_RANLIB="ranlib" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB +if test -n "$ac_ct_RANLIB"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 +$as_echo "$ac_ct_RANLIB" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_RANLIB" = x; then + RANLIB="ranlib-not-found-in-path-error" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + RANLIB=$ac_ct_RANLIB + fi +else + RANLIB="$ac_cv_prog_RANLIB" +fi + +# Extract the first word of "perl", so it can be a program name with args. +set dummy perl; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_path_PERL+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + case $PERL in + [\\/]* | ?:[\\/]*) + ac_cv_path_PERL="$PERL" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_PERL="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + test -z "$ac_cv_path_PERL" && ac_cv_path_PERL="perl-not-found-in-path-error" + ;; +esac +fi +PERL=$ac_cv_path_PERL +if test -n "$PERL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PERL" >&5 +$as_echo "$PERL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 +$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } +set x ${MAKE-make} +ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` +if { as_var=ac_cv_prog_make_${ac_make}_set; eval "test \"\${$as_var+set}\" = set"; }; then : + $as_echo_n "(cached) " >&6 +else + cat >conftest.make <<\_ACEOF +SHELL = /bin/sh +all: + @echo '@@@%%%=$(MAKE)=@@@%%%' +_ACEOF +# GNU make sometimes prints "make[1]: Entering...", which would confuse us. +case `${MAKE-make} -f conftest.make 2>/dev/null` in + *@@@%%%=?*=@@@%%%*) + eval ac_cv_prog_make_${ac_make}_set=yes;; + *) + eval ac_cv_prog_make_${ac_make}_set=no;; +esac +rm -f conftest.make +fi +if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + SET_MAKE= +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + SET_MAKE="MAKE=${MAKE-make}" +fi + + + +# See if makeinfo has been installed and is modern enough +# that we can use it. + + # Extract the first word of "makeinfo", so it can be a program name with args. +set dummy makeinfo; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_MAKEINFO+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$MAKEINFO"; then + ac_cv_prog_MAKEINFO="$MAKEINFO" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_MAKEINFO="makeinfo" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +MAKEINFO=$ac_cv_prog_MAKEINFO +if test -n "$MAKEINFO"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAKEINFO" >&5 +$as_echo "$MAKEINFO" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + if test -n "$MAKEINFO"; then + # Found it, now check the version. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for modern makeinfo" >&5 +$as_echo_n "checking for modern makeinfo... " >&6; } +if test "${gcc_cv_prog_makeinfo_modern+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + ac_prog_version=`eval $MAKEINFO --version 2>&1 | + sed -n 's/^.*GNU texinfo.* \([0-9][0-9.]*\).*$/\1/p'` + + case $ac_prog_version in + '') gcc_cv_prog_makeinfo_modern=no;; + 4.[4-9]*|4.[1-9][0-9]*|[5-9]*|[1-9][0-9]*) gcc_cv_prog_makeinfo_modern=yes;; + *) gcc_cv_prog_makeinfo_modern=no;; + esac + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_prog_makeinfo_modern" >&5 +$as_echo "$gcc_cv_prog_makeinfo_modern" >&6; } + else + gcc_cv_prog_makeinfo_modern=no + fi + if test $gcc_cv_prog_makeinfo_modern = no; then + MAKEINFO="${CONFIG_SHELL-/bin/sh} $ac_aux_dir/missing makeinfo" + fi + + if test $gcc_cv_prog_makeinfo_modern = "yes"; then + BUILD_INFO_TRUE= + BUILD_INFO_FALSE='#' +else + BUILD_INFO_TRUE='#' + BUILD_INFO_FALSE= +fi + + + +# Configure libtool +case `pwd` in + *\ * | *\ *) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&5 +$as_echo "$as_me: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&2;} ;; +esac + + + +macro_version='2.2.7a' +macro_revision='1.3134' + + + + + + + + + + + + + +ltmain="$ac_aux_dir/ltmain.sh" + +# Backslashify metacharacters that are still active within +# double-quoted strings. +sed_quote_subst='s/\(["`$\\]\)/\\\1/g' + +# Same as above, but do not quote variable references. +double_quote_subst='s/\(["`\\]\)/\\\1/g' + +# Sed substitution to delay expansion of an escaped shell variable in a +# double_quote_subst'ed string. +delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' + +# Sed substitution to delay expansion of an escaped single quote. +delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' + +# Sed substitution to avoid accidental globbing in evaled expressions +no_glob_subst='s/\*/\\\*/g' + +ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to print strings" >&5 +$as_echo_n "checking how to print strings... " >&6; } +# Test print first, because it will be a builtin if present. +if test "X`print -r -- -n 2>/dev/null`" = X-n && \ + test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='print -r --' +elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='printf %s\n' +else + # Use this function as a fallback that always works. + func_fallback_echo () + { + eval 'cat <<_LTECHO_EOF +$1 +_LTECHO_EOF' + } + ECHO='func_fallback_echo' +fi + +# func_echo_all arg... +# Invoke $ECHO with all args, space-separated. +func_echo_all () +{ + $ECHO "" +} + +case "$ECHO" in + printf*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: printf" >&5 +$as_echo "printf" >&6; } ;; + print*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: print -r" >&5 +$as_echo "print -r" >&6; } ;; + *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: cat" >&5 +$as_echo "cat" >&6; } ;; +esac + + + + + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5 +$as_echo_n "checking for a sed that does not truncate output... " >&6; } +if test "${ac_cv_path_SED+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ + for ac_i in 1 2 3 4 5 6 7; do + ac_script="$ac_script$as_nl$ac_script" + done + echo "$ac_script" 2>/dev/null | sed 99q >conftest.sed + { ac_script=; unset ac_script;} + if test -z "$SED"; then + ac_path_SED_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in sed gsed; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_SED="$as_dir/$ac_prog$ac_exec_ext" + { test -f "$ac_path_SED" && $as_test_x "$ac_path_SED"; } || continue +# Check for GNU ac_path_SED and select it if it is found. + # Check for GNU $ac_path_SED +case `"$ac_path_SED" --version 2>&1` in +*GNU*) + ac_cv_path_SED="$ac_path_SED" ac_path_SED_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo '' >> "conftest.nl" + "$ac_path_SED" -f conftest.sed < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_SED_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_SED="$ac_path_SED" + ac_path_SED_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_SED_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_SED"; then + as_fn_error "no acceptable sed could be found in \$PATH" "$LINENO" 5 + fi +else + ac_cv_path_SED=$SED +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_SED" >&5 +$as_echo "$ac_cv_path_SED" >&6; } + SED="$ac_cv_path_SED" + rm -f conftest.sed + +test -z "$SED" && SED=sed +Xsed="$SED -e 1s/^X//" + + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 +$as_echo_n "checking for grep that handles long lines and -e... " >&6; } +if test "${ac_cv_path_GREP+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$GREP"; then + ac_path_GREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in grep ggrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" + { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue +# Check for GNU ac_path_GREP and select it if it is found. + # Check for GNU $ac_path_GREP +case `"$ac_path_GREP" --version 2>&1` in +*GNU*) + ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'GREP' >> "conftest.nl" + "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_GREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_GREP="$ac_path_GREP" + ac_path_GREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_GREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_GREP"; then + as_fn_error "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_GREP=$GREP +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 +$as_echo "$ac_cv_path_GREP" >&6; } + GREP="$ac_cv_path_GREP" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 +$as_echo_n "checking for egrep... " >&6; } +if test "${ac_cv_path_EGREP+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 + then ac_cv_path_EGREP="$GREP -E" + else + if test -z "$EGREP"; then + ac_path_EGREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in egrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" + { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue +# Check for GNU ac_path_EGREP and select it if it is found. + # Check for GNU $ac_path_EGREP +case `"$ac_path_EGREP" --version 2>&1` in +*GNU*) + ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'EGREP' >> "conftest.nl" + "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_EGREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_EGREP="$ac_path_EGREP" + ac_path_EGREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_EGREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_EGREP"; then + as_fn_error "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_EGREP=$EGREP +fi + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 +$as_echo "$ac_cv_path_EGREP" >&6; } + EGREP="$ac_cv_path_EGREP" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for fgrep" >&5 +$as_echo_n "checking for fgrep... " >&6; } +if test "${ac_cv_path_FGREP+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if echo 'ab*c' | $GREP -F 'ab*c' >/dev/null 2>&1 + then ac_cv_path_FGREP="$GREP -F" + else + if test -z "$FGREP"; then + ac_path_FGREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in fgrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_FGREP="$as_dir/$ac_prog$ac_exec_ext" + { test -f "$ac_path_FGREP" && $as_test_x "$ac_path_FGREP"; } || continue +# Check for GNU ac_path_FGREP and select it if it is found. + # Check for GNU $ac_path_FGREP +case `"$ac_path_FGREP" --version 2>&1` in +*GNU*) + ac_cv_path_FGREP="$ac_path_FGREP" ac_path_FGREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'FGREP' >> "conftest.nl" + "$ac_path_FGREP" FGREP < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_FGREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_FGREP="$ac_path_FGREP" + ac_path_FGREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_FGREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_FGREP"; then + as_fn_error "no acceptable fgrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_FGREP=$FGREP +fi + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_FGREP" >&5 +$as_echo "$ac_cv_path_FGREP" >&6; } + FGREP="$ac_cv_path_FGREP" + + +test -z "$GREP" && GREP=grep + + + + + + + + + + + + + + + + + + + +# Check whether --with-gnu-ld was given. +if test "${with_gnu_ld+set}" = set; then : + withval=$with_gnu_ld; test "$withval" = no || with_gnu_ld=yes +else + with_gnu_ld=no +fi + +ac_prog=ld +if test "$GCC" = yes; then + # Check if gcc -print-prog-name=ld gives a path. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5 +$as_echo_n "checking for ld used by $CC... " >&6; } + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case $ac_prog in + # Accept absolute paths. + [\\/]* | ?:[\\/]*) + re_direlt='/[^/][^/]*/\.\./' + # Canonicalize the pathname of ld + ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` + while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do + ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` + done + test -z "$LD" && LD="$ac_prog" + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test "$with_gnu_ld" = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5 +$as_echo_n "checking for GNU ld... " >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5 +$as_echo_n "checking for non-GNU ld... " >&6; } +fi +if test "${lt_cv_path_LD+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$LD"; then + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + lt_cv_path_LD="$ac_dir/$ac_prog" + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some variants of GNU ld only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + case `"$lt_cv_path_LD" -v 2>&1 </dev/null` in + *GNU* | *'with BFD'*) + test "$with_gnu_ld" != no && break + ;; + *) + test "$with_gnu_ld" != yes && break + ;; + esac + fi + done + IFS="$lt_save_ifs" +else + lt_cv_path_LD="$LD" # Let the user override the test with a path. +fi +fi + +LD="$lt_cv_path_LD" +if test -n "$LD"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LD" >&5 +$as_echo "$LD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +test -z "$LD" && as_fn_error "no acceptable ld found in \$PATH" "$LINENO" 5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5 +$as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; } +if test "${lt_cv_prog_gnu_ld+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + # I'd rather use --version here, but apparently some GNU lds only accept -v. +case `$LD -v 2>&1 </dev/null` in +*GNU* | *'with BFD'*) + lt_cv_prog_gnu_ld=yes + ;; +*) + lt_cv_prog_gnu_ld=no + ;; +esac +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_gnu_ld" >&5 +$as_echo "$lt_cv_prog_gnu_ld" >&6; } +with_gnu_ld=$lt_cv_prog_gnu_ld + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for BSD- or MS-compatible name lister (nm)" >&5 +$as_echo_n "checking for BSD- or MS-compatible name lister (nm)... " >&6; } +if test "${lt_cv_path_NM+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$NM"; then + # Let the user override the test. + lt_cv_path_NM="$NM" +else + lt_nm_to_check="${ac_tool_prefix}nm" + if test -n "$ac_tool_prefix" && test "$build" = "$host"; then + lt_nm_to_check="$lt_nm_to_check nm" + fi + for lt_tmp_nm in $lt_nm_to_check; do + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + tmp_nm="$ac_dir/$lt_tmp_nm" + if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then + # Check to see if the nm accepts a BSD-compat flag. + # Adding the `sed 1q' prevents false positives on HP-UX, which says: + # nm: unknown option "B" ignored + # Tru64's nm complains that /dev/null is an invalid object file + case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in + */dev/null* | *'Invalid file or object type'*) + lt_cv_path_NM="$tmp_nm -B" + break + ;; + *) + case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in + */dev/null*) + lt_cv_path_NM="$tmp_nm -p" + break + ;; + *) + lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but + continue # so that we can try to find one that supports BSD flags + ;; + esac + ;; + esac + fi + done + IFS="$lt_save_ifs" + done + : ${lt_cv_path_NM=no} +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_NM" >&5 +$as_echo "$lt_cv_path_NM" >&6; } +if test "$lt_cv_path_NM" != "no"; then + NM="$lt_cv_path_NM" +else + # Didn't find any BSD compatible name lister, look for dumpbin. + if test -n "$DUMPBIN"; then : + # Let the user override the test. + else + if test -n "$ac_tool_prefix"; then + for ac_prog in dumpbin "link -dump" + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_DUMPBIN+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$DUMPBIN"; then + ac_cv_prog_DUMPBIN="$DUMPBIN" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_DUMPBIN="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +DUMPBIN=$ac_cv_prog_DUMPBIN +if test -n "$DUMPBIN"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DUMPBIN" >&5 +$as_echo "$DUMPBIN" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$DUMPBIN" && break + done +fi +if test -z "$DUMPBIN"; then + ac_ct_DUMPBIN=$DUMPBIN + for ac_prog in dumpbin "link -dump" +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_ac_ct_DUMPBIN+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_DUMPBIN"; then + ac_cv_prog_ac_ct_DUMPBIN="$ac_ct_DUMPBIN" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_DUMPBIN="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_DUMPBIN=$ac_cv_prog_ac_ct_DUMPBIN +if test -n "$ac_ct_DUMPBIN"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DUMPBIN" >&5 +$as_echo "$ac_ct_DUMPBIN" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_DUMPBIN" && break +done + + if test "x$ac_ct_DUMPBIN" = x; then + DUMPBIN=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + DUMPBIN=$ac_ct_DUMPBIN + fi +fi + + case `$DUMPBIN -symbols /dev/null 2>&1 | sed '1q'` in + *COFF*) + DUMPBIN="$DUMPBIN -symbols" + ;; + *) + DUMPBIN=: + ;; + esac + fi + + if test "$DUMPBIN" != ":"; then + NM="$DUMPBIN" + fi +fi +test -z "$NM" && NM=nm + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the name lister ($NM) interface" >&5 +$as_echo_n "checking the name lister ($NM) interface... " >&6; } +if test "${lt_cv_nm_interface+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_nm_interface="BSD nm" + echo "int some_variable = 0;" > conftest.$ac_ext + (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&5) + (eval "$ac_compile" 2>conftest.err) + cat conftest.err >&5 + (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&5) + (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) + cat conftest.err >&5 + (eval echo "\"\$as_me:$LINENO: output\"" >&5) + cat conftest.out >&5 + if $GREP 'External.*some_variable' conftest.out > /dev/null; then + lt_cv_nm_interface="MS dumpbin" + fi + rm -f conftest* +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_nm_interface" >&5 +$as_echo "$lt_cv_nm_interface" >&6; } + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5 +$as_echo_n "checking whether ln -s works... " >&6; } +LN_S=$as_ln_s +if test "$LN_S" = "ln -s"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5 +$as_echo "no, using $LN_S" >&6; } +fi + +# find the maximum length of command line arguments +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the maximum length of command line arguments" >&5 +$as_echo_n "checking the maximum length of command line arguments... " >&6; } +if test "${lt_cv_sys_max_cmd_len+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + i=0 + teststring="ABCD" + + case $build_os in + msdosdjgpp*) + # On DJGPP, this test can blow up pretty badly due to problems in libc + # (any single argument exceeding 2000 bytes causes a buffer overrun + # during glob expansion). Even if it were fixed, the result of this + # check would be larger than it should be. + lt_cv_sys_max_cmd_len=12288; # 12K is about right + ;; + + gnu*) + # Under GNU Hurd, this test is not required because there is + # no limit to the length of command line arguments. + # Libtool will interpret -1 as no limit whatsoever + lt_cv_sys_max_cmd_len=-1; + ;; + + cygwin* | mingw* | cegcc*) + # On Win9x/ME, this test blows up -- it succeeds, but takes + # about 5 minutes as the teststring grows exponentially. + # Worse, since 9x/ME are not pre-emptively multitasking, + # you end up with a "frozen" computer, even though with patience + # the test eventually succeeds (with a max line length of 256k). + # Instead, let's just punt: use the minimum linelength reported by + # all of the supported platforms: 8192 (on NT/2K/XP). + lt_cv_sys_max_cmd_len=8192; + ;; + + mint*) + # On MiNT this can take a long time and run out of memory. + lt_cv_sys_max_cmd_len=8192; + ;; + + amigaos*) + # On AmigaOS with pdksh, this test takes hours, literally. + # So we just punt and use a minimum line length of 8192. + lt_cv_sys_max_cmd_len=8192; + ;; + + netbsd* | freebsd* | openbsd* | darwin* | dragonfly*) + # This has been around since 386BSD, at least. Likely further. + if test -x /sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` + elif test -x /usr/sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` + else + lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs + fi + # And add a safety zone + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + ;; + + interix*) + # We know the value 262144 and hardcode it with a safety zone (like BSD) + lt_cv_sys_max_cmd_len=196608 + ;; + + osf*) + # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure + # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not + # nice to cause kernel panics so lets avoid the loop below. + # First set a reasonable default. + lt_cv_sys_max_cmd_len=16384 + # + if test -x /sbin/sysconfig; then + case `/sbin/sysconfig -q proc exec_disable_arg_limit` in + *1*) lt_cv_sys_max_cmd_len=-1 ;; + esac + fi + ;; + sco3.2v5*) + lt_cv_sys_max_cmd_len=102400 + ;; + sysv5* | sco5v6* | sysv4.2uw2*) + kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` + if test -n "$kargmax"; then + lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[ ]//'` + else + lt_cv_sys_max_cmd_len=32768 + fi + ;; + *) + lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` + if test -n "$lt_cv_sys_max_cmd_len"; then + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + else + # Make teststring a little bigger before we do anything with it. + # a 1K string should be a reasonable start. + for i in 1 2 3 4 5 6 7 8 ; do + teststring=$teststring$teststring + done + SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} + # If test is not a shell built-in, we'll probably end up computing a + # maximum length that is only half of the actual maximum length, but + # we can't tell. + while { test "X"`func_fallback_echo "$teststring$teststring" 2>/dev/null` \ + = "X$teststring$teststring"; } >/dev/null 2>&1 && + test $i != 17 # 1/2 MB should be enough + do + i=`expr $i + 1` + teststring=$teststring$teststring + done + # Only check the string length outside the loop. + lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` + teststring= + # Add a significant safety factor because C++ compilers can tack on + # massive amounts of additional arguments before passing them to the + # linker. It appears as though 1/2 is a usable value. + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` + fi + ;; + esac + +fi + +if test -n $lt_cv_sys_max_cmd_len ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sys_max_cmd_len" >&5 +$as_echo "$lt_cv_sys_max_cmd_len" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5 +$as_echo "none" >&6; } +fi +max_cmd_len=$lt_cv_sys_max_cmd_len + + + + + + +: ${CP="cp -f"} +: ${MV="mv -f"} +: ${RM="rm -f"} + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the shell understands some XSI constructs" >&5 +$as_echo_n "checking whether the shell understands some XSI constructs... " >&6; } +# Try some XSI features +xsi_shell=no +( _lt_dummy="a/b/c" + test "${_lt_dummy##*/},${_lt_dummy%/*},"${_lt_dummy%"$_lt_dummy"}, \ + = c,a/b,, \ + && eval 'test $(( 1 + 1 )) -eq 2 \ + && test "${#_lt_dummy}" -eq 5' ) >/dev/null 2>&1 \ + && xsi_shell=yes +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $xsi_shell" >&5 +$as_echo "$xsi_shell" >&6; } + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the shell understands \"+=\"" >&5 +$as_echo_n "checking whether the shell understands \"+=\"... " >&6; } +lt_shell_append=no +( foo=bar; set foo baz; eval "$1+=\$2" && test "$foo" = barbaz ) \ + >/dev/null 2>&1 \ + && lt_shell_append=yes +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_shell_append" >&5 +$as_echo "$lt_shell_append" >&6; } + + +if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + lt_unset=unset +else + lt_unset=false +fi + + + + + +# test EBCDIC or ASCII +case `echo X|tr X '\101'` in + A) # ASCII based system + # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr + lt_SP2NL='tr \040 \012' + lt_NL2SP='tr \015\012 \040\040' + ;; + *) # EBCDIC based system + lt_SP2NL='tr \100 \n' + lt_NL2SP='tr \r\n \100\100' + ;; +esac + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $LD option to reload object files" >&5 +$as_echo_n "checking for $LD option to reload object files... " >&6; } +if test "${lt_cv_ld_reload_flag+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_ld_reload_flag='-r' +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_reload_flag" >&5 +$as_echo "$lt_cv_ld_reload_flag" >&6; } +reload_flag=$lt_cv_ld_reload_flag +case $reload_flag in +"" | " "*) ;; +*) reload_flag=" $reload_flag" ;; +esac +reload_cmds='$LD$reload_flag -o $output$reload_objs' +case $host_os in + darwin*) + if test "$GCC" = yes; then + reload_cmds='$LTCC $LTCFLAGS -nostdlib ${wl}-r -o $output$reload_objs' + else + reload_cmds='$LD$reload_flag -o $output$reload_objs' + fi + ;; +esac + + + + + + + + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args. +set dummy ${ac_tool_prefix}objdump; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_OBJDUMP+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$OBJDUMP"; then + ac_cv_prog_OBJDUMP="$OBJDUMP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +OBJDUMP=$ac_cv_prog_OBJDUMP +if test -n "$OBJDUMP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OBJDUMP" >&5 +$as_echo "$OBJDUMP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_OBJDUMP"; then + ac_ct_OBJDUMP=$OBJDUMP + # Extract the first word of "objdump", so it can be a program name with args. +set dummy objdump; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_ac_ct_OBJDUMP+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_OBJDUMP"; then + ac_cv_prog_ac_ct_OBJDUMP="$ac_ct_OBJDUMP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_OBJDUMP="objdump" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP +if test -n "$ac_ct_OBJDUMP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJDUMP" >&5 +$as_echo "$ac_ct_OBJDUMP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_OBJDUMP" = x; then + OBJDUMP="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + OBJDUMP=$ac_ct_OBJDUMP + fi +else + OBJDUMP="$ac_cv_prog_OBJDUMP" +fi + +test -z "$OBJDUMP" && OBJDUMP=objdump + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to recognize dependent libraries" >&5 +$as_echo_n "checking how to recognize dependent libraries... " >&6; } +if test "${lt_cv_deplibs_check_method+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_file_magic_cmd='$MAGIC_CMD' +lt_cv_file_magic_test_file= +lt_cv_deplibs_check_method='unknown' +# Need to set the preceding variable on all platforms that support +# interlibrary dependencies. +# 'none' -- dependencies not supported. +# `unknown' -- same as none, but documents that we really don't know. +# 'pass_all' -- all dependencies passed with no checks. +# 'test_compile' -- check by making test program. +# 'file_magic [[regex]]' -- check by looking for files in library path +# which responds to the $file_magic_cmd with a given extended regex. +# If you have `file' or equivalent on your system and you're not sure +# whether `pass_all' will *always* work, you probably want this one. + +case $host_os in +aix[4-9]*) + lt_cv_deplibs_check_method=pass_all + ;; + +beos*) + lt_cv_deplibs_check_method=pass_all + ;; + +bsdi[45]*) + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)' + lt_cv_file_magic_cmd='/usr/bin/file -L' + lt_cv_file_magic_test_file=/shlib/libc.so + ;; + +cygwin*) + # func_win32_libid is a shell function defined in ltmain.sh + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + ;; + +mingw* | pw32*) + # Base MSYS/MinGW do not provide the 'file' command needed by + # func_win32_libid shell function, so use a weaker test based on 'objdump', + # unless we find 'file', for example because we are cross-compiling. + # func_win32_libid assumes BSD nm, so disallow it if using MS dumpbin. + if ( test "$lt_cv_nm_interface" = "BSD nm" && file / ) >/dev/null 2>&1; then + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + else + lt_cv_deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?' + lt_cv_file_magic_cmd='$OBJDUMP -f' + fi + ;; + +cegcc*) + # use the weaker test based on 'objdump'. See mingw*. + lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' + lt_cv_file_magic_cmd='$OBJDUMP -f' + ;; + +darwin* | rhapsody*) + lt_cv_deplibs_check_method=pass_all + ;; + +freebsd* | dragonfly*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then + case $host_cpu in + i*86 ) + # Not sure whether the presence of OpenBSD here was a mistake. + # Let's accept both of them until this is cleared up. + lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[3-9]86 (compact )?demand paged shared library' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` + ;; + esac + else + lt_cv_deplibs_check_method=pass_all + fi + ;; + +gnu*) + lt_cv_deplibs_check_method=pass_all + ;; + +haiku*) + lt_cv_deplibs_check_method=pass_all + ;; + +hpux10.20* | hpux11*) + lt_cv_file_magic_cmd=/usr/bin/file + case $host_cpu in + ia64*) + lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - IA64' + lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so + ;; + hppa*64*) + lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]' + lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl + ;; + *) + lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9]\.[0-9]) shared library' + lt_cv_file_magic_test_file=/usr/lib/libc.sl + ;; + esac + ;; + +interix[3-9]*) + # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|\.a)$' + ;; + +irix5* | irix6* | nonstopux*) + case $LD in + *-32|*"-32 ") libmagic=32-bit;; + *-n32|*"-n32 ") libmagic=N32;; + *-64|*"-64 ") libmagic=64-bit;; + *) libmagic=never-match;; + esac + lt_cv_deplibs_check_method=pass_all + ;; + +# This must be Linux ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu) + lt_cv_deplibs_check_method=pass_all + ;; + +netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|_pic\.a)$' + fi + ;; + +newos6*) + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=/usr/lib/libnls.so + ;; + +*nto* | *qnx*) + lt_cv_deplibs_check_method=pass_all + ;; + +openbsd*) + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|\.so|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' + fi + ;; + +osf3* | osf4* | osf5*) + lt_cv_deplibs_check_method=pass_all + ;; + +rdos*) + lt_cv_deplibs_check_method=pass_all + ;; + +solaris*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv4 | sysv4.3*) + case $host_vendor in + motorola) + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]' + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` + ;; + ncr) + lt_cv_deplibs_check_method=pass_all + ;; + sequent) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )' + ;; + sni) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB dynamic lib" + lt_cv_file_magic_test_file=/lib/libc.so + ;; + siemens) + lt_cv_deplibs_check_method=pass_all + ;; + pc) + lt_cv_deplibs_check_method=pass_all + ;; + esac + ;; + +tpf*) + lt_cv_deplibs_check_method=pass_all + ;; +esac + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_deplibs_check_method" >&5 +$as_echo "$lt_cv_deplibs_check_method" >&6; } +file_magic_cmd=$lt_cv_file_magic_cmd +deplibs_check_method=$lt_cv_deplibs_check_method +test -z "$deplibs_check_method" && deplibs_check_method=unknown + + + + + + + + + + + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args. +set dummy ${ac_tool_prefix}ar; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_AR+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$AR"; then + ac_cv_prog_AR="$AR" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_AR="${ac_tool_prefix}ar" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +AR=$ac_cv_prog_AR +if test -n "$AR"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 +$as_echo "$AR" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_AR"; then + ac_ct_AR=$AR + # Extract the first word of "ar", so it can be a program name with args. +set dummy ar; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_ac_ct_AR+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_AR"; then + ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_AR="ar" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_AR=$ac_cv_prog_ac_ct_AR +if test -n "$ac_ct_AR"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5 +$as_echo "$ac_ct_AR" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_AR" = x; then + AR="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + AR=$ac_ct_AR + fi +else + AR="$ac_cv_prog_AR" +fi + +test -z "$AR" && AR=ar +test -z "$AR_FLAGS" && AR_FLAGS=cru + + + + + + + + + + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. +set dummy ${ac_tool_prefix}strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_STRIP+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$STRIP"; then + ac_cv_prog_STRIP="$STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_STRIP="${ac_tool_prefix}strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +STRIP=$ac_cv_prog_STRIP +if test -n "$STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 +$as_echo "$STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_STRIP"; then + ac_ct_STRIP=$STRIP + # Extract the first word of "strip", so it can be a program name with args. +set dummy strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_STRIP"; then + ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_STRIP="strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP +if test -n "$ac_ct_STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 +$as_echo "$ac_ct_STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_STRIP" = x; then + STRIP=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + STRIP=$ac_ct_STRIP + fi +else + STRIP="$ac_cv_prog_STRIP" +fi + +test -z "$STRIP" && STRIP=: + + + + + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. +set dummy ${ac_tool_prefix}ranlib; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_RANLIB+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$RANLIB"; then + ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +RANLIB=$ac_cv_prog_RANLIB +if test -n "$RANLIB"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 +$as_echo "$RANLIB" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_RANLIB"; then + ac_ct_RANLIB=$RANLIB + # Extract the first word of "ranlib", so it can be a program name with args. +set dummy ranlib; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_RANLIB"; then + ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_RANLIB="ranlib" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB +if test -n "$ac_ct_RANLIB"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 +$as_echo "$ac_ct_RANLIB" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_RANLIB" = x; then + RANLIB=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + RANLIB=$ac_ct_RANLIB + fi +else + RANLIB="$ac_cv_prog_RANLIB" +fi + +test -z "$RANLIB" && RANLIB=: + + + + + + +# Determine commands to create old-style static archives. +old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' +old_postinstall_cmds='chmod 644 $oldlib' +old_postuninstall_cmds= + +if test -n "$RANLIB"; then + case $host_os in + openbsd*) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$oldlib" + ;; + *) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$oldlib" + ;; + esac + old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib" +fi + +case $host_os in + darwin*) + lock_old_archive_extraction=yes ;; + *) + lock_old_archive_extraction=no ;; +esac + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC + + +# Check for command to grab the raw symbol name followed by C symbol from nm. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking command to parse $NM output from $compiler object" >&5 +$as_echo_n "checking command to parse $NM output from $compiler object... " >&6; } +if test "${lt_cv_sys_global_symbol_pipe+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + +# These are sane defaults that work on at least a few old systems. +# [They come from Ultrix. What could be older than Ultrix?!! ;)] + +# Character class describing NM global symbol codes. +symcode='[BCDEGRST]' + +# Regexp to match symbols that can be accessed directly from C. +sympat='\([_A-Za-z][_A-Za-z0-9]*\)' + +# Define system-specific variables. +case $host_os in +aix*) + symcode='[BCDT]' + ;; +cygwin* | mingw* | pw32* | cegcc*) + symcode='[ABCDGISTW]' + ;; +hpux*) + if test "$host_cpu" = ia64; then + symcode='[ABCDEGRST]' + fi + ;; +irix* | nonstopux*) + symcode='[BCDEGRST]' + ;; +osf*) + symcode='[BCDEGQRST]' + ;; +solaris*) + symcode='[BDRT]' + ;; +sco3.2v5*) + symcode='[DT]' + ;; +sysv4.2uw2*) + symcode='[DT]' + ;; +sysv5* | sco5v6* | unixware* | OpenUNIX*) + symcode='[ABDT]' + ;; +sysv4) + symcode='[DFNSTU]' + ;; +esac + +# If we're using GNU nm, then use its standard symbol codes. +case `$NM -V 2>&1` in +*GNU* | *'with BFD'*) + symcode='[ABCDGIRSTW]' ;; +esac + +# Transform an extracted symbol line into a proper C declaration. +# Some systems (esp. on ia64) link data and code symbols differently, +# so use this general approach. +lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" + +# Transform an extracted symbol line into symbol name and symbol address +lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\) $/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"\2\", (void *) \&\2},/p'" +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([^ ]*\) $/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \(lib[^ ]*\)$/ {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"lib\2\", (void *) \&\2},/p'" + +# Handle CRLF in mingw tool chain +opt_cr= +case $build_os in +mingw*) + opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp + ;; +esac + +# Try without a prefix underscore, then with it. +for ac_symprfx in "" "_"; do + + # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. + symxfrm="\\1 $ac_symprfx\\2 \\2" + + # Write the raw and C identifiers. + if test "$lt_cv_nm_interface" = "MS dumpbin"; then + # Fake it for dumpbin and say T for any non-static function + # and D for any global variable. + # Also find C++ and __fastcall symbols from MSVC++, + # which start with @ or ?. + lt_cv_sys_global_symbol_pipe="$AWK '"\ +" {last_section=section; section=\$ 3};"\ +" /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ +" \$ 0!~/External *\|/{next};"\ +" / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ +" {if(hide[section]) next};"\ +" {f=0}; \$ 0~/\(\).*\|/{f=1}; {printf f ? \"T \" : \"D \"};"\ +" {split(\$ 0, a, /\||\r/); split(a[2], s)};"\ +" s[1]~/^[@?]/{print s[1], s[1]; next};"\ +" s[1]~prfx {split(s[1],t,\"@\"); print t[1], substr(t[1],length(prfx))}"\ +" ' prfx=^$ac_symprfx" + else + lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[ ]\($symcode$symcode*\)[ ][ ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" + fi + + # Check to see that the pipe works correctly. + pipe_works=no + + rm -f conftest* + cat > conftest.$ac_ext <<_LT_EOF +#ifdef __cplusplus +extern "C" { +#endif +char nm_test_var; +void nm_test_func(void); +void nm_test_func(void){} +#ifdef __cplusplus +} +#endif +int main(){nm_test_var='a';nm_test_func();return(0);} +_LT_EOF + + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + # Now try to grab the symbols. + nlist=conftest.nm + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist\""; } >&5 + (eval $NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s "$nlist"; then + # Try sorting and uniquifying the output. + if sort "$nlist" | uniq > "$nlist"T; then + mv -f "$nlist"T "$nlist" + else + rm -f "$nlist"T + fi + + # Make sure that we snagged all the symbols we need. + if $GREP ' nm_test_var$' "$nlist" >/dev/null; then + if $GREP ' nm_test_func$' "$nlist" >/dev/null; then + cat <<_LT_EOF > conftest.$ac_ext +#ifdef __cplusplus +extern "C" { +#endif + +_LT_EOF + # Now generate the symbol file. + eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' + + cat <<_LT_EOF >> conftest.$ac_ext + +/* The mapping between symbol names and symbols. */ +const struct { + const char *name; + void *address; +} +lt__PROGRAM__LTX_preloaded_symbols[] = +{ + { "@PROGRAM@", (void *) 0 }, +_LT_EOF + $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (void *) \&\2},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext + cat <<\_LT_EOF >> conftest.$ac_ext + {0, (void *) 0} +}; + +/* This works around a problem in FreeBSD linker */ +#ifdef FREEBSD_WORKAROUND +static const void *lt_preloaded_setup() { + return lt__PROGRAM__LTX_preloaded_symbols; +} +#endif + +#ifdef __cplusplus +} +#endif +_LT_EOF + # Now try linking the two files. + mv conftest.$ac_objext conftstm.$ac_objext + lt_save_LIBS="$LIBS" + lt_save_CFLAGS="$CFLAGS" + LIBS="conftstm.$ac_objext" + CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag" + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 + (eval $ac_link) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s conftest${ac_exeext}; then + pipe_works=yes + fi + LIBS="$lt_save_LIBS" + CFLAGS="$lt_save_CFLAGS" + else + echo "cannot find nm_test_func in $nlist" >&5 + fi + else + echo "cannot find nm_test_var in $nlist" >&5 + fi + else + echo "cannot run $lt_cv_sys_global_symbol_pipe" >&5 + fi + else + echo "$progname: failed program was:" >&5 + cat conftest.$ac_ext >&5 + fi + rm -rf conftest* conftst* + + # Do not use the global_symbol_pipe unless it works. + if test "$pipe_works" = yes; then + break + else + lt_cv_sys_global_symbol_pipe= + fi +done + +fi + +if test -z "$lt_cv_sys_global_symbol_pipe"; then + lt_cv_sys_global_symbol_to_cdecl= +fi +if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5 +$as_echo "failed" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 +$as_echo "ok" >&6; } +fi + + + + + + + + + + + + + + + + + + + + + + + +# Check whether --enable-libtool-lock was given. +if test "${enable_libtool_lock+set}" = set; then : + enableval=$enable_libtool_lock; +fi + +test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes + +# Some flags need to be propagated to the compiler or linker for good +# libtool support. +case $host in +ia64-*-hpux*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + case `/usr/bin/file conftest.$ac_objext` in + *ELF-32*) + HPUX_IA64_MODE="32" + ;; + *ELF-64*) + HPUX_IA64_MODE="64" + ;; + esac + fi + rm -rf conftest* + ;; +*-*-irix6*) + # Find out which ABI we are using. + echo '#line '$LINENO' "configure"' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + if test "$lt_cv_prog_gnu_ld" = yes; then + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -melf32bsmip" + ;; + *N32*) + LD="${LD-ld} -melf32bmipn32" + ;; + *64-bit*) + LD="${LD-ld} -melf64bmip" + ;; + esac + else + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -32" + ;; + *N32*) + LD="${LD-ld} -n32" + ;; + *64-bit*) + LD="${LD-ld} -64" + ;; + esac + fi + fi + rm -rf conftest* + ;; + +x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \ +s390*-*linux*|s390*-*tpf*|sparc*-*linux*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + case `/usr/bin/file conftest.o` in + *32-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_i386_fbsd" + ;; + x86_64-*linux*) + LD="${LD-ld} -m elf_i386" + ;; + ppc64-*linux*|powerpc64-*linux*) + LD="${LD-ld} -m elf32ppclinux" + ;; + s390x-*linux*) + LD="${LD-ld} -m elf_s390" + ;; + sparc64-*linux*) + LD="${LD-ld} -m elf32_sparc" + ;; + esac + ;; + *64-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_x86_64_fbsd" + ;; + x86_64-*linux*) + LD="${LD-ld} -m elf_x86_64" + ;; + ppc*-*linux*|powerpc*-*linux*) + LD="${LD-ld} -m elf64ppc" + ;; + s390*-*linux*|s390*-*tpf*) + LD="${LD-ld} -m elf64_s390" + ;; + sparc*-*linux*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; + +*-*-sco3.2v5*) + # On SCO OpenServer 5, we need -belf to get full-featured binaries. + SAVE_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -belf" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler needs -belf" >&5 +$as_echo_n "checking whether the C compiler needs -belf... " >&6; } +if test "${lt_cv_cc_needs_belf+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + lt_cv_cc_needs_belf=yes +else + lt_cv_cc_needs_belf=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_cc_needs_belf" >&5 +$as_echo "$lt_cv_cc_needs_belf" >&6; } + if test x"$lt_cv_cc_needs_belf" != x"yes"; then + # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf + CFLAGS="$SAVE_CFLAGS" + fi + ;; +sparc*-*solaris*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + case `/usr/bin/file conftest.o` in + *64-bit*) + case $lt_cv_prog_gnu_ld in + yes*) LD="${LD-ld} -m elf64_sparc" ;; + *) + if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then + LD="${LD-ld} -64" + fi + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; +esac + +need_locks="$enable_libtool_lock" + + + case $host_os in + rhapsody* | darwin*) + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}dsymutil", so it can be a program name with args. +set dummy ${ac_tool_prefix}dsymutil; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_DSYMUTIL+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$DSYMUTIL"; then + ac_cv_prog_DSYMUTIL="$DSYMUTIL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_DSYMUTIL="${ac_tool_prefix}dsymutil" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +DSYMUTIL=$ac_cv_prog_DSYMUTIL +if test -n "$DSYMUTIL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DSYMUTIL" >&5 +$as_echo "$DSYMUTIL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_DSYMUTIL"; then + ac_ct_DSYMUTIL=$DSYMUTIL + # Extract the first word of "dsymutil", so it can be a program name with args. +set dummy dsymutil; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_ac_ct_DSYMUTIL+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_DSYMUTIL"; then + ac_cv_prog_ac_ct_DSYMUTIL="$ac_ct_DSYMUTIL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_DSYMUTIL="dsymutil" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_DSYMUTIL=$ac_cv_prog_ac_ct_DSYMUTIL +if test -n "$ac_ct_DSYMUTIL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DSYMUTIL" >&5 +$as_echo "$ac_ct_DSYMUTIL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_DSYMUTIL" = x; then + DSYMUTIL=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + DSYMUTIL=$ac_ct_DSYMUTIL + fi +else + DSYMUTIL="$ac_cv_prog_DSYMUTIL" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}nmedit", so it can be a program name with args. +set dummy ${ac_tool_prefix}nmedit; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_NMEDIT+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$NMEDIT"; then + ac_cv_prog_NMEDIT="$NMEDIT" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_NMEDIT="${ac_tool_prefix}nmedit" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +NMEDIT=$ac_cv_prog_NMEDIT +if test -n "$NMEDIT"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $NMEDIT" >&5 +$as_echo "$NMEDIT" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_NMEDIT"; then + ac_ct_NMEDIT=$NMEDIT + # Extract the first word of "nmedit", so it can be a program name with args. +set dummy nmedit; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_ac_ct_NMEDIT+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_NMEDIT"; then + ac_cv_prog_ac_ct_NMEDIT="$ac_ct_NMEDIT" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_NMEDIT="nmedit" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_NMEDIT=$ac_cv_prog_ac_ct_NMEDIT +if test -n "$ac_ct_NMEDIT"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_NMEDIT" >&5 +$as_echo "$ac_ct_NMEDIT" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_NMEDIT" = x; then + NMEDIT=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + NMEDIT=$ac_ct_NMEDIT + fi +else + NMEDIT="$ac_cv_prog_NMEDIT" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}lipo", so it can be a program name with args. +set dummy ${ac_tool_prefix}lipo; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_LIPO+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$LIPO"; then + ac_cv_prog_LIPO="$LIPO" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_LIPO="${ac_tool_prefix}lipo" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +LIPO=$ac_cv_prog_LIPO +if test -n "$LIPO"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIPO" >&5 +$as_echo "$LIPO" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_LIPO"; then + ac_ct_LIPO=$LIPO + # Extract the first word of "lipo", so it can be a program name with args. +set dummy lipo; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_ac_ct_LIPO+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_LIPO"; then + ac_cv_prog_ac_ct_LIPO="$ac_ct_LIPO" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_LIPO="lipo" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_LIPO=$ac_cv_prog_ac_ct_LIPO +if test -n "$ac_ct_LIPO"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_LIPO" >&5 +$as_echo "$ac_ct_LIPO" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_LIPO" = x; then + LIPO=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + LIPO=$ac_ct_LIPO + fi +else + LIPO="$ac_cv_prog_LIPO" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}otool", so it can be a program name with args. +set dummy ${ac_tool_prefix}otool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_OTOOL+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$OTOOL"; then + ac_cv_prog_OTOOL="$OTOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_OTOOL="${ac_tool_prefix}otool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +OTOOL=$ac_cv_prog_OTOOL +if test -n "$OTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL" >&5 +$as_echo "$OTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_OTOOL"; then + ac_ct_OTOOL=$OTOOL + # Extract the first word of "otool", so it can be a program name with args. +set dummy otool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_ac_ct_OTOOL+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_OTOOL"; then + ac_cv_prog_ac_ct_OTOOL="$ac_ct_OTOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_OTOOL="otool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_OTOOL=$ac_cv_prog_ac_ct_OTOOL +if test -n "$ac_ct_OTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL" >&5 +$as_echo "$ac_ct_OTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_OTOOL" = x; then + OTOOL=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + OTOOL=$ac_ct_OTOOL + fi +else + OTOOL="$ac_cv_prog_OTOOL" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}otool64", so it can be a program name with args. +set dummy ${ac_tool_prefix}otool64; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_OTOOL64+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$OTOOL64"; then + ac_cv_prog_OTOOL64="$OTOOL64" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_OTOOL64="${ac_tool_prefix}otool64" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +OTOOL64=$ac_cv_prog_OTOOL64 +if test -n "$OTOOL64"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL64" >&5 +$as_echo "$OTOOL64" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_OTOOL64"; then + ac_ct_OTOOL64=$OTOOL64 + # Extract the first word of "otool64", so it can be a program name with args. +set dummy otool64; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_ac_ct_OTOOL64+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_OTOOL64"; then + ac_cv_prog_ac_ct_OTOOL64="$ac_ct_OTOOL64" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_OTOOL64="otool64" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_OTOOL64=$ac_cv_prog_ac_ct_OTOOL64 +if test -n "$ac_ct_OTOOL64"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL64" >&5 +$as_echo "$ac_ct_OTOOL64" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_OTOOL64" = x; then + OTOOL64=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + OTOOL64=$ac_ct_OTOOL64 + fi +else + OTOOL64="$ac_cv_prog_OTOOL64" +fi + + + + + + + + + + + + + + + + + + + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -single_module linker flag" >&5 +$as_echo_n "checking for -single_module linker flag... " >&6; } +if test "${lt_cv_apple_cc_single_mod+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_apple_cc_single_mod=no + if test -z "${LT_MULTI_MODULE}"; then + # By default we will add the -single_module flag. You can override + # by either setting the environment variable LT_MULTI_MODULE + # non-empty at configure time, or by adding -multi_module to the + # link flags. + rm -rf libconftest.dylib* + echo "int foo(void){return 1;}" > conftest.c + echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ +-dynamiclib -Wl,-single_module conftest.c" >&5 + $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ + -dynamiclib -Wl,-single_module conftest.c 2>conftest.err + _lt_result=$? + if test -f libconftest.dylib && test ! -s conftest.err && test $_lt_result = 0; then + lt_cv_apple_cc_single_mod=yes + else + cat conftest.err >&5 + fi + rm -rf libconftest.dylib* + rm -f conftest.* + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_apple_cc_single_mod" >&5 +$as_echo "$lt_cv_apple_cc_single_mod" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -exported_symbols_list linker flag" >&5 +$as_echo_n "checking for -exported_symbols_list linker flag... " >&6; } +if test "${lt_cv_ld_exported_symbols_list+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_ld_exported_symbols_list=no + save_LDFLAGS=$LDFLAGS + echo "_main" > conftest.sym + LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + lt_cv_ld_exported_symbols_list=yes +else + lt_cv_ld_exported_symbols_list=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS="$save_LDFLAGS" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_exported_symbols_list" >&5 +$as_echo "$lt_cv_ld_exported_symbols_list" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -force_load linker flag" >&5 +$as_echo_n "checking for -force_load linker flag... " >&6; } +if test "${lt_cv_ld_force_load+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_ld_force_load=no + cat > conftest.c << _LT_EOF +int forced_loaded() { return 2;} +_LT_EOF + echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&5 + $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&5 + echo "$AR cru libconftest.a conftest.o" >&5 + $AR cru libconftest.a conftest.o 2>&5 + cat > conftest.c << _LT_EOF +int main() { return 0;} +_LT_EOF + echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&5 + $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err + _lt_result=$? + if test -f conftest && test ! -s conftest.err && test $_lt_result = 0 && $GREP forced_load conftest 2>&1 >/dev/null; then + lt_cv_ld_force_load=yes + else + cat conftest.err >&5 + fi + rm -f conftest.err libconftest.a conftest conftest.c + rm -rf conftest.dSYM + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_force_load" >&5 +$as_echo "$lt_cv_ld_force_load" >&6; } + case $host_os in + rhapsody* | darwin1.[012]) + _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;; + darwin1.*) + _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; + darwin*) # darwin 5.x on + # if running on 10.5 or later, the deployment target defaults + # to the OS version, if on x86, and 10.4, the deployment + # target defaults to 10.4. Don't you love it? + case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in + 10.0,*86*-darwin8*|10.0,*-darwin[91]*) + _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; + 10.[012]*) + _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; + 10.*) + _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; + esac + ;; + esac + if test "$lt_cv_apple_cc_single_mod" = "yes"; then + _lt_dar_single_mod='$single_module' + fi + if test "$lt_cv_ld_exported_symbols_list" = "yes"; then + _lt_dar_export_syms=' ${wl}-exported_symbols_list,$output_objdir/${libname}-symbols.expsym' + else + _lt_dar_export_syms='~$NMEDIT -s $output_objdir/${libname}-symbols.expsym ${lib}' + fi + if test "$DSYMUTIL" != ":" && test "$lt_cv_ld_force_load" = "no"; then + _lt_dsymutil='~$DSYMUTIL $lib || :' + else + _lt_dsymutil= + fi + ;; + esac + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 +$as_echo_n "checking how to run the C preprocessor... " >&6; } +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then + if test "${ac_cv_prog_CPP+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + # Double quotes because CPP needs to be expanded + for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" + do + ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + # <limits.h> exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + Syntax error +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <ac_nonexistent.h> +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + break +fi + + done + ac_cv_prog_CPP=$CPP + +fi + CPP=$ac_cv_prog_CPP +else + ac_cv_prog_CPP=$CPP +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 +$as_echo "$CPP" >&6; } +ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + # <limits.h> exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + Syntax error +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <ac_nonexistent.h> +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error "C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details." "$LINENO" 5; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 +$as_echo_n "checking for ANSI C header files... " >&6; } +if test "${ac_cv_header_stdc+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <stdlib.h> +#include <stdarg.h> +#include <string.h> +#include <float.h> + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_header_stdc=yes +else + ac_cv_header_stdc=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <string.h> + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "memchr" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <stdlib.h> + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "free" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. + if test "$cross_compiling" = yes; then : + : +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <ctype.h> +#include <stdlib.h> +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) \ + (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int +main () +{ + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + return 2; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + +else + ac_cv_header_stdc=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 +$as_echo "$ac_cv_header_stdc" >&6; } +if test $ac_cv_header_stdc = yes; then + +$as_echo "#define STDC_HEADERS 1" >>confdefs.h + +fi + +# On IRIX 5.3, sys/types and inttypes.h are conflicting. +for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ + inttypes.h stdint.h unistd.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default +" +eval as_val=\$$as_ac_Header + if test "x$as_val" = x""yes; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + +for ac_header in dlfcn.h +do : + ac_fn_c_check_header_compile "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default +" +if test "x$ac_cv_header_dlfcn_h" = x""yes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_DLFCN_H 1 +_ACEOF + +fi + +done + + + + + + +# Set options + + + + enable_dlopen=no + + + enable_win32_dll=no + + + # Check whether --enable-shared was given. +if test "${enable_shared+set}" = set; then : + enableval=$enable_shared; p=${PACKAGE-default} + case $enableval in + yes) enable_shared=yes ;; + no) enable_shared=no ;; + *) + enable_shared=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_shared=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac +else + enable_shared=yes +fi + + + + + + + + + + # Check whether --enable-static was given. +if test "${enable_static+set}" = set; then : + enableval=$enable_static; p=${PACKAGE-default} + case $enableval in + yes) enable_static=yes ;; + no) enable_static=no ;; + *) + enable_static=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_static=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac +else + enable_static=yes +fi + + + + + + + + + + +# Check whether --with-pic was given. +if test "${with_pic+set}" = set; then : + withval=$with_pic; pic_mode="$withval" +else + pic_mode=default +fi + + +test -z "$pic_mode" && pic_mode=default + + + + + + + + # Check whether --enable-fast-install was given. +if test "${enable_fast_install+set}" = set; then : + enableval=$enable_fast_install; p=${PACKAGE-default} + case $enableval in + yes) enable_fast_install=yes ;; + no) enable_fast_install=no ;; + *) + enable_fast_install=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_fast_install=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac +else + enable_fast_install=yes +fi + + + + + + + + + + + +# This can be used to rebuild libtool when needed +LIBTOOL_DEPS="$ltmain" + +# Always use our own libtool. +LIBTOOL='$(SHELL) $(top_builddir)/libtool' + + + + + + + + + + + + + + + + + + + + + + + + + + +test -z "$LN_S" && LN_S="ln -s" + + + + + + + + + + + + + + +if test -n "${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for objdir" >&5 +$as_echo_n "checking for objdir... " >&6; } +if test "${lt_cv_objdir+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + rm -f .libs 2>/dev/null +mkdir .libs 2>/dev/null +if test -d .libs; then + lt_cv_objdir=.libs +else + # MS-DOS does not allow filenames that begin with a dot. + lt_cv_objdir=_libs +fi +rmdir .libs 2>/dev/null +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_objdir" >&5 +$as_echo "$lt_cv_objdir" >&6; } +objdir=$lt_cv_objdir + + + + + +cat >>confdefs.h <<_ACEOF +#define LT_OBJDIR "$lt_cv_objdir/" +_ACEOF + + + + +case $host_os in +aix3*) + # AIX sometimes has problems with the GCC collect2 program. For some + # reason, if we set the COLLECT_NAMES environment variable, the problems + # vanish in a puff of smoke. + if test "X${COLLECT_NAMES+set}" != Xset; then + COLLECT_NAMES= + export COLLECT_NAMES + fi + ;; +esac + +# Global variables: +ofile=libtool +can_build_shared=yes + +# All known linkers require a `.a' archive for static linking (except MSVC, +# which needs '.lib'). +libext=a + +with_gnu_ld="$lt_cv_prog_gnu_ld" + +old_CC="$CC" +old_CFLAGS="$CFLAGS" + +# Set sane defaults for various variables +test -z "$CC" && CC=cc +test -z "$LTCC" && LTCC=$CC +test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS +test -z "$LD" && LD=ld +test -z "$ac_objext" && ac_objext=o + +for cc_temp in $compiler""; do + case $cc_temp in + compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; + distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; + \-*) ;; + *) break;; + esac +done +cc_basename=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` + + +# Only perform the check for file, if the check method requires it +test -z "$MAGIC_CMD" && MAGIC_CMD=file +case $deplibs_check_method in +file_magic*) + if test "$file_magic_cmd" = '$MAGIC_CMD'; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${ac_tool_prefix}file" >&5 +$as_echo_n "checking for ${ac_tool_prefix}file... " >&6; } +if test "${lt_cv_path_MAGIC_CMD+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + case $MAGIC_CMD in +[\\/*] | ?:[\\/]*) + lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. + ;; +*) + lt_save_MAGIC_CMD="$MAGIC_CMD" + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" + for ac_dir in $ac_dummy; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/${ac_tool_prefix}file; then + lt_cv_path_MAGIC_CMD="$ac_dir/${ac_tool_prefix}file" + if test -n "$file_magic_test_file"; then + case $deplibs_check_method in + "file_magic "*) + file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` + MAGIC_CMD="$lt_cv_path_MAGIC_CMD" + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + $EGREP "$file_magic_regex" > /dev/null; then + : + else + cat <<_LT_EOF 1>&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +_LT_EOF + fi ;; + esac + fi + break + fi + done + IFS="$lt_save_ifs" + MAGIC_CMD="$lt_save_MAGIC_CMD" + ;; +esac +fi + +MAGIC_CMD="$lt_cv_path_MAGIC_CMD" +if test -n "$MAGIC_CMD"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 +$as_echo "$MAGIC_CMD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + + + +if test -z "$lt_cv_path_MAGIC_CMD"; then + if test -n "$ac_tool_prefix"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for file" >&5 +$as_echo_n "checking for file... " >&6; } +if test "${lt_cv_path_MAGIC_CMD+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + case $MAGIC_CMD in +[\\/*] | ?:[\\/]*) + lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. + ;; +*) + lt_save_MAGIC_CMD="$MAGIC_CMD" + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" + for ac_dir in $ac_dummy; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/file; then + lt_cv_path_MAGIC_CMD="$ac_dir/file" + if test -n "$file_magic_test_file"; then + case $deplibs_check_method in + "file_magic "*) + file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` + MAGIC_CMD="$lt_cv_path_MAGIC_CMD" + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + $EGREP "$file_magic_regex" > /dev/null; then + : + else + cat <<_LT_EOF 1>&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +_LT_EOF + fi ;; + esac + fi + break + fi + done + IFS="$lt_save_ifs" + MAGIC_CMD="$lt_save_MAGIC_CMD" + ;; +esac +fi + +MAGIC_CMD="$lt_cv_path_MAGIC_CMD" +if test -n "$MAGIC_CMD"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 +$as_echo "$MAGIC_CMD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + else + MAGIC_CMD=: + fi +fi + + fi + ;; +esac + +# Use C for the default configuration in the libtool script + +lt_save_CC="$CC" +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +# Source file extension for C test sources. +ac_ext=c + +# Object file extension for compiled C test sources. +objext=o +objext=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="int some_variable = 0;" + +# Code to be used in simple link tests +lt_simple_link_test_code='int main(){return(0);}' + + + + + + + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC + +# Save the default compiler, since it gets overwritten when the other +# tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. +compiler_DEFAULT=$CC + +# save warnings/boilerplate of simple test code +ac_outfile=conftest.$ac_objext +echo "$lt_simple_compile_test_code" >conftest.$ac_ext +eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_compiler_boilerplate=`cat conftest.err` +$RM conftest* + +ac_outfile=conftest.$ac_objext +echo "$lt_simple_link_test_code" >conftest.$ac_ext +eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_linker_boilerplate=`cat conftest.err` +$RM -r conftest* + + +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... +if test -n "$compiler"; then + +lt_prog_compiler_no_builtin_flag= + +if test "$GCC" = yes; then + case $cc_basename in + nvcc*) + lt_prog_compiler_no_builtin_flag=' -Xcompiler -fno-builtin' ;; + *) + lt_prog_compiler_no_builtin_flag=' -fno-builtin' ;; + esac + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -fno-rtti -fno-exceptions" >&5 +$as_echo_n "checking if $compiler supports -fno-rtti -fno-exceptions... " >&6; } +if test "${lt_cv_prog_compiler_rtti_exceptions+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_rtti_exceptions=no + ac_outfile=conftest.$ac_objext + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="-fno-rtti -fno-exceptions" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler_rtti_exceptions=yes + fi + fi + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_rtti_exceptions" >&5 +$as_echo "$lt_cv_prog_compiler_rtti_exceptions" >&6; } + +if test x"$lt_cv_prog_compiler_rtti_exceptions" = xyes; then + lt_prog_compiler_no_builtin_flag="$lt_prog_compiler_no_builtin_flag -fno-rtti -fno-exceptions" +else + : +fi + +fi + + + + + + + lt_prog_compiler_wl= +lt_prog_compiler_pic= +lt_prog_compiler_static= + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5 +$as_echo_n "checking for $compiler option to produce PIC... " >&6; } + + if test "$GCC" = yes; then + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_static='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static='-Bstatic' + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + lt_prog_compiler_pic='-fPIC' + ;; + m68k) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. + lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4' + ;; + esac + ;; + + beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + + mingw* | cygwin* | pw32* | os2* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + # Although the cygwin gcc ignores -fPIC, still need this for old-style + # (--disable-auto-import) libraries + lt_prog_compiler_pic='-DDLL_EXPORT' + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + lt_prog_compiler_pic='-fno-common' + ;; + + haiku*) + # PIC is the default for Haiku. + # The "-static" flag exists, but is broken. + lt_prog_compiler_static= + ;; + + hpux*) + # PIC is the default for 64-bit PA HP-UX, but not for 32-bit + # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag + # sets the default TLS model and affects inlining. + case $host_cpu in + hppa*64*) + # +Z the default + ;; + *) + lt_prog_compiler_pic='-fPIC' + ;; + esac + ;; + + interix[3-9]*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + + msdosdjgpp*) + # Just because we use GCC doesn't mean we suddenly get shared libraries + # on systems that don't support them. + lt_prog_compiler_can_build_shared=no + enable_shared=no + ;; + + *nto* | *qnx*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + lt_prog_compiler_pic='-fPIC -shared' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + lt_prog_compiler_pic=-Kconform_pic + fi + ;; + + *) + lt_prog_compiler_pic='-fPIC' + ;; + esac + + case $cc_basename in + nvcc*) # Cuda Compiler Driver 2.2 + lt_prog_compiler_wl='-Xlinker ' + lt_prog_compiler_pic='-Xcompiler -fPIC' + ;; + esac + else + # PORTME Check for flag to pass linker flags through the system compiler. + case $host_os in + aix*) + lt_prog_compiler_wl='-Wl,' + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static='-Bstatic' + else + lt_prog_compiler_static='-bnso -bI:/lib/syscalls.exp' + fi + ;; + + mingw* | cygwin* | pw32* | os2* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + lt_prog_compiler_pic='-DDLL_EXPORT' + ;; + + hpux9* | hpux10* | hpux11*) + lt_prog_compiler_wl='-Wl,' + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + lt_prog_compiler_pic='+Z' + ;; + esac + # Is there a better lt_prog_compiler_static that works with the bundled CC? + lt_prog_compiler_static='${wl}-a ${wl}archive' + ;; + + irix5* | irix6* | nonstopux*) + lt_prog_compiler_wl='-Wl,' + # PIC (with -KPIC) is the default. + lt_prog_compiler_static='-non_shared' + ;; + + linux* | k*bsd*-gnu | kopensolaris*-gnu) + case $cc_basename in + # old Intel for x86_64 which still supported -KPIC. + ecc*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-static' + ;; + # icc used to be incompatible with GCC. + # ICC 10 doesn't accept -KPIC any more. + icc* | ifort*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fPIC' + lt_prog_compiler_static='-static' + ;; + # Lahey Fortran 8.1. + lf95*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='--shared' + lt_prog_compiler_static='--static' + ;; + pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) + # Portland Group compilers (*not* the Pentium gcc compiler, + # which looks to be a dead project) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fpic' + lt_prog_compiler_static='-Bstatic' + ;; + ccc*) + lt_prog_compiler_wl='-Wl,' + # All Alpha code is PIC. + lt_prog_compiler_static='-non_shared' + ;; + xl* | bgxl* | bgf* | mpixl*) + # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-qpic' + lt_prog_compiler_static='-qstaticlink' + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ F* | *Sun*Fortran*) + # Sun Fortran 8.3 passes all unrecognized flags to the linker + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + lt_prog_compiler_wl='' + ;; + *Sun\ C*) + # Sun C 5.9 + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + lt_prog_compiler_wl='-Wl,' + ;; + esac + ;; + esac + ;; + + newsos6) + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + ;; + + *nto* | *qnx*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + lt_prog_compiler_pic='-fPIC -shared' + ;; + + osf3* | osf4* | osf5*) + lt_prog_compiler_wl='-Wl,' + # All OSF/1 code is PIC. + lt_prog_compiler_static='-non_shared' + ;; + + rdos*) + lt_prog_compiler_static='-non_shared' + ;; + + solaris*) + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + case $cc_basename in + f77* | f90* | f95*) + lt_prog_compiler_wl='-Qoption ld ';; + *) + lt_prog_compiler_wl='-Wl,';; + esac + ;; + + sunos4*) + lt_prog_compiler_wl='-Qoption ld ' + lt_prog_compiler_pic='-PIC' + lt_prog_compiler_static='-Bstatic' + ;; + + sysv4 | sysv4.2uw2* | sysv4.3*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + ;; + + sysv4*MP*) + if test -d /usr/nec ;then + lt_prog_compiler_pic='-Kconform_pic' + lt_prog_compiler_static='-Bstatic' + fi + ;; + + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + ;; + + unicos*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_can_build_shared=no + ;; + + uts4*) + lt_prog_compiler_pic='-pic' + lt_prog_compiler_static='-Bstatic' + ;; + + *) + lt_prog_compiler_can_build_shared=no + ;; + esac + fi + +case $host_os in + # For platforms which do not support PIC, -DPIC is meaningless: + *djgpp*) + lt_prog_compiler_pic= + ;; + *) + lt_prog_compiler_pic="$lt_prog_compiler_pic -DPIC" + ;; +esac +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_prog_compiler_pic" >&5 +$as_echo "$lt_prog_compiler_pic" >&6; } + + + + + + +# +# Check to make sure the PIC flag actually works. +# +if test -n "$lt_prog_compiler_pic"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5 +$as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic works... " >&6; } +if test "${lt_cv_prog_compiler_pic_works+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_pic_works=no + ac_outfile=conftest.$ac_objext + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="$lt_prog_compiler_pic -DPIC" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler_pic_works=yes + fi + fi + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works" >&5 +$as_echo "$lt_cv_prog_compiler_pic_works" >&6; } + +if test x"$lt_cv_prog_compiler_pic_works" = xyes; then + case $lt_prog_compiler_pic in + "" | " "*) ;; + *) lt_prog_compiler_pic=" $lt_prog_compiler_pic" ;; + esac +else + lt_prog_compiler_pic= + lt_prog_compiler_can_build_shared=no +fi + +fi + + + + + + +# +# Check to make sure the static flag actually works. +# +wl=$lt_prog_compiler_wl eval lt_tmp_static_flag=\"$lt_prog_compiler_static\" +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5 +$as_echo_n "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; } +if test "${lt_cv_prog_compiler_static_works+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_static_works=no + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS $lt_tmp_static_flag" + echo "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&5 + $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler_static_works=yes + fi + else + lt_cv_prog_compiler_static_works=yes + fi + fi + $RM -r conftest* + LDFLAGS="$save_LDFLAGS" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works" >&5 +$as_echo "$lt_cv_prog_compiler_static_works" >&6; } + +if test x"$lt_cv_prog_compiler_static_works" = xyes; then + : +else + lt_prog_compiler_static= +fi + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 +$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } +if test "${lt_cv_prog_compiler_c_o+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_c_o=no + $RM -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + lt_cv_prog_compiler_c_o=yes + fi + fi + chmod u+w . 2>&5 + $RM conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files + $RM out/* && rmdir out + cd .. + $RM -r conftest + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 +$as_echo "$lt_cv_prog_compiler_c_o" >&6; } + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 +$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } +if test "${lt_cv_prog_compiler_c_o+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_c_o=no + $RM -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + lt_cv_prog_compiler_c_o=yes + fi + fi + chmod u+w . 2>&5 + $RM conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files + $RM out/* && rmdir out + cd .. + $RM -r conftest + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 +$as_echo "$lt_cv_prog_compiler_c_o" >&6; } + + + + +hard_links="nottested" +if test "$lt_cv_prog_compiler_c_o" = no && test "$need_locks" != no; then + # do not overwrite the value of need_locks provided by the user + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5 +$as_echo_n "checking if we can lock with hard links... " >&6; } + hard_links=yes + $RM conftest* + ln conftest.a conftest.b 2>/dev/null && hard_links=no + touch conftest.a + ln conftest.a conftest.b 2>&5 || hard_links=no + ln conftest.a conftest.b 2>/dev/null && hard_links=no + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5 +$as_echo "$hard_links" >&6; } + if test "$hard_links" = no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5 +$as_echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;} + need_locks=warn + fi +else + need_locks=no +fi + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5 +$as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } + + runpath_var= + allow_undefined_flag= + always_export_symbols=no + archive_cmds= + archive_expsym_cmds= + compiler_needs_object=no + enable_shared_with_static_runtimes=no + export_dynamic_flag_spec= + export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + hardcode_automatic=no + hardcode_direct=no + hardcode_direct_absolute=no + hardcode_libdir_flag_spec= + hardcode_libdir_flag_spec_ld= + hardcode_libdir_separator= + hardcode_minus_L=no + hardcode_shlibpath_var=unsupported + inherit_rpath=no + link_all_deplibs=unknown + module_cmds= + module_expsym_cmds= + old_archive_from_new_cmds= + old_archive_from_expsyms_cmds= + thread_safe_flag_spec= + whole_archive_flag_spec= + # include_expsyms should be a list of space-separated symbols to be *always* + # included in the symbol list + include_expsyms= + # exclude_expsyms can be an extended regexp of symbols to exclude + # it will be wrapped by ` (' and `)$', so one must not match beginning or + # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', + # as well as any symbol that contains `d'. + exclude_expsyms='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*' + # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out + # platforms (ab)use it in PIC code, but their linkers get confused if + # the symbol is explicitly referenced. Since portable code cannot + # rely on this symbol name, it's probably fine to never include it in + # preloaded symbol tables. + # Exclude shared library initialization/finalization symbols. + extract_expsyms_cmds= + + case $host_os in + cygwin* | mingw* | pw32* | cegcc*) + # FIXME: the MSVC++ port hasn't been tested in a loooong time + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + if test "$GCC" != yes; then + with_gnu_ld=no + fi + ;; + interix*) + # we just hope/assume this is gcc and not c89 (= MSVC++) + with_gnu_ld=yes + ;; + openbsd*) + with_gnu_ld=no + ;; + esac + + ld_shlibs=yes + + # On some targets, GNU ld is compatible enough with the native linker + # that we're better off using the native interface for both. + lt_use_gnu_ld_interface=no + if test "$with_gnu_ld" = yes; then + case $host_os in + aix*) + # The AIX port of GNU ld has always aspired to compatibility + # with the native linker. However, as the warning in the GNU ld + # block says, versions before 2.19.5* couldn't really create working + # shared libraries, regardless of the interface used. + case `$LD -v 2>&1` in + *\ \(GNU\ Binutils\)\ 2.19.5*) ;; + *\ \(GNU\ Binutils\)\ 2.[2-9]*) ;; + *\ \(GNU\ Binutils\)\ [3-9]*) ;; + *) + lt_use_gnu_ld_interface=yes + ;; + esac + ;; + *) + lt_use_gnu_ld_interface=yes + ;; + esac + fi + + if test "$lt_use_gnu_ld_interface" = yes; then + # If archive_cmds runs LD, not CC, wlarc should be empty + wlarc='${wl}' + + # Set some defaults for GNU ld with shared library support. These + # are reset later if shared libraries are not supported. Putting them + # here allows them to be overridden if necessary. + runpath_var=LD_RUN_PATH + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + export_dynamic_flag_spec='${wl}--export-dynamic' + # ancient GNU ld didn't support --whole-archive et. al. + if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then + whole_archive_flag_spec="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + else + whole_archive_flag_spec= + fi + supports_anon_versioning=no + case `$LD -v 2>&1` in + *GNU\ gold*) supports_anon_versioning=yes ;; + *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 + *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... + *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... + *\ 2.11.*) ;; # other 2.11 versions + *) supports_anon_versioning=yes ;; + esac + + # See if GNU ld supports shared libraries. + case $host_os in + aix[3-9]*) + # On AIX/PPC, the GNU linker is very broken + if test "$host_cpu" != ia64; then + ld_shlibs=no + cat <<_LT_EOF 1>&2 + +*** Warning: the GNU linker, at least up to release 2.19, is reported +*** to be unable to reliably create shared libraries on AIX. +*** Therefore, libtool is disabling shared libraries support. If you +*** really care for shared libraries, you may want to install binutils +*** 2.20 or above, or modify your PATH so that a non-GNU linker is found. +*** You will then need to restart the configuration process. + +_LT_EOF + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='' + ;; + m68k) + archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + ;; + esac + ;; + + beos*) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + allow_undefined_flag=unsupported + # Joseph Beckenbach <jrb3@best.com> says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + else + ld_shlibs=no + fi + ;; + + cygwin* | mingw* | pw32* | cegcc*) + # _LT_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless, + # as there is no search path for DLLs. + hardcode_libdir_flag_spec='-L$libdir' + export_dynamic_flag_spec='${wl}--export-all-symbols' + allow_undefined_flag=unsupported + always_export_symbols=no + enable_shared_with_static_runtimes=yes + export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/'\'' | $SED -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols' + + if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file (1st line + # is EXPORTS), use it as is; otherwise, prepend... + archive_expsym_cmds='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + ld_shlibs=no + fi + ;; + + haiku*) + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + link_all_deplibs=yes + ;; + + interix[3-9]*) + hardcode_direct=no + hardcode_shlibpath_var=no + hardcode_libdir_flag_spec='${wl}-rpath,$libdir' + export_dynamic_flag_spec='${wl}-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + archive_expsym_cmds='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + + gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) + tmp_diet=no + if test "$host_os" = linux-dietlibc; then + case $cc_basename in + diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) + esac + fi + if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ + && test "$tmp_diet" = no + then + tmp_addflag= + tmp_sharedflag='-shared' + case $cc_basename,$host_cpu in + pgcc*) # Portland Group C compiler + whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_addflag=' $pic_flag' + ;; + pgf77* | pgf90* | pgf95* | pgfortran*) + # Portland Group f77 and f90 compilers + whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_addflag=' $pic_flag -Mnomain' ;; + ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 + tmp_addflag=' -i_dynamic' ;; + efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 + tmp_addflag=' -i_dynamic -nofor_main' ;; + ifc* | ifort*) # Intel Fortran compiler + tmp_addflag=' -nofor_main' ;; + lf95*) # Lahey Fortran 8.1 + whole_archive_flag_spec= + tmp_sharedflag='--shared' ;; + xl[cC]* | bgxl[cC]* | mpixl[cC]*) # IBM XL C 8.0 on PPC (deal with xlf below) + tmp_sharedflag='-qmkshrobj' + tmp_addflag= ;; + nvcc*) # Cuda Compiler Driver 2.2 + whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + compiler_needs_object=yes + ;; + esac + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) # Sun C 5.9 + whole_archive_flag_spec='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + compiler_needs_object=yes + tmp_sharedflag='-G' ;; + *Sun\ F*) # Sun Fortran 8.3 + tmp_sharedflag='-G' ;; + esac + archive_cmds='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + + if test "x$supports_anon_versioning" = xyes; then + archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' + fi + + case $cc_basename in + xlf* | bgf* | bgxlf* | mpixlf*) + # IBM XL Fortran 10.1 on PPC cannot create shared libs itself + whole_archive_flag_spec='--whole-archive$convenience --no-whole-archive' + hardcode_libdir_flag_spec= + hardcode_libdir_flag_spec_ld='-rpath $libdir' + archive_cmds='$LD -shared $libobjs $deplibs $compiler_flags -soname $soname -o $lib' + if test "x$supports_anon_versioning" = xyes; then + archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $LD -shared $libobjs $deplibs $compiler_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' + fi + ;; + esac + else + ld_shlibs=no + fi + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' + wlarc= + else + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + fi + ;; + + solaris*) + if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then + ld_shlibs=no + cat <<_LT_EOF 1>&2 + +*** Warning: The releases 2.8.* of the GNU linker cannot reliably +*** create shared libraries on Solaris systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.9.1 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs=no + fi + ;; + + sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) + case `$LD -v 2>&1` in + *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*) + ld_shlibs=no + cat <<_LT_EOF 1>&2 + +*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not +*** reliably create shared libraries on SCO systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.16.91.0.3 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + ;; + *) + # For security reasons, it is highly recommended that you always + # use absolute paths for naming shared libraries, and exclude the + # DT_RUNPATH tag from executables and libraries. But doing so + # requires that you compile everything twice, which is a pain. + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs=no + fi + ;; + esac + ;; + + sunos4*) + archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' + wlarc= + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + *) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs=no + fi + ;; + esac + + if test "$ld_shlibs" = no; then + runpath_var= + hardcode_libdir_flag_spec= + export_dynamic_flag_spec= + whole_archive_flag_spec= + fi + else + # PORTME fill in a description of your system's linker (not GNU ld) + case $host_os in + aix3*) + allow_undefined_flag=unsupported + always_export_symbols=yes + archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' + # Note: this linker hardcodes the directories in LIBPATH if there + # are no directories specified by -L. + hardcode_minus_L=yes + if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then + # Neither direct hardcoding nor static linking is supported with a + # broken collect2. + hardcode_direct=unsupported + fi + ;; + + aix[4-9]*) + if test "$host_cpu" = ia64; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag="" + else + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to AIX nm, but means don't demangle with GNU nm + # Also, AIX nm treats weak defined symbols like other global + # defined symbols, whereas GNU nm marks them as "W". + if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then + export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' + else + export_symbols_cmds='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' + fi + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # need to do runtime linking. + case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) + for ld_flag in $LDFLAGS; do + if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then + aix_use_runtimelinking=yes + break + fi + done + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + archive_cmds='' + hardcode_direct=yes + hardcode_direct_absolute=yes + hardcode_libdir_separator=':' + link_all_deplibs=yes + file_list_spec='${wl}-f,' + + if test "$GCC" = yes; then + case $host_os in aix4.[012]|aix4.[012].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`${CC} -print-prog-name=collect2` + if test -f "$collect2name" && + strings "$collect2name" | $GREP resolve_lib_name >/dev/null + then + # We have reworked collect2 + : + else + # We have old collect2 + hardcode_direct=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + hardcode_minus_L=yes + hardcode_libdir_flag_spec='-L$libdir' + hardcode_libdir_separator= + fi + ;; + esac + shared_flag='-shared' + if test "$aix_use_runtimelinking" = yes; then + shared_flag="$shared_flag "'${wl}-G' + fi + else + # not using gcc + if test "$host_cpu" = ia64; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test "$aix_use_runtimelinking" = yes; then + shared_flag='${wl}-G' + else + shared_flag='${wl}-bM:SRE' + fi + fi + fi + + export_dynamic_flag_spec='${wl}-bexpall' + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to export. + always_export_symbols=yes + if test "$aix_use_runtimelinking" = yes; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + allow_undefined_flag='-berok' + # Determine the default libpath from the value encoded in an + # empty executable. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + +lt_aix_libpath_sed=' + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\(.*\)$/\1/ + p + } + }' +aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` +# Check for a 64-bit object if we didn't find anything. +if test -z "$aix_libpath"; then + aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` +fi +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi + + hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" + archive_expsym_cmds='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" + else + if test "$host_cpu" = ia64; then + hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib' + allow_undefined_flag="-z nodefs" + archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an + # empty executable. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + +lt_aix_libpath_sed=' + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\(.*\)$/\1/ + p + } + }' +aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` +# Check for a 64-bit object if we didn't find anything. +if test -z "$aix_libpath"; then + aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` +fi +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi + + hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + no_undefined_flag=' ${wl}-bernotok' + allow_undefined_flag=' ${wl}-berok' + if test "$with_gnu_ld" = yes; then + # We only use this code for GNU lds that support --whole-archive. + whole_archive_flag_spec='${wl}--whole-archive$convenience ${wl}--no-whole-archive' + else + # Exported symbols can be pulled into shared objects from archives + whole_archive_flag_spec='$convenience' + fi + archive_cmds_need_lc=yes + # This is similar to how AIX traditionally builds its shared libraries. + archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' + fi + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='' + ;; + m68k) + archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + ;; + esac + ;; + + bsdi[45]*) + export_dynamic_flag_spec=-rdynamic + ;; + + cygwin* | mingw* | pw32* | cegcc*) + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + hardcode_libdir_flag_spec=' ' + allow_undefined_flag=unsupported + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=".dll" + # FIXME: Setting linknames here is a bad hack. + archive_cmds='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' + # The linker will automatically build a .lib file if we build a DLL. + old_archive_from_new_cmds='true' + # FIXME: Should let the user specify the lib program. + old_archive_cmds='lib -OUT:$oldlib$oldobjs$old_deplibs' + fix_srcfile_path='`cygpath -w "$srcfile"`' + enable_shared_with_static_runtimes=yes + ;; + + darwin* | rhapsody*) + + + archive_cmds_need_lc=no + hardcode_direct=no + hardcode_automatic=yes + hardcode_shlibpath_var=unsupported + if test "$lt_cv_ld_force_load" = "yes"; then + whole_archive_flag_spec='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience ${wl}-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' + else + whole_archive_flag_spec='' + fi + link_all_deplibs=yes + allow_undefined_flag="$_lt_dar_allow_undefined" + case $cc_basename in + ifort*) _lt_dar_can_shared=yes ;; + *) _lt_dar_can_shared=$GCC ;; + esac + if test "$_lt_dar_can_shared" = "yes"; then + output_verbose_link_cmd=func_echo_all + archive_cmds="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}" + module_cmds="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}" + archive_expsym_cmds="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}" + module_expsym_cmds="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}" + + else + ld_shlibs=no + fi + + ;; + + dgux*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_shlibpath_var=no + ;; + + # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor + # support. Future versions do this automatically, but an explicit c++rt0.o + # does not break anything, and helps significantly (at the cost of a little + # extra space). + freebsd2.2*) + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + # Unfortunately, older versions of FreeBSD 2 do not have this feature. + freebsd2*) + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=yes + hardcode_minus_L=yes + hardcode_shlibpath_var=no + ;; + + # FreeBSD 3 and greater uses gcc -shared to do shared libraries. + freebsd* | dragonfly*) + archive_cmds='$CC -shared -o $lib $libobjs $deplibs $compiler_flags' + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + hpux9*) + if test "$GCC" = yes; then + archive_cmds='$RM $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + else + archive_cmds='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + fi + hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' + hardcode_libdir_separator=: + hardcode_direct=yes + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + export_dynamic_flag_spec='${wl}-E' + ;; + + hpux10*) + if test "$GCC" = yes && test "$with_gnu_ld" = no; then + archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' + fi + if test "$with_gnu_ld" = no; then + hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' + hardcode_libdir_flag_spec_ld='+b $libdir' + hardcode_libdir_separator=: + hardcode_direct=yes + hardcode_direct_absolute=yes + export_dynamic_flag_spec='${wl}-E' + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + fi + ;; + + hpux11*) + if test "$GCC" = yes && test "$with_gnu_ld" = no; then + case $host_cpu in + hppa*64*) + archive_cmds='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + else + case $host_cpu in + hppa*64*) + archive_cmds='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + + # Older versions of the 11.00 compiler do not understand -b yet + # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC understands -b" >&5 +$as_echo_n "checking if $CC understands -b... " >&6; } +if test "${lt_cv_prog_compiler__b+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler__b=no + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS -b" + echo "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&5 + $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler__b=yes + fi + else + lt_cv_prog_compiler__b=yes + fi + fi + $RM -r conftest* + LDFLAGS="$save_LDFLAGS" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler__b" >&5 +$as_echo "$lt_cv_prog_compiler__b" >&6; } + +if test x"$lt_cv_prog_compiler__b" = xyes; then + archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' +else + archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' +fi + + ;; + esac + fi + if test "$with_gnu_ld" = no; then + hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' + hardcode_libdir_separator=: + + case $host_cpu in + hppa*64*|ia64*) + hardcode_direct=no + hardcode_shlibpath_var=no + ;; + *) + hardcode_direct=yes + hardcode_direct_absolute=yes + export_dynamic_flag_spec='${wl}-E' + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + ;; + esac + fi + ;; + + irix5* | irix6* | nonstopux*) + if test "$GCC" = yes; then + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + # Try to use the -exported_symbol ld option, if it does not + # work, assume that -exports_file does not work either and + # implicitly export all symbols. + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +int foo(void) {} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib' + +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS="$save_LDFLAGS" + else + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib' + fi + archive_cmds_need_lc='no' + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator=: + inherit_rpath=yes + link_all_deplibs=yes + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out + else + archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF + fi + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + newsos6) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=yes + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator=: + hardcode_shlibpath_var=no + ;; + + *nto* | *qnx*) + ;; + + openbsd*) + if test -f /usr/libexec/ld.so; then + hardcode_direct=yes + hardcode_shlibpath_var=no + hardcode_direct_absolute=yes + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' + hardcode_libdir_flag_spec='${wl}-rpath,$libdir' + export_dynamic_flag_spec='${wl}-E' + else + case $host_os in + openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec='-R$libdir' + ;; + *) + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + hardcode_libdir_flag_spec='${wl}-rpath,$libdir' + ;; + esac + fi + else + ld_shlibs=no + fi + ;; + + os2*) + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + allow_undefined_flag=unsupported + archive_cmds='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~echo DATA >> $output_objdir/$libname.def~echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' + old_archive_from_new_cmds='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' + ;; + + osf3*) + if test "$GCC" = yes; then + allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' + archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + allow_undefined_flag=' -expect_unresolved \*' + archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + fi + archive_cmds_need_lc='no' + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator=: + ;; + + osf4* | osf5*) # as osf3* with the addition of -msym flag + if test "$GCC" = yes; then + allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' + archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + else + allow_undefined_flag=' -expect_unresolved \*' + archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + archive_expsym_cmds='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ + $CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~$RM $lib.exp' + + # Both c and cxx compiler support -rpath directly + hardcode_libdir_flag_spec='-rpath $libdir' + fi + archive_cmds_need_lc='no' + hardcode_libdir_separator=: + ;; + + solaris*) + no_undefined_flag=' -z defs' + if test "$GCC" = yes; then + wlarc='${wl}' + archive_cmds='$CC -shared ${wl}-z ${wl}text ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -shared ${wl}-z ${wl}text ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + else + case `$CC -V 2>&1` in + *"Compilers 5.0"*) + wlarc='' + archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' + archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' + ;; + *) + wlarc='${wl}' + archive_cmds='$CC -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + ;; + esac + fi + hardcode_libdir_flag_spec='-R$libdir' + hardcode_shlibpath_var=no + case $host_os in + solaris2.[0-5] | solaris2.[0-5].*) ;; + *) + # The compiler driver will combine and reorder linker options, + # but understands `-z linker_flag'. GCC discards it without `$wl', + # but is careful enough not to reorder. + # Supported since Solaris 2.6 (maybe 2.5.1?) + if test "$GCC" = yes; then + whole_archive_flag_spec='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' + else + whole_archive_flag_spec='-z allextract$convenience -z defaultextract' + fi + ;; + esac + link_all_deplibs=yes + ;; + + sunos4*) + if test "x$host_vendor" = xsequent; then + # Use $CC to link under sequent, because it throws in some extra .o + # files that make .init and .fini sections work. + archive_cmds='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' + fi + hardcode_libdir_flag_spec='-L$libdir' + hardcode_direct=yes + hardcode_minus_L=yes + hardcode_shlibpath_var=no + ;; + + sysv4) + case $host_vendor in + sni) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=yes # is this really true??? + ;; + siemens) + ## LD is ld it makes a PLAMLIB + ## CC just makes a GrossModule. + archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags' + reload_cmds='$CC -r -o $output$reload_objs' + hardcode_direct=no + ;; + motorola) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=no #Motorola manual says yes, but my tests say they lie + ;; + esac + runpath_var='LD_RUN_PATH' + hardcode_shlibpath_var=no + ;; + + sysv4.3*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_shlibpath_var=no + export_dynamic_flag_spec='-Bexport' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_shlibpath_var=no + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + ld_shlibs=yes + fi + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) + no_undefined_flag='${wl}-z,text' + archive_cmds_need_lc=no + hardcode_shlibpath_var=no + runpath_var='LD_RUN_PATH' + + if test "$GCC" = yes; then + archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # Note: We can NOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + no_undefined_flag='${wl}-z,text' + allow_undefined_flag='${wl}-z,nodefs' + archive_cmds_need_lc=no + hardcode_shlibpath_var=no + hardcode_libdir_flag_spec='${wl}-R,$libdir' + hardcode_libdir_separator=':' + link_all_deplibs=yes + export_dynamic_flag_spec='${wl}-Bexport' + runpath_var='LD_RUN_PATH' + + if test "$GCC" = yes; then + archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + uts4*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_shlibpath_var=no + ;; + + *) + ld_shlibs=no + ;; + esac + + if test x$host_vendor = xsni; then + case $host in + sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) + export_dynamic_flag_spec='${wl}-Blargedynsym' + ;; + esac + fi + fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs" >&5 +$as_echo "$ld_shlibs" >&6; } +test "$ld_shlibs" = no && can_build_shared=no + +with_gnu_ld=$with_gnu_ld + + + + + + + + + + + + + + + +# +# Do we need to explicitly link libc? +# +case "x$archive_cmds_need_lc" in +x|xyes) + # Assume -lc should be added + archive_cmds_need_lc=yes + + if test "$enable_shared" = yes && test "$GCC" = yes; then + case $archive_cmds in + *'~'*) + # FIXME: we may have to deal with multi-command sequences. + ;; + '$CC '*) + # Test whether the compiler implicitly links with -lc since on some + # systems, -lgcc has to come before -lc. If gcc already passes -lc + # to ld, don't add -lc before -lgcc. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5 +$as_echo_n "checking whether -lc should be explicitly linked in... " >&6; } +if test "${lt_cv_archive_cmds_need_lc+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + $RM conftest* + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } 2>conftest.err; then + soname=conftest + lib=conftest + libobjs=conftest.$ac_objext + deplibs= + wl=$lt_prog_compiler_wl + pic_flag=$lt_prog_compiler_pic + compiler_flags=-v + linker_flags=-v + verstring= + output_objdir=. + libname=conftest + lt_save_allow_undefined_flag=$allow_undefined_flag + allow_undefined_flag= + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5 + (eval $archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + then + lt_cv_archive_cmds_need_lc=no + else + lt_cv_archive_cmds_need_lc=yes + fi + allow_undefined_flag=$lt_save_allow_undefined_flag + else + cat conftest.err 1>&5 + fi + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_archive_cmds_need_lc" >&5 +$as_echo "$lt_cv_archive_cmds_need_lc" >&6; } + archive_cmds_need_lc=$lt_cv_archive_cmds_need_lc + ;; + esac + fi + ;; +esac + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5 +$as_echo_n "checking dynamic linker characteristics... " >&6; } + +if test "$GCC" = yes; then + case $host_os in + darwin*) lt_awk_arg="/^libraries:/,/LR/" ;; + *) lt_awk_arg="/^libraries:/" ;; + esac + case $host_os in + mingw* | cegcc*) lt_sed_strip_eq="s,=\([A-Za-z]:\),\1,g" ;; + *) lt_sed_strip_eq="s,=/,/,g" ;; + esac + lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` + case $lt_search_path_spec in + *\;*) + # if the path contains ";" then we assume it to be the separator + # otherwise default to the standard path separator (i.e. ":") - it is + # assumed that no part of a normal pathname contains ";" but that should + # okay in the real world where ";" in dirpaths is itself problematic. + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'` + ;; + *) + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"` + ;; + esac + # Ok, now we have the path, separated by spaces, we can step through it + # and add multilib dir if necessary. + lt_tmp_lt_search_path_spec= + lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` + for lt_sys_path in $lt_search_path_spec; do + if test -d "$lt_sys_path/$lt_multi_os_dir"; then + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir" + else + test -d "$lt_sys_path" && \ + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" + fi + done + lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' +BEGIN {RS=" "; FS="/|\n";} { + lt_foo=""; + lt_count=0; + for (lt_i = NF; lt_i > 0; lt_i--) { + if ($lt_i != "" && $lt_i != ".") { + if ($lt_i == "..") { + lt_count++; + } else { + if (lt_count == 0) { + lt_foo="/" $lt_i lt_foo; + } else { + lt_count--; + } + } + } + } + if (lt_foo != "") { lt_freq[lt_foo]++; } + if (lt_freq[lt_foo] == 1) { print lt_foo; } +}'` + # AWK program above erroneously prepends '/' to C:/dos/paths + # for these hosts. + case $host_os in + mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ + $SED 's,/\([A-Za-z]:\),\1,g'` ;; + esac + sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` +else + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" +fi +library_names_spec= +libname_spec='lib$name' +soname_spec= +shrext_cmds=".so" +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +shlibpath_overrides_runpath=unknown +version_type=none +dynamic_linker="$host_os ld.so" +sys_lib_dlsearch_path_spec="/lib /usr/lib" +need_lib_prefix=unknown +hardcode_into_libs=no + +# when you set need_version to no, make sure it does not cause -set_version +# flags to be left without arguments +need_version=unknown + +case $host_os in +aix3*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX 3 has no versioning support, so we append a major version to the name. + soname_spec='${libname}${release}${shared_ext}$major' + ;; + +aix[4-9]*) + version_type=linux + need_lib_prefix=no + need_version=no + hardcode_into_libs=yes + if test "$host_cpu" = ia64; then + # AIX 5 supports IA64 + library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + else + # With GCC up to 2.95.x, collect2 would create an import file + # for dependence libraries. The import file would start with + # the line `#! .'. This would cause the generated library to + # depend on `.', always an invalid library. This was fixed in + # development snapshots of GCC prior to 3.0. + case $host_os in + aix4 | aix4.[01] | aix4.[01].*) + if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' + echo ' yes ' + echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then + : + else + can_build_shared=no + fi + ;; + esac + # AIX (on Power*) has no versioning support, so currently we can not hardcode correct + # soname into executable. Probably we can add versioning support to + # collect2, so additional links can be useful in future. + if test "$aix_use_runtimelinking" = yes; then + # If using run time linking (on AIX 4.2 or later) use lib<name>.so + # instead of lib<name>.a to let people know that these are not + # typical AIX shared libraries. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + else + # We preserve .a as extension for shared libraries through AIX4.2 + # and later when we are not doing run time linking. + library_names_spec='${libname}${release}.a $libname.a' + soname_spec='${libname}${release}${shared_ext}$major' + fi + shlibpath_var=LIBPATH + fi + ;; + +amigaos*) + case $host_cpu in + powerpc) + # Since July 2007 AmigaOS4 officially supports .so libraries. + # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + ;; + m68k) + library_names_spec='$libname.ixlibrary $libname.a' + # Create ${libname}_ixlibrary.a entries in /sys/libs. + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' + ;; + esac + ;; + +beos*) + library_names_spec='${libname}${shared_ext}' + dynamic_linker="$host_os ld.so" + shlibpath_var=LIBRARY_PATH + ;; + +bsdi[45]*) + version_type=linux + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" + sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" + # the default ld.so.conf also contains /usr/contrib/lib and + # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow + # libtool to hard-code these into programs + ;; + +cygwin* | mingw* | pw32* | cegcc*) + version_type=windows + shrext_cmds=".dll" + need_version=no + need_lib_prefix=no + + case $GCC,$host_os in + yes,cygwin* | yes,mingw* | yes,pw32* | yes,cegcc*) + library_names_spec='$libname.dll.a' + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \${file}`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname~ + if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then + eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; + fi' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + + case $host_os in + cygwin*) + # Cygwin DLLs use 'cyg' prefix rather than 'lib' + soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api" + ;; + mingw* | cegcc*) + # MinGW DLLs use traditional 'lib' prefix + soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + ;; + pw32*) + # pw32 DLLs use 'pw' prefix rather than 'lib' + library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + ;; + esac + ;; + + *) + library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib' + ;; + esac + dynamic_linker='Win32 ld.exe' + # FIXME: first we should search . and the directory the executable is in + shlibpath_var=PATH + ;; + +darwin* | rhapsody*) + dynamic_linker="$host_os dyld" + version_type=darwin + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext' + soname_spec='${libname}${release}${major}$shared_ext' + shlibpath_overrides_runpath=yes + shlibpath_var=DYLD_LIBRARY_PATH + shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' + + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib" + sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' + ;; + +dgux*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +freebsd* | dragonfly*) + # DragonFly does not have aout. When/if they implement a new + # versioning mechanism, adjust this. + if test -x /usr/bin/objformat; then + objformat=`/usr/bin/objformat` + else + case $host_os in + freebsd[123]*) objformat=aout ;; + *) objformat=elf ;; + esac + fi + version_type=freebsd-$objformat + case $version_type in + freebsd-elf*) + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + need_version=no + need_lib_prefix=no + ;; + freebsd-*) + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' + need_version=yes + ;; + esac + shlibpath_var=LD_LIBRARY_PATH + case $host_os in + freebsd2*) + shlibpath_overrides_runpath=yes + ;; + freebsd3.[01]* | freebsdelf3.[01]*) + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ + freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + *) # from 4.6 on, and DragonFly + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + esac + ;; + +gnu*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + hardcode_into_libs=yes + ;; + +haiku*) + version_type=linux + need_lib_prefix=no + need_version=no + dynamic_linker="$host_os runtime_loader" + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LIBRARY_PATH + shlibpath_overrides_runpath=yes + sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/beos/system/lib' + hardcode_into_libs=yes + ;; + +hpux9* | hpux10* | hpux11*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + version_type=sunos + need_lib_prefix=no + need_version=no + case $host_cpu in + ia64*) + shrext_cmds='.so' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.so" + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + if test "X$HPUX_IA64_MODE" = X32; then + sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" + else + sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" + fi + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + hppa*64*) + shrext_cmds='.sl' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.sl" + shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + *) + shrext_cmds='.sl' + dynamic_linker="$host_os dld.sl" + shlibpath_var=SHLIB_PATH + shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + ;; + esac + # HP-UX runs *really* slowly unless shared libraries are mode 555, ... + postinstall_cmds='chmod 555 $lib' + # or fails outright, so override atomically: + install_override_mode=555 + ;; + +interix[3-9]*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +irix5* | irix6* | nonstopux*) + case $host_os in + nonstopux*) version_type=nonstopux ;; + *) + if test "$lt_cv_prog_gnu_ld" = yes; then + version_type=linux + else + version_type=irix + fi ;; + esac + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' + case $host_os in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in # libtool.m4 will add one of these switches to LD + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") + libsuff= shlibsuff= libmagic=32-bit;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") + libsuff=32 shlibsuff=N32 libmagic=N32;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") + libsuff=64 shlibsuff=64 libmagic=64-bit;; + *) libsuff= shlibsuff= libmagic=never-match;; + esac + ;; + esac + shlibpath_var=LD_LIBRARY${shlibsuff}_PATH + shlibpath_overrides_runpath=no + sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" + sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" + hardcode_into_libs=yes + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux*oldld* | linux*aout* | linux*coff*) + dynamic_linker=no + ;; + +# This must be Linux ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + + # Some binutils ld are patched to set DT_RUNPATH + if test "${lt_cv_shlibpath_overrides_runpath+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_shlibpath_overrides_runpath=no + save_LDFLAGS=$LDFLAGS + save_libdir=$libdir + eval "libdir=/foo; wl=\"$lt_prog_compiler_wl\"; \ + LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec\"" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + if ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null; then : + lt_cv_shlibpath_overrides_runpath=yes +fi +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS=$save_LDFLAGS + libdir=$save_libdir + +fi + + shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath + + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + # Append ld.so.conf contents to the search path + if test -f /etc/ld.so.conf; then + lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` + sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" + fi + + # We used to test for /lib/ld.so.1 and disable shared libraries on + # powerpc, because MkLinux only supported shared libraries with the + # GNU dynamic linker. Since this was broken with cross compilers, + # most powerpc-linux boxes support dynamic linking these days and + # people can always --disable-shared, the test was removed, and we + # assume the GNU/Linux dynamic linker is in use. + dynamic_linker='GNU/Linux ld.so' + ;; + +netbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + dynamic_linker='NetBSD (a.out) ld.so' + else + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='NetBSD ld.elf_so' + fi + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + +newsos6) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +*nto* | *qnx*) + version_type=qnx + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='ldqnx.so' + ;; + +openbsd*) + version_type=sunos + sys_lib_dlsearch_path_spec="/usr/lib" + need_lib_prefix=no + # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. + case $host_os in + openbsd3.3 | openbsd3.3.*) need_version=yes ;; + *) need_version=no ;; + esac + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + case $host_os in + openbsd2.[89] | openbsd2.[89].*) + shlibpath_overrides_runpath=no + ;; + *) + shlibpath_overrides_runpath=yes + ;; + esac + else + shlibpath_overrides_runpath=yes + fi + ;; + +os2*) + libname_spec='$name' + shrext_cmds=".dll" + need_lib_prefix=no + library_names_spec='$libname${shared_ext} $libname.a' + dynamic_linker='OS/2 ld.exe' + shlibpath_var=LIBPATH + ;; + +osf3* | osf4* | osf5*) + version_type=osf + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" + sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" + ;; + +rdos*) + dynamic_linker=no + ;; + +solaris*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + ;; + +sunos4*) + version_type=sunos + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + if test "$with_gnu_ld" = yes; then + need_lib_prefix=no + fi + need_version=yes + ;; + +sysv4 | sysv4.3*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + case $host_vendor in + sni) + shlibpath_overrides_runpath=no + need_lib_prefix=no + runpath_var=LD_RUN_PATH + ;; + siemens) + need_lib_prefix=no + ;; + motorola) + need_lib_prefix=no + need_version=no + shlibpath_overrides_runpath=no + sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' + ;; + esac + ;; + +sysv4*MP*) + if test -d /usr/nec ;then + version_type=linux + library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' + soname_spec='$libname${shared_ext}.$major' + shlibpath_var=LD_LIBRARY_PATH + fi + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + version_type=freebsd-elf + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + if test "$with_gnu_ld" = yes; then + sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' + else + sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' + case $host_os in + sco3.2v5*) + sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" + ;; + esac + fi + sys_lib_dlsearch_path_spec='/usr/lib' + ;; + +tpf*) + # TPF is a cross-target only. Preferred cross-host = GNU/Linux. + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +uts4*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +*) + dynamic_linker=no + ;; +esac +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5 +$as_echo "$dynamic_linker" >&6; } +test "$dynamic_linker" = no && can_build_shared=no + +variables_saved_for_relink="PATH $shlibpath_var $runpath_var" +if test "$GCC" = yes; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" +fi + +if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then + sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec" +fi +if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then + sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec" +fi + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5 +$as_echo_n "checking how to hardcode library paths into programs... " >&6; } +hardcode_action= +if test -n "$hardcode_libdir_flag_spec" || + test -n "$runpath_var" || + test "X$hardcode_automatic" = "Xyes" ; then + + # We can hardcode non-existent directories. + if test "$hardcode_direct" != no && + # If the only mechanism to avoid hardcoding is shlibpath_var, we + # have to relink, otherwise we might link with an installed library + # when we should be linking with a yet-to-be-installed one + ## test "$_LT_TAGVAR(hardcode_shlibpath_var, )" != no && + test "$hardcode_minus_L" != no; then + # Linking always hardcodes the temporary library directory. + hardcode_action=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + hardcode_action=immediate + fi +else + # We cannot hardcode anything, or else we can only hardcode existing + # directories. + hardcode_action=unsupported +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action" >&5 +$as_echo "$hardcode_action" >&6; } + +if test "$hardcode_action" = relink || + test "$inherit_rpath" = yes; then + # Fast installation is not supported + enable_fast_install=no +elif test "$shlibpath_overrides_runpath" = yes || + test "$enable_shared" = no; then + # Fast installation is not necessary + enable_fast_install=needless +fi + + + + + + + if test "x$enable_dlopen" != xyes; then + enable_dlopen=unknown + enable_dlopen_self=unknown + enable_dlopen_self_static=unknown +else + lt_cv_dlopen=no + lt_cv_dlopen_libs= + + case $host_os in + beos*) + lt_cv_dlopen="load_add_on" + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ;; + + mingw* | pw32* | cegcc*) + lt_cv_dlopen="LoadLibrary" + lt_cv_dlopen_libs= + ;; + + cygwin*) + lt_cv_dlopen="dlopen" + lt_cv_dlopen_libs= + ;; + + darwin*) + # if libdl is installed we need to link against it + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 +$as_echo_n "checking for dlopen in -ldl... " >&6; } +if test "${ac_cv_lib_dl_dlopen+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldl $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 dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dl_dlopen=yes +else + ac_cv_lib_dl_dlopen=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 +$as_echo "$ac_cv_lib_dl_dlopen" >&6; } +if test "x$ac_cv_lib_dl_dlopen" = x""yes; then : + lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" +else + + lt_cv_dlopen="dyld" + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + +fi + + ;; + + *) + ac_fn_c_check_func "$LINENO" "shl_load" "ac_cv_func_shl_load" +if test "x$ac_cv_func_shl_load" = x""yes; then : + lt_cv_dlopen="shl_load" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5 +$as_echo_n "checking for shl_load in -ldld... " >&6; } +if test "${ac_cv_lib_dld_shl_load+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldld $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 shl_load (); +int +main () +{ +return shl_load (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dld_shl_load=yes +else + ac_cv_lib_dld_shl_load=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5 +$as_echo "$ac_cv_lib_dld_shl_load" >&6; } +if test "x$ac_cv_lib_dld_shl_load" = x""yes; then : + lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld" +else + ac_fn_c_check_func "$LINENO" "dlopen" "ac_cv_func_dlopen" +if test "x$ac_cv_func_dlopen" = x""yes; then : + lt_cv_dlopen="dlopen" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 +$as_echo_n "checking for dlopen in -ldl... " >&6; } +if test "${ac_cv_lib_dl_dlopen+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldl $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 dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dl_dlopen=yes +else + ac_cv_lib_dl_dlopen=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 +$as_echo "$ac_cv_lib_dl_dlopen" >&6; } +if test "x$ac_cv_lib_dl_dlopen" = x""yes; then : + lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -lsvld" >&5 +$as_echo_n "checking for dlopen in -lsvld... " >&6; } +if test "${ac_cv_lib_svld_dlopen+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lsvld $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 dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_svld_dlopen=yes +else + ac_cv_lib_svld_dlopen=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_svld_dlopen" >&5 +$as_echo "$ac_cv_lib_svld_dlopen" >&6; } +if test "x$ac_cv_lib_svld_dlopen" = x""yes; then : + lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dld_link in -ldld" >&5 +$as_echo_n "checking for dld_link in -ldld... " >&6; } +if test "${ac_cv_lib_dld_dld_link+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldld $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 dld_link (); +int +main () +{ +return dld_link (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dld_dld_link=yes +else + ac_cv_lib_dld_dld_link=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_dld_link" >&5 +$as_echo "$ac_cv_lib_dld_dld_link" >&6; } +if test "x$ac_cv_lib_dld_dld_link" = x""yes; then : + lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld" +fi + + +fi + + +fi + + +fi + + +fi + + +fi + + ;; + esac + + if test "x$lt_cv_dlopen" != xno; then + enable_dlopen=yes + else + enable_dlopen=no + fi + + case $lt_cv_dlopen in + dlopen) + save_CPPFLAGS="$CPPFLAGS" + test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" + + save_LDFLAGS="$LDFLAGS" + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" + + save_LIBS="$LIBS" + LIBS="$lt_cv_dlopen_libs $LIBS" + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a program can dlopen itself" >&5 +$as_echo_n "checking whether a program can dlopen itself... " >&6; } +if test "${lt_cv_dlopen_self+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test "$cross_compiling" = yes; then : + lt_cv_dlopen_self=cross +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext <<_LT_EOF +#line 11717 "configure" +#include "confdefs.h" + +#if HAVE_DLFCN_H +#include <dlfcn.h> +#endif + +#include <stdio.h> + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +/* When -fvisbility=hidden is used, assume the code has been annotated + correspondingly for the symbols needed. */ +#if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) +void fnord () __attribute__((visibility("default"))); +#endif + +void fnord () { int i=42; } +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else + { + if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + else puts (dlerror ()); + } + /* dlclose (self); */ + } + else + puts (dlerror ()); + + return status; +} +_LT_EOF + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 + (eval $ac_link) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s conftest${ac_exeext} 2>/dev/null; then + (./conftest; exit; ) >&5 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;; + x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;; + x$lt_dlunknown|x*) lt_cv_dlopen_self=no ;; + esac + else : + # compilation failed + lt_cv_dlopen_self=no + fi +fi +rm -fr conftest* + + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self" >&5 +$as_echo "$lt_cv_dlopen_self" >&6; } + + if test "x$lt_cv_dlopen_self" = xyes; then + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a statically linked program can dlopen itself" >&5 +$as_echo_n "checking whether a statically linked program can dlopen itself... " >&6; } +if test "${lt_cv_dlopen_self_static+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test "$cross_compiling" = yes; then : + lt_cv_dlopen_self_static=cross +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext <<_LT_EOF +#line 11823 "configure" +#include "confdefs.h" + +#if HAVE_DLFCN_H +#include <dlfcn.h> +#endif + +#include <stdio.h> + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +/* When -fvisbility=hidden is used, assume the code has been annotated + correspondingly for the symbols needed. */ +#if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) +void fnord () __attribute__((visibility("default"))); +#endif + +void fnord () { int i=42; } +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else + { + if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + else puts (dlerror ()); + } + /* dlclose (self); */ + } + else + puts (dlerror ()); + + return status; +} +_LT_EOF + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 + (eval $ac_link) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s conftest${ac_exeext} 2>/dev/null; then + (./conftest; exit; ) >&5 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;; + x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;; + x$lt_dlunknown|x*) lt_cv_dlopen_self_static=no ;; + esac + else : + # compilation failed + lt_cv_dlopen_self_static=no + fi +fi +rm -fr conftest* + + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self_static" >&5 +$as_echo "$lt_cv_dlopen_self_static" >&6; } + fi + + CPPFLAGS="$save_CPPFLAGS" + LDFLAGS="$save_LDFLAGS" + LIBS="$save_LIBS" + ;; + esac + + case $lt_cv_dlopen_self in + yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; + *) enable_dlopen_self=unknown ;; + esac + + case $lt_cv_dlopen_self_static in + yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; + *) enable_dlopen_self_static=unknown ;; + esac +fi + + + + + + + + + + + + + + + + + +striplib= +old_striplib= +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether stripping libraries is possible" >&5 +$as_echo_n "checking whether stripping libraries is possible... " >&6; } +if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then + test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" + test -z "$striplib" && striplib="$STRIP --strip-unneeded" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else +# FIXME - insert some real tests, host_os isn't really good enough + case $host_os in + darwin*) + if test -n "$STRIP" ; then + striplib="$STRIP -x" + old_striplib="$STRIP -S" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + fi + ;; + *) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + ;; + esac +fi + + + + + + + + + + + + + # Report which library types will actually be built + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if libtool supports shared libraries" >&5 +$as_echo_n "checking if libtool supports shared libraries... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $can_build_shared" >&5 +$as_echo "$can_build_shared" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build shared libraries" >&5 +$as_echo_n "checking whether to build shared libraries... " >&6; } + test "$can_build_shared" = "no" && enable_shared=no + + # On AIX, shared libraries and static libraries use the same namespace, and + # are all built from PIC. + case $host_os in + aix3*) + test "$enable_shared" = yes && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + + aix[4-9]*) + if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then + test "$enable_shared" = yes && enable_static=no + fi + ;; + esac + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_shared" >&5 +$as_echo "$enable_shared" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build static libraries" >&5 +$as_echo_n "checking whether to build static libraries... " >&6; } + # Make sure either enable_shared or enable_static is yes. + test "$enable_shared" = yes || enable_static=yes + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_static" >&5 +$as_echo "$enable_static" >&6; } + + + + +fi +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +CC="$lt_save_CC" + + if test -n "$CXX" && ( test "X$CXX" != "Xno" && + ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) || + (test "X$CXX" != "Xg++"))) ; then + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C++ preprocessor" >&5 +$as_echo_n "checking how to run the C++ preprocessor... " >&6; } +if test -z "$CXXCPP"; then + if test "${ac_cv_prog_CXXCPP+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + # Double quotes because CXXCPP needs to be expanded + for CXXCPP in "$CXX -E" "/lib/cpp" + do + ac_preproc_ok=false +for ac_cxx_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + # <limits.h> exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + Syntax error +_ACEOF +if ac_fn_cxx_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <ac_nonexistent.h> +_ACEOF +if ac_fn_cxx_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + break +fi + + done + ac_cv_prog_CXXCPP=$CXXCPP + +fi + CXXCPP=$ac_cv_prog_CXXCPP +else + ac_cv_prog_CXXCPP=$CXXCPP +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXXCPP" >&5 +$as_echo "$CXXCPP" >&6; } +ac_preproc_ok=false +for ac_cxx_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + # <limits.h> exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + Syntax error +_ACEOF +if ac_fn_cxx_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <ac_nonexistent.h> +_ACEOF +if ac_fn_cxx_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error "C++ preprocessor \"$CXXCPP\" fails sanity check +See \`config.log' for more details." "$LINENO" 5; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +else + _lt_caught_CXX_error=yes +fi + +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + +archive_cmds_need_lc_CXX=no +allow_undefined_flag_CXX= +always_export_symbols_CXX=no +archive_expsym_cmds_CXX= +compiler_needs_object_CXX=no +export_dynamic_flag_spec_CXX= +hardcode_direct_CXX=no +hardcode_direct_absolute_CXX=no +hardcode_libdir_flag_spec_CXX= +hardcode_libdir_flag_spec_ld_CXX= +hardcode_libdir_separator_CXX= +hardcode_minus_L_CXX=no +hardcode_shlibpath_var_CXX=unsupported +hardcode_automatic_CXX=no +inherit_rpath_CXX=no +module_cmds_CXX= +module_expsym_cmds_CXX= +link_all_deplibs_CXX=unknown +old_archive_cmds_CXX=$old_archive_cmds +reload_flag_CXX=$reload_flag +reload_cmds_CXX=$reload_cmds +no_undefined_flag_CXX= +whole_archive_flag_spec_CXX= +enable_shared_with_static_runtimes_CXX=no + +# Source file extension for C++ test sources. +ac_ext=cpp + +# Object file extension for compiled C++ test sources. +objext=o +objext_CXX=$objext + +# No sense in running all these tests if we already determined that +# the CXX compiler isn't working. Some variables (like enable_shared) +# are currently assumed to apply to all compilers on this platform, +# and will be corrupted by setting them based on a non-working compiler. +if test "$_lt_caught_CXX_error" != yes; then + # Code to be used in simple compile tests + lt_simple_compile_test_code="int some_variable = 0;" + + # Code to be used in simple link tests + lt_simple_link_test_code='int main(int, char *[]) { return(0); }' + + # ltmain only uses $CC for tagged configurations so make sure $CC is set. + + + + + + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC + + + # save warnings/boilerplate of simple test code + ac_outfile=conftest.$ac_objext +echo "$lt_simple_compile_test_code" >conftest.$ac_ext +eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_compiler_boilerplate=`cat conftest.err` +$RM conftest* + + ac_outfile=conftest.$ac_objext +echo "$lt_simple_link_test_code" >conftest.$ac_ext +eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_linker_boilerplate=`cat conftest.err` +$RM -r conftest* + + + # Allow CC to be a program name with arguments. + lt_save_CC=$CC + lt_save_LD=$LD + lt_save_GCC=$GCC + GCC=$GXX + lt_save_with_gnu_ld=$with_gnu_ld + lt_save_path_LD=$lt_cv_path_LD + if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then + lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx + else + $as_unset lt_cv_prog_gnu_ld + fi + if test -n "${lt_cv_path_LDCXX+set}"; then + lt_cv_path_LD=$lt_cv_path_LDCXX + else + $as_unset lt_cv_path_LD + fi + test -z "${LDCXX+set}" || LD=$LDCXX + CC=${CXX-"c++"} + compiler=$CC + compiler_CXX=$CC + for cc_temp in $compiler""; do + case $cc_temp in + compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; + distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; + \-*) ;; + *) break;; + esac +done +cc_basename=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` + + + if test -n "$compiler"; then + # We don't want -fno-exception when compiling C++ code, so set the + # no_builtin_flag separately + if test "$GXX" = yes; then + lt_prog_compiler_no_builtin_flag_CXX=' -fno-builtin' + else + lt_prog_compiler_no_builtin_flag_CXX= + fi + + if test "$GXX" = yes; then + # Set up default GNU C++ configuration + + + +# Check whether --with-gnu-ld was given. +if test "${with_gnu_ld+set}" = set; then : + withval=$with_gnu_ld; test "$withval" = no || with_gnu_ld=yes +else + with_gnu_ld=no +fi + +ac_prog=ld +if test "$GCC" = yes; then + # Check if gcc -print-prog-name=ld gives a path. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5 +$as_echo_n "checking for ld used by $CC... " >&6; } + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case $ac_prog in + # Accept absolute paths. + [\\/]* | ?:[\\/]*) + re_direlt='/[^/][^/]*/\.\./' + # Canonicalize the pathname of ld + ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` + while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do + ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` + done + test -z "$LD" && LD="$ac_prog" + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test "$with_gnu_ld" = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5 +$as_echo_n "checking for GNU ld... " >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5 +$as_echo_n "checking for non-GNU ld... " >&6; } +fi +if test "${lt_cv_path_LD+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$LD"; then + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + lt_cv_path_LD="$ac_dir/$ac_prog" + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some variants of GNU ld only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + case `"$lt_cv_path_LD" -v 2>&1 </dev/null` in + *GNU* | *'with BFD'*) + test "$with_gnu_ld" != no && break + ;; + *) + test "$with_gnu_ld" != yes && break + ;; + esac + fi + done + IFS="$lt_save_ifs" +else + lt_cv_path_LD="$LD" # Let the user override the test with a path. +fi +fi + +LD="$lt_cv_path_LD" +if test -n "$LD"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LD" >&5 +$as_echo "$LD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +test -z "$LD" && as_fn_error "no acceptable ld found in \$PATH" "$LINENO" 5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5 +$as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; } +if test "${lt_cv_prog_gnu_ld+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + # I'd rather use --version here, but apparently some GNU lds only accept -v. +case `$LD -v 2>&1 </dev/null` in +*GNU* | *'with BFD'*) + lt_cv_prog_gnu_ld=yes + ;; +*) + lt_cv_prog_gnu_ld=no + ;; +esac +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_gnu_ld" >&5 +$as_echo "$lt_cv_prog_gnu_ld" >&6; } +with_gnu_ld=$lt_cv_prog_gnu_ld + + + + + + + + # Check if GNU C++ uses GNU ld as the underlying linker, since the + # archiving commands below assume that GNU ld is being used. + if test "$with_gnu_ld" = yes; then + archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + + hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' + export_dynamic_flag_spec_CXX='${wl}--export-dynamic' + + # If archive_cmds runs LD, not CC, wlarc should be empty + # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to + # investigate it a little bit more. (MM) + wlarc='${wl}' + + # ancient GNU ld didn't support --whole-archive et. al. + if eval "`$CC -print-prog-name=ld` --help 2>&1" | + $GREP 'no-whole-archive' > /dev/null; then + whole_archive_flag_spec_CXX="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + else + whole_archive_flag_spec_CXX= + fi + else + with_gnu_ld=no + wlarc= + + # A generic and very simple default shared library creation + # command for GNU C++ for the case where it uses the native + # linker, instead of GNU ld. If possible, this setting should + # overridden to take advantage of the native linker features on + # the platform it is being used on. + archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' + fi + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + + else + GXX=no + with_gnu_ld=no + wlarc= + fi + + # PORTME: fill in a description of your system's C++ link characteristics + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5 +$as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } + ld_shlibs_CXX=yes + case $host_os in + aix3*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + aix[4-9]*) + if test "$host_cpu" = ia64; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag="" + else + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # need to do runtime linking. + case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) + for ld_flag in $LDFLAGS; do + case $ld_flag in + *-brtl*) + aix_use_runtimelinking=yes + break + ;; + esac + done + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + archive_cmds_CXX='' + hardcode_direct_CXX=yes + hardcode_direct_absolute_CXX=yes + hardcode_libdir_separator_CXX=':' + link_all_deplibs_CXX=yes + file_list_spec_CXX='${wl}-f,' + + if test "$GXX" = yes; then + case $host_os in aix4.[012]|aix4.[012].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`${CC} -print-prog-name=collect2` + if test -f "$collect2name" && + strings "$collect2name" | $GREP resolve_lib_name >/dev/null + then + # We have reworked collect2 + : + else + # We have old collect2 + hardcode_direct_CXX=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + hardcode_minus_L_CXX=yes + hardcode_libdir_flag_spec_CXX='-L$libdir' + hardcode_libdir_separator_CXX= + fi + esac + shared_flag='-shared' + if test "$aix_use_runtimelinking" = yes; then + shared_flag="$shared_flag "'${wl}-G' + fi + else + # not using gcc + if test "$host_cpu" = ia64; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test "$aix_use_runtimelinking" = yes; then + shared_flag='${wl}-G' + else + shared_flag='${wl}-bM:SRE' + fi + fi + fi + + export_dynamic_flag_spec_CXX='${wl}-bexpall' + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to + # export. + always_export_symbols_CXX=yes + if test "$aix_use_runtimelinking" = yes; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + allow_undefined_flag_CXX='-berok' + # Determine the default libpath from the value encoded in an empty + # executable. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + +lt_aix_libpath_sed=' + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\(.*\)$/\1/ + p + } + }' +aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` +# Check for a 64-bit object if we didn't find anything. +if test -z "$aix_libpath"; then + aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` +fi +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi + + hardcode_libdir_flag_spec_CXX='${wl}-blibpath:$libdir:'"$aix_libpath" + + archive_expsym_cmds_CXX='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" + else + if test "$host_cpu" = ia64; then + hardcode_libdir_flag_spec_CXX='${wl}-R $libdir:/usr/lib:/lib' + allow_undefined_flag_CXX="-z nodefs" + archive_expsym_cmds_CXX="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an + # empty executable. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + +lt_aix_libpath_sed=' + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\(.*\)$/\1/ + p + } + }' +aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` +# Check for a 64-bit object if we didn't find anything. +if test -z "$aix_libpath"; then + aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` +fi +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi + + hardcode_libdir_flag_spec_CXX='${wl}-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + no_undefined_flag_CXX=' ${wl}-bernotok' + allow_undefined_flag_CXX=' ${wl}-berok' + if test "$with_gnu_ld" = yes; then + # We only use this code for GNU lds that support --whole-archive. + whole_archive_flag_spec_CXX='${wl}--whole-archive$convenience ${wl}--no-whole-archive' + else + # Exported symbols can be pulled into shared objects from archives + whole_archive_flag_spec_CXX='$convenience' + fi + archive_cmds_need_lc_CXX=yes + # This is similar to how AIX traditionally builds its shared + # libraries. + archive_expsym_cmds_CXX="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' + fi + fi + ;; + + beos*) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + allow_undefined_flag_CXX=unsupported + # Joseph Beckenbach <jrb3@best.com> says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + archive_cmds_CXX='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + else + ld_shlibs_CXX=no + fi + ;; + + chorus*) + case $cc_basename in + *) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + esac + ;; + + cygwin* | mingw* | pw32* | cegcc*) + # _LT_TAGVAR(hardcode_libdir_flag_spec, CXX) is actually meaningless, + # as there is no search path for DLLs. + hardcode_libdir_flag_spec_CXX='-L$libdir' + export_dynamic_flag_spec_CXX='${wl}--export-all-symbols' + allow_undefined_flag_CXX=unsupported + always_export_symbols_CXX=no + enable_shared_with_static_runtimes_CXX=yes + + if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then + archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file (1st line + # is EXPORTS), use it as is; otherwise, prepend... + archive_expsym_cmds_CXX='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + ld_shlibs_CXX=no + fi + ;; + darwin* | rhapsody*) + + + archive_cmds_need_lc_CXX=no + hardcode_direct_CXX=no + hardcode_automatic_CXX=yes + hardcode_shlibpath_var_CXX=unsupported + if test "$lt_cv_ld_force_load" = "yes"; then + whole_archive_flag_spec_CXX='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience ${wl}-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' + else + whole_archive_flag_spec_CXX='' + fi + link_all_deplibs_CXX=yes + allow_undefined_flag_CXX="$_lt_dar_allow_undefined" + case $cc_basename in + ifort*) _lt_dar_can_shared=yes ;; + *) _lt_dar_can_shared=$GCC ;; + esac + if test "$_lt_dar_can_shared" = "yes"; then + output_verbose_link_cmd=func_echo_all + archive_cmds_CXX="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}" + module_cmds_CXX="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}" + archive_expsym_cmds_CXX="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}" + module_expsym_cmds_CXX="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}" + if test "$lt_cv_apple_cc_single_mod" != "yes"; then + archive_cmds_CXX="\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dsymutil}" + archive_expsym_cmds_CXX="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dar_export_syms}${_lt_dsymutil}" + fi + + else + ld_shlibs_CXX=no + fi + + ;; + + dgux*) + case $cc_basename in + ec++*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + ghcx*) + # Green Hills C++ Compiler + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + *) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + esac + ;; + + freebsd[12]*) + # C++ shared libraries reported to be fairly broken before + # switch to ELF + ld_shlibs_CXX=no + ;; + + freebsd-elf*) + archive_cmds_need_lc_CXX=no + ;; + + freebsd* | dragonfly*) + # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF + # conventions + ld_shlibs_CXX=yes + ;; + + gnu*) + ;; + + haiku*) + archive_cmds_CXX='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + link_all_deplibs_CXX=yes + ;; + + hpux9*) + hardcode_libdir_flag_spec_CXX='${wl}+b ${wl}$libdir' + hardcode_libdir_separator_CXX=: + export_dynamic_flag_spec_CXX='${wl}-E' + hardcode_direct_CXX=yes + hardcode_minus_L_CXX=yes # Not in the search PATH, + # but as the default + # location of the library. + + case $cc_basename in + CC*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + aCC*) + archive_cmds_CXX='$RM $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + ;; + *) + if test "$GXX" = yes; then + archive_cmds_CXX='$RM $output_objdir/$soname~$CC -shared -nostdlib -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + else + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + fi + ;; + esac + ;; + + hpux10*|hpux11*) + if test $with_gnu_ld = no; then + hardcode_libdir_flag_spec_CXX='${wl}+b ${wl}$libdir' + hardcode_libdir_separator_CXX=: + + case $host_cpu in + hppa*64*|ia64*) + ;; + *) + export_dynamic_flag_spec_CXX='${wl}-E' + ;; + esac + fi + case $host_cpu in + hppa*64*|ia64*) + hardcode_direct_CXX=no + hardcode_shlibpath_var_CXX=no + ;; + *) + hardcode_direct_CXX=yes + hardcode_direct_absolute_CXX=yes + hardcode_minus_L_CXX=yes # Not in the search PATH, + # but as the default + # location of the library. + ;; + esac + + case $cc_basename in + CC*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + aCC*) + case $host_cpu in + hppa*64*) + archive_cmds_CXX='$CC -b ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + ia64*) + archive_cmds_CXX='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + *) + archive_cmds_CXX='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + esac + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + ;; + *) + if test "$GXX" = yes; then + if test $with_gnu_ld = no; then + case $host_cpu in + hppa*64*) + archive_cmds_CXX='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + ia64*) + archive_cmds_CXX='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + *) + archive_cmds_CXX='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + esac + fi + else + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + fi + ;; + esac + ;; + + interix[3-9]*) + hardcode_direct_CXX=no + hardcode_shlibpath_var_CXX=no + hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' + export_dynamic_flag_spec_CXX='${wl}-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + archive_cmds_CXX='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + archive_expsym_cmds_CXX='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + irix5* | irix6*) + case $cc_basename in + CC*) + # SGI C++ + archive_cmds_CXX='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + + # Archives containing C++ object files must be created using + # "CC -ar", where "CC" is the IRIX C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + old_archive_cmds_CXX='$CC -ar -WR,-u -o $oldlib $oldobjs' + ;; + *) + if test "$GXX" = yes; then + if test "$with_gnu_ld" = no; then + archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` -o $lib' + fi + fi + link_all_deplibs_CXX=yes + ;; + esac + hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator_CXX=: + inherit_rpath_CXX=yes + ;; + + linux* | k*bsd*-gnu | kopensolaris*-gnu) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + archive_expsym_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib' + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + + hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' + export_dynamic_flag_spec_CXX='${wl}--export-dynamic' + + # Archives containing C++ object files must be created using + # "CC -Bstatic", where "CC" is the KAI C++ compiler. + old_archive_cmds_CXX='$CC -Bstatic -o $oldlib $oldobjs' + ;; + icpc* | ecpc* ) + # Intel C++ + with_gnu_ld=yes + # version 8.0 and above of icpc choke on multiply defined symbols + # if we add $predep_objects and $postdep_objects, however 7.1 and + # earlier do not add the objects themselves. + case `$CC -V 2>&1` in + *"Version 7."*) + archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + ;; + *) # Version 8.0 or newer + tmp_idyn= + case $host_cpu in + ia64*) tmp_idyn=' -i_dynamic';; + esac + archive_cmds_CXX='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds_CXX='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + ;; + esac + archive_cmds_need_lc_CXX=no + hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' + export_dynamic_flag_spec_CXX='${wl}--export-dynamic' + whole_archive_flag_spec_CXX='${wl}--whole-archive$convenience ${wl}--no-whole-archive' + ;; + pgCC* | pgcpp*) + # Portland Group C++ compiler + case `$CC -V` in + *pgCC\ [1-5].* | *pgcpp\ [1-5].*) + prelink_cmds_CXX='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~ + compile_command="$compile_command `find $tpldir -name \*.o | $NL2SP`"' + old_archive_cmds_CXX='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~ + $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | $NL2SP`~ + $RANLIB $oldlib' + archive_cmds_CXX='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ + $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' + archive_expsym_cmds_CXX='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ + $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' + ;; + *) # Version 6 and above use weak symbols + archive_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' + archive_expsym_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' + ;; + esac + + hardcode_libdir_flag_spec_CXX='${wl}--rpath ${wl}$libdir' + export_dynamic_flag_spec_CXX='${wl}--export-dynamic' + whole_archive_flag_spec_CXX='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + ;; + cxx*) + # Compaq C++ + archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib ${wl}-retain-symbols-file $wl$export_symbols' + + runpath_var=LD_RUN_PATH + hardcode_libdir_flag_spec_CXX='-rpath $libdir' + hardcode_libdir_separator_CXX=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed' + ;; + xl* | mpixl* | bgxl*) + # IBM XL 8.0 on PPC, with GNU ld + hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' + export_dynamic_flag_spec_CXX='${wl}--export-dynamic' + archive_cmds_CXX='$CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + if test "x$supports_anon_versioning" = xyes; then + archive_expsym_cmds_CXX='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' + fi + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C++ 5.9 + no_undefined_flag_CXX=' -zdefs' + archive_cmds_CXX='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + archive_expsym_cmds_CXX='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file ${wl}$export_symbols' + hardcode_libdir_flag_spec_CXX='-R$libdir' + whole_archive_flag_spec_CXX='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + compiler_needs_object_CXX=yes + + # Not sure whether something based on + # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 + # would be better. + output_verbose_link_cmd='func_echo_all' + + # Archives containing C++ object files must be created using + # "CC -xar", where "CC" is the Sun C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + old_archive_cmds_CXX='$CC -xar -o $oldlib $oldobjs' + ;; + esac + ;; + esac + ;; + + lynxos*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + + m88k*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + + mvs*) + case $cc_basename in + cxx*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + *) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + esac + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + archive_cmds_CXX='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' + wlarc= + hardcode_libdir_flag_spec_CXX='-R$libdir' + hardcode_direct_CXX=yes + hardcode_shlibpath_var_CXX=no + fi + # Workaround some broken pre-1.5 toolchains + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' + ;; + + *nto* | *qnx*) + ld_shlibs_CXX=yes + ;; + + openbsd2*) + # C++ shared libraries are fairly broken + ld_shlibs_CXX=no + ;; + + openbsd*) + if test -f /usr/libexec/ld.so; then + hardcode_direct_CXX=yes + hardcode_shlibpath_var_CXX=no + hardcode_direct_absolute_CXX=yes + archive_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' + hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + archive_expsym_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib' + export_dynamic_flag_spec_CXX='${wl}-E' + whole_archive_flag_spec_CXX="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + fi + output_verbose_link_cmd=func_echo_all + else + ld_shlibs_CXX=no + fi + ;; + + osf3* | osf4* | osf5*) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + + hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' + hardcode_libdir_separator_CXX=: + + # Archives containing C++ object files must be created using + # the KAI C++ compiler. + case $host in + osf3*) old_archive_cmds_CXX='$CC -Bstatic -o $oldlib $oldobjs' ;; + *) old_archive_cmds_CXX='$CC -o $oldlib $oldobjs' ;; + esac + ;; + RCC*) + # Rational C++ 2.4.1 + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + cxx*) + case $host in + osf3*) + allow_undefined_flag_CXX=' ${wl}-expect_unresolved ${wl}\*' + archive_cmds_CXX='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && func_echo_all "${wl}-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' + ;; + *) + allow_undefined_flag_CXX=' -expect_unresolved \*' + archive_cmds_CXX='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + archive_expsym_cmds_CXX='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ + echo "-hidden">> $lib.exp~ + $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname ${wl}-input ${wl}$lib.exp `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~ + $RM $lib.exp' + hardcode_libdir_flag_spec_CXX='-rpath $libdir' + ;; + esac + + hardcode_libdir_separator_CXX=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + ;; + *) + if test "$GXX" = yes && test "$with_gnu_ld" = no; then + allow_undefined_flag_CXX=' ${wl}-expect_unresolved ${wl}\*' + case $host in + osf3*) + archive_cmds_CXX='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + ;; + *) + archive_cmds_CXX='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + ;; + esac + + hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator_CXX=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + + else + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + fi + ;; + esac + ;; + + psos*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + + sunos4*) + case $cc_basename in + CC*) + # Sun C++ 4.x + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + lcc*) + # Lucid + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + *) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + esac + ;; + + solaris*) + case $cc_basename in + CC*) + # Sun C++ 4.2, 5.x and Centerline C++ + archive_cmds_need_lc_CXX=yes + no_undefined_flag_CXX=' -zdefs' + archive_cmds_CXX='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + archive_expsym_cmds_CXX='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G${allow_undefined_flag} ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + + hardcode_libdir_flag_spec_CXX='-R$libdir' + hardcode_shlibpath_var_CXX=no + case $host_os in + solaris2.[0-5] | solaris2.[0-5].*) ;; + *) + # The compiler driver will combine and reorder linker options, + # but understands `-z linker_flag'. + # Supported since Solaris 2.6 (maybe 2.5.1?) + whole_archive_flag_spec_CXX='-z allextract$convenience -z defaultextract' + ;; + esac + link_all_deplibs_CXX=yes + + output_verbose_link_cmd='func_echo_all' + + # Archives containing C++ object files must be created using + # "CC -xar", where "CC" is the Sun C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + old_archive_cmds_CXX='$CC -xar -o $oldlib $oldobjs' + ;; + gcx*) + # Green Hills C++ Compiler + archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + + # The C++ compiler must be used to create the archive. + old_archive_cmds_CXX='$CC $LDFLAGS -archive -o $oldlib $oldobjs' + ;; + *) + # GNU C++ compiler with Solaris linker + if test "$GXX" = yes && test "$with_gnu_ld" = no; then + no_undefined_flag_CXX=' ${wl}-z ${wl}defs' + if $CC --version | $GREP -v '^2\.7' > /dev/null; then + archive_cmds_CXX='$CC -shared -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + archive_expsym_cmds_CXX='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -shared -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + else + # g++ 2.7 appears to require `-G' NOT `-shared' on this + # platform. + archive_cmds_CXX='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + archive_expsym_cmds_CXX='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + fi + + hardcode_libdir_flag_spec_CXX='${wl}-R $wl$libdir' + case $host_os in + solaris2.[0-5] | solaris2.[0-5].*) ;; + *) + whole_archive_flag_spec_CXX='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' + ;; + esac + fi + ;; + esac + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) + no_undefined_flag_CXX='${wl}-z,text' + archive_cmds_need_lc_CXX=no + hardcode_shlibpath_var_CXX=no + runpath_var='LD_RUN_PATH' + + case $cc_basename in + CC*) + archive_cmds_CXX='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_CXX='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + archive_cmds_CXX='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_CXX='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # Note: We can NOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + no_undefined_flag_CXX='${wl}-z,text' + allow_undefined_flag_CXX='${wl}-z,nodefs' + archive_cmds_need_lc_CXX=no + hardcode_shlibpath_var_CXX=no + hardcode_libdir_flag_spec_CXX='${wl}-R,$libdir' + hardcode_libdir_separator_CXX=':' + link_all_deplibs_CXX=yes + export_dynamic_flag_spec_CXX='${wl}-Bexport' + runpath_var='LD_RUN_PATH' + + case $cc_basename in + CC*) + archive_cmds_CXX='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_CXX='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + old_archive_cmds_CXX='$CC -Tprelink_objects $oldobjs~ + '"$old_archive_cmds_CXX" + reload_cmds_CXX='$CC -Tprelink_objects $reload_objs~ + '"$reload_cmds_CXX" + ;; + *) + archive_cmds_CXX='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_CXX='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + + tandem*) + case $cc_basename in + NCC*) + # NonStop-UX NCC 3.20 + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + *) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + esac + ;; + + vxworks*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + + *) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + esac + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs_CXX" >&5 +$as_echo "$ld_shlibs_CXX" >&6; } + test "$ld_shlibs_CXX" = no && can_build_shared=no + + GCC_CXX="$GXX" + LD_CXX="$LD" + + ## CAVEAT EMPTOR: + ## There is no encapsulation within the following macros, do not change + ## the running order or otherwise move them around unless you know exactly + ## what you are doing... + # Dependencies to place before and after the object being linked: +predep_objects_CXX= +postdep_objects_CXX= +predeps_CXX= +postdeps_CXX= +compiler_lib_search_path_CXX= + +cat > conftest.$ac_ext <<_LT_EOF +class Foo +{ +public: + Foo (void) { a = 0; } +private: + int a; +}; +_LT_EOF + +if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + # Parse the compiler output and extract the necessary + # objects, libraries and library flags. + + # Sentinel used to keep track of whether or not we are before + # the conftest object file. + pre_test_object_deps_done=no + + for p in `eval "$output_verbose_link_cmd"`; do + case $p in + + -L* | -R* | -l*) + # Some compilers place space between "-{L,R}" and the path. + # Remove the space. + if test $p = "-L" || + test $p = "-R"; then + prev=$p + continue + else + prev= + fi + + if test "$pre_test_object_deps_done" = no; then + case $p in + -L* | -R*) + # Internal compiler library paths should come after those + # provided the user. The postdeps already come after the + # user supplied libs so there is no need to process them. + if test -z "$compiler_lib_search_path_CXX"; then + compiler_lib_search_path_CXX="${prev}${p}" + else + compiler_lib_search_path_CXX="${compiler_lib_search_path_CXX} ${prev}${p}" + fi + ;; + # The "-l" case would never come before the object being + # linked, so don't bother handling this case. + esac + else + if test -z "$postdeps_CXX"; then + postdeps_CXX="${prev}${p}" + else + postdeps_CXX="${postdeps_CXX} ${prev}${p}" + fi + fi + ;; + + *.$objext) + # This assumes that the test object file only shows up + # once in the compiler output. + if test "$p" = "conftest.$objext"; then + pre_test_object_deps_done=yes + continue + fi + + if test "$pre_test_object_deps_done" = no; then + if test -z "$predep_objects_CXX"; then + predep_objects_CXX="$p" + else + predep_objects_CXX="$predep_objects_CXX $p" + fi + else + if test -z "$postdep_objects_CXX"; then + postdep_objects_CXX="$p" + else + postdep_objects_CXX="$postdep_objects_CXX $p" + fi + fi + ;; + + *) ;; # Ignore the rest. + + esac + done + + # Clean up. + rm -f a.out a.exe +else + echo "libtool.m4: error: problem compiling CXX test program" +fi + +$RM -f confest.$objext + +# PORTME: override above test on systems where it is broken +case $host_os in +interix[3-9]*) + # Interix 3.5 installs completely hosed .la files for C++, so rather than + # hack all around it, let's just trust "g++" to DTRT. + predep_objects_CXX= + postdep_objects_CXX= + postdeps_CXX= + ;; + +linux*) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C++ 5.9 + + # The more standards-conforming stlport4 library is + # incompatible with the Cstd library. Avoid specifying + # it if it's in CXXFLAGS. Ignore libCrun as + # -library=stlport4 depends on it. + case " $CXX $CXXFLAGS " in + *" -library=stlport4 "*) + solaris_use_stlport4=yes + ;; + esac + + if test "$solaris_use_stlport4" != yes; then + postdeps_CXX='-library=Cstd -library=Crun' + fi + ;; + esac + ;; + +solaris*) + case $cc_basename in + CC*) + # The more standards-conforming stlport4 library is + # incompatible with the Cstd library. Avoid specifying + # it if it's in CXXFLAGS. Ignore libCrun as + # -library=stlport4 depends on it. + case " $CXX $CXXFLAGS " in + *" -library=stlport4 "*) + solaris_use_stlport4=yes + ;; + esac + + # Adding this requires a known-good setup of shared libraries for + # Sun compiler versions before 5.6, else PIC objects from an old + # archive will be linked into the output, leading to subtle bugs. + if test "$solaris_use_stlport4" != yes; then + postdeps_CXX='-library=Cstd -library=Crun' + fi + ;; + esac + ;; +esac + + +case " $postdeps_CXX " in +*" -lc "*) archive_cmds_need_lc_CXX=no ;; +esac + compiler_lib_search_dirs_CXX= +if test -n "${compiler_lib_search_path_CXX}"; then + compiler_lib_search_dirs_CXX=`echo " ${compiler_lib_search_path_CXX}" | ${SED} -e 's! -L! !g' -e 's!^ !!'` +fi + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + lt_prog_compiler_wl_CXX= +lt_prog_compiler_pic_CXX= +lt_prog_compiler_static_CXX= + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5 +$as_echo_n "checking for $compiler option to produce PIC... " >&6; } + + # C++ specific cases for pic, static, wl, etc. + if test "$GXX" = yes; then + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_static_CXX='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static_CXX='-Bstatic' + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + lt_prog_compiler_pic_CXX='-fPIC' + ;; + m68k) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. + lt_prog_compiler_pic_CXX='-m68020 -resident32 -malways-restore-a4' + ;; + esac + ;; + + beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + mingw* | cygwin* | os2* | pw32* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + # Although the cygwin gcc ignores -fPIC, still need this for old-style + # (--disable-auto-import) libraries + lt_prog_compiler_pic_CXX='-DDLL_EXPORT' + ;; + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + lt_prog_compiler_pic_CXX='-fno-common' + ;; + *djgpp*) + # DJGPP does not support shared libraries at all + lt_prog_compiler_pic_CXX= + ;; + haiku*) + # PIC is the default for Haiku. + # The "-static" flag exists, but is broken. + lt_prog_compiler_static_CXX= + ;; + interix[3-9]*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + sysv4*MP*) + if test -d /usr/nec; then + lt_prog_compiler_pic_CXX=-Kconform_pic + fi + ;; + hpux*) + # PIC is the default for 64-bit PA HP-UX, but not for 32-bit + # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag + # sets the default TLS model and affects inlining. + case $host_cpu in + hppa*64*) + ;; + *) + lt_prog_compiler_pic_CXX='-fPIC' + ;; + esac + ;; + *qnx* | *nto*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + lt_prog_compiler_pic_CXX='-fPIC -shared' + ;; + *) + lt_prog_compiler_pic_CXX='-fPIC' + ;; + esac + else + case $host_os in + aix[4-9]*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static_CXX='-Bstatic' + else + lt_prog_compiler_static_CXX='-bnso -bI:/lib/syscalls.exp' + fi + ;; + chorus*) + case $cc_basename in + cxch68*) + # Green Hills C++ Compiler + # _LT_TAGVAR(lt_prog_compiler_static, CXX)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" + ;; + esac + ;; + dgux*) + case $cc_basename in + ec++*) + lt_prog_compiler_pic_CXX='-KPIC' + ;; + ghcx*) + # Green Hills C++ Compiler + lt_prog_compiler_pic_CXX='-pic' + ;; + *) + ;; + esac + ;; + freebsd* | dragonfly*) + # FreeBSD uses GNU C++ + ;; + hpux9* | hpux10* | hpux11*) + case $cc_basename in + CC*) + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_static_CXX='${wl}-a ${wl}archive' + if test "$host_cpu" != ia64; then + lt_prog_compiler_pic_CXX='+Z' + fi + ;; + aCC*) + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_static_CXX='${wl}-a ${wl}archive' + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + lt_prog_compiler_pic_CXX='+Z' + ;; + esac + ;; + *) + ;; + esac + ;; + interix*) + # This is c89, which is MS Visual C++ (no shared libs) + # Anyone wants to do a port? + ;; + irix5* | irix6* | nonstopux*) + case $cc_basename in + CC*) + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_static_CXX='-non_shared' + # CC pic flag -KPIC is the default. + ;; + *) + ;; + esac + ;; + linux* | k*bsd*-gnu | kopensolaris*-gnu) + case $cc_basename in + KCC*) + # KAI C++ Compiler + lt_prog_compiler_wl_CXX='--backend -Wl,' + lt_prog_compiler_pic_CXX='-fPIC' + ;; + ecpc* ) + # old Intel C++ for x86_64 which still supported -KPIC. + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_pic_CXX='-KPIC' + lt_prog_compiler_static_CXX='-static' + ;; + icpc* ) + # Intel C++, used to be incompatible with GCC. + # ICC 10 doesn't accept -KPIC any more. + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_pic_CXX='-fPIC' + lt_prog_compiler_static_CXX='-static' + ;; + pgCC* | pgcpp*) + # Portland Group C++ compiler + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_pic_CXX='-fpic' + lt_prog_compiler_static_CXX='-Bstatic' + ;; + cxx*) + # Compaq C++ + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + lt_prog_compiler_pic_CXX= + lt_prog_compiler_static_CXX='-non_shared' + ;; + xlc* | xlC* | bgxl[cC]* | mpixl[cC]*) + # IBM XL 8.0, 9.0 on PPC and BlueGene + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_pic_CXX='-qpic' + lt_prog_compiler_static_CXX='-qstaticlink' + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C++ 5.9 + lt_prog_compiler_pic_CXX='-KPIC' + lt_prog_compiler_static_CXX='-Bstatic' + lt_prog_compiler_wl_CXX='-Qoption ld ' + ;; + esac + ;; + esac + ;; + lynxos*) + ;; + m88k*) + ;; + mvs*) + case $cc_basename in + cxx*) + lt_prog_compiler_pic_CXX='-W c,exportall' + ;; + *) + ;; + esac + ;; + netbsd*) + ;; + *qnx* | *nto*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + lt_prog_compiler_pic_CXX='-fPIC -shared' + ;; + osf3* | osf4* | osf5*) + case $cc_basename in + KCC*) + lt_prog_compiler_wl_CXX='--backend -Wl,' + ;; + RCC*) + # Rational C++ 2.4.1 + lt_prog_compiler_pic_CXX='-pic' + ;; + cxx*) + # Digital/Compaq C++ + lt_prog_compiler_wl_CXX='-Wl,' + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + lt_prog_compiler_pic_CXX= + lt_prog_compiler_static_CXX='-non_shared' + ;; + *) + ;; + esac + ;; + psos*) + ;; + solaris*) + case $cc_basename in + CC*) + # Sun C++ 4.2, 5.x and Centerline C++ + lt_prog_compiler_pic_CXX='-KPIC' + lt_prog_compiler_static_CXX='-Bstatic' + lt_prog_compiler_wl_CXX='-Qoption ld ' + ;; + gcx*) + # Green Hills C++ Compiler + lt_prog_compiler_pic_CXX='-PIC' + ;; + *) + ;; + esac + ;; + sunos4*) + case $cc_basename in + CC*) + # Sun C++ 4.x + lt_prog_compiler_pic_CXX='-pic' + lt_prog_compiler_static_CXX='-Bstatic' + ;; + lcc*) + # Lucid + lt_prog_compiler_pic_CXX='-pic' + ;; + *) + ;; + esac + ;; + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + case $cc_basename in + CC*) + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_pic_CXX='-KPIC' + lt_prog_compiler_static_CXX='-Bstatic' + ;; + esac + ;; + tandem*) + case $cc_basename in + NCC*) + # NonStop-UX NCC 3.20 + lt_prog_compiler_pic_CXX='-KPIC' + ;; + *) + ;; + esac + ;; + vxworks*) + ;; + *) + lt_prog_compiler_can_build_shared_CXX=no + ;; + esac + fi + +case $host_os in + # For platforms which do not support PIC, -DPIC is meaningless: + *djgpp*) + lt_prog_compiler_pic_CXX= + ;; + *) + lt_prog_compiler_pic_CXX="$lt_prog_compiler_pic_CXX -DPIC" + ;; +esac +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_prog_compiler_pic_CXX" >&5 +$as_echo "$lt_prog_compiler_pic_CXX" >&6; } + + + +# +# Check to make sure the PIC flag actually works. +# +if test -n "$lt_prog_compiler_pic_CXX"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works" >&5 +$as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works... " >&6; } +if test "${lt_cv_prog_compiler_pic_works_CXX+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_pic_works_CXX=no + ac_outfile=conftest.$ac_objext + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="$lt_prog_compiler_pic_CXX -DPIC" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler_pic_works_CXX=yes + fi + fi + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works_CXX" >&5 +$as_echo "$lt_cv_prog_compiler_pic_works_CXX" >&6; } + +if test x"$lt_cv_prog_compiler_pic_works_CXX" = xyes; then + case $lt_prog_compiler_pic_CXX in + "" | " "*) ;; + *) lt_prog_compiler_pic_CXX=" $lt_prog_compiler_pic_CXX" ;; + esac +else + lt_prog_compiler_pic_CXX= + lt_prog_compiler_can_build_shared_CXX=no +fi + +fi + + + +# +# Check to make sure the static flag actually works. +# +wl=$lt_prog_compiler_wl_CXX eval lt_tmp_static_flag=\"$lt_prog_compiler_static_CXX\" +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5 +$as_echo_n "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; } +if test "${lt_cv_prog_compiler_static_works_CXX+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_static_works_CXX=no + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS $lt_tmp_static_flag" + echo "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&5 + $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler_static_works_CXX=yes + fi + else + lt_cv_prog_compiler_static_works_CXX=yes + fi + fi + $RM -r conftest* + LDFLAGS="$save_LDFLAGS" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works_CXX" >&5 +$as_echo "$lt_cv_prog_compiler_static_works_CXX" >&6; } + +if test x"$lt_cv_prog_compiler_static_works_CXX" = xyes; then + : +else + lt_prog_compiler_static_CXX= +fi + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 +$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } +if test "${lt_cv_prog_compiler_c_o_CXX+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_c_o_CXX=no + $RM -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + lt_cv_prog_compiler_c_o_CXX=yes + fi + fi + chmod u+w . 2>&5 + $RM conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files + $RM out/* && rmdir out + cd .. + $RM -r conftest + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o_CXX" >&5 +$as_echo "$lt_cv_prog_compiler_c_o_CXX" >&6; } + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 +$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } +if test "${lt_cv_prog_compiler_c_o_CXX+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_c_o_CXX=no + $RM -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + lt_cv_prog_compiler_c_o_CXX=yes + fi + fi + chmod u+w . 2>&5 + $RM conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files + $RM out/* && rmdir out + cd .. + $RM -r conftest + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o_CXX" >&5 +$as_echo "$lt_cv_prog_compiler_c_o_CXX" >&6; } + + + + +hard_links="nottested" +if test "$lt_cv_prog_compiler_c_o_CXX" = no && test "$need_locks" != no; then + # do not overwrite the value of need_locks provided by the user + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5 +$as_echo_n "checking if we can lock with hard links... " >&6; } + hard_links=yes + $RM conftest* + ln conftest.a conftest.b 2>/dev/null && hard_links=no + touch conftest.a + ln conftest.a conftest.b 2>&5 || hard_links=no + ln conftest.a conftest.b 2>/dev/null && hard_links=no + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5 +$as_echo "$hard_links" >&6; } + if test "$hard_links" = no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5 +$as_echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;} + need_locks=warn + fi +else + need_locks=no +fi + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5 +$as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } + + export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + case $host_os in + aix[4-9]*) + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to AIX nm, but means don't demangle with GNU nm + # Also, AIX nm treats weak defined symbols like other global defined + # symbols, whereas GNU nm marks them as "W". + if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then + export_symbols_cmds_CXX='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' + else + export_symbols_cmds_CXX='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' + fi + ;; + pw32*) + export_symbols_cmds_CXX="$ltdll_cmds" + ;; + cygwin* | mingw* | cegcc*) + export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/;/^.*[ ]__nm__/s/^.*[ ]__nm__\([^ ]*\)[ ][^ ]*/\1 DATA/;/^I[ ]/d;/^[AITW][ ]/s/.* //'\'' | sort | uniq > $export_symbols' + ;; + *) + export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + ;; + esac + exclude_expsyms_CXX='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*' + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs_CXX" >&5 +$as_echo "$ld_shlibs_CXX" >&6; } +test "$ld_shlibs_CXX" = no && can_build_shared=no + +with_gnu_ld_CXX=$with_gnu_ld + + + + + + +# +# Do we need to explicitly link libc? +# +case "x$archive_cmds_need_lc_CXX" in +x|xyes) + # Assume -lc should be added + archive_cmds_need_lc_CXX=yes + + if test "$enable_shared" = yes && test "$GCC" = yes; then + case $archive_cmds_CXX in + *'~'*) + # FIXME: we may have to deal with multi-command sequences. + ;; + '$CC '*) + # Test whether the compiler implicitly links with -lc since on some + # systems, -lgcc has to come before -lc. If gcc already passes -lc + # to ld, don't add -lc before -lgcc. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5 +$as_echo_n "checking whether -lc should be explicitly linked in... " >&6; } +if test "${lt_cv_archive_cmds_need_lc_CXX+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + $RM conftest* + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } 2>conftest.err; then + soname=conftest + lib=conftest + libobjs=conftest.$ac_objext + deplibs= + wl=$lt_prog_compiler_wl_CXX + pic_flag=$lt_prog_compiler_pic_CXX + compiler_flags=-v + linker_flags=-v + verstring= + output_objdir=. + libname=conftest + lt_save_allow_undefined_flag=$allow_undefined_flag_CXX + allow_undefined_flag_CXX= + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds_CXX 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5 + (eval $archive_cmds_CXX 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + then + lt_cv_archive_cmds_need_lc_CXX=no + else + lt_cv_archive_cmds_need_lc_CXX=yes + fi + allow_undefined_flag_CXX=$lt_save_allow_undefined_flag + else + cat conftest.err 1>&5 + fi + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_archive_cmds_need_lc_CXX" >&5 +$as_echo "$lt_cv_archive_cmds_need_lc_CXX" >&6; } + archive_cmds_need_lc_CXX=$lt_cv_archive_cmds_need_lc_CXX + ;; + esac + fi + ;; +esac + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5 +$as_echo_n "checking dynamic linker characteristics... " >&6; } + +library_names_spec= +libname_spec='lib$name' +soname_spec= +shrext_cmds=".so" +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +shlibpath_overrides_runpath=unknown +version_type=none +dynamic_linker="$host_os ld.so" +sys_lib_dlsearch_path_spec="/lib /usr/lib" +need_lib_prefix=unknown +hardcode_into_libs=no + +# when you set need_version to no, make sure it does not cause -set_version +# flags to be left without arguments +need_version=unknown + +case $host_os in +aix3*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX 3 has no versioning support, so we append a major version to the name. + soname_spec='${libname}${release}${shared_ext}$major' + ;; + +aix[4-9]*) + version_type=linux + need_lib_prefix=no + need_version=no + hardcode_into_libs=yes + if test "$host_cpu" = ia64; then + # AIX 5 supports IA64 + library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + else + # With GCC up to 2.95.x, collect2 would create an import file + # for dependence libraries. The import file would start with + # the line `#! .'. This would cause the generated library to + # depend on `.', always an invalid library. This was fixed in + # development snapshots of GCC prior to 3.0. + case $host_os in + aix4 | aix4.[01] | aix4.[01].*) + if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' + echo ' yes ' + echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then + : + else + can_build_shared=no + fi + ;; + esac + # AIX (on Power*) has no versioning support, so currently we can not hardcode correct + # soname into executable. Probably we can add versioning support to + # collect2, so additional links can be useful in future. + if test "$aix_use_runtimelinking" = yes; then + # If using run time linking (on AIX 4.2 or later) use lib<name>.so + # instead of lib<name>.a to let people know that these are not + # typical AIX shared libraries. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + else + # We preserve .a as extension for shared libraries through AIX4.2 + # and later when we are not doing run time linking. + library_names_spec='${libname}${release}.a $libname.a' + soname_spec='${libname}${release}${shared_ext}$major' + fi + shlibpath_var=LIBPATH + fi + ;; + +amigaos*) + case $host_cpu in + powerpc) + # Since July 2007 AmigaOS4 officially supports .so libraries. + # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + ;; + m68k) + library_names_spec='$libname.ixlibrary $libname.a' + # Create ${libname}_ixlibrary.a entries in /sys/libs. + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' + ;; + esac + ;; + +beos*) + library_names_spec='${libname}${shared_ext}' + dynamic_linker="$host_os ld.so" + shlibpath_var=LIBRARY_PATH + ;; + +bsdi[45]*) + version_type=linux + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" + sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" + # the default ld.so.conf also contains /usr/contrib/lib and + # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow + # libtool to hard-code these into programs + ;; + +cygwin* | mingw* | pw32* | cegcc*) + version_type=windows + shrext_cmds=".dll" + need_version=no + need_lib_prefix=no + + case $GCC,$host_os in + yes,cygwin* | yes,mingw* | yes,pw32* | yes,cegcc*) + library_names_spec='$libname.dll.a' + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \${file}`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname~ + if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then + eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; + fi' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + + case $host_os in + cygwin*) + # Cygwin DLLs use 'cyg' prefix rather than 'lib' + soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + + ;; + mingw* | cegcc*) + # MinGW DLLs use traditional 'lib' prefix + soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + ;; + pw32*) + # pw32 DLLs use 'pw' prefix rather than 'lib' + library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + ;; + esac + ;; + + *) + library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib' + ;; + esac + dynamic_linker='Win32 ld.exe' + # FIXME: first we should search . and the directory the executable is in + shlibpath_var=PATH + ;; + +darwin* | rhapsody*) + dynamic_linker="$host_os dyld" + version_type=darwin + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext' + soname_spec='${libname}${release}${major}$shared_ext' + shlibpath_overrides_runpath=yes + shlibpath_var=DYLD_LIBRARY_PATH + shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' + + sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' + ;; + +dgux*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +freebsd* | dragonfly*) + # DragonFly does not have aout. When/if they implement a new + # versioning mechanism, adjust this. + if test -x /usr/bin/objformat; then + objformat=`/usr/bin/objformat` + else + case $host_os in + freebsd[123]*) objformat=aout ;; + *) objformat=elf ;; + esac + fi + version_type=freebsd-$objformat + case $version_type in + freebsd-elf*) + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + need_version=no + need_lib_prefix=no + ;; + freebsd-*) + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' + need_version=yes + ;; + esac + shlibpath_var=LD_LIBRARY_PATH + case $host_os in + freebsd2*) + shlibpath_overrides_runpath=yes + ;; + freebsd3.[01]* | freebsdelf3.[01]*) + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ + freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + *) # from 4.6 on, and DragonFly + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + esac + ;; + +gnu*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + hardcode_into_libs=yes + ;; + +haiku*) + version_type=linux + need_lib_prefix=no + need_version=no + dynamic_linker="$host_os runtime_loader" + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LIBRARY_PATH + shlibpath_overrides_runpath=yes + sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/beos/system/lib' + hardcode_into_libs=yes + ;; + +hpux9* | hpux10* | hpux11*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + version_type=sunos + need_lib_prefix=no + need_version=no + case $host_cpu in + ia64*) + shrext_cmds='.so' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.so" + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + if test "X$HPUX_IA64_MODE" = X32; then + sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" + else + sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" + fi + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + hppa*64*) + shrext_cmds='.sl' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.sl" + shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + *) + shrext_cmds='.sl' + dynamic_linker="$host_os dld.sl" + shlibpath_var=SHLIB_PATH + shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + ;; + esac + # HP-UX runs *really* slowly unless shared libraries are mode 555, ... + postinstall_cmds='chmod 555 $lib' + # or fails outright, so override atomically: + install_override_mode=555 + ;; + +interix[3-9]*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +irix5* | irix6* | nonstopux*) + case $host_os in + nonstopux*) version_type=nonstopux ;; + *) + if test "$lt_cv_prog_gnu_ld" = yes; then + version_type=linux + else + version_type=irix + fi ;; + esac + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' + case $host_os in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in # libtool.m4 will add one of these switches to LD + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") + libsuff= shlibsuff= libmagic=32-bit;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") + libsuff=32 shlibsuff=N32 libmagic=N32;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") + libsuff=64 shlibsuff=64 libmagic=64-bit;; + *) libsuff= shlibsuff= libmagic=never-match;; + esac + ;; + esac + shlibpath_var=LD_LIBRARY${shlibsuff}_PATH + shlibpath_overrides_runpath=no + sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" + sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" + hardcode_into_libs=yes + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux*oldld* | linux*aout* | linux*coff*) + dynamic_linker=no + ;; + +# This must be Linux ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + + # Some binutils ld are patched to set DT_RUNPATH + if test "${lt_cv_shlibpath_overrides_runpath+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_shlibpath_overrides_runpath=no + save_LDFLAGS=$LDFLAGS + save_libdir=$libdir + eval "libdir=/foo; wl=\"$lt_prog_compiler_wl_CXX\"; \ + LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec_CXX\"" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + if ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null; then : + lt_cv_shlibpath_overrides_runpath=yes +fi +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS=$save_LDFLAGS + libdir=$save_libdir + +fi + + shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath + + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + # Append ld.so.conf contents to the search path + if test -f /etc/ld.so.conf; then + lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` + sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" + fi + + # We used to test for /lib/ld.so.1 and disable shared libraries on + # powerpc, because MkLinux only supported shared libraries with the + # GNU dynamic linker. Since this was broken with cross compilers, + # most powerpc-linux boxes support dynamic linking these days and + # people can always --disable-shared, the test was removed, and we + # assume the GNU/Linux dynamic linker is in use. + dynamic_linker='GNU/Linux ld.so' + ;; + +netbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + dynamic_linker='NetBSD (a.out) ld.so' + else + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='NetBSD ld.elf_so' + fi + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + +newsos6) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +*nto* | *qnx*) + version_type=qnx + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='ldqnx.so' + ;; + +openbsd*) + version_type=sunos + sys_lib_dlsearch_path_spec="/usr/lib" + need_lib_prefix=no + # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. + case $host_os in + openbsd3.3 | openbsd3.3.*) need_version=yes ;; + *) need_version=no ;; + esac + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + case $host_os in + openbsd2.[89] | openbsd2.[89].*) + shlibpath_overrides_runpath=no + ;; + *) + shlibpath_overrides_runpath=yes + ;; + esac + else + shlibpath_overrides_runpath=yes + fi + ;; + +os2*) + libname_spec='$name' + shrext_cmds=".dll" + need_lib_prefix=no + library_names_spec='$libname${shared_ext} $libname.a' + dynamic_linker='OS/2 ld.exe' + shlibpath_var=LIBPATH + ;; + +osf3* | osf4* | osf5*) + version_type=osf + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" + sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" + ;; + +rdos*) + dynamic_linker=no + ;; + +solaris*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + ;; + +sunos4*) + version_type=sunos + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + if test "$with_gnu_ld" = yes; then + need_lib_prefix=no + fi + need_version=yes + ;; + +sysv4 | sysv4.3*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + case $host_vendor in + sni) + shlibpath_overrides_runpath=no + need_lib_prefix=no + runpath_var=LD_RUN_PATH + ;; + siemens) + need_lib_prefix=no + ;; + motorola) + need_lib_prefix=no + need_version=no + shlibpath_overrides_runpath=no + sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' + ;; + esac + ;; + +sysv4*MP*) + if test -d /usr/nec ;then + version_type=linux + library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' + soname_spec='$libname${shared_ext}.$major' + shlibpath_var=LD_LIBRARY_PATH + fi + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + version_type=freebsd-elf + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + if test "$with_gnu_ld" = yes; then + sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' + else + sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' + case $host_os in + sco3.2v5*) + sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" + ;; + esac + fi + sys_lib_dlsearch_path_spec='/usr/lib' + ;; + +tpf*) + # TPF is a cross-target only. Preferred cross-host = GNU/Linux. + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +uts4*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +*) + dynamic_linker=no + ;; +esac +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5 +$as_echo "$dynamic_linker" >&6; } +test "$dynamic_linker" = no && can_build_shared=no + +variables_saved_for_relink="PATH $shlibpath_var $runpath_var" +if test "$GCC" = yes; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" +fi + +if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then + sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec" +fi +if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then + sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec" +fi + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5 +$as_echo_n "checking how to hardcode library paths into programs... " >&6; } +hardcode_action_CXX= +if test -n "$hardcode_libdir_flag_spec_CXX" || + test -n "$runpath_var_CXX" || + test "X$hardcode_automatic_CXX" = "Xyes" ; then + + # We can hardcode non-existent directories. + if test "$hardcode_direct_CXX" != no && + # If the only mechanism to avoid hardcoding is shlibpath_var, we + # have to relink, otherwise we might link with an installed library + # when we should be linking with a yet-to-be-installed one + ## test "$_LT_TAGVAR(hardcode_shlibpath_var, CXX)" != no && + test "$hardcode_minus_L_CXX" != no; then + # Linking always hardcodes the temporary library directory. + hardcode_action_CXX=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + hardcode_action_CXX=immediate + fi +else + # We cannot hardcode anything, or else we can only hardcode existing + # directories. + hardcode_action_CXX=unsupported +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action_CXX" >&5 +$as_echo "$hardcode_action_CXX" >&6; } + +if test "$hardcode_action_CXX" = relink || + test "$inherit_rpath_CXX" = yes; then + # Fast installation is not supported + enable_fast_install=no +elif test "$shlibpath_overrides_runpath" = yes || + test "$enable_shared" = no; then + # Fast installation is not necessary + enable_fast_install=needless +fi + + + + + + + + fi # test -n "$compiler" + + CC=$lt_save_CC + LDCXX=$LD + LD=$lt_save_LD + GCC=$lt_save_GCC + with_gnu_ld=$lt_save_with_gnu_ld + lt_cv_path_LDCXX=$lt_cv_path_LD + lt_cv_path_LD=$lt_save_path_LD + lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld + lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld +fi # test "$_lt_caught_CXX_error" != yes + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + + + + + + + + + + + + ac_config_commands="$ac_config_commands libtool" + + + + +# Only expand once: + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable maintainer-specific portions of Makefiles" >&5 +$as_echo_n "checking whether to enable maintainer-specific portions of Makefiles... " >&6; } + # Check whether --enable-maintainer-mode was given. +if test "${enable_maintainer_mode+set}" = set; then : + enableval=$enable_maintainer_mode; USE_MAINTAINER_MODE=$enableval +else + USE_MAINTAINER_MODE=no +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $USE_MAINTAINER_MODE" >&5 +$as_echo "$USE_MAINTAINER_MODE" >&6; } + if test $USE_MAINTAINER_MODE = yes; then + MAINTAINER_MODE_TRUE= + MAINTAINER_MODE_FALSE='#' +else + MAINTAINER_MODE_TRUE='#' + MAINTAINER_MODE_FALSE= +fi + + MAINT=$MAINTAINER_MODE_TRUE + + + +# For libtool versioning info, format is CURRENT:REVISION:AGE +libtool_VERSION=1:0:0 + + +# Check header files. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 +$as_echo_n "checking for ANSI C header files... " >&6; } +if test "${ac_cv_header_stdc+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <stdlib.h> +#include <stdarg.h> +#include <string.h> +#include <float.h> + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_header_stdc=yes +else + ac_cv_header_stdc=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <string.h> + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "memchr" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <stdlib.h> + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "free" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. + if test "$cross_compiling" = yes; then : + : +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <ctype.h> +#include <stdlib.h> +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) \ + (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int +main () +{ + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + return 2; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + +else + ac_cv_header_stdc=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 +$as_echo "$ac_cv_header_stdc" >&6; } +if test $ac_cv_header_stdc = yes; then + +$as_echo "#define STDC_HEADERS 1" >>confdefs.h + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether time.h and sys/time.h may both be included" >&5 +$as_echo_n "checking whether time.h and sys/time.h may both be included... " >&6; } +if test "${ac_cv_header_time+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <sys/types.h> +#include <sys/time.h> +#include <time.h> + +int +main () +{ +if ((struct tm *) 0) +return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_header_time=yes +else + ac_cv_header_time=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_time" >&5 +$as_echo "$ac_cv_header_time" >&6; } +if test $ac_cv_header_time = yes; then + +$as_echo "#define TIME_WITH_SYS_TIME 1" >>confdefs.h + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether string.h and strings.h may both be included" >&5 +$as_echo_n "checking whether string.h and strings.h may both be included... " >&6; } +if test "${gcc_cv_header_string+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <string.h> +#include <strings.h> +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + gcc_cv_header_string=yes +else + gcc_cv_header_string=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_header_string" >&5 +$as_echo "$gcc_cv_header_string" >&6; } +if test $gcc_cv_header_string = yes; then + +$as_echo "#define STRING_WITH_STRINGS 1" >>confdefs.h + +fi + +for ac_header in unistd.h semaphore.h sys/time.h malloc.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" +eval as_val=\$$as_ac_Header + if test "x$as_val" = x""yes; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + + + +inttype_headers=`echo inttypes.h sys/inttypes.h | sed -e 's/,/ /g'` + +acx_cv_header_stdint=stddef.h +acx_cv_header_stdint_kind="(already complete)" +for i in stdint.h $inttype_headers; do + unset ac_cv_type_uintptr_t + unset ac_cv_type_uintmax_t + unset ac_cv_type_int_least32_t + unset ac_cv_type_int_fast32_t + unset ac_cv_type_uint64_t + $as_echo_n "looking for a compliant stdint.h in $i, " >&6 + ac_fn_c_check_type "$LINENO" "uintmax_t" "ac_cv_type_uintmax_t" "#include <sys/types.h> +#include <$i> +" +if test "x$ac_cv_type_uintmax_t" = x""yes; then : + acx_cv_header_stdint=$i +else + continue +fi + + ac_fn_c_check_type "$LINENO" "uintptr_t" "ac_cv_type_uintptr_t" "#include <sys/types.h> +#include <$i> +" +if test "x$ac_cv_type_uintptr_t" = x""yes; then : + +else + acx_cv_header_stdint_kind="(mostly complete)" +fi + + ac_fn_c_check_type "$LINENO" "int_least32_t" "ac_cv_type_int_least32_t" "#include <sys/types.h> +#include <$i> +" +if test "x$ac_cv_type_int_least32_t" = x""yes; then : + +else + acx_cv_header_stdint_kind="(mostly complete)" +fi + + ac_fn_c_check_type "$LINENO" "int_fast32_t" "ac_cv_type_int_fast32_t" "#include <sys/types.h> +#include <$i> +" +if test "x$ac_cv_type_int_fast32_t" = x""yes; then : + +else + acx_cv_header_stdint_kind="(mostly complete)" +fi + + ac_fn_c_check_type "$LINENO" "uint64_t" "ac_cv_type_uint64_t" "#include <sys/types.h> +#include <$i> +" +if test "x$ac_cv_type_uint64_t" = x""yes; then : + +else + acx_cv_header_stdint_kind="(lacks uint64_t)" +fi + + break +done +if test "$acx_cv_header_stdint" = stddef.h; then + acx_cv_header_stdint_kind="(lacks uintmax_t)" + for i in stdint.h $inttype_headers; do + unset ac_cv_type_uintptr_t + unset ac_cv_type_uint32_t + unset ac_cv_type_uint64_t + $as_echo_n "looking for an incomplete stdint.h in $i, " >&6 + ac_fn_c_check_type "$LINENO" "uint32_t" "ac_cv_type_uint32_t" "#include <sys/types.h> +#include <$i> +" +if test "x$ac_cv_type_uint32_t" = x""yes; then : + acx_cv_header_stdint=$i +else + continue +fi + + ac_fn_c_check_type "$LINENO" "uint64_t" "ac_cv_type_uint64_t" "#include <sys/types.h> +#include <$i> +" +if test "x$ac_cv_type_uint64_t" = x""yes; then : + +fi + + ac_fn_c_check_type "$LINENO" "uintptr_t" "ac_cv_type_uintptr_t" "#include <sys/types.h> +#include <$i> +" +if test "x$ac_cv_type_uintptr_t" = x""yes; then : + +fi + + break + done +fi +if test "$acx_cv_header_stdint" = stddef.h; then + acx_cv_header_stdint_kind="(u_intXX_t style)" + for i in sys/types.h $inttype_headers; do + unset ac_cv_type_u_int32_t + unset ac_cv_type_u_int64_t + $as_echo_n "looking for u_intXX_t types in $i, " >&6 + ac_fn_c_check_type "$LINENO" "u_int32_t" "ac_cv_type_u_int32_t" "#include <sys/types.h> +#include <$i> +" +if test "x$ac_cv_type_u_int32_t" = x""yes; then : + acx_cv_header_stdint=$i +else + continue +fi + + ac_fn_c_check_type "$LINENO" "u_int64_t" "ac_cv_type_u_int64_t" "#include <sys/types.h> +#include <$i> +" +if test "x$ac_cv_type_u_int64_t" = x""yes; then : + +fi + + break + done +fi +if test "$acx_cv_header_stdint" = stddef.h; then + acx_cv_header_stdint_kind="(using manual detection)" +fi + +test -z "$ac_cv_type_uintptr_t" && ac_cv_type_uintptr_t=no +test -z "$ac_cv_type_uint64_t" && ac_cv_type_uint64_t=no +test -z "$ac_cv_type_u_int64_t" && ac_cv_type_u_int64_t=no +test -z "$ac_cv_type_int_least32_t" && ac_cv_type_int_least32_t=no +test -z "$ac_cv_type_int_fast32_t" && ac_cv_type_int_fast32_t=no + +# ----------------- Summarize what we found so far + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking what to include in gstdint.h" >&5 +$as_echo_n "checking what to include in gstdint.h... " >&6; } + +case `$as_basename -- gstdint.h || +$as_expr X/gstdint.h : '.*/\([^/][^/]*\)/*$' \| \ + Xgstdint.h : 'X\(//\)$' \| \ + Xgstdint.h : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/gstdint.h | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` in + stdint.h) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: are you sure you want it there?" >&5 +$as_echo "$as_me: WARNING: are you sure you want it there?" >&2;} ;; + inttypes.h) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: are you sure you want it there?" >&5 +$as_echo "$as_me: WARNING: are you sure you want it there?" >&2;} ;; + *) ;; +esac + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $acx_cv_header_stdint $acx_cv_header_stdint_kind" >&5 +$as_echo "$acx_cv_header_stdint $acx_cv_header_stdint_kind" >&6; } + +# ----------------- done included file, check C basic types -------- + +# Lacking an uintptr_t? Test size of void * +case "$acx_cv_header_stdint:$ac_cv_type_uintptr_t" in + stddef.h:* | *:no) # The cast to long int works around a bug in the HP C Compiler +# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects +# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. +# This bug is HP SR number 8606223364. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of void *" >&5 +$as_echo_n "checking size of void *... " >&6; } +if test "${ac_cv_sizeof_void_p+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (void *))" "ac_cv_sizeof_void_p" "$ac_includes_default"; then : + +else + if test "$ac_cv_type_void_p" = yes; then + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +{ as_fn_set_status 77 +as_fn_error "cannot compute sizeof (void *) +See \`config.log' for more details." "$LINENO" 5; }; } + else + ac_cv_sizeof_void_p=0 + fi +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_void_p" >&5 +$as_echo "$ac_cv_sizeof_void_p" >&6; } + + + +cat >>confdefs.h <<_ACEOF +#define SIZEOF_VOID_P $ac_cv_sizeof_void_p +_ACEOF + + ;; +esac + +# Lacking an uint64_t? Test size of long +case "$acx_cv_header_stdint:$ac_cv_type_uint64_t:$ac_cv_type_u_int64_t" in + stddef.h:*:* | *:no:no) # The cast to long int works around a bug in the HP C Compiler +# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects +# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. +# This bug is HP SR number 8606223364. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of long" >&5 +$as_echo_n "checking size of long... " >&6; } +if test "${ac_cv_sizeof_long+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (long))" "ac_cv_sizeof_long" "$ac_includes_default"; then : + +else + if test "$ac_cv_type_long" = yes; then + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +{ as_fn_set_status 77 +as_fn_error "cannot compute sizeof (long) +See \`config.log' for more details." "$LINENO" 5; }; } + else + ac_cv_sizeof_long=0 + fi +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_long" >&5 +$as_echo "$ac_cv_sizeof_long" >&6; } + + + +cat >>confdefs.h <<_ACEOF +#define SIZEOF_LONG $ac_cv_sizeof_long +_ACEOF + + ;; +esac + +if test $acx_cv_header_stdint = stddef.h; then + # Lacking a good header? Test size of everything and deduce all types. + # The cast to long int works around a bug in the HP C Compiler +# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects +# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. +# This bug is HP SR number 8606223364. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of int" >&5 +$as_echo_n "checking size of int... " >&6; } +if test "${ac_cv_sizeof_int+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (int))" "ac_cv_sizeof_int" "$ac_includes_default"; then : + +else + if test "$ac_cv_type_int" = yes; then + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +{ as_fn_set_status 77 +as_fn_error "cannot compute sizeof (int) +See \`config.log' for more details." "$LINENO" 5; }; } + else + ac_cv_sizeof_int=0 + fi +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_int" >&5 +$as_echo "$ac_cv_sizeof_int" >&6; } + + + +cat >>confdefs.h <<_ACEOF +#define SIZEOF_INT $ac_cv_sizeof_int +_ACEOF + + + # The cast to long int works around a bug in the HP C Compiler +# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects +# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. +# This bug is HP SR number 8606223364. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of short" >&5 +$as_echo_n "checking size of short... " >&6; } +if test "${ac_cv_sizeof_short+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (short))" "ac_cv_sizeof_short" "$ac_includes_default"; then : + +else + if test "$ac_cv_type_short" = yes; then + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +{ as_fn_set_status 77 +as_fn_error "cannot compute sizeof (short) +See \`config.log' for more details." "$LINENO" 5; }; } + else + ac_cv_sizeof_short=0 + fi +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_short" >&5 +$as_echo "$ac_cv_sizeof_short" >&6; } + + + +cat >>confdefs.h <<_ACEOF +#define SIZEOF_SHORT $ac_cv_sizeof_short +_ACEOF + + + # The cast to long int works around a bug in the HP C Compiler +# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects +# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. +# This bug is HP SR number 8606223364. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of char" >&5 +$as_echo_n "checking size of char... " >&6; } +if test "${ac_cv_sizeof_char+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (char))" "ac_cv_sizeof_char" "$ac_includes_default"; then : + +else + if test "$ac_cv_type_char" = yes; then + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +{ as_fn_set_status 77 +as_fn_error "cannot compute sizeof (char) +See \`config.log' for more details." "$LINENO" 5; }; } + else + ac_cv_sizeof_char=0 + fi +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_char" >&5 +$as_echo "$ac_cv_sizeof_char" >&6; } + + + +cat >>confdefs.h <<_ACEOF +#define SIZEOF_CHAR $ac_cv_sizeof_char +_ACEOF + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for type equivalent to int8_t" >&5 +$as_echo_n "checking for type equivalent to int8_t... " >&6; } + case "$ac_cv_sizeof_char" in + 1) acx_cv_type_int8_t=char ;; + *) as_fn_error "no 8-bit type, please report a bug" "$LINENO" 5 + esac + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $acx_cv_type_int8_t" >&5 +$as_echo "$acx_cv_type_int8_t" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for type equivalent to int16_t" >&5 +$as_echo_n "checking for type equivalent to int16_t... " >&6; } + case "$ac_cv_sizeof_int:$ac_cv_sizeof_short" in + 2:*) acx_cv_type_int16_t=int ;; + *:2) acx_cv_type_int16_t=short ;; + *) as_fn_error "no 16-bit type, please report a bug" "$LINENO" 5 + esac + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $acx_cv_type_int16_t" >&5 +$as_echo "$acx_cv_type_int16_t" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for type equivalent to int32_t" >&5 +$as_echo_n "checking for type equivalent to int32_t... " >&6; } + case "$ac_cv_sizeof_int:$ac_cv_sizeof_long" in + 4:*) acx_cv_type_int32_t=int ;; + *:4) acx_cv_type_int32_t=long ;; + *) as_fn_error "no 32-bit type, please report a bug" "$LINENO" 5 + esac + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $acx_cv_type_int32_t" >&5 +$as_echo "$acx_cv_type_int32_t" >&6; } +fi + +# These tests are here to make the output prettier + +if test "$ac_cv_type_uint64_t" != yes && test "$ac_cv_type_u_int64_t" != yes; then + case "$ac_cv_sizeof_long" in + 8) acx_cv_type_int64_t=long ;; + esac + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for type equivalent to int64_t" >&5 +$as_echo_n "checking for type equivalent to int64_t... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${acx_cv_type_int64_t-'using preprocessor symbols'}" >&5 +$as_echo "${acx_cv_type_int64_t-'using preprocessor symbols'}" >&6; } +fi + +# Now we can use the above types + +if test "$ac_cv_type_uintptr_t" != yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for type equivalent to intptr_t" >&5 +$as_echo_n "checking for type equivalent to intptr_t... " >&6; } + case $ac_cv_sizeof_void_p in + 2) acx_cv_type_intptr_t=int16_t ;; + 4) acx_cv_type_intptr_t=int32_t ;; + 8) acx_cv_type_intptr_t=int64_t ;; + *) as_fn_error "no equivalent for intptr_t, please report a bug" "$LINENO" 5 + esac + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $acx_cv_type_intptr_t" >&5 +$as_echo "$acx_cv_type_intptr_t" >&6; } +fi + +# ----------------- done all checks, emit header ------------- +ac_config_commands="$ac_config_commands gstdint.h" + + + + + +ac_fn_c_check_header_mongrel "$LINENO" "sys/mman.h" "ac_cv_header_sys_mman_h" "$ac_includes_default" +if test "x$ac_cv_header_sys_mman_h" = x""yes; then : + gcc_header_sys_mman_h=yes +else + gcc_header_sys_mman_h=no +fi + + +ac_fn_c_check_func "$LINENO" "mmap" "ac_cv_func_mmap" +if test "x$ac_cv_func_mmap" = x""yes; then : + gcc_func_mmap=yes +else + gcc_func_mmap=no +fi + +if test "$gcc_header_sys_mman_h" != yes \ + || test "$gcc_func_mmap" != yes; then + gcc_cv_func_mmap_file=no + gcc_cv_func_mmap_dev_zero=no + gcc_cv_func_mmap_anon=no +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether read-only mmap of a plain file works" >&5 +$as_echo_n "checking whether read-only mmap of a plain file works... " >&6; } +if test "${gcc_cv_func_mmap_file+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + # Add a system to this blacklist if + # mmap(0, stat_size, PROT_READ, MAP_PRIVATE, fd, 0) doesn't return a + # memory area containing the same data that you'd get if you applied + # read() to the same fd. The only system known to have a problem here + # is VMS, where text files have record structure. + case "$host_os" in + vms* | ultrix*) + gcc_cv_func_mmap_file=no ;; + *) + gcc_cv_func_mmap_file=yes;; + esac +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_func_mmap_file" >&5 +$as_echo "$gcc_cv_func_mmap_file" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether mmap from /dev/zero works" >&5 +$as_echo_n "checking whether mmap from /dev/zero works... " >&6; } +if test "${gcc_cv_func_mmap_dev_zero+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + # Add a system to this blacklist if it has mmap() but /dev/zero + # does not exist, or if mmapping /dev/zero does not give anonymous + # zeroed pages with both the following properties: + # 1. If you map N consecutive pages in with one call, and then + # unmap any subset of those pages, the pages that were not + # explicitly unmapped remain accessible. + # 2. If you map two adjacent blocks of memory and then unmap them + # both at once, they must both go away. + # Systems known to be in this category are Windows (all variants), + # VMS, and Darwin. + case "$host_os" in + vms* | cygwin* | pe | mingw* | darwin* | ultrix* | hpux10* | hpux11.00) + gcc_cv_func_mmap_dev_zero=no ;; + *) + gcc_cv_func_mmap_dev_zero=yes;; + esac +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_func_mmap_dev_zero" >&5 +$as_echo "$gcc_cv_func_mmap_dev_zero" >&6; } + + # Unlike /dev/zero, the MAP_ANON(YMOUS) defines can be probed for. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for MAP_ANON(YMOUS)" >&5 +$as_echo_n "checking for MAP_ANON(YMOUS)... " >&6; } +if test "${gcc_cv_decl_map_anon+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <sys/types.h> +#include <sys/mman.h> +#include <unistd.h> + +#ifndef MAP_ANONYMOUS +#define MAP_ANONYMOUS MAP_ANON +#endif + +int +main () +{ +int n = MAP_ANONYMOUS; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + gcc_cv_decl_map_anon=yes +else + gcc_cv_decl_map_anon=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_decl_map_anon" >&5 +$as_echo "$gcc_cv_decl_map_anon" >&6; } + + if test $gcc_cv_decl_map_anon = no; then + gcc_cv_func_mmap_anon=no + else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether mmap with MAP_ANON(YMOUS) works" >&5 +$as_echo_n "checking whether mmap with MAP_ANON(YMOUS) works... " >&6; } +if test "${gcc_cv_func_mmap_anon+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + # Add a system to this blacklist if it has mmap() and MAP_ANON or + # MAP_ANONYMOUS, but using mmap(..., MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) + # doesn't give anonymous zeroed pages with the same properties listed + # above for use of /dev/zero. + # Systems known to be in this category are Windows, VMS, and SCO Unix. + case "$host_os" in + vms* | cygwin* | pe | mingw* | sco* | udk* ) + gcc_cv_func_mmap_anon=no ;; + *) + gcc_cv_func_mmap_anon=yes;; + esac +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_func_mmap_anon" >&5 +$as_echo "$gcc_cv_func_mmap_anon" >&6; } + fi +fi + +if test $gcc_cv_func_mmap_file = yes; then + +$as_echo "#define HAVE_MMAP_FILE 1" >>confdefs.h + +fi +if test $gcc_cv_func_mmap_dev_zero = yes; then + +$as_echo "#define HAVE_MMAP_DEV_ZERO 1" >>confdefs.h + +fi +if test $gcc_cv_func_mmap_anon = yes; then + +$as_echo "#define HAVE_MMAP_ANON 1" >>confdefs.h + +fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether byte ordering is bigendian" >&5 +$as_echo_n "checking whether byte ordering is bigendian... " >&6; } +if test "${ac_cv_c_bigendian+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_c_bigendian=unknown + # See if we're dealing with a universal compiler. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifndef __APPLE_CC__ + not a universal capable compiler + #endif + typedef int dummy; + +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + + # Check for potential -arch flags. It is not universal unless + # there are at least two -arch flags with different values. + ac_arch= + ac_prev= + for ac_word in $CC $CFLAGS $CPPFLAGS $LDFLAGS; do + if test -n "$ac_prev"; then + case $ac_word in + i?86 | x86_64 | ppc | ppc64) + if test -z "$ac_arch" || test "$ac_arch" = "$ac_word"; then + ac_arch=$ac_word + else + ac_cv_c_bigendian=universal + break + fi + ;; + esac + ac_prev= + elif test "x$ac_word" = "x-arch"; then + ac_prev=arch + fi + done +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + if test $ac_cv_c_bigendian = unknown; then + # See if sys/param.h defines the BYTE_ORDER macro. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <sys/types.h> + #include <sys/param.h> + +int +main () +{ +#if ! (defined BYTE_ORDER && defined BIG_ENDIAN \ + && defined LITTLE_ENDIAN && BYTE_ORDER && BIG_ENDIAN \ + && LITTLE_ENDIAN) + bogus endian macros + #endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + # It does; now see whether it defined to BIG_ENDIAN or not. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <sys/types.h> + #include <sys/param.h> + +int +main () +{ +#if BYTE_ORDER != BIG_ENDIAN + not big endian + #endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_c_bigendian=yes +else + ac_cv_c_bigendian=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + fi + if test $ac_cv_c_bigendian = unknown; then + # See if <limits.h> defines _LITTLE_ENDIAN or _BIG_ENDIAN (e.g., Solaris). + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <limits.h> + +int +main () +{ +#if ! (defined _LITTLE_ENDIAN || defined _BIG_ENDIAN) + bogus endian macros + #endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + # It does; now see whether it defined to _BIG_ENDIAN or not. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <limits.h> + +int +main () +{ +#ifndef _BIG_ENDIAN + not big endian + #endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_c_bigendian=yes +else + ac_cv_c_bigendian=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + fi + if test $ac_cv_c_bigendian = unknown; then + # Compile a test program. + if test "$cross_compiling" = yes; then : + # Try to guess by grepping values from an object file. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +short int ascii_mm[] = + { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 }; + short int ascii_ii[] = + { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 }; + int use_ascii (int i) { + return ascii_mm[i] + ascii_ii[i]; + } + short int ebcdic_ii[] = + { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 }; + short int ebcdic_mm[] = + { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 }; + int use_ebcdic (int i) { + return ebcdic_mm[i] + ebcdic_ii[i]; + } + extern int foo; + +int +main () +{ +return use_ascii (foo) == use_ebcdic (foo); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + if grep BIGenDianSyS conftest.$ac_objext >/dev/null; then + ac_cv_c_bigendian=yes + fi + if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then + if test "$ac_cv_c_bigendian" = unknown; then + ac_cv_c_bigendian=no + else + # finding both strings is unlikely to happen, but who knows? + ac_cv_c_bigendian=unknown + fi + fi +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ + + /* Are we little or big endian? From Harbison&Steele. */ + union + { + long int l; + char c[sizeof (long int)]; + } u; + u.l = 1; + return u.c[sizeof (long int) - 1] == 1; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + ac_cv_c_bigendian=no +else + ac_cv_c_bigendian=yes +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_bigendian" >&5 +$as_echo "$ac_cv_c_bigendian" >&6; } + case $ac_cv_c_bigendian in #( + yes) + $as_echo "#define WORDS_BIGENDIAN 1" >>confdefs.h +;; #( + no) + ;; #( + universal) + +$as_echo "#define AC_APPLE_UNIVERSAL_BUILD 1" >>confdefs.h + + ;; #( + *) + as_fn_error "unknown endianness + presetting ac_cv_c_bigendian=no (or yes) will help" "$LINENO" 5 ;; + esac + +# I don't like the default behaviour of WORDS_BIGENDIAN undefined for LE. + + +# Check to see if -pthread or -lpthread is needed. Prefer the former. +# In case the pthread.h system header is not found, this test will fail. +XPCFLAGS="" +CFLAGS="$CFLAGS -pthread" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <pthread.h> + void *g(void *d) { return NULL; } +int +main () +{ +pthread_t t; pthread_create(&t,NULL,g,NULL); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + XPCFLAGS=" -Wc,-pthread" +else + CFLAGS="$save_CFLAGS" LIBS="-lpthread $LIBS" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <pthread.h> + void *g(void *d) { return NULL; } +int +main () +{ +pthread_t t; pthread_create(&t,NULL,g,NULL); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + +else + as_fn_error "Pthreads are required to build libitm" "$LINENO" 5 +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + +# Check for functions needed. +for ac_func in strtoull memalign posix_memalign +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +eval as_val=\$$as_ac_var + if test "x$as_val" = x""yes; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + +# Check for broken semaphore implementation on darwin. +# sem_init returns: sem_init error: Function not implemented. +case "$host" in + *-darwin*) + +$as_echo "#define HAVE_BROKEN_POSIX_SEMAPHORES 1" >>confdefs.h + + ;; +esac + + # Check whether --enable-linux-futex was given. +if test "${enable_linux_futex+set}" = set; then : + enableval=$enable_linux_futex; + case "$enableval" in + yes|no|default) ;; + *) as_fn_error "Unknown argument to enable/disable linux-futex" "$LINENO" 5 ;; + esac + +else + enable_linux_futex=default +fi + + +case "$target" in + *-linux*) + case "$enable_linux_futex" in + default) + # If headers don't have gettid/futex syscalls definition, then + # default to no, otherwise there will be compile time failures. + # Otherwise, default to yes. If we don't detect we are + # compiled/linked against NPTL and not cross-compiling, check + # if programs are run by default against NPTL and if not, issue + # a warning. + enable_linux_futex=no + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <sys/syscall.h> + int lk; +int +main () +{ +syscall (SYS_gettid); syscall (SYS_futex, &lk, 0, 0, 0); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + save_LIBS="$LIBS" + LIBS="-lpthread $LIBS" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifndef _GNU_SOURCE + #define _GNU_SOURCE 1 + #endif + #include <pthread.h> + pthread_t th; void *status; +int +main () +{ +pthread_tryjoin_np (th, &status); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + enable_linux_futex=yes +else + if test x$cross_compiling = xno; then + if getconf GNU_LIBPTHREAD_VERSION 2>/dev/null \ + | LC_ALL=C grep -i NPTL > /dev/null 2>/dev/null; then :; else + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: The kernel might not support futex or gettid syscalls. +If so, please configure with --disable-linux-futex" >&5 +$as_echo "$as_me: WARNING: The kernel might not support futex or gettid syscalls. +If so, please configure with --disable-linux-futex" >&2;} + fi + fi + enable_linux_futex=yes +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LIBS="$save_LIBS" +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + ;; + yes) + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <sys/syscall.h> + int lk; +int +main () +{ +syscall (SYS_gettid); syscall (SYS_futex, &lk, 0, 0, 0); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + +else + as_fn_error "SYS_gettid and SYS_futex required for --enable-linux-futex" "$LINENO" 5 +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + ;; + esac + ;; + *) + enable_linux_futex=no + ;; +esac +if test x$enable_linux_futex = xyes; then + : +fi + + +# See if we support thread-local storage. + + + # Check whether --enable-tls was given. +if test "${enable_tls+set}" = set; then : + enableval=$enable_tls; + case "$enableval" in + yes|no) ;; + *) as_fn_error "Argument to enable/disable tls must be yes or no" "$LINENO" 5 ;; + esac + +else + enable_tls=yes +fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the target supports thread-local storage" >&5 +$as_echo_n "checking whether the target supports thread-local storage... " >&6; } +if test "${gcc_cv_have_tls+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + + if test "$cross_compiling" = yes; then : + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +__thread int a; int b; int main() { return a = b; } +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + chktls_save_LDFLAGS="$LDFLAGS" + case $host in + *-*-linux*) + LDFLAGS="-shared -Wl,--no-undefined $LDFLAGS" + ;; + esac + chktls_save_CFLAGS="$CFLAGS" + CFLAGS="-fPIC $CFLAGS" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +int f() { return 0; } +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +__thread int a; int b; int f() { return a = b; } +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + gcc_cv_have_tls=yes +else + gcc_cv_have_tls=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +else + gcc_cv_have_tls=yes +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CFLAGS="$chktls_save_CFLAGS" + LDFLAGS="$chktls_save_LDFLAGS" +else + gcc_cv_have_tls=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + + +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +__thread int a; int b; int main() { return a = b; } +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + chktls_save_LDFLAGS="$LDFLAGS" + LDFLAGS="-static $LDFLAGS" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +int main() { return 0; } +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + if test "$cross_compiling" = yes; then : + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error "cannot run test program while cross compiling +See \`config.log' for more details." "$LINENO" 5; } +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +__thread int a; int b; int main() { return a = b; } +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + gcc_cv_have_tls=yes +else + gcc_cv_have_tls=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +else + gcc_cv_have_tls=yes +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS="$chktls_save_LDFLAGS" + if test $gcc_cv_have_tls = yes; then + chktls_save_CFLAGS="$CFLAGS" + thread_CFLAGS=failed + for flag in '' '-pthread' '-lpthread'; do + CFLAGS="$flag $chktls_save_CFLAGS" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <pthread.h> + void *g(void *d) { return NULL; } +int +main () +{ +pthread_t t; pthread_create(&t,NULL,g,NULL); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + thread_CFLAGS="$flag" +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + if test "X$thread_CFLAGS" != Xfailed; then + break + fi + done + CFLAGS="$chktls_save_CFLAGS" + if test "X$thread_CFLAGS" != Xfailed; then + CFLAGS="$thread_CFLAGS $chktls_save_CFLAGS" + if test "$cross_compiling" = yes; then : + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error "cannot run test program while cross compiling +See \`config.log' for more details." "$LINENO" 5; } +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <pthread.h> + __thread int a; + static int *volatile a_in_other_thread; + static void * + thread_func (void *arg) + { + a_in_other_thread = &a; + return (void *)0; + } +int +main () +{ +pthread_t thread; + void *thread_retval; + int *volatile a_in_main_thread; + a_in_main_thread = &a; + if (pthread_create (&thread, (pthread_attr_t *)0, + thread_func, (void *)0)) + return 0; + if (pthread_join (thread, &thread_retval)) + return 0; + return (a_in_other_thread == a_in_main_thread); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + gcc_cv_have_tls=yes +else + gcc_cv_have_tls=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + + CFLAGS="$chktls_save_CFLAGS" + fi + fi +else + gcc_cv_have_tls=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_have_tls" >&5 +$as_echo "$gcc_cv_have_tls" >&6; } + if test "$enable_tls $gcc_cv_have_tls" = "yes yes"; then + +$as_echo "#define HAVE_TLS 1" >>confdefs.h + + fi + +# See what sort of export controls are availible. + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the target supports hidden visibility" >&5 +$as_echo_n "checking whether the target supports hidden visibility... " >&6; } +if test "${libitm_cv_have_attribute_visibility+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + + save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -Werror" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +void __attribute__((visibility("hidden"))) foo(void) { } +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + libitm_cv_have_attribute_visibility=yes +else + libitm_cv_have_attribute_visibility=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + CFLAGS="$save_CFLAGS" +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libitm_cv_have_attribute_visibility" >&5 +$as_echo "$libitm_cv_have_attribute_visibility" >&6; } + if test $libitm_cv_have_attribute_visibility = yes; then + +$as_echo "#define HAVE_ATTRIBUTE_VISIBILITY 1" >>confdefs.h + + fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the target supports dllexport" >&5 +$as_echo_n "checking whether the target supports dllexport... " >&6; } +if test "${libitm_cv_have_attribute_dllexport+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + + save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -Werror" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +void __attribute__((dllexport)) foo(void) { } +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + libitm_cv_have_attribute_dllexport=yes +else + libitm_cv_have_attribute_dllexport=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + CFLAGS="$save_CFLAGS" +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libitm_cv_have_attribute_dllexport" >&5 +$as_echo "$libitm_cv_have_attribute_dllexport" >&6; } + if test $libitm_cv_have_attribute_dllexport = yes; then + +$as_echo "#define HAVE_ATTRIBUTE_DLLEXPORT 1" >>confdefs.h + + fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the target supports symbol aliases" >&5 +$as_echo_n "checking whether the target supports symbol aliases... " >&6; } +if test "${libitm_cv_have_attribute_alias+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +void foo(void) { } +extern void bar(void) __attribute__((alias("foo"))); +int +main () +{ +bar(); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + libitm_cv_have_attribute_alias=yes +else + libitm_cv_have_attribute_alias=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libitm_cv_have_attribute_alias" >&5 +$as_echo "$libitm_cv_have_attribute_alias" >&6; } + if test $libitm_cv_have_attribute_alias = yes; then + +$as_echo "#define HAVE_ATTRIBUTE_ALIAS 1" >>confdefs.h + + fi + + +# Check whether --with-gnu-ld was given. +if test "${with_gnu_ld+set}" = set; then : + withval=$with_gnu_ld; test "$withval" = no || with_gnu_ld=yes +else + with_gnu_ld=no +fi + +ac_prog=ld +if test "$GCC" = yes; then + # Check if gcc -print-prog-name=ld gives a path. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5 +$as_echo_n "checking for ld used by $CC... " >&6; } + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case $ac_prog in + # Accept absolute paths. + [\\/]* | ?:[\\/]*) + re_direlt='/[^/][^/]*/\.\./' + # Canonicalize the pathname of ld + ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` + while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do + ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` + done + test -z "$LD" && LD="$ac_prog" + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test "$with_gnu_ld" = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5 +$as_echo_n "checking for GNU ld... " >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5 +$as_echo_n "checking for non-GNU ld... " >&6; } +fi +if test "${lt_cv_path_LD+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$LD"; then + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + lt_cv_path_LD="$ac_dir/$ac_prog" + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some variants of GNU ld only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + case `"$lt_cv_path_LD" -v 2>&1 </dev/null` in + *GNU* | *'with BFD'*) + test "$with_gnu_ld" != no && break + ;; + *) + test "$with_gnu_ld" != yes && break + ;; + esac + fi + done + IFS="$lt_save_ifs" +else + lt_cv_path_LD="$LD" # Let the user override the test with a path. +fi +fi + +LD="$lt_cv_path_LD" +if test -n "$LD"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LD" >&5 +$as_echo "$LD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +test -z "$LD" && as_fn_error "no acceptable ld found in \$PATH" "$LINENO" 5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5 +$as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; } +if test "${lt_cv_prog_gnu_ld+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + # I'd rather use --version here, but apparently some GNU lds only accept -v. +case `$LD -v 2>&1 </dev/null` in +*GNU* | *'with BFD'*) + lt_cv_prog_gnu_ld=yes + ;; +*) + lt_cv_prog_gnu_ld=no + ;; +esac +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_gnu_ld" >&5 +$as_echo "$lt_cv_prog_gnu_ld" >&6; } +with_gnu_ld=$lt_cv_prog_gnu_ld + + + + + + + + # If we're not using GNU ld, then there's no point in even trying these + # tests. Check for that first. We should have already tested for gld + # by now (in libtool), but require it now just to be safe... + test -z "$SECTION_LDFLAGS" && SECTION_LDFLAGS='' + test -z "$OPT_LDFLAGS" && OPT_LDFLAGS='' + + + + # The name set by libtool depends on the version of libtool. Shame on us + # for depending on an impl detail, but c'est la vie. Older versions used + # ac_cv_prog_gnu_ld, but now it's lt_cv_prog_gnu_ld, and is copied back on + # top of with_gnu_ld (which is also set by --with-gnu-ld, so that actually + # makes sense). We'll test with_gnu_ld everywhere else, so if that isn't + # set (hence we're using an older libtool), then set it. + if test x${with_gnu_ld+set} != xset; then + if test x${ac_cv_prog_gnu_ld+set} != xset; then + # We got through "ac_require(ac_prog_ld)" and still not set? Huh? + with_gnu_ld=no + else + with_gnu_ld=$ac_cv_prog_gnu_ld + fi + fi + + # Start by getting the version number. I think the libtool test already + # does some of this, but throws away the result. + + ldver=`$LD --version 2>/dev/null | head -1 | \ + sed -e 's/GNU ld \(version \)\{0,1\}\(([^)]*) \)\{0,1\}\([0-9.][0-9.]*\).*/\3/'` + + libitm_gnu_ld_version=`echo $ldver | \ + $AWK -F. '{ if (NF<3) $3=0; print ($1*100+$2)*100+$3 }'` + + # Set --gc-sections. + if test "$with_gnu_ld" = "notbroken"; then + # GNU ld it is! Joy and bunny rabbits! + + # All these tests are for C++; save the language and the compiler flags. + # Need to do this so that g++ won't try to link in libstdc++ + ac_test_CFLAGS="${CFLAGS+set}" + ac_save_CFLAGS="$CFLAGS" + CFLAGS='-x c++ -Wl,--gc-sections' + + # Check for -Wl,--gc-sections + # XXX This test is broken at the moment, as symbols required for linking + # are now in libsupc++ (not built yet). In addition, this test has + # cored on solaris in the past. In addition, --gc-sections doesn't + # really work at the moment (keeps on discarding used sections, first + # .eh_frame and now some of the glibc sections for iconv). + # Bzzzzt. Thanks for playing, maybe next time. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld that supports -Wl,--gc-sections" >&5 +$as_echo_n "checking for ld that supports -Wl,--gc-sections... " >&6; } + if test "$cross_compiling" = yes; then : + ac_sectionLDflags=yes +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + int main(void) + { + try { throw 1; } + catch (...) { }; + return 0; + } + +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + ac_sectionLDflags=yes +else + ac_sectionLDflags=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + + if test "$ac_test_CFLAGS" = set; then + CFLAGS="$ac_save_CFLAGS" + else + # this is the suspicious part + CFLAGS='' + fi + if test "$ac_sectionLDflags" = "yes"; then + SECTION_LDFLAGS="-Wl,--gc-sections $SECTION_LDFLAGS" + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_sectionLDflags" >&5 +$as_echo "$ac_sectionLDflags" >&6; } + fi + + # Set linker optimization flags. + if test x"$with_gnu_ld" = x"yes"; then + OPT_LDFLAGS="-Wl,-O1 $OPT_LDFLAGS" + fi + + + + + + + # Check whether --enable-symvers was given. +if test "${enable_symvers+set}" = set; then : + enableval=$enable_symvers; + case "$enableval" in + yes|no|gnu) ;; + *) as_fn_error "Unknown argument to enable/disable symvers" "$LINENO" 5 ;; + esac + +else + enable_symvers=yes +fi + + + +# If we never went through the LIBITM_CHECK_LINKER_FEATURES macro, then we +# don't know enough about $LD to do tricks... + +# FIXME The following test is too strict, in theory. +if test $enable_shared = no || + test "x$LD" = x || + test x$libitm_gnu_ld_version = x; then + enable_symvers=no +fi + +# Check to see if libgcc_s exists, indicating that shared libgcc is possible. +if test $enable_symvers != no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shared libgcc" >&5 +$as_echo_n "checking for shared libgcc... " >&6; } + ac_save_CFLAGS="$CFLAGS" + CFLAGS=' -lgcc_s' + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + libitm_shared_libgcc=yes +else + libitm_shared_libgcc=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CFLAGS="$ac_save_CFLAGS" + if test $libitm_shared_libgcc = no; then + cat > conftest.c <<EOF +int main (void) { return 0; } +EOF + libitm_libgcc_s_suffix=`${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS \ + -shared -shared-libgcc -o conftest.so \ + conftest.c -v 2>&1 >/dev/null \ + | sed -n 's/^.* -lgcc_s\([^ ]*\) .*$/\1/p'` + rm -f conftest.c conftest.so + if test x${libitm_libgcc_s_suffix+set} = xset; then + CFLAGS=" -lgcc_s$libitm_libgcc_s_suffix" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + libitm_shared_libgcc=yes +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CFLAGS="$ac_save_CFLAGS" + fi + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $libitm_shared_libgcc" >&5 +$as_echo "$libitm_shared_libgcc" >&6; } +fi + +# For GNU ld, we need at least this version. The format is described in +# LIBITM_CHECK_LINKER_FEATURES above. +libitm_min_gnu_ld_version=21400 +# XXXXXXXXXXX libitm_gnu_ld_version=21390 + +# Check to see if unspecified "yes" value can win, given results above. +# Change "yes" into either "no" or a style name. +if test $enable_symvers = yes; then + if test $with_gnu_ld = yes && + test $libitm_shared_libgcc = yes; + then + if test $libitm_gnu_ld_version -ge $libitm_min_gnu_ld_version ; then + enable_symvers=gnu + else + # The right tools, the right setup, but too old. Fallbacks? + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: === Linker version $libitm_gnu_ld_version is too old for" >&5 +$as_echo "$as_me: WARNING: === Linker version $libitm_gnu_ld_version is too old for" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: === full symbol versioning support in this release of GCC." >&5 +$as_echo "$as_me: WARNING: === full symbol versioning support in this release of GCC." >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: === You would need to upgrade your binutils to version" >&5 +$as_echo "$as_me: WARNING: === You would need to upgrade your binutils to version" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: === $libitm_min_gnu_ld_version or later and rebuild GCC." >&5 +$as_echo "$as_me: WARNING: === $libitm_min_gnu_ld_version or later and rebuild GCC." >&2;} + if test $libitm_gnu_ld_version -ge 21200 ; then + # Globbing fix is present, proper block support is not. + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: === Symbol versioning will be disabled." >&5 +$as_echo "$as_me: WARNING: === Symbol versioning will be disabled." >&2;} + enable_symvers=no + else + # 2.11 or older. + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: === Symbol versioning will be disabled." >&5 +$as_echo "$as_me: WARNING: === Symbol versioning will be disabled." >&2;} + enable_symvers=no + fi + fi + else + # just fail for now + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: === You have requested some kind of symbol versioning, but" >&5 +$as_echo "$as_me: WARNING: === You have requested some kind of symbol versioning, but" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: === either you are not using a supported linker, or you are" >&5 +$as_echo "$as_me: WARNING: === either you are not using a supported linker, or you are" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: === not building a shared libgcc_s (which is required)." >&5 +$as_echo "$as_me: WARNING: === not building a shared libgcc_s (which is required)." >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: === Symbol versioning will be disabled." >&5 +$as_echo "$as_me: WARNING: === Symbol versioning will be disabled." >&2;} + enable_symvers=no + fi +fi + + if test $enable_symvers != no; then + LIBITM_BUILD_VERSIONED_SHLIB_TRUE= + LIBITM_BUILD_VERSIONED_SHLIB_FALSE='#' +else + LIBITM_BUILD_VERSIONED_SHLIB_TRUE='#' + LIBITM_BUILD_VERSIONED_SHLIB_FALSE= +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: versioning on shared library symbols is $enable_symvers" >&5 +$as_echo "$as_me: versioning on shared library symbols is $enable_symvers" >&6;} + + +if test $enable_symvers = gnu; then + +$as_echo "#define LIBITM_GNU_SYMBOL_VERSIONING 1" >>confdefs.h + +fi + +# Determine the proper ABI type for size_t. + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking how size_t is mangled" >&5 +$as_echo_n "checking how size_t is mangled... " >&6; } +if test "${libitm_cv_size_t_mangling+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +extern __SIZE_TYPE__ x; extern unsigned long x; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + libitm_cv_size_t_mangling=m +else + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +extern __SIZE_TYPE__ x; extern unsigned int x; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + libitm_cv_size_t_mangling=j +else + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +extern __SIZE_TYPE__ x; extern unsigned long long x; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + libitm_cv_size_t_mangling=y +else + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +extern __SIZE_TYPE__ x; extern unsigned short x; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + libitm_cv_size_t_mangling=t +else + libitm_cv_size_t_mangling=x +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libitm_cv_size_t_mangling" >&5 +$as_echo "$libitm_cv_size_t_mangling" >&6; } + if test $libitm_cv_size_t_mangling = x; then + as_fn_error "Unknown underlying type for size_t" "$LINENO" 5 + fi + +cat >>confdefs.h <<_ACEOF +#define MANGLE_SIZE_T $libitm_cv_size_t_mangling +_ACEOF + + + +# Get target configury. +. ${srcdir}/configure.tgt +CFLAGS="$save_CFLAGS $XCFLAGS" + +# Check for __sync_val_compare_and_swap, but only after the target has +# had a chance to set XCFLAGS. + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the target supports __sync_*_compare_and_swap" >&5 +$as_echo_n "checking whether the target supports __sync_*_compare_and_swap... " >&6; } +if test "${libitm_cv_have_sync_builtins+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +int foo, bar; bar = __sync_val_compare_and_swap(&foo, 0, 1); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + libitm_cv_have_sync_builtins=yes +else + libitm_cv_have_sync_builtins=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libitm_cv_have_sync_builtins" >&5 +$as_echo "$libitm_cv_have_sync_builtins" >&6; } + if test $libitm_cv_have_sync_builtins = yes; then + +$as_echo "#define HAVE_SYNC_BUILTINS 1" >>confdefs.h + + fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the target supports 64-bit __sync_*_compare_and_swap" >&5 +$as_echo_n "checking whether the target supports 64-bit __sync_*_compare_and_swap... " >&6; } +if test "${libitm_cv_have_64bit_sync_builtins+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <stdint.h> +int +main () +{ +uint64_t foo, bar; + bar = __sync_val_compare_and_swap(&foo, 0, 1); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + libitm_cv_have_64bit_sync_builtins=yes +else + libitm_cv_have_64bit_sync_builtins=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libitm_cv_have_64bit_sync_builtins" >&5 +$as_echo "$libitm_cv_have_64bit_sync_builtins" >&6; } + if test $libitm_cv_have_64bit_sync_builtins = yes; then + +$as_echo "#define HAVE_64BIT_SYNC_BUILTINS 1" >>confdefs.h + + fi + +# Cleanup and exit. +CFLAGS="$save_CFLAGS" +cat >confcache <<\_ACEOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs, see configure's option --config-cache. +# It is not useful on other systems. If it contains results you don't +# want to keep, you may remove or edit it. +# +# config.status only pays attention to the cache file if you give it +# the --recheck option to rerun configure. +# +# `ac_cv_env_foo' variables (set or unset) will be overridden when +# loading this file, other *unset* `ac_cv_foo' will be assigned the +# following values. + +_ACEOF + +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, we kill variables containing newlines. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +( + for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + + (set) 2>&1 | + case $as_nl`(ac_space=' '; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + # `set' does not quote correctly, so add quotes: double-quote + # substitution turns \\\\ into \\, and sed turns \\ into \. + sed -n \ + "s/'/'\\\\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" + ;; #( + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) | + sed ' + /^ac_cv_env_/b end + t clear + :clear + s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ + t end + s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ + :end' >>confcache +if diff "$cache_file" confcache >/dev/null 2>&1; then :; else + if test -w "$cache_file"; then + test "x$cache_file" != "x/dev/null" && + { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 +$as_echo "$as_me: updating cache $cache_file" >&6;} + cat confcache >$cache_file + else + { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 +$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} + fi +fi +rm -f confcache + +# Add -Wall -Werror if we are using GCC. +if test "x$GCC" = "xyes"; then + XCFLAGS="$XCFLAGS -Wall -Werror" +fi + +XCFLAGS="$XCFLAGS $XPCFLAGS" + + + + + +if test ${multilib} = yes; then + multilib_arg="--enable-multilib" +else + multilib_arg= +fi + +# Set up the set of libraries that we need to link against for libitm. +# Note that the GOMP_SELF_SPEC in gcc.c will force -pthread for -fopenmp, +# which will force linkage against -lpthread (or equivalent for the system). +# That's not 100% ideal, but about the best we can do easily. +if test $enable_shared = yes; then + link_itm="-litm %{static: $LIBS}" +else + link_itm="-litm $LIBS" +fi + + + if test "$ARCH" = x86; then + ARCH_X86_TRUE= + ARCH_X86_FALSE='#' +else + ARCH_X86_TRUE='#' + ARCH_X86_FALSE= +fi + + if test $enable_linux_futex = yes; then + ARCH_FUTEX_TRUE= + ARCH_FUTEX_FALSE='#' +else + ARCH_FUTEX_TRUE='#' + ARCH_FUTEX_FALSE= +fi + + +ac_config_files="$ac_config_files Makefile testsuite/Makefile libitm.spec" + +cat >confcache <<\_ACEOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs, see configure's option --config-cache. +# It is not useful on other systems. If it contains results you don't +# want to keep, you may remove or edit it. +# +# config.status only pays attention to the cache file if you give it +# the --recheck option to rerun configure. +# +# `ac_cv_env_foo' variables (set or unset) will be overridden when +# loading this file, other *unset* `ac_cv_foo' will be assigned the +# following values. + +_ACEOF + +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, we kill variables containing newlines. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +( + for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + + (set) 2>&1 | + case $as_nl`(ac_space=' '; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + # `set' does not quote correctly, so add quotes: double-quote + # substitution turns \\\\ into \\, and sed turns \\ into \. + sed -n \ + "s/'/'\\\\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" + ;; #( + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) | + sed ' + /^ac_cv_env_/b end + t clear + :clear + s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ + t end + s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ + :end' >>confcache +if diff "$cache_file" confcache >/dev/null 2>&1; then :; else + if test -w "$cache_file"; then + test "x$cache_file" != "x/dev/null" && + { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 +$as_echo "$as_me: updating cache $cache_file" >&6;} + cat confcache >$cache_file + else + { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 +$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} + fi +fi +rm -f confcache + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +DEFS=-DHAVE_CONFIG_H + +ac_libobjs= +ac_ltlibobjs= +for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue + # 1. Remove the extension, and $U if already installed. + ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' + ac_i=`$as_echo "$ac_i" | sed "$ac_script"` + # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR + # will be set to the directory where LIBOBJS objects are built. + as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" + as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' +done +LIBOBJS=$ac_libobjs + +LTLIBOBJS=$ac_ltlibobjs + + +if test -z "${GENINSRC_TRUE}" && test -z "${GENINSRC_FALSE}"; then + as_fn_error "conditional \"GENINSRC\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi + if test -n "$EXEEXT"; then + am__EXEEXT_TRUE= + am__EXEEXT_FALSE='#' +else + am__EXEEXT_TRUE='#' + am__EXEEXT_FALSE= +fi + +if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then + as_fn_error "conditional \"AMDEP\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then + as_fn_error "conditional \"am__fastdepCC\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${am__fastdepCXX_TRUE}" && test -z "${am__fastdepCXX_FALSE}"; then + as_fn_error "conditional \"am__fastdepCXX\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${am__fastdepCCAS_TRUE}" && test -z "${am__fastdepCCAS_FALSE}"; then + as_fn_error "conditional \"am__fastdepCCAS\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${BUILD_INFO_TRUE}" && test -z "${BUILD_INFO_FALSE}"; then + as_fn_error "conditional \"BUILD_INFO\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${MAINTAINER_MODE_TRUE}" && test -z "${MAINTAINER_MODE_FALSE}"; then + as_fn_error "conditional \"MAINTAINER_MODE\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi + +if test -z "${LIBITM_BUILD_VERSIONED_SHLIB_TRUE}" && test -z "${LIBITM_BUILD_VERSIONED_SHLIB_FALSE}"; then + as_fn_error "conditional \"LIBITM_BUILD_VERSIONED_SHLIB\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${ARCH_X86_TRUE}" && test -z "${ARCH_X86_FALSE}"; then + as_fn_error "conditional \"ARCH_X86\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${ARCH_FUTEX_TRUE}" && test -z "${ARCH_FUTEX_FALSE}"; then + as_fn_error "conditional \"ARCH_FUTEX\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi + +: ${CONFIG_STATUS=./config.status} +ac_write_fail=0 +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files $CONFIG_STATUS" +{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 +$as_echo "$as_me: creating $CONFIG_STATUS" >&6;} +as_write_fail=0 +cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 +#! $SHELL +# Generated by $as_me. +# Run this file to recreate the current configuration. +# Compiler output produced by configure, useful for debugging +# configure, is in config.log if it exists. + +debug=false +ac_cs_recheck=false +ac_cs_silent=false + +SHELL=\${CONFIG_SHELL-$SHELL} +export SHELL +_ASEOF +cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + + +# as_fn_error ERROR [LINENO LOG_FD] +# --------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with status $?, using 1 if that was 0. +as_fn_error () +{ + as_status=$?; test $as_status -eq 0 && as_status=1 + if test "$3"; then + as_lineno=${as_lineno-"$2"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $1" >&$3 + fi + $as_echo "$as_me: error: $1" >&2 + as_fn_exit $as_status +} # as_fn_error + + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -p'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -p' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -p' + fi +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error "cannot create directory $as_dir" + + +} # as_fn_mkdir_p +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +if test -x / >/dev/null 2>&1; then + as_test_x='test -x' +else + if ls -dL / >/dev/null 2>&1; then + as_ls_L_option=L + else + as_ls_L_option= + fi + as_test_x=' + eval sh -c '\'' + if test -d "$1"; then + test -d "$1/."; + else + case $1 in #( + -*)set "./$1";; + esac; + case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #(( + ???[sx]*):;;*)false;;esac;fi + '\'' sh + ' +fi +as_executable_p=$as_test_x + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +exec 6>&1 +## ----------------------------------- ## +## Main body of $CONFIG_STATUS script. ## +## ----------------------------------- ## +_ASEOF +test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# Save the log message, to keep $0 and so on meaningful, and to +# report actual input values of CONFIG_FILES etc. instead of their +# values after options handling. +ac_log=" +This file was extended by GNU TM Runtime Library $as_me 1.0, which was +generated by GNU Autoconf 2.64. Invocation command line was + + CONFIG_FILES = $CONFIG_FILES + CONFIG_HEADERS = $CONFIG_HEADERS + CONFIG_LINKS = $CONFIG_LINKS + CONFIG_COMMANDS = $CONFIG_COMMANDS + $ $0 $@ + +on `(hostname || uname -n) 2>/dev/null | sed 1q` +" + +_ACEOF + +case $ac_config_files in *" +"*) set x $ac_config_files; shift; ac_config_files=$*;; +esac + +case $ac_config_headers in *" +"*) set x $ac_config_headers; shift; ac_config_headers=$*;; +esac + + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +# Files that config.status was made for. +config_files="$ac_config_files" +config_headers="$ac_config_headers" +config_commands="$ac_config_commands" + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +ac_cs_usage="\ +\`$as_me' instantiates files and other configuration actions +from templates according to the current configuration. Unless the files +and actions are specified as TAGs, all are instantiated by default. + +Usage: $0 [OPTION]... [TAG]... + + -h, --help print this help, then exit + -V, --version print version number and configuration settings, then exit + -q, --quiet, --silent + do not print progress messages + -d, --debug don't remove temporary files + --recheck update $as_me by reconfiguring in the same conditions + --file=FILE[:TEMPLATE] + instantiate the configuration file FILE + --header=FILE[:TEMPLATE] + instantiate the configuration header FILE + +Configuration files: +$config_files + +Configuration headers: +$config_headers + +Configuration commands: +$config_commands + +Report bugs to the package provider. +GNU TM Runtime Library home page: <http://www.gnu.org/software/libitm/>. +General help using GNU software: <http://www.gnu.org/gethelp/>." + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_cs_version="\\ +GNU TM Runtime Library config.status 1.0 +configured by $0, generated by GNU Autoconf 2.64, + with options \\"`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\" + +Copyright (C) 2009 Free Software Foundation, Inc. +This config.status script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it." + +ac_pwd='$ac_pwd' +srcdir='$srcdir' +INSTALL='$INSTALL' +MKDIR_P='$MKDIR_P' +AWK='$AWK' +test -n "\$AWK" || AWK=awk +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# The default lists apply if the user does not specify any file. +ac_need_defaults=: +while test $# != 0 +do + case $1 in + --*=*) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` + ac_shift=: + ;; + *) + ac_option=$1 + ac_optarg=$2 + ac_shift=shift + ;; + esac + + case $ac_option in + # Handling of the options. + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + ac_cs_recheck=: ;; + --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) + $as_echo "$ac_cs_version"; exit ;; + --debug | --debu | --deb | --de | --d | -d ) + debug=: ;; + --file | --fil | --fi | --f ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + as_fn_append CONFIG_FILES " '$ac_optarg'" + ac_need_defaults=false;; + --header | --heade | --head | --hea ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + as_fn_append CONFIG_HEADERS " '$ac_optarg'" + ac_need_defaults=false;; + --he | --h) + # Conflict between --help and --header + as_fn_error "ambiguous option: \`$1' +Try \`$0 --help' for more information.";; + --help | --hel | -h ) + $as_echo "$ac_cs_usage"; exit ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil | --si | --s) + ac_cs_silent=: ;; + + # This is an error. + -*) as_fn_error "unrecognized option: \`$1' +Try \`$0 --help' for more information." ;; + + *) as_fn_append ac_config_targets " $1" + ac_need_defaults=false ;; + + esac + shift +done + +ac_configure_extra_args= + +if $ac_cs_silent; then + exec 6>/dev/null + ac_configure_extra_args="$ac_configure_extra_args --silent" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +if \$ac_cs_recheck; then + set X '$SHELL' '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion + shift + \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 + CONFIG_SHELL='$SHELL' + export CONFIG_SHELL + exec "\$@" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +exec 5>>config.log +{ + echo + sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX +## Running $as_me. ## +_ASBOX + $as_echo "$ac_log" +} >&5 + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +# +# INIT-COMMANDS +# + +srcdir="$srcdir" +host="$host" +target="$target" +with_multisubdir="$with_multisubdir" +with_multisrctop="$with_multisrctop" +with_target_subdir="$with_target_subdir" +ac_configure_args="${multilib_arg} ${ac_configure_args}" +multi_basedir="$multi_basedir" +CONFIG_SHELL=${CONFIG_SHELL-/bin/sh} +CC="$CC" +CXX="$CXX" +GFORTRAN="$GFORTRAN" +GCJ="$GCJ" +AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir" + + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +sed_quote_subst='$sed_quote_subst' +double_quote_subst='$double_quote_subst' +delay_variable_subst='$delay_variable_subst' +macro_version='`$ECHO "$macro_version" | $SED "$delay_single_quote_subst"`' +macro_revision='`$ECHO "$macro_revision" | $SED "$delay_single_quote_subst"`' +enable_shared='`$ECHO "$enable_shared" | $SED "$delay_single_quote_subst"`' +enable_static='`$ECHO "$enable_static" | $SED "$delay_single_quote_subst"`' +pic_mode='`$ECHO "$pic_mode" | $SED "$delay_single_quote_subst"`' +enable_fast_install='`$ECHO "$enable_fast_install" | $SED "$delay_single_quote_subst"`' +SHELL='`$ECHO "$SHELL" | $SED "$delay_single_quote_subst"`' +ECHO='`$ECHO "$ECHO" | $SED "$delay_single_quote_subst"`' +host_alias='`$ECHO "$host_alias" | $SED "$delay_single_quote_subst"`' +host='`$ECHO "$host" | $SED "$delay_single_quote_subst"`' +host_os='`$ECHO "$host_os" | $SED "$delay_single_quote_subst"`' +build_alias='`$ECHO "$build_alias" | $SED "$delay_single_quote_subst"`' +build='`$ECHO "$build" | $SED "$delay_single_quote_subst"`' +build_os='`$ECHO "$build_os" | $SED "$delay_single_quote_subst"`' +SED='`$ECHO "$SED" | $SED "$delay_single_quote_subst"`' +Xsed='`$ECHO "$Xsed" | $SED "$delay_single_quote_subst"`' +GREP='`$ECHO "$GREP" | $SED "$delay_single_quote_subst"`' +EGREP='`$ECHO "$EGREP" | $SED "$delay_single_quote_subst"`' +FGREP='`$ECHO "$FGREP" | $SED "$delay_single_quote_subst"`' +LD='`$ECHO "$LD" | $SED "$delay_single_quote_subst"`' +NM='`$ECHO "$NM" | $SED "$delay_single_quote_subst"`' +LN_S='`$ECHO "$LN_S" | $SED "$delay_single_quote_subst"`' +max_cmd_len='`$ECHO "$max_cmd_len" | $SED "$delay_single_quote_subst"`' +ac_objext='`$ECHO "$ac_objext" | $SED "$delay_single_quote_subst"`' +exeext='`$ECHO "$exeext" | $SED "$delay_single_quote_subst"`' +lt_unset='`$ECHO "$lt_unset" | $SED "$delay_single_quote_subst"`' +lt_SP2NL='`$ECHO "$lt_SP2NL" | $SED "$delay_single_quote_subst"`' +lt_NL2SP='`$ECHO "$lt_NL2SP" | $SED "$delay_single_quote_subst"`' +reload_flag='`$ECHO "$reload_flag" | $SED "$delay_single_quote_subst"`' +reload_cmds='`$ECHO "$reload_cmds" | $SED "$delay_single_quote_subst"`' +OBJDUMP='`$ECHO "$OBJDUMP" | $SED "$delay_single_quote_subst"`' +deplibs_check_method='`$ECHO "$deplibs_check_method" | $SED "$delay_single_quote_subst"`' +file_magic_cmd='`$ECHO "$file_magic_cmd" | $SED "$delay_single_quote_subst"`' +AR='`$ECHO "$AR" | $SED "$delay_single_quote_subst"`' +AR_FLAGS='`$ECHO "$AR_FLAGS" | $SED "$delay_single_quote_subst"`' +STRIP='`$ECHO "$STRIP" | $SED "$delay_single_quote_subst"`' +RANLIB='`$ECHO "$RANLIB" | $SED "$delay_single_quote_subst"`' +old_postinstall_cmds='`$ECHO "$old_postinstall_cmds" | $SED "$delay_single_quote_subst"`' +old_postuninstall_cmds='`$ECHO "$old_postuninstall_cmds" | $SED "$delay_single_quote_subst"`' +old_archive_cmds='`$ECHO "$old_archive_cmds" | $SED "$delay_single_quote_subst"`' +lock_old_archive_extraction='`$ECHO "$lock_old_archive_extraction" | $SED "$delay_single_quote_subst"`' +CC='`$ECHO "$CC" | $SED "$delay_single_quote_subst"`' +CFLAGS='`$ECHO "$CFLAGS" | $SED "$delay_single_quote_subst"`' +compiler='`$ECHO "$compiler" | $SED "$delay_single_quote_subst"`' +GCC='`$ECHO "$GCC" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_pipe='`$ECHO "$lt_cv_sys_global_symbol_pipe" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_cdecl='`$ECHO "$lt_cv_sys_global_symbol_to_cdecl" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_c_name_address='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address_lib_prefix" | $SED "$delay_single_quote_subst"`' +objdir='`$ECHO "$objdir" | $SED "$delay_single_quote_subst"`' +MAGIC_CMD='`$ECHO "$MAGIC_CMD" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_no_builtin_flag='`$ECHO "$lt_prog_compiler_no_builtin_flag" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_wl='`$ECHO "$lt_prog_compiler_wl" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_pic='`$ECHO "$lt_prog_compiler_pic" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_static='`$ECHO "$lt_prog_compiler_static" | $SED "$delay_single_quote_subst"`' +lt_cv_prog_compiler_c_o='`$ECHO "$lt_cv_prog_compiler_c_o" | $SED "$delay_single_quote_subst"`' +need_locks='`$ECHO "$need_locks" | $SED "$delay_single_quote_subst"`' +DSYMUTIL='`$ECHO "$DSYMUTIL" | $SED "$delay_single_quote_subst"`' +NMEDIT='`$ECHO "$NMEDIT" | $SED "$delay_single_quote_subst"`' +LIPO='`$ECHO "$LIPO" | $SED "$delay_single_quote_subst"`' +OTOOL='`$ECHO "$OTOOL" | $SED "$delay_single_quote_subst"`' +OTOOL64='`$ECHO "$OTOOL64" | $SED "$delay_single_quote_subst"`' +libext='`$ECHO "$libext" | $SED "$delay_single_quote_subst"`' +shrext_cmds='`$ECHO "$shrext_cmds" | $SED "$delay_single_quote_subst"`' +extract_expsyms_cmds='`$ECHO "$extract_expsyms_cmds" | $SED "$delay_single_quote_subst"`' +archive_cmds_need_lc='`$ECHO "$archive_cmds_need_lc" | $SED "$delay_single_quote_subst"`' +enable_shared_with_static_runtimes='`$ECHO "$enable_shared_with_static_runtimes" | $SED "$delay_single_quote_subst"`' +export_dynamic_flag_spec='`$ECHO "$export_dynamic_flag_spec" | $SED "$delay_single_quote_subst"`' +whole_archive_flag_spec='`$ECHO "$whole_archive_flag_spec" | $SED "$delay_single_quote_subst"`' +compiler_needs_object='`$ECHO "$compiler_needs_object" | $SED "$delay_single_quote_subst"`' +old_archive_from_new_cmds='`$ECHO "$old_archive_from_new_cmds" | $SED "$delay_single_quote_subst"`' +old_archive_from_expsyms_cmds='`$ECHO "$old_archive_from_expsyms_cmds" | $SED "$delay_single_quote_subst"`' +archive_cmds='`$ECHO "$archive_cmds" | $SED "$delay_single_quote_subst"`' +archive_expsym_cmds='`$ECHO "$archive_expsym_cmds" | $SED "$delay_single_quote_subst"`' +module_cmds='`$ECHO "$module_cmds" | $SED "$delay_single_quote_subst"`' +module_expsym_cmds='`$ECHO "$module_expsym_cmds" | $SED "$delay_single_quote_subst"`' +with_gnu_ld='`$ECHO "$with_gnu_ld" | $SED "$delay_single_quote_subst"`' +allow_undefined_flag='`$ECHO "$allow_undefined_flag" | $SED "$delay_single_quote_subst"`' +no_undefined_flag='`$ECHO "$no_undefined_flag" | $SED "$delay_single_quote_subst"`' +hardcode_libdir_flag_spec='`$ECHO "$hardcode_libdir_flag_spec" | $SED "$delay_single_quote_subst"`' +hardcode_libdir_flag_spec_ld='`$ECHO "$hardcode_libdir_flag_spec_ld" | $SED "$delay_single_quote_subst"`' +hardcode_libdir_separator='`$ECHO "$hardcode_libdir_separator" | $SED "$delay_single_quote_subst"`' +hardcode_direct='`$ECHO "$hardcode_direct" | $SED "$delay_single_quote_subst"`' +hardcode_direct_absolute='`$ECHO "$hardcode_direct_absolute" | $SED "$delay_single_quote_subst"`' +hardcode_minus_L='`$ECHO "$hardcode_minus_L" | $SED "$delay_single_quote_subst"`' +hardcode_shlibpath_var='`$ECHO "$hardcode_shlibpath_var" | $SED "$delay_single_quote_subst"`' +hardcode_automatic='`$ECHO "$hardcode_automatic" | $SED "$delay_single_quote_subst"`' +inherit_rpath='`$ECHO "$inherit_rpath" | $SED "$delay_single_quote_subst"`' +link_all_deplibs='`$ECHO "$link_all_deplibs" | $SED "$delay_single_quote_subst"`' +fix_srcfile_path='`$ECHO "$fix_srcfile_path" | $SED "$delay_single_quote_subst"`' +always_export_symbols='`$ECHO "$always_export_symbols" | $SED "$delay_single_quote_subst"`' +export_symbols_cmds='`$ECHO "$export_symbols_cmds" | $SED "$delay_single_quote_subst"`' +exclude_expsyms='`$ECHO "$exclude_expsyms" | $SED "$delay_single_quote_subst"`' +include_expsyms='`$ECHO "$include_expsyms" | $SED "$delay_single_quote_subst"`' +prelink_cmds='`$ECHO "$prelink_cmds" | $SED "$delay_single_quote_subst"`' +file_list_spec='`$ECHO "$file_list_spec" | $SED "$delay_single_quote_subst"`' +variables_saved_for_relink='`$ECHO "$variables_saved_for_relink" | $SED "$delay_single_quote_subst"`' +need_lib_prefix='`$ECHO "$need_lib_prefix" | $SED "$delay_single_quote_subst"`' +need_version='`$ECHO "$need_version" | $SED "$delay_single_quote_subst"`' +version_type='`$ECHO "$version_type" | $SED "$delay_single_quote_subst"`' +runpath_var='`$ECHO "$runpath_var" | $SED "$delay_single_quote_subst"`' +shlibpath_var='`$ECHO "$shlibpath_var" | $SED "$delay_single_quote_subst"`' +shlibpath_overrides_runpath='`$ECHO "$shlibpath_overrides_runpath" | $SED "$delay_single_quote_subst"`' +libname_spec='`$ECHO "$libname_spec" | $SED "$delay_single_quote_subst"`' +library_names_spec='`$ECHO "$library_names_spec" | $SED "$delay_single_quote_subst"`' +soname_spec='`$ECHO "$soname_spec" | $SED "$delay_single_quote_subst"`' +install_override_mode='`$ECHO "$install_override_mode" | $SED "$delay_single_quote_subst"`' +postinstall_cmds='`$ECHO "$postinstall_cmds" | $SED "$delay_single_quote_subst"`' +postuninstall_cmds='`$ECHO "$postuninstall_cmds" | $SED "$delay_single_quote_subst"`' +finish_cmds='`$ECHO "$finish_cmds" | $SED "$delay_single_quote_subst"`' +finish_eval='`$ECHO "$finish_eval" | $SED "$delay_single_quote_subst"`' +hardcode_into_libs='`$ECHO "$hardcode_into_libs" | $SED "$delay_single_quote_subst"`' +sys_lib_search_path_spec='`$ECHO "$sys_lib_search_path_spec" | $SED "$delay_single_quote_subst"`' +sys_lib_dlsearch_path_spec='`$ECHO "$sys_lib_dlsearch_path_spec" | $SED "$delay_single_quote_subst"`' +hardcode_action='`$ECHO "$hardcode_action" | $SED "$delay_single_quote_subst"`' +enable_dlopen='`$ECHO "$enable_dlopen" | $SED "$delay_single_quote_subst"`' +enable_dlopen_self='`$ECHO "$enable_dlopen_self" | $SED "$delay_single_quote_subst"`' +enable_dlopen_self_static='`$ECHO "$enable_dlopen_self_static" | $SED "$delay_single_quote_subst"`' +old_striplib='`$ECHO "$old_striplib" | $SED "$delay_single_quote_subst"`' +striplib='`$ECHO "$striplib" | $SED "$delay_single_quote_subst"`' +compiler_lib_search_dirs='`$ECHO "$compiler_lib_search_dirs" | $SED "$delay_single_quote_subst"`' +predep_objects='`$ECHO "$predep_objects" | $SED "$delay_single_quote_subst"`' +postdep_objects='`$ECHO "$postdep_objects" | $SED "$delay_single_quote_subst"`' +predeps='`$ECHO "$predeps" | $SED "$delay_single_quote_subst"`' +postdeps='`$ECHO "$postdeps" | $SED "$delay_single_quote_subst"`' +compiler_lib_search_path='`$ECHO "$compiler_lib_search_path" | $SED "$delay_single_quote_subst"`' +LD_CXX='`$ECHO "$LD_CXX" | $SED "$delay_single_quote_subst"`' +reload_flag_CXX='`$ECHO "$reload_flag_CXX" | $SED "$delay_single_quote_subst"`' +reload_cmds_CXX='`$ECHO "$reload_cmds_CXX" | $SED "$delay_single_quote_subst"`' +old_archive_cmds_CXX='`$ECHO "$old_archive_cmds_CXX" | $SED "$delay_single_quote_subst"`' +compiler_CXX='`$ECHO "$compiler_CXX" | $SED "$delay_single_quote_subst"`' +GCC_CXX='`$ECHO "$GCC_CXX" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_no_builtin_flag_CXX='`$ECHO "$lt_prog_compiler_no_builtin_flag_CXX" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_wl_CXX='`$ECHO "$lt_prog_compiler_wl_CXX" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_pic_CXX='`$ECHO "$lt_prog_compiler_pic_CXX" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_static_CXX='`$ECHO "$lt_prog_compiler_static_CXX" | $SED "$delay_single_quote_subst"`' +lt_cv_prog_compiler_c_o_CXX='`$ECHO "$lt_cv_prog_compiler_c_o_CXX" | $SED "$delay_single_quote_subst"`' +archive_cmds_need_lc_CXX='`$ECHO "$archive_cmds_need_lc_CXX" | $SED "$delay_single_quote_subst"`' +enable_shared_with_static_runtimes_CXX='`$ECHO "$enable_shared_with_static_runtimes_CXX" | $SED "$delay_single_quote_subst"`' +export_dynamic_flag_spec_CXX='`$ECHO "$export_dynamic_flag_spec_CXX" | $SED "$delay_single_quote_subst"`' +whole_archive_flag_spec_CXX='`$ECHO "$whole_archive_flag_spec_CXX" | $SED "$delay_single_quote_subst"`' +compiler_needs_object_CXX='`$ECHO "$compiler_needs_object_CXX" | $SED "$delay_single_quote_subst"`' +old_archive_from_new_cmds_CXX='`$ECHO "$old_archive_from_new_cmds_CXX" | $SED "$delay_single_quote_subst"`' +old_archive_from_expsyms_cmds_CXX='`$ECHO "$old_archive_from_expsyms_cmds_CXX" | $SED "$delay_single_quote_subst"`' +archive_cmds_CXX='`$ECHO "$archive_cmds_CXX" | $SED "$delay_single_quote_subst"`' +archive_expsym_cmds_CXX='`$ECHO "$archive_expsym_cmds_CXX" | $SED "$delay_single_quote_subst"`' +module_cmds_CXX='`$ECHO "$module_cmds_CXX" | $SED "$delay_single_quote_subst"`' +module_expsym_cmds_CXX='`$ECHO "$module_expsym_cmds_CXX" | $SED "$delay_single_quote_subst"`' +with_gnu_ld_CXX='`$ECHO "$with_gnu_ld_CXX" | $SED "$delay_single_quote_subst"`' +allow_undefined_flag_CXX='`$ECHO "$allow_undefined_flag_CXX" | $SED "$delay_single_quote_subst"`' +no_undefined_flag_CXX='`$ECHO "$no_undefined_flag_CXX" | $SED "$delay_single_quote_subst"`' +hardcode_libdir_flag_spec_CXX='`$ECHO "$hardcode_libdir_flag_spec_CXX" | $SED "$delay_single_quote_subst"`' +hardcode_libdir_flag_spec_ld_CXX='`$ECHO "$hardcode_libdir_flag_spec_ld_CXX" | $SED "$delay_single_quote_subst"`' +hardcode_libdir_separator_CXX='`$ECHO "$hardcode_libdir_separator_CXX" | $SED "$delay_single_quote_subst"`' +hardcode_direct_CXX='`$ECHO "$hardcode_direct_CXX" | $SED "$delay_single_quote_subst"`' +hardcode_direct_absolute_CXX='`$ECHO "$hardcode_direct_absolute_CXX" | $SED "$delay_single_quote_subst"`' +hardcode_minus_L_CXX='`$ECHO "$hardcode_minus_L_CXX" | $SED "$delay_single_quote_subst"`' +hardcode_shlibpath_var_CXX='`$ECHO "$hardcode_shlibpath_var_CXX" | $SED "$delay_single_quote_subst"`' +hardcode_automatic_CXX='`$ECHO "$hardcode_automatic_CXX" | $SED "$delay_single_quote_subst"`' +inherit_rpath_CXX='`$ECHO "$inherit_rpath_CXX" | $SED "$delay_single_quote_subst"`' +link_all_deplibs_CXX='`$ECHO "$link_all_deplibs_CXX" | $SED "$delay_single_quote_subst"`' +fix_srcfile_path_CXX='`$ECHO "$fix_srcfile_path_CXX" | $SED "$delay_single_quote_subst"`' +always_export_symbols_CXX='`$ECHO "$always_export_symbols_CXX" | $SED "$delay_single_quote_subst"`' +export_symbols_cmds_CXX='`$ECHO "$export_symbols_cmds_CXX" | $SED "$delay_single_quote_subst"`' +exclude_expsyms_CXX='`$ECHO "$exclude_expsyms_CXX" | $SED "$delay_single_quote_subst"`' +include_expsyms_CXX='`$ECHO "$include_expsyms_CXX" | $SED "$delay_single_quote_subst"`' +prelink_cmds_CXX='`$ECHO "$prelink_cmds_CXX" | $SED "$delay_single_quote_subst"`' +file_list_spec_CXX='`$ECHO "$file_list_spec_CXX" | $SED "$delay_single_quote_subst"`' +hardcode_action_CXX='`$ECHO "$hardcode_action_CXX" | $SED "$delay_single_quote_subst"`' +compiler_lib_search_dirs_CXX='`$ECHO "$compiler_lib_search_dirs_CXX" | $SED "$delay_single_quote_subst"`' +predep_objects_CXX='`$ECHO "$predep_objects_CXX" | $SED "$delay_single_quote_subst"`' +postdep_objects_CXX='`$ECHO "$postdep_objects_CXX" | $SED "$delay_single_quote_subst"`' +predeps_CXX='`$ECHO "$predeps_CXX" | $SED "$delay_single_quote_subst"`' +postdeps_CXX='`$ECHO "$postdeps_CXX" | $SED "$delay_single_quote_subst"`' +compiler_lib_search_path_CXX='`$ECHO "$compiler_lib_search_path_CXX" | $SED "$delay_single_quote_subst"`' + +LTCC='$LTCC' +LTCFLAGS='$LTCFLAGS' +compiler='$compiler_DEFAULT' + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +\$1 +_LTECHO_EOF' +} + +# Quote evaled strings. +for var in SHELL \ +ECHO \ +SED \ +GREP \ +EGREP \ +FGREP \ +LD \ +NM \ +LN_S \ +lt_SP2NL \ +lt_NL2SP \ +reload_flag \ +OBJDUMP \ +deplibs_check_method \ +file_magic_cmd \ +AR \ +AR_FLAGS \ +STRIP \ +RANLIB \ +CC \ +CFLAGS \ +compiler \ +lt_cv_sys_global_symbol_pipe \ +lt_cv_sys_global_symbol_to_cdecl \ +lt_cv_sys_global_symbol_to_c_name_address \ +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix \ +lt_prog_compiler_no_builtin_flag \ +lt_prog_compiler_wl \ +lt_prog_compiler_pic \ +lt_prog_compiler_static \ +lt_cv_prog_compiler_c_o \ +need_locks \ +DSYMUTIL \ +NMEDIT \ +LIPO \ +OTOOL \ +OTOOL64 \ +shrext_cmds \ +export_dynamic_flag_spec \ +whole_archive_flag_spec \ +compiler_needs_object \ +with_gnu_ld \ +allow_undefined_flag \ +no_undefined_flag \ +hardcode_libdir_flag_spec \ +hardcode_libdir_flag_spec_ld \ +hardcode_libdir_separator \ +fix_srcfile_path \ +exclude_expsyms \ +include_expsyms \ +file_list_spec \ +variables_saved_for_relink \ +libname_spec \ +library_names_spec \ +soname_spec \ +install_override_mode \ +finish_eval \ +old_striplib \ +striplib \ +compiler_lib_search_dirs \ +predep_objects \ +postdep_objects \ +predeps \ +postdeps \ +compiler_lib_search_path \ +LD_CXX \ +reload_flag_CXX \ +compiler_CXX \ +lt_prog_compiler_no_builtin_flag_CXX \ +lt_prog_compiler_wl_CXX \ +lt_prog_compiler_pic_CXX \ +lt_prog_compiler_static_CXX \ +lt_cv_prog_compiler_c_o_CXX \ +export_dynamic_flag_spec_CXX \ +whole_archive_flag_spec_CXX \ +compiler_needs_object_CXX \ +with_gnu_ld_CXX \ +allow_undefined_flag_CXX \ +no_undefined_flag_CXX \ +hardcode_libdir_flag_spec_CXX \ +hardcode_libdir_flag_spec_ld_CXX \ +hardcode_libdir_separator_CXX \ +fix_srcfile_path_CXX \ +exclude_expsyms_CXX \ +include_expsyms_CXX \ +file_list_spec_CXX \ +compiler_lib_search_dirs_CXX \ +predep_objects_CXX \ +postdep_objects_CXX \ +predeps_CXX \ +postdeps_CXX \ +compiler_lib_search_path_CXX; do + case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in + *[\\\\\\\`\\"\\\$]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +# Double-quote double-evaled strings. +for var in reload_cmds \ +old_postinstall_cmds \ +old_postuninstall_cmds \ +old_archive_cmds \ +extract_expsyms_cmds \ +old_archive_from_new_cmds \ +old_archive_from_expsyms_cmds \ +archive_cmds \ +archive_expsym_cmds \ +module_cmds \ +module_expsym_cmds \ +export_symbols_cmds \ +prelink_cmds \ +postinstall_cmds \ +postuninstall_cmds \ +finish_cmds \ +sys_lib_search_path_spec \ +sys_lib_dlsearch_path_spec \ +reload_cmds_CXX \ +old_archive_cmds_CXX \ +old_archive_from_new_cmds_CXX \ +old_archive_from_expsyms_cmds_CXX \ +archive_cmds_CXX \ +archive_expsym_cmds_CXX \ +module_cmds_CXX \ +module_expsym_cmds_CXX \ +export_symbols_cmds_CXX \ +prelink_cmds_CXX; do + case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in + *[\\\\\\\`\\"\\\$]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +ac_aux_dir='$ac_aux_dir' +xsi_shell='$xsi_shell' +lt_shell_append='$lt_shell_append' + +# See if we are running on zsh, and set the options which allow our +# commands through without removal of \ escapes INIT. +if test -n "\${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST +fi + + + PACKAGE='$PACKAGE' + VERSION='$VERSION' + TIMESTAMP='$TIMESTAMP' + RM='$RM' + ofile='$ofile' + + + + + + +GCC="$GCC" +CC="$CC" +acx_cv_header_stdint="$acx_cv_header_stdint" +acx_cv_type_int8_t="$acx_cv_type_int8_t" +acx_cv_type_int16_t="$acx_cv_type_int16_t" +acx_cv_type_int32_t="$acx_cv_type_int32_t" +acx_cv_type_int64_t="$acx_cv_type_int64_t" +acx_cv_type_intptr_t="$acx_cv_type_intptr_t" +ac_cv_type_uintmax_t="$ac_cv_type_uintmax_t" +ac_cv_type_uintptr_t="$ac_cv_type_uintptr_t" +ac_cv_type_uint64_t="$ac_cv_type_uint64_t" +ac_cv_type_u_int64_t="$ac_cv_type_u_int64_t" +ac_cv_type_u_int32_t="$ac_cv_type_u_int32_t" +ac_cv_type_int_least32_t="$ac_cv_type_int_least32_t" +ac_cv_type_int_fast32_t="$ac_cv_type_int_fast32_t" +ac_cv_sizeof_void_p="$ac_cv_sizeof_void_p" + + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + +# Handling of arguments. +for ac_config_target in $ac_config_targets +do + case $ac_config_target in + "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; + "default-1") CONFIG_COMMANDS="$CONFIG_COMMANDS default-1" ;; + "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; + "libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;; + "gstdint.h") CONFIG_COMMANDS="$CONFIG_COMMANDS gstdint.h" ;; + "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; + "testsuite/Makefile") CONFIG_FILES="$CONFIG_FILES testsuite/Makefile" ;; + "libitm.spec") CONFIG_FILES="$CONFIG_FILES libitm.spec" ;; + + *) as_fn_error "invalid argument: \`$ac_config_target'" "$LINENO" 5;; + esac +done + + +# If the user did not use the arguments to specify the items to instantiate, +# then the envvar interface is used. Set only those that are not. +# We use the long form for the default assignment because of an extremely +# bizarre bug on SunOS 4.1.3. +if $ac_need_defaults; then + test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files + test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers + test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands +fi + +# Have a temporary directory for convenience. Make it in the build tree +# simply because there is no reason against having it here, and in addition, +# creating and moving files from /tmp can sometimes cause problems. +# Hook for its removal unless debugging. +# Note that there is a small window in which the directory will not be cleaned: +# after its creation but before its name has been assigned to `$tmp'. +$debug || +{ + tmp= + trap 'exit_status=$? + { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status +' 0 + trap 'as_fn_exit 1' 1 2 13 15 +} +# Create a (secure) tmp directory for tmp files. + +{ + tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && + test -n "$tmp" && test -d "$tmp" +} || +{ + tmp=./conf$$-$RANDOM + (umask 077 && mkdir "$tmp") +} || as_fn_error "cannot create a temporary directory in ." "$LINENO" 5 + +# Set up the scripts for CONFIG_FILES section. +# No need to generate them if there are no CONFIG_FILES. +# This happens for instance with `./config.status config.h'. +if test -n "$CONFIG_FILES"; then + + +ac_cr=`echo X | tr X '\015'` +# On cygwin, bash can eat \r inside `` if the user requested igncr. +# But we know of no other shell where ac_cr would be empty at this +# point, so we can use a bashism as a fallback. +if test "x$ac_cr" = x; then + eval ac_cr=\$\'\\r\' +fi +ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' </dev/null 2>/dev/null` +if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then + ac_cs_awk_cr='\r' +else + ac_cs_awk_cr=$ac_cr +fi + +echo 'BEGIN {' >"$tmp/subs1.awk" && +_ACEOF + + +{ + echo "cat >conf$$subs.awk <<_ACEOF" && + echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && + echo "_ACEOF" +} >conf$$subs.sh || + as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5 +ac_delim_num=`echo "$ac_subst_vars" | grep -c '$'` +ac_delim='%!_!# ' +for ac_last_try in false false false false false :; do + . ./conf$$subs.sh || + as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5 + + ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` + if test $ac_delim_n = $ac_delim_num; then + break + elif $ac_last_try; then + as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done +rm -f conf$$subs.sh + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +cat >>"\$tmp/subs1.awk" <<\\_ACAWK && +_ACEOF +sed -n ' +h +s/^/S["/; s/!.*/"]=/ +p +g +s/^[^!]*!// +:repl +t repl +s/'"$ac_delim"'$// +t delim +:nl +h +s/\(.\{148\}\).*/\1/ +t more1 +s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ +p +n +b repl +:more1 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t nl +:delim +h +s/\(.\{148\}\).*/\1/ +t more2 +s/["\\]/\\&/g; s/^/"/; s/$/"/ +p +b +:more2 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t delim +' <conf$$subs.awk | sed ' +/^[^""]/{ + N + s/\n// +} +' >>$CONFIG_STATUS || ac_write_fail=1 +rm -f conf$$subs.awk +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +_ACAWK +cat >>"\$tmp/subs1.awk" <<_ACAWK && + for (key in S) S_is_set[key] = 1 + FS = "" + +} +{ + line = $ 0 + nfields = split(line, field, "@") + substed = 0 + len = length(field[1]) + for (i = 2; i < nfields; i++) { + key = field[i] + keylen = length(key) + if (S_is_set[key]) { + value = S[key] + line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) + len += length(value) + length(field[++i]) + substed = 1 + } else + len += 1 + keylen + } + + print line +} + +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then + sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" +else + cat +fi < "$tmp/subs1.awk" > "$tmp/subs.awk" \ + || as_fn_error "could not setup config files machinery" "$LINENO" 5 +_ACEOF + +# VPATH may cause trouble with some makes, so we remove $(srcdir), +# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and +# trailing colons and then remove the whole line if VPATH becomes empty +# (actually we leave an empty line to preserve line numbers). +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=/{ +s/:*\$(srcdir):*/:/ +s/:*\${srcdir}:*/:/ +s/:*@srcdir@:*/:/ +s/^\([^=]*=[ ]*\):*/\1/ +s/:*$// +s/^[^=]*=[ ]*$// +}' +fi + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +fi # test -n "$CONFIG_FILES" + +# Set up the scripts for CONFIG_HEADERS section. +# No need to generate them if there are no CONFIG_HEADERS. +# This happens for instance with `./config.status Makefile'. +if test -n "$CONFIG_HEADERS"; then +cat >"$tmp/defines.awk" <<\_ACAWK || +BEGIN { +_ACEOF + +# Transform confdefs.h into an awk script `defines.awk', embedded as +# here-document in config.status, that substitutes the proper values into +# config.h.in to produce config.h. + +# Create a delimiter string that does not exist in confdefs.h, to ease +# handling of long lines. +ac_delim='%!_!# ' +for ac_last_try in false false :; do + ac_t=`sed -n "/$ac_delim/p" confdefs.h` + if test -z "$ac_t"; then + break + elif $ac_last_try; then + as_fn_error "could not make $CONFIG_HEADERS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done + +# For the awk script, D is an array of macro values keyed by name, +# likewise P contains macro parameters if any. Preserve backslash +# newline sequences. + +ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* +sed -n ' +s/.\{148\}/&'"$ac_delim"'/g +t rset +:rset +s/^[ ]*#[ ]*define[ ][ ]*/ / +t def +d +:def +s/\\$// +t bsnl +s/["\\]/\\&/g +s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ +D["\1"]=" \3"/p +s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p +d +:bsnl +s/["\\]/\\&/g +s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ +D["\1"]=" \3\\\\\\n"\\/p +t cont +s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p +t cont +d +:cont +n +s/.\{148\}/&'"$ac_delim"'/g +t clear +:clear +s/\\$// +t bsnlc +s/["\\]/\\&/g; s/^/"/; s/$/"/p +d +:bsnlc +s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p +b cont +' <confdefs.h | sed ' +s/'"$ac_delim"'/"\\\ +"/g' >>$CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + for (key in D) D_is_set[key] = 1 + FS = "" +} +/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { + line = \$ 0 + split(line, arg, " ") + if (arg[1] == "#") { + defundef = arg[2] + mac1 = arg[3] + } else { + defundef = substr(arg[1], 2) + mac1 = arg[2] + } + split(mac1, mac2, "(") #) + macro = mac2[1] + prefix = substr(line, 1, index(line, defundef) - 1) + if (D_is_set[macro]) { + # Preserve the white space surrounding the "#". + print prefix "define", macro P[macro] D[macro] + next + } else { + # Replace #undef with comments. This is necessary, for example, + # in the case of _POSIX_SOURCE, which is predefined and required + # on some systems where configure will not decide to define it. + if (defundef == "undef") { + print "/*", prefix defundef, macro, "*/" + next + } + } +} +{ print } +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + as_fn_error "could not setup config headers machinery" "$LINENO" 5 +fi # test -n "$CONFIG_HEADERS" + + +eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS :C $CONFIG_COMMANDS" +shift +for ac_tag +do + case $ac_tag in + :[FHLC]) ac_mode=$ac_tag; continue;; + esac + case $ac_mode$ac_tag in + :[FHL]*:*);; + :L* | :C*:*) as_fn_error "invalid tag \`$ac_tag'" "$LINENO" 5;; + :[FH]-) ac_tag=-:-;; + :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; + esac + ac_save_IFS=$IFS + IFS=: + set x $ac_tag + IFS=$ac_save_IFS + shift + ac_file=$1 + shift + + case $ac_mode in + :L) ac_source=$1;; + :[FH]) + ac_file_inputs= + for ac_f + do + case $ac_f in + -) ac_f="$tmp/stdin";; + *) # Look for the file first in the build tree, then in the source tree + # (if the path is not absolute). The absolute path cannot be DOS-style, + # because $ac_f cannot contain `:'. + test -f "$ac_f" || + case $ac_f in + [\\/$]*) false;; + *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; + esac || + as_fn_error "cannot find input file: \`$ac_f'" "$LINENO" 5;; + esac + case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac + as_fn_append ac_file_inputs " '$ac_f'" + done + + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + configure_input='Generated from '` + $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' + `' by configure.' + if test x"$ac_file" != x-; then + configure_input="$ac_file. $configure_input" + { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 +$as_echo "$as_me: creating $ac_file" >&6;} + fi + # Neutralize special characters interpreted by sed in replacement strings. + case $configure_input in #( + *\&* | *\|* | *\\* ) + ac_sed_conf_input=`$as_echo "$configure_input" | + sed 's/[\\\\&|]/\\\\&/g'`;; #( + *) ac_sed_conf_input=$configure_input;; + esac + + case $ac_tag in + *:-:* | *:-) cat >"$tmp/stdin" \ + || as_fn_error "could not create $ac_file" "$LINENO" 5 ;; + esac + ;; + esac + + ac_dir=`$as_dirname -- "$ac_file" || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + as_dir="$ac_dir"; as_fn_mkdir_p + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + + case $ac_mode in + :F) + # + # CONFIG_FILE + # + + case $INSTALL in + [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; + *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; + esac + ac_MKDIR_P=$MKDIR_P + case $MKDIR_P in + [\\/$]* | ?:[\\/]* ) ;; + */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;; + esac +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# If the template does not know about datarootdir, expand it. +# FIXME: This hack should be removed a few years after 2.60. +ac_datarootdir_hack=; ac_datarootdir_seen= +ac_sed_dataroot=' +/datarootdir/ { + p + q +} +/@datadir@/p +/@docdir@/p +/@infodir@/p +/@localedir@/p +/@mandir@/p' +case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in +*datarootdir*) ac_datarootdir_seen=yes;; +*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 +$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + ac_datarootdir_hack=' + s&@datadir@&$datadir&g + s&@docdir@&$docdir&g + s&@infodir@&$infodir&g + s&@localedir@&$localedir&g + s&@mandir@&$mandir&g + s&\\\${datarootdir}&$datarootdir&g' ;; +esac +_ACEOF + +# Neutralize VPATH when `$srcdir' = `.'. +# Shell code in configure.ac might set extrasub. +# FIXME: do we really want to maintain this feature? +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_sed_extra="$ac_vpsub +$extrasub +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +:t +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +s|@configure_input@|$ac_sed_conf_input|;t t +s&@top_builddir@&$ac_top_builddir_sub&;t t +s&@top_build_prefix@&$ac_top_build_prefix&;t t +s&@srcdir@&$ac_srcdir&;t t +s&@abs_srcdir@&$ac_abs_srcdir&;t t +s&@top_srcdir@&$ac_top_srcdir&;t t +s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t +s&@builddir@&$ac_builddir&;t t +s&@abs_builddir@&$ac_abs_builddir&;t t +s&@abs_top_builddir@&$ac_abs_top_builddir&;t t +s&@INSTALL@&$ac_INSTALL&;t t +s&@MKDIR_P@&$ac_MKDIR_P&;t t +$ac_datarootdir_hack +" +eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$tmp/subs.awk" >$tmp/out \ + || as_fn_error "could not create $ac_file" "$LINENO" 5 + +test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && + { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } && + { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } && + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined." >&5 +$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined." >&2;} + + rm -f "$tmp/stdin" + case $ac_file in + -) cat "$tmp/out" && rm -f "$tmp/out";; + *) rm -f "$ac_file" && mv "$tmp/out" "$ac_file";; + esac \ + || as_fn_error "could not create $ac_file" "$LINENO" 5 + ;; + :H) + # + # CONFIG_HEADER + # + if test x"$ac_file" != x-; then + { + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$tmp/defines.awk"' "$ac_file_inputs" + } >"$tmp/config.h" \ + || as_fn_error "could not create $ac_file" "$LINENO" 5 + if diff "$ac_file" "$tmp/config.h" >/dev/null 2>&1; then + { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 +$as_echo "$as_me: $ac_file is unchanged" >&6;} + else + rm -f "$ac_file" + mv "$tmp/config.h" "$ac_file" \ + || as_fn_error "could not create $ac_file" "$LINENO" 5 + fi + else + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$tmp/defines.awk"' "$ac_file_inputs" \ + || as_fn_error "could not create -" "$LINENO" 5 + fi +# Compute "$ac_file"'s index in $config_headers. +_am_arg="$ac_file" +_am_stamp_count=1 +for _am_header in $config_headers :; do + case $_am_header in + $_am_arg | $_am_arg:* ) + break ;; + * ) + _am_stamp_count=`expr $_am_stamp_count + 1` ;; + esac +done +echo "timestamp for $_am_arg" >`$as_dirname -- "$_am_arg" || +$as_expr X"$_am_arg" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$_am_arg" : 'X\(//\)[^/]' \| \ + X"$_am_arg" : 'X\(//\)$' \| \ + X"$_am_arg" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$_am_arg" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'`/stamp-h$_am_stamp_count + ;; + + :C) { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5 +$as_echo "$as_me: executing $ac_file commands" >&6;} + ;; + esac + + + case $ac_file$ac_mode in + "default-1":C) +# Only add multilib support code if we just rebuilt the top-level +# Makefile. +case " $CONFIG_FILES " in + *" Makefile "*) + ac_file=Makefile . ${multi_basedir}/config-ml.in + ;; +esac ;; + "depfiles":C) test x"$AMDEP_TRUE" != x"" || { + # Autoconf 2.62 quotes --file arguments for eval, but not when files + # are listed without --file. Let's play safe and only enable the eval + # if we detect the quoting. + case $CONFIG_FILES in + *\'*) eval set x "$CONFIG_FILES" ;; + *) set x $CONFIG_FILES ;; + esac + shift + for mf + do + # Strip MF so we end up with the name of the file. + mf=`echo "$mf" | sed -e 's/:.*$//'` + # Check whether this is an Automake generated Makefile or not. + # We used to match only the files named `Makefile.in', but + # some people rename them; so instead we look at the file content. + # Grep'ing the first line is not enough: some people post-process + # each Makefile.in and add a new line on top of each file to say so. + # Grep'ing the whole file is not good either: AIX grep has a line + # limit of 2048, but all sed's we know have understand at least 4000. + if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then + dirpart=`$as_dirname -- "$mf" || +$as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$mf" : 'X\(//\)[^/]' \| \ + X"$mf" : 'X\(//\)$' \| \ + X"$mf" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$mf" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + else + continue + fi + # Extract the definition of DEPDIR, am__include, and am__quote + # from the Makefile without running `make'. + DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` + test -z "$DEPDIR" && continue + am__include=`sed -n 's/^am__include = //p' < "$mf"` + test -z "am__include" && continue + am__quote=`sed -n 's/^am__quote = //p' < "$mf"` + # When using ansi2knr, U may be empty or an underscore; expand it + U=`sed -n 's/^U = //p' < "$mf"` + # Find all dependency output files, they are included files with + # $(DEPDIR) in their names. We invoke sed twice because it is the + # simplest approach to changing $(DEPDIR) to its actual value in the + # expansion. + for file in `sed -n " + s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ + sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do + # Make sure the directory exists. + test -f "$dirpart/$file" && continue + fdir=`$as_dirname -- "$file" || +$as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$file" : 'X\(//\)[^/]' \| \ + X"$file" : 'X\(//\)$' \| \ + X"$file" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + as_dir=$dirpart/$fdir; as_fn_mkdir_p + # echo "creating $dirpart/$file" + echo '# dummy' > "$dirpart/$file" + done + done +} + ;; + "libtool":C) + + # See if we are running on zsh, and set the options which allow our + # commands through without removal of \ escapes. + if test -n "${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST + fi + + cfgfile="${ofile}T" + trap "$RM \"$cfgfile\"; exit 1" 1 2 15 + $RM "$cfgfile" + + cat <<_LT_EOF >> "$cfgfile" +#! $SHELL + +# `$ECHO "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services. +# Generated automatically by $as_me ($PACKAGE$TIMESTAMP) $VERSION +# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: +# NOTE: Changes made to this file will be lost: look at ltmain.sh. +# +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, +# 2006, 2007, 2008, 2009 Free Software Foundation, Inc. +# Written by Gordon Matzigkeit, 1996 +# +# This file is part of GNU Libtool. +# +# GNU Libtool is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# As a special exception to the GNU General Public License, +# if you distribute this file as part of a program or library that +# is built using GNU Libtool, you may include this file under the +# same distribution terms that you use for the rest of that program. +# +# GNU Libtool is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Libtool; see the file COPYING. If not, a copy +# can be downloaded from http://www.gnu.org/licenses/gpl.html, or +# obtained by writing to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + +# The names of the tagged configurations supported by this script. +available_tags="CXX " + +# ### BEGIN LIBTOOL CONFIG + +# Which release of libtool.m4 was used? +macro_version=$macro_version +macro_revision=$macro_revision + +# Whether or not to build shared libraries. +build_libtool_libs=$enable_shared + +# Whether or not to build static libraries. +build_old_libs=$enable_static + +# What type of objects to build. +pic_mode=$pic_mode + +# Whether or not to optimize for fast installation. +fast_install=$enable_fast_install + +# Shell to use when invoking shell scripts. +SHELL=$lt_SHELL + +# An echo program that protects backslashes. +ECHO=$lt_ECHO + +# The host system. +host_alias=$host_alias +host=$host +host_os=$host_os + +# The build system. +build_alias=$build_alias +build=$build +build_os=$build_os + +# A sed program that does not truncate output. +SED=$lt_SED + +# Sed that helps us avoid accidentally triggering echo(1) options like -n. +Xsed="\$SED -e 1s/^X//" + +# A grep program that handles long lines. +GREP=$lt_GREP + +# An ERE matcher. +EGREP=$lt_EGREP + +# A literal string matcher. +FGREP=$lt_FGREP + +# A BSD- or MS-compatible name lister. +NM=$lt_NM + +# Whether we need soft or hard links. +LN_S=$lt_LN_S + +# What is the maximum length of a command? +max_cmd_len=$max_cmd_len + +# Object file suffix (normally "o"). +objext=$ac_objext + +# Executable file suffix (normally ""). +exeext=$exeext + +# whether the shell understands "unset". +lt_unset=$lt_unset + +# turn spaces into newlines. +SP2NL=$lt_lt_SP2NL + +# turn newlines into spaces. +NL2SP=$lt_lt_NL2SP + +# An object symbol dumper. +OBJDUMP=$lt_OBJDUMP + +# Method to check whether dependent libraries are shared objects. +deplibs_check_method=$lt_deplibs_check_method + +# Command to use when deplibs_check_method == "file_magic". +file_magic_cmd=$lt_file_magic_cmd + +# The archiver. +AR=$lt_AR +AR_FLAGS=$lt_AR_FLAGS + +# A symbol stripping program. +STRIP=$lt_STRIP + +# Commands used to install an old-style archive. +RANLIB=$lt_RANLIB +old_postinstall_cmds=$lt_old_postinstall_cmds +old_postuninstall_cmds=$lt_old_postuninstall_cmds + +# Whether to use a lock for old archive extraction. +lock_old_archive_extraction=$lock_old_archive_extraction + +# A C compiler. +LTCC=$lt_CC + +# LTCC compiler flags. +LTCFLAGS=$lt_CFLAGS + +# Take the output of nm and produce a listing of raw symbols and C names. +global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe + +# Transform the output of nm in a proper C declaration. +global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl + +# Transform the output of nm in a C name address pair. +global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address + +# Transform the output of nm in a C name address pair when lib prefix is needed. +global_symbol_to_c_name_address_lib_prefix=$lt_lt_cv_sys_global_symbol_to_c_name_address_lib_prefix + +# The name of the directory that contains temporary libtool files. +objdir=$objdir + +# Used to examine libraries when file_magic_cmd begins with "file". +MAGIC_CMD=$MAGIC_CMD + +# Must we lock files when doing compilation? +need_locks=$lt_need_locks + +# Tool to manipulate archived DWARF debug symbol files on Mac OS X. +DSYMUTIL=$lt_DSYMUTIL + +# Tool to change global to local symbols on Mac OS X. +NMEDIT=$lt_NMEDIT + +# Tool to manipulate fat objects and archives on Mac OS X. +LIPO=$lt_LIPO + +# ldd/readelf like tool for Mach-O binaries on Mac OS X. +OTOOL=$lt_OTOOL + +# ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4. +OTOOL64=$lt_OTOOL64 + +# Old archive suffix (normally "a"). +libext=$libext + +# Shared library suffix (normally ".so"). +shrext_cmds=$lt_shrext_cmds + +# The commands to extract the exported symbol list from a shared archive. +extract_expsyms_cmds=$lt_extract_expsyms_cmds + +# Variables whose values should be saved in libtool wrapper scripts and +# restored at link time. +variables_saved_for_relink=$lt_variables_saved_for_relink + +# Do we need the "lib" prefix for modules? +need_lib_prefix=$need_lib_prefix + +# Do we need a version for libraries? +need_version=$need_version + +# Library versioning type. +version_type=$version_type + +# Shared library runtime path variable. +runpath_var=$runpath_var + +# Shared library path variable. +shlibpath_var=$shlibpath_var + +# Is shlibpath searched before the hard-coded library search path? +shlibpath_overrides_runpath=$shlibpath_overrides_runpath + +# Format of library name prefix. +libname_spec=$lt_libname_spec + +# List of archive names. First name is the real one, the rest are links. +# The last name is the one that the linker finds with -lNAME +library_names_spec=$lt_library_names_spec + +# The coded name of the library, if different from the real name. +soname_spec=$lt_soname_spec + +# Permission mode override for installation of shared libraries. +install_override_mode=$lt_install_override_mode + +# Command to use after installation of a shared archive. +postinstall_cmds=$lt_postinstall_cmds + +# Command to use after uninstallation of a shared archive. +postuninstall_cmds=$lt_postuninstall_cmds + +# Commands used to finish a libtool library installation in a directory. +finish_cmds=$lt_finish_cmds + +# As "finish_cmds", except a single script fragment to be evaled but +# not shown. +finish_eval=$lt_finish_eval + +# Whether we should hardcode library paths into libraries. +hardcode_into_libs=$hardcode_into_libs + +# Compile-time system search path for libraries. +sys_lib_search_path_spec=$lt_sys_lib_search_path_spec + +# Run-time system search path for libraries. +sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec + +# Whether dlopen is supported. +dlopen_support=$enable_dlopen + +# Whether dlopen of programs is supported. +dlopen_self=$enable_dlopen_self + +# Whether dlopen of statically linked programs is supported. +dlopen_self_static=$enable_dlopen_self_static + +# Commands to strip libraries. +old_striplib=$lt_old_striplib +striplib=$lt_striplib + + +# The linker used to build libraries. +LD=$lt_LD + +# How to create reloadable object files. +reload_flag=$lt_reload_flag +reload_cmds=$lt_reload_cmds + +# Commands used to build an old-style archive. +old_archive_cmds=$lt_old_archive_cmds + +# A language specific compiler. +CC=$lt_compiler + +# Is the compiler the GNU compiler? +with_gcc=$GCC + +# Compiler flag to turn off builtin functions. +no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag + +# How to pass a linker flag through the compiler. +wl=$lt_lt_prog_compiler_wl + +# Additional compiler flags for building library objects. +pic_flag=$lt_lt_prog_compiler_pic + +# Compiler flag to prevent dynamic linking. +link_static_flag=$lt_lt_prog_compiler_static + +# Does compiler simultaneously support -c and -o options? +compiler_c_o=$lt_lt_cv_prog_compiler_c_o + +# Whether or not to add -lc for building shared libraries. +build_libtool_need_lc=$archive_cmds_need_lc + +# Whether or not to disallow shared libs when runtime libs are static. +allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes + +# Compiler flag to allow reflexive dlopens. +export_dynamic_flag_spec=$lt_export_dynamic_flag_spec + +# Compiler flag to generate shared objects directly from archives. +whole_archive_flag_spec=$lt_whole_archive_flag_spec + +# Whether the compiler copes with passing no objects directly. +compiler_needs_object=$lt_compiler_needs_object + +# Create an old-style archive from a shared archive. +old_archive_from_new_cmds=$lt_old_archive_from_new_cmds + +# Create a temporary old-style archive to link instead of a shared archive. +old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds + +# Commands used to build a shared archive. +archive_cmds=$lt_archive_cmds +archive_expsym_cmds=$lt_archive_expsym_cmds + +# Commands used to build a loadable module if different from building +# a shared archive. +module_cmds=$lt_module_cmds +module_expsym_cmds=$lt_module_expsym_cmds + +# Whether we are building with GNU ld or not. +with_gnu_ld=$lt_with_gnu_ld + +# Flag that allows shared libraries with undefined symbols to be built. +allow_undefined_flag=$lt_allow_undefined_flag + +# Flag that enforces no undefined symbols. +no_undefined_flag=$lt_no_undefined_flag + +# Flag to hardcode \$libdir into a binary during linking. +# This must work even if \$libdir does not exist +hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec + +# If ld is used when linking, flag to hardcode \$libdir into a binary +# during linking. This must work even if \$libdir does not exist. +hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld + +# Whether we need a single "-rpath" flag with a separated argument. +hardcode_libdir_separator=$lt_hardcode_libdir_separator + +# Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes +# DIR into the resulting binary. +hardcode_direct=$hardcode_direct + +# Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes +# DIR into the resulting binary and the resulting library dependency is +# "absolute",i.e impossible to change by setting \${shlibpath_var} if the +# library is relocated. +hardcode_direct_absolute=$hardcode_direct_absolute + +# Set to "yes" if using the -LDIR flag during linking hardcodes DIR +# into the resulting binary. +hardcode_minus_L=$hardcode_minus_L + +# Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR +# into the resulting binary. +hardcode_shlibpath_var=$hardcode_shlibpath_var + +# Set to "yes" if building a shared library automatically hardcodes DIR +# into the library and all subsequent libraries and executables linked +# against it. +hardcode_automatic=$hardcode_automatic + +# Set to yes if linker adds runtime paths of dependent libraries +# to runtime path list. +inherit_rpath=$inherit_rpath + +# Whether libtool must link a program against all its dependency libraries. +link_all_deplibs=$link_all_deplibs + +# Fix the shell variable \$srcfile for the compiler. +fix_srcfile_path=$lt_fix_srcfile_path + +# Set to "yes" if exported symbols are required. +always_export_symbols=$always_export_symbols + +# The commands to list exported symbols. +export_symbols_cmds=$lt_export_symbols_cmds + +# Symbols that should not be listed in the preloaded symbols. +exclude_expsyms=$lt_exclude_expsyms + +# Symbols that must always be exported. +include_expsyms=$lt_include_expsyms + +# Commands necessary for linking programs (against libraries) with templates. +prelink_cmds=$lt_prelink_cmds + +# Specify filename containing input files. +file_list_spec=$lt_file_list_spec + +# How to hardcode a shared library path into an executable. +hardcode_action=$hardcode_action + +# The directories searched by this compiler when creating a shared library. +compiler_lib_search_dirs=$lt_compiler_lib_search_dirs + +# Dependencies to place before and after the objects being linked to +# create a shared library. +predep_objects=$lt_predep_objects +postdep_objects=$lt_postdep_objects +predeps=$lt_predeps +postdeps=$lt_postdeps + +# The library search path used internally by the compiler when linking +# a shared library. +compiler_lib_search_path=$lt_compiler_lib_search_path + +# ### END LIBTOOL CONFIG + +_LT_EOF + + case $host_os in + aix3*) + cat <<\_LT_EOF >> "$cfgfile" +# AIX sometimes has problems with the GCC collect2 program. For some +# reason, if we set the COLLECT_NAMES environment variable, the problems +# vanish in a puff of smoke. +if test "X${COLLECT_NAMES+set}" != Xset; then + COLLECT_NAMES= + export COLLECT_NAMES +fi +_LT_EOF + ;; + esac + + +ltmain="$ac_aux_dir/ltmain.sh" + + + # We use sed instead of cat because bash on DJGPP gets confused if + # if finds mixed CR/LF and LF-only lines. Since sed operates in + # text mode, it properly converts lines to CR/LF. This bash problem + # is reportedly fixed, but why not run on old versions too? + sed '/^# Generated shell functions inserted here/q' "$ltmain" >> "$cfgfile" \ + || (rm -f "$cfgfile"; exit 1) + + case $xsi_shell in + yes) + cat << \_LT_EOF >> "$cfgfile" + +# func_dirname file append nondir_replacement +# Compute the dirname of FILE. If nonempty, add APPEND to the result, +# otherwise set result to NONDIR_REPLACEMENT. +func_dirname () +{ + case ${1} in + */*) func_dirname_result="${1%/*}${2}" ;; + * ) func_dirname_result="${3}" ;; + esac +} + +# func_basename file +func_basename () +{ + func_basename_result="${1##*/}" +} + +# func_dirname_and_basename file append nondir_replacement +# perform func_basename and func_dirname in a single function +# call: +# dirname: Compute the dirname of FILE. If nonempty, +# add APPEND to the result, otherwise set result +# to NONDIR_REPLACEMENT. +# value returned in "$func_dirname_result" +# basename: Compute filename of FILE. +# value retuned in "$func_basename_result" +# Implementation must be kept synchronized with func_dirname +# and func_basename. For efficiency, we do not delegate to +# those functions but instead duplicate the functionality here. +func_dirname_and_basename () +{ + case ${1} in + */*) func_dirname_result="${1%/*}${2}" ;; + * ) func_dirname_result="${3}" ;; + esac + func_basename_result="${1##*/}" +} + +# func_stripname prefix suffix name +# strip PREFIX and SUFFIX off of NAME. +# PREFIX and SUFFIX must not contain globbing or regex special +# characters, hashes, percent signs, but SUFFIX may contain a leading +# dot (in which case that matches only a dot). +func_stripname () +{ + # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are + # positional parameters, so assign one to ordinary parameter first. + func_stripname_result=${3} + func_stripname_result=${func_stripname_result#"${1}"} + func_stripname_result=${func_stripname_result%"${2}"} +} + +# func_opt_split +func_opt_split () +{ + func_opt_split_opt=${1%%=*} + func_opt_split_arg=${1#*=} +} + +# func_lo2o object +func_lo2o () +{ + case ${1} in + *.lo) func_lo2o_result=${1%.lo}.${objext} ;; + *) func_lo2o_result=${1} ;; + esac +} + +# func_xform libobj-or-source +func_xform () +{ + func_xform_result=${1%.*}.lo +} + +# func_arith arithmetic-term... +func_arith () +{ + func_arith_result=$(( $* )) +} + +# func_len string +# STRING may not start with a hyphen. +func_len () +{ + func_len_result=${#1} +} + +_LT_EOF + ;; + *) # Bourne compatible functions. + cat << \_LT_EOF >> "$cfgfile" + +# func_dirname file append nondir_replacement +# Compute the dirname of FILE. If nonempty, add APPEND to the result, +# otherwise set result to NONDIR_REPLACEMENT. +func_dirname () +{ + # Extract subdirectory from the argument. + func_dirname_result=`$ECHO "${1}" | $SED "$dirname"` + if test "X$func_dirname_result" = "X${1}"; then + func_dirname_result="${3}" + else + func_dirname_result="$func_dirname_result${2}" + fi +} + +# func_basename file +func_basename () +{ + func_basename_result=`$ECHO "${1}" | $SED "$basename"` +} + + +# func_stripname prefix suffix name +# strip PREFIX and SUFFIX off of NAME. +# PREFIX and SUFFIX must not contain globbing or regex special +# characters, hashes, percent signs, but SUFFIX may contain a leading +# dot (in which case that matches only a dot). +# func_strip_suffix prefix name +func_stripname () +{ + case ${2} in + .*) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%\\\\${2}\$%%"`;; + *) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%${2}\$%%"`;; + esac +} + +# sed scripts: +my_sed_long_opt='1s/^\(-[^=]*\)=.*/\1/;q' +my_sed_long_arg='1s/^-[^=]*=//' + +# func_opt_split +func_opt_split () +{ + func_opt_split_opt=`$ECHO "${1}" | $SED "$my_sed_long_opt"` + func_opt_split_arg=`$ECHO "${1}" | $SED "$my_sed_long_arg"` +} + +# func_lo2o object +func_lo2o () +{ + func_lo2o_result=`$ECHO "${1}" | $SED "$lo2o"` +} + +# func_xform libobj-or-source +func_xform () +{ + func_xform_result=`$ECHO "${1}" | $SED 's/\.[^.]*$/.lo/'` +} + +# func_arith arithmetic-term... +func_arith () +{ + func_arith_result=`expr "$@"` +} + +# func_len string +# STRING may not start with a hyphen. +func_len () +{ + func_len_result=`expr "$1" : ".*" 2>/dev/null || echo $max_cmd_len` +} + +_LT_EOF +esac + +case $lt_shell_append in + yes) + cat << \_LT_EOF >> "$cfgfile" + +# func_append var value +# Append VALUE to the end of shell variable VAR. +func_append () +{ + eval "$1+=\$2" +} +_LT_EOF + ;; + *) + cat << \_LT_EOF >> "$cfgfile" + +# func_append var value +# Append VALUE to the end of shell variable VAR. +func_append () +{ + eval "$1=\$$1\$2" +} + +_LT_EOF + ;; + esac + + + sed -n '/^# Generated shell functions inserted here/,$p' "$ltmain" >> "$cfgfile" \ + || (rm -f "$cfgfile"; exit 1) + + mv -f "$cfgfile" "$ofile" || + (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") + chmod +x "$ofile" + + + cat <<_LT_EOF >> "$ofile" + +# ### BEGIN LIBTOOL TAG CONFIG: CXX + +# The linker used to build libraries. +LD=$lt_LD_CXX + +# How to create reloadable object files. +reload_flag=$lt_reload_flag_CXX +reload_cmds=$lt_reload_cmds_CXX + +# Commands used to build an old-style archive. +old_archive_cmds=$lt_old_archive_cmds_CXX + +# A language specific compiler. +CC=$lt_compiler_CXX + +# Is the compiler the GNU compiler? +with_gcc=$GCC_CXX + +# Compiler flag to turn off builtin functions. +no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_CXX + +# How to pass a linker flag through the compiler. +wl=$lt_lt_prog_compiler_wl_CXX + +# Additional compiler flags for building library objects. +pic_flag=$lt_lt_prog_compiler_pic_CXX + +# Compiler flag to prevent dynamic linking. +link_static_flag=$lt_lt_prog_compiler_static_CXX + +# Does compiler simultaneously support -c and -o options? +compiler_c_o=$lt_lt_cv_prog_compiler_c_o_CXX + +# Whether or not to add -lc for building shared libraries. +build_libtool_need_lc=$archive_cmds_need_lc_CXX + +# Whether or not to disallow shared libs when runtime libs are static. +allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_CXX + +# Compiler flag to allow reflexive dlopens. +export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_CXX + +# Compiler flag to generate shared objects directly from archives. +whole_archive_flag_spec=$lt_whole_archive_flag_spec_CXX + +# Whether the compiler copes with passing no objects directly. +compiler_needs_object=$lt_compiler_needs_object_CXX + +# Create an old-style archive from a shared archive. +old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_CXX + +# Create a temporary old-style archive to link instead of a shared archive. +old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_CXX + +# Commands used to build a shared archive. +archive_cmds=$lt_archive_cmds_CXX +archive_expsym_cmds=$lt_archive_expsym_cmds_CXX + +# Commands used to build a loadable module if different from building +# a shared archive. +module_cmds=$lt_module_cmds_CXX +module_expsym_cmds=$lt_module_expsym_cmds_CXX + +# Whether we are building with GNU ld or not. +with_gnu_ld=$lt_with_gnu_ld_CXX + +# Flag that allows shared libraries with undefined symbols to be built. +allow_undefined_flag=$lt_allow_undefined_flag_CXX + +# Flag that enforces no undefined symbols. +no_undefined_flag=$lt_no_undefined_flag_CXX + +# Flag to hardcode \$libdir into a binary during linking. +# This must work even if \$libdir does not exist +hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_CXX + +# If ld is used when linking, flag to hardcode \$libdir into a binary +# during linking. This must work even if \$libdir does not exist. +hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld_CXX + +# Whether we need a single "-rpath" flag with a separated argument. +hardcode_libdir_separator=$lt_hardcode_libdir_separator_CXX + +# Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes +# DIR into the resulting binary. +hardcode_direct=$hardcode_direct_CXX + +# Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes +# DIR into the resulting binary and the resulting library dependency is +# "absolute",i.e impossible to change by setting \${shlibpath_var} if the +# library is relocated. +hardcode_direct_absolute=$hardcode_direct_absolute_CXX + +# Set to "yes" if using the -LDIR flag during linking hardcodes DIR +# into the resulting binary. +hardcode_minus_L=$hardcode_minus_L_CXX + +# Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR +# into the resulting binary. +hardcode_shlibpath_var=$hardcode_shlibpath_var_CXX + +# Set to "yes" if building a shared library automatically hardcodes DIR +# into the library and all subsequent libraries and executables linked +# against it. +hardcode_automatic=$hardcode_automatic_CXX + +# Set to yes if linker adds runtime paths of dependent libraries +# to runtime path list. +inherit_rpath=$inherit_rpath_CXX + +# Whether libtool must link a program against all its dependency libraries. +link_all_deplibs=$link_all_deplibs_CXX + +# Fix the shell variable \$srcfile for the compiler. +fix_srcfile_path=$lt_fix_srcfile_path_CXX + +# Set to "yes" if exported symbols are required. +always_export_symbols=$always_export_symbols_CXX + +# The commands to list exported symbols. +export_symbols_cmds=$lt_export_symbols_cmds_CXX + +# Symbols that should not be listed in the preloaded symbols. +exclude_expsyms=$lt_exclude_expsyms_CXX + +# Symbols that must always be exported. +include_expsyms=$lt_include_expsyms_CXX + +# Commands necessary for linking programs (against libraries) with templates. +prelink_cmds=$lt_prelink_cmds_CXX + +# Specify filename containing input files. +file_list_spec=$lt_file_list_spec_CXX + +# How to hardcode a shared library path into an executable. +hardcode_action=$hardcode_action_CXX + +# The directories searched by this compiler when creating a shared library. +compiler_lib_search_dirs=$lt_compiler_lib_search_dirs_CXX + +# Dependencies to place before and after the objects being linked to +# create a shared library. +predep_objects=$lt_predep_objects_CXX +postdep_objects=$lt_postdep_objects_CXX +predeps=$lt_predeps_CXX +postdeps=$lt_postdeps_CXX + +# The library search path used internally by the compiler when linking +# a shared library. +compiler_lib_search_path=$lt_compiler_lib_search_path_CXX + +# ### END LIBTOOL TAG CONFIG: CXX +_LT_EOF + + ;; + "gstdint.h":C) +if test "$GCC" = yes; then + echo "/* generated for " `$CC --version | sed 1q` "*/" > tmp-stdint.h +else + echo "/* generated for $CC */" > tmp-stdint.h +fi + +sed 's/^ *//' >> tmp-stdint.h <<EOF + + #ifndef GCC_GENERATED_STDINT_H + #define GCC_GENERATED_STDINT_H 1 + + #include <sys/types.h> +EOF + +if test "$acx_cv_header_stdint" != stdint.h; then + echo "#include <stddef.h>" >> tmp-stdint.h +fi +if test "$acx_cv_header_stdint" != stddef.h; then + echo "#include <$acx_cv_header_stdint>" >> tmp-stdint.h +fi + +sed 's/^ *//' >> tmp-stdint.h <<EOF + /* glibc uses these symbols as guards to prevent redefinitions. */ + #ifdef __int8_t_defined + #define _INT8_T + #define _INT16_T + #define _INT32_T + #endif + #ifdef __uint32_t_defined + #define _UINT32_T + #endif + +EOF + +# ----------------- done header, emit basic int types ------------- +if test "$acx_cv_header_stdint" = stddef.h; then + sed 's/^ *//' >> tmp-stdint.h <<EOF + + #ifndef _UINT8_T + #define _UINT8_T + #ifndef __uint8_t_defined + #define __uint8_t_defined + #ifndef uint8_t + typedef unsigned $acx_cv_type_int8_t uint8_t; + #endif + #endif + #endif + + #ifndef _UINT16_T + #define _UINT16_T + #ifndef __uint16_t_defined + #define __uint16_t_defined + #ifndef uint16_t + typedef unsigned $acx_cv_type_int16_t uint16_t; + #endif + #endif + #endif + + #ifndef _UINT32_T + #define _UINT32_T + #ifndef __uint32_t_defined + #define __uint32_t_defined + #ifndef uint32_t + typedef unsigned $acx_cv_type_int32_t uint32_t; + #endif + #endif + #endif + + #ifndef _INT8_T + #define _INT8_T + #ifndef __int8_t_defined + #define __int8_t_defined + #ifndef int8_t + typedef $acx_cv_type_int8_t int8_t; + #endif + #endif + #endif + + #ifndef _INT16_T + #define _INT16_T + #ifndef __int16_t_defined + #define __int16_t_defined + #ifndef int16_t + typedef $acx_cv_type_int16_t int16_t; + #endif + #endif + #endif + + #ifndef _INT32_T + #define _INT32_T + #ifndef __int32_t_defined + #define __int32_t_defined + #ifndef int32_t + typedef $acx_cv_type_int32_t int32_t; + #endif + #endif + #endif +EOF +elif test "$ac_cv_type_u_int32_t" = yes; then + sed 's/^ *//' >> tmp-stdint.h <<EOF + + /* int8_t int16_t int32_t defined by inet code, we do the u_intXX types */ + #ifndef _INT8_T + #define _INT8_T + #endif + #ifndef _INT16_T + #define _INT16_T + #endif + #ifndef _INT32_T + #define _INT32_T + #endif + + #ifndef _UINT8_T + #define _UINT8_T + #ifndef __uint8_t_defined + #define __uint8_t_defined + #ifndef uint8_t + typedef u_int8_t uint8_t; + #endif + #endif + #endif + + #ifndef _UINT16_T + #define _UINT16_T + #ifndef __uint16_t_defined + #define __uint16_t_defined + #ifndef uint16_t + typedef u_int16_t uint16_t; + #endif + #endif + #endif + + #ifndef _UINT32_T + #define _UINT32_T + #ifndef __uint32_t_defined + #define __uint32_t_defined + #ifndef uint32_t + typedef u_int32_t uint32_t; + #endif + #endif + #endif +EOF +else + sed 's/^ *//' >> tmp-stdint.h <<EOF + + /* Some systems have guard macros to prevent redefinitions, define them. */ + #ifndef _INT8_T + #define _INT8_T + #endif + #ifndef _INT16_T + #define _INT16_T + #endif + #ifndef _INT32_T + #define _INT32_T + #endif + #ifndef _UINT8_T + #define _UINT8_T + #endif + #ifndef _UINT16_T + #define _UINT16_T + #endif + #ifndef _UINT32_T + #define _UINT32_T + #endif +EOF +fi + +# ------------- done basic int types, emit int64_t types ------------ +if test "$ac_cv_type_uint64_t" = yes; then + sed 's/^ *//' >> tmp-stdint.h <<EOF + + /* system headers have good uint64_t and int64_t */ + #ifndef _INT64_T + #define _INT64_T + #endif + #ifndef _UINT64_T + #define _UINT64_T + #endif +EOF +elif test "$ac_cv_type_u_int64_t" = yes; then + sed 's/^ *//' >> tmp-stdint.h <<EOF + + /* system headers have an u_int64_t (and int64_t) */ + #ifndef _INT64_T + #define _INT64_T + #endif + #ifndef _UINT64_T + #define _UINT64_T + #ifndef __uint64_t_defined + #define __uint64_t_defined + #ifndef uint64_t + typedef u_int64_t uint64_t; + #endif + #endif + #endif +EOF +elif test -n "$acx_cv_type_int64_t"; then + sed 's/^ *//' >> tmp-stdint.h <<EOF + + /* architecture has a 64-bit type, $acx_cv_type_int64_t */ + #ifndef _INT64_T + #define _INT64_T + #ifndef int64_t + typedef $acx_cv_type_int64_t int64_t; + #endif + #endif + #ifndef _UINT64_T + #define _UINT64_T + #ifndef __uint64_t_defined + #define __uint64_t_defined + #ifndef uint64_t + typedef unsigned $acx_cv_type_int64_t uint64_t; + #endif + #endif + #endif +EOF +else + sed 's/^ *//' >> tmp-stdint.h <<EOF + + /* some common heuristics for int64_t, using compiler-specific tests */ + #if defined __STDC_VERSION__ && (__STDC_VERSION__-0) >= 199901L + #ifndef _INT64_T + #define _INT64_T + #ifndef __int64_t_defined + #ifndef int64_t + typedef long long int64_t; + #endif + #endif + #endif + #ifndef _UINT64_T + #define _UINT64_T + #ifndef uint64_t + typedef unsigned long long uint64_t; + #endif + #endif + + #elif defined __GNUC__ && defined (__STDC__) && __STDC__-0 + /* NextStep 2.0 cc is really gcc 1.93 but it defines __GNUC__ = 2 and + does not implement __extension__. But that compiler doesn't define + __GNUC_MINOR__. */ + # if __GNUC__ < 2 || (__NeXT__ && !__GNUC_MINOR__) + # define __extension__ + # endif + + # ifndef _INT64_T + # define _INT64_T + # ifndef int64_t + __extension__ typedef long long int64_t; + # endif + # endif + # ifndef _UINT64_T + # define _UINT64_T + # ifndef uint64_t + __extension__ typedef unsigned long long uint64_t; + # endif + # endif + + #elif !defined __STRICT_ANSI__ + # if defined _MSC_VER || defined __WATCOMC__ || defined __BORLANDC__ + + # ifndef _INT64_T + # define _INT64_T + # ifndef int64_t + typedef __int64 int64_t; + # endif + # endif + # ifndef _UINT64_T + # define _UINT64_T + # ifndef uint64_t + typedef unsigned __int64 uint64_t; + # endif + # endif + # endif /* compiler */ + + #endif /* ANSI version */ +EOF +fi + +# ------------- done int64_t types, emit intptr types ------------ +if test "$ac_cv_type_uintptr_t" != yes; then + sed 's/^ *//' >> tmp-stdint.h <<EOF + + /* Define intptr_t based on sizeof(void*) = $ac_cv_sizeof_void_p */ + #ifndef __uintptr_t_defined + #ifndef uintptr_t + typedef u$acx_cv_type_intptr_t uintptr_t; + #endif + #endif + #ifndef __intptr_t_defined + #ifndef intptr_t + typedef $acx_cv_type_intptr_t intptr_t; + #endif + #endif +EOF +fi + +# ------------- done intptr types, emit int_least types ------------ +if test "$ac_cv_type_int_least32_t" != yes; then + sed 's/^ *//' >> tmp-stdint.h <<EOF + + /* Define int_least types */ + typedef int8_t int_least8_t; + typedef int16_t int_least16_t; + typedef int32_t int_least32_t; + #ifdef _INT64_T + typedef int64_t int_least64_t; + #endif + + typedef uint8_t uint_least8_t; + typedef uint16_t uint_least16_t; + typedef uint32_t uint_least32_t; + #ifdef _UINT64_T + typedef uint64_t uint_least64_t; + #endif +EOF +fi + +# ------------- done intptr types, emit int_fast types ------------ +if test "$ac_cv_type_int_fast32_t" != yes; then + sed 's/^ *//' >> tmp-stdint.h <<EOF + + /* Define int_fast types. short is often slow */ + typedef int8_t int_fast8_t; + typedef int int_fast16_t; + typedef int32_t int_fast32_t; + #ifdef _INT64_T + typedef int64_t int_fast64_t; + #endif + + typedef uint8_t uint_fast8_t; + typedef unsigned int uint_fast16_t; + typedef uint32_t uint_fast32_t; + #ifdef _UINT64_T + typedef uint64_t uint_fast64_t; + #endif +EOF +fi + +if test "$ac_cv_type_uintmax_t" != yes; then + sed 's/^ *//' >> tmp-stdint.h <<EOF + + /* Define intmax based on what we found */ + #ifndef intmax_t + #ifdef _INT64_T + typedef int64_t intmax_t; + #else + typedef long intmax_t; + #endif + #endif + #ifndef uintmax_t + #ifdef _UINT64_T + typedef uint64_t uintmax_t; + #else + typedef unsigned long uintmax_t; + #endif + #endif +EOF +fi + +sed 's/^ *//' >> tmp-stdint.h <<EOF + + #endif /* GCC_GENERATED_STDINT_H */ +EOF + +if test -r gstdint.h && cmp -s tmp-stdint.h gstdint.h; then + rm -f tmp-stdint.h +else + mv -f tmp-stdint.h gstdint.h +fi + + ;; + + esac +done # for ac_tag + + +as_fn_exit 0 +_ACEOF +ac_clean_files=$ac_clean_files_save + +test $ac_write_fail = 0 || + as_fn_error "write failure creating $CONFIG_STATUS" "$LINENO" 5 + + +# configure is writing to config.log, and then calls config.status. +# config.status does its own redirection, appending to config.log. +# Unfortunately, on DOS this fails, as config.log is still kept open +# by configure, so config.status won't be able to write to it; its +# output is simply discarded. So we exec the FD to /dev/null, +# effectively closing config.log, so it can be properly (re)opened and +# appended to by config.status. When coming back to configure, we +# need to make the FD available again. +if test "$no_create" != yes; then + ac_cs_success=: + ac_config_status_args= + test "$silent" = yes && + ac_config_status_args="$ac_config_status_args --quiet" + exec 5>/dev/null + $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false + exec 5>>config.log + # Use ||, not &&, to avoid exiting from the if with $? = 1, which + # would make configure fail if this is the last instruction. + $ac_cs_success || as_fn_exit $? +fi +if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 +$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} +fi + diff --git a/libitm/configure.ac b/libitm/configure.ac new file mode 100644 index 00000000000..7f35b154529 --- /dev/null +++ b/libitm/configure.ac @@ -0,0 +1,270 @@ +# Process this file with autoreconf to produce a configure script. +# Copyright (C) 2011 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +AC_PREREQ(2.59) +AC_INIT([GNU TM Runtime Library], 1.0,,[libitm]) +AC_CONFIG_HEADER(config.h) + +# ------- +# Options +# ------- + +AC_MSG_CHECKING([for --enable-version-specific-runtime-libs]) +LIBITM_ENABLE(version-specific-runtime-libs, no, , + [Specify that runtime libraries should be installed in a compiler-specific directory], + permit yes|no) +AC_MSG_RESULT($enable_version_specific_runtime_libs) + +# We would like our source tree to be readonly. However when releases or +# pre-releases are generated, the flex/bison generated files as well as the +# various formats of manuals need to be included along with the rest of the +# sources. Therefore we have --enable-generated-files-in-srcdir to do +# just that. +AC_MSG_CHECKING([for --enable-generated-files-in-srcdir]) +LIBITM_ENABLE(generated-files-in-srcdir, no, , + [put copies of generated files in source dir intended for creating source + tarballs for users without texinfo bison or flex.], + permit yes|no) +AC_MSG_RESULT($enable_generated_files_in_srcdir) +AM_CONDITIONAL(GENINSRC, test "$enable_generated_files_in_srcdir" = yes) + + +# ------- +# ------- + +# Gets build, host, target, *_vendor, *_cpu, *_os, etc. +# +# You will slowly go insane if you do not grok the following fact: when +# building this library, the top-level /target/ becomes the library's /host/. +# +# configure then causes --target to default to --host, exactly like any +# other package using autoconf. Therefore, 'target' and 'host' will +# always be the same. This makes sense both for native and cross compilers +# just think about it for a little while. :-) +# +# Also, if this library is being configured as part of a cross compiler, the +# top-level configure script will pass the "real" host as $with_cross_host. +# +# Do not delete or change the following two lines. For why, see +# http://gcc.gnu.org/ml/libstdc++/2003-07/msg00451.html +AC_CANONICAL_SYSTEM +target_alias=${target_alias-$host_alias} + +# Sets up automake. Must come after AC_CANONICAL_SYSTEM. Each of the +# following is magically included in AUTOMAKE_OPTIONS in each Makefile.am. +# 1.9.0: minimum required version +# no-define: PACKAGE and VERSION will not be #define'd in config.h (a bunch +# of other PACKAGE_* variables will, however, and there's nothing +# we can do about that; they come from AC_INIT). +# foreign: we don't follow the normal rules for GNU packages (no COPYING +# file in the top srcdir, etc, etc), so stop complaining. +# -Wall: turns on all automake warnings... +# -Wno-portability: ...except this one, since GNU make is required. +# -Wno-override: ... and this one, since we do want this in testsuite. +AM_INIT_AUTOMAKE([1.9.0 foreign -Wall -Wno-portability -Wno-override]) +AM_ENABLE_MULTILIB(, ..) + +# Calculate toolexeclibdir +# Also toolexecdir, though it's only used in toolexeclibdir +case ${enable_version_specific_runtime_libs} in + yes) + # Need the gcc compiler version to know where to install libraries + # and header files if --enable-version-specific-runtime-libs option + # is selected. + toolexecdir='$(libdir)/gcc/$(target_alias)' + toolexeclibdir='$(toolexecdir)/$(gcc_version)$(MULTISUBDIR)' + ;; + no) + if test -n "$with_cross_host" && + test x"$with_cross_host" != x"no"; then + # Install a library built with a cross compiler in tooldir, not libdir. + toolexecdir='$(exec_prefix)/$(target_alias)' + toolexeclibdir='$(toolexecdir)/lib' + else + toolexecdir='$(libdir)/gcc-lib/$(target_alias)' + toolexeclibdir='$(libdir)' + fi + multi_os_directory=`$CC -print-multi-os-directory` + case $multi_os_directory in + .) ;; # Avoid trailing /. + *) toolexeclibdir=$toolexeclibdir/$multi_os_directory ;; + esac + ;; +esac +AC_SUBST(toolexecdir) +AC_SUBST(toolexeclibdir) + +# Check the compiler. +# The same as in boehm-gc and libstdc++. Have to borrow it from there. +# We must force CC to /not/ be precious variables; otherwise +# the wrong, non-multilib-adjusted value will be used in multilibs. +# As a side effect, we have to subst CFLAGS ourselves. + +m4_rename([_AC_ARG_VAR_PRECIOUS],[real_PRECIOUS]) +m4_define([_AC_ARG_VAR_PRECIOUS],[]) +AC_PROG_CC +AC_PROG_CXX +AM_PROG_AS +m4_rename_force([real_PRECIOUS],[_AC_ARG_VAR_PRECIOUS]) + +AC_SUBST(CFLAGS) + +# In order to override CFLAGS_FOR_TARGET, all of our special flags go +# in XCFLAGS. But we need them in CFLAGS during configury. So put them +# in both places for now and restore CFLAGS at the end of config. +save_CFLAGS="$CFLAGS" + +# Find other programs we need. +AC_CHECK_TOOL(AR, ar) +AC_CHECK_TOOL(NM, nm) +AC_CHECK_TOOL(RANLIB, ranlib, ranlib-not-found-in-path-error) +AC_PATH_PROG(PERL, perl, perl-not-found-in-path-error) +AC_PROG_MAKE_SET +AC_PROG_INSTALL + +# See if makeinfo has been installed and is modern enough +# that we can use it. +ACX_CHECK_PROG_VER([MAKEINFO], [makeinfo], [--version], + [GNU texinfo.* \([0-9][0-9.]*\)], + [4.[4-9]*|4.[1-9][0-9]*|[5-9]*|[1-9][0-9]*]) +AM_CONDITIONAL(BUILD_INFO, test $gcc_cv_prog_makeinfo_modern = "yes") + + +# Configure libtool +AM_PROG_LIBTOOL +AC_SUBST(enable_shared) +AC_SUBST(enable_static) + +AM_MAINTAINER_MODE + +# For libtool versioning info, format is CURRENT:REVISION:AGE +libtool_VERSION=1:0:0 +AC_SUBST(libtool_VERSION) + +# Check header files. +AC_STDC_HEADERS +AC_HEADER_TIME +ACX_HEADER_STRING +AC_CHECK_HEADERS(unistd.h semaphore.h sys/time.h malloc.h) + +GCC_HEADER_STDINT(gstdint.h) + +GCC_AC_FUNC_MMAP_BLACKLIST + +AC_C_BIGENDIAN +# I don't like the default behaviour of WORDS_BIGENDIAN undefined for LE. +AH_BOTTOM( +[#ifndef WORDS_BIGENDIAN +#define WORDS_BIGENDIAN 0 +#endif]) + +# Check to see if -pthread or -lpthread is needed. Prefer the former. +# In case the pthread.h system header is not found, this test will fail. +XPCFLAGS="" +CFLAGS="$CFLAGS -pthread" +AC_LINK_IFELSE( + [AC_LANG_PROGRAM( + [#include <pthread.h> + void *g(void *d) { return NULL; }], + [pthread_t t; pthread_create(&t,NULL,g,NULL);])], + [XPCFLAGS=" -Wc,-pthread"], + [CFLAGS="$save_CFLAGS" LIBS="-lpthread $LIBS" + AC_LINK_IFELSE( + [AC_LANG_PROGRAM( + [#include <pthread.h> + void *g(void *d) { return NULL; }], + [pthread_t t; pthread_create(&t,NULL,g,NULL);])], + [], + [AC_MSG_ERROR([Pthreads are required to build libitm])])]) + +# Check for functions needed. +AC_CHECK_FUNCS(strtoull memalign posix_memalign) + +# Check for broken semaphore implementation on darwin. +# sem_init returns: sem_init error: Function not implemented. +case "$host" in + *-darwin*) + AC_DEFINE(HAVE_BROKEN_POSIX_SEMAPHORES, 1, + Define if the POSIX Semaphores do not work on your system.) + ;; +esac + +GCC_LINUX_FUTEX(:) + +# See if we support thread-local storage. +GCC_CHECK_TLS + +# See what sort of export controls are availible. +LIBITM_CHECK_ATTRIBUTE_VISIBILITY +LIBITM_CHECK_ATTRIBUTE_DLLEXPORT +LIBITM_CHECK_ATTRIBUTE_ALIAS +LIBITM_ENABLE_SYMVERS + +if test $enable_symvers = gnu; then + AC_DEFINE(LIBITM_GNU_SYMBOL_VERSIONING, 1, + [Define to 1 if GNU symbol versioning is used for libitm.]) +fi + +# Determine the proper ABI type for size_t. +LIBITM_CHECK_SIZE_T_MANGLING + +# Get target configury. +. ${srcdir}/configure.tgt +CFLAGS="$save_CFLAGS $XCFLAGS" + +# Check for __sync_val_compare_and_swap, but only after the target has +# had a chance to set XCFLAGS. +LIBITM_CHECK_SYNC_BUILTINS +LIBITM_CHECK_64BIT_SYNC_BUILTINS + +# Cleanup and exit. +CFLAGS="$save_CFLAGS" +AC_CACHE_SAVE + +# Add -Wall -Werror if we are using GCC. +if test "x$GCC" = "xyes"; then + XCFLAGS="$XCFLAGS -Wall -Werror" +fi + +XCFLAGS="$XCFLAGS $XPCFLAGS" + +AC_SUBST(config_path) +AC_SUBST(XCFLAGS) +AC_SUBST(XLDFLAGS) + +if test ${multilib} = yes; then + multilib_arg="--enable-multilib" +else + multilib_arg= +fi + +# Set up the set of libraries that we need to link against for libitm. +# Note that the GOMP_SELF_SPEC in gcc.c will force -pthread for -fopenmp, +# which will force linkage against -lpthread (or equivalent for the system). +# That's not 100% ideal, but about the best we can do easily. +if test $enable_shared = yes; then + link_itm="-litm %{static: $LIBS}" +else + link_itm="-litm $LIBS" +fi +AC_SUBST(link_itm) + +AM_CONDITIONAL([ARCH_X86], [test "$ARCH" = x86]) +AM_CONDITIONAL([ARCH_FUTEX], [test $enable_linux_futex = yes]) + +AC_CONFIG_FILES(Makefile testsuite/Makefile libitm.spec) +AC_OUTPUT diff --git a/libitm/configure.tgt b/libitm/configure.tgt new file mode 100644 index 00000000000..efc01e095aa --- /dev/null +++ b/libitm/configure.tgt @@ -0,0 +1,131 @@ +# -*- shell-script -*- +# Copyright (C) 2011 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +# This is the target specific configuration file. This is invoked by the +# autoconf generated configure script. Putting it in a separate shell file +# lets us skip running autoconf when modifying target specific information. + +# This file switches on the shell variable ${target}, and sets the +# following shell variables: +# config_path An ordered list of directories to search for +# sources and headers. This is relative to the +# config subdirectory of the source tree. +# XCFLAGS Add extra compile flags to use. +# XLDFLAGS Add extra link flags to use. + +# Optimize TLS usage by avoiding the overhead of dynamic allocation. +if test $gcc_cv_have_tls = yes ; then + case "${target}" in + + # For x86, we use slots in the TCB head for most of our TLS. + # The setup of those slots in beginTransaction can afford to + # use the global-dynamic model. + i[456]86-*-linux* | x86_64-*-linux*) + ;; + + *-*-linux*) + XCFLAGS="${XCFLAGS} -ftls-model=initial-exec" + ;; + esac +fi + +# Map the target cpu to an ARCH sub-directory. At the same time, +# work out any special compilation flags as necessary. +case "${target_cpu}" in + alpha*) ARCH=alpha ;; + ia64*) ARCH=ia64 ;; + mips*) ARCH=mips ;; + powerpc*) ARCH=powerpc ;; + s390*) ARCH=s390 ;; + + i[456]86) + case " ${CC} ${CFLAGS} " in + *" -m64 "*) + ;; + *) + if test -z "$with_arch"; then + XCFLAGS="${XCFLAGS} -march=i486 -mtune=${target_cpu}" + XCFLAGS="${XCFLAGS} -fomit-frame-pointer" + fi + esac + ARCH=x86 + ;; + + x86_64) + case " ${CC} ${CFLAGS} " in + *" -m32 "*) + XCFLAGS="${XCFLAGS} -march=i486 -mtune=i686" + XCFLAGS="${XCFLAGS} -fomit-frame-pointer" + ;; + esac + ARCH=x86 + ;; + + sparcv9 | sparc64) + # Note that sparcv7 and sparcv8 is not included here. We need cas. + echo "int i;" > conftestx.c + if ${CC} ${CFLAGS} -c -o conftestx.o conftestx.c > /dev/null 2>&1; then + case "`/usr/bin/file conftestx.o`" in + *32-bit*) + case " ${CC} ${CFLAGS}" in + *" -mcpu=ultrasparc"*) + ;; + *) + XCFLAGS="${XCFLAGS} -mcpu=v9" + ;; + esac + ;; + esac + fi + rm -f conftestx.c conftestx.o + ARCH=sparc + ;; + + *) + ARCH="${target_cpu}" + ;; +esac + +# Since we require POSIX threads, assume a POSIX system by default. +config_path="$ARCH posix generic" + +# Other system configury +case "${target}" in + *-*-linux*) + if test $enable_linux_futex = yes; then + config_path="linux/$ARCH linux $config_path" + fi + ;; + + *-*-hpux11*) + # HPUX v11.x requires -lrt to resolve sem_init in libgomp.la + XLDFLAGS="${XLDFLAGS} -lrt" + ;; + + *-*-mingw32*) + config_path="$ARCH mingw32 posix generic" + ;; + + *-*-solaris2.[56]*) + config_path="$ARCH posix95 posix generic" + XLDFLAGS="${XLDFLAGS} -lposix4" + ;; + + *-*-darwin*) + config_path="$ARCH bsd posix generic" + ;; +esac diff --git a/libitm/containers.h b/libitm/containers.h new file mode 100644 index 00000000000..e8aa94bb4f4 --- /dev/null +++ b/libitm/containers.h @@ -0,0 +1,108 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + Contributed by Torvald Riegel <triegel@redhat.com>. + + This file is part of the GNU Transactional Memory Library (libitm). + + Libitm is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + Libitm is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + <http://www.gnu.org/licenses/>. */ + +#ifndef LIBITM_CONTAINERS_H +#define LIBITM_CONTAINERS_H 1 + +#include "common.h" + +namespace GTM HIDDEN { + +// A simple vector-like container. +// If alloc_seperate_cl is true, allocations will happen on separate cache +// lines. +template <typename T, bool alloc_separate_cl = true> +class vector +{ + private: + size_t m_capacity; + size_t m_size; + T* entries; + + // Initial capacity of the vector. + static const size_t default_initial_capacity = 32; + // Above that capacity, grow vector by that size for each call. + static const size_t default_resize_max = 2048; + // Resize vector to at least this capacity. + static const size_t default_resize_min = 32; + + // Don't try to copy this vector. + vector<T, alloc_separate_cl>(const vector<T, alloc_separate_cl>& x); + + public: + typedef T datatype; + typedef T* iterator; + + iterator begin() const { return entries; } + iterator end() const { return entries + m_size; } + T& operator[] (size_t pos) { return entries[pos]; } + const T& operator[] (size_t pos) const { return entries[pos]; } + + vector<T, alloc_separate_cl>(size_t initial_size = default_initial_capacity) + : m_capacity(initial_size), + m_size(0) + { + if (m_capacity > 0) + entries = (T*) xmalloc(sizeof(T) * m_capacity, alloc_separate_cl); + else + entries = 0; + } + ~vector<T, alloc_separate_cl>() { if (m_capacity) free(entries); } + + void resize() + { + if (m_capacity >= default_resize_max) + m_capacity = m_capacity + default_resize_max; + else + m_capacity = m_capacity * 2; + if (m_capacity < default_resize_min) + m_capacity = default_resize_min; + entries = (T*) xrealloc(entries, sizeof(T) * m_capacity, alloc_separate_cl); + } + void resize_noinline() __attribute__((noinline)) { resize(); } + + size_t size() const { return m_size; } + size_t capacity() const { return this->capacity; } + + void clear() { m_size = 0; } + + iterator push() { + // We don't want inlining here since push() is often on the fast path. + if (unlikely(m_size == m_capacity)) resize_noinline(); + return &entries[m_size++]; + } + + iterator pop() { + if (likely(m_size > 0)) + { + m_size--; + return entries + m_size; + } + else return 0; + } +}; + +} // namespace GTM + +#endif // LIBITM_CONTAINERS_H diff --git a/libitm/dispatch.h b/libitm/dispatch.h new file mode 100644 index 00000000000..dbf05e4da37 --- /dev/null +++ b/libitm/dispatch.h @@ -0,0 +1,334 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + Contributed by Torvald Riegel <triegel@redhat.com>. + + This file is part of the GNU Transactional Memory Library (libitm). + + Libitm is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + Libitm is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + <http://www.gnu.org/licenses/>. */ + +#ifndef DISPATCH_H +#define DISPATCH_H 1 + +#include "libitm.h" +#include "common.h" + +// Creates ABI load/store methods (can be made virtual or static using M, +// use M2 to create separate methods names for virtual and static) +// The _PV variants are for the pure-virtual methods in the base class. +#define ITM_READ_M(T, LSMOD, M, M2) \ + M _ITM_TYPE_##T ITM_REGPARM ITM_##LSMOD##T##M2 (const _ITM_TYPE_##T *ptr) \ + { \ + return load(ptr, abi_dispatch::LSMOD); \ + } + +#define ITM_READ_M_PV(T, LSMOD, M, M2) \ + M _ITM_TYPE_##T ITM_REGPARM ITM_##LSMOD##T##M2 (const _ITM_TYPE_##T *ptr) \ + = 0; + +#define ITM_WRITE_M(T, LSMOD, M, M2) \ + M void ITM_REGPARM ITM_##LSMOD##T##M2 (_ITM_TYPE_##T *ptr, \ + _ITM_TYPE_##T val) \ + { \ + store(ptr, val, abi_dispatch::LSMOD); \ + } + +#define ITM_WRITE_M_PV(T, LSMOD, M, M2) \ + M void ITM_REGPARM ITM_##LSMOD##T##M2 (_ITM_TYPE_##T *ptr, \ + _ITM_TYPE_##T val) \ + = 0; + +// Creates ABI load/store methods for all load/store modifiers for a particular +// type. +#define CREATE_DISPATCH_METHODS_T(T, M, M2) \ + ITM_READ_M(T, R, M, M2) \ + ITM_READ_M(T, RaR, M, M2) \ + ITM_READ_M(T, RaW, M, M2) \ + ITM_READ_M(T, RfW, M, M2) \ + ITM_WRITE_M(T, W, M, M2) \ + ITM_WRITE_M(T, WaR, M, M2) \ + ITM_WRITE_M(T, WaW, M, M2) +#define CREATE_DISPATCH_METHODS_T_PV(T, M, M2) \ + ITM_READ_M_PV(T, R, M, M2) \ + ITM_READ_M_PV(T, RaR, M, M2) \ + ITM_READ_M_PV(T, RaW, M, M2) \ + ITM_READ_M_PV(T, RfW, M, M2) \ + ITM_WRITE_M_PV(T, W, M, M2) \ + ITM_WRITE_M_PV(T, WaR, M, M2) \ + ITM_WRITE_M_PV(T, WaW, M, M2) + +// Creates ABI load/store methods for all types. +// See CREATE_DISPATCH_FUNCTIONS for comments. +#define CREATE_DISPATCH_METHODS(M, M2) \ + CREATE_DISPATCH_METHODS_T (U1, M, M2) \ + CREATE_DISPATCH_METHODS_T (U2, M, M2) \ + CREATE_DISPATCH_METHODS_T (U4, M, M2) \ + CREATE_DISPATCH_METHODS_T (U8, M, M2) \ + CREATE_DISPATCH_METHODS_T (F, M, M2) \ + CREATE_DISPATCH_METHODS_T (D, M, M2) \ + CREATE_DISPATCH_METHODS_T (E, M, M2) \ + CREATE_DISPATCH_METHODS_T (CF, M, M2) \ + CREATE_DISPATCH_METHODS_T (CD, M, M2) \ + CREATE_DISPATCH_METHODS_T (CE, M, M2) +#define CREATE_DISPATCH_METHODS_PV(M, M2) \ + CREATE_DISPATCH_METHODS_T_PV (U1, M, M2) \ + CREATE_DISPATCH_METHODS_T_PV (U2, M, M2) \ + CREATE_DISPATCH_METHODS_T_PV (U4, M, M2) \ + CREATE_DISPATCH_METHODS_T_PV (U8, M, M2) \ + CREATE_DISPATCH_METHODS_T_PV (F, M, M2) \ + CREATE_DISPATCH_METHODS_T_PV (D, M, M2) \ + CREATE_DISPATCH_METHODS_T_PV (E, M, M2) \ + CREATE_DISPATCH_METHODS_T_PV (CF, M, M2) \ + CREATE_DISPATCH_METHODS_T_PV (CD, M, M2) \ + CREATE_DISPATCH_METHODS_T_PV (CE, M, M2) + +// Creates memcpy/memmove/memset methods. +#define CREATE_DISPATCH_METHODS_MEM() \ +virtual void memtransfer(void *dst, const void* src, size_t size, \ + bool may_overlap, ls_modifier dst_mod, ls_modifier src_mod) \ +{ \ + memtransfer_static(dst, src, size, may_overlap, dst_mod, src_mod); \ +} \ +virtual void memset(void *dst, int c, size_t size, ls_modifier mod) \ +{ \ + memset_static(dst, c, size, mod); \ +} + +#define CREATE_DISPATCH_METHODS_MEM_PV() \ +virtual void memtransfer(void *dst, const void* src, size_t size, \ + bool may_overlap, ls_modifier dst_mod, ls_modifier src_mod) = 0; \ +virtual void memset(void *dst, int c, size_t size, ls_modifier mod) = 0; + + +// Creates ABI load/store functions that can target either a class or an +// object. +#define ITM_READ(T, LSMOD, TARGET, M2) \ + _ITM_TYPE_##T ITM_REGPARM _ITM_##LSMOD##T (const _ITM_TYPE_##T *ptr) \ + { \ + return TARGET ITM_##LSMOD##T##M2(ptr); \ + } + +#define ITM_WRITE(T, LSMOD, TARGET, M2) \ + void ITM_REGPARM _ITM_##LSMOD##T (_ITM_TYPE_##T *ptr, _ITM_TYPE_##T val) \ + { \ + TARGET ITM_##LSMOD##T##M2(ptr, val); \ + } + +// Creates ABI load/store functions for all load/store modifiers for a +// particular type. +#define CREATE_DISPATCH_FUNCTIONS_T(T, TARGET, M2) \ + ITM_READ(T, R, TARGET, M2) \ + ITM_READ(T, RaR, TARGET, M2) \ + ITM_READ(T, RaW, TARGET, M2) \ + ITM_READ(T, RfW, TARGET, M2) \ + ITM_WRITE(T, W, TARGET, M2) \ + ITM_WRITE(T, WaR, TARGET, M2) \ + ITM_WRITE(T, WaW, TARGET, M2) + +// Creates ABI memcpy/memmove/memset functions. +#define ITM_MEMTRANSFER_DEF(TARGET, M2, NAME, READ, WRITE) \ +void ITM_REGPARM _ITM_memcpy##NAME(void *dst, const void *src, size_t size) \ +{ \ + TARGET memtransfer##M2 (dst, src, size, \ + false, GTM::abi_dispatch::WRITE, GTM::abi_dispatch::READ); \ +} \ +void ITM_REGPARM _ITM_memmove##NAME(void *dst, const void *src, size_t size) \ +{ \ + TARGET memtransfer##M2 (dst, src, size, \ + GTM::abi_dispatch::memmove_overlap_check(dst, src, size, \ + GTM::abi_dispatch::WRITE, GTM::abi_dispatch::READ), \ + GTM::abi_dispatch::WRITE, GTM::abi_dispatch::READ); \ +} + +#define ITM_MEMSET_DEF(TARGET, M2, WRITE) \ +void ITM_REGPARM _ITM_memset##WRITE(void *dst, int c, size_t size) \ +{ \ + TARGET memset##M2 (dst, c, size, GTM::abi_dispatch::WRITE); \ +} \ + + +// ??? The number of virtual methods is large (7*4 for integers, 7*6 for FP, +// 7*3 for vectors). Is the cache footprint so costly that we should go for +// a small table instead (i.e., only have two virtual load/store methods for +// each supported type)? Note that this doesn't affect custom code paths at +// all because these use only direct calls. +// A large cache footprint could especially decrease HTM performance (due +// to HTM capacity). We could add the modifier (RaR etc.) as parameter, which +// would give us just 4*2+6*2+3*2 functions (so we'd just need one line for +// the integer loads/stores), but then the modifier can be checked only at +// runtime. +// For memcpy/memmove/memset, we just have two virtual methods (memtransfer +// and memset). +#define CREATE_DISPATCH_FUNCTIONS(TARGET, M2) \ + CREATE_DISPATCH_FUNCTIONS_T (U1, TARGET, M2) \ + CREATE_DISPATCH_FUNCTIONS_T (U2, TARGET, M2) \ + CREATE_DISPATCH_FUNCTIONS_T (U4, TARGET, M2) \ + CREATE_DISPATCH_FUNCTIONS_T (U8, TARGET, M2) \ + CREATE_DISPATCH_FUNCTIONS_T (F, TARGET, M2) \ + CREATE_DISPATCH_FUNCTIONS_T (D, TARGET, M2) \ + CREATE_DISPATCH_FUNCTIONS_T (E, TARGET, M2) \ + CREATE_DISPATCH_FUNCTIONS_T (CF, TARGET, M2) \ + CREATE_DISPATCH_FUNCTIONS_T (CD, TARGET, M2) \ + CREATE_DISPATCH_FUNCTIONS_T (CE, TARGET, M2) \ + ITM_MEMTRANSFER_DEF(TARGET, M2, RnWt, NONTXNAL, W) \ + ITM_MEMTRANSFER_DEF(TARGET, M2, RnWtaR, NONTXNAL, WaR) \ + ITM_MEMTRANSFER_DEF(TARGET, M2, RnWtaW, NONTXNAL, WaW) \ + ITM_MEMTRANSFER_DEF(TARGET, M2, RtWn, R, NONTXNAL) \ + ITM_MEMTRANSFER_DEF(TARGET, M2, RtWt, R, W) \ + ITM_MEMTRANSFER_DEF(TARGET, M2, RtWtaR, R, WaR) \ + ITM_MEMTRANSFER_DEF(TARGET, M2, RtWtaW, R, WaW) \ + ITM_MEMTRANSFER_DEF(TARGET, M2, RtaRWn, RaR, NONTXNAL) \ + ITM_MEMTRANSFER_DEF(TARGET, M2, RtaRWt, RaR, W) \ + ITM_MEMTRANSFER_DEF(TARGET, M2, RtaRWtaR, RaR, WaR) \ + ITM_MEMTRANSFER_DEF(TARGET, M2, RtaRWtaW, RaR, WaW) \ + ITM_MEMTRANSFER_DEF(TARGET, M2, RtaWWn, RaW, NONTXNAL) \ + ITM_MEMTRANSFER_DEF(TARGET, M2, RtaWWt, RaW, W) \ + ITM_MEMTRANSFER_DEF(TARGET, M2, RtaWWtaR, RaW, WaR) \ + ITM_MEMTRANSFER_DEF(TARGET, M2, RtaWWtaW, RaW, WaW) \ + ITM_MEMSET_DEF(TARGET, M2, W) \ + ITM_MEMSET_DEF(TARGET, M2, WaR) \ + ITM_MEMSET_DEF(TARGET, M2, WaW) + + +// Creates ABI load/store functions that delegate to a transactional memcpy. +#define ITM_READ_MEMCPY(T, LSMOD, TARGET, M2) \ + _ITM_TYPE_##T ITM_REGPARM _ITM_##LSMOD##T (const _ITM_TYPE_##T *ptr)\ + { \ + _ITM_TYPE_##T v; \ + TARGET memtransfer##M2(&v, ptr, sizeof(_ITM_TYPE_##T), false, \ + GTM::abi_dispatch::NONTXNAL, GTM::abi_dispatch::LSMOD); \ + return v; \ + } + +#define ITM_WRITE_MEMCPY(T, LSMOD, TARGET, M2) \ + void ITM_REGPARM _ITM_##LSMOD##T (_ITM_TYPE_##T *ptr, _ITM_TYPE_##T val)\ + { \ + TARGET memtransfer##M2(ptr, &val, sizeof(_ITM_TYPE_##T), false, \ + GTM::abi_dispatch::LSMOD, GTM::abi_dispatch::NONTXNAL); \ + } + +#define CREATE_DISPATCH_FUNCTIONS_T_MEMCPY(T, TARGET, M2) \ + ITM_READ_MEMCPY(T, R, TARGET, M2) \ + ITM_READ_MEMCPY(T, RaR, TARGET, M2) \ + ITM_READ_MEMCPY(T, RaW, TARGET, M2) \ + ITM_READ_MEMCPY(T, RfW, TARGET, M2) \ + ITM_WRITE_MEMCPY(T, W, TARGET, M2) \ + ITM_WRITE_MEMCPY(T, WaR, TARGET, M2) \ + ITM_WRITE_MEMCPY(T, WaW, TARGET, M2) + + +namespace GTM HIDDEN { + +struct gtm_transaction_cp; + +struct method_group +{ + // Start using a TM method from this group. This constructs required meta + // data on demand when this method group is actually used. Will be called + // either on first use or after a previous call to fini(). + virtual void init() = 0; + // Stop using any method from this group for now. This can be used to + // destruct meta data as soon as this method group is not used anymore. + virtual void fini() = 0; +}; + + +// This is the base interface that all TM methods have to implement. +struct abi_dispatch +{ +public: + enum ls_modifier { NONTXNAL, R, RaR, RaW, RfW, W, WaR, WaW }; + +private: + // Disallow copies + abi_dispatch(const abi_dispatch &) = delete; + abi_dispatch& operator=(const abi_dispatch &) = delete; + +public: + // Starts or restarts a transaction. Is called right before executing the + // transactional application code (by either returning from + // gtm_thread::begin_transaction or doing the longjmp when restarting). + // Returns NO_RESTART if the transaction started successfully. Returns + // a real restart reason if it couldn't start and does need to abort. This + // allows TM methods to just give up and delegate ensuring progress to the + // restart mechanism. If it returns a restart reason, this call must be + // idempotent because it will trigger the restart mechanism, which could + // switch to a different TM method. + virtual gtm_restart_reason begin_or_restart() = 0; + // Tries to commit the transaction. Iff this returns true, the transaction + // got committed and all per-transaction data will have been reset. + // Currently, this is called only for the commit of the outermost + // transaction, or when switching to serial mode (which can happen in a + // nested transaction). + // If privatization safety must be ensured in a quiescence-based way, set + // priv_time to a value different to 0. Nontransactional code will not be + // executed after this commit until all registered threads' shared_state is + // larger than or equal to this value. + virtual bool trycommit(gtm_word& priv_time) = 0; + // Rolls back a transaction. Called on abort or after trycommit() returned + // false. + virtual void rollback(gtm_transaction_cp *cp = 0) = 0; + + // Return an alternative method that is compatible with the current + // method but supports closed nesting. Return zero if there is none. + // Note that too be compatible, it must be possible to switch to this other + // method on begin of a nested transaction without committing or restarting + // the parent method. + virtual abi_dispatch* closed_nesting_alternative() { return 0; } + + bool read_only () const { return m_read_only; } + bool write_through() const { return m_write_through; } + bool can_run_uninstrumented_code() const + { + return m_can_run_uninstrumented_code; + } + // Returns true iff this TM method supports closed nesting. + bool closed_nesting() const { return m_closed_nesting; } + method_group* get_method_group() const { return m_method_group; } + + static void *operator new(size_t s) { return xmalloc (s); } + static void operator delete(void *p) { free (p); } + +public: + static bool memmove_overlap_check(void *dst, const void *src, size_t size, + ls_modifier dst_mod, ls_modifier src_mod); + + // Creates the ABI dispatch methods for loads and stores. + // ??? Should the dispatch table instead be embedded in the dispatch object + // to avoid the indirect lookup in the vtable? + CREATE_DISPATCH_METHODS_PV(virtual, ) + // Creates the ABI dispatch methods for memcpy/memmove/memset. + CREATE_DISPATCH_METHODS_MEM_PV() + +protected: + const bool m_read_only; + const bool m_write_through; + const bool m_can_run_uninstrumented_code; + const bool m_closed_nesting; + method_group* const m_method_group; + abi_dispatch(bool ro, bool wt, bool uninstrumented, bool closed_nesting, + method_group* mg) : + m_read_only(ro), m_write_through(wt), + m_can_run_uninstrumented_code(uninstrumented), + m_closed_nesting(closed_nesting), m_method_group(mg) + { } +}; + +} + +#endif // DISPATCH_H diff --git a/libitm/eh_cpp.cc b/libitm/eh_cpp.cc new file mode 100644 index 00000000000..7cba97cc48c --- /dev/null +++ b/libitm/eh_cpp.cc @@ -0,0 +1,108 @@ +/* Copyright (C) 2009, 2011 Free Software Foundation, Inc. + Contributed by Richard Henderson <rth@redhat.com>. + + This file is part of the GNU Transactional Memory Library (libitm). + + Libitm is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + Libitm is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + <http://www.gnu.org/licenses/>. */ + +#include "libitm_i.h" + +using namespace GTM; + +/* Everything from libstdc++ is weak, to avoid requiring that library + to be linked into plain C applications using libitm.so. */ + +#define WEAK __attribute__((weak)) + +extern "C" { + +extern void *__cxa_allocate_exception (size_t) WEAK; +extern void __cxa_throw (void *, void *, void *) WEAK; +extern void *__cxa_begin_catch (void *) WEAK; +extern void *__cxa_end_catch (void) WEAK; +extern void __cxa_tm_cleanup (void *, void *, unsigned int) WEAK; + +} + + +void * +_ITM_cxa_allocate_exception (size_t size) +{ + void *r = __cxa_allocate_exception (size); + gtm_thr()->cxa_unthrown = r; + return r; +} + +void +_ITM_cxa_throw (void *obj, void *tinfo, void *dest) +{ + gtm_thr()->cxa_unthrown = NULL; + __cxa_throw (obj, tinfo, dest); +} + +void * +_ITM_cxa_begin_catch (void *exc_ptr) +{ + gtm_thr()->cxa_catch_count++; + return __cxa_begin_catch (exc_ptr); +} + +void +_ITM_cxa_end_catch (void) +{ + gtm_thr()->cxa_catch_count--; + __cxa_end_catch (); +} + +void +GTM::gtm_thread::revert_cpp_exceptions (gtm_transaction_cp *cp) +{ + if (cp) + { + // If rolling back a nested transaction, only clean up unthrown + // exceptions since the last checkpoint. Always reset eh_in_flight + // because it just contains the argument provided to + // _ITM_commitTransactionEH + void *unthrown = + (cxa_unthrown != cp->cxa_unthrown ? cxa_unthrown : NULL); + assert (cxa_catch_count >= cp->cxa_catch_count); + uint32_t catch_count = cxa_catch_count - cp->cxa_catch_count; + if (unthrown || catch_count) + { + __cxa_tm_cleanup (unthrown, this->eh_in_flight, catch_count); + cxa_catch_count = cp->cxa_catch_count; + cxa_unthrown = cp->cxa_unthrown; + this->eh_in_flight = NULL; + } + } + else + { + // Both cxa_catch_count and cxa_unthrown are maximal because EH regions + // and transactions are properly nested. + if (this->cxa_unthrown || this->cxa_catch_count) + { + __cxa_tm_cleanup (this->cxa_unthrown, this->eh_in_flight, + this->cxa_catch_count); + this->cxa_catch_count = 0; + this->cxa_unthrown = NULL; + this->eh_in_flight = NULL; + } + } +} diff --git a/libitm/libitm.h b/libitm/libitm.h new file mode 100644 index 00000000000..80ae96dedb9 --- /dev/null +++ b/libitm/libitm.h @@ -0,0 +1,288 @@ +/* Copyright (C) 2008, 2009, 2011 Free Software Foundation, Inc. + Contributed by Richard Henderson <rth@redhat.com>. + + This file is part of the GNU Transactional Memory Library (libitm). + + Libitm is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + Libitm is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + <http://www.gnu.org/licenses/>. */ + +/* The external interface of this library follows the specification described + in version 1 of http://www.intel.com/some/path/here.pdf. */ + +#ifndef LIBITM_H +#define LIBITM_H 1 + +#include <stddef.h> +#include <stdbool.h> +#include <stdint.h> + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __i386__ +/* Only for 32-bit x86. */ +# define ITM_REGPARM __attribute__((regparm(2))) +#else +# define ITM_REGPARM +#endif + +#define ITM_NORETURN __attribute__((noreturn)) +#define ITM_PURE __attribute__((transaction_pure)) + +/* The following are externally visible definitions and functions, though + only very few of these should be called by user code. */ + +/* Values used as arguments to abort. */ +typedef enum { + userAbort = 1, + userRetry = 2, + TMConflict= 4, + exceptionBlockAbort = 8, + outerAbort = 16 +} _ITM_abortReason; + +/* Arguments to changeTransactionMode */ +typedef enum +{ + modeSerialIrrevocable, +} _ITM_transactionState; + +/* Results from inTransaction */ +typedef enum +{ + outsideTransaction = 0, /* So "if (inTransaction(td))" works */ + inRetryableTransaction, + inIrrevocableTransaction +} _ITM_howExecuting; + +/* Values to describe properties of code, passed in to beginTransaction */ +typedef enum +{ + pr_instrumentedCode = 0x0001, + pr_uninstrumentedCode = 0x0002, + pr_multiwayCode = pr_instrumentedCode | pr_uninstrumentedCode, + /* Called pr_hasNoXMMUpdate in the Intel document, used for + avoiding vector register save/restore for any target. */ + pr_hasNoVectorUpdate = 0x0004, + pr_hasNoAbort = 0x0008, + /* Not present in the Intel document, used for avoiding + floating point register save/restore for any target. */ + pr_hasNoFloatUpdate = 0x0010, + pr_hasNoIrrevocable = 0x0020, + pr_doesGoIrrevocable = 0x0040, + pr_aWBarriersOmitted = 0x0100, + pr_RaRBarriersOmitted = 0x0200, + pr_undoLogCode = 0x0400, + pr_preferUninstrumented = 0x0800, + /* Exception blocks are not used nor supported. */ + pr_exceptionBlock = 0x1000, + pr_hasElse = 0x2000, + pr_readOnly = 0x4000, + pr_hasNoSimpleReads = 0x400000 +} _ITM_codeProperties; + +/* Result from startTransaction that describes what actions to take. */ +typedef enum +{ + a_runInstrumentedCode = 0x01, + a_runUninstrumentedCode = 0x02, + a_saveLiveVariables = 0x04, + a_restoreLiveVariables = 0x08, + a_abortTransaction = 0x10, +} _ITM_actions; + +typedef struct +{ + uint32_t reserved_1; + uint32_t flags; + uint32_t reserved_2; + uint32_t reserved_3; + const char *psource; +} _ITM_srcLocation; + +typedef void (* _ITM_userUndoFunction)(void *); +typedef void (* _ITM_userCommitFunction) (void *); + +#define _ITM_VERSION "0.90 (Feb 29 2008)" +#define _ITM_VERSION_NO 90 + +extern int _ITM_versionCompatible (int) ITM_REGPARM; +extern const char * _ITM_libraryVersion (void) ITM_REGPARM; + +void _ITM_error(const _ITM_srcLocation *, int errorCode) + ITM_REGPARM ITM_NORETURN; + +extern _ITM_howExecuting _ITM_inTransaction(void) ITM_REGPARM; + +typedef uint64_t _ITM_transactionId_t; /* Transaction identifier */ +#define _ITM_noTransactionId 1 /* Id for non-transactional code. */ + +extern _ITM_transactionId_t _ITM_getTransactionId(void) ITM_REGPARM; + +extern uint32_t _ITM_beginTransaction(uint32_t, ...) ITM_REGPARM; + +extern void _ITM_abortTransaction(_ITM_abortReason) ITM_REGPARM ITM_NORETURN; + +extern void _ITM_commitTransaction (void) ITM_REGPARM; + +extern void _ITM_changeTransactionMode (_ITM_transactionState) ITM_REGPARM; + +extern void _ITM_addUserCommitAction(_ITM_userCommitFunction, + _ITM_transactionId_t, void *) ITM_REGPARM; + +extern void _ITM_addUserUndoAction(_ITM_userUndoFunction, void *) ITM_REGPARM; + +extern int _ITM_getThreadnum(void) ITM_REGPARM; + +extern void _ITM_dropReferences (void *, size_t) ITM_REGPARM ITM_PURE; + +extern void *_ITM_malloc (size_t) + __attribute__((__malloc__)) ITM_PURE; + +extern void *_ITM_calloc (size_t, size_t) + __attribute__((__malloc__)) ITM_PURE; + +extern void _ITM_free (void *) ITM_PURE; + + +/* The following typedefs exist to make the macro expansions below work + properly. They are not part of any API. */ +typedef uint8_t _ITM_TYPE_U1; +typedef uint16_t _ITM_TYPE_U2; +typedef uint32_t _ITM_TYPE_U4; +typedef uint64_t _ITM_TYPE_U8; +typedef float _ITM_TYPE_F; +typedef double _ITM_TYPE_D; +typedef long double _ITM_TYPE_E; +typedef float _Complex _ITM_TYPE_CF; +typedef double _Complex _ITM_TYPE_CD; +typedef long double _Complex _ITM_TYPE_CE; + +#define ITM_BARRIERS(T) \ + extern _ITM_TYPE_##T _ITM_R##T(const _ITM_TYPE_##T *) ITM_REGPARM; \ + extern _ITM_TYPE_##T _ITM_RaR##T(const _ITM_TYPE_##T *) ITM_REGPARM; \ + extern _ITM_TYPE_##T _ITM_RaW##T(const _ITM_TYPE_##T *) ITM_REGPARM; \ + extern _ITM_TYPE_##T _ITM_RfW##T(const _ITM_TYPE_##T *) ITM_REGPARM; \ + extern void _ITM_W##T (_ITM_TYPE_##T *, _ITM_TYPE_##T) ITM_REGPARM; \ + extern void _ITM_WaR##T (_ITM_TYPE_##T *, _ITM_TYPE_##T) ITM_REGPARM; \ + extern void _ITM_WaW##T (_ITM_TYPE_##T *, _ITM_TYPE_##T) ITM_REGPARM; + +ITM_BARRIERS(U1) +ITM_BARRIERS(U2) +ITM_BARRIERS(U4) +ITM_BARRIERS(U8) +ITM_BARRIERS(F) +ITM_BARRIERS(D) +ITM_BARRIERS(E) +ITM_BARRIERS(CF) +ITM_BARRIERS(CD) +ITM_BARRIERS(CE) + +#define ITM_LOG(T) \ + extern void _ITM_L##T (const _ITM_TYPE_##T *) ITM_REGPARM; + +ITM_LOG(U1) +ITM_LOG(U2) +ITM_LOG(U4) +ITM_LOG(U8) +ITM_LOG(F) +ITM_LOG(D) +ITM_LOG(E) +ITM_LOG(CF) +ITM_LOG(CD) +ITM_LOG(CE) + +#if defined(__i386__) || defined(__x86_64__) +# ifdef __MMX__ + typedef int _ITM_TYPE_M64 __attribute__((vector_size(8), may_alias)); + ITM_BARRIERS(M64) + ITM_LOG(M64) +# endif +# ifdef __SSE__ + typedef float _ITM_TYPE_M128 __attribute__((vector_size(16), may_alias)); + ITM_BARRIERS(M128) + ITM_LOG(M128) +# endif +# ifdef __AVX__ + typedef float _ITM_TYPE_M256 __attribute__((vector_size(32), may_alias)); + ITM_BARRIERS(M256) + ITM_LOG(M256) +# endif +#endif /* i386 */ + +#undef ITM_BARRIERS +#undef ITM_LOG + +extern void _ITM_LB (const void *, size_t) ITM_REGPARM; + +extern void _ITM_memcpyRnWt(void *, const void *, size_t) ITM_REGPARM; +extern void _ITM_memcpyRnWtaR(void *, const void *, size_t) ITM_REGPARM; +extern void _ITM_memcpyRnWtaW(void *, const void *, size_t) ITM_REGPARM; +extern void _ITM_memcpyRtWn(void *, const void *, size_t) ITM_REGPARM; +extern void _ITM_memcpyRtWt(void *, const void *, size_t) ITM_REGPARM; +extern void _ITM_memcpyRtWtaR(void *, const void *, size_t) ITM_REGPARM; +extern void _ITM_memcpyRtWtaW(void *, const void *, size_t) ITM_REGPARM; +extern void _ITM_memcpyRtaRWn(void *, const void *, size_t) ITM_REGPARM; +extern void _ITM_memcpyRtaRWt(void *, const void *, size_t) ITM_REGPARM; +extern void _ITM_memcpyRtaRWtaR(void *, const void *, size_t) ITM_REGPARM; +extern void _ITM_memcpyRtaRWtaW(void *, const void *, size_t) ITM_REGPARM; +extern void _ITM_memcpyRtaWWn(void *, const void *, size_t) ITM_REGPARM; +extern void _ITM_memcpyRtaWWt(void *, const void *, size_t) ITM_REGPARM; +extern void _ITM_memcpyRtaWWtaR(void *, const void *, size_t) ITM_REGPARM; +extern void _ITM_memcpyRtaWWtaW(void *, const void *, size_t) ITM_REGPARM; + +extern void _ITM_memmoveRnWt(void *, const void *, size_t) ITM_REGPARM; +extern void _ITM_memmoveRnWtaR(void *, const void *, size_t) ITM_REGPARM; +extern void _ITM_memmoveRnWtaW(void *, const void *, size_t) ITM_REGPARM; +extern void _ITM_memmoveRtWn(void *, const void *, size_t) ITM_REGPARM; +extern void _ITM_memmoveRtWt(void *, const void *, size_t) ITM_REGPARM; +extern void _ITM_memmoveRtWtaR(void *, const void *, size_t) ITM_REGPARM; +extern void _ITM_memmoveRtWtaW(void *, const void *, size_t) ITM_REGPARM; +extern void _ITM_memmoveRtaRWn(void *, const void *, size_t) ITM_REGPARM; +extern void _ITM_memmoveRtaRWt(void *, const void *, size_t) ITM_REGPARM; +extern void _ITM_memmoveRtaRWtaR(void *, const void *, size_t) ITM_REGPARM; +extern void _ITM_memmoveRtaRWtaW(void *, const void *, size_t) ITM_REGPARM; +extern void _ITM_memmoveRtaWWn(void *, const void *, size_t) ITM_REGPARM; +extern void _ITM_memmoveRtaWWt(void *, const void *, size_t) ITM_REGPARM; +extern void _ITM_memmoveRtaWWtaR(void *, const void *, size_t) ITM_REGPARM; +extern void _ITM_memmoveRtaWWtaW(void *, const void *, size_t) ITM_REGPARM; + +extern void _ITM_memsetW(void *, int, size_t) ITM_REGPARM; +extern void _ITM_memsetWaR(void *, int, size_t) ITM_REGPARM; +extern void _ITM_memsetWaW(void *, int, size_t) ITM_REGPARM; + +// ??? These are not yet in the official spec; still work-in-progress. + +extern void *_ITM_getTMCloneOrIrrevocable (void *) ITM_REGPARM; +extern void *_ITM_getTMCloneSafe (void *) ITM_REGPARM; +extern void _ITM_registerTMCloneTable (void *, size_t); +extern void _ITM_deregisterTMCloneTable (void *); + +extern void *_ITM_cxa_allocate_exception (size_t); +extern void _ITM_cxa_throw (void *obj, void *tinfo, void *dest); +extern void *_ITM_cxa_begin_catch (void *exc_ptr); +extern void _ITM_cxa_end_catch (void); +extern void _ITM_commitTransactionEH(void *exc_ptr) ITM_REGPARM; + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* LIBITM_H */ diff --git a/libitm/libitm.map b/libitm/libitm.map new file mode 100644 index 00000000000..49d0b1b5ebb --- /dev/null +++ b/libitm/libitm.map @@ -0,0 +1,185 @@ +LIBITM_1.0 { + global: + _ITM_abortTransaction; + _ITM_addUserCommitAction; + _ITM_addUserUndoAction; + _ITM_beginTransaction; + _ITM_changeTransactionMode; + _ITM_commitTransaction; + _ITM_commitTransactionEH; + _ITM_error; + _ITM_getThreadnum; + _ITM_getTransactionId; + _ITM_inTransaction; + _ITM_libraryVersion; + _ITM_versionCompatible; + + _ITM_registerTMCloneTable; + _ITM_deregisterTMCloneTable; + _ITM_getTMCloneOrIrrevocable; + _ITM_getTMCloneSafe; + + _ITM_LB; + _ITM_LCD; + _ITM_LCE; + _ITM_LCF; + _ITM_LD; + _ITM_LE; + _ITM_LF; + _ITM_LM128; + _ITM_LM256; + _ITM_LM64; + _ITM_LU1; + _ITM_LU2; + _ITM_LU4; + _ITM_LU8; + + _ITM_RCD; + _ITM_RCE; + _ITM_RCF; + _ITM_RD; + _ITM_RE; + _ITM_RF; + _ITM_RM128; + _ITM_RM256; + _ITM_RM64; + _ITM_RU1; + _ITM_RU2; + _ITM_RU4; + _ITM_RU8; + _ITM_RaRCD; + _ITM_RaRCE; + _ITM_RaRCF; + _ITM_RaRD; + _ITM_RaRE; + _ITM_RaRF; + _ITM_RaRM128; + _ITM_RaRM256; + _ITM_RaRM64; + _ITM_RaRU1; + _ITM_RaRU2; + _ITM_RaRU4; + _ITM_RaRU8; + _ITM_RaWCD; + _ITM_RaWCE; + _ITM_RaWCF; + _ITM_RaWD; + _ITM_RaWE; + _ITM_RaWF; + _ITM_RaWM128; + _ITM_RaWM256; + _ITM_RaWM64; + _ITM_RaWU1; + _ITM_RaWU2; + _ITM_RaWU4; + _ITM_RaWU8; + _ITM_RfWCD; + _ITM_RfWCE; + _ITM_RfWCF; + _ITM_RfWD; + _ITM_RfWE; + _ITM_RfWF; + _ITM_RfWM128; + _ITM_RfWM256; + _ITM_RfWM64; + _ITM_RfWU1; + _ITM_RfWU2; + _ITM_RfWU4; + _ITM_RfWU8; + + _ITM_WCD; + _ITM_WCE; + _ITM_WCF; + _ITM_WD; + _ITM_WE; + _ITM_WF; + _ITM_WM128; + _ITM_WM256; + _ITM_WM64; + _ITM_WU1; + _ITM_WU2; + _ITM_WU4; + _ITM_WU8; + _ITM_WaRCD; + _ITM_WaRCE; + _ITM_WaRCF; + _ITM_WaRD; + _ITM_WaRE; + _ITM_WaRF; + _ITM_WaRM128; + _ITM_WaRM256; + _ITM_WaRM64; + _ITM_WaRU1; + _ITM_WaRU2; + _ITM_WaRU4; + _ITM_WaRU8; + _ITM_WaWCD; + _ITM_WaWCE; + _ITM_WaWCF; + _ITM_WaWD; + _ITM_WaWE; + _ITM_WaWF; + _ITM_WaWM128; + _ITM_WaWM256; + _ITM_WaWM64; + _ITM_WaWU1; + _ITM_WaWU2; + _ITM_WaWU4; + _ITM_WaWU8; + + _ITM_memcpyRnWt; + _ITM_memcpyRnWtaR; + _ITM_memcpyRnWtaW; + _ITM_memcpyRtWn; + _ITM_memcpyRtWt; + _ITM_memcpyRtWtaR; + _ITM_memcpyRtWtaW; + _ITM_memcpyRtaRWn; + _ITM_memcpyRtaRWt; + _ITM_memcpyRtaRWtaR; + _ITM_memcpyRtaRWtaW; + _ITM_memcpyRtaWWn; + _ITM_memcpyRtaWWt; + _ITM_memcpyRtaWWtaR; + _ITM_memcpyRtaWWtaW; + _ITM_memmoveRnWt; + _ITM_memmoveRnWtaR; + _ITM_memmoveRnWtaW; + _ITM_memmoveRtWn; + _ITM_memmoveRtWt; + _ITM_memmoveRtWtaR; + _ITM_memmoveRtWtaW; + _ITM_memmoveRtaRWn; + _ITM_memmoveRtaRWt; + _ITM_memmoveRtaRWtaR; + _ITM_memmoveRtaRWtaW; + _ITM_memmoveRtaWWn; + _ITM_memmoveRtaWWt; + _ITM_memmoveRtaWWtaR; + _ITM_memmoveRtaWWtaW; + _ITM_memsetW; + _ITM_memsetWaR; + _ITM_memsetWaW; + + _ITM_malloc; + _ITM_calloc; + _ITM_free; + _ITM_dropReferences; + + _ZGTtnw?; + _ZGTtna?; + _ZGTtdlPv; + _ZGTtdaPv; + _ZGTtnw?RKSt9nothrow_t; + _ZGTtna?RKSt9nothrow_t; + _ZGTtdlPvRKSt9nothrow_t; + _ZGTtdaPvRKSt9nothrow_t; + + _ITM_cxa_allocate_exception; + _ITM_cxa_begin_catch; + _ITM_cxa_end_catch; + _ITM_cxa_throw; + + local: + *; +}; diff --git a/libitm/libitm.spec.in b/libitm/libitm.spec.in new file mode 100644 index 00000000000..eccc091fbdc --- /dev/null +++ b/libitm/libitm.spec.in @@ -0,0 +1,3 @@ +# This spec file is read by gcc when linking. It is used to specify the +# standard libraries we need in order to link with -fgnu-tm +*link_itm: @link_itm@ diff --git a/libitm/libitm.texi b/libitm/libitm.texi new file mode 100644 index 00000000000..b31657f7f97 --- /dev/null +++ b/libitm/libitm.texi @@ -0,0 +1,739 @@ +\input texinfo @c -*-texinfo-*- + +@c %**start of header +@setfilename libitm.info +@settitle GNU libitm +@c %**end of header + + +@copying +Copyright @copyright{} 2011 Free Software Foundation, Inc. + +Permission is granted to copy, distribute and/or modify this document +under the terms of the GNU Free Documentation License, Version 1.2 or +any later version published by the Free Software Foundation; with no +Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. +A copy of the license is included in the section entitled ``GNU +Free Documentation License''. +@end copying + +@ifinfo +@dircategory GNU Libraries +@direntry +* libitm: (libitm). GNU Transactional Memory Library +@end direntry + +This manual documents the GNU Transactional Memory Library. + +@insertcopying +@end ifinfo + + +@setchapternewpage odd + +@titlepage +@title The GNU Transactional Memory Library +@page +@vskip 0pt plus 1filll +@comment For the @value{version-GCC} Version* +@sp 1 +@insertcopying +@end titlepage + +@summarycontents +@contents +@page + + +@node Top +@top Introduction +@cindex Introduction + +This manual documents the usage and internals of libitm, the GNU Transactional +Memory Library. It provides transaction support for accesses to a process' +memory, enabling easy-to-use synchronization of accesses to shared memory by +several threads. + + +@comment +@comment When you add a new menu item, please keep the right hand +@comment aligned to the same column. Do not use tabs. This provides +@comment better formatting. +@comment +@menu +* Enabling libitm:: How to enable libitm for your applications. +* C/C++ Language Constructs for TM:: + Notes on the language-level interface supported + by gcc. +* The libitm ABI:: Notes on the external ABI provided by libitm. +* Internals:: Notes on libitm's internal synchronization. +* GNU Free Documentation License:: + How you can copy and share this manual. +* Index:: Index of this documentation. +@end menu + + +@c --------------------------------------------------------------------- +@c Enabling libitm +@c --------------------------------------------------------------------- + +@node Enabling libitm +@chapter Enabling libitm + +To activate support for TM in C/C++, the compile-time flag @option{-fgnu-tm} +must be specified. This enables TM language-level constructs such as +transaction statements (@code{__transaction}, @pxref{C/C++ Language +Constructs for TM} for details). + +@c --------------------------------------------------------------------- +@c C/C++ Language Constructs for TM +@c --------------------------------------------------------------------- + +@node C/C++ Language Constructs for TM +@chapter C/C++ Language Constructs for TM + +TODO: link to the C++ TM spec. a few examples. how gcc's support differs. + +@c --------------------------------------------------------------------- +@c The libitm ABI +@c --------------------------------------------------------------------- + +@node The libitm ABI +@chapter The libitm ABI + +The ABI provided by libitm is basically equal to the Linux variant of Intel's +current TM ABI specification document (Revision 1.1, May 6 2009) but with the +differences listed in this chapter. It would be good if these changes would +eventually be merged into a future version of this specification. To ease +look-up, the following subsections mirror the structure of this specification. + +@section [No changes] Objectives +@section [No changes] Non-objectives + +@section Library design principles +@subsection [No changes] Calling conventions +@subsection [No changes] TM library algorithms +@subsection [No changes] Optimized load and store routines +@subsection [No changes] Aligned load and store routines + +@subsection Data logging functions + +The memory locations accessed with transactional loads and stores and the +memory locations whose values are logged must not overlap. This required +separation only extends to the scope of the execution of one transaction +including all the executions of all nested transactions. + +The compiler must be consistent (within the scope of a single transaction) +about which memory locations are shared and which are not shared with other +threads (i.e., data must be accessed either transactionally or +nontransactionally). Otherwise, non-write-through TM algorithms would not work. + +@subsection [No changes] Scatter/gather calls +@subsection [No changes] Serial and irrevocable mode +@subsection [No changes] Transaction descriptor +@subsection Store allocation + +There is no @code{getTransaction} function. + +@subsection [No changes] Naming conventions + +@subsection Function pointer encryption + +Currently, this is not implemented. + + +@section Types and macros list + +@code{_ITM_codeProperties} has changed, @pxref{txn-code-properties,,Starting a +transaction}. +@code{_ITM_srcLocation} is not used. + + +@section Function list + +@subsection Initialization and finalization functions +These functions are not part of the ABI. + +@subsection [No changes] Version checking +@subsection [No changes] Error reporting +@subsection [No changes] inTransaction call + +@subsection State manipulation functions +There is no @code{getTransaction} function. Transaction identifiers for +nested transactions will be ordered but not necessarily sequential (i.e., for +a nested transaction's identifier @var{IN} and its enclosing transaction's +identifier @var{IE}, it is guaranteed that @math{IN >= IE}). + +@subsection [No changes] Source locations + +@subsection Starting a transaction + +@subsubsection Transaction code properties + +@anchor{txn-code-properties} +The bit @code{hasNoXMMUpdate} is instead called @code{hasNoVectorUpdate}. +Iff it is set, vector register save/restore is not necessary for any target +machine. + +The @code{hasNoFloatUpdate} bit (@code{0x0010}) is new. Iff it is set, floating +point register save/restore is not necessary for any target machine. + +@code{undoLogCode} is not supported and a fatal runtime error will be raised +if this bit is set. It is not properly defined in the ABI why barriers +other than undo logging are not present; Are they not necessary (e.g., a +transaction operating purely on thread-local data) or have they been omitted by +the compiler because it thinks that some kind of global synchronization +(e.g., serial mode) might perform better? The specification suggests that the +latter might be the case, but the former seems to be more useful. + +The @code{readOnly} bit (@code{0x4000}) is new. @strong{TODO} Lexical or dynamic +scope? + +@code{hasNoRetry} is not supported. If this bit is not set, but +@code{hasNoAbort} is set, the library can assume that transaction +rollback will not be requested. + +It would be useful if the absence of externally-triggered rollbacks would be +reported for the dynamic scope as well, not just for the lexical scope +(@code{hasNoAbort}). Without this, a library cannot exploit this together +with flat nesting. + +@code{exceptionBlock} is not supported because exception blocks are not used. + +@subsubsection [No changes] Windows exception state +@subsubsection [No changes] Other machine state + +@subsubsection [No changes] Results from beginTransaction + +@subsection Aborting a transaction + +@code{_ITM_rollbackTransaction} is not supported. @code{_ITM_abortTransaction} +is supported but the abort reasons @code{exceptionBlockAbort}, +@code{TMConflict}, and @code{userRetry} are not supported. There are no +exception blocks in general, so the related cases also do not have to be +considered. To encode @code{__transaction_cancel [[outer]]}, compilers must +set the new @code{outerAbort} bit (@code{0x10}) additionally to the +@code{userAbort} bit in the abort reason. + +@subsection Committing a transaction + +The exception handling (EH) scheme is different. The Intel ABI requires the +@code{_ITM_tryCommitTransaction} function that will return even when the +commit failed and will have to be matched with calls to either +@code{_ITM_abortTransaction} or @code{_ITM_commitTransaction}. In contrast, +gcc relies on transactional wrappers for the functions of the Exception +Handling ABI and on one additional commit function (shown below). This allows +the TM to keep track of EH internally and thus it does not have to embed the +cleanup of EH state into the existing EH code in the program. +@code{_ITM_tryCommitTransaction} is not supported. +@code{_ITM_commitTransactionToId} is also not supported because the +propagation of thrown exceptions will not bypass commits of nested +transactions. + +@example +void _ITM_commitTransactionEH(void *exc_ptr) ITM_REGPARM; +void *_ITM_cxa_allocate_exception (size_t); +void _ITM_cxa_throw (void *obj, void *tinfo, void *dest); +void *_ITM_cxa_begin_catch (void *exc_ptr); +void _ITM_cxa_end_catch (void); +@end example + +@code{_ITM_commitTransactionEH} must be called to commit a transaction if an +exception could be in flight at this position in the code. @code{exc_ptr} is +the current exception or zero if there is no current exception. +The @code{_ITM_cxa...} functions are transactional wrappers for the respective +@code{__cxa...} functions and must be called instead of these in transactional +code. + +To support this EH scheme, libstdc++ needs to provide one additional function +(@code{_cxa_tm_cleanup}), which is used by the TM to clean up the exception +handling state while rolling back a transaction: + +@example +void __cxa_tm_cleanup (void *unthrown_obj, void *cleanup_exc, + unsigned int caught_count); +@end example + +@code{unthrown_obj} is non-null if the program called +@code{__cxa_allocate_exception} for this exception but did not yet called +@code{__cxa_throw} for it. @code{cleanup_exc} is non-null if the program is +currently processing a cleanup along an exception path but has not caught this +exception yet. @code{caught_count} is the nesting depth of +@code{__cxa_begin_catch} within the transaction (which can be counted by the TM +using @code{_ITM_cxa_begin_catch} and @code{_ITM_cxa_end_catch}); +@code{__cxa_tm_cleanup} then performs rollback by essentially performing +@code{__cxa_end_catch} that many times. + + + +@subsection Exception handling support + +Currently, there is no support for functionality like +@code{__transaction_cancel throw} as described in the C++ TM specification. +Supporting this should be possible with the EH scheme explained previously +because via the transactional wrappers for the EH ABI, the TM is able to +observe and intercept EH. + + +@subsection [No changes] Transition to serial--irrevocable mode +@subsection [No changes] Data transfer functions +@subsection [No changes] Transactional memory copies + +@subsection Transactional versions of memmove + +If either the source or destination memory region is to be accessed +nontransactionally, then source and destination regions must not be +overlapping. The respective @code{_ITM_memmove} functions are still +available but a fatal runtime error will be raised if such regions do overlap. +To support this functionality, the ABI would have to specify how the +intersection of the regions has to be accessed (i.e., transactionally or +nontransactionally). + +@subsection [No changes] Transactional versions of memset +@subsection [No changes] Logging functions + +@subsection User-registered commit and undo actions + +Commit actions will get executed in the same order in which the respective +calls to @code{_ITM_addUserCommitAction} happened. Only +@code{_ITM_noTransactionId} is allowed as value for the +@code{resumingTransactionId} argument. Commit actions get executed after +privatization safety has been ensured. + +Undo actions will get executed in reverse order compared to the order in which +the respective calls to @code{_ITM_addUserUndoAction} happened. The ordering of +undo actions w.r.t. the roll-back of other actions (e.g., data transfers or +memory allocations) is undefined. + +@code{_ITM_getThreadnum} is not supported currently because its only purpose +is to provide a thread ID that matches some assumed performance tuning output, +but this output is not part of the ABI nor further defined by it. + +@code{_ITM_dropReferences} is not supported currently because its semantics and +the intention behind it is not entirely clear. The +specification suggests that this function is necessary because of certain +orderings of data transfer undos and the releasing of memory regions (i.e., +privatization). However, this ordering is never defined, nor is the ordering of +dropping references w.r.t. other events. + +@subsection [New] Transactional indirect calls + +Indirect calls (i.e., calls through a function pointer) within transactions +should execute the transactional clone of the original function (i.e., a clone +of the original that has been fully instrumented to use the TM runtime), if +such a clone is available. The runtime provides two functions to +register/deregister clone tables: + +@example +struct clone_entry +@{ + void *orig, *clone; +@}; + +void _ITM_registerTMCloneTable (clone_entry *table, size_t entries); +void _ITM_deregisterTMCloneTable (clone_entry *table); +@end example + +Registered tables must be writable by the TM runtime, and must be live +throughout the life-time of the TM runtime. + +@strong{TODO} The intention was always to drop the registration functions +entirely, and create a new ELF Phdr describing the linker-sorted table. Much +like what currently happens for @code{PT_GNU_EH_FRAME}. +This work kept getting bogged down in how to represent the @var{N} different +code generation variants. We clearly needed at least two---SW and HW +transactional clones---but there was always a suggestion of more variants for +different TM assumptions/invariants. + +The compiler can then use two TM runtime functions to perform indirect calls in +transactions: +@example +void *_ITM_getTMCloneOrIrrevocable (void *function) ITM_REGPARM; +void *_ITM_getTMCloneSafe (void *function) ITM_REGPARM; +@end example + +If there is a registered clone for supplied function, both will return a +pointer to the clone. If not, the first runtime function will attempt to switch +to serial--irrevocable mode and return the original pointer, whereas the second +will raise a fatal runtime error. + +@subsection [New] Transactional dynamic memory management + +@example +void *_ITM_malloc (size_t) + __attribute__((__malloc__)) ITM_PURE; +void *_ITM_calloc (size_t, size_t) + __attribute__((__malloc__)) ITM_PURE; +void _ITM_free (void *) ITM_PURE; +@end example + +These functions are essentially transactional wrappers for @code{malloc}, +@code{calloc}, and @code{free}. Within transactions, the compiler should +replace calls to the original functions with calls to the wrapper functions. + + +@section [No changes] Future Enhancements to the ABI + +@section Sample code + +The code examples might not be correct w.r.t. the current version of the ABI, +especially everything related to exception handling. + + +@section [New] Memory model + +The ABI should define a memory model and the ordering that is guaranteed for +data transfers and commit/undo actions, or at least refer to another memory +model that needs to be preserved. Without that, the compiler cannot ensure the +memory model specified on the level of the programming language (e.g., by the +C++ TM specification). + +For example, if a transactional load is ordered before another load/store, then +the TM runtime must also ensure this ordering when accessing shared state. If +not, this might break the kind of publication safety used in the C++ TM +specification. Likewise, the TM runtime must ensure privatization safety. + + + +@c --------------------------------------------------------------------- +@c Internals +@c --------------------------------------------------------------------- + +@node Internals +@chapter Internals + +@section TM methods and method groups + +libitm supports several ways of synchronizing transactions with each other. +These TM methods (or TM algorithms) are implemented in the form of +subclasses of @code{abi_dispatch}, which provide methods for +transactional loads and stores as well as callbacks for rollback and commit. +All methods that are compatible with each other (i.e., that let concurrently +running transactions still synchronize correctly even if different methods +are used) belong to the same TM method group. Pointers to TM methods can be +obtained using the factory methods prefixed with @code{dispatch_} in +@file{libitm_i.h}. There are two special methods, @code{dispatch_serial} and +@code{dispatch_serialirr}, that are compatible with all methods because they +run transactions completely in serial mode. + +@subsection TM method life cycle + +The state of TM methods does not change after construction, but they do alter +the state of transactions that use this method. However, because +per-transaction data gets used by several methods, @code{gtm_thread} is +responsible for setting an initial state that is useful for all methods. +After that, methods are responsible for resetting/clearing this state on each +rollback or commit (of outermost transactions), so that the transaction +executed next is not affected by the previous transaction. + +There is also global state associated with each method group, which is +initialized and shut down (@code{method_group::init()} and @code{fini()}) +when switching between method groups (see @file{retry.cc}). + +@subsection Selecting the default method + +The default method that libitm uses for freshly started transactions (but +not necessarily for restarted transactions) can be set via an environment +variable (@env{ITM_DEFAULT_METHOD}), whose value should be equal to the name +of one of the factory methods returning abi_dispatch subclasses but without +the "dispatch_" prefix (e.g., "serialirr" instead of +@code{GTM::dispatch_serialirr()}). + +Note that this environment variable is only a hint for libitm and might not +be supported in the future. + + +@section Nesting: flat vs. closed + +We support two different kinds of nesting of transactions. In the case of +@emph{flat nesting}, the nesting structure is flattened and all nested +transactions are subsumed by the enclosing transaction. In contrast, +with @emph{closed nesting}, nested transactions that have not yet committed +can be rolled back separately from the enclosing transactions; when they +commit, they are subsumed by the enclosing transaction, and their effects +will be finally committed when the outermost transaction commits. +@emph{Open nesting} (where nested transactions can commit independently of the +enclosing transactions) are not supported. + +Flat nesting is the default nesting mode, but closed nesting is supported and +used when transactions contain user-controlled aborts +(@code{__transaction_cancel} statements). We assume that user-controlled +aborts are rare in typical code and used mostly in exceptional situations. +Thus, it makes more sense to use flat nesting by default to avoid the +performance overhead of the additional checkpoints required for closed +nesting. User-controlled aborts will correctly abort the innermost enclosing +transaction, whereas the whole (i.e., outermost) transaction will be restarted +otherwise (e.g., when a transaction encounters data conflicts during +optimistic execution). + + +@section Locking conventions + +This section documents the locking scheme and rules for all uses of locking +in libitm. We have to support serial(-irrevocable) mode, which is implemented +using a global lock as explained next (called the @emph{serial lock}). To +simplify the overall design, we use the same lock as catch-all locking +mechanism for other infrequent tasks such as (de)registering clone tables or +threads. Besides the serial lock, there are @emph{per-method-group locks} that +are managed by specific method groups (i.e., groups of similar TM concurrency +control algorithms), and lock-like constructs for quiescence-based operations +such as ensuring privatization safety. + +Thus, the actions that participate in the libitm-internal locking are either +@emph{active transactions} that do not run in serial mode, @emph{serial +transactions} (which (are about to) run in serial mode), and management tasks +that do not execute within a transaction but have acquired the serial mode +like a serial transaction would do (e.g., to be able to register threads with +libitm). Transactions become active as soon as they have successfully used the +serial lock to announce this globally (@pxref{serial-lock-impl,,Serial lock +implementation}). Likewise, transactions become serial transactions as soon as +they have acquired the exclusive rights provided by the serial lock (i.e., +serial mode, which also means that there are no other concurrent active or +serial transactions). Note that active transactions can become serial +transactions when they enter serial mode during the runtime of the +transaction. + +@subsection State-to-lock mapping + +Application data is protected by the serial lock if there is a serial +transaction and no concurrently running active transaction (i.e., non-serial). +Otherwise, application data is protected by the currently selected method +group, which might use per-method-group locks or other mechanisms. Also note +that application data that is about to be privatized might not be allowed to be +accessed by nontransactional code until privatization safety has been ensured; +the details of this are handled by the current method group. + +libitm-internal state is either protected by the serial lock or accessed +through custom concurrent code. The latter applies to the public/shared part +of a transaction object and most typical method-group-specific state. + +The former category (protected by the serial lock) includes: +@itemize @bullet +@item The list of active threads that have used transactions. +@item The tables that map functions to their transactional clones. +@item The current selection of which method group to use. +@item Some method-group-specific data, or invariants of this data. For example, +resetting a method group to its initial state is handled by switching to the +same method group, so the serial lock protects such resetting as well. +@end itemize +In general, such state is immutable whenever there exists an active +(non-serial) transaction. If there is no active transaction, a serial +transaction (or a thread that is not currently executing a transaction but has +acquired the serial lock) is allowed to modify this state (but must of course +be careful to not surprise the current method group's implementation with such +modifications). + +@subsection Lock acquisition order + +To prevent deadlocks, locks acquisition must happen in a globally agreed-upon +order. Note that this applies to other forms of blocking too, but does not +necessarily apply to lock acquisitions that do not block (e.g., trylock() +calls that do not get retried forever). Note that serial transactions are +never return back to active transactions until the transaction has committed. +Likewise, active transactions stay active until they have committed. +Per-method-group locks are typically also not released before commit. + +Lock acquisition / blocking rules: +@itemize @bullet + +@item Transactions must become active or serial before they are allowed to +use method-group-specific locks or blocking (i.e., the serial lock must be +acquired before those other locks, either in serial or nonserial mode). + +@item Any number of threads that do not currently run active transactions can +block while trying to get the serial lock in exclusive mode. Note that active +transactions must not block when trying to upgrade to serial mode unless there +is no other transaction that is trying that (the latter is ensured by the +serial lock implementation. + +@item Method groups must prevent deadlocks on their locks. In particular, they +must also be prepared for another active transaction that has acquired +method-group-specific locks but is blocked during an attempt to upgrade to +being a serial transaction. See below for details. + +@item Serial transactions can acquire method-group-specific locks because there +will be no other active nor serial transaction. + +@end itemize + +There is no single rule for per-method-group blocking because this depends on +when a TM method might acquire locks. If no active transaction can upgrade to +being a serial transaction after it has acquired per-method-group locks (e.g., +when those locks are only acquired during an attempt to commit), then the TM +method does not need to consider a potential deadlock due to serial mode. + +If there can be upgrades to serial mode after the acquisition of +per-method-group locks, then TM methods need to avoid those deadlocks: +@itemize @bullet +@item When upgrading to a serial transaction, after acquiring exclusive rights +to the serial lock but before waiting for concurrent active transactions to +finish (@pxref{serial-lock-impl,,Serial lock implementation} for details), +we have to wake up all active transactions waiting on the upgrader's +per-method-group locks. +@item Active transactions blocking on per-method-group locks need to check the +serial lock and abort if there is a pending serial transaction. +@item Lost wake-ups have to be prevented (e.g., by changing a bit in each +per-method-group lock before doing the wake-up, and only blocking on this lock +using a futex if this bit is not group). +@end itemize + +@strong{TODO}: Can reuse serial lock for gl-*? And if we can, does it make +sense to introduce further complexity in the serial lock? For gl-*, we can +really only avoid an abort if we do -wb and -vbv. + + +@subsection Serial lock implementation +@anchor{serial-lock-impl} + +The serial lock implementation is optimized towards assuming that serial +transactions are infrequent and not the common case. However, the performance +of entering serial mode can matter because when only few transactions are run +concurrently or if there are few threads, then it can be efficient to run +transactions serially. + +The serial lock is similar to a multi-reader-single-writer lock in that there +can be several active transactions but only one serial transaction. However, +we do want to avoid contention (in the lock implementation) between active +transactions, so we split up the reader side of the lock into per-transaction +flags that are true iff the transaction is active. The exclusive writer side +remains a shared single flag, which is acquired using a CAS, for example. +On the fast-path, the serial lock then works similar to Dekker's algorithm but +with several reader flags that a serial transaction would have to check. +A serial transaction thus requires a list of all threads with potentially +active transactions; we can use the serial lock itself to protect this list +(i.e., only threads that have acquired the serial lock can modify this list). + +We want starvation-freedom for the serial lock to allow for using it to ensure +progress for potentially starved transactions (@pxref{progress-guarantees,, +Progress Guarantees} for details). However, this is currently not enforced by +the implementation of the serial lock. + +Here is pseudo-code for the read/write fast paths of acquiring the serial +lock (read-to-write upgrade is similar to write_lock: +@example +// read_lock: +tx->shared_state |= active; +__sync_synchronize(); // or STLD membar, or C++0x seq-cst fence +while (!serial_lock.exclusive) + if (spinning_for_too_long) goto slowpath; + +// write_lock: +if (CAS(&serial_lock.exclusive, 0, this) != 0) + goto slowpath; // writer-writer contention +// need a membar here, but CAS already has full membar semantics +bool need_blocking = false; +for (t: all txns) + @{ + for (;t->shared_state & active;) + if (spinning_for_too_long) @{ need_blocking = true; break; @} + @} +if (need_blocking) goto slowpath; +@end example + +Releasing a lock in this spin-lock version then just consists of resetting +@code{tx->shared_state} to inactive or clearing @code{serial_lock.exclusive}. + +However, we can't rely on a pure spinlock because we need to get the OS +involved at some time (e.g., when there are more threads than CPUs to run on). +Therefore, the real implementation falls back to a blocking slow path, either +based on pthread mutexes or Linux futexes. + + +@subsection Reentrancy + +libitm has to consider the following cases of reentrancy: +@itemize @bullet + +@item Transaction calls unsafe code that starts a new transaction: The outer +transaction will become a serial transaction before executing unsafe code. +Therefore, nesting within serial transactions must work, even if the nested +transaction is called from within uninstrumented code. + +@item Transaction calls either a transactional wrapper or safe code, which in +turn starts a new transaction: It is not yet defined in the specification +whether this is allowed. Thus, it is undefined whether libitm supports this. + +@item Code that starts new transactions might be called from within any part +of libitm: This kind of reentrancy would likely be rather complex and can +probably be avoided. Therefore, it is not supported. + +@end itemize + +@subsection Privatization safety + +Privatization safety is ensured by libitm using a quiescence-based approach. +Basically, a privatizing transaction waits until all concurrent active +transactions will either have finished (are not active anymore) or operate on +a sufficiently recent snapshot to not access the privatized data anymore. This +happens after the privatizing transaction has stopped being an active +transaction, so waiting for quiescence does not contribute to deadlocks. + +In method groups that need to ensure publication safety explicitly, active +transactions maintain a flag or timestamp in the public/shared part of the +transaction descriptor. Before blocking, privatizers need to let the other +transactions know that they should wake up the privatizer. + +@strong{TODO} Ho to implement the waiters? Should those flags be +per-transaction or at a central place? We want to avoid one wake/wait call +per active transactions, so we might want to use either a tree or combining +to reduce the syscall overhead, or rather spin for a long amount of time +instead of doing blocking. Also, it would be good if only the last transaction +that the privatizer waits for would do the wake-up. + +@subsection Progress guarantees +@anchor{progress-guarantees} + +Transactions that do not make progress when using the current TM method will +eventually try to execute in serial mode. Thus, the serial lock's progress +guarantees determine the progress guarantees of the whole TM. Obviously, we at +least need deadlock-freedom for the serial lock, but it would also be good to +provide starvation-freedom (informally, all threads will finish executing a +transaction eventually iff they get enough cycles). + +However, the scheduling of transactions (e.g., thread scheduling by the OS) +also affects the handling of progress guarantees by the TM. First, the TM +can only guarantee deadlock-freedom if threads do not get stopped. Likewise, +low-priority threads can starve if they do not get scheduled when other +high-priority threads get those cycles instead. + +If all threads get scheduled eventually, correct lock implementations will +provide deadlock-freedom, but might not provide starvation-freedom. We can +either enforce the latter in the TM's lock implementation, or assume that +the scheduling is sufficiently random to yield a probabilistic guarantee that +no thread will starve (because eventually, a transaction will encounter a +scheduling that will allow it to run). This can indeed work well in practice +but is not necessarily guaranteed to work (e.g., simple spin locks can be +pretty efficient). + +Because enforcing stronger progress guarantees in the TM has a higher runtime +overhead, we focus on deadlock-freedom right now and assume that the threads +will get scheduled eventually by the OS (but don't consider threads with +different priorities). We should support starvation-freedom for serial +transactions in the future. Everything beyond that is highly related to proper +contention management across all of the TM (including with TM method to +choose), and is future work. + +@strong{TODO} Handling thread priorities: We want to avoid priority inversion +but it's unclear how often that actually matters in practice. Workloads that +have threads with different priorities will likely also require lower latency +or higher throughput for high-priority threads. Therefore, it probably makes +not that much sense (except for eventual progress guarantees) to use +priority inheritance until the TM has priority-aware contention management. + + +@c --------------------------------------------------------------------- +@c GNU Free Documentation License +@c --------------------------------------------------------------------- + +@include fdl.texi + +@c --------------------------------------------------------------------- +@c Index +@c --------------------------------------------------------------------- + +@node Index +@unnumbered Index + +@printindex cp + +@bye diff --git a/libitm/libitm_i.h b/libitm/libitm_i.h new file mode 100644 index 00000000000..c188fa5f43f --- /dev/null +++ b/libitm/libitm_i.h @@ -0,0 +1,302 @@ +/* Copyright (C) 2008, 2009, 2011 Free Software Foundation, Inc. + Contributed by Richard Henderson <rth@redhat.com>. + + This file is part of the GNU Transactional Memory Library (libitm). + + Libitm is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + Libitm is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + <http://www.gnu.org/licenses/>. */ + +/* The following are internal implementation functions and definitions. + To distinguish them from those defined by the Intel ABI, they all + begin with GTM/gtm. */ + +#ifndef LIBITM_I_H +#define LIBITM_I_H 1 + +#include "libitm.h" +#include "config.h" + +#include <assert.h> +#include <stdlib.h> +#include <string.h> +#include <unwind.h> +#include "local_type_traits" + +#include "common.h" + +namespace GTM HIDDEN { + +using namespace std; + +// A helper template for accessing an unsigned integral of SIZE bytes. +template<size_t SIZE> struct sized_integral { }; +template<> struct sized_integral<1> { typedef uint8_t type; }; +template<> struct sized_integral<2> { typedef uint16_t type; }; +template<> struct sized_integral<4> { typedef uint32_t type; }; +template<> struct sized_integral<8> { typedef uint64_t type; }; + +typedef unsigned int gtm_word __attribute__((mode (word))); + +// These values are given to GTM_restart_transaction and indicate the +// reason for the restart. The reason is used to decide what STM +// implementation should be used during the next iteration. +enum gtm_restart_reason +{ + RESTART_REALLOCATE, + RESTART_LOCKED_READ, + RESTART_LOCKED_WRITE, + RESTART_VALIDATE_READ, + RESTART_VALIDATE_WRITE, + RESTART_VALIDATE_COMMIT, + RESTART_SERIAL_IRR, + RESTART_NOT_READONLY, + RESTART_CLOSED_NESTING, + RESTART_INIT_METHOD_GROUP, + NUM_RESTARTS, + NO_RESTART = NUM_RESTARTS +}; + +} // namespace GTM + +#include "target.h" +#include "rwlock.h" +#include "aatree.h" +#include "cacheline.h" +#include "cachepage.h" +#include "stmlock.h" +#include "dispatch.h" +#include "containers.h" + +namespace GTM HIDDEN { + +// This type is private to alloc.c, but needs to be defined so that +// the template used inside gtm_thread can instantiate. +struct gtm_alloc_action +{ + void (*free_fn)(void *); + bool allocated; +}; + +// This type is private to local.c. +struct gtm_undolog_entry; + +struct gtm_thread; + +// A transaction checkpoint: data that has to saved and restored when doing +// closed nesting. +struct gtm_transaction_cp +{ + gtm_jmpbuf jb; + size_t undolog_size; + aa_tree<uintptr_t, gtm_alloc_action> alloc_actions; + size_t user_actions_size; + _ITM_transactionId_t id; + uint32_t prop; + uint32_t cxa_catch_count; + void *cxa_unthrown; + // We might want to use a different but compatible dispatch method for + // a nested transaction. + abi_dispatch *disp; + // Nesting level of this checkpoint (1 means that this is a checkpoint of + // the outermost transaction). + uint32_t nesting; + + void save(gtm_thread* tx); + void commit(gtm_thread* tx); +}; + +// Contains all thread-specific data required by the entire library. +// This includes all data relevant to a single transaction. Because most +// thread-specific data is about the current transaction, we also refer to +// the transaction-specific parts of gtm_thread as "the transaction" (the +// same applies to names of variables and arguments). +// All but the shared part of this data structure are thread-local data. +// gtm_thread could be split into transaction-specific structures and other +// per-thread data (with those parts then nested in gtm_thread), but this +// would make it harder to later rearrange individual members to optimize data +// accesses. Thus, for now we keep one flat object, and will only split it if +// the code gets too messy. +struct gtm_thread +{ + + struct user_action + { + _ITM_userCommitFunction fn; + void *arg; + bool on_commit; + _ITM_transactionId_t resuming_id; + }; + + // The jump buffer by which GTM_longjmp restarts the transaction. + // This field *must* be at the beginning of the transaction. + gtm_jmpbuf jb; + + // Data used by local.c for the undo log for both local and shared memory. + vector<gtm_undolog_entry*> undolog; + + // Data used by alloc.c for the malloc/free undo log. + aa_tree<uintptr_t, gtm_alloc_action> alloc_actions; + + // Data used by useraction.c for the user-defined commit/abort handlers. + vector<user_action> user_actions; + + // A numerical identifier for this transaction. + _ITM_transactionId_t id; + + // The _ITM_codeProperties of this transaction as given by the compiler. + uint32_t prop; + + // The nesting depth for subsequently started transactions. This variable + // will be set to 1 when starting an outermost transaction. + uint32_t nesting; + + // Set if this transaction owns the serial write lock. + // Can be reset only when restarting the outermost transaction. + static const uint32_t STATE_SERIAL = 0x0001; + // Set if the serial-irrevocable dispatch table is installed. + // Implies that no logging is being done, and abort is not possible. + // Can be reset only when restarting the outermost transaction. + static const uint32_t STATE_IRREVOCABLE = 0x0002; + + // A bitmask of the above. + uint32_t state; + + // In order to reduce cacheline contention on global_tid during + // beginTransaction, we allocate a block of 2**N ids to the thread + // all at once. This number is the next value to be allocated from + // the block, or 0 % 2**N if no such block is allocated. + _ITM_transactionId_t local_tid; + + // Data used by eh_cpp.c for managing exceptions within the transaction. + uint32_t cxa_catch_count; + void *cxa_unthrown; + void *eh_in_flight; + + // Checkpoints for closed nesting. + vector<gtm_transaction_cp> parent_txns; + + // Data used by retry.c for deciding what STM implementation should + // be used for the next iteration of the transaction. + // Only restart_total is reset to zero when the transaction commits, the + // other counters are total values for all previously executed transactions. + uint32_t restart_reason[NUM_RESTARTS]; + uint32_t restart_total; + + // *** The shared part of gtm_thread starts here. *** + // Shared state is on separate cachelines to avoid false sharing with + // thread-local parts of gtm_thread. + + // Points to the next thread in the list of all threads. + gtm_thread *next_thread __attribute__((__aligned__(HW_CACHELINE_SIZE))); + + // If this transaction is inactive, shared_state is ~0. Otherwise, this is + // an active or serial transaction. + gtm_word shared_state; + + // The lock that provides access to serial mode. Non-serialized + // transactions acquire read locks; a serialized transaction aquires + // a write lock. + static gtm_rwlock serial_lock; + + // The head of the list of all threads' transactions. + static gtm_thread *list_of_threads; + // The number of all registered threads. + static unsigned number_of_threads; + + // In alloc.cc + void commit_allocations (bool, aa_tree<uintptr_t, gtm_alloc_action>*); + void record_allocation (void *, void (*)(void *)); + void forget_allocation (void *, void (*)(void *)); + void drop_references_allocations (const void *ptr) + { + this->alloc_actions.erase((uintptr_t) ptr); + } + + // In beginend.cc + void rollback (gtm_transaction_cp *cp = 0, bool aborting = false); + bool trycommit (); + void restart (gtm_restart_reason) ITM_NORETURN; + + gtm_thread(); + ~gtm_thread(); + + static void *operator new(size_t); + static void operator delete(void *); + + // Invoked from assembly language, thus the "asm" specifier on + // the name, avoiding complex name mangling. + static uint32_t begin_transaction(uint32_t, const gtm_jmpbuf *) + __asm__("GTM_begin_transaction") ITM_REGPARM; + + // In eh_cpp.cc + void revert_cpp_exceptions (gtm_transaction_cp *cp = 0); + + // In local.cc + void commit_undolog (void); + void rollback_undolog (size_t until_size = 0); + void drop_references_undolog (const void *, size_t); + + // In retry.cc + // Must be called outside of transactions (i.e., after rollback). + void decide_retry_strategy (gtm_restart_reason); + abi_dispatch* decide_begin_dispatch (uint32_t prop); + void number_of_threads_changed(unsigned previous, unsigned now); + // Must be called from serial mode. Does not call set_abi_disp(). + void set_default_dispatch(abi_dispatch* disp); + + // In method-serial.cc + void serialirr_mode (); + + // In useraction.cc + void rollback_user_actions (size_t until_size = 0); + void commit_user_actions (); +}; + +} // namespace GTM + +#include "tls.h" + +namespace GTM HIDDEN { + +// An unscaled count of the number of times we should spin attempting to +// acquire locks before we block the current thread and defer to the OS. +// This variable isn't used when the standard POSIX lock implementations +// are used. +extern uint64_t gtm_spin_count_var; + +extern "C" uint32_t GTM_longjmp (const gtm_jmpbuf *, uint32_t, uint32_t) + ITM_NORETURN ITM_REGPARM; + +extern "C" void GTM_LB (const void *, size_t) ITM_REGPARM; + +extern void GTM_error (const char *fmt, ...) + __attribute__((format (printf, 1, 2))); +extern void GTM_fatal (const char *fmt, ...) + __attribute__((noreturn, format (printf, 1, 2))); + +extern abi_dispatch *dispatch_serial(); +extern abi_dispatch *dispatch_serialirr(); +extern abi_dispatch *dispatch_serialirr_onwrite(); +extern abi_dispatch *dispatch_gl_wt(); + +extern gtm_cacheline_mask gtm_mask_stack(gtm_cacheline *, gtm_cacheline_mask); + +} // namespace GTM + +#endif // LIBITM_I_H diff --git a/libitm/local.cc b/libitm/local.cc new file mode 100644 index 00000000000..fab73c50895 --- /dev/null +++ b/libitm/local.cc @@ -0,0 +1,129 @@ +/* Copyright (C) 2008, 2009, 2011 Free Software Foundation, Inc. + Contributed by Richard Henderson <rth@redhat.com>. + + This file is part of the GNU Transactional Memory Library (libitm). + + Libitm is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + Libitm is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + <http://www.gnu.org/licenses/>. */ + +#include "libitm_i.h" + +namespace GTM HIDDEN { + +struct gtm_undolog_entry +{ + void *addr; + size_t len; + char saved[]; +}; + + +void +gtm_thread::commit_undolog () +{ + size_t i, n = undolog.size(); + + if (n > 0) + { + for (i = 0; i < n; ++i) + free (undolog[i]); + this->undolog.clear(); + } +} + +void +gtm_thread::rollback_undolog (size_t until_size) +{ + size_t i, n = undolog.size(); + + if (n > 0) + { + for (i = n; i-- > until_size; ) + { + gtm_undolog_entry *u = *undolog.pop(); + if (u) + { + memcpy (u->addr, u->saved, u->len); + free (u); + } + } + } +} + +/* Forget any references to PTR in the local log. */ + +void +gtm_thread::drop_references_undolog (const void *ptr, size_t len) +{ + size_t i, n = undolog.size(); + + if (n > 0) + { + for (i = n; i > 0; i--) + { + gtm_undolog_entry *u = undolog[i]; + /* ?? Do we need such granularity, or can we get away with + just comparing PTR and LEN. ?? */ + if ((const char *)u->addr >= (const char *)ptr + && ((const char *)u->addr + u->len <= (const char *)ptr + len)) + { + free (u); + undolog[i] = NULL; + } + } + } +} + +void ITM_REGPARM +GTM_LB (const void *ptr, size_t len) +{ + gtm_thread *tx = gtm_thr(); + gtm_undolog_entry *undo; + + undo = (gtm_undolog_entry *) + xmalloc (sizeof (struct gtm_undolog_entry) + len); + undo->addr = (void *) ptr; + undo->len = len; + + tx->undolog.push()[0] = undo; + + memcpy (undo->saved, ptr, len); +} + +} // namespace GTM + +using namespace GTM; + +void _ITM_LB (const void *ptr, size_t len) ITM_REGPARM + __attribute__((alias("GTM_LB"))); + +#define ITM_LOG_DEF(T) \ +void ITM_REGPARM _ITM_L##T (const _ITM_TYPE_##T *ptr) \ +{ GTM_LB (ptr, sizeof (*ptr)); } + +ITM_LOG_DEF(U1) +ITM_LOG_DEF(U2) +ITM_LOG_DEF(U4) +ITM_LOG_DEF(U8) +ITM_LOG_DEF(F) +ITM_LOG_DEF(D) +ITM_LOG_DEF(E) +ITM_LOG_DEF(CF) +ITM_LOG_DEF(CD) +ITM_LOG_DEF(CE) diff --git a/libitm/local_type_traits b/libitm/local_type_traits new file mode 100644 index 00000000000..8349cd50263 --- /dev/null +++ b/libitm/local_type_traits @@ -0,0 +1,1901 @@ +// C++0x type_traits -*- C++ -*- + +// Copyright (C) 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// <http://www.gnu.org/licenses/>. + +// ???????????????????????????????????????????????????????????????????? +// +// This is a copy of the libstdc++ header, with the trivial modification +// of ignoring the c++config.h include. If and when the top-level build is +// fixed so that target libraries can be built using the newly built, we can +// delete this file. +// +// ???????????????????????????????????????????????????????????????????? + +/** @file include/type_traits + * This is a Standard C++ Library header. + */ + +#ifndef _GLIBCXX_TYPE_TRAITS +#define _GLIBCXX_TYPE_TRAITS 1 + +// #pragma GCC system_header + +// #ifndef __GXX_EXPERIMENTAL_CXX0X__ +// # include <bits/c++0x_warning.h> +// #else +// #include <bits/c++config.h> + +namespace std // _GLIBCXX_VISIBILITY(default) +{ +// _GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @addtogroup metaprogramming + * @{ + */ + + /// integral_constant + template<typename _Tp, _Tp __v> + struct integral_constant + { + static constexpr _Tp value = __v; + typedef _Tp value_type; + typedef integral_constant<_Tp, __v> type; + constexpr operator value_type() { return value; } + }; + + /// typedef for true_type + typedef integral_constant<bool, true> true_type; + + /// typedef for false_type + typedef integral_constant<bool, false> false_type; + + template<typename _Tp, _Tp __v> + constexpr _Tp integral_constant<_Tp, __v>::value; + + // Meta programming helper types. + + template<bool, typename, typename> + struct conditional; + + template<typename...> + struct __or_; + + template<> + struct __or_<> + : public false_type + { }; + + template<typename _B1> + struct __or_<_B1> + : public _B1 + { }; + + template<typename _B1, typename _B2> + struct __or_<_B1, _B2> + : public conditional<_B1::value, _B1, _B2>::type + { }; + + template<typename _B1, typename _B2, typename _B3, typename... _Bn> + struct __or_<_B1, _B2, _B3, _Bn...> + : public conditional<_B1::value, _B1, __or_<_B2, _B3, _Bn...>>::type + { }; + + template<typename...> + struct __and_; + + template<> + struct __and_<> + : public true_type + { }; + + template<typename _B1> + struct __and_<_B1> + : public _B1 + { }; + + template<typename _B1, typename _B2> + struct __and_<_B1, _B2> + : public conditional<_B1::value, _B2, _B1>::type + { }; + + template<typename _B1, typename _B2, typename _B3, typename... _Bn> + struct __and_<_B1, _B2, _B3, _Bn...> + : public conditional<_B1::value, __and_<_B2, _B3, _Bn...>, _B1>::type + { }; + + template<typename _Pp> + struct __not_ + : public integral_constant<bool, !_Pp::value> + { }; + + struct __sfinae_types + { + typedef char __one; + typedef struct { char __arr[2]; } __two; + }; + + // primary type categories. + + template<typename> + struct remove_cv; + + template<typename> + struct __is_void_helper + : public false_type { }; + + template<> + struct __is_void_helper<void> + : public true_type { }; + + /// is_void + template<typename _Tp> + struct is_void + : public integral_constant<bool, (__is_void_helper<typename + remove_cv<_Tp>::type>::value)> + { }; + + template<typename> + struct __is_integral_helper + : public false_type { }; + + template<> + struct __is_integral_helper<bool> + : public true_type { }; + + template<> + struct __is_integral_helper<char> + : public true_type { }; + + template<> + struct __is_integral_helper<signed char> + : public true_type { }; + + template<> + struct __is_integral_helper<unsigned char> + : public true_type { }; + +#ifdef _GLIBCXX_USE_WCHAR_T + template<> + struct __is_integral_helper<wchar_t> + : public true_type { }; +#endif + + template<> + struct __is_integral_helper<char16_t> + : public true_type { }; + + template<> + struct __is_integral_helper<char32_t> + : public true_type { }; + + template<> + struct __is_integral_helper<short> + : public true_type { }; + + template<> + struct __is_integral_helper<unsigned short> + : public true_type { }; + + template<> + struct __is_integral_helper<int> + : public true_type { }; + + template<> + struct __is_integral_helper<unsigned int> + : public true_type { }; + + template<> + struct __is_integral_helper<long> + : public true_type { }; + + template<> + struct __is_integral_helper<unsigned long> + : public true_type { }; + + template<> + struct __is_integral_helper<long long> + : public true_type { }; + + template<> + struct __is_integral_helper<unsigned long long> + : public true_type { }; + +#if !defined(__STRICT_ANSI__) && defined(_GLIBCXX_USE_INT128) + template<> + struct __is_integral_helper<__int128> + : public true_type { }; + + template<> + struct __is_integral_helper<unsigned __int128> + : public true_type { }; +#endif + + /// is_integral + template<typename _Tp> + struct is_integral + : public integral_constant<bool, (__is_integral_helper<typename + remove_cv<_Tp>::type>::value)> + { }; + + template<typename> + struct __is_floating_point_helper + : public false_type { }; + + template<> + struct __is_floating_point_helper<float> + : public true_type { }; + + template<> + struct __is_floating_point_helper<double> + : public true_type { }; + + template<> + struct __is_floating_point_helper<long double> + : public true_type { }; + +#if !defined(__STRICT_ANSI__) && defined(_GLIBCXX_USE_FLOAT128) + template<> + struct __is_floating_point_helper<__float128> + : public true_type { }; +#endif + + /// is_floating_point + template<typename _Tp> + struct is_floating_point + : public integral_constant<bool, (__is_floating_point_helper<typename + remove_cv<_Tp>::type>::value)> + { }; + + /// is_array + template<typename> + struct is_array + : public false_type { }; + + template<typename _Tp, size_t _Size> + struct is_array<_Tp[_Size]> + : public true_type { }; + + template<typename _Tp> + struct is_array<_Tp[]> + : public true_type { }; + + template<typename> + struct __is_pointer_helper + : public false_type { }; + + template<typename _Tp> + struct __is_pointer_helper<_Tp*> + : public true_type { }; + + /// is_pointer + template<typename _Tp> + struct is_pointer + : public integral_constant<bool, (__is_pointer_helper<typename + remove_cv<_Tp>::type>::value)> + { }; + + /// is_lvalue_reference + template<typename> + struct is_lvalue_reference + : public false_type { }; + + template<typename _Tp> + struct is_lvalue_reference<_Tp&> + : public true_type { }; + + /// is_rvalue_reference + template<typename> + struct is_rvalue_reference + : public false_type { }; + + template<typename _Tp> + struct is_rvalue_reference<_Tp&&> + : public true_type { }; + + template<typename> + struct is_function; + + template<typename> + struct __is_member_object_pointer_helper + : public false_type { }; + + template<typename _Tp, typename _Cp> + struct __is_member_object_pointer_helper<_Tp _Cp::*> + : public integral_constant<bool, !is_function<_Tp>::value> { }; + + /// is_member_object_pointer + template<typename _Tp> + struct is_member_object_pointer + : public integral_constant<bool, (__is_member_object_pointer_helper< + typename remove_cv<_Tp>::type>::value)> + { }; + + template<typename> + struct __is_member_function_pointer_helper + : public false_type { }; + + template<typename _Tp, typename _Cp> + struct __is_member_function_pointer_helper<_Tp _Cp::*> + : public integral_constant<bool, is_function<_Tp>::value> { }; + + /// is_member_function_pointer + template<typename _Tp> + struct is_member_function_pointer + : public integral_constant<bool, (__is_member_function_pointer_helper< + typename remove_cv<_Tp>::type>::value)> + { }; + + /// is_enum + template<typename _Tp> + struct is_enum + : public integral_constant<bool, __is_enum(_Tp)> + { }; + + /// is_union + template<typename _Tp> + struct is_union + : public integral_constant<bool, __is_union(_Tp)> + { }; + + /// is_class + template<typename _Tp> + struct is_class + : public integral_constant<bool, __is_class(_Tp)> + { }; + + /// is_function + template<typename> + struct is_function + : public false_type { }; + + template<typename _Res, typename... _ArgTypes> + struct is_function<_Res(_ArgTypes...)> + : public true_type { }; + + template<typename _Res, typename... _ArgTypes> + struct is_function<_Res(_ArgTypes......)> + : public true_type { }; + + template<typename _Res, typename... _ArgTypes> + struct is_function<_Res(_ArgTypes...) const> + : public true_type { }; + + template<typename _Res, typename... _ArgTypes> + struct is_function<_Res(_ArgTypes......) const> + : public true_type { }; + + template<typename _Res, typename... _ArgTypes> + struct is_function<_Res(_ArgTypes...) volatile> + : public true_type { }; + + template<typename _Res, typename... _ArgTypes> + struct is_function<_Res(_ArgTypes......) volatile> + : public true_type { }; + + template<typename _Res, typename... _ArgTypes> + struct is_function<_Res(_ArgTypes...) const volatile> + : public true_type { }; + + template<typename _Res, typename... _ArgTypes> + struct is_function<_Res(_ArgTypes......) const volatile> + : public true_type { }; + + template<typename> + struct __is_nullptr_t_helper + : public false_type { }; + +#if 0 + template<> + struct __is_nullptr_t_helper<nullptr_t> + : public true_type { }; +#endif + + // __is_nullptr_t (extension). + template<typename _Tp> + struct __is_nullptr_t + : public integral_constant<bool, (__is_nullptr_t_helper<typename + remove_cv<_Tp>::type>::value)> + { }; + + // composite type categories. + + /// is_reference + template<typename _Tp> + struct is_reference + : public __or_<is_lvalue_reference<_Tp>, + is_rvalue_reference<_Tp>>::type + { }; + + /// is_arithmetic + template<typename _Tp> + struct is_arithmetic + : public __or_<is_integral<_Tp>, is_floating_point<_Tp>>::type + { }; + + /// is_fundamental + template<typename _Tp> + struct is_fundamental + : public __or_<is_arithmetic<_Tp>, is_void<_Tp>>::type + { }; + + /// is_object + template<typename _Tp> + struct is_object + : public __not_<__or_<is_function<_Tp>, is_reference<_Tp>, + is_void<_Tp>>>::type + { }; + + template<typename> + struct is_member_pointer; + + /// is_scalar + template<typename _Tp> + struct is_scalar + : public __or_<is_arithmetic<_Tp>, is_enum<_Tp>, is_pointer<_Tp>, + is_member_pointer<_Tp>, __is_nullptr_t<_Tp>>::type + { }; + + /// is_compound + template<typename _Tp> + struct is_compound + : public integral_constant<bool, !is_fundamental<_Tp>::value> { }; + + /// is_member_pointer + template<typename _Tp> + struct __is_member_pointer_helper + : public false_type { }; + + template<typename _Tp, typename _Cp> + struct __is_member_pointer_helper<_Tp _Cp::*> + : public true_type { }; + + template<typename _Tp> + struct is_member_pointer + : public integral_constant<bool, (__is_member_pointer_helper< + typename remove_cv<_Tp>::type>::value)> + { }; + + // type properties. + + /// is_const + template<typename> + struct is_const + : public false_type { }; + + template<typename _Tp> + struct is_const<_Tp const> + : public true_type { }; + + /// is_volatile + template<typename> + struct is_volatile + : public false_type { }; + + template<typename _Tp> + struct is_volatile<_Tp volatile> + : public true_type { }; + + /// is_trivial + template<typename _Tp> + struct is_trivial + : public integral_constant<bool, __is_trivial(_Tp)> + { }; + + /// is_trivially_copyable (still unimplemented) + + /// is_standard_layout + template<typename _Tp> + struct is_standard_layout + : public integral_constant<bool, __is_standard_layout(_Tp)> + { }; + + /// is_pod + // Could use is_standard_layout && is_trivial instead of the builtin. + template<typename _Tp> + struct is_pod + : public integral_constant<bool, __is_pod(_Tp)> + { }; + + /// is_literal_type + template<typename _Tp> + struct is_literal_type + : public integral_constant<bool, __is_literal_type(_Tp)> + { }; + + /// is_empty + template<typename _Tp> + struct is_empty + : public integral_constant<bool, __is_empty(_Tp)> + { }; + + /// is_polymorphic + template<typename _Tp> + struct is_polymorphic + : public integral_constant<bool, __is_polymorphic(_Tp)> + { }; + + /// is_abstract + template<typename _Tp> + struct is_abstract + : public integral_constant<bool, __is_abstract(_Tp)> + { }; + + template<typename _Tp, + bool = is_integral<_Tp>::value, + bool = is_floating_point<_Tp>::value> + struct __is_signed_helper + : public false_type { }; + + template<typename _Tp> + struct __is_signed_helper<_Tp, false, true> + : public true_type { }; + + template<typename _Tp> + struct __is_signed_helper<_Tp, true, false> + : public integral_constant<bool, static_cast<bool>(_Tp(-1) < _Tp(0))> + { }; + + /// is_signed + template<typename _Tp> + struct is_signed + : public integral_constant<bool, __is_signed_helper<_Tp>::value> + { }; + + /// is_unsigned + template<typename _Tp> + struct is_unsigned + : public __and_<is_arithmetic<_Tp>, __not_<is_signed<_Tp>>>::type + { }; + + + // destructible and constructible type properties + + template<typename> + struct add_rvalue_reference; + + template<typename _Tp> + typename add_rvalue_reference<_Tp>::type declval() noexcept; + + template<typename, unsigned = 0> + struct extent; + + template<typename> + struct remove_all_extents; + + template<typename _Tp> + struct __is_array_known_bounds + : public integral_constant<bool, (extent<_Tp>::value > 0)> + { }; + + template<typename _Tp> + struct __is_array_unknown_bounds + : public __and_<is_array<_Tp>, __not_<extent<_Tp>>>::type + { }; + + // In N3290 is_destructible does not say anything about function + // types and abstract types, see LWG 2049. This implementation + // describes function types as trivially nothrow destructible and + // abstract types as destructible, iff the explicit destructor + // call expression is wellformed. + struct __do_is_destructible_impl_1 + { + template<typename _Up> + struct __w { _Up __u; }; + + template<typename _Tp, typename + = decltype(declval<__w<_Tp>&>().~__w<_Tp>())> + static true_type __test(int); + + template<typename> + static false_type __test(...); + }; + + template<typename _Tp> + struct __is_destructible_impl_1 + : public __do_is_destructible_impl_1 + { + typedef decltype(__test<_Tp>(0)) type; + }; + + // Special implementation for abstract types + struct __do_is_destructible_impl_2 + { + template<typename _Tp, typename = decltype(declval<_Tp&>().~_Tp())> + static true_type __test(int); + + template<typename> + static false_type __test(...); + }; + + template<typename _Tp> + struct __is_destructible_impl_2 + : public __do_is_destructible_impl_2 + { + typedef decltype(__test<_Tp>(0)) type; + }; + + template<typename _Tp, + bool = __or_<is_void<_Tp>, + __is_array_unknown_bounds<_Tp>>::value, + bool = __or_<is_reference<_Tp>, is_function<_Tp>>::value> + struct __is_destructible_safe; + + template<typename _Tp> + struct __is_destructible_safe<_Tp, false, false> + : public conditional<is_abstract<_Tp>::value, + __is_destructible_impl_2<_Tp>, + __is_destructible_impl_1<_Tp>>::type::type + { }; + + template<typename _Tp> + struct __is_destructible_safe<_Tp, true, false> + : public false_type { }; + + template<typename _Tp> + struct __is_destructible_safe<_Tp, false, true> + : public true_type { }; + + /// is_destructible + template<typename _Tp> + struct is_destructible + : public integral_constant<bool, (__is_destructible_safe<_Tp>::value)> + { }; + + struct __do_is_default_constructible_impl + { + template<typename _Tp, typename = decltype(_Tp())> + static true_type __test(int); + + template<typename> + static false_type __test(...); + }; + + template<typename _Tp> + struct __is_default_constructible_impl + : public __do_is_default_constructible_impl + { + typedef decltype(__test<_Tp>(0)) type; + }; + + template<typename _Tp> + struct __is_default_constructible_atom + : public __and_<__not_<is_void<_Tp>>, + __is_default_constructible_impl<_Tp>>::type + { }; + + template<typename _Tp, bool = is_array<_Tp>::value> + struct __is_default_constructible_safe; + + // The following technique is a workaround for a current core language + // restriction, which does not allow for array types to occur in + // functional casts of the form T(). Complete arrays can be default- + // constructed, if the element type is default-constructible, but + // arrays with unknown bounds are not. + template<typename _Tp> + struct __is_default_constructible_safe<_Tp, true> + : public __and_<__is_array_known_bounds<_Tp>, + __is_default_constructible_atom<typename + remove_all_extents<_Tp>::type>>::type + { }; + + template<typename _Tp> + struct __is_default_constructible_safe<_Tp, false> + : public __is_default_constructible_atom<_Tp>::type + { }; + + /// is_default_constructible + template<typename _Tp> + struct is_default_constructible + : public integral_constant<bool, (__is_default_constructible_safe< + _Tp>::value)> + { }; + + + // Implementation of is_constructible. + + // The hardest part of this trait is the binary direct-initialization + // case, because we hit into a functional cast of the form T(arg). + // This implementation uses different strategies depending on the + // target type to reduce the test overhead as much as possible: + // + // a) For a reference target type, we use a static_cast expression + // modulo its extra cases. + // + // b) For a non-reference target type we use a ::new expression. + struct __do_is_static_castable_impl + { + template<typename _From, typename _To, typename + = decltype(static_cast<_To>(declval<_From>()))> + static true_type __test(int); + + template<typename, typename> + static false_type __test(...); + }; + + template<typename _From, typename _To> + struct __is_static_castable_impl + : public __do_is_static_castable_impl + { + typedef decltype(__test<_From, _To>(0)) type; + }; + + template<typename _From, typename _To> + struct __is_static_castable_safe + : public __is_static_castable_impl<_From, _To>::type + { }; + + // __is_static_castable + template<typename _From, typename _To> + struct __is_static_castable + : public integral_constant<bool, (__is_static_castable_safe< + _From, _To>::value)> + { }; + + // Implementation for non-reference types. To meet the proper + // variable definition semantics, we also need to test for + // is_destructible in this case. + struct __do_is_direct_constructible_impl + { + template<typename _Tp, typename _Arg, typename + = decltype(::new _Tp(declval<_Arg>()))> + static true_type __test(int); + + template<typename, typename> + static false_type __test(...); + }; + + template<typename _Tp, typename _Arg> + struct __is_direct_constructible_impl + : public __do_is_direct_constructible_impl + { + typedef decltype(__test<_Tp, _Arg>(0)) type; + }; + + template<typename _Tp, typename _Arg> + struct __is_direct_constructible_new_safe + : public __and_<is_destructible<_Tp>, + __is_direct_constructible_impl<_Tp, _Arg>>::type + { }; + + template<typename, typename> + struct is_same; + + template<typename, typename> + struct is_base_of; + + template<typename> + struct remove_reference; + + template<typename _From, typename _To, bool + = is_reference<_From>::value> + struct __is_base_to_derived_ref; + + template<typename _From, typename _To> + struct __is_base_to_derived_ref<_From, _To, true> + { + typedef typename remove_cv<typename remove_reference<_From + >::type>::type __src_t; + typedef typename remove_cv<typename remove_reference<_To + >::type>::type __dst_t; + typedef __and_<__not_<is_same<__src_t, __dst_t>>, + is_base_of<__src_t, __dst_t>> type; + static constexpr bool value = type::value; + }; + + template<typename _From, typename _To> + struct __is_base_to_derived_ref<_From, _To, false> + : public false_type + { }; + + template<typename _From, typename _To, bool + = __and_<is_lvalue_reference<_From>, + is_rvalue_reference<_To>>::value> + struct __is_lvalue_to_rvalue_ref; + + template<typename _From, typename _To> + struct __is_lvalue_to_rvalue_ref<_From, _To, true> + { + typedef typename remove_cv<typename remove_reference< + _From>::type>::type __src_t; + typedef typename remove_cv<typename remove_reference< + _To>::type>::type __dst_t; + typedef __or_<is_same<__src_t, __dst_t>, + is_base_of<__dst_t, __src_t>> type; + static constexpr bool value = type::value; + }; + + template<typename _From, typename _To> + struct __is_lvalue_to_rvalue_ref<_From, _To, false> + : public false_type + { }; + + // Here we handle direct-initialization to a reference type as + // equivalent to a static_cast modulo overshooting conversions. + // These are restricted to the following conversions: + // a) A glvalue of a base class to a derived class reference + // b) An lvalue to an rvalue-reference of reference-compatible + // types + template<typename _Tp, typename _Arg> + struct __is_direct_constructible_ref_cast + : public __and_<__is_static_castable<_Arg, _Tp>, + __not_<__or_<__is_base_to_derived_ref<_Arg, _Tp>, + __is_lvalue_to_rvalue_ref<_Arg, _Tp> + >>>::type + { }; + + template<typename _Tp, typename _Arg> + struct __is_direct_constructible_new + : public conditional<is_reference<_Tp>::value, + __is_direct_constructible_ref_cast<_Tp, _Arg>, + __is_direct_constructible_new_safe<_Tp, _Arg> + >::type + { }; + + template<typename _Tp, typename _Arg> + struct __is_direct_constructible + : public integral_constant<bool, (__is_direct_constructible_new< + _Tp, _Arg>::value)> + { }; + + // Since default-construction and binary direct-initialization have + // been handled separately, the implementation of the remaining + // n-ary construction cases is rather straightforward. + struct __do_is_nary_constructible_impl + { + template<typename _Tp, typename... _Args, typename + = decltype(_Tp(declval<_Args>()...))> + static true_type __test(int); + + template<typename, typename...> + static false_type __test(...); + }; + + template<typename _Tp, typename... _Args> + struct __is_nary_constructible_impl + : public __do_is_nary_constructible_impl + { + typedef decltype(__test<_Tp, _Args...>(0)) type; + }; + + template<typename _Tp, typename... _Args> + struct __is_nary_constructible + : public __is_nary_constructible_impl<_Tp, _Args...>::type + { + static_assert(sizeof...(_Args) > 1, + "Only useful for > 1 arguments"); + }; + + template<typename _Tp, typename... _Args> + struct __is_constructible_impl + : public __is_nary_constructible<_Tp, _Args...> + { }; + + template<typename _Tp, typename _Arg> + struct __is_constructible_impl<_Tp, _Arg> + : public __is_direct_constructible<_Tp, _Arg> + { }; + + template<typename _Tp> + struct __is_constructible_impl<_Tp> + : public is_default_constructible<_Tp> + { }; + + /// is_constructible + template<typename _Tp, typename... _Args> + struct is_constructible + : public integral_constant<bool, (__is_constructible_impl<_Tp, + _Args...>::value)> + { }; + + template<typename _Tp, bool = is_void<_Tp>::value> + struct __is_copy_constructible_impl; + + template<typename _Tp> + struct __is_copy_constructible_impl<_Tp, true> + : public false_type { }; + + template<typename _Tp> + struct __is_copy_constructible_impl<_Tp, false> + : public is_constructible<_Tp, const _Tp&> + { }; + + /// is_copy_constructible + template<typename _Tp> + struct is_copy_constructible + : public __is_copy_constructible_impl<_Tp> + { }; + + template<typename _Tp, bool = is_void<_Tp>::value> + struct __is_move_constructible_impl; + + template<typename _Tp> + struct __is_move_constructible_impl<_Tp, true> + : public false_type { }; + + template<typename _Tp> + struct __is_move_constructible_impl<_Tp, false> + : public is_constructible<_Tp, _Tp&&> + { }; + + /// is_move_constructible + template<typename _Tp> + struct is_move_constructible + : public __is_move_constructible_impl<_Tp> + { }; + + template<typename _Tp> + struct __is_nt_default_constructible_atom + : public integral_constant<bool, noexcept(_Tp())> + { }; + + template<typename _Tp, bool = is_array<_Tp>::value> + struct __is_nt_default_constructible_impl; + + template<typename _Tp> + struct __is_nt_default_constructible_impl<_Tp, true> + : public __and_<__is_array_known_bounds<_Tp>, + __is_nt_default_constructible_atom<typename + remove_all_extents<_Tp>::type>>::type + { }; + + template<typename _Tp> + struct __is_nt_default_constructible_impl<_Tp, false> + : public __is_nt_default_constructible_atom<_Tp> + { }; + + /// is_nothrow_default_constructible + template<typename _Tp> + struct is_nothrow_default_constructible + : public __and_<is_default_constructible<_Tp>, + __is_nt_default_constructible_impl<_Tp>>::type + { }; + + template<typename _Tp, typename... _Args> + struct __is_nt_constructible_impl + : public integral_constant<bool, noexcept(_Tp(declval<_Args>()...))> + { }; + + template<typename _Tp, typename _Arg> + struct __is_nt_constructible_impl<_Tp, _Arg> + : public integral_constant<bool, + noexcept(static_cast<_Tp>(declval<_Arg>()))> + { }; + + template<typename _Tp> + struct __is_nt_constructible_impl<_Tp> + : public is_nothrow_default_constructible<_Tp> + { }; + + /// is_nothrow_constructible + template<typename _Tp, typename... _Args> + struct is_nothrow_constructible + : public __and_<is_constructible<_Tp, _Args...>, + __is_nt_constructible_impl<_Tp, _Args...>>::type + { }; + + template<typename _Tp, bool = is_void<_Tp>::value> + struct __is_nothrow_copy_constructible_impl; + + template<typename _Tp> + struct __is_nothrow_copy_constructible_impl<_Tp, true> + : public false_type { }; + + template<typename _Tp> + struct __is_nothrow_copy_constructible_impl<_Tp, false> + : public is_nothrow_constructible<_Tp, const _Tp&> + { }; + + /// is_nothrow_copy_constructible + template<typename _Tp> + struct is_nothrow_copy_constructible + : public __is_nothrow_copy_constructible_impl<_Tp> + { }; + + template<typename _Tp, bool = is_void<_Tp>::value> + struct __is_nothrow_move_constructible_impl; + + template<typename _Tp> + struct __is_nothrow_move_constructible_impl<_Tp, true> + : public false_type { }; + + template<typename _Tp> + struct __is_nothrow_move_constructible_impl<_Tp, false> + : public is_nothrow_constructible<_Tp, _Tp&&> + { }; + + /// is_nothrow_move_constructible + template<typename _Tp> + struct is_nothrow_move_constructible + : public __is_nothrow_move_constructible_impl<_Tp> + { }; + + template<typename _Tp, typename _Up> + class __is_assignable_helper + : public __sfinae_types + { + template<typename _Tp1, typename _Up1> + static decltype(declval<_Tp1>() = declval<_Up1>(), __one()) + __test(int); + + template<typename, typename> + static __two __test(...); + + public: + static constexpr bool value = sizeof(__test<_Tp, _Up>(0)) == 1; + }; + + /// is_assignable + template<typename _Tp, typename _Up> + struct is_assignable + : public integral_constant<bool, + __is_assignable_helper<_Tp, _Up>::value> + { }; + + template<typename _Tp, bool = is_void<_Tp>::value> + struct __is_copy_assignable_impl; + + template<typename _Tp> + struct __is_copy_assignable_impl<_Tp, true> + : public false_type { }; + + template<typename _Tp> + struct __is_copy_assignable_impl<_Tp, false> + : public is_assignable<_Tp&, const _Tp&> + { }; + + /// is_copy_assignable + template<typename _Tp> + struct is_copy_assignable + : public __is_copy_assignable_impl<_Tp> + { }; + + template<typename _Tp, bool = is_void<_Tp>::value> + struct __is_move_assignable_impl; + + template<typename _Tp> + struct __is_move_assignable_impl<_Tp, true> + : public false_type { }; + + template<typename _Tp> + struct __is_move_assignable_impl<_Tp, false> + : public is_assignable<_Tp&, _Tp&&> + { }; + + /// is_move_assignable + template<typename _Tp> + struct is_move_assignable + : public __is_move_assignable_impl<_Tp> + { }; + + template<typename _Tp, typename _Up> + struct __is_nt_assignable_impl + : public integral_constant<bool, noexcept(declval<_Tp>() = declval<_Up>())> + { }; + + /// is_nothrow_assignable + template<typename _Tp, typename _Up> + struct is_nothrow_assignable + : public __and_<is_assignable<_Tp, _Up>, + __is_nt_assignable_impl<_Tp, _Up>>::type + { }; + + template<typename _Tp, bool = is_void<_Tp>::value> + struct __is_nt_copy_assignable_impl; + + template<typename _Tp> + struct __is_nt_copy_assignable_impl<_Tp, true> + : public false_type { }; + + template<typename _Tp> + struct __is_nt_copy_assignable_impl<_Tp, false> + : public is_nothrow_assignable<_Tp&, const _Tp&> + { }; + + /// is_nothrow_copy_assignable + template<typename _Tp> + struct is_nothrow_copy_assignable + : public __is_nt_copy_assignable_impl<_Tp> + { }; + + template<typename _Tp, bool = is_void<_Tp>::value> + struct __is_nt_move_assignable_impl; + + template<typename _Tp> + struct __is_nt_move_assignable_impl<_Tp, true> + : public false_type { }; + + template<typename _Tp> + struct __is_nt_move_assignable_impl<_Tp, false> + : public is_nothrow_assignable<_Tp&, _Tp&&> + { }; + + /// is_nothrow_move_assignable + template<typename _Tp> + struct is_nothrow_move_assignable + : public __is_nt_move_assignable_impl<_Tp> + { }; + + /// has_trivial_default_constructor + template<typename _Tp> + struct has_trivial_default_constructor + : public integral_constant<bool, __has_trivial_constructor(_Tp)> + { }; + + /// has_trivial_copy_constructor + template<typename _Tp> + struct has_trivial_copy_constructor + : public integral_constant<bool, __has_trivial_copy(_Tp)> + { }; + + /// has_trivial_copy_assign + template<typename _Tp> + struct has_trivial_copy_assign + : public integral_constant<bool, __has_trivial_assign(_Tp)> + { }; + + /// has_trivial_destructor + template<typename _Tp> + struct has_trivial_destructor + : public integral_constant<bool, __has_trivial_destructor(_Tp)> + { }; + + /// has_virtual_destructor + template<typename _Tp> + struct has_virtual_destructor + : public integral_constant<bool, __has_virtual_destructor(_Tp)> + { }; + + + // type property queries. + + /// alignment_of + template<typename _Tp> + struct alignment_of + : public integral_constant<size_t, __alignof__(_Tp)> { }; + + /// rank + template<typename> + struct rank + : public integral_constant<size_t, 0> { }; + + template<typename _Tp, size_t _Size> + struct rank<_Tp[_Size]> + : public integral_constant<size_t, 1 + rank<_Tp>::value> { }; + + template<typename _Tp> + struct rank<_Tp[]> + : public integral_constant<size_t, 1 + rank<_Tp>::value> { }; + + /// extent + template<typename, unsigned _Uint> + struct extent + : public integral_constant<size_t, 0> { }; + + template<typename _Tp, unsigned _Uint, size_t _Size> + struct extent<_Tp[_Size], _Uint> + : public integral_constant<size_t, + _Uint == 0 ? _Size : extent<_Tp, + _Uint - 1>::value> + { }; + + template<typename _Tp, unsigned _Uint> + struct extent<_Tp[], _Uint> + : public integral_constant<size_t, + _Uint == 0 ? 0 : extent<_Tp, + _Uint - 1>::value> + { }; + + + // type relations. + + /// is_same + template<typename, typename> + struct is_same + : public false_type { }; + + template<typename _Tp> + struct is_same<_Tp, _Tp> + : public true_type { }; + + /// is_base_of + template<typename _Base, typename _Derived> + struct is_base_of + : public integral_constant<bool, __is_base_of(_Base, _Derived)> + { }; + + template<typename _From, typename _To, + bool = __or_<is_void<_From>, is_function<_To>, + is_array<_To>>::value> + struct __is_convertible_helper + { static constexpr bool value = is_void<_To>::value; }; + + template<typename _From, typename _To> + class __is_convertible_helper<_From, _To, false> + : public __sfinae_types + { + template<typename _To1> + static void __test_aux(_To1); + + template<typename _From1, typename _To1> + static decltype(__test_aux<_To1>(declval<_From1>()), __one()) + __test(int); + + template<typename, typename> + static __two __test(...); + + public: + static constexpr bool value = sizeof(__test<_From, _To>(0)) == 1; + }; + + /// is_convertible + template<typename _From, typename _To> + struct is_convertible + : public integral_constant<bool, + __is_convertible_helper<_From, _To>::value> + { }; + + /// is_explicitly_convertible + template<typename _From, typename _To> + struct is_explicitly_convertible + : public is_constructible<_To, _From> + { }; + + + // const-volatile modifications. + + /// remove_const + template<typename _Tp> + struct remove_const + { typedef _Tp type; }; + + template<typename _Tp> + struct remove_const<_Tp const> + { typedef _Tp type; }; + + /// remove_volatile + template<typename _Tp> + struct remove_volatile + { typedef _Tp type; }; + + template<typename _Tp> + struct remove_volatile<_Tp volatile> + { typedef _Tp type; }; + + /// remove_cv + template<typename _Tp> + struct remove_cv + { + typedef typename + remove_const<typename remove_volatile<_Tp>::type>::type type; + }; + + /// add_const + template<typename _Tp> + struct add_const + { typedef _Tp const type; }; + + /// add_volatile + template<typename _Tp> + struct add_volatile + { typedef _Tp volatile type; }; + + /// add_cv + template<typename _Tp> + struct add_cv + { + typedef typename + add_const<typename add_volatile<_Tp>::type>::type type; + }; + + + // Reference transformations. + + /// remove_reference + template<typename _Tp> + struct remove_reference + { typedef _Tp type; }; + + template<typename _Tp> + struct remove_reference<_Tp&> + { typedef _Tp type; }; + + template<typename _Tp> + struct remove_reference<_Tp&&> + { typedef _Tp type; }; + + template<typename _Tp, + bool = __and_<__not_<is_reference<_Tp>>, + __not_<is_void<_Tp>>>::value, + bool = is_rvalue_reference<_Tp>::value> + struct __add_lvalue_reference_helper + { typedef _Tp type; }; + + template<typename _Tp> + struct __add_lvalue_reference_helper<_Tp, true, false> + { typedef _Tp& type; }; + + template<typename _Tp> + struct __add_lvalue_reference_helper<_Tp, false, true> + { typedef typename remove_reference<_Tp>::type& type; }; + + /// add_lvalue_reference + template<typename _Tp> + struct add_lvalue_reference + : public __add_lvalue_reference_helper<_Tp> + { }; + + template<typename _Tp, + bool = __and_<__not_<is_reference<_Tp>>, + __not_<is_void<_Tp>>>::value> + struct __add_rvalue_reference_helper + { typedef _Tp type; }; + + template<typename _Tp> + struct __add_rvalue_reference_helper<_Tp, true> + { typedef _Tp&& type; }; + + /// add_rvalue_reference + template<typename _Tp> + struct add_rvalue_reference + : public __add_rvalue_reference_helper<_Tp> + { }; + + + // sign modifications. + + // Utility for constructing identically cv-qualified types. + template<typename _Unqualified, bool _IsConst, bool _IsVol> + struct __cv_selector; + + template<typename _Unqualified> + struct __cv_selector<_Unqualified, false, false> + { typedef _Unqualified __type; }; + + template<typename _Unqualified> + struct __cv_selector<_Unqualified, false, true> + { typedef volatile _Unqualified __type; }; + + template<typename _Unqualified> + struct __cv_selector<_Unqualified, true, false> + { typedef const _Unqualified __type; }; + + template<typename _Unqualified> + struct __cv_selector<_Unqualified, true, true> + { typedef const volatile _Unqualified __type; }; + + template<typename _Qualified, typename _Unqualified, + bool _IsConst = is_const<_Qualified>::value, + bool _IsVol = is_volatile<_Qualified>::value> + class __match_cv_qualifiers + { + typedef __cv_selector<_Unqualified, _IsConst, _IsVol> __match; + + public: + typedef typename __match::__type __type; + }; + + // Utility for finding the unsigned versions of signed integral types. + template<typename _Tp> + struct __make_unsigned + { typedef _Tp __type; }; + + template<> + struct __make_unsigned<char> + { typedef unsigned char __type; }; + + template<> + struct __make_unsigned<signed char> + { typedef unsigned char __type; }; + + template<> + struct __make_unsigned<short> + { typedef unsigned short __type; }; + + template<> + struct __make_unsigned<int> + { typedef unsigned int __type; }; + + template<> + struct __make_unsigned<long> + { typedef unsigned long __type; }; + + template<> + struct __make_unsigned<long long> + { typedef unsigned long long __type; }; + +#if !defined(__STRICT_ANSI__) && defined(_GLIBCXX_USE_INT128) + template<> + struct __make_unsigned<__int128> + { typedef unsigned __int128 __type; }; +#endif + + // Select between integral and enum: not possible to be both. + template<typename _Tp, + bool _IsInt = is_integral<_Tp>::value, + bool _IsEnum = is_enum<_Tp>::value> + class __make_unsigned_selector; + + template<typename _Tp> + class __make_unsigned_selector<_Tp, true, false> + { + typedef __make_unsigned<typename remove_cv<_Tp>::type> __unsignedt; + typedef typename __unsignedt::__type __unsigned_type; + typedef __match_cv_qualifiers<_Tp, __unsigned_type> __cv_unsigned; + + public: + typedef typename __cv_unsigned::__type __type; + }; + + template<typename _Tp> + class __make_unsigned_selector<_Tp, false, true> + { + // With -fshort-enums, an enum may be as small as a char. + typedef unsigned char __smallest; + static const bool __b0 = sizeof(_Tp) <= sizeof(__smallest); + static const bool __b1 = sizeof(_Tp) <= sizeof(unsigned short); + static const bool __b2 = sizeof(_Tp) <= sizeof(unsigned int); + typedef conditional<__b2, unsigned int, unsigned long> __cond2; + typedef typename __cond2::type __cond2_type; + typedef conditional<__b1, unsigned short, __cond2_type> __cond1; + typedef typename __cond1::type __cond1_type; + + public: + typedef typename conditional<__b0, __smallest, __cond1_type>::type __type; + }; + + // Given an integral/enum type, return the corresponding unsigned + // integer type. + // Primary template. + /// make_unsigned + template<typename _Tp> + struct make_unsigned + { typedef typename __make_unsigned_selector<_Tp>::__type type; }; + + // Integral, but don't define. + template<> + struct make_unsigned<bool>; + + + // Utility for finding the signed versions of unsigned integral types. + template<typename _Tp> + struct __make_signed + { typedef _Tp __type; }; + + template<> + struct __make_signed<char> + { typedef signed char __type; }; + + template<> + struct __make_signed<unsigned char> + { typedef signed char __type; }; + + template<> + struct __make_signed<unsigned short> + { typedef signed short __type; }; + + template<> + struct __make_signed<unsigned int> + { typedef signed int __type; }; + + template<> + struct __make_signed<unsigned long> + { typedef signed long __type; }; + + template<> + struct __make_signed<unsigned long long> + { typedef signed long long __type; }; + +#if !defined(__STRICT_ANSI__) && defined(_GLIBCXX_USE_INT128) + template<> + struct __make_signed<unsigned __int128> + { typedef __int128 __type; }; +#endif + + // Select between integral and enum: not possible to be both. + template<typename _Tp, + bool _IsInt = is_integral<_Tp>::value, + bool _IsEnum = is_enum<_Tp>::value> + class __make_signed_selector; + + template<typename _Tp> + class __make_signed_selector<_Tp, true, false> + { + typedef __make_signed<typename remove_cv<_Tp>::type> __signedt; + typedef typename __signedt::__type __signed_type; + typedef __match_cv_qualifiers<_Tp, __signed_type> __cv_signed; + + public: + typedef typename __cv_signed::__type __type; + }; + + template<typename _Tp> + class __make_signed_selector<_Tp, false, true> + { + // With -fshort-enums, an enum may be as small as a char. + typedef signed char __smallest; + static const bool __b0 = sizeof(_Tp) <= sizeof(__smallest); + static const bool __b1 = sizeof(_Tp) <= sizeof(signed short); + static const bool __b2 = sizeof(_Tp) <= sizeof(signed int); + typedef conditional<__b2, signed int, signed long> __cond2; + typedef typename __cond2::type __cond2_type; + typedef conditional<__b1, signed short, __cond2_type> __cond1; + typedef typename __cond1::type __cond1_type; + + public: + typedef typename conditional<__b0, __smallest, __cond1_type>::type __type; + }; + + // Given an integral/enum type, return the corresponding signed + // integer type. + // Primary template. + /// make_signed + template<typename _Tp> + struct make_signed + { typedef typename __make_signed_selector<_Tp>::__type type; }; + + // Integral, but don't define. + template<> + struct make_signed<bool>; + + + // array modifications. + + /// remove_extent + template<typename _Tp> + struct remove_extent + { typedef _Tp type; }; + + template<typename _Tp, size_t _Size> + struct remove_extent<_Tp[_Size]> + { typedef _Tp type; }; + + template<typename _Tp> + struct remove_extent<_Tp[]> + { typedef _Tp type; }; + + /// remove_all_extents + template<typename _Tp> + struct remove_all_extents + { typedef _Tp type; }; + + template<typename _Tp, size_t _Size> + struct remove_all_extents<_Tp[_Size]> + { typedef typename remove_all_extents<_Tp>::type type; }; + + template<typename _Tp> + struct remove_all_extents<_Tp[]> + { typedef typename remove_all_extents<_Tp>::type type; }; + + + // pointer modifications. + + template<typename _Tp, typename> + struct __remove_pointer_helper + { typedef _Tp type; }; + + template<typename _Tp, typename _Up> + struct __remove_pointer_helper<_Tp, _Up*> + { typedef _Up type; }; + + /// remove_pointer + template<typename _Tp> + struct remove_pointer + : public __remove_pointer_helper<_Tp, typename remove_cv<_Tp>::type> + { }; + + /// add_pointer + template<typename _Tp> + struct add_pointer + { typedef typename remove_reference<_Tp>::type* type; }; + + + template<size_t _Len> + struct __aligned_storage_msa + { + union __type + { + unsigned char __data[_Len]; + struct __attribute__((__aligned__)) { } __align; + }; + }; + + /** + * @brief Alignment type. + * + * The value of _Align is a default-alignment which shall be the + * most stringent alignment requirement for any C++ object type + * whose size is no greater than _Len (3.9). The member typedef + * type shall be a POD type suitable for use as uninitialized + * storage for any object whose size is at most _Len and whose + * alignment is a divisor of _Align. + */ + template<size_t _Len, size_t _Align = + __alignof__(typename __aligned_storage_msa<_Len>::__type)> + struct aligned_storage + { + union type + { + unsigned char __data[_Len]; + struct __attribute__((__aligned__((_Align)))) { } __align; + }; + }; + + + // Decay trait for arrays and functions, used for perfect forwarding + // in make_pair, make_tuple, etc. + template<typename _Up, + bool _IsArray = is_array<_Up>::value, + bool _IsFunction = is_function<_Up>::value> + struct __decay_selector; + + // NB: DR 705. + template<typename _Up> + struct __decay_selector<_Up, false, false> + { typedef typename remove_cv<_Up>::type __type; }; + + template<typename _Up> + struct __decay_selector<_Up, true, false> + { typedef typename remove_extent<_Up>::type* __type; }; + + template<typename _Up> + struct __decay_selector<_Up, false, true> + { typedef typename add_pointer<_Up>::type __type; }; + + /// decay + template<typename _Tp> + class decay + { + typedef typename remove_reference<_Tp>::type __remove_type; + + public: + typedef typename __decay_selector<__remove_type>::__type type; + }; + + template<typename _Tp> + class reference_wrapper; + + // Helper which adds a reference to a type when given a reference_wrapper + template<typename _Tp> + struct __strip_reference_wrapper + { + typedef _Tp __type; + }; + + template<typename _Tp> + struct __strip_reference_wrapper<reference_wrapper<_Tp> > + { + typedef _Tp& __type; + }; + + template<typename _Tp> + struct __strip_reference_wrapper<const reference_wrapper<_Tp> > + { + typedef _Tp& __type; + }; + + template<typename _Tp> + struct __decay_and_strip + { + typedef typename __strip_reference_wrapper< + typename decay<_Tp>::type>::__type __type; + }; + + + // Define a nested type if some predicate holds. + // Primary template. + /// enable_if + template<bool, typename _Tp = void> + struct enable_if + { }; + + // Partial specialization for true. + template<typename _Tp> + struct enable_if<true, _Tp> + { typedef _Tp type; }; + + + // A conditional expression, but for types. If true, first, if false, second. + // Primary template. + /// conditional + template<bool _Cond, typename _Iftrue, typename _Iffalse> + struct conditional + { typedef _Iftrue type; }; + + // Partial specialization for false. + template<typename _Iftrue, typename _Iffalse> + struct conditional<false, _Iftrue, _Iffalse> + { typedef _Iffalse type; }; + + + /// common_type + template<typename... _Tp> + struct common_type; + + template<typename _Tp> + struct common_type<_Tp> + { typedef _Tp type; }; + + template<typename _Tp, typename _Up> + struct common_type<_Tp, _Up> + { typedef decltype(true ? declval<_Tp>() : declval<_Up>()) type; }; + + template<typename _Tp, typename _Up, typename... _Vp> + struct common_type<_Tp, _Up, _Vp...> + { + typedef typename + common_type<typename common_type<_Tp, _Up>::type, _Vp...>::type type; + }; + + /// underlying_type + template<typename _Tp> + struct underlying_type + { + typedef __underlying_type(_Tp) type; + }; + + /// declval + template<typename _Tp> + struct __declval_protector + { + static const bool __stop = false; + static typename add_rvalue_reference<_Tp>::type __delegate(); + }; + + template<typename _Tp> + inline typename add_rvalue_reference<_Tp>::type + declval() noexcept + { + static_assert(__declval_protector<_Tp>::__stop, + "declval() must not be used!"); + return __declval_protector<_Tp>::__delegate(); + } + + /// result_of + template<typename _Signature> + class result_of; + + template<typename _MemPtr, typename _Arg> + struct _Result_of_memobj; + + template<typename _Res, typename _Class, typename _Arg> + struct _Result_of_memobj<_Res _Class::*, _Arg> + { + private: + typedef _Res _Class::* _Func; + + template<typename _Tp> + static _Tp _S_get(const _Class&); + template<typename _Tp> + static decltype(*declval<_Tp>()) _S_get(...); + + public: + typedef + decltype(_S_get<_Arg>(declval<_Arg>()).*declval<_Func>()) + __type; + }; + + template<typename _MemPtr, typename _Arg, typename... _ArgTypes> + struct _Result_of_memfun; + + template<typename _Res, typename _Class, typename _Arg, typename... _Args> + struct _Result_of_memfun<_Res _Class::*, _Arg, _Args...> + { + private: + typedef _Res _Class::* _Func; + + template<typename _Tp> + static _Tp _S_get(const _Class&); + template<typename _Tp> + static decltype(*declval<_Tp>()) _S_get(...); + + public: + typedef + decltype((_S_get<_Arg>(declval<_Arg>()).*declval<_Func>()) + (declval<_Args>()...) ) + __type; + }; + + template<bool, bool, typename _Functor, typename... _ArgTypes> + struct _Result_of_impl; + + template<typename _Functor, typename... _ArgTypes> + struct _Result_of_impl<false, false, _Functor, _ArgTypes...> + { + typedef + decltype( declval<_Functor>()(declval<_ArgTypes>()...) ) + __type; + }; + + template<typename _MemPtr, typename _Arg> + struct _Result_of_impl<true, false, _MemPtr, _Arg> + : _Result_of_memobj<typename remove_reference<_MemPtr>::type, _Arg> + { + typedef typename _Result_of_memobj< + typename remove_reference<_MemPtr>::type, _Arg>::__type + __type; + }; + + template<typename _MemPtr, typename _Arg, typename... _ArgTypes> + struct _Result_of_impl<false, true, _MemPtr, _Arg, _ArgTypes...> + : _Result_of_memfun<typename remove_reference<_MemPtr>::type, _Arg, + _ArgTypes...> + { + typedef typename _Result_of_memfun< + typename remove_reference<_MemPtr>::type, _Arg, _ArgTypes...>::__type + __type; + }; + + template<typename _Functor, typename... _ArgTypes> + struct result_of<_Functor(_ArgTypes...)> + : _Result_of_impl<is_member_object_pointer< + typename remove_reference<_Functor>::type >::value, + is_member_function_pointer< + typename remove_reference<_Functor>::type >::value, + _Functor, _ArgTypes...> + { + typedef typename _Result_of_impl< + is_member_object_pointer< + typename remove_reference<_Functor>::type >::value, + is_member_function_pointer< + typename remove_reference<_Functor>::type >::value, + _Functor, _ArgTypes...>::__type + type; + }; + + /** + * Use SFINAE to determine if the type _Tp has a publicly-accessible + * member type _NTYPE. + */ +#define _GLIBCXX_HAS_NESTED_TYPE(_NTYPE) \ + template<typename _Tp> \ + class __has_##_NTYPE##_helper \ + : __sfinae_types \ + { \ + template<typename _Up> \ + struct _Wrap_type \ + { }; \ + \ + template<typename _Up> \ + static __one __test(_Wrap_type<typename _Up::_NTYPE>*); \ + \ + template<typename _Up> \ + static __two __test(...); \ + \ + public: \ + static constexpr bool value = sizeof(__test<_Tp>(0)) == 1; \ + }; \ + \ + template<typename _Tp> \ + struct __has_##_NTYPE \ + : integral_constant<bool, __has_##_NTYPE##_helper \ + <typename remove_cv<_Tp>::type>::value> \ + { }; + + // @} group metaprogramming +// _GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +// #endif // __GXX_EXPERIMENTAL_CXX0X__ + +#endif // _GLIBCXX_TYPE_TRAITS diff --git a/libitm/memcpy.cc b/libitm/memcpy.cc new file mode 100644 index 00000000000..9919e6a9afa --- /dev/null +++ b/libitm/memcpy.cc @@ -0,0 +1,365 @@ +/* Copyright (C) 2008, 2009, 2011 Free Software Foundation, Inc. + Contributed by Richard Henderson <rth@redhat.com>. + + This file is part of the GNU Transactional Memory Library (libitm). + + Libitm is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + Libitm is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + <http://www.gnu.org/licenses/>. */ + +#include "libitm_i.h" + +using namespace GTM; + +static void +do_memcpy (uintptr_t idst, uintptr_t isrc, size_t size, + abi_dispatch::lock_type W, abi_dispatch::lock_type R) +{ + abi_dispatch *disp = abi_disp(); + // The position in the destination cacheline where *IDST starts. + uintptr_t dofs = idst & (CACHELINE_SIZE - 1); + // The position in the source cacheline where *ISRC starts. + uintptr_t sofs = isrc & (CACHELINE_SIZE - 1); + const gtm_cacheline *src + = reinterpret_cast<const gtm_cacheline *>(isrc & -CACHELINE_SIZE); + gtm_cacheline *dst + = reinterpret_cast<gtm_cacheline *>(idst & -CACHELINE_SIZE); + const gtm_cacheline *sline; + abi_dispatch::mask_pair dpair; + + if (size == 0) + return; + + // If both SRC and DST data start at the same position in the cachelines, + // we can easily copy the data in tandem, cacheline by cacheline... + if (dofs == sofs) + { + // We copy the data in three stages: + + // (a) Copy stray bytes at the beginning that are smaller than a + // cacheline. + if (sofs != 0) + { + size_t sleft = CACHELINE_SIZE - sofs; + size_t min = (size <= sleft ? size : sleft); + + dpair = disp->write_lock(dst, W); + sline = disp->read_lock(src, R); + *dpair.mask |= (((gtm_cacheline_mask)1 << min) - 1) << sofs; + memcpy (&dpair.line->b[sofs], &sline->b[sofs], min); + dst++; + src++; + size -= min; + } + + // (b) Copy subsequent cacheline sized chunks. + while (size >= CACHELINE_SIZE) + { + dpair = disp->write_lock(dst, W); + sline = disp->read_lock(src, R); + *dpair.mask = -1; + *dpair.line = *sline; + dst++; + src++; + size -= CACHELINE_SIZE; + } + + // (c) Copy anything left over. + if (size != 0) + { + dpair = disp->write_lock(dst, W); + sline = disp->read_lock(src, R); + *dpair.mask |= ((gtm_cacheline_mask)1 << size) - 1; + memcpy (dpair.line, sline, size); + } + } + // ... otherwise, we must copy the data in disparate hunks using + // temporary storage. + else + { + gtm_cacheline c; + size_t sleft = CACHELINE_SIZE - sofs; + + sline = disp->read_lock(src, R); + + // As above, we copy the data in three stages: + + // (a) Copy stray bytes at the beginning that are smaller than a + // cacheline. + if (dofs != 0) + { + size_t dleft = CACHELINE_SIZE - dofs; + size_t min = (size <= dleft ? size : dleft); + + dpair = disp->write_lock(dst, W); + *dpair.mask |= (((gtm_cacheline_mask)1 << min) - 1) << dofs; + + // If what's left in the source cacheline will fit in the + // rest of the destination cacheline, straight up copy it. + if (min <= sleft) + { + memcpy (&dpair.line->b[dofs], &sline->b[sofs], min); + sofs += min; + } + // Otherwise, we need more bits from the source cacheline + // that are available. Piece together what we need from + // contiguous (source) cachelines, into temp space, and copy + // it over. + else + { + memcpy (&c, &sline->b[sofs], sleft); + sline = disp->read_lock(++src, R); + sofs = min - sleft; + memcpy (&c.b[sleft], sline, sofs); + memcpy (&dpair.line->b[dofs], &c, min); + } + sleft = CACHELINE_SIZE - sofs; + + dst++; + size -= min; + } + + // (b) Copy subsequent cacheline sized chunks. + while (size >= CACHELINE_SIZE) + { + // We have a full (destination) cacheline where to put the + // data, but to get to the corresponding cacheline sized + // chunk in the source, we have to piece together two + // contiguous source cachelines. + + memcpy (&c, &sline->b[sofs], sleft); + sline = disp->read_lock(++src, R); + memcpy (&c.b[sleft], sline, sofs); + + dpair = disp->write_lock(dst, W); + *dpair.mask = -1; + *dpair.line = c; + + dst++; + size -= CACHELINE_SIZE; + } + + // (c) Copy anything left over. + if (size != 0) + { + dpair = disp->write_lock(dst, W); + *dpair.mask |= ((gtm_cacheline_mask)1 << size) - 1; + // If what's left to copy is entirely in the remaining + // source cacheline, do it. + if (size <= sleft) + memcpy (dpair.line, &sline->b[sofs], size); + // Otherwise, piece together the remaining bits, and copy. + else + { + memcpy (&c, &sline->b[sofs], sleft); + sline = disp->read_lock(++src, R); + memcpy (&c.b[sleft], sline, size - sleft); + memcpy (dpair.line, &c, size); + } + } + } +} + +static void +do_memmove (uintptr_t idst, uintptr_t isrc, size_t size, + abi_dispatch::lock_type W, abi_dispatch::lock_type R) +{ + abi_dispatch *disp = abi_disp(); + uintptr_t dleft, sleft, sofs, dofs; + const gtm_cacheline *sline; + abi_dispatch::mask_pair dpair; + + if (size == 0) + return; + + /* The co-aligned memmove below doesn't work for DST == SRC, so filter + that out. It's tempting to just return here, as this is a no-op move. + However, our caller has the right to expect the locks to be acquired + as advertized. */ + if (__builtin_expect (idst == isrc, 0)) + { + /* If the write lock is already acquired, nothing to do. */ + if (W == abi_dispatch::WaW) + return; + /* If the destination is protected, acquire a write lock. */ + if (W != abi_dispatch::NOLOCK) + R = abi_dispatch::RfW; + /* Notice serial mode, where we don't acquire locks at all. */ + if (R == abi_dispatch::NOLOCK) + return; + + idst = isrc + size; + for (isrc &= -CACHELINE_SIZE; isrc < idst; isrc += CACHELINE_SIZE) + disp->read_lock(reinterpret_cast<const gtm_cacheline *>(isrc), R); + return; + } + + /* Fall back to memcpy if the implementation above can handle it. */ + if (idst < isrc || isrc + size <= idst) + { + do_memcpy (idst, isrc, size, W, R); + return; + } + + /* What remains requires a backward copy from the end of the blocks. */ + idst += size; + isrc += size; + dofs = idst & (CACHELINE_SIZE - 1); + sofs = isrc & (CACHELINE_SIZE - 1); + dleft = CACHELINE_SIZE - dofs; + sleft = CACHELINE_SIZE - sofs; + + gtm_cacheline *dst + = reinterpret_cast<gtm_cacheline *>(idst & -CACHELINE_SIZE); + const gtm_cacheline *src + = reinterpret_cast<const gtm_cacheline *>(isrc & -CACHELINE_SIZE); + if (dofs == 0) + dst--; + if (sofs == 0) + src--; + + if (dofs == sofs) + { + /* Since DST and SRC are co-aligned, and we didn't use the memcpy + optimization above, that implies that SIZE > CACHELINE_SIZE. */ + if (sofs != 0) + { + dpair = disp->write_lock(dst, W); + sline = disp->read_lock(src, R); + *dpair.mask |= ((gtm_cacheline_mask)1 << sleft) - 1; + memcpy (dpair.line, sline, sleft); + dst--; + src--; + size -= sleft; + } + + while (size >= CACHELINE_SIZE) + { + dpair = disp->write_lock(dst, W); + sline = disp->read_lock(src, R); + *dpair.mask = -1; + *dpair.line = *sline; + dst--; + src--; + size -= CACHELINE_SIZE; + } + + if (size != 0) + { + size_t ofs = CACHELINE_SIZE - size; + dpair = disp->write_lock(dst, W); + sline = disp->read_lock(src, R); + *dpair.mask |= (((gtm_cacheline_mask)1 << size) - 1) << ofs; + memcpy (&dpair.line->b[ofs], &sline->b[ofs], size); + } + } + else + { + gtm_cacheline c; + + sline = disp->read_lock(src, R); + if (dofs != 0) + { + size_t min = (size <= dofs ? size : dofs); + + if (min <= sofs) + { + sofs -= min; + memcpy (&c, &sline->b[sofs], min); + } + else + { + size_t min_ofs = min - sofs; + memcpy (&c.b[min_ofs], sline, sofs); + sline = disp->read_lock(--src, R); + sofs = CACHELINE_SIZE - min_ofs; + memcpy (&c, &sline->b[sofs], min_ofs); + } + + dofs = dleft - min; + dpair = disp->write_lock(dst, W); + *dpair.mask |= (((gtm_cacheline_mask)1 << min) - 1) << dofs; + memcpy (&dpair.line->b[dofs], &c, min); + + sleft = CACHELINE_SIZE - sofs; + dst--; + size -= min; + } + + while (size >= CACHELINE_SIZE) + { + memcpy (&c.b[sleft], sline, sofs); + sline = disp->read_lock(--src, R); + memcpy (&c, &sline->b[sofs], sleft); + + dpair = disp->write_lock(dst, W); + *dpair.mask = -1; + *dpair.line = c; + + dst--; + size -= CACHELINE_SIZE; + } + + if (size != 0) + { + dofs = CACHELINE_SIZE - size; + + memcpy (&c.b[sleft], sline, sofs); + if (sleft > dofs) + { + sline = disp->read_lock(--src, R); + memcpy (&c, &sline->b[sofs], sleft); + } + + dpair = disp->write_lock(dst, W); + *dpair.mask |= (gtm_cacheline_mask)-1 << dofs; + memcpy (&dpair.line->b[dofs], &c.b[dofs], size); + } + } +} + +#define ITM_MEM_DEF(NAME, READ, WRITE) \ +void ITM_REGPARM _ITM_memcpy##NAME(void *dst, const void *src, size_t size) \ +{ \ + do_memcpy ((uintptr_t)dst, (uintptr_t)src, size, \ + abi_dispatch::WRITE, abi_dispatch::READ); \ +} \ +void ITM_REGPARM _ITM_memmove##NAME(void *dst, const void *src, size_t size) \ +{ \ + do_memmove ((uintptr_t)dst, (uintptr_t)src, size, \ + abi_dispatch::WRITE, abi_dispatch::READ); \ +} + +ITM_MEM_DEF(RnWt, NOLOCK, W) +ITM_MEM_DEF(RnWtaR, NOLOCK, WaR) +ITM_MEM_DEF(RnWtaW, NOLOCK, WaW) + +ITM_MEM_DEF(RtWn, R, NOLOCK) +ITM_MEM_DEF(RtWt, R, W) +ITM_MEM_DEF(RtWtaR, R, WaR) +ITM_MEM_DEF(RtWtaW, R, WaW) + +ITM_MEM_DEF(RtaRWn, RaR, NOLOCK) +ITM_MEM_DEF(RtaRWt, RaR, W) +ITM_MEM_DEF(RtaRWtaR, RaR, WaR) +ITM_MEM_DEF(RtaRWtaW, RaR, WaW) + +ITM_MEM_DEF(RtaWWn, RaW, NOLOCK) +ITM_MEM_DEF(RtaWWt, RaW, W) +ITM_MEM_DEF(RtaWWtaR, RaW, WaR) +ITM_MEM_DEF(RtaWWtaW, RaW, WaW) diff --git a/libitm/memset.cc b/libitm/memset.cc new file mode 100644 index 00000000000..3a627dd6c7d --- /dev/null +++ b/libitm/memset.cc @@ -0,0 +1,78 @@ +/* Copyright (C) 2008, 2009, 2011 Free Software Foundation, Inc. + Contributed by Richard Henderson <rth@redhat.com>. + + This file is part of the GNU Transactional Memory Library (libitm). + + Libitm is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + Libitm is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + <http://www.gnu.org/licenses/>. */ + +#include "libitm_i.h" + +using namespace GTM; + +static void +do_memset(uintptr_t idst, int c, size_t size, abi_dispatch::lock_type W) +{ + abi_dispatch *disp = abi_disp(); + uintptr_t dofs = idst & (CACHELINE_SIZE - 1); + abi_dispatch::mask_pair dpair; + gtm_cacheline *dst + = reinterpret_cast<gtm_cacheline *>(idst & -CACHELINE_SIZE); + + if (size == 0) + return; + + if (dofs != 0) + { + size_t dleft = CACHELINE_SIZE - dofs; + size_t min = (size <= dleft ? size : dleft); + + dpair = disp->write_lock(dst, W); + *dpair.mask |= (((gtm_cacheline_mask)1 << min) - 1) << dofs; + memset (&dpair.line->b[dofs], c, min); + dst++; + size -= min; + } + + while (size >= CACHELINE_SIZE) + { + dpair = disp->write_lock(dst, W); + *dpair.mask = -1; + memset (dpair.line, c, CACHELINE_SIZE); + dst++; + size -= CACHELINE_SIZE; + } + + if (size != 0) + { + dpair = disp->write_lock(dst, W); + *dpair.mask |= ((gtm_cacheline_mask)1 << size) - 1; + memset (dpair.line, c, size); + } +} + +#define ITM_MEM_DEF(WRITE) \ +void ITM_REGPARM _ITM_memset##WRITE(void *dst, int c, size_t size) \ +{ \ + do_memset ((uintptr_t)dst, c, size, abi_dispatch::WRITE); \ +} + +ITM_MEM_DEF(W) +ITM_MEM_DEF(WaR) +ITM_MEM_DEF(WaW) diff --git a/libitm/method-gl.cc b/libitm/method-gl.cc new file mode 100644 index 00000000000..60c26626779 --- /dev/null +++ b/libitm/method-gl.cc @@ -0,0 +1,303 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + Contributed by Torvald Riegel <triegel@redhat.com>. + + This file is part of the GNU Transactional Memory Library (libitm). + + Libitm is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + Libitm is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + <http://www.gnu.org/licenses/>. */ + +#include "libitm_i.h" + +using namespace GTM; + +namespace { + +// This group consists of all TM methods that synchronize via just a single +// global lock (or ownership record). +struct gl_mg : public method_group +{ + static const gtm_word LOCK_BIT = (~(gtm_word)0 >> 1) + 1; + // We can't use the full bitrange because ~0 in gtm_thread::shared_state has + // special meaning. + static const gtm_word VERSION_MAX = (~(gtm_word)0 >> 1) - 1; + static bool is_locked(gtm_word l) { return l & LOCK_BIT; } + static gtm_word set_locked(gtm_word l) { return l | LOCK_BIT; } + static gtm_word clear_locked(gtm_word l) { return l & ~LOCK_BIT; } + + // The global ownership record. + gtm_word orec; + virtual void init() + { + orec = 0; + } + virtual void fini() { } +}; + +static gl_mg o_gl_mg; + + +// The global lock, write-through TM method. +// Acquires the orec eagerly before the first write, and then writes through. +// Reads abort if the global orec's version number changed or if it is locked. +// Currently, writes require undo-logging to prevent deadlock between the +// serial lock and the global orec (writer txn acquires orec, reader txn +// upgrades to serial and waits for all other txns, writer tries to upgrade to +// serial too but cannot, writer cannot abort either, deadlock). We could +// avoid this if the serial lock would allow us to prevent other threads from +// going to serial mode, but this probably is too much additional complexity +// just to optimize this TM method. +// gtm_thread::shared_state is used to store a transaction's current +// snapshot time (or commit time). The serial lock uses ~0 for inactive +// transactions and 0 for active ones. Thus, we always have a meaningful +// timestamp in shared_state that can be used to implement quiescence-based +// privatization safety. This even holds if a writing transaction has the +// lock bit set in its shared_state because this is fine for both the serial +// lock (the value will be smaller than ~0) and privatization safety (we +// validate that no other update transaction comitted before we acquired the +// orec, so we have the most recent timestamp and no other transaction can +// commit until we have committed). +// However, we therefore cannot use this method for a serial transaction +// (because shared_state needs to remain at ~0) and we have to be careful +// when switching to serial mode (see the special handling in trycommit() and +// rollback()). +// ??? This sharing adds some complexity wrt. serial mode. Just use a separate +// state variable? +class gl_wt_dispatch : public abi_dispatch +{ +protected: + static void pre_write(const void *addr, size_t len) + { + gtm_thread *tx = gtm_thr(); + if (unlikely(!gl_mg::is_locked(tx->shared_state))) + { + // Check for and handle version number overflow. + if (unlikely(tx->shared_state >= gl_mg::VERSION_MAX)) + tx->restart(RESTART_INIT_METHOD_GROUP); + + // CAS global orec from our snapshot time to the locked state. + // This validates that we have a consistent snapshot, which is also + // for making privatization safety work (see the class' comments). + gtm_word now = o_gl_mg.orec; + if (now != tx->shared_state) + tx->restart(RESTART_VALIDATE_WRITE); + if (__sync_val_compare_and_swap(&o_gl_mg.orec, now, + gl_mg::set_locked(now)) != now) + tx->restart(RESTART_LOCKED_WRITE); + + // Set shared_state to new value. The CAS is a full barrier, so the + // acquisition of the global orec is visible before this store here, + // and the store will not be visible before earlier data loads, which + // is required to correctly ensure privatization safety (see + // begin_and_restart() and release_orec() for further comments). + tx->shared_state = gl_mg::set_locked(now); + } + + // TODO Ensure that this gets inlined: Use internal log interface and LTO. + GTM_LB(addr, len); + } + + static void validate() + { + // Check that snapshot is consistent. The barrier ensures that this + // happens after previous data loads. + atomic_read_barrier(); + gtm_thread *tx = gtm_thr(); + gtm_word l = o_gl_mg.orec; + if (l != tx->shared_state) + tx->restart(RESTART_VALIDATE_READ); + } + + template <typename V> static V load(const V* addr, ls_modifier mod) + { + // Read-for-write should be unlikely, but we need to handle it or will + // break later WaW optimizations. + if (unlikely(mod == RfW)) + { + pre_write(addr, sizeof(V)); + return *addr; + } + V v = *addr; + if (likely(mod != RaW)) + validate(); + return v; + } + + template <typename V> static void store(V* addr, const V value, + ls_modifier mod) + { + if (unlikely(mod != WaW)) + pre_write(addr, sizeof(V)); + *addr = value; + } + +public: + static void memtransfer_static(void *dst, const void* src, size_t size, + bool may_overlap, ls_modifier dst_mod, ls_modifier src_mod) + { + if ((dst_mod != WaW && src_mod != RaW) + && (dst_mod != NONTXNAL || src_mod == RfW)) + pre_write(dst, size); + + if (!may_overlap) + ::memcpy(dst, src, size); + else + ::memmove(dst, src, size); + + if (src_mod != RfW && src_mod != RaW && src_mod != NONTXNAL + && dst_mod != WaW) + validate(); + } + + static void memset_static(void *dst, int c, size_t size, ls_modifier mod) + { + if (mod != WaW) + pre_write(dst, size); + ::memset(dst, c, size); + } + + virtual gtm_restart_reason begin_or_restart() + { + // We don't need to do anything for nested transactions. + gtm_thread *tx = gtm_thr(); + if (tx->parent_txns.size() > 0) + return NO_RESTART; + + // Spin until global orec is not locked. + // TODO This is not necessary if there are no pure loads (check txn props). + gtm_word v; + unsigned i = 0; + while (gl_mg::is_locked(v = o_gl_mg.orec)) + { + // TODO need method-specific max spin count + if (++i > gtm_spin_count_var) return RESTART_VALIDATE_READ; + cpu_relax(); + } + // This barrier ensures that we have read the global orec before later + // data loads. + atomic_read_barrier(); + + // Everything is okay, we have a snapshot time. + // We don't need to enforce any ordering for the following store. There + // are no earlier data loads in this transaction, so the store cannot + // become visible before those (which could lead to the violation of + // privatization safety). The store can become visible after later loads + // but this does not matter because the previous value will have been + // smaller or equal (the serial lock will set shared_state to zero when + // marking the transaction as active, and restarts enforce immediate + // visibility of a smaller or equal value with a barrier (see + // release_orec()). + tx->shared_state = v; + return NO_RESTART; + } + + virtual bool trycommit(gtm_word& priv_time) + { + gtm_thread* tx = gtm_thr(); + gtm_word v = tx->shared_state; + + // Special case: If shared_state is ~0, then we have acquired the + // serial lock (tx->state is not updated yet). In this case, the previous + // value isn't available anymore, so grab it from the global lock, which + // must have a meaningful value because no other transactions are active + // anymore. In particular, if it is locked, then we are an update + // transaction, which is all we care about for commit. + if (v == ~(typeof v)0) + v = o_gl_mg.orec; + + // Release the orec but do not reset shared_state, which will be modified + // by the serial lock right after our commit anyway. Also, resetting + // shared state here would interfere with the serial lock's use of this + // location. + if (gl_mg::is_locked(v)) + { + // Release the global orec, increasing its version number / timestamp. + // TODO replace with C++0x-style atomics (a release in this case) + atomic_write_barrier(); + v = gl_mg::clear_locked(v) + 1; + o_gl_mg.orec = v; + + // Need to ensure privatization safety. Every other transaction must + // have a snapshot time that is at least as high as our commit time + // (i.e., our commit must be visible to them). + priv_time = v; + } + return true; + } + + virtual void rollback(gtm_transaction_cp *cp) + { + // We don't do anything for rollbacks of nested transactions. + if (cp != 0) + return; + + gtm_thread *tx = gtm_thr(); + gtm_word v = tx->shared_state; + // Special case: If shared_state is ~0, then we have acquired the + // serial lock (tx->state is not updated yet). In this case, the previous + // value isn't available anymore, so grab it from the global lock, which + // must have a meaningful value because no other transactions are active + // anymore. In particular, if it is locked, then we are an update + // transaction, which is all we care about for rollback. + if (v == ~(typeof v)0) + v = o_gl_mg.orec; + + // Release lock and increment version number to prevent dirty reads. + // Also reset shared state here, so that begin_or_restart() can expect a + // value that is correct wrt. privatization safety. + if (gl_mg::is_locked(v)) + { + // Release the global orec, increasing its version number / timestamp. + // TODO replace with C++0x-style atomics (a release in this case) + atomic_write_barrier(); + v = gl_mg::clear_locked(v) + 1; + o_gl_mg.orec = v; + + // Also reset the timestamp published via shared_state. + // Special case: Only do this if we are not a serial transaction + // because otherwise, we would interfere with the serial lock. + if (tx->shared_state != ~(typeof tx->shared_state)0) + tx->shared_state = v; + + // We need a store-load barrier after this store to prevent it + // from becoming visible after later data loads because the + // previous value of shared_state has been higher than the actual + // snapshot time (the lock bit had been set), which could break + // privatization safety. We do not need a barrier before this + // store (see pre_write() for an explanation). + __sync_synchronize(); + } + + } + + CREATE_DISPATCH_METHODS(virtual, ) + CREATE_DISPATCH_METHODS_MEM() + + gl_wt_dispatch() : abi_dispatch(false, true, false, false, &o_gl_mg) + { } +}; + +} // anon namespace + +static const gl_wt_dispatch o_gl_wt_dispatch; + +abi_dispatch * +GTM::dispatch_gl_wt () +{ + return const_cast<gl_wt_dispatch *>(&o_gl_wt_dispatch); +} diff --git a/libitm/method-serial.cc b/libitm/method-serial.cc new file mode 100644 index 00000000000..5e85653a2f4 --- /dev/null +++ b/libitm/method-serial.cc @@ -0,0 +1,285 @@ +/* Copyright (C) 2008, 2009, 2011 Free Software Foundation, Inc. + Contributed by Richard Henderson <rth@redhat.com>. + + This file is part of the GNU Transactional Memory Library (libitm). + + Libitm is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + Libitm is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + <http://www.gnu.org/licenses/>. */ + +#include "libitm_i.h" + +// Avoid a dependency on libstdc++ for the pure virtuals in abi_dispatch. +extern "C" void HIDDEN +__cxa_pure_virtual () +{ + abort (); +} + +using namespace GTM; + +namespace { + +// This group consists of the serial, serialirr, and serialirr_onwrite +// methods, which all need no global state (except what is already provided +// by the serial mode implementation). +struct serial_mg : public method_group +{ + virtual void init() { } + virtual void fini() { } +}; + +static serial_mg o_serial_mg; + + +class serialirr_dispatch : public abi_dispatch +{ + public: + serialirr_dispatch() : abi_dispatch(false, true, true, false, &o_serial_mg) + { } + + protected: + serialirr_dispatch(bool ro, bool wt, bool uninstrumented, + bool closed_nesting, method_group* mg) : + abi_dispatch(ro, wt, uninstrumented, closed_nesting, mg) { } + + // Transactional loads and stores simply access memory directly. + // These methods are static to avoid indirect calls, and will be used by the + // virtual ABI dispatch methods or by static direct-access methods created + // below. + template <typename V> static V load(const V* addr, ls_modifier mod) + { + return *addr; + } + template <typename V> static void store(V* addr, const V value, + ls_modifier mod) + { + *addr = value; + } + + public: + static void memtransfer_static(void *dst, const void* src, size_t size, + bool may_overlap, ls_modifier dst_mod, ls_modifier src_mod) + { + if (!may_overlap) + ::memcpy(dst, src, size); + else + ::memmove(dst, src, size); + } + + static void memset_static(void *dst, int c, size_t size, ls_modifier mod) + { + ::memset(dst, c, size); + } + + CREATE_DISPATCH_METHODS(virtual, ) + CREATE_DISPATCH_METHODS_MEM() + + virtual gtm_restart_reason begin_or_restart() { return NO_RESTART; } + virtual bool trycommit(gtm_word& priv_time) { return true; } + virtual void rollback(gtm_transaction_cp *cp) { abort(); } + + virtual abi_dispatch* closed_nesting_alternative() + { + // For nested transactions with an instrumented code path, we can do + // undo logging. + return GTM::dispatch_serial(); + } +}; + +class serial_dispatch : public abi_dispatch +{ +protected: + static void log(const void *addr, size_t len) + { + // TODO Ensure that this gets inlined: Use internal log interface and LTO. + GTM_LB(addr, len); + } + + template <typename V> static V load(const V* addr, ls_modifier mod) + { + return *addr; + } + template <typename V> static void store(V* addr, const V value, + ls_modifier mod) + { + if (mod != WaW) + log(addr, sizeof(V)); + *addr = value; + } + +public: + static void memtransfer_static(void *dst, const void* src, size_t size, + bool may_overlap, ls_modifier dst_mod, ls_modifier src_mod) + { + if (dst_mod != WaW && dst_mod != NONTXNAL) + log(dst, size); + if (!may_overlap) + ::memcpy(dst, src, size); + else + ::memmove(dst, src, size); + } + + static void memset_static(void *dst, int c, size_t size, ls_modifier mod) + { + if (mod != WaW) + log(dst, size); + ::memset(dst, c, size); + } + + virtual gtm_restart_reason begin_or_restart() { return NO_RESTART; } + virtual bool trycommit(gtm_word& priv_time) { return true; } + // Local undo will handle this. + // trydropreference() need not be changed either. + virtual void rollback(gtm_transaction_cp *cp) { } + + CREATE_DISPATCH_METHODS(virtual, ) + CREATE_DISPATCH_METHODS_MEM() + + serial_dispatch() : abi_dispatch(false, true, false, true, &o_serial_mg) { } +}; + + +// Like serialirr_dispatch but does not requests serial-irrevocable mode until +// the first write in the transaction. Can be useful for read-mostly workloads +// and testing, but is likely too simple to be of general purpose. +class serialirr_onwrite_dispatch : public serialirr_dispatch +{ + public: + serialirr_onwrite_dispatch() : + serialirr_dispatch(false, true, false, false, &o_serial_mg) { } + + protected: + static void pre_write() + { + gtm_thread *tx = gtm_thr(); + if (!(tx->state & (gtm_thread::STATE_SERIAL + | gtm_thread::STATE_IRREVOCABLE))) + tx->serialirr_mode(); + } + + // Transactional loads access memory directly. + // Transactional stores switch to serial mode first. + template <typename V> static void store(V* addr, const V value, + ls_modifier mod) + { + pre_write(); + serialirr_dispatch::store(addr, value, mod); + } + + public: + static void memtransfer_static(void *dst, const void* src, size_t size, + bool may_overlap, ls_modifier dst_mod, ls_modifier src_mod) + { + pre_write(); + serialirr_dispatch::memtransfer_static(dst, src, size, may_overlap, + dst_mod, src_mod); + } + + static void memset_static(void *dst, int c, size_t size, ls_modifier mod) + { + pre_write(); + serialirr_dispatch::memset_static(dst, c, size, mod); + } + + CREATE_DISPATCH_METHODS(virtual, ) + CREATE_DISPATCH_METHODS_MEM() + + virtual void rollback(gtm_transaction_cp *cp) + { + gtm_thread *tx = gtm_thr(); + if (tx->state & gtm_thread::STATE_IRREVOCABLE) + abort(); + } +}; + +} // anon namespace + +static const serialirr_dispatch o_serialirr_dispatch; +static const serial_dispatch o_serial_dispatch; +static const serialirr_onwrite_dispatch o_serialirr_onwrite_dispatch; + +abi_dispatch * +GTM::dispatch_serialirr () +{ + return const_cast<serialirr_dispatch *>(&o_serialirr_dispatch); +} + +abi_dispatch * +GTM::dispatch_serial () +{ + return const_cast<serial_dispatch *>(&o_serial_dispatch); +} + +abi_dispatch * +GTM::dispatch_serialirr_onwrite () +{ + return + const_cast<serialirr_onwrite_dispatch *>(&o_serialirr_onwrite_dispatch); +} + +// Put the transaction into serial-irrevocable mode. + +void +GTM::gtm_thread::serialirr_mode () +{ + struct abi_dispatch *disp = abi_disp (); + bool need_restart = true; + + if (this->state & STATE_SERIAL) + { + if (this->state & STATE_IRREVOCABLE) + return; + + // Try to commit the dispatch-specific part of the transaction, as we + // would do for an outermost commit. + // We're already serial, so we don't need to ensure privatization safety + // for other transactions here. + gtm_word priv_time = 0; + bool ok = disp->trycommit (priv_time); + // Given that we're already serial, the trycommit better work. + assert (ok); + need_restart = false; + } + else if (serial_lock.write_upgrade (this)) + { + this->state |= STATE_SERIAL; + // Try to commit the dispatch-specific part of the transaction, as we + // would do for an outermost commit. + // We have successfully upgraded to serial mode, so we don't need to + // ensure privatization safety for other transactions here. + gtm_word priv_time = 0; + if (disp->trycommit (priv_time)) + need_restart = false; + } + + if (need_restart) + restart (RESTART_SERIAL_IRR); + else + { + this->state |= (STATE_SERIAL | STATE_IRREVOCABLE); + set_abi_disp (dispatch_serialirr ()); + } +} + +void ITM_REGPARM +_ITM_changeTransactionMode (_ITM_transactionState state) +{ + assert (state == modeSerialIrrevocable); + gtm_thr()->serialirr_mode (); +} diff --git a/libitm/method-wbetl.cc b/libitm/method-wbetl.cc new file mode 100644 index 00000000000..093d1c769f1 --- /dev/null +++ b/libitm/method-wbetl.cc @@ -0,0 +1,628 @@ +/* Copyright (C) 2009, 2011 Free Software Foundation, Inc. + Contributed by Richard Henderson <rth@redhat.com>. + + This file is part of the GNU Transactional Memory Library (libitm). + + Libitm is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + Libitm is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + <http://www.gnu.org/licenses/>. */ + +#include "libitm_i.h" + +namespace { + +using namespace GTM; + +class wbetl_dispatch : public abi_dispatch +{ + private: + static const size_t RW_SET_SIZE = 4096; + + struct r_entry + { + gtm_version version; + gtm_stmlock *lock; + }; + + r_entry *m_rset_entries; + size_t m_rset_nb_entries; + size_t m_rset_size; + + struct w_entry + { + /* There's a hashtable where the locks are held, so multiple + cachelines can hash to a given bucket. This link points to the + possible next cacheline that also hashes to this bucket. */ + struct w_entry *next; + + /* Every entry in this bucket (accessed by NEXT) has the same LOCK + address below. */ + gtm_stmlock *lock; + + gtm_cacheline *addr; + gtm_cacheline *value; + gtm_version version; + }; + + w_entry *m_wset_entries; + size_t m_wset_nb_entries; + size_t m_wset_size; + bool m_wset_reallocate; + + gtm_version m_start; + gtm_version m_end; + + gtm_cacheline_page *m_cache_page; + unsigned m_n_cache_page; + + private: + bool local_w_entry_p (w_entry *w); + bool has_read (gtm_stmlock *lock); + bool validate(); + bool extend(); + + gtm_cacheline *do_write_lock(gtm_cacheline *); + gtm_cacheline *do_after_write_lock(gtm_cacheline *); + const gtm_cacheline *do_read_lock(const gtm_cacheline *, bool); + + public: + wbetl_dispatch(); + + virtual const gtm_cacheline *read_lock(const gtm_cacheline *, ls_modifier); + virtual mask_pair write_lock(gtm_cacheline *, ls_modifier); + + virtual bool trycommit(); + virtual void rollback(); + virtual void reinit(); + virtual void fini(); + virtual bool trydropreference (void *, size_t); +}; + +/* Check if W is one of our write locks. */ + +inline bool +wbetl_dispatch::local_w_entry_p (w_entry *w) +{ + return (m_wset_entries <= w && w < m_wset_entries + m_wset_nb_entries); +} + +/* Check if stripe has been read previously. */ + +inline bool +wbetl_dispatch::has_read (gtm_stmlock *lock) +{ + // ??? Consider using an AA tree to lookup the r_set entries. + size_t n = m_rset_nb_entries; + for (size_t i = 0; i < n; ++i) + if (m_rset_entries[i].lock == lock) + return true; + + return false; +} + +/* Validate read set, i.e. check if all read addresses are still valid now. */ + +bool +wbetl_dispatch::validate () +{ + __sync_synchronize (); + + size_t n = m_rset_nb_entries; + for (size_t i = 0; i < n; ++i) + { + r_entry *r = &m_rset_entries[i]; + gtm_stmlock l = *r->lock; + + if (gtm_stmlock_owned_p (l)) + { + w_entry *w = (w_entry *) gtm_stmlock_get_addr (l); + + // If someone has locked us, it better be by someone in the + // current thread. + if (!local_w_entry_p (w)) + return false; + } + else if (gtm_stmlock_get_version (l) != r->version) + return false; + } + + return true; +} + +/* Extend the snapshot range. */ + +bool +wbetl_dispatch::extend () +{ + gtm_version now = gtm_get_clock (); + + if (validate ()) + { + m_end = now; + return true; + } + return false; +} + +/* Acquire a write lock on ADDR. */ + +gtm_cacheline * +wbetl_dispatch::do_write_lock(gtm_cacheline *addr) +{ + gtm_stmlock *lock; + gtm_stmlock l, l2; + gtm_version version; + w_entry *w, *prev = NULL; + + lock = gtm_get_stmlock (addr); + l = *lock; + + restart_no_load: + if (gtm_stmlock_owned_p (l)) + { + w = (w_entry *) gtm_stmlock_get_addr (l); + + /* Did we previously write the same address? */ + if (local_w_entry_p (w)) + { + prev = w; + while (1) + { + if (addr == prev->addr) + return prev->value; + if (prev->next == NULL) + break; + prev = prev->next; + } + + /* Get version from previous entry write set. */ + version = prev->version; + + /* If there's not enough entries, we must reallocate the array, + which invalidates all pointers to write set entries, which + means we have to restart the transaction. */ + if (m_wset_nb_entries == m_wset_size) + { + m_wset_size *= 2; + m_wset_reallocate = true; + gtm_tx()->restart (RESTART_REALLOCATE); + } + + w = &m_wset_entries[m_wset_nb_entries]; + goto do_write; + } + + gtm_tx()->restart (RESTART_LOCKED_WRITE); + } + else + { + version = gtm_stmlock_get_version (l); + + /* We might have read an older version previously. */ + if (version > m_end) + { + if (has_read (lock)) + gtm_tx()->restart (RESTART_VALIDATE_WRITE); + } + + /* Extend write set, aborting to reallocate write set entries. */ + if (m_wset_nb_entries == m_wset_size) + { + m_wset_size *= 2; + m_wset_reallocate = true; + gtm_tx()->restart (RESTART_REALLOCATE); + } + + /* Acquire the lock. */ + w = &m_wset_entries[m_wset_nb_entries]; + l2 = gtm_stmlock_set_owned (w); + l = __sync_val_compare_and_swap (lock, l, l2); + if (l != l2) + goto restart_no_load; + } + + do_write: + m_wset_nb_entries++; + if (prev != NULL) + prev->next = w; + w->next = 0; + w->lock = lock; + w->addr = addr; + w->version = version; + + gtm_cacheline_page *page = m_cache_page; + unsigned index = m_n_cache_page; + + if (page == NULL || index == gtm_cacheline_page::LINES) + { + gtm_cacheline_page *npage = new gtm_cacheline_page; + npage->prev = page; + m_cache_page = page = npage; + m_n_cache_page = 1; + index = 0; + } + else + m_n_cache_page = index + 1; + + gtm_cacheline *line = &page->lines[index]; + w->value = line; + page->masks[index] = 0; + *line = *addr; + + return line; +} + +gtm_cacheline * +wbetl_dispatch::do_after_write_lock (gtm_cacheline *addr) +{ + gtm_stmlock *lock; + gtm_stmlock l; + w_entry *w; + + lock = gtm_get_stmlock (addr); + l = *lock; + assert (gtm_stmlock_owned_p (l)); + + w = (w_entry *) gtm_stmlock_get_addr (l); + assert (local_w_entry_p (w)); + + while (1) + { + if (addr == w->addr) + return w->value; + w = w->next; + } +} + +/* Acquire a read lock on ADDR. */ + +const gtm_cacheline * +wbetl_dispatch::do_read_lock (const gtm_cacheline *addr, bool after_read) +{ + gtm_stmlock *lock; + gtm_stmlock l, l2; + gtm_version version; + w_entry *w; + + lock = gtm_get_stmlock (addr); + l = *lock; + + restart_no_load: + if (gtm_stmlock_owned_p (l)) + { + w = (w_entry *) gtm_stmlock_get_addr (l); + + /* Did we previously write the same address? */ + if (local_w_entry_p (w)) + { + while (1) + { + if (addr == w->addr) + return w->value; + if (w->next == NULL) + return addr; + w = w->next; + } + } + + gtm_tx()->restart (RESTART_LOCKED_READ); + } + + version = gtm_stmlock_get_version (l); + + /* If version is no longer valid, re-validate the read set. */ + if (version > m_end) + { + if (!extend ()) + gtm_tx()->restart (RESTART_VALIDATE_READ); + + if (!after_read) + { + // Verify that the version has not yet been overwritten. The read + // value has not yet been added to read set and may not have been + // checked during the extend. + // + // ??? This only makes sense if we're actually reading the value + // and returning it now -- which I believe the original TinySTM + // did. This doesn't make a whole lot of sense when we're + // manipulating cachelines as we are now. Do we need some other + // form of lock verification here, or is the validate call in + // trycommit sufficient? + + __sync_synchronize (); + l2 = *lock; + if (l != l2) + { + l = l2; + goto restart_no_load; + } + } + } + + if (!after_read) + { + r_entry *r; + + /* Add the address and version to the read set. */ + if (m_rset_nb_entries == m_rset_size) + { + m_rset_size *= 2; + + m_rset_entries = (r_entry *) + xrealloc (m_rset_entries, m_rset_size * sizeof(r_entry)); + } + r = &m_rset_entries[m_rset_nb_entries++]; + r->version = version; + r->lock = lock; + } + + return addr; +} + +const gtm_cacheline * +wbetl_dispatch::read_lock (const gtm_cacheline *addr, ls_modifier ltype) +{ + switch (ltype) + { + case NONTXNAL: + return addr; + case R: + return do_read_lock (addr, false); + case RaR: + return do_read_lock (addr, true); + case RaW: + return do_after_write_lock (const_cast<gtm_cacheline *>(addr)); + case RfW: + return do_write_lock (const_cast<gtm_cacheline *>(addr)); + default: + abort (); + } +} + +abi_dispatch::mask_pair +wbetl_dispatch::write_lock (gtm_cacheline *addr, ls_modifier ltype) +{ + gtm_cacheline *line; + + switch (ltype) + { + case NONTXNAL: + return mask_pair (addr, &mask_sink); + case W: + case WaR: + line = do_write_lock (addr); + break; + case WaW: + line = do_after_write_lock (addr); + break; + default: + abort (); + } + + return mask_pair (line, gtm_cacheline_page::mask_for_page_line (line)); +} + +/* Commit the transaction. */ + +bool +wbetl_dispatch::trycommit () +{ + const size_t n = m_wset_nb_entries; + if (n != 0) + { + /* Get commit timestamp. */ + gtm_version t = gtm_inc_clock (); + + /* Validate only if a concurrent transaction has started since. */ + if (m_start != t - 1 && !validate ()) + return false; + + /* Install new versions. */ + for (size_t i = 0; i < n; ++i) + { + w_entry *w = &m_wset_entries[i]; + gtm_cacheline_mask mask + = *gtm_cacheline_page::mask_for_page_line (w->value); + + /* Filter out any updates that overlap the libitm stack. */ + mask = gtm_mask_stack (w->addr, mask); + + gtm_cacheline::copy_mask (w->addr, w->value, mask); + } + + /* Only emit barrier after all cachelines are copied. */ + gtm_cacheline::copy_mask_wb (); + + /* Drop locks. */ + for (size_t i = 0; i < n; ++i) + { + w_entry *w = &m_wset_entries[i]; + + /* Every link along the chain has the same lock, but only + bother dropping the lock once per bucket (at the end). */ + if (w->next == NULL) + *w->lock = gtm_stmlock_set_version (t); + } + } + + __sync_synchronize (); + return true; +} + +void +wbetl_dispatch::rollback () +{ + /* Drop locks. */ + const size_t n = m_wset_nb_entries; + for (size_t i = 0; i < n; ++i) + { + w_entry *w = &m_wset_entries[i]; + + /* Every link along the chain has the same lock, but only + bother dropping the lock once per bucket (at the end). */ + if (w->next == NULL) + *w->lock = gtm_stmlock_set_version (w->version); + } + + __sync_synchronize (); +} + +void +wbetl_dispatch::reinit () +{ + gtm_cacheline_page *page; + + m_rset_nb_entries = 0; + m_wset_nb_entries = 0; + + if (m_wset_reallocate) + { + m_wset_reallocate = 0; + m_wset_entries = (w_entry *) + xrealloc (m_wset_entries, m_wset_size * sizeof(w_entry)); + } + + page = m_cache_page; + if (page) + { + /* Release all but one of the pages of cachelines. */ + gtm_cacheline_page *prev = page->prev; + if (prev) + { + page->prev = 0; + delete prev; + } + + /* Start the next cacheline allocation from the beginning. */ + m_n_cache_page = 0; + } + + m_start = m_end = gtm_get_clock (); +} + +void +wbetl_dispatch::fini () +{ + delete m_cache_page; + free (m_rset_entries); + free (m_wset_entries); + delete this; +} + +/* Attempt to drop any internal references to PTR. Return TRUE if successful. + + This is an adaptation of the transactional memcpy function. + + What we do here is flush out the current transactional content of + PTR to real memory, and remove the write mask bits associated with + it so future commits will ignore this piece of memory. */ + +bool +wbetl_dispatch::trydropreference (void *ptr, size_t size) +{ + if (size == 0) + return true; + + if (!validate ()) + return false; + + uintptr_t isrc = (uintptr_t)ptr; + // The position in the source cacheline where *PTR starts. + uintptr_t sofs = isrc & (CACHELINE_SIZE - 1); + gtm_cacheline *src + = reinterpret_cast<gtm_cacheline *>(isrc & -CACHELINE_SIZE); + unsigned char *dst = (unsigned char *)ptr; + abi_dispatch::mask_pair pair; + + // If we're trying to drop a reference, we should already have a + // write lock on it. If we don't have one, there's no work to do. + if (!gtm_stmlock_owned_p (*gtm_get_stmlock (src))) + return true; + + // We copy the data in three stages: + + // (a) Copy stray bytes at the beginning that are smaller than a + // cacheline. + if (sofs != 0) + { + size_t sleft = CACHELINE_SIZE - sofs; + size_t min = (size <= sleft ? size : sleft); + + // WaW will give us the current locked entry. + pair = this->write_lock (src, WaW); + + // *jedi mind wave*...these aren't the droids you're looking for. + *pair.mask &= ~((((gtm_cacheline_mask)1 << min) - 1) << sofs); + + memcpy (dst, &pair.line->b[sofs], min); + dst += min; + src++; + size -= min; + } + + // (b) Copy subsequent cacheline sized chunks. + while (size >= CACHELINE_SIZE) + { + pair = this->write_lock(src, WaW); + *pair.mask = 0; + memcpy (dst, pair.line, CACHELINE_SIZE); + dst += CACHELINE_SIZE; + src++; + size -= CACHELINE_SIZE; + } + + // (c) Copy anything left over. + if (size != 0) + { + pair = this->write_lock(src, WaW); + *pair.mask &= ~(((gtm_cacheline_mask)1 << size) - 1); + memcpy (dst, pair.line, size); + } + + // No need to drop locks, since we're going to abort the transaction + // anyhow. + + return true; +} + + +wbetl_dispatch::wbetl_dispatch () + : abi_dispatch (false, false) +{ + m_rset_entries = (r_entry *) xmalloc (RW_SET_SIZE * sizeof(r_entry)); + m_rset_nb_entries = 0; + m_rset_size = RW_SET_SIZE; + + m_wset_entries = (w_entry *) xmalloc (RW_SET_SIZE * sizeof(w_entry)); + m_wset_nb_entries = 0; + m_wset_size = RW_SET_SIZE; + m_wset_reallocate = false; + + m_start = m_end = gtm_get_clock (); + + m_cache_page = 0; + m_n_cache_page = 0; +} + +} // anon namespace + +abi_dispatch * +GTM::dispatch_wbetl () +{ + return new wbetl_dispatch (); +} diff --git a/libitm/query.cc b/libitm/query.cc new file mode 100644 index 00000000000..ce72f702046 --- /dev/null +++ b/libitm/query.cc @@ -0,0 +1,70 @@ +/* Copyright (C) 2008, 2009, 2011 Free Software Foundation, Inc. + Contributed by Richard Henderson <rth@redhat.com>. + + This file is part of the GNU Transactional Memory Library (libitm). + + Libitm is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + Libitm is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + <http://www.gnu.org/licenses/>. */ + +#include "libitm_i.h" + +using namespace GTM; + +int ITM_REGPARM +_ITM_versionCompatible (int version) +{ + return version == _ITM_VERSION_NO; +} + + +const char * ITM_REGPARM +_ITM_libraryVersion (void) +{ + return "GNU libitm " _ITM_VERSION; +} + + +_ITM_howExecuting ITM_REGPARM +_ITM_inTransaction (void) +{ + struct gtm_thread *tx = gtm_thr(); + if (tx && (tx->nesting > 0)) + { + if (tx->state & gtm_thread::STATE_IRREVOCABLE) + return inIrrevocableTransaction; + else + return inRetryableTransaction; + } + return outsideTransaction; +} + + +_ITM_transactionId_t ITM_REGPARM +_ITM_getTransactionId (void) +{ + struct gtm_thread *tx = gtm_thr(); + return (tx && (tx->nesting > 0)) ? tx->id : _ITM_noTransactionId; +} + + +void ITM_REGPARM ITM_NORETURN +_ITM_error (const _ITM_srcLocation * loc UNUSED, int errorCode UNUSED) +{ + abort (); +} diff --git a/libitm/retry.cc b/libitm/retry.cc new file mode 100644 index 00000000000..decd7731b46 --- /dev/null +++ b/libitm/retry.cc @@ -0,0 +1,265 @@ +/* Copyright (C) 2008, 2009, 2011 Free Software Foundation, Inc. + Contributed by Richard Henderson <rth@redhat.com>. + + This file is part of the GNU Transactional Memory Library (libitm). + + Libitm is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + Libitm is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + <http://www.gnu.org/licenses/>. */ + +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include "libitm_i.h" + +// The default TM method used when starting a new transaction. +static GTM::abi_dispatch* default_dispatch = 0; +// The default TM method as requested by the user, if any. +static GTM::abi_dispatch* default_dispatch_user = 0; + +void +GTM::gtm_thread::decide_retry_strategy (gtm_restart_reason r) +{ + struct abi_dispatch *disp = abi_disp (); + + this->restart_reason[r]++; + this->restart_total++; + + if (r == RESTART_INIT_METHOD_GROUP) + { + // A re-initializations of the method group has been requested. Switch + // to serial mode, initialize, and resume normal operation. + if ((state & STATE_SERIAL) == 0) + { + // We have to eventually re-init the method group. Therefore, + // we cannot just upgrade to a write lock here because this could + // fail forever when other transactions execute in serial mode. + // However, giving up the read lock then means that a change of the + // method group could happen in-between, so check that we're not + // re-initializing without a need. + // ??? Note that we can still re-initialize too often, but avoiding + // that would increase code complexity, which seems unnecessary + // given that re-inits should be very infrequent. + serial_lock.read_unlock(this); + serial_lock.write_lock(); + if (disp->get_method_group() == default_dispatch->get_method_group()) + { + // Still the same method group. + disp->get_method_group()->fini(); + disp->get_method_group()->init(); + } + serial_lock.write_unlock(); + serial_lock.read_lock(this); + if (disp->get_method_group() != default_dispatch->get_method_group()) + { + disp = default_dispatch; + set_abi_disp(disp); + } + } + else + { + // We are a serial transaction already, which makes things simple. + disp->get_method_group()->fini(); + disp->get_method_group()->init(); + } + } + + bool retry_irr = (r == RESTART_SERIAL_IRR); + bool retry_serial = (retry_irr || this->restart_total > 100); + + // We assume closed nesting to be infrequently required, so just use + // dispatch_serial (with undo logging) if required. + if (r == RESTART_CLOSED_NESTING) + retry_serial = true; + + if (retry_serial) + { + // In serialirr_mode we can succeed with the upgrade to + // write-lock but fail the trycommit. In any case, if the + // write lock is not yet held, grab it. Don't do this with + // an upgrade, since we've no need to preserve the state we + // acquired with the read. + // Note that we will be restarting with either dispatch_serial or + // dispatch_serialirr, which are compatible with all TM methods; if + // we would retry with a different method, we would have to first check + // whether the default dispatch or the method group have changed. Also, + // the caller must have rolled back the previous transaction, so we + // don't have to worry about things such as privatization. + if ((this->state & STATE_SERIAL) == 0) + { + this->state |= STATE_SERIAL; + serial_lock.read_unlock (this); + serial_lock.write_lock (); + } + + // We can retry with dispatch_serialirr if the transaction + // doesn't contain an abort and if we don't need closed nesting. + if ((this->prop & pr_hasNoAbort) && (r != RESTART_CLOSED_NESTING)) + retry_irr = true; + } + + // Note that we can just use serial mode here without having to switch + // TM method sets because serial mode is compatible with all of them. + if (retry_irr) + { + this->state = (STATE_SERIAL | STATE_IRREVOCABLE); + disp = dispatch_serialirr (); + set_abi_disp (disp); + } + else if (retry_serial) + { + disp = dispatch_serial(); + set_abi_disp (disp); + } +} + + +// Decides which TM method should be used on the first attempt to run this +// transaction. +GTM::abi_dispatch* +GTM::gtm_thread::decide_begin_dispatch (uint32_t prop) +{ + // TODO Pay more attention to prop flags (eg, *omitted) when selecting + // dispatch. + if ((prop & pr_doesGoIrrevocable) || !(prop & pr_instrumentedCode)) + return dispatch_serialirr(); + + // If we might need closed nesting and the default dispatch has an + // alternative that supports closed nesting, use it. + // ??? We could choose another TM method that we know supports closed + // nesting but isn't the default (e.g., dispatch_serial()). However, we + // assume that aborts that need closed nesting are infrequent, so don't + // choose a non-default method until we have to actually restart the + // transaction. + if (!(prop & pr_hasNoAbort) && !default_dispatch->closed_nesting() + && default_dispatch->closed_nesting_alternative()) + return default_dispatch->closed_nesting_alternative(); + + // No special case, just use the default dispatch. + return default_dispatch; +} + + +void +GTM::gtm_thread::set_default_dispatch(GTM::abi_dispatch* disp) +{ + if (default_dispatch == disp) + return; + if (default_dispatch) + { + // If we are switching method groups, initialize and shut down properly. + if (default_dispatch->get_method_group() != disp->get_method_group()) + { + default_dispatch->get_method_group()->fini(); + disp->get_method_group()->init(); + } + } + else + disp->get_method_group()->init(); + default_dispatch = disp; +} + + +static GTM::abi_dispatch* +parse_default_method() +{ + const char *env = getenv("ITM_DEFAULT_METHOD"); + GTM::abi_dispatch* disp = 0; + if (env == NULL) + return 0; + + while (isspace((unsigned char) *env)) + ++env; + if (strncmp(env, "serialirr_onwrite", 17) == 0) + { + disp = GTM::dispatch_serialirr_onwrite(); + env += 17; + } + else if (strncmp(env, "serialirr", 9) == 0) + { + disp = GTM::dispatch_serialirr(); + env += 9; + } + else if (strncmp(env, "serial", 6) == 0) + { + disp = GTM::dispatch_serial(); + env += 6; + } + else if (strncmp(env, "gl_wt", 5) == 0) + { + disp = GTM::dispatch_gl_wt(); + env += 5; + } + else + goto unknown; + + while (isspace((unsigned char) *env)) + ++env; + if (*env == '\0') + return disp; + + unknown: + GTM::GTM_error("Unknown TM method in environment variable " + "ITM_DEFAULT_METHOD\n"); + return 0; +} + +// Gets notifications when the number of registered threads changes. This is +// used to initialize the method set choice and trigger straightforward choice +// adaption. +// This must be called only by serial threads. +void +GTM::gtm_thread::number_of_threads_changed(unsigned previous, unsigned now) +{ + if (previous == 0) + { + // No registered threads before, so initialize. + static bool initialized = false; + if (!initialized) + { + initialized = true; + // Check for user preferences here. + default_dispatch_user = parse_default_method(); + } + } + else if (now == 0) + { + // No registered threads anymore. The dispatch based on serial mode do + // not have any global state, so this effectively shuts down properly. + set_default_dispatch(dispatch_serialirr()); + } + + if (now == 1) + { + // Only one thread, so use a serializing method. + // ??? If we don't have a fast serial mode implementation, it might be + // better to use the global lock method set here. + if (default_dispatch_user) + set_default_dispatch(default_dispatch_user); + else + set_default_dispatch(dispatch_serialirr()); + } + else if (now > 1 && previous <= 1) + { + // More than one thread, use the default method. + if (default_dispatch_user) + set_default_dispatch(default_dispatch_user); + else + set_default_dispatch(dispatch_serialirr_onwrite()); + } +} diff --git a/libitm/stmlock.h b/libitm/stmlock.h new file mode 100644 index 00000000000..f115a417da2 --- /dev/null +++ b/libitm/stmlock.h @@ -0,0 +1,123 @@ +/* Copyright (C) 2009, 2011 Free Software Foundation, Inc. + Contributed by Richard Henderson <rth@redhat.com>. + + This file is part of the GNU Transactional Memory Library (libitm). + + Libitm is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + Libitm is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + <http://www.gnu.org/licenses/>. */ + +#ifndef LIBITM_STMLOCK_H +#define LIBITM_STMLOCK_H 1 + +namespace GTM HIDDEN { + +/* A versioned write lock on a cacheline. This must be wide enough to + store a pointer, and preferably wide enough to avoid overflowing the + version counter. Thus we use a "word", which should be 64-bits on + 64-bit systems even when their pointer size is forced smaller. */ +typedef gtm_word gtm_stmlock; + +/* This has to be the same size as gtm_stmlock, we just use this name + for documentation purposes. */ +typedef gtm_word gtm_version; + +/* The maximum value a version number can have. This is a consequence + of having the low bit of gtm_stmlock reserved for the owned bit. */ +#define GTM_VERSION_MAX (~(gtm_version)0 >> 1) + +/* A value that may be used to indicate "uninitialized" for a version. */ +#define GTM_VERSION_INVALID (~(gtm_version)0) + +/* This bit is set when the write lock is held. When set, the balance of + the bits in the lock is a pointer that references STM backend specific + data; it is up to the STM backend to determine if this thread holds the + lock. If this bit is clear, the balance of the bits are the last + version number committed to the cacheline. */ +static inline bool +gtm_stmlock_owned_p (gtm_stmlock lock) +{ + return lock & 1; +} + +static inline gtm_stmlock +gtm_stmlock_set_owned (void *data) +{ + return (gtm_stmlock)(uintptr_t)data | 1; +} + +static inline void * +gtm_stmlock_get_addr (gtm_stmlock lock) +{ + return (void *)((uintptr_t)lock & ~(uintptr_t)1); +} + +static inline gtm_version +gtm_stmlock_get_version (gtm_stmlock lock) +{ + return lock >> 1; +} + +static inline gtm_stmlock +gtm_stmlock_set_version (gtm_version ver) +{ + return ver << 1; +} + +/* We use a fixed set of locks for all memory, hashed into the + following table. */ +#define LOCK_ARRAY_SIZE (1024 * 1024) +extern gtm_stmlock gtm_stmlock_array[LOCK_ARRAY_SIZE]; + +static inline gtm_stmlock * +gtm_get_stmlock (const gtm_cacheline *addr) +{ + size_t idx = ((uintptr_t) addr / CACHELINE_SIZE) % LOCK_ARRAY_SIZE; + return gtm_stmlock_array + idx; +} + +/* The current global version number. */ +extern gtm_version gtm_clock; + +static inline gtm_version +gtm_get_clock (void) +{ + gtm_version r; + + __sync_synchronize (); + r = gtm_clock; + atomic_read_barrier (); + + return r; +} + +static inline gtm_version +gtm_inc_clock (void) +{ + gtm_version r = __sync_add_and_fetch (>m_clock, 1); + + /* ??? Ought to handle wraparound for 32-bit. */ + if (sizeof(r) < 8 && r > GTM_VERSION_MAX) + abort (); + + return r; +} + +} // namespace GTM + +#endif // LIBITM_STMLOCK_H diff --git a/libitm/testsuite/Makefile.am b/libitm/testsuite/Makefile.am new file mode 100644 index 00000000000..561b7e25448 --- /dev/null +++ b/libitm/testsuite/Makefile.am @@ -0,0 +1,13 @@ +## Process this file with automake to produce Makefile.in. + +AUTOMAKE_OPTIONS = foreign dejagnu + +# May be used by various substitution variables. +gcc_version := $(shell cat $(top_srcdir)/../gcc/BASE-VER) + +EXPECT = $(shell if test -f $(top_builddir)/../expect/expect; then \ + echo $(top_builddir)/../expect/expect; else echo expect; fi) + +_RUNTEST = $(shell if test -f $(top_srcdir)/../dejagnu/runtest; then \ + echo $(top_srcdir)/../dejagnu/runtest; else echo runtest; fi) +RUNTEST = "$(_RUNTEST) $(AM_RUNTESTFLAGS)" diff --git a/libitm/testsuite/Makefile.in b/libitm/testsuite/Makefile.in new file mode 100644 index 00000000000..ed1f314e0d6 --- /dev/null +++ b/libitm/testsuite/Makefile.in @@ -0,0 +1,441 @@ +# Makefile.in generated by automake 1.11.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, +# Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +subdir = testsuite +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/../config/acx.m4 \ + $(top_srcdir)/../config/depstand.m4 \ + $(top_srcdir)/../config/enable.m4 \ + $(top_srcdir)/../config/futex.m4 \ + $(top_srcdir)/../config/lead-dot.m4 \ + $(top_srcdir)/../config/mmap.m4 \ + $(top_srcdir)/../config/multi.m4 \ + $(top_srcdir)/../config/override.m4 \ + $(top_srcdir)/../config/stdint.m4 \ + $(top_srcdir)/../config/tls.m4 $(top_srcdir)/../ltoptions.m4 \ + $(top_srcdir)/../ltsugar.m4 $(top_srcdir)/../ltversion.m4 \ + $(top_srcdir)/../lt~obsolete.m4 $(top_srcdir)/acinclude.m4 \ + $(top_srcdir)/../libtool.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(SHELL) $(top_srcdir)/../mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.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@ +AMTAR = @AMTAR@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCAS = @CCAS@ +CCASDEPMODE = @CCASDEPMODE@ +CCASFLAGS = @CCASFLAGS@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FC = @FC@ +FCFLAGS = @FCFLAGS@ +FGREP = @FGREP@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OPT_LDFLAGS = @OPT_LDFLAGS@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +RANLIB = @RANLIB@ +SECTION_LDFLAGS = @SECTION_LDFLAGS@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +XCFLAGS = @XCFLAGS@ +XLDFLAGS = @XLDFLAGS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +ac_ct_FC = @ac_ct_FC@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +config_path = @config_path@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +enable_shared = @enable_shared@ +enable_static = @enable_static@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +libtool_VERSION = @libtool_VERSION@ +link_itm = @link_itm@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +multi_basedir = @multi_basedir@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +toolexecdir = @toolexecdir@ +toolexeclibdir = @toolexeclibdir@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +AUTOMAKE_OPTIONS = foreign dejagnu + +# May be used by various substitution variables. +gcc_version := $(shell cat $(top_srcdir)/../gcc/BASE-VER) +EXPECT = $(shell if test -f $(top_builddir)/../expect/expect; then \ + echo $(top_builddir)/../expect/expect; else echo expect; fi) + +_RUNTEST = $(shell if test -f $(top_srcdir)/../dejagnu/runtest; then \ + echo $(top_srcdir)/../dejagnu/runtest; else echo runtest; fi) + +RUNTEST = "$(_RUNTEST) $(AM_RUNTESTFLAGS)" +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign testsuite/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign testsuite/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +tags: TAGS +TAGS: + +ctags: CTAGS +CTAGS: + + +check-DEJAGNU: site.exp + srcdir=`$(am__cd) $(srcdir) && pwd`; export srcdir; \ + EXPECT=$(EXPECT); export EXPECT; \ + runtest=$(RUNTEST); \ + if $(SHELL) -c "$$runtest --version" > /dev/null 2>&1; then \ + exit_status=0; l='$(DEJATOOL)'; for tool in $$l; do \ + if $$runtest $(AM_RUNTESTFLAGS) $(RUNTESTDEFAULTFLAGS) $(RUNTESTFLAGS); \ + then :; else exit_status=1; fi; \ + done; \ + else echo "WARNING: could not find \`runtest'" 1>&2; :;\ + fi; \ + exit $$exit_status +site.exp: Makefile + @echo 'Making a new site.exp file...' + @echo '## these variables are automatically generated by make ##' >site.tmp + @echo '# Do not edit here. If you wish to override these values' >>site.tmp + @echo '# edit the last section' >>site.tmp + @echo 'set srcdir $(srcdir)' >>site.tmp + @echo "set objdir `pwd`" >>site.tmp + @echo 'set build_alias "$(build_alias)"' >>site.tmp + @echo 'set build_triplet $(build_triplet)' >>site.tmp + @echo 'set host_alias "$(host_alias)"' >>site.tmp + @echo 'set host_triplet $(host_triplet)' >>site.tmp + @echo 'set target_alias "$(target_alias)"' >>site.tmp + @echo 'set target_triplet $(target_triplet)' >>site.tmp + @echo '## All variables above are generated by configure. Do Not Edit ##' >>site.tmp + @test ! -f site.exp || \ + sed '1,/^## All variables above are.*##/ d' site.exp >> site.tmp + @-rm -f site.bak + @test ! -f site.exp || mv site.exp site.bak + @mv site.tmp site.exp + +distclean-DEJAGNU: + -rm -f site.exp site.bak + -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 +all-am: Makefile +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-DEJAGNU distclean-generic + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: check-am install-am install-strip + +.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 \ + 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 \ + uninstall uninstall-am + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/libitm/testsuite/config/default.exp b/libitm/testsuite/config/default.exp new file mode 100644 index 00000000000..b5e53fc792e --- /dev/null +++ b/libitm/testsuite/config/default.exp @@ -0,0 +1,17 @@ +# Copyright (C) 2011 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +load_lib "standard.exp" diff --git a/libitm/testsuite/lib/libitm-dg.exp b/libitm/testsuite/lib/libitm-dg.exp new file mode 100644 index 00000000000..f684ce899ef --- /dev/null +++ b/libitm/testsuite/lib/libitm-dg.exp @@ -0,0 +1,21 @@ +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +proc libitm-dg-test { prog do_what extra_tool_flags } { + return [gcc-dg-test-1 libitm_target_compile $prog $do_what $extra_tool_flags] +} + +proc libitm-dg-prune { system text } { + return [gcc-dg-prune $system $text] +} diff --git a/libitm/testsuite/lib/libitm.exp b/libitm/testsuite/lib/libitm.exp new file mode 100644 index 00000000000..701120aa557 --- /dev/null +++ b/libitm/testsuite/lib/libitm.exp @@ -0,0 +1,229 @@ +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +# Damn dejagnu for not having proper library search paths for load_lib. +# We have to explicitly load everything that gcc-dg.exp wants to load. + +proc load_gcc_lib { filename } { + global srcdir loaded_libs + + load_file $srcdir/../../gcc/testsuite/lib/$filename + set loaded_libs($filename) "" +} + +load_lib dg.exp +load_gcc_lib file-format.exp +load_gcc_lib target-supports.exp +load_gcc_lib target-supports-dg.exp +load_gcc_lib scanasm.exp +load_gcc_lib scandump.exp +load_gcc_lib scanrtl.exp +load_gcc_lib scantree.exp +load_gcc_lib scanipa.exp +load_gcc_lib prune.exp +load_gcc_lib target-libpath.exp +load_gcc_lib wrapper.exp +load_gcc_lib gcc-defs.exp +load_gcc_lib torture-options.exp +load_gcc_lib timeout.exp +load_gcc_lib timeout-dg.exp +load_gcc_lib gcc-dg.exp + +set dg-do-what-default run + +# +# GCC_UNDER_TEST is the compiler under test. +# + +set libitm_compile_options "" + +# +# libitm_init +# + +if [info exists TOOL_OPTIONS] { + set multilibs [get_multilibs $TOOL_OPTIONS] +} else { + set multilibs [get_multilibs] +} + +proc libitm_init { args } { + global srcdir blddir objdir tool_root_dir + global libitm_initialized + global tmpdir + global blddir + global gluefile wrap_flags + global ALWAYS_CFLAGS + global CFLAGS + global TOOL_EXECUTABLE TOOL_OPTIONS + global GCC_UNDER_TEST + global TESTING_IN_BUILD_TREE + global target_triplet + global always_ld_library_path + + set blddir [lookfor_file [get_multilibs] libitm] + + # We set LC_ALL and LANG to C so that we get the same error + # messages as expected. + setenv LC_ALL C + setenv LANG C + + if ![info exists GCC_UNDER_TEST] then { + if [info exists TOOL_EXECUTABLE] { + set GCC_UNDER_TEST $TOOL_EXECUTABLE + } else { + set GCC_UNDER_TEST "[find_gcc]" + } + } + + if ![info exists tmpdir] { + set tmpdir "/tmp" + } + + if [info exists gluefile] { + unset gluefile + } + + if {![info exists CFLAGS]} { + set CFLAGS "" + } + + # Locate libgcc.a so we don't need to account for different values of + # SHLIB_EXT on different platforms + set gccdir [lookfor_file $tool_root_dir gcc/libgcc.a] + if {$gccdir != ""} { + set gccdir [file dirname $gccdir] + } + + # Compute what needs to be put into LD_LIBRARY_PATH + set always_ld_library_path ".:${blddir}/.libs" + + # Compute what needs to be added to the existing LD_LIBRARY_PATH. + if {$gccdir != ""} { + # Add AIX pthread directory first. + if { [llength [glob -nocomplain ${gccdir}/pthread/libgcc_s*.a]] >= 1 } { + append always_ld_library_path ":${gccdir}/pthread" + } + append always_ld_library_path ":${gccdir}" + set compiler [lindex $GCC_UNDER_TEST 0] + + if { [is_remote host] == 0 && [which $compiler] != 0 } { + foreach i "[exec $compiler --print-multi-lib]" { + set mldir "" + regexp -- "\[a-z0-9=_/\.-\]*;" $i mldir + set mldir [string trimright $mldir "\;@"] + if { "$mldir" == "." } { + continue + } + if { [llength [glob -nocomplain ${gccdir}/${mldir}/libgcc_s*.so.*]] >= 1 } { + append always_ld_library_path ":${gccdir}/${mldir}" + } + } + } + } + + set ALWAYS_CFLAGS "" + if { $blddir != "" } { + lappend ALWAYS_CFLAGS "additional_flags=-B${blddir}/" + lappend ALWAYS_CFLAGS "additional_flags=-I${blddir}" + lappend ALWAYS_CFLAGS "ldflags=-L${blddir}/.libs" + } + lappend ALWAYS_CFLAGS "additional_flags=-I${srcdir}/.." + lappend ALWAYS_CFLAGS "ldflags=-litm" + + # We use atomic operations in the testcases to validate results. + if { ([istarget i?86-*-*] || [istarget x86_64-*-*]) + && [check_effective_target_ilp32] } { + lappend ALWAYS_CFLAGS "additional_flags=-march=i486" + } + + if [istarget *-*-darwin*] { + lappend ALWAYS_CFLAGS "additional_flags=-shared-libgcc" + } + + if [istarget sparc*-*-*] { + lappend ALWAYS_CFLAGS "additional_flags=-mcpu=v9" + } + + if [info exists TOOL_OPTIONS] { + lappend ALWAYS_CFLAGS "additional_flags=$TOOL_OPTIONS" + } + + # Make sure that lines are not wrapped. That can confuse the + # error-message parsing machinery. + lappend ALWAYS_CFLAGS "additional_flags=-fmessage-length=0" + + # Turn on transactional memory support. + lappend ALWAYS_CFLAGS "additional_flags=-fgnu-tm" +} + +# +# libitm_target_compile -- compile a source file +# + +proc libitm_target_compile { source dest type options } { + global blddir + global libitm_compile_options + global gluefile wrap_flags + global ALWAYS_CFLAGS + global GCC_UNDER_TEST + global lang_test_file + global lang_library_path + global lang_link_flags + + if { [info exists lang_test_file] } { + if { $blddir != "" } { + lappend options "ldflags=-L${blddir}/${lang_library_path}" + } + lappend options "ldflags=${lang_link_flags}" + } + + if { [target_info needs_status_wrapper] != "" && [info exists gluefile] } { + lappend options "libs=${gluefile}" + lappend options "ldflags=${wrap_flags}" + } + + lappend options "additional_flags=[libio_include_flags]" + lappend options "timeout=[timeout_value]" + lappend options "compiler=$GCC_UNDER_TEST" + + set options [concat $libitm_compile_options $options] + + if [info exists ALWAYS_CFLAGS] { + set options [concat "$ALWAYS_CFLAGS" $options] + } + + set options [dg-additional-files-options $options $source] + + set result [target_compile $source $dest $type $options] + + return $result +} + +proc libitm_option_help { } { + send_user " --additional_options,OPTIONS\t\tUse OPTIONS to compile the testcase files. OPTIONS should be comma-separated.\n" +} + +proc libitm_option_proc { option } { + if [regexp "^--additional_options," $option] { + global libitm_compile_options + regsub "--additional_options," $option "" option + foreach x [split $option ","] { + lappend libitm_compile_options "additional_flags=$x" + } + return 1 + } else { + return 0 + } +} diff --git a/libitm/testsuite/libitm.c++/c++.exp b/libitm/testsuite/libitm.c++/c++.exp new file mode 100644 index 00000000000..d30e9455c16 --- /dev/null +++ b/libitm/testsuite/libitm.c++/c++.exp @@ -0,0 +1,74 @@ +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +load_lib libitm-dg.exp + +global shlib_ext + +set shlib_ext [get_shlib_extension] +set lang_link_flags "-lstdc++" +set lang_test_file_found 0 +set lang_library_path "../libstdc++-v3/src/.libs" + +# Initialize dg. +dg-init + +set blddir [lookfor_file [get_multilibs] libgomp] + + +if { $blddir != "" } { + # Look for a static libstdc++ first. + if [file exists "${blddir}/${lang_library_path}/libstdc++.a"] { + set lang_test_file "${lang_library_path}/libstdc++.a" + set lang_test_file_found 1 + # We may have a shared only build, so look for a shared libstdc++. + } elseif [file exists "${blddir}/${lang_library_path}/libstdc++.${shlib_ext}"] { + set lang_test_file "${lang_library_path}/libstdc++.${shlib_ext}" + set lang_test_file_found 1 + } else { + puts "No libstdc++ library found, will not execute c++ tests" + } +} elseif { [info exists GXX_UNDER_TEST] } { + set lang_test_file_found 1 + # Needs to exist for libgomp.exp. + set lang_test_file "" +} else { + puts "GXX_UNDER_TEST not defined, will not execute c++ tests" +} + +if { $lang_test_file_found } { + # Gather a list of all tests. + set tests [lsort [glob -nocomplain $srcdir/$subdir/*.C]] + + if { $blddir != "" } { + set ld_library_path "$always_ld_library_path:${blddir}/${lang_library_path}" + } else { + set ld_library_path "$always_ld_library_path" + } + append ld_library_path [gcc-set-multilib-library-path $GCC_UNDER_TEST] + set_ld_library_path_env_vars + + set flags_file "${blddir}/../libstdc++-v3/scripts/testsuite_flags" + if { [file exists $flags_file] } { + set libstdcxx_includes [exec sh $flags_file --build-includes] + } else { + set libstdcxx_includes "" + } + + # Main loop. + dg-runtest $tests "" $libstdcxx_includes +} + +# All done. +dg-finish diff --git a/libitm/testsuite/libitm.c++/dropref.C b/libitm/testsuite/libitm.c++/dropref.C new file mode 100644 index 00000000000..c9bdfff32cf --- /dev/null +++ b/libitm/testsuite/libitm.c++/dropref.C @@ -0,0 +1,12 @@ +/* { dg-xfail-run-if "unsupported" { *-*-* } } */ +#include <libitm.h> + +char *pp; + +int main() +{ + __transaction_atomic { + _ITM_dropReferences (pp, 555); + } + return 0; +} diff --git a/libitm/testsuite/libitm.c++/eh-1.C b/libitm/testsuite/libitm.c++/eh-1.C new file mode 100644 index 00000000000..49e2213e1ff --- /dev/null +++ b/libitm/testsuite/libitm.c++/eh-1.C @@ -0,0 +1,36 @@ +// { dg-do run } + +extern "C" void abort (); + +int dothrow; +int g; + +static void f1() +{ + g++; + if (dothrow) + throw 1; +} + +static void f2() +{ + __transaction_atomic { + f1(); + } +} + +int main() +{ + dothrow = 0; + f2(); + + dothrow = 1; + try { + f2(); + } catch (...) { + } + + if (g != 2) + abort (); + return 0; +} diff --git a/libitm/testsuite/libitm.c++/static_ctor.C b/libitm/testsuite/libitm.c++/static_ctor.C new file mode 100644 index 00000000000..1ba751687ba --- /dev/null +++ b/libitm/testsuite/libitm.c++/static_ctor.C @@ -0,0 +1,39 @@ +/* { dg-do run } */ +/* { dg-xfail-if "" { *-*-* } { "*" } { "" } } */ +/* Tests static constructors inside of transactional code. */ + +#include <pthread.h> +#include <stdlib.h> + +int f(int x) __attribute__((noinline,transaction_safe)); +int f(int x) +{ + static int y = x; + return y*x; +} + +static void *thread (void *) +{ + int bar; + __transaction_atomic { bar = f(10); } + if (bar != 100) + abort(); + return 0; +} + +int main() +{ + int bar; + + // First, initialize y in another thread. + pthread_t pt; + pthread_create(&pt, NULL, thread, NULL); + pthread_join(pt, NULL); + + // Now y should already be initialized. + __transaction_atomic { bar = f(20); } + if (bar != 200) + abort(); + + return 0; +} diff --git a/libitm/testsuite/libitm.c++/throwdown.C b/libitm/testsuite/libitm.c++/throwdown.C new file mode 100644 index 00000000000..8c65508656a --- /dev/null +++ b/libitm/testsuite/libitm.c++/throwdown.C @@ -0,0 +1,13 @@ +// { dg-do compile } + +#include <libitm.h> + +static void throwit() { + throw 1; +} + +void tranfunc() { + __transaction_atomic { + throwit(); + } +} diff --git a/libitm/testsuite/libitm.c/c.exp b/libitm/testsuite/libitm.c/c.exp new file mode 100644 index 00000000000..f7229a5bcdf --- /dev/null +++ b/libitm/testsuite/libitm.c/c.exp @@ -0,0 +1,44 @@ +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +if [info exists lang_library_path] then { + unset lang_library_path + unset lang_link_flags +} +if [info exists lang_test_file] then { + unset lang_test_file +} + +load_lib libitm-dg.exp + +# If a testcase doesn't have special options, use these. +if ![info exists DEFAULT_CFLAGS] then { + set DEFAULT_CFLAGS "-O2" +} + +# Initialize dg. +dg-init + +# Gather a list of all tests. +set tests [lsort [find $srcdir/$subdir *.c]] + +set ld_library_path $always_ld_library_path +append ld_library_path [gcc-set-multilib-library-path $GCC_UNDER_TEST] +set_ld_library_path_env_vars + +# Main loop. +dg-runtest $tests "" $DEFAULT_CFLAGS + +# All done. +dg-finish diff --git a/libitm/testsuite/libitm.c/cancel.c b/libitm/testsuite/libitm.c/cancel.c new file mode 100644 index 00000000000..28276db07a1 --- /dev/null +++ b/libitm/testsuite/libitm.c/cancel.c @@ -0,0 +1,55 @@ +#include <stdlib.h> +#include <libitm.h> + +unsigned char pp[100]; + +void __attribute((transaction_may_cancel_outer,noinline)) cancel1() +{ + __transaction_cancel [[outer]]; +} + +int a, b; + +int main() +{ + a = b = 0; + + __transaction_atomic { + a = 1; + __transaction_atomic { + b = 1; + __transaction_cancel; + } + } + if (a != 1 || b != 0) + abort(); + if (_ITM_inTransaction() != outsideTransaction) + abort(); + + __transaction_atomic [[outer]] { + a = 2; + __transaction_atomic { + b = 2; + __transaction_cancel [[outer]]; + } + } + if (a != 1 || b != 0) + abort(); + if (_ITM_inTransaction() != outsideTransaction) + abort(); + + __transaction_atomic [[outer]] { + a = 2; + __transaction_atomic { + b = 2; + __transaction_cancel [[outer]]; + cancel1(); + } + } + if (a != 1 || b != 0) + abort(); + if (_ITM_inTransaction() != outsideTransaction) + abort(); + + return 0; +} diff --git a/libitm/testsuite/libitm.c/clone-1.c b/libitm/testsuite/libitm.c/clone-1.c new file mode 100644 index 00000000000..03e62664d80 --- /dev/null +++ b/libitm/testsuite/libitm.c/clone-1.c @@ -0,0 +1,28 @@ +/* Verify that we can look up tm clone of transaction_callable + and transaction_pure. */ + +#include <stdlib.h> +#include <libitm.h> + +static int x; + +int __attribute__((transaction_pure)) pure(int i) +{ + return i+2; +} + +int __attribute__((transaction_callable)) callable(void) +{ + return ++x; +} + +int main() +{ + if (_ITM_getTMCloneSafe (&pure) != &pure) + abort (); + + if (_ITM_getTMCloneSafe (&callable) == NULL) + abort (); + + return 0; +} diff --git a/libitm/testsuite/libitm.c/dropref-2.c b/libitm/testsuite/libitm.c/dropref-2.c new file mode 100644 index 00000000000..5bb2726dbd9 --- /dev/null +++ b/libitm/testsuite/libitm.c/dropref-2.c @@ -0,0 +1,36 @@ +/* { dg-xfail-run-if "unsupported" { *-*-* } } */ +#include <stdlib.h> +#include <libitm.h> + +/* Test that _ITM_dropReferences() forces a commit of given chunk. */ + +unsigned char pp[100]; + +int main() +{ + int i; + + for(i=0; i < 100; ++i) + pp[i]=0x22; + + __transaction_atomic { + for(i=0; i < 100; ++i) + pp[i]=0x33; + + /* This should write-through pp[0..49]... */ + _ITM_dropReferences (pp, 50); + + /* ...while this should revert everything but pp[0..49]. */ + __transaction_cancel; + } + + for(i=0; i < 50; ++i) + if (pp[i] != 0x33) + abort(); + + for(i=50; i < 100; ++i) + if (pp[i] != 0x22) + abort(); + + return 0; +} diff --git a/libitm/testsuite/libitm.c/dropref.c b/libitm/testsuite/libitm.c/dropref.c new file mode 100644 index 00000000000..c9bdfff32cf --- /dev/null +++ b/libitm/testsuite/libitm.c/dropref.c @@ -0,0 +1,12 @@ +/* { dg-xfail-run-if "unsupported" { *-*-* } } */ +#include <libitm.h> + +char *pp; + +int main() +{ + __transaction_atomic { + _ITM_dropReferences (pp, 555); + } + return 0; +} diff --git a/libitm/testsuite/libitm.c/memcpy-1.c b/libitm/testsuite/libitm.c/memcpy-1.c new file mode 100644 index 00000000000..e4b56573b26 --- /dev/null +++ b/libitm/testsuite/libitm.c/memcpy-1.c @@ -0,0 +1,154 @@ +/* This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. */ + +/* Verify memcpy operation. */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/mman.h> +#include <libitm.h> + +#define BEG_TRANSACTION \ + _ITM_beginTransaction (pr_instrumentedCode | pr_hasNoAbort \ + | pr_hasNoIrrevocable) +#define END_TRANSACTION \ + _ITM_commitTransaction () + +#define MEMCPY _ITM_memcpyRtWt + +static unsigned char *buf1, *buf2; +static size_t bufsize, page_size; +static int fail; + +static void +do_test (size_t align1, size_t align2, size_t len) +{ + size_t i, j; + unsigned char *s1, *s2; + unsigned char c1, c2; + + if (align1 + len >= bufsize) + return; + if (align2 + len >= bufsize) + return; + + c1 = random () >> 8; + c2 = random () >> 8; + memset (buf1, c1, bufsize); + memset (buf2, c2, bufsize); + + s1 = buf1 + align1; + s2 = buf2 + align2; + + for (i = 0, j = 1; i < len; i++, j += 23) + s1[i] = (j == c1 ? j + 1 : j); + + BEG_TRANSACTION; + MEMCPY (s2, s1, len); + END_TRANSACTION; + + if (memcmp (s1, s2, len) != 0) + { + printf ("Wrong result: dalign %zd salign %zd len %zd\n", + align2, align1, len); + fail = 1; + return; + } + + for (i = (align2 > 64 ? align2 - 64 : 0); i < align2; ++i) + if (buf2[i] != c2) + { + printf ("Garbage before: ofs %zd\n", i); + fail = 1; + break; + } + for (i = align2 + len, j = i+64 < bufsize ? i+64 : bufsize; i < j; ++i) + if (buf2[i] != c2) + { + printf ("Garbage after: ofs %zd\n", i); + fail = 1; + break; + } +} + +int main() +{ + size_t i, j; + + page_size = getpagesize (); + bufsize = 2 * page_size; + + buf1 = mmap (NULL, bufsize + 2*page_size, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (buf1 == MAP_FAILED) + return 1; + buf2 = mmap (NULL, bufsize + 2*page_size, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (buf2 == MAP_FAILED) + return 1; + + if (mprotect (buf1, page_size, PROT_NONE)) + return 1; + buf1 += page_size; + if (mprotect (buf1 + bufsize, page_size, PROT_NONE)) + return 1; + + if (mprotect (buf2, page_size, PROT_NONE)) + return 1; + buf2 += page_size; + if (mprotect (buf2 + bufsize, page_size, PROT_NONE)) + return 1; + + for (i = 0; i < 18; ++i) + { + size_t len = 1 << i; + + do_test (0, 0, len); + do_test (i, 0, len); + do_test (0, i, len); + do_test (i, i, len); + + do_test (0, bufsize - len, len); + do_test (bufsize - len, 0, len); + do_test (i, bufsize - len, len); + do_test (bufsize - len, i, len); + } + + for (i = 0; i < 32; ++i) + { + do_test (i, 0, i); + do_test (0, i, i); + do_test (i, i, i); + + for (j = 0; j < 32; ++j) + { + do_test (i, bufsize - i - j, i); + do_test (bufsize - i - j, i, i); + } + } + + for (i = 3; i < 32; ++i) + { + if ((i & (i - 1)) == 0) + continue; + do_test (0, 0, 16 * i); + do_test (i, 0, 16 * i); + do_test (0, i, 16 * i); + do_test (i, i, 16 * i); + } + + return fail; +} diff --git a/libitm/testsuite/libitm.c/memset-1.c b/libitm/testsuite/libitm.c/memset-1.c new file mode 100644 index 00000000000..87bf6c62322 --- /dev/null +++ b/libitm/testsuite/libitm.c/memset-1.c @@ -0,0 +1,117 @@ +/* This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. */ + +/* Verify memcpy operation. */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/mman.h> +#include <libitm.h> + +#define BEG_TRANSACTION \ + _ITM_beginTransaction (pr_instrumentedCode | pr_hasNoAbort \ + | pr_hasNoIrrevocable) +#define END_TRANSACTION \ + _ITM_commitTransaction () + +#define MEMSET _ITM_memsetW + +static unsigned char *buf; +static size_t bufsize, page_size; +static int fail; + +static void +do_test (size_t align, size_t len) +{ + size_t i, j; + unsigned char c1, c2; + + if (align + len >= bufsize) + return; + + c1 = random () >> 8; + c2 = random () >> 8; + if (c1 == c2) + c1++; + memset (buf, c1, bufsize); + + BEG_TRANSACTION; + MEMSET (buf + align, c2, len); + END_TRANSACTION; + + i = (align > 64 ? align - 64 : 0); + for (; i < align; ++i) + if (buf[i] != c1) + { + printf ("Garbage before: ofs %zd\n", i); + fail = 1; + break; + } + for (; i < align + len; ++i) + if (buf[i] != c2) + { + printf ("Wrong result: ofs %zd\n", i); + fail = 1; + break; + } + for (j = i + 64 < bufsize ? i + 64 : bufsize; i < j; ++i) + if (buf[i] != c1) + { + printf ("Garbage after: ofs %zd\n", i); + fail = 1; + break; + } +} + +int main() +{ + size_t i, j; + + page_size = getpagesize (); + bufsize = 2 * page_size; + + buf = mmap (NULL, bufsize + 2*page_size, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (buf == MAP_FAILED) + return 1; + + if (mprotect (buf, page_size, PROT_NONE)) + return 1; + buf += page_size; + if (mprotect (buf + bufsize, page_size, PROT_NONE)) + return 1; + + for (i = 0; i < 18; ++i) + { + size_t len = 1 << i; + do_test (0, len); + do_test (bufsize - len, len); + } + + for (i = 0; i < 32; ++i) + for (j = 0; j < 32; ++j) + do_test (j, i); + + for (i = 3; i < 32; ++i) + { + if ((i & (i - 1)) == 0) + continue; + do_test (0, 16 * i); + do_test (i, 16 * i); + } + + return fail; +} diff --git a/libitm/testsuite/libitm.c/notx.c b/libitm/testsuite/libitm.c/notx.c new file mode 100644 index 00000000000..999da025a82 --- /dev/null +++ b/libitm/testsuite/libitm.c/notx.c @@ -0,0 +1,33 @@ +/* These tests all check whether initialization happens properly even if no + transaction has been used in the current thread yet. */ +#include <stdlib.h> +#include <pthread.h> +#include <libitm.h> + +static void *test1 (void *dummy __attribute__((unused))) +{ + if (_ITM_inTransaction() != outsideTransaction) + abort(); + return NULL; +} + +static void *test2 (void *dummy __attribute__((unused))) +{ + if (_ITM_getTransactionId() != _ITM_noTransactionId) + abort(); + return NULL; +} + + +int main() +{ + pthread_t thread; + + pthread_create(&thread, NULL, test1, NULL); + pthread_join(thread, NULL); + + pthread_create(&thread, NULL, test2, NULL); + pthread_join(thread, NULL); + + return 0; +} diff --git a/libitm/testsuite/libitm.c/reentrant.c b/libitm/testsuite/libitm.c/reentrant.c new file mode 100644 index 00000000000..007bbaab741 --- /dev/null +++ b/libitm/testsuite/libitm.c/reentrant.c @@ -0,0 +1,66 @@ +/* { dg-do run { xfail *-*-* } } + +/* Tests that new transactions can be started from both transaction_pure and + transaction_unsafe code. This also requires proper handling of reentrant + nesting in the serial_lock implementation. */ + +#include <stdlib.h> +#include <pthread.h> +#include <libitm.h> + +int x = 0; + +int __attribute__((transaction_pure)) pure(int i) +{ + __transaction_atomic { + x++; + } + if (_ITM_inTransaction() == outsideTransaction) + abort(); + return i+1; +} + +int __attribute__((transaction_unsafe)) unsafe(int i) +{ + if (_ITM_inTransaction() != inIrrevocableTransaction) + abort(); + __transaction_atomic { + x++; + } + if (_ITM_inTransaction() != inIrrevocableTransaction) + abort(); + return i+1; +} + +static void *thread (void *dummy __attribute__((unused))) +{ + __transaction_atomic { + pure(1); + } + __transaction_relaxed { + unsafe(1); + } + return 0; +} + +int main() +{ + pthread_t pt; + int r = 0; + + __transaction_atomic { + r += pure(1) + x; + } + __transaction_relaxed { + r += unsafe(1) + x; + } + if (r != 7) + abort(); + + // Spawn a new thread to check that the serial lock is not held. + pthread_create(&pt, NULL, thread, NULL); + pthread_join(pt, NULL); + if (x != 4) + abort(); + return 0; +} diff --git a/libitm/testsuite/libitm.c/simple-1.c b/libitm/testsuite/libitm.c/simple-1.c new file mode 100644 index 00000000000..de41740d49a --- /dev/null +++ b/libitm/testsuite/libitm.c/simple-1.c @@ -0,0 +1,24 @@ +/* Verify that two sequential runs of a transaction will complete and + produce correct results. An early test of the library did in fact + leave things in an inconsistent state following the commit of the + first transaction. */ + +#include <stdlib.h> + +static int x; + +static void start (void) +{ + __transaction_atomic { x++; } +} + +int main() +{ + start (); + start (); + + if (x != 2) + abort (); + + return 0; +} diff --git a/libitm/testsuite/libitm.c/simple-2.c b/libitm/testsuite/libitm.c/simple-2.c new file mode 100644 index 00000000000..e92c917340d --- /dev/null +++ b/libitm/testsuite/libitm.c/simple-2.c @@ -0,0 +1,29 @@ +/* Simplest test involving real threads. Verify we get the correct answer. */ + +#include <stdlib.h> +#include <pthread.h> + +static int x; + +static void *start (void *dummy __attribute__((unused))) +{ + __transaction_atomic { x++; } + return NULL; +} + +int main() +{ + pthread_t p[10]; + int i; + + for (i = 0; i < 10; ++i) + pthread_create (p+i, NULL, start, NULL); + + for (i = 0; i < 10; ++i) + pthread_join (p[i], NULL); + + if (x != 10) + abort (); + + return 0; +} diff --git a/libitm/testsuite/libitm.c/txrelease.c b/libitm/testsuite/libitm.c/txrelease.c new file mode 100644 index 00000000000..7bf04343d57 --- /dev/null +++ b/libitm/testsuite/libitm.c/txrelease.c @@ -0,0 +1,47 @@ +/* This test triggers execution of the code that releases per-thread + transaction data when a thread exists, potentially repeatedly. However, + we currently cannot check whether the data has indeed been released. */ + +#include <stddef.h> +#include <stdlib.h> +#include <pthread.h> + +static int round = 0; +static pthread_key_t key; + +static void +thread_exit_handler(void *dummy __attribute__((unused))) +{ + if (round == 0) + abort(); + if (round == 1) + { + // ??? It would be good if we could check here that the transaction has + // indeed been released. + __transaction_atomic { round++; } + if (pthread_setspecific(key, &round)) + abort(); + } + // ??? It would be good if we could check here that the transaction has + // indeed been released (again). +} + +static void *thread (void *dummy __attribute__((unused))) +{ + if (pthread_key_create(&key, thread_exit_handler)) + abort(); + if (pthread_setspecific(key, &round)) + abort(); + __transaction_atomic { round++; } + return NULL; +} + +int main() +{ + pthread_t pt; + pthread_create(&pt, NULL, thread, NULL); + pthread_join(pt, NULL); + if (round != 2) + abort(); + return 0; +} diff --git a/libitm/useraction.cc b/libitm/useraction.cc new file mode 100644 index 00000000000..952bbd991b4 --- /dev/null +++ b/libitm/useraction.cc @@ -0,0 +1,81 @@ +/* Copyright (C) 2008, 2009, 2011 Free Software Foundation, Inc. + Contributed by Richard Henderson <rth@redhat.com>. + + This file is part of the GNU Transactional Memory Library (libitm). + + Libitm is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + Libitm is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + <http://www.gnu.org/licenses/>. */ + +#include "libitm_i.h" + +namespace GTM HIDDEN { + +void +gtm_thread::rollback_user_actions(size_t until_size) +{ + for (size_t s = user_actions.size(); s > until_size; s--) + { + user_action *a = user_actions.pop(); + if (!a->on_commit) + a->fn (a->arg); + } +} + + +void +gtm_thread::commit_user_actions() +{ + for (vector<user_action>::iterator i = user_actions.begin(), + ie = user_actions.end(); i != ie; i++) + { + if (i->on_commit) + i->fn (i->arg); + } + user_actions.clear(); +} + +} // namespace GTM + +using namespace GTM; + +void ITM_REGPARM +_ITM_addUserCommitAction(_ITM_userCommitFunction fn, + _ITM_transactionId_t tid, void *arg) +{ + gtm_thread *tx = gtm_thr(); + if (tid != _ITM_noTransactionId) + GTM_fatal("resumingTransactionId in _ITM_addUserCommitAction must be " + "_ITM_noTransactionId"); + gtm_thread::user_action *a = tx->user_actions.push(); + a->fn = fn; + a->arg = arg; + a->on_commit = true; + a->resuming_id = tid; +} + + +void ITM_REGPARM +_ITM_addUserUndoAction(_ITM_userUndoFunction fn, void * arg) +{ + gtm_thread *tx = gtm_thr(); + gtm_thread::user_action *a = tx->user_actions.push(); + a->fn = fn; + a->arg = arg; + a->on_commit = false; +} diff --git a/libitm/util.cc b/libitm/util.cc new file mode 100644 index 00000000000..afd37e41731 --- /dev/null +++ b/libitm/util.cc @@ -0,0 +1,85 @@ +/* Copyright (C) 2009, 2011 Free Software Foundation, Inc. + Contributed by Richard Henderson <rth@redhat.com>. + + This file is part of the GNU Transactional Memory Library (libitm). + + Libitm is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + Libitm is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + <http://www.gnu.org/licenses/>. */ + +#include "libitm_i.h" +#include <stdarg.h> +#include <stdio.h> + +namespace GTM HIDDEN { + +static void +gtm_verror (const char *fmt, va_list list) +{ + fputs ("\nlibitm: ", stderr); + vfprintf (stderr, fmt, list); + fputc ('\n', stderr); +} + +void +GTM_error (const char *fmt, ...) +{ + va_list list; + + va_start (list, fmt); + gtm_verror (fmt, list); + va_end (list); +} + +void +GTM_fatal (const char *fmt, ...) +{ + va_list list; + + va_start (list, fmt); + gtm_verror (fmt, list); + va_end (list); + + exit (EXIT_FAILURE); +} + +void * +xmalloc (size_t size, bool separate_cl) +{ + // TODO Use posix_memalign if separate_cl is true, or some other allocation + // method that will avoid sharing cache lines with data used by other + // threads. + void *r = malloc (size); + if (r == 0) + GTM_fatal ("Out of memory allocating %lu bytes", (unsigned long) size); + return r; +} + +void * +xrealloc (void *old, size_t size, bool separate_cl) +{ + // TODO Use posix_memalign if separate_cl is true, or some other allocation + // method that will avoid sharing cache lines with data used by other + // threads. + void *r = realloc (old, size); + if (r == 0) + GTM_fatal ("Out of memory allocating %lu bytes", (unsigned long) size); + return r; +} + +} // namespace GTM diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index e9f1f1b0fd3..51abac9fe05 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,16 @@ +2011-11-07 Aldy Hernandez <aldyh@redhat.com> + Richard Henderson <rth@redhat.com> + + Merged from transactional-memory. + + * testsuite/util/testsuite_abi.cc (check_version): Add CXXABI_TM_1. + * libsupc++/eh_tm.cc: New file. + * libsupc++/unwind-cxx.h (__cxa_tm_cleanup): Declare. + * config/abi/pre/gnu.ver: Export __cxa_tm_cleanup. + * config/abi/pre/gnu-versioned-namespace.ver: Likewise. + * libsupc++/Makefile.am (sources): Add eh_tm.cc. + * libsupc++/Makefile.in: Rebuild. + 2011-11-07 Paolo Carlini <paolo.carlini@oracle.com> PR libstdc++/51018 diff --git a/libstdc++-v3/config/abi/pre/gnu-versioned-namespace.ver b/libstdc++-v3/config/abi/pre/gnu-versioned-namespace.ver index 32bcf67d819..13f06ef4568 100644 --- a/libstdc++-v3/config/abi/pre/gnu-versioned-namespace.ver +++ b/libstdc++-v3/config/abi/pre/gnu-versioned-namespace.ver @@ -302,3 +302,12 @@ CXXABI_2.0 { local: *; }; + +# Symbols in the support library (libsupc++) supporting trans-mem. +CXXABI_TM_1 { + global: + __cxa_tm_cleanup; + + local: + *; +}; diff --git a/libstdc++-v3/config/abi/pre/gnu.ver b/libstdc++-v3/config/abi/pre/gnu.ver index 31807945144..ce56120c960 100644 --- a/libstdc++-v3/config/abi/pre/gnu.ver +++ b/libstdc++-v3/config/abi/pre/gnu.ver @@ -1463,6 +1463,15 @@ CXXABI_1.3.3 { } CXXABI_1.3.2; +# Symbols in the support library (libsupc++) supporting trans-mem. +CXXABI_TM_1 { + global: + __cxa_tm_cleanup; + + local: + *; +}; + CXXABI_1.3.4 { # typeinfo for decimal floating point types diff --git a/libstdc++-v3/libsupc++/Makefile.am b/libstdc++-v3/libsupc++/Makefile.am index 701c2d9a76a..c8e661d5788 100644 --- a/libstdc++-v3/libsupc++/Makefile.am +++ b/libstdc++-v3/libsupc++/Makefile.am @@ -68,6 +68,7 @@ sources = \ eh_ptr.cc \ eh_term_handler.cc \ eh_terminate.cc \ + eh_tm.cc \ eh_throw.cc \ eh_type.cc \ eh_unex_handler.cc \ diff --git a/libstdc++-v3/libsupc++/Makefile.in b/libstdc++-v3/libsupc++/Makefile.in index 9ef5e683af8..191bd281e3d 100644 --- a/libstdc++-v3/libsupc++/Makefile.in +++ b/libstdc++-v3/libsupc++/Makefile.in @@ -95,13 +95,14 @@ am__objects_1 = array_type_info.lo atexit_arm.lo bad_alloc.lo \ del_opnt.lo del_opv.lo del_opvnt.lo dyncast.lo eh_alloc.lo \ eh_arm.lo eh_aux_runtime.lo eh_call.lo eh_catch.lo \ eh_exception.lo eh_globals.lo eh_personality.lo eh_ptr.lo \ - eh_term_handler.lo eh_terminate.lo eh_throw.lo eh_type.lo \ - eh_unex_handler.lo enum_type_info.lo function_type_info.lo \ - fundamental_type_info.lo guard.lo guard_error.lo hash_bytes.lo \ - nested_exception.lo new_handler.lo new_op.lo new_opnt.lo \ - new_opv.lo new_opvnt.lo pbase_type_info.lo pmem_type_info.lo \ - pointer_type_info.lo pure.lo si_class_type_info.lo tinfo.lo \ - tinfo2.lo vec.lo vmi_class_type_info.lo vterminate.lo + eh_term_handler.lo eh_terminate.lo eh_tm.lo eh_throw.lo \ + eh_type.lo eh_unex_handler.lo enum_type_info.lo \ + function_type_info.lo fundamental_type_info.lo guard.lo \ + guard_error.lo hash_bytes.lo nested_exception.lo \ + new_handler.lo new_op.lo new_opnt.lo new_opv.lo new_opvnt.lo \ + pbase_type_info.lo pmem_type_info.lo pointer_type_info.lo \ + pure.lo si_class_type_info.lo tinfo.lo tinfo2.lo vec.lo \ + vmi_class_type_info.lo vterminate.lo @GLIBCXX_HOSTED_TRUE@am__objects_2 = cp-demangle.lo am_libsupc___la_OBJECTS = $(am__objects_1) $(am__objects_2) libsupc___la_OBJECTS = $(am_libsupc___la_OBJECTS) @@ -375,6 +376,7 @@ sources = \ eh_ptr.cc \ eh_term_handler.cc \ eh_terminate.cc \ + eh_tm.cc \ eh_throw.cc \ eh_type.cc \ eh_unex_handler.cc \ diff --git a/libstdc++-v3/libsupc++/eh_tm.cc b/libstdc++-v3/libsupc++/eh_tm.cc new file mode 100644 index 00000000000..f5815a180df --- /dev/null +++ b/libstdc++-v3/libsupc++/eh_tm.cc @@ -0,0 +1,124 @@ +// -*- C++ -*- Exception handling routines for Transactional Memory. +// Copyright (C) 2009 Free Software Foundation, Inc. +// +// This file is part of GCC. +// +// GCC is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 3, or (at your option) +// any later version. +// +// GCC is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// <http://www.gnu.org/licenses/>. + +#include <cstdlib> +#include "unwind-cxx.h" + +using namespace __cxxabiv1; + +// Free one C++ exception. + +static void +free_any_cxa_exception (_Unwind_Exception *eo) +{ + __cxa_refcounted_exception *h + = __get_refcounted_exception_header_from_ue (eo); + + if (__is_dependent_exception (eo->exception_class)) + { + __cxa_dependent_exception *dep + = __get_dependent_exception_from_ue (eo); + + h = __get_refcounted_exception_header_from_obj (dep->primaryException); + + __cxa_free_dependent_exception (dep); + } + + if (__sync_sub_and_fetch (&h->referenceCount, 1) == 0) + __cxa_free_exception (h + 1); +} + +// Cleanup exception handling state while rolling back state for +// a software transactional memory transaction. +// +// UNTHROWN_OBJ is non-null if we've called __cxa_allocate_exception +// but not yet called __cxa_throw for it. +// +// CLEANUP_EXC is non-null if we're currently processing a cleanup +// along an exception path, but we've not caught the exception yet. +// +// CAUGHT_COUNT is the nesting depth of __cxa_begin_catch within +// the transaction; undo as if calling __cxa_end_catch that many times. + +extern "C" void +__cxxabiv1::__cxa_tm_cleanup (void *unthrown_obj, + void *cleanup_exc, + unsigned int caught_count) throw() +{ + __cxa_eh_globals *globals = __cxa_get_globals_fast (); + + // Handle a C++ exception not yet thrown. + if (unthrown_obj) + { + globals->uncaughtExceptions -= 1; + __cxa_free_exception (unthrown_obj); + } + + // Handle an exception not yet caught ie. processing a cleanup + // in between the throw and the catch. + if (cleanup_exc) + { + _Unwind_Exception *eo + = reinterpret_cast <_Unwind_Exception *>(cleanup_exc); + if (__is_gxx_exception_class (eo->exception_class)) + free_any_cxa_exception (eo); + else + _Unwind_DeleteException (eo); + } + + // Do __cxa_end_catch caught_count times, but don't bother running + // the destructors for the objects involved. All of that is being + // undone by the transaction restart. + if (caught_count > 0) + { + __cxa_exception *h = globals->caughtExceptions; + + // Rethrown foreign exceptions are removed from the stack immediately. + // We would have freed this exception via THIS_EXC above. + if (h == NULL) + return; + + do + { + __cxa_exception *next; + _Unwind_Exception *eo = &h->unwindHeader; + + if (__is_gxx_exception_class (eo->exception_class)) + { + next = h->nextException; + free_any_cxa_exception (eo); + } + else + { + _Unwind_DeleteException (eo); + next = 0; + } + + h = next; + } + while (--caught_count); + + globals->caughtExceptions = h; + } +} diff --git a/libstdc++-v3/libsupc++/unwind-cxx.h b/libstdc++-v3/libsupc++/unwind-cxx.h index 84dd36781df..e538bdedf05 100644 --- a/libstdc++-v3/libsupc++/unwind-cxx.h +++ b/libstdc++-v3/libsupc++/unwind-cxx.h @@ -167,6 +167,9 @@ extern "C" bool __cxa_begin_cleanup (_Unwind_Exception*); extern "C" void __cxa_end_cleanup (void); #endif +// Handles cleanup from transactional memory restart. +extern "C" void __cxa_tm_cleanup (void *, void *, unsigned int) throw(); + // Invokes given handler, dying appropriately if the user handler was // so inconsiderate as to return. extern void __terminate(std::terminate_handler) throw () diff --git a/libstdc++-v3/testsuite/util/testsuite_abi.cc b/libstdc++-v3/testsuite/util/testsuite_abi.cc index 9e6837e9b52..8c3b37f8373 100644 --- a/libstdc++-v3/testsuite/util/testsuite_abi.cc +++ b/libstdc++-v3/testsuite/util/testsuite_abi.cc @@ -203,6 +203,7 @@ check_version(symbol& test, bool added) known_versions.push_back("CXXABI_1.3.2"); known_versions.push_back("CXXABI_1.3.3"); known_versions.push_back("CXXABI_1.3.4"); + known_versions.push_back("CXXABI_TM_1"); known_versions.push_back("CXXABI_1.3.5"); known_versions.push_back("CXXABI_1.3.6"); known_versions.push_back("CXXABI_LDBL_1.3"); |