- :: [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 =