summaryrefslogtreecommitdiff
path: root/compiler/GHC/HsToCore
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/GHC/HsToCore')
-rw-r--r--compiler/GHC/HsToCore/Usage.hs167
1 files changed, 61 insertions, 106 deletions
diff --git a/compiler/GHC/HsToCore/Usage.hs b/compiler/GHC/HsToCore/Usage.hs
index 0da8f59070..4731d32591 100644
--- a/compiler/GHC/HsToCore/Usage.hs
+++ b/compiler/GHC/HsToCore/Usage.hs
@@ -12,8 +12,6 @@ import GHC.Prelude
import GHC.Driver.Env
import GHC.Driver.Session
-import GHC.Platform
-import GHC.Platform.Ways
import GHC.Tc.Types
@@ -23,29 +21,26 @@ import GHC.Utils.Fingerprint
import GHC.Utils.Panic
import GHC.Types.Name
-import GHC.Types.Name.Set
+import GHC.Types.Name.Set ( NameSet, allUses )
import GHC.Types.Unique.Set
import GHC.Types.Unique.FM
import GHC.Unit
import GHC.Unit.External
-import GHC.Unit.State
-import GHC.Unit.Finder
import GHC.Unit.Module.Imported
import GHC.Unit.Module.ModIface
import GHC.Unit.Module.Deps
import GHC.Data.Maybe
-import Control.Monad (filterM)
-import Data.List (sortBy, sort, nub)
-import Data.IORef
+import Data.List (sortBy, sort, partition)
import Data.Map (Map)
import qualified Data.Map as Map
import qualified Data.Set as Set
-import System.Directory
-import System.FilePath
+import GHC.Linker.Types
+import GHC.Linker.Loader ( getLoaderState )
+import GHC.Types.SourceFile
{- Note [Module self-dependency]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -73,15 +68,15 @@ its dep_orphs. This was the cause of #14128.
mkDependencies :: UnitId -> [Module] -> TcGblEnv -> IO Dependencies
mkDependencies iuid pluginModules
(TcGblEnv{ tcg_mod = mod,
- tcg_imports = imports,
- tcg_th_used = th_var
+ tcg_imports = imports
})
= do
- -- Template Haskell used?
- let (dep_plgins, ms) = unzip [ (moduleName mn, mn) | mn <- pluginModules ]
- plugin_dep_pkgs = filter (/= iuid) (map (toUnitId . moduleUnit) ms)
- th_used <- readIORef th_var
- let direct_mods = modDepsElts (delFromUFM (imp_direct_dep_mods imports) (moduleName mod))
+
+ let (home_plugins, package_plugins) = partition ((== iuid) . toUnitId . moduleUnit) pluginModules
+ plugin_dep_pkgs = map (toUnitId . moduleUnit) package_plugins
+ all_direct_mods = foldr (\mn m -> addToUFM m mn (GWIB mn NotBoot)) (imp_direct_dep_mods imports) (map moduleName home_plugins)
+
+ direct_mods = modDepsElts (delFromUFM all_direct_mods (moduleName mod))
-- M.hi-boot can be in the imp_dep_mods, but we must remove
-- it before recording the modules on which this one depends!
-- (We want to retain M.hi-boot in imp_dep_mods so that
@@ -95,9 +90,7 @@ mkDependencies iuid pluginModules
direct_pkgs_0 = foldr Set.insert (imp_dep_direct_pkgs imports) plugin_dep_pkgs
- direct_pkgs
- | th_used = Set.insert thUnitId direct_pkgs_0
- | otherwise = direct_pkgs_0
+ direct_pkgs = direct_pkgs_0
-- Set the packages required to be Safe according to Safe Haskell.
-- See Note [Tracking Trust Transitively] in GHC.Rename.Names
@@ -116,7 +109,6 @@ mkDependencies iuid pluginModules
dep_trusted_pkgs = sort (Set.toList trust_pkgs),
dep_boot_mods = sort source_mods,
dep_orphs = dep_orphs,
- dep_plgins = dep_plgins,
dep_finsts = sortBy stableModuleCmp (imp_finsts imports) }
-- sort to get into canonical order
-- NB. remember to use lexicographic ordering
@@ -124,25 +116,26 @@ mkDependencies iuid pluginModules
mkUsedNames :: TcGblEnv -> NameSet
mkUsedNames TcGblEnv{ tcg_dus = dus } = allUses dus
-mkUsageInfo :: HscEnv -> Module -> ImportedMods -> NameSet -> [FilePath]
- -> [(Module, Fingerprint)] -> [ModIface] -> IO [Usage]
-mkUsageInfo hsc_env this_mod dir_imp_mods used_names dependent_files merged
- pluginModules
+mkUsageInfo :: HscEnv -> Module -> HscSource -> ImportedMods -> NameSet -> [FilePath]
+ -> [(Module, Fingerprint)] -> IO [Usage]
+mkUsageInfo hsc_env this_mod src dir_imp_mods used_names dependent_files merged
= do
eps <- hscEPS hsc_env
hashes <- mapM getFileHash dependent_files
- plugin_usages <- mapM (mkPluginUsage hsc_env) pluginModules
+ -- Dependencies on object files due to TH and plugins
+ object_usages <- mkObjectUsage (eps_PIT eps) hsc_env (GWIB (moduleName this_mod) (hscSourceToIsBoot src))
let mod_usages = mk_mod_usage_info (eps_PIT eps) hsc_env this_mod
dir_imp_mods used_names
usages = mod_usages ++ [ UsageFile { usg_file_path = f
- , usg_file_hash = hash }
+ , usg_file_hash = hash
+ , usg_file_label = Nothing }
| (f, hash) <- zip dependent_files hashes ]
++ [ UsageMergedRequirement
{ usg_mod = mod,
usg_mod_hash = hash
}
| (mod, hash) <- merged ]
- ++ concat plugin_usages
+ ++ object_usages
usages `seqList` return usages
-- seq the list of Usages returned: occasionally these
-- don't get evaluated for a while and we can end up hanging on to
@@ -185,85 +178,47 @@ One way to improve this is to either:
compare implementation hashes for recompilation. Creation of implementation
hashes is however potentially expensive.
-}
-mkPluginUsage :: HscEnv -> ModIface -> IO [Usage]
-mkPluginUsage hsc_env pluginModule
- = case lookupPluginModuleWithSuggestions pkgs pNm Nothing of
- LookupFound _ pkg -> do
- -- The plugin is from an external package:
- -- search for the library files containing the plugin.
- let searchPaths = collectLibraryDirs (ways dflags) [pkg]
- useDyn = WayDyn `elem` ways dflags
- suffix = if useDyn then platformSOExt platform else "a"
- libLocs = [ searchPath </> "lib" ++ libLoc <.> suffix
- | searchPath <- searchPaths
- , libLoc <- unitHsLibs (ghcNameVersion dflags) (ways dflags) pkg
- ]
- -- we also try to find plugin library files by adding WayDyn way,
- -- if it isn't already present (see trac #15492)
- paths =
- if useDyn
- then libLocs
- else
- let dflags' = dflags { targetWays_ = addWay WayDyn (targetWays_ dflags) }
- dlibLocs = [ searchPath </> platformHsSOName platform dlibLoc
- | searchPath <- searchPaths
- , dlibLoc <- unitHsLibs (ghcNameVersion dflags') (ways dflags') pkg
- ]
- in libLocs ++ dlibLocs
- files <- filterM doesFileExist paths
- case files of
- [] ->
- pprPanic
- ( "mkPluginUsage: missing plugin library, tried:\n"
- ++ unlines paths
- )
- (ppr pNm)
- _ -> mapM hashFile (nub files)
- _ -> do
- let fc = hsc_FC hsc_env
- let units = hsc_units hsc_env
- let home_unit = hsc_home_unit hsc_env
- let dflags = hsc_dflags hsc_env
- foundM <- findPluginModule fc units home_unit dflags pNm
- case foundM of
- -- The plugin was built locally: look up the object file containing
- -- the `plugin` binder, and all object files belong to modules that are
- -- transitive dependencies of the plugin that belong to the same package.
- Found ml _ -> do
- pluginObject <- hashFile (ml_obj_file ml)
- depObjects <- catMaybes <$> mapM lookupObjectFile deps
- return (nub (pluginObject : depObjects))
- _ -> pprPanic "mkPluginUsage: no object file found" (ppr pNm)
+
+-- | Find object files corresponding to the transitive closure of given home
+-- modules and direct object files for pkg dependencies
+mkObjectUsage :: PackageIfaceTable -> HscEnv -> ModuleNameWithIsBoot -> IO [Usage]
+mkObjectUsage pit hsc_env mnwib = do
+ case hsc_interp hsc_env of
+ Just interp -> do
+ mps <- getLoaderState interp
+ case mps of
+ Just ps -> do
+ let ls = fromMaybe [] $ Map.lookup mnwib (module_deps ps)
+ ds = hs_objs_loaded ps
+ concat <$> sequence (map linkableToUsage ls ++ map librarySpecToUsage ds)
+ Nothing -> return []
+ Nothing -> return []
+
+
where
- dflags = hsc_dflags hsc_env
- fc = hsc_FC hsc_env
- home_unit = hsc_home_unit hsc_env
- units = hsc_units hsc_env
- platform = targetPlatform dflags
- pkgs = hsc_units hsc_env
- pNm = moduleName $ mi_module pluginModule
- pPkg = moduleUnit $ mi_module pluginModule
- deps = map gwib_mod $
- dep_direct_mods $ mi_deps pluginModule
-
- -- Lookup object file for a plugin dependency,
- -- from the same package as the plugin.
- lookupObjectFile nm = do
- foundM <- findImportedModule fc units home_unit dflags nm Nothing
- case foundM of
- Found ml m
- | moduleUnit m == pPkg -> Just <$> hashFile (ml_obj_file ml)
- | otherwise -> return Nothing
- _ -> pprPanic "mkPluginUsage: no object for dependency"
- (ppr pNm <+> ppr nm)
-
- hashFile f = do
- fExist <- doesFileExist f
- if fExist
- then do
- h <- getFileHash f
- return (UsageFile f h)
- else pprPanic "mkPluginUsage: file not found" (ppr pNm <+> text f)
+ linkableToUsage (LM _ m uls) = mapM (unlinkedToUsage m) uls
+
+ msg m = moduleNameString (moduleName m) ++ "[TH] changed"
+
+ fing mmsg fn = UsageFile fn <$> getFileHash fn <*> pure mmsg
+
+ unlinkedToUsage m ul =
+ case nameOfObject_maybe ul of
+ Just fn -> fing (Just (msg m)) fn
+ Nothing -> do
+ -- This should only happen for home package things but oneshot puts
+ -- home package ifaces in the PIT.
+ let miface = lookupIfaceByModule (hsc_HPT hsc_env) pit m
+ case miface of
+ Nothing -> pprPanic "mkObjectUsage" (ppr m)
+ Just iface ->
+ return $ UsageHomeModuleInterface (moduleName m) (mi_iface_hash (mi_final_exts iface))
+
+ librarySpecToUsage :: LibrarySpec -> IO [Usage]
+ librarySpecToUsage (Objects os) = traverse (fing Nothing) os
+ librarySpecToUsage (Archive fn) = traverse (fing Nothing) [fn]
+ librarySpecToUsage (DLLPath fn) = traverse (fing Nothing) [fn]
+ librarySpecToUsage _ = return []
mk_mod_usage_info :: PackageIfaceTable
-> HscEnv