FIX #1427, #1569: gcc 4.2.x needs -fno-toplevel-reorder
authorSimon Marlow <simonmar@microsoft.com>
Tue, 21 Aug 2007 15:15:53 +0000 (15:15 +0000)
committerSimon Marlow <simonmar@microsoft.com>
Tue, 21 Aug 2007 15:15:53 +0000 (15:15 +0000)
We now have various flags that need to be passed to gcc, but only if
the local gcc version supports them.  So instead of wiring this
knowledge into ghc when it is built, we now put these "extra gcc
flags" into a text file in $libdir, extra-gcc-flags, which is created
by configure.  It is also created by the configure script of a binary
distribution, so a binary dist is independent of the gcc version used
to build it.

Hopefully I got the binary-dist stuff right, but binary dists aren't
currently working so we'll need to come back and check this.

Makefile
aclocal.m4
compiler/main/DriverPipeline.hs
compiler/main/DynFlags.hs
compiler/main/SysTools.lhs
configure.ac
distrib/configure-bin.ac
extra-gcc-opts.in [new file with mode: 0644]

index 981fec0..192a0d5 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -199,6 +199,11 @@ install ::
 endif
 endif
 
 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 \
 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 \
               ANNOUNCE \
               LICENSE \
               install-sh \
+             extra-gcc-opts.in \
               config.guess \
               config.sub   \
               aclocal.m4
               config.guess \
               config.sub   \
               aclocal.m4
index e5aed8a..12db959 100644 (file)
@@ -936,45 +936,47 @@ AC_SUBST([GhcHasReadline], [`echo $fp_cv_ghc_has_readline | sed 'y/yesno/YESNO/'
 ])# FP_GHC_HAS_READLINE
 
 
 ])# 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
 # 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_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
 # ---------------------
 
 # FP_SETUP_PROJECT_VERSION
 # ---------------------
index e414f4c..cf6bff1 100644 (file)
@@ -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
                              (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
         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 && 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 [])
                       ++ (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
                       ++ 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)
                       ))
 
        return (next_phase, dflags, maybe_loc, output_fn)
index 8880550..1721b4c 100644 (file)
@@ -1515,6 +1515,18 @@ setOptHpcDir arg  = upd $ \ d -> d{hpcDir = arg}
 -----------------------------------------------------------------------------
 -- Via-C compilation stuff
 
 -----------------------------------------------------------------------------
 -- 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
 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",
 --                    , 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
                        "-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.
                        -- 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
                 "-fno-builtin"
                        -- calling builtins like strlen() using the FFI can
                        -- cause gcc to run out of regs, so use the external
index 64e7b78..e098dd9 100644 (file)
@@ -22,6 +22,7 @@ module SysTools (
        copy,
         copyWithHeader,
        normalisePath,          -- FilePath -> FilePath
        copy,
         copyWithHeader,
        normalisePath,          -- FilePath -> FilePath
+        getExtraViaCOpts,
        
        -- Temporary-file management
        setTmpDir,
        
        -- Temporary-file management
        setTmpDir,
@@ -536,6 +537,10 @@ copyWithHeader dflags purpose maybe_header from to = do
   hPutStr h ls
   hClose h
 
   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}
 
 %************************************************************************
 \end{code}
 
 %************************************************************************
index b35c7e7..8dec569 100644 (file)
@@ -876,9 +876,7 @@ dnl     If gcc, make sure it's at least 2.1
 dnl
 FP_HAVE_GCC
 FP_MINGW_GCC
 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
 
 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)
 
 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
 AC_CONFIG_COMMANDS([mk/stamp-h],[echo timestamp > mk/stamp-h])
 AC_OUTPUT
index 0d01388..8d9ea90 100644 (file)
@@ -148,7 +148,13 @@ FP_HAVE_GCC
 AC_PROG_CPP
 
 #
 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'"
 
 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 (file)
index 0000000..8c9832c
--- /dev/null
@@ -0,0 +1 @@
+@GccExtraViaCOpts@