{-# LANGUAGE LambdaCase #-}
module GHC.Unit.Home.PackageTable
(
HomePackageTable(..)
, emptyHomePackageTable
, lookupHpt
, lookupHptByModule
, addHomeModInfoToHpt
, addHomeModInfosToHpt
, restrictHpt
, hptCompleteSigs
, hptAllInstances
, hptAllFamInstances
, hptAllAnnotations
, hptCollectDependencies
, hptCollectObjects
, hptCollectModules
, concatHpt
, pprHPT
, hptInternalTableRef
, hptInternalTableFromRef
, addToHpt
, addListToHpt
) where
import GHC.Prelude
import GHC.Data.Maybe
import Data.IORef
import Control.Monad ((<$!>))
import qualified Data.Set as Set
import GHC.Core.FamInstEnv
import GHC.Core.InstEnv
import GHC.Linker.Types
import GHC.Types.Annotations
import GHC.Types.CompleteMatch
import GHC.Types.Unique.DFM
import GHC.Unit.Home.ModInfo
import GHC.Unit.Module
import GHC.Unit.Module.Deps
import GHC.Unit.Module.ModDetails
import GHC.Unit.Module.ModIface
import GHC.Utils.Outputable
import GHC.Types.Unique (getUnique, getKey)
import qualified GHC.Data.Word64Set as W64
newtype HomePackageTable = HPT {
HomePackageTable -> IORef (DModuleNameEnv HomeModInfo)
table :: IORef (DModuleNameEnv HomeModInfo)
}
emptyHomePackageTable :: IO HomePackageTable
emptyHomePackageTable :: IO HomePackageTable
emptyHomePackageTable = do
table <- DModuleNameEnv HomeModInfo
-> IO (IORef (DModuleNameEnv HomeModInfo))
forall a. a -> IO (IORef a)
newIORef DModuleNameEnv HomeModInfo
forall {k} (key :: k) elt. UniqDFM key elt
emptyUDFM
return HPT{table}
lookupHpt :: HomePackageTable -> ModuleName -> IO (Maybe HomeModInfo)
lookupHpt :: HomePackageTable -> ModuleName -> IO (Maybe HomeModInfo)
lookupHpt HPT{table :: HomePackageTable -> IORef (DModuleNameEnv HomeModInfo)
table=IORef (DModuleNameEnv HomeModInfo)
hpt} ModuleName
mn = (DModuleNameEnv HomeModInfo -> ModuleName -> Maybe HomeModInfo
forall key elt.
Uniquable key =>
UniqDFM key elt -> key -> Maybe elt
`lookupUDFM` ModuleName
mn) (DModuleNameEnv HomeModInfo -> Maybe HomeModInfo)
-> IO (DModuleNameEnv HomeModInfo) -> IO (Maybe HomeModInfo)
forall (m :: * -> *) a b. Monad m => (a -> b) -> m a -> m b
<$!> IORef (DModuleNameEnv HomeModInfo)
-> IO (DModuleNameEnv HomeModInfo)
forall a. IORef a -> IO a
readIORef IORef (DModuleNameEnv HomeModInfo)
hpt
lookupHptByModule :: HomePackageTable -> Module -> IO (Maybe HomeModInfo)
lookupHptByModule :: HomePackageTable -> Module -> IO (Maybe HomeModInfo)
lookupHptByModule HomePackageTable
hpt Module
mod
=
HomePackageTable -> ModuleName -> IO (Maybe HomeModInfo)
lookupHpt HomePackageTable
hpt (Module -> ModuleName
forall unit. GenModule unit -> ModuleName
moduleName Module
mod) IO (Maybe HomeModInfo)
-> (Maybe HomeModInfo -> IO (Maybe HomeModInfo))
-> IO (Maybe HomeModInfo)
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Maybe HomeModInfo -> IO (Maybe HomeModInfo)
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Maybe HomeModInfo -> IO (Maybe HomeModInfo))
-> (Maybe HomeModInfo -> Maybe HomeModInfo)
-> Maybe HomeModInfo
-> IO (Maybe HomeModInfo)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. \case
Just HomeModInfo
hm | ModIface_ 'ModIfaceFinal -> Module
forall (phase :: ModIfacePhase). ModIface_ phase -> Module
mi_module (HomeModInfo -> ModIface_ 'ModIfaceFinal
hm_iface HomeModInfo
hm) Module -> Module -> Bool
forall a. Eq a => a -> a -> Bool
== Module
mod -> HomeModInfo -> Maybe HomeModInfo
forall a. a -> Maybe a
Just HomeModInfo
hm
Maybe HomeModInfo
_otherwise -> Maybe HomeModInfo
forall a. Maybe a
Nothing
addHomeModInfoToHpt :: HomeModInfo -> HomePackageTable -> IO ()
addHomeModInfoToHpt :: HomeModInfo -> HomePackageTable -> IO ()
addHomeModInfoToHpt HomeModInfo
hmi HomePackageTable
hpt = HomePackageTable -> ModuleName -> HomeModInfo -> IO ()
addToHpt HomePackageTable
hpt (Module -> ModuleName
forall unit. GenModule unit -> ModuleName
moduleName (ModIface_ 'ModIfaceFinal -> Module
forall (phase :: ModIfacePhase). ModIface_ phase -> Module
mi_module (HomeModInfo -> ModIface_ 'ModIfaceFinal
hm_iface HomeModInfo
hmi))) HomeModInfo
hmi
{-# DEPRECATED addToHpt "Deprecated in favour of 'addHomeModInfoToHpt', as the module at which a 'HomeModInfo' is inserted should always be derived from the 'HomeModInfo' itself." #-}
addToHpt :: HomePackageTable -> ModuleName -> HomeModInfo -> IO ()
addToHpt :: HomePackageTable -> ModuleName -> HomeModInfo -> IO ()
addToHpt HPT{table :: HomePackageTable -> IORef (DModuleNameEnv HomeModInfo)
table=IORef (DModuleNameEnv HomeModInfo)
hptr} ModuleName
mn HomeModInfo
hmi = do
IORef (DModuleNameEnv HomeModInfo)
-> (DModuleNameEnv HomeModInfo -> (DModuleNameEnv HomeModInfo, ()))
-> IO ()
forall a b. IORef a -> (a -> (a, b)) -> IO b
atomicModifyIORef' IORef (DModuleNameEnv HomeModInfo)
hptr (\DModuleNameEnv HomeModInfo
hpt -> (DModuleNameEnv HomeModInfo
-> ModuleName -> HomeModInfo -> DModuleNameEnv HomeModInfo
forall key elt.
Uniquable key =>
UniqDFM key elt -> key -> elt -> UniqDFM key elt
addToUDFM DModuleNameEnv HomeModInfo
hpt ModuleName
mn HomeModInfo
hmi, ()))
addHomeModInfosToHpt :: HomePackageTable -> [HomeModInfo] -> IO ()
addHomeModInfosToHpt :: HomePackageTable -> [HomeModInfo] -> IO ()
addHomeModInfosToHpt HomePackageTable
hpt = (HomeModInfo -> IO ()) -> [HomeModInfo] -> IO ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ ((HomeModInfo -> HomePackageTable -> IO ())
-> HomePackageTable -> HomeModInfo -> IO ()
forall a b c. (a -> b -> c) -> b -> a -> c
flip HomeModInfo -> HomePackageTable -> IO ()
addHomeModInfoToHpt HomePackageTable
hpt)
restrictHpt :: HomePackageTable -> [HomeModInfo] -> IO ()
restrictHpt :: HomePackageTable -> [HomeModInfo] -> IO ()
restrictHpt HPT{table :: HomePackageTable -> IORef (DModuleNameEnv HomeModInfo)
table=IORef (DModuleNameEnv HomeModInfo)
hptr} [HomeModInfo]
hmis =
let key_set :: [Word64]
key_set = (HomeModInfo -> Word64) -> [HomeModInfo] -> [Word64]
forall a b. (a -> b) -> [a] -> [b]
map (Unique -> Word64
getKey (Unique -> Word64)
-> (HomeModInfo -> Unique) -> HomeModInfo -> Word64
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ModuleName -> Unique
forall a. Uniquable a => a -> Unique
getUnique (ModuleName -> Unique)
-> (HomeModInfo -> ModuleName) -> HomeModInfo -> Unique
forall b c a. (b -> c) -> (a -> b) -> a -> c
. HomeModInfo -> ModuleName
hmi_mod) [HomeModInfo]
hmis
hmi_mod :: HomeModInfo -> ModuleName
hmi_mod HomeModInfo
hmi = Module -> ModuleName
forall unit. GenModule unit -> ModuleName
moduleName (ModIface_ 'ModIfaceFinal -> Module
forall (phase :: ModIfacePhase). ModIface_ phase -> Module
mi_module (HomeModInfo -> ModIface_ 'ModIfaceFinal
hm_iface HomeModInfo
hmi))
in IORef (DModuleNameEnv HomeModInfo)
-> (DModuleNameEnv HomeModInfo -> (DModuleNameEnv HomeModInfo, ()))
-> IO ()
forall a b. IORef a -> (a -> (a, b)) -> IO b
atomicModifyIORef' IORef (DModuleNameEnv HomeModInfo)
hptr (\DModuleNameEnv HomeModInfo
hpt -> (DModuleNameEnv HomeModInfo
-> Word64Set -> DModuleNameEnv HomeModInfo
forall {k} (key :: k) elt.
UniqDFM key elt -> Word64Set -> UniqDFM key elt
udfmRestrictKeysSet DModuleNameEnv HomeModInfo
hpt ([Word64] -> Word64Set
W64.fromList [Word64]
key_set), ()))
{-# DEPRECATED addListToHpt "Deprecated in favour of 'addHomeModInfosToHpt', as the module at which a 'HomeModInfo' is inserted should always be derived from the 'HomeModInfo' itself." #-}
addListToHpt :: HomePackageTable -> [(ModuleName, HomeModInfo)] -> IO ()
addListToHpt :: HomePackageTable -> [(ModuleName, HomeModInfo)] -> IO ()
addListToHpt HomePackageTable
hpt = ((ModuleName, HomeModInfo) -> IO ())
-> [(ModuleName, HomeModInfo)] -> IO ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ ((ModuleName -> HomeModInfo -> IO ())
-> (ModuleName, HomeModInfo) -> IO ()
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry (HomePackageTable -> ModuleName -> HomeModInfo -> IO ()
addToHpt HomePackageTable
hpt))
hptCompleteSigs :: HomePackageTable -> IO CompleteMatches
hptCompleteSigs :: HomePackageTable -> IO CompleteMatches
hptCompleteSigs = (HomeModInfo -> CompleteMatches)
-> HomePackageTable -> IO CompleteMatches
forall a. (HomeModInfo -> [a]) -> HomePackageTable -> IO [a]
concatHpt (ModDetails -> CompleteMatches
md_complete_matches (ModDetails -> CompleteMatches)
-> (HomeModInfo -> ModDetails) -> HomeModInfo -> CompleteMatches
forall b c a. (b -> c) -> (a -> b) -> a -> c
. HomeModInfo -> ModDetails
hm_details)
hptAllInstances :: HomePackageTable -> IO (InstEnv, [FamInst])
hptAllInstances :: HomePackageTable -> IO (InstEnv, [FamInst])
hptAllInstances HomePackageTable
hpt = do
hits <- ((HomeModInfo -> [(InstEnv, [FamInst])])
-> HomePackageTable -> IO [(InstEnv, [FamInst])])
-> HomePackageTable
-> (HomeModInfo -> [(InstEnv, [FamInst])])
-> IO [(InstEnv, [FamInst])]
forall a b c. (a -> b -> c) -> b -> a -> c
flip (HomeModInfo -> [(InstEnv, [FamInst])])
-> HomePackageTable -> IO [(InstEnv, [FamInst])]
forall a. (HomeModInfo -> [a]) -> HomePackageTable -> IO [a]
concatHpt HomePackageTable
hpt ((HomeModInfo -> [(InstEnv, [FamInst])])
-> IO [(InstEnv, [FamInst])])
-> (HomeModInfo -> [(InstEnv, [FamInst])])
-> IO [(InstEnv, [FamInst])]
forall a b. (a -> b) -> a -> b
$ \HomeModInfo
mod_info -> do
let details :: ModDetails
details = HomeModInfo -> ModDetails
hm_details HomeModInfo
mod_info
(InstEnv, [FamInst]) -> [(InstEnv, [FamInst])]
forall a. a -> [a]
forall (m :: * -> *) a. Monad m => a -> m a
return (ModDetails -> InstEnv
md_insts ModDetails
details, ModDetails -> [FamInst]
md_fam_insts ModDetails
details)
let (insts, famInsts) = unzip hits
return (foldl' unionInstEnv emptyInstEnv insts, concat famInsts)
hptAllFamInstances :: HomePackageTable -> IO (ModuleEnv FamInstEnv)
hptAllFamInstances :: HomePackageTable -> IO (ModuleEnv FamInstEnv)
hptAllFamInstances = ([(Module, FamInstEnv)] -> ModuleEnv FamInstEnv)
-> IO [(Module, FamInstEnv)] -> IO (ModuleEnv FamInstEnv)
forall a b. (a -> b) -> IO a -> IO b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap [(Module, FamInstEnv)] -> ModuleEnv FamInstEnv
forall a. [(Module, a)] -> ModuleEnv a
mkModuleEnv (IO [(Module, FamInstEnv)] -> IO (ModuleEnv FamInstEnv))
-> (HomePackageTable -> IO [(Module, FamInstEnv)])
-> HomePackageTable
-> IO (ModuleEnv FamInstEnv)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (HomeModInfo -> [(Module, FamInstEnv)])
-> HomePackageTable -> IO [(Module, FamInstEnv)]
forall a. (HomeModInfo -> [a]) -> HomePackageTable -> IO [a]
concatHpt (\HomeModInfo
hmi -> [(HomeModInfo -> Module
hmiModule HomeModInfo
hmi, HomeModInfo -> FamInstEnv
hmiFamInstEnv HomeModInfo
hmi)])
where
hmiModule :: HomeModInfo -> Module
hmiModule = ModIface_ 'ModIfaceFinal -> Module
forall (phase :: ModIfacePhase). ModIface_ phase -> Module
mi_module (ModIface_ 'ModIfaceFinal -> Module)
-> (HomeModInfo -> ModIface_ 'ModIfaceFinal)
-> HomeModInfo
-> Module
forall b c a. (b -> c) -> (a -> b) -> a -> c
. HomeModInfo -> ModIface_ 'ModIfaceFinal
hm_iface
hmiFamInstEnv :: HomeModInfo -> FamInstEnv
hmiFamInstEnv = FamInstEnv -> [FamInst] -> FamInstEnv
extendFamInstEnvList FamInstEnv
emptyFamInstEnv
([FamInst] -> FamInstEnv)
-> (HomeModInfo -> [FamInst]) -> HomeModInfo -> FamInstEnv
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ModDetails -> [FamInst]
md_fam_insts (ModDetails -> [FamInst])
-> (HomeModInfo -> ModDetails) -> HomeModInfo -> [FamInst]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. HomeModInfo -> ModDetails
hm_details
hptAllAnnotations :: HomePackageTable -> IO AnnEnv
hptAllAnnotations :: HomePackageTable -> IO AnnEnv
hptAllAnnotations = ([Annotation] -> AnnEnv) -> IO [Annotation] -> IO AnnEnv
forall a b. (a -> b) -> IO a -> IO b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap [Annotation] -> AnnEnv
mkAnnEnv (IO [Annotation] -> IO AnnEnv)
-> (HomePackageTable -> IO [Annotation])
-> HomePackageTable
-> IO AnnEnv
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (HomeModInfo -> [Annotation])
-> HomePackageTable -> IO [Annotation]
forall a. (HomeModInfo -> [a]) -> HomePackageTable -> IO [a]
concatHpt (ModDetails -> [Annotation]
md_anns (ModDetails -> [Annotation])
-> (HomeModInfo -> ModDetails) -> HomeModInfo -> [Annotation]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. HomeModInfo -> ModDetails
hm_details)
hptCollectDependencies :: HomePackageTable -> IO (Set.Set UnitId)
hptCollectDependencies :: HomePackageTable -> IO (Set UnitId)
hptCollectDependencies HPT{IORef (DModuleNameEnv HomeModInfo)
table :: HomePackageTable -> IORef (DModuleNameEnv HomeModInfo)
table :: IORef (DModuleNameEnv HomeModInfo)
table} = do
hpt <- IORef (DModuleNameEnv HomeModInfo)
-> IO (DModuleNameEnv HomeModInfo)
forall a. IORef a -> IO a
readIORef IORef (DModuleNameEnv HomeModInfo)
table
return $
foldr (Set.union . dep_direct_pkgs . mi_deps . hm_iface) Set.empty hpt
hptCollectObjects :: HomePackageTable -> IO [Linkable]
hptCollectObjects :: HomePackageTable -> IO [Linkable]
hptCollectObjects HPT{IORef (DModuleNameEnv HomeModInfo)
table :: HomePackageTable -> IORef (DModuleNameEnv HomeModInfo)
table :: IORef (DModuleNameEnv HomeModInfo)
table} = do
hpt <- IORef (DModuleNameEnv HomeModInfo)
-> IO (DModuleNameEnv HomeModInfo)
forall a. IORef a -> IO a
readIORef IORef (DModuleNameEnv HomeModInfo)
table
return $
foldr ((:) . expectJust "collectObjects" . homeModInfoObject) [] hpt
hptCollectModules :: HomePackageTable -> IO [Module]
hptCollectModules :: HomePackageTable -> IO [Module]
hptCollectModules HPT{IORef (DModuleNameEnv HomeModInfo)
table :: HomePackageTable -> IORef (DModuleNameEnv HomeModInfo)
table :: IORef (DModuleNameEnv HomeModInfo)
table} = do
hpt <- IORef (DModuleNameEnv HomeModInfo)
-> IO (DModuleNameEnv HomeModInfo)
forall a. IORef a -> IO a
readIORef IORef (DModuleNameEnv HomeModInfo)
table
return $
foldr ((:) . mi_module . hm_iface) [] hpt
pprHPT :: HomePackageTable -> IO SDoc
pprHPT :: HomePackageTable -> IO SDoc
pprHPT HPT{table :: HomePackageTable -> IORef (DModuleNameEnv HomeModInfo)
table=IORef (DModuleNameEnv HomeModInfo)
hptr} = do
hpt <- IORef (DModuleNameEnv HomeModInfo)
-> IO (DModuleNameEnv HomeModInfo)
forall a. IORef a -> IO a
readIORef IORef (DModuleNameEnv HomeModInfo)
hptr
return $!
pprUDFM hpt $ \[HomeModInfo]
hms ->
[SDoc] -> SDoc
forall doc. IsDoc doc => [doc] -> doc
vcat [ Module -> SDoc
forall a. Outputable a => a -> SDoc
ppr (ModIface_ 'ModIfaceFinal -> Module
forall (phase :: ModIfacePhase). ModIface_ phase -> Module
mi_module (HomeModInfo -> ModIface_ 'ModIfaceFinal
hm_iface HomeModInfo
hm))
| HomeModInfo
hm <- [HomeModInfo]
hms ]
concatHpt :: (HomeModInfo -> [a]) -> HomePackageTable -> IO [a]
concatHpt :: forall a. (HomeModInfo -> [a]) -> HomePackageTable -> IO [a]
concatHpt HomeModInfo -> [a]
f HPT{IORef (DModuleNameEnv HomeModInfo)
table :: HomePackageTable -> IORef (DModuleNameEnv HomeModInfo)
table :: IORef (DModuleNameEnv HomeModInfo)
table} = do
hpt <- IORef (DModuleNameEnv HomeModInfo)
-> IO (DModuleNameEnv HomeModInfo)
forall a. IORef a -> IO a
readIORef IORef (DModuleNameEnv HomeModInfo)
table
return $ concat . eltsUDFM . mapMaybeUDFM g $ hpt
where
g :: HomeModInfo -> Maybe [a]
g HomeModInfo
hmi = case HomeModInfo -> [a]
f HomeModInfo
hmi of { [] -> Maybe [a]
forall a. Maybe a
Nothing; [a]
as -> [a] -> Maybe [a]
forall a. a -> Maybe a
Just [a]
as }
hptInternalTableRef :: HomePackageTable -> IORef (DModuleNameEnv HomeModInfo)
hptInternalTableRef :: HomePackageTable -> IORef (DModuleNameEnv HomeModInfo)
hptInternalTableRef = HomePackageTable -> IORef (DModuleNameEnv HomeModInfo)
table
hptInternalTableFromRef :: IORef (DModuleNameEnv HomeModInfo) -> IO HomePackageTable
hptInternalTableFromRef :: IORef (DModuleNameEnv HomeModInfo) -> IO HomePackageTable
hptInternalTableFromRef IORef (DModuleNameEnv HomeModInfo)
ref = do
HomePackageTable -> IO HomePackageTable
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return HPT {
table :: IORef (DModuleNameEnv HomeModInfo)
table = IORef (DModuleNameEnv HomeModInfo)
ref
}