Comments and esthetical changes.
[ghc-hetmet.git] / ghc / compiler / main / DriverPipeline.hs
index 171cecf..bbc8051 100644 (file)
@@ -65,6 +65,7 @@ import Directory
 import System
 import IO
 import Monad
+import Data.List       ( isSuffixOf )
 import Maybe
 
 
@@ -165,70 +166,65 @@ compile hsc_env mod_summary maybe_old_linkable old_iface mod_index nmods = do
        hsc_env' = hsc_env { hsc_dflags = dflags' }
        object_filename = ml_obj_file location
 
+   let getStubLinkable False = return []
+       getStubLinkable True
+           = do stub_o <- compileStub dflags' this_mod location
+                return [ DotO stub_o ]
+
+       handleMake (HscNoRecomp, iface, details)
+           = ASSERT (isJust maybe_old_linkable)
+             return (CompOK details iface maybe_old_linkable)
+       handleMake (HscRecomp hasStub, iface, details)
+           | isHsBoot src_flavour
+               = return (CompOK details iface Nothing)
+           | otherwise
+               = do stub_unlinked <- getStubLinkable hasStub
+                    (hs_unlinked, unlinked_time) <-
+                        case hsc_lang of
+                          HscNothing
+                            -> return ([], ms_hs_date mod_summary)
+                          -- We're in --make mode: finish the compilation pipeline.
+                          _other
+                            -> do runPipeline StopLn dflags (output_fn,Nothing) Persistent
+                                              (Just location)
+                                  -- The object filename comes from the ModLocation
+                                  o_time <- getModificationTime object_filename
+                                  return ([DotO object_filename], o_time)
+                    let linkable = LM unlinked_time this_mod
+                                  (hs_unlinked ++ stub_unlinked)
+                    return (CompOK details iface (Just linkable))
+
+       handleInterpreted (InteractiveNoRecomp, iface, details)
+           = ASSERT (isJust maybe_old_linkable)
+             return (CompOK details iface maybe_old_linkable)
+       handleInterpreted (InteractiveRecomp hasStub comp_bc, iface, details)
+           = do stub_unlinked <- getStubLinkable hasStub
+                let hs_unlinked = [BCOs comp_bc]
+                    unlinked_time = ms_hs_date mod_summary
+                  -- Why do we use the timestamp of the source file here,
+                  -- rather than the current time?  This works better in
+                  -- the case where the local clock is out of sync
+                  -- with the filesystem's clock.  It's just as accurate:
+                  -- if the source is modified, then the linkable will
+                  -- be out of date.
+                let linkable = LM unlinked_time this_mod
+                               (hs_unlinked ++ stub_unlinked)
+                return (CompOK details iface (Just linkable))
+
+   let runCompiler compiler handle
+           = do mbResult <- compiler hsc_env' mod_summary
+                                     source_unchanged have_object old_iface
+                                     (Just (mod_index, nmods))
+                case mbResult of
+                  Nothing     -> return CompErrs
+                  Just result -> handle result
    -- run the compiler
-   hsc_result <- hscMain hsc_env' mod_summary
-                        source_unchanged have_object old_iface
-                         (Just (mod_index, nmods))
-
-   case hsc_result of
-      HscFail -> return CompErrs
-
-      HscNoRecomp details iface -> 
-         ASSERT(isJust maybe_old_linkable)
-         return (CompOK details iface maybe_old_linkable)
-
-      HscRecomp details iface stub_h_exists stub_c_exists maybe_interpreted_code 
-
-       | isHsBoot src_flavour  -- No further compilation to do
-       -> do   case hsc_lang of
-                  HscInterpreted -> return ()
-                  _other -> SysTools.touch dflags' "Touching object file" 
-                                           object_filename
-               return (CompOK details iface Nothing)
-
-       | otherwise     -- Normal source file
-       -> do
-          stub_unlinked <-
-            if stub_c_exists then do
-               stub_o <- compileStub dflags' this_mod location
-               return [ DotO stub_o ]
-            else
-               return []
-
-          (hs_unlinked, unlinked_time) <-
-            case hsc_lang of
-
-               -- in interpreted mode, just return the compiled code
-               -- as our "unlinked" object.
-               HscInterpreted
-                 -> case maybe_interpreted_code of
-#ifdef GHCI
-                      Just comp_bc -> return ([BCOs comp_bc], ms_hs_date mod_summary)
-                       -- Why do we use the timestamp of the source file here,
-                       -- rather than the current time?  This works better in
-                       -- the case where the local clock is out of sync
-                       -- with the filesystem's clock.  It's just as accurate:
-                       -- if the source is modified, then the linkable will
-                       -- be out of date.
-#endif
-                      Nothing -> panic "compile: no interpreted code"
-
-               HscNothing
-                 -> return ([], ms_hs_date mod_summary)
-
-               -- We're in --make mode: finish the compilation pipeline.
-               _other
-                 -> do runPipeline StopLn dflags (output_fn,Nothing) Persistent
-                                   (Just location)
-                               -- The object filename comes from the ModLocation
-
-                       o_time <- getModificationTime object_filename
-                       return ([DotO object_filename], o_time)
-
-          let linkable = LM unlinked_time this_mod
-                            (hs_unlinked ++ stub_unlinked)
-
-          return (CompOK details iface (Just linkable))
+   case hsc_lang of
+     HscInterpreted | not (isHsBoot src_flavour) -- We can't compile boot files to
+                                                 -- bytecode so don't even try.
+         -> runCompiler hscCompileInteractive handleInterpreted
+     _other
+         -> runCompiler hscCompileMake handleMake
 
 -----------------------------------------------------------------------------
 -- stub .h and .c files (for foreign export support)
