[project @ 2001-02-12 13:33:46 by simonmar]
[ghc-hetmet.git] / ghc / compiler / compMan / CompManager.lhs
index befb5b3..f136af7 100644 (file)
@@ -36,6 +36,7 @@ import DriverUtil     ( splitFilename3 )
 import ErrUtils                ( showPass )
 import Util
 import DriverUtil
+import TmpFiles
 import Outputable
 import Panic
 import CmdLineOpts     ( DynFlags(..) )
@@ -201,18 +202,9 @@ cmLoadModule cmstate1 rootname
         let mg2_with_srcimps = topological_sort True mg2unsorted
 
        -- Sort out which linkables we wish to keep in the unlinked image.
-       -- For each module, we take:
-       --
-       --      - the old in-core linkable, if available
-       --      - an on-disk linkable, if available
-       --
-       -- and we take the youngest of these, provided it is younger than the
-       -- source file.
-       --
-       -- If a module has a valid linkable, then it may be STABLE (see below),
-       -- and it is classified as SOURCE UNCHANGED for the purposes of calling
-       -- compile.
-       valid_linkables <- getValidLinkables ui1 mg2unsorted
+       -- See getValidLinkables below for details.
+       valid_linkables <- getValidLinkables ui1 mg2unsorted_names 
+                               mg2_with_srcimps
 
         -- Figure out a stable set of modules which can be retained
         -- the top level envs, to avoid upsweeping them.  Goes to a
@@ -293,6 +285,10 @@ cmLoadModule cmstate1 rootname
            -- Easy; just relink it all.
            do when (verb >= 2) $ 
                 hPutStrLn stderr "Upsweep completely successful."
+
+             -- clean up after ourselves
+             cleanTempFilesExcept verb (ppFilesFromSummaries modsDone)
+
               linkresult 
                  <- link ghci_mode dflags a_root_is_Main ui3 pls2
               case linkresult of
@@ -330,6 +326,9 @@ cmLoadModule cmstate1 rootname
                      = map (unJust "linkables_to_link" . findModuleLinkable_maybe ui4)
                            mods_to_keep_names
 
+             -- clean up after ourselves
+             cleanTempFilesExcept verb (ppFilesFromSummaries mods_to_keep)
+
               linkresult <- link ghci_mode dflags False linkables_to_link pls2
               case linkresult of
                  LinkErrs _ _
@@ -343,38 +342,90 @@ cmLoadModule cmstate1 rootname
                                   map ms_mod mods_to_keep)
 
 
+ppFilesFromSummaries summaries
+  = [ fn | Just fn <- map (ml_hspp_file . ms_location) summaries ]
+
 -----------------------------------------------------------------------------
 -- getValidLinkables
 
+-- For each module (or SCC of modules), we take:
+--
+--     - the old in-core linkable, if available
+--     - an on-disk linkable, if available
+--
+-- and we take the youngest of these, provided it is younger than the
+-- source file.  We ignore the on-disk linkables unless all of the
+-- dependents of this SCC also have on-disk linkables.
+--
+-- If a module has a valid linkable, then it may be STABLE (see below),
+-- and it is classified as SOURCE UNCHANGED for the purposes of calling
+-- compile.
+--
+-- ToDo: this pass could be merged with the preUpsweep.
+
 getValidLinkables
-       :: [Linkable]                   -- old linkables
-       -> [ModSummary]                 -- all modules in the program
-       -> IO [Linkable]                -- still-valid linkables 
-
-getValidLinkables old_linkables summaries
-  = do lis <- mapM (getValidLinkable old_linkables) summaries
-       return (concat lis)
-
-getValidLinkable old_linkables summary
-  = do let mod_name = moduleName (ms_mod summary)
-       maybe_disk_linkable
-           <- case ml_obj_file (ms_location summary) of
-                 Nothing -> return Nothing
-                 Just obj_fn -> maybe_getFileLinkable mod_name obj_fn
-
-       -- find an old in-core linkable if we have one. (forget about
-       -- on-disk linkables for now, we'll check again whether there's
-       -- one here below, just in case a new one has popped up recently).
-       let old_linkable = findModuleLinkable_maybe old_linkables mod_name
-           maybe_old_linkable =
+       :: [Linkable]           -- old linkables
+       -> [ModuleName]         -- all home modules
+       -> [SCC ModSummary]     -- all modules in the program, dependency order
+       -> IO [Linkable]        -- still-valid linkables 
+
+getValidLinkables old_linkables all_home_mods module_graph
+  = foldM (getValidLinkablesSCC old_linkables all_home_mods) [] module_graph
+
+getValidLinkablesSCC old_linkables all_home_mods new_linkables scc0
+   = let 
+         scc             = flattenSCC scc0
+          scc_names       = map name_of_summary scc
+         home_module m   = m `elem` all_home_mods && m `notElem` scc_names
+          scc_allhomeimps = nub (filter home_module (concatMap ms_allimps scc))
+
+         has_object m = case findModuleLinkable_maybe new_linkables m of
+                           Nothing -> False
+                           Just l  -> isObjectLinkable l
+
+          objects_allowed = all has_object scc_allhomeimps
+     in do
+
+     these_linkables 
+       <- foldM (getValidLinkable old_linkables objects_allowed) [] scc
+
+       -- since an scc can contain only all objects or no objects at all,
+       -- we have to check whether we got all objects or not, and re-do
+       -- the linkable check if not.
+     adjusted_linkables 
+       <- if objects_allowed && not (all isObjectLinkable these_linkables)
+             then foldM (getValidLinkable old_linkables False) [] scc
+             else return these_linkables
+
+     return (adjusted_linkables ++ new_linkables)
+
+
+getValidLinkable :: [Linkable] -> Bool -> [Linkable] -> ModSummary 
+       -> IO [Linkable]
+getValidLinkable old_linkables objects_allowed new_linkables summary 
+   = do 
+       let mod_name = name_of_summary summary
+
+       maybe_disk_linkable
+           <- if (not objects_allowed)
+               then return Nothing
+               else case ml_obj_file (ms_location summary) of
+                       Just obj_fn -> maybe_getFileLinkable mod_name obj_fn
+                       Nothing -> return Nothing
+
+        -- find an old in-core linkable if we have one. (forget about
+        -- on-disk linkables for now, we'll check again whether there's
+        -- one here below, just in case a new one has popped up recently).
+        let old_linkable = findModuleLinkable_maybe old_linkables mod_name
+            maybe_old_linkable =
                case old_linkable of
                    Just (LM _ _ ls) | all isInterpretable ls -> old_linkable
