diff --git a/Makefile b/Makefile index 981fec0d8c52026d82e73e0e9a79cbcd4927f3bd..192a0d5cc11429c524be6fd44f393ae5d76e1103 100644 --- a/Makefile +++ b/Makefile @@ -199,6 +199,11 @@ install :: endif endif +# Install gcc-extra-opts +install :: + @$(INSTALL_DIR) $(libdir) + $(INSTALL_DATA) $(INSTALL_OPTS) extra-gcc-opts $(libdir) + install-docs :: @case '${MFLAGS}' in *-[ik]*) x_on_err=0;; *-r*[ik]*) x_on_err=0;; *) x_on_err=1;; esac; \ for i in $(SUBDIRS); do \ @@ -262,6 +267,7 @@ BIN_DIST_TOP= distrib/Makefile \ ANNOUNCE \ LICENSE \ install-sh \ + extra-gcc-opts.in \ config.guess \ config.sub \ aclocal.m4 diff --git a/aclocal.m4 b/aclocal.m4 index e5aed8acb6961ae5dd843e31b865a9be93b37ff2..12db959bb1dae0fcbea0239c25a965a700803b0a 100644 --- a/aclocal.m4 +++ b/aclocal.m4 @@ -936,45 +936,47 @@ AC_SUBST([GhcHasReadline], [`echo $fp_cv_ghc_has_readline | sed 'y/yesno/YESNO/' ])# FP_GHC_HAS_READLINE -# FP_GCC_NEEDS_NO_OMIT_LFPTR -# -------------------------- +# FP_GCC_EXTRA_FLAGS +# ------------------ +# Determine which extra flags we need to pass gcc when we invoke it +# to compile .hc code. +# # Some OSs (Mandrake Linux, in particular) configure GCC with -# -momit-leaf-frame-pointer on by default. If this is the case, we need to turn -# it off for mangling to work. The test is currently a bit crude, using only the -# version number of gcc. Defines HAVE_GCC_MNO_OMIT_LFPTR. -AC_DEFUN([FP_GCC_NEEDS_NO_OMIT_LFPTR], -[AC_REQUIRE([FP_HAVE_GCC]) -AC_CACHE_CHECK([whether gcc needs -mno-omit-leaf-frame-pointer], [fp_cv_gcc_needs_no_omit_lfptr], -[FP_COMPARE_VERSIONS([$fp_gcc_version], [-ge], [3.2], - [fp_cv_gcc_needs_no_omit_lfptr=yes], - [fp_cv_gcc_needs_no_omit_lfptr=no])]) -if test "$fp_cv_gcc_needs_no_omit_lfptr" = "yes"; then - AC_DEFINE([HAVE_GCC_MNO_OMIT_LFPTR], [1], [Define to 1 if gcc supports -mno-omit-leaf-frame-pointer.]) -fi])# FP_GCC_NEEDS_NO_OMIT_LFPTR - -# FP_GCC_HAS_NO_UNIT_AT_A_TIME -# -------------------------- -AC_DEFUN([FP_GCC_HAS_NO_UNIT_AT_A_TIME], +# -momit-leaf-frame-pointer on by default. If this is the case, we +# need to turn it off for mangling to work. The test is currently a +# bit crude, using only the version number of gcc. +# +# -fwrapv is needed for gcc to emit well-behaved code in the presence of +# integer wrap around. (Trac #952) +# +# -fno-unit-at-a-time or -fno-toplevel-reoder is necessary to avoid gcc +# reordering things in the module and confusing the manger and/or splitter. +# (eg. Trac #1427) +# +AC_DEFUN([FP_GCC_EXTRA_FLAGS], [AC_REQUIRE([FP_HAVE_GCC]) -AC_CACHE_CHECK([whether gcc has -fno-unit-at-a-time], [fp_cv_gcc_has_no_unit_at_a_time], -[FP_COMPARE_VERSIONS([$fp_gcc_version], [-ge], [3.4], - [fp_cv_gcc_has_no_unit_at_a_time=yes], - [fp_cv_gcc_has_no_unit_at_a_time=no])]) -if test "$fp_cv_gcc_has_no_unit_at_a_time" = "yes"; then - AC_DEFINE([HAVE_GCC_HAS_NO_UNIT_AT_A_TIME], [1], [Define to 1 if gcc supports -fno-unit-at-a-time.]) -fi]) +AC_CACHE_CHECK([for extra options to pass gcc when compiling via C], [fp_cv_gcc_extra_opts], +[fp_cv_gcc_extra_opts= + FP_COMPARE_VERSIONS([$fp_gcc_version], [-ge], [3.4], + [fp_cv_gcc_extra_opts="$fp_cv_gcc_extra_opts -fwrapv"], + []) + case $TargetPlatform in + i386-*|x86_64-*) + FP_COMPARE_VERSIONS([$fp_gcc_version], [-ge], [3.2], + [fp_cv_gcc_extra_opts="$fp_cv_gcc_extra_opts -mno-omit-leaf-frame-pointer"], + []) + FP_COMPARE_VERSIONS([$fp_gcc_version], [-ge], [3.4], + [FP_COMPARE_VERSIONS([$fp_gcc_version], [-ge], [4.2], + [fp_cv_gcc_extra_opts="$fp_cv_gcc_extra_opts -fno-toplevel-reorder"], + [fp_cv_gcc_extra_opts="$fp_cv_gcc_extra_opts -fno-unit-at-a-time"] + )], + []) + ;; + esac +]) +AC_SUBST([GccExtraViaCOpts],$fp_cv_gcc_extra_opts) +]) -# FP_GCC_HAS_WRAPV -# -------------------------- -AC_DEFUN([FP_GCC_HAS_WRAPV], -[AC_REQUIRE([FP_HAVE_GCC]) -AC_CACHE_CHECK([whether gcc has -fwrapv], [fp_cv_gcc_has_wrapv], -[FP_COMPARE_VERSIONS([$fp_gcc_version], [-ge], [3.4], - [fp_cv_gcc_has_wrapv=yes], - [fp_cv_gcc_has_wrapv=no])]) -if test "$fp_cv_gcc_has_wrapv" = "yes"; then - AC_DEFINE([HAVE_GCC_HAS_WRAPV], [1], [Define to 1 if gcc supports -fwrapv.]) -fi]) # FP_SETUP_PROJECT_VERSION # --------------------- diff --git a/compiler/main/DriverPipeline.hs b/compiler/main/DriverPipeline.hs index e414f4cb3d61e40652207882c98dd60de27fe0f8..cf6bff18eef2321a61a693a8ff6bf19fdca2dc68 100644 --- a/compiler/main/DriverPipeline.hs +++ b/compiler/main/DriverPipeline.hs @@ -811,6 +811,7 @@ runPhase cc_phase stop dflags basename suff input_fn get_output_fn maybe_loc (cmdline_include_paths ++ pkg_include_dirs) let (md_c_flags, md_regd_c_flags) = machdepCCOpts dflags + gcc_extra_viac_flags <- getExtraViaCOpts dflags let pic_c_flags = picCCOpts dflags let verb = getVerbFlag dflags @@ -877,6 +878,13 @@ runPhase cc_phase stop dflags basename suff input_fn get_output_fn maybe_loc ++ (if hcc && mangle then md_regd_c_flags else []) + ++ (if hcc + then if mangle + then gcc_extra_viac_flags + else filter (=="-fwrapv") + gcc_extra_viac_flags + -- still want -fwrapv even for unreg'd + else []) ++ (if hcc then more_hcc_opts else []) @@ -886,10 +894,6 @@ runPhase cc_phase stop dflags basename suff input_fn get_output_fn maybe_loc ++ split_opt ++ include_paths ++ pkg_extra_cc_opts -#ifdef HAVE_GCC_HAS_WRAPV - -- We need consistent integer overflow (trac #952) - ++ ["-fwrapv"] -#endif )) return (next_phase, dflags, maybe_loc, output_fn) diff --git a/compiler/main/DynFlags.hs b/compiler/main/DynFlags.hs index 8880550fa34b5a70e3fe25f1a0ac58676581ce81..1721b4c0b36a8198f8fe5d4eb4d59f991c1db48b 100644 --- a/compiler/main/DynFlags.hs +++ b/compiler/main/DynFlags.hs @@ -1515,6 +1515,18 @@ setOptHpcDir arg = upd $ \ d -> d{hpcDir = arg} ----------------------------------------------------------------------------- -- Via-C compilation stuff +-- There are some options that we need to pass to gcc when compiling +-- Haskell code via C, but are only supported by recent versions of +-- gcc. The configure script decides which of these options we need, +-- and puts them in the file "extra-gcc-opts" in $topdir, which is +-- read before each via-C compilation. The advantage of having these +-- in a separate file is that the file can be created at install-time +-- depending on the available gcc version, and even re-generated later +-- if gcc is upgraded. +-- +-- The options below are not dependent on the version of gcc, only the +-- platform. + machdepCCOpts :: DynFlags -> ([String], -- flags for all C compilations [String]) -- for registerised HC compilations machdepCCOpts dflags @@ -1557,20 +1569,6 @@ machdepCCOpts dflags -- , if "mingw32" `isSuffixOf` cTARGETPLATFORM then "-mno-cygwin" else "" ], [ "-fno-defer-pop", -#ifdef HAVE_GCC_MNO_OMIT_LFPTR - -- Some gccs are configured with - -- -momit-leaf-frame-pointer on by default, and it - -- apparently takes precedence over - -- -fomit-frame-pointer, so we disable it first here. - "-mno-omit-leaf-frame-pointer", -#endif -#ifdef HAVE_GCC_HAS_NO_UNIT_AT_A_TIME - "-fno-unit-at-a-time", - -- unit-at-a-time doesn't do us any good, and screws - -- up -split-objs by moving the split markers around. - -- It's only turned on with -O2, but put it here just - -- in case someone uses -optc-O2. -#endif "-fomit-frame-pointer", -- we want -fno-builtin, because when gcc inlines -- built-in functions like memcpy() it tends to @@ -1589,13 +1587,6 @@ machdepCCOpts dflags -- and get in the way of -split-objs. Another option -- would be to throw them away in the mangler, but this -- is easier. -#ifdef HAVE_GCC_HAS_NO_UNIT_AT_A_TIME - "-fno-unit-at-a-time", - -- unit-at-a-time doesn't do us any good, and screws - -- up -split-objs by moving the split markers around. - -- It's only turned on with -O2, but put it here just - -- in case someone uses -optc-O2. -#endif "-fno-builtin" -- calling builtins like strlen() using the FFI can -- cause gcc to run out of regs, so use the external diff --git a/compiler/main/SysTools.lhs b/compiler/main/SysTools.lhs index 64e7b7803f1ecef11553a6cdebb3ee1fc414339b..e098dd9eabce8cf301e895694ebe4014d38f95b5 100644 --- a/compiler/main/SysTools.lhs +++ b/compiler/main/SysTools.lhs @@ -22,6 +22,7 @@ module SysTools ( copy, copyWithHeader, normalisePath, -- FilePath -> FilePath + getExtraViaCOpts, -- Temporary-file management setTmpDir, @@ -536,6 +537,10 @@ copyWithHeader dflags purpose maybe_header from to = do hPutStr h ls hClose h +getExtraViaCOpts :: DynFlags -> IO [String] +getExtraViaCOpts dflags = do + f <- readFile (topDir dflags `joinFileName` "extra-gcc-opts") + return (words f) \end{code} %************************************************************************ diff --git a/configure.ac b/configure.ac index b35c7e7d39c1790d159f941303eb3b72164f7d44..8dec5693929c4effceba4dca74558d53e3b795b6 100644 --- a/configure.ac +++ b/configure.ac @@ -876,9 +876,7 @@ dnl If gcc, make sure it's at least 2.1 dnl FP_HAVE_GCC FP_MINGW_GCC -FP_GCC_NEEDS_NO_OMIT_LFPTR -FP_GCC_HAS_NO_UNIT_AT_A_TIME -FP_GCC_HAS_WRAPV +FP_GCC_EXTRA_FLAGS dnl ** figure out how to invoke cpp directly (gcc -E is no good) AC_PROG_CPP @@ -1230,6 +1228,6 @@ else fi AC_SUBST(HavePapi) -AC_CONFIG_FILES([mk/config.mk ghc.spec docs/users_guide/ug-book.xml]) +AC_CONFIG_FILES([mk/config.mk ghc.spec extra-gcc-opts docs/users_guide/ug-book.xml]) AC_CONFIG_COMMANDS([mk/stamp-h],[echo timestamp > mk/stamp-h]) AC_OUTPUT diff --git a/distrib/configure-bin.ac b/distrib/configure-bin.ac index 0d01388e8086797d653e89dae73dd7d5776e38b4..8d9ea90d27beedd38e95a6e0f0ef47ceef7d06f0 100644 --- a/distrib/configure-bin.ac +++ b/distrib/configure-bin.ac @@ -148,7 +148,13 @@ FP_HAVE_GCC AC_PROG_CPP # -AC_OUTPUT(Makefile-vars) +dnl ** Check gcc version and flags we need to pass it ** +# +FP_GCC_EXTRA_FLAGS + +# +AC_CONFIG_FILES(Makefile-vars extra-gcc-opts) +AC_OUTPUT echo "****************************************************" echo "Configuration done, ready to either 'make install'" diff --git a/extra-gcc-opts.in b/extra-gcc-opts.in new file mode 100644 index 0000000000000000000000000000000000000000..8c9832c835feb54efa708ace3f4e45e74362cf4b --- /dev/null +++ b/extra-gcc-opts.in @@ -0,0 +1 @@ +@GccExtraViaCOpts@