@@ -297,7 +293,7 @@ link BatchCompile dflags batch_attempt_linking hpt
            pkg_deps  = concatMap (dep_pkgs . mi_deps . hm_iface) home_mod_infos
 
            -- the linkables to link
-           linkables = map (fromJust.hm_linkable) home_mod_infos
+           linkables = map (expectJust "link".hm_linkable) home_mod_infos
 
         debugTraceMsg dflags 3 (text "link: linkables are ..." $$ vcat (map ppr linkables))
 
@@ -753,38 +749,29 @@ runPhase (Hsc src_flavour) stop dflags0 basename suff input_fn get_output_fn _ma
        addHomeModuleToFinder hsc_env mod_name location4
 
   -- run the compiler!
-       result <- hscMain hsc_env
+       mbResult <- hscCompileOneShot hsc_env
                          mod_summary source_unchanged 
                          False         -- No object file
                          Nothing       -- No iface
                           Nothing       -- No "module i of n" progress info
 
-       case result of
-
-           HscFail -> throwDyn (PhaseFailed "hsc" (ExitFailure 1))
-
-            HscNoRecomp details iface -> do
-               SysTools.touch dflags' "Touching object file" o_file
-                       -- The .o file must have a later modification date
-                       -- than the source file (else we wouldn't be in HscNoRecomp)
-                       -- but we touch it anyway, to keep 'make' happy (we think).
-               return (StopLn, dflags', Just location4, o_file)
-
-           HscRecomp _details _iface 
-                     stub_h_exists stub_c_exists
-                     _maybe_interpreted_code -> do
-
-               when stub_c_exists $ do
-                       stub_o <- compileStub dflags' mod_name location4
-                       consIORef v_Ld_inputs stub_o
-
-               -- In the case of hs-boot files, generate a dummy .o-boot 
-               -- stamp file for the benefit of Make
-               case src_flavour of
-                 HsBootFile -> SysTools.touch dflags' "Touching object file" o_file
-                 other      -> return ()
-
-               return (next_phase, dflags', Just location4, output_fn)
+       case mbResult of
+          Nothing -> throwDyn (PhaseFailed "hsc" (ExitFailure 1))
+          Just HscNoRecomp
+              -> do SysTools.touch dflags' "Touching object file" o_file
+                    -- The .o file must have a later modification date
+                    -- than the source file (else we wouldn't be in HscNoRecomp)
+                    -- but we touch it anyway, to keep 'make' happy (we think).
+                    return (StopLn, dflags', Just location4, o_file)
+          Just (HscRecomp hasStub)
+              -> do when hasStub $
+                         do stub_o <- compileStub dflags' mod_name location4
+                            consIORef v_Ld_inputs stub_o
+                    -- In the case of hs-boot files, generate a dummy .o-boot 
+                    -- stamp file for the benefit of Make
+                    when (isHsBoot src_flavour) $
+                      SysTools.touch dflags' "Touching object file" o_file
+                    return (next_phase, dflags', Just location4, output_fn)
 
 -----------------------------------------------------------------------------
 -- Cmm phase
@@ -847,6 +834,9 @@ runPhase cc_phase stop dflags basename suff input_fn get_output_fn maybe_loc
 
        let excessPrecision = dopt Opt_ExcessPrecision dflags
 
+       let cc_opt | optLevel dflags >= 2 = "-O2"
+                  | otherwise            = "-O"
+
        -- Decide next phase
        
         let mangle = dopt Opt_DoAsmMangling dflags
@@ -891,7 +881,7 @@ runPhase cc_phase stop dflags basename suff input_fn get_output_fn maybe_loc
                       ++ (if hcc 
                             then more_hcc_opts
                             else [])
-                      ++ [ verb, "-S", "-Wimplicit", "-O" ]
+                      ++ [ verb, "-S", "-Wimplicit", cc_opt ]
                       ++ [ "-D__GLASGOW_HASKELL__="++cProjectVersionInt ]
                       ++ cc_opts
                       ++ split_opt
@@ -982,34 +972,64 @@ runPhase As stop dflags _basename _suff input_fn get_output_fn maybe_loc
 
 
 runPhase SplitAs stop dflags basename _suff _input_fn get_output_fn maybe_loc
-  = do  let as_opts = getOpts dflags opt_a
+  = do  
+       output_fn <- get_output_fn StopLn maybe_loc
+
+       let (base_o, _) = splitFilename output_fn
+           split_odir  = base_o ++ "_split"
+           osuf = objectSuf dflags
+
+       createDirectoryHierarchy split_odir
+
+       -- remove M_split/ *.o, because we're going to archive M_split/ *.o
+       -- later and we don't want to pick up any old objects.
+       fs <- getDirectoryContents split_odir 
+       mapM_ removeFile $ map (split_odir `joinFileName`)
+                        $ filter (osuf `isSuffixOf`) fs
+
+       let as_opts = getOpts dflags opt_a
 
        (split_s_prefix, n) <- readIORef v_Split_info
 
-       let real_odir
-               | Just d <- objectDir dflags = d
-               | otherwise                  = basename ++ "_split"
+       let split_s   n = split_s_prefix ++ "__" ++ show n `joinFileExt` "s"
+           split_obj n = split_odir `joinFileName`
+                               filenameOf base_o ++ "__" ++ show n
+                                       `joinFileExt` osuf
 
        let assemble_file n
-             = do  let input_s  = split_s_prefix ++ "__" ++ show n ++ ".s"
-                   let output_o = replaceFilenameDirectory
-                                       (basename ++ "__" ++ show n ++ ".o")
-                                        real_odir
-                   let osuf = objectSuf dflags
-                   let real_o = replaceFilenameSuffix output_o osuf
-                   SysTools.runAs dflags
-                                (map SysTools.Option as_opts ++
-                                   [ SysTools.Option "-c"
-                                   , SysTools.Option "-o"
-                                   , SysTools.FileOption "" real_o
-                                   , SysTools.FileOption "" input_s
-                                   ])
+             = SysTools.runAs dflags
+                        (map SysTools.Option as_opts ++
+                        [ SysTools.Option "-c"
+                        , SysTools.Option "-o"
+                        , SysTools.FileOption "" (split_obj n)
+                        , SysTools.FileOption "" (split_s n)
+                        ])
        
        mapM_ assemble_file [1..n]
 
-       output_fn <- get_output_fn StopLn maybe_loc
+       -- and join the split objects into a single object file:
+       let ld_r args = SysTools.runLink dflags ([ 
+                               SysTools.Option "-nostdlib",
+                               SysTools.Option "-nodefaultlibs",
+                               SysTools.Option "-Wl,-r", 
+                               SysTools.Option ld_x_flag, 
+                               SysTools.Option "-o", 
+                               SysTools.FileOption "" output_fn ] ++ args)
+            ld_x_flag | null cLD_X = ""
+                     | otherwise  = "-Wl,-x"     
+
+       if cLdIsGNULd == "YES"
+           then do 
+                 let script = split_odir `joinFileName` "ld.script"
+                 writeFile script $
+                     "INPUT(" ++ unwords (map split_obj [1..n]) ++ ")"
+                 ld_r [SysTools.FileOption "" script]
+           else do
+                 ld_r (map (SysTools.FileOption "" . split_obj) [1..n])
+
        return (StopLn, dflags, maybe_loc, output_fn)
 
+
 -----------------------------------------------------------------------------
 -- MoveBinary sort-of-phase
 -- After having produced a binary, move it somewhere else and generate a