-                   _ -> Nothing      
+                   _ -> Nothing
 
-       -- The most recent of the old UI linkable or whatever we could
-       -- find on disk is returned as the linkable if compile
-       -- doesn't think we need to recompile.        
-       let linkable_list
+        -- The most recent of the old UI linkable or whatever we could
+        -- find on disk is returned as the linkable if compile
+        -- doesn't think we need to recompile.        
+        let linkable_list
                = case (maybe_old_linkable, maybe_disk_linkable) of
                     (Nothing, Nothing) -> []
                     (Nothing, Just di) -> [di]
@@ -383,17 +434,16 @@ getValidLinkable old_linkables summary
                        | linkableTime ui >= linkableTime di -> [ui]
                        | otherwise                          -> [di]
 
-       -- only linkables newer than the source code are valid
-       let maybe_src_date = ms_hs_date summary
+        -- only linkables newer than the source code are valid
+        let maybe_src_date = ms_hs_date summary
 
-          valid_linkable_list
+           valid_linkable_list
              = case maybe_src_date of
                  Nothing -> panic "valid_linkable_list"
                  Just src_date 
-                     -> filter (\li -> linkableTime li > src_date) linkable_list
-
-       return valid_linkable_list
+                    -> filter (\li -> linkableTime li > src_date) linkable_list
 
+        return (valid_linkable_list ++ new_linkables)
 
 
 maybe_getFileLinkable :: ModuleName -> FilePath -> IO (Maybe Linkable)
@@ -434,9 +484,7 @@ preUpsweep valid_lis old_lis all_home_mods stable (scc0:sccs)
             scc_names
                = map name_of_summary scc
             in_stable_or_scc m
-               = --trace (showSDoc (text "ISOS" <+> ppr m <+> ppr scc_names <+> ppr stable)) (
-                 m `elem` scc_names || m `elem` stable
-                 --)
+               = m `elem` scc_names || m `elem` stable
 
            -- now we check for valid linkables: each module in the SCC must 
            -- have a valid linkable (see getValidLinkables above), and the
@@ -744,14 +792,8 @@ downsweep rootNm old_summaries
 
         getSummary :: ModuleName -> IO ModSummary
         getSummary nm
-           -- | trace ("getSummary: "++ showSDoc (ppr nm)) True
            = do found <- findModule nm
                case found of
-                   -- Be sure not to use the mod and location passed in to 
-                   -- summarise for any other purpose -- summarise may change
-                   -- the module names in them if name of module /= name of file,
-                   -- and put the changed versions in the returned summary.
-                   -- These will then conflict with the passed-in versions.
                   Just (mod, location) -> do
                        let old_summary = findModInSummaries old_summaries mod
                        new_summary <- summarise mod location old_summary
@@ -771,7 +813,7 @@ downsweep rootNm old_summaries
                let all_home = map (moduleName.ms_mod) home_summaries
 
                -- imports for modules we don't already have
-                let needed_imps = filter (`notElem` all_home) imps
+                let needed_imps = nub (filter (`notElem` all_home) imps)
 
                -- summarise them
                 needed_summaries <- mapM getSummary needed_imps
@@ -844,12 +886,11 @@ summarise mod location old_summary
                  Nothing     -> return Nothing
                  Just src_fn -> maybe_getModificationTime src_fn
 
-       if mod_name == moduleName mod
-               then return ()
-               else throwDyn (OtherError 
-                       (showSDoc (text "file name does not match module name: "
-                          <+> ppr (moduleName mod) <+> text "vs" 
-                          <+> ppr mod_name)))
+       when (mod_name /= moduleName mod) $
+               throwDyn (OtherError 
+                  (showSDoc (text "file name does not match module name: "
+                             <+> ppr (moduleName mod) <+> text "vs" 
+                             <+> ppr mod_name)))
 
         return (Just (ModSummary mod location{ml_hspp_file=Just hspp_fn} 
                                  srcimps imps