{-# LANGUAGE TypeApplications #-}
module GHC.Linker.Types
( Loader (..)
, LoaderState (..)
, uninitializedLoader
, modifyClosureEnv
, LinkerEnv(..)
, filterLinkerEnv
, ClosureEnv
, emptyClosureEnv
, extendClosureEnv
, Linkable(..)
, LinkableSet
, mkLinkableSet
, unionLinkableSet
, ObjFile
, Unlinked(..)
, SptEntry(..)
, isObjectLinkable
, linkableObjs
, isObject
, nameOfObject
, nameOfObject_maybe
, isInterpretable
, byteCodeOfObject
, LibrarySpec(..)
, LoadedPkgInfo(..)
, PkgsLoaded
)
where
import GHC.Prelude
import GHC.Unit ( UnitId, Module )
import GHC.ByteCode.Types ( ItblEnv, AddrEnv, CompiledByteCode )
import GHC.Fingerprint.Type ( Fingerprint )
import GHCi.RemoteTypes ( ForeignHValue )
import GHC.Types.Var ( Id )
import GHC.Types.Name.Env ( NameEnv, emptyNameEnv, extendNameEnvList, filterNameEnv )
import GHC.Types.Name ( Name )
import GHC.Utils.Outputable
import GHC.Utils.Panic
import Control.Concurrent.MVar
import Data.Time ( UTCTime )
import Data.Maybe
import GHC.Unit.Module.Env
import GHC.Types.Unique.DSet
import GHC.Types.Unique.DFM
import GHC.Unit.Module.WholeCoreBindings
newtype Loader = Loader { Loader -> MVar (Maybe LoaderState)
loader_state :: MVar (Maybe LoaderState) }
data LoaderState = LoaderState
{ LoaderState -> LinkerEnv
linker_env :: !LinkerEnv
, LoaderState -> LinkableSet
bcos_loaded :: !LinkableSet
, LoaderState -> LinkableSet
objs_loaded :: !LinkableSet
, LoaderState -> PkgsLoaded
pkgs_loaded :: !PkgsLoaded
, LoaderState -> [(FilePath, FilePath)]
temp_sos :: ![(FilePath, String)]
}
uninitializedLoader :: IO Loader
uninitializedLoader :: IO Loader
uninitializedLoader = MVar (Maybe LoaderState) -> Loader
Loader forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a. a -> IO (MVar a)
newMVar forall a. Maybe a
Nothing
modifyClosureEnv :: LoaderState -> (ClosureEnv -> ClosureEnv) -> LoaderState
modifyClosureEnv :: LoaderState -> (ClosureEnv -> ClosureEnv) -> LoaderState
modifyClosureEnv LoaderState
pls ClosureEnv -> ClosureEnv
f =
let le :: LinkerEnv
le = LoaderState -> LinkerEnv
linker_env LoaderState
pls
ce :: ClosureEnv
ce = LinkerEnv -> ClosureEnv
closure_env LinkerEnv
le
in LoaderState
pls { linker_env :: LinkerEnv
linker_env = LinkerEnv
le { closure_env :: ClosureEnv
closure_env = ClosureEnv -> ClosureEnv
f ClosureEnv
ce } }
data LinkerEnv = LinkerEnv
{ LinkerEnv -> ClosureEnv
closure_env :: ClosureEnv
, LinkerEnv -> ItblEnv
itbl_env :: !ItblEnv
, LinkerEnv -> AddrEnv
addr_env :: !AddrEnv
}
filterLinkerEnv :: (Name -> Bool) -> LinkerEnv -> LinkerEnv
filterLinkerEnv :: (Name -> Bool) -> LinkerEnv -> LinkerEnv
filterLinkerEnv Name -> Bool
f LinkerEnv
le = LinkerEnv
{ closure_env :: ClosureEnv
closure_env = forall elt. (elt -> Bool) -> NameEnv elt -> NameEnv elt
filterNameEnv (Name -> Bool
f forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a, b) -> a
fst) (LinkerEnv -> ClosureEnv
closure_env LinkerEnv
le)
, itbl_env :: ItblEnv
itbl_env = forall elt. (elt -> Bool) -> NameEnv elt -> NameEnv elt
filterNameEnv (Name -> Bool
f forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a, b) -> a
fst) (LinkerEnv -> ItblEnv
itbl_env LinkerEnv
le)
, addr_env :: AddrEnv
addr_env = forall elt. (elt -> Bool) -> NameEnv elt -> NameEnv elt
filterNameEnv (Name -> Bool
f forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a, b) -> a
fst) (LinkerEnv -> AddrEnv
addr_env LinkerEnv
le)
}
type ClosureEnv = NameEnv (Name, ForeignHValue)
emptyClosureEnv :: ClosureEnv
emptyClosureEnv :: ClosureEnv
emptyClosureEnv = forall a. NameEnv a
emptyNameEnv
extendClosureEnv :: ClosureEnv -> [(Name,ForeignHValue)] -> ClosureEnv
extendClosureEnv :: ClosureEnv -> [(Name, ForeignHValue)] -> ClosureEnv
extendClosureEnv ClosureEnv
cl_env [(Name, ForeignHValue)]
pairs
= forall a. NameEnv a -> [(Name, a)] -> NameEnv a
extendNameEnvList ClosureEnv
cl_env [ (Name
n, (Name
n,ForeignHValue
v)) | (Name
n,ForeignHValue
v) <- [(Name, ForeignHValue)]
pairs]
type PkgsLoaded = UniqDFM UnitId LoadedPkgInfo
data LoadedPkgInfo
= LoadedPkgInfo
{ LoadedPkgInfo -> UnitId
loaded_pkg_uid :: !UnitId
, LoadedPkgInfo -> [LibrarySpec]
loaded_pkg_hs_objs :: ![LibrarySpec]
, LoadedPkgInfo -> [LibrarySpec]
loaded_pkg_non_hs_objs :: ![LibrarySpec]
, LoadedPkgInfo -> UniqDSet UnitId
loaded_pkg_trans_deps :: UniqDSet UnitId
}
instance Outputable LoadedPkgInfo where
ppr :: LoadedPkgInfo -> SDoc
ppr (LoadedPkgInfo UnitId
uid [LibrarySpec]
hs_objs [LibrarySpec]
non_hs_objs UniqDSet UnitId
trans_deps) =
forall doc. IsDoc doc => [doc] -> doc
vcat [forall a. Outputable a => a -> SDoc
ppr UnitId
uid
, forall a. Outputable a => a -> SDoc
ppr [LibrarySpec]
hs_objs
, forall a. Outputable a => a -> SDoc
ppr [LibrarySpec]
non_hs_objs
, forall a. Outputable a => a -> SDoc
ppr UniqDSet UnitId
trans_deps ]
data Linkable = LM {
Linkable -> UTCTime
linkableTime :: !UTCTime,
Linkable -> Module
linkableModule :: !Module,
Linkable -> [Unlinked]
linkableUnlinked :: [Unlinked]
}
type LinkableSet = ModuleEnv Linkable
mkLinkableSet :: [Linkable] -> LinkableSet
mkLinkableSet :: [Linkable] -> LinkableSet
mkLinkableSet [Linkable]
ls = forall a. [(Module, a)] -> ModuleEnv a
mkModuleEnv [(Linkable -> Module
linkableModule Linkable
l, Linkable
l) | Linkable
l <- [Linkable]
ls]
unionLinkableSet :: LinkableSet -> LinkableSet -> LinkableSet
unionLinkableSet :: LinkableSet -> LinkableSet -> LinkableSet
unionLinkableSet = forall a.
(a -> a -> a) -> ModuleEnv a -> ModuleEnv a -> ModuleEnv a
plusModuleEnv_C Linkable -> Linkable -> Linkable
go
where
go :: Linkable -> Linkable -> Linkable
go Linkable
l1 Linkable
l2
| Linkable -> UTCTime
linkableTime Linkable
l1 forall a. Ord a => a -> a -> Bool
> Linkable -> UTCTime
linkableTime Linkable
l2 = Linkable
l1
| Bool
otherwise = Linkable
l2
instance Outputable Linkable where
ppr :: Linkable -> SDoc
ppr (LM UTCTime
when_made Module
mod [Unlinked]
unlinkeds)
= (forall doc. IsLine doc => FilePath -> doc
text FilePath
"LinkableM" forall doc. IsLine doc => doc -> doc -> doc
<+> forall doc. IsLine doc => doc -> doc
parens (forall doc. IsLine doc => FilePath -> doc
text (forall a. Show a => a -> FilePath
show UTCTime
when_made)) forall doc. IsLine doc => doc -> doc -> doc
<+> forall a. Outputable a => a -> SDoc
ppr Module
mod)
forall doc. IsDoc doc => doc -> doc -> doc
$$ Int -> SDoc -> SDoc
nest Int
3 (forall a. Outputable a => a -> SDoc
ppr [Unlinked]
unlinkeds)
type ObjFile = FilePath
data Unlinked
= DotO ObjFile
| DotA FilePath
| DotDLL FilePath
| CoreBindings WholeCoreBindings
| LoadedBCOs [Unlinked]
| BCOs CompiledByteCode
[SptEntry]
instance Outputable Unlinked where
ppr :: Unlinked -> SDoc
ppr (DotO FilePath
path) = forall doc. IsLine doc => FilePath -> doc
text FilePath
"DotO" forall doc. IsLine doc => doc -> doc -> doc
<+> forall doc. IsLine doc => FilePath -> doc
text FilePath
path
ppr (DotA FilePath
path) = forall doc. IsLine doc => FilePath -> doc
text FilePath
"DotA" forall doc. IsLine doc => doc -> doc -> doc
<+> forall doc. IsLine doc => FilePath -> doc
text FilePath
path
ppr (DotDLL FilePath
path) = forall doc. IsLine doc => FilePath -> doc
text FilePath
"DotDLL" forall doc. IsLine doc => doc -> doc -> doc
<+> forall doc. IsLine doc => FilePath -> doc
text FilePath
path
ppr (BCOs CompiledByteCode
bcos [SptEntry]
spt) = forall doc. IsLine doc => FilePath -> doc
text FilePath
"BCOs" forall doc. IsLine doc => doc -> doc -> doc
<+> forall a. Outputable a => a -> SDoc
ppr CompiledByteCode
bcos forall doc. IsLine doc => doc -> doc -> doc
<+> forall a. Outputable a => a -> SDoc
ppr [SptEntry]
spt
ppr (LoadedBCOs{}) = forall doc. IsLine doc => FilePath -> doc
text FilePath
"LoadedBCOs"
ppr (CoreBindings {}) = forall doc. IsLine doc => FilePath -> doc
text FilePath
"FI"
data SptEntry = SptEntry Id Fingerprint
instance Outputable SptEntry where
ppr :: SptEntry -> SDoc
ppr (SptEntry Id
id Fingerprint
fpr) = forall a. Outputable a => a -> SDoc
ppr Id
id forall doc. IsLine doc => doc -> doc -> doc
<> forall doc. IsLine doc => doc
colon forall doc. IsLine doc => doc -> doc -> doc
<+> forall a. Outputable a => a -> SDoc
ppr Fingerprint
fpr
isObjectLinkable :: Linkable -> Bool
isObjectLinkable :: Linkable -> Bool
isObjectLinkable Linkable
l = Bool -> Bool
not (forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Unlinked]
unlinked) Bool -> Bool -> Bool
&& forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all Unlinked -> Bool
isObject [Unlinked]
unlinked
where unlinked :: [Unlinked]
unlinked = Linkable -> [Unlinked]
linkableUnlinked Linkable
l
linkableObjs :: Linkable -> [FilePath]
linkableObjs :: Linkable -> [FilePath]
linkableObjs Linkable
l = [ FilePath
f | DotO FilePath
f <- Linkable -> [Unlinked]
linkableUnlinked Linkable
l ]
isObject :: Unlinked -> Bool
isObject :: Unlinked -> Bool
isObject (DotO FilePath
_) = Bool
True
isObject (DotA FilePath
_) = Bool
True
isObject (DotDLL FilePath
_) = Bool
True
isObject Unlinked
_ = Bool
False
isInterpretable :: Unlinked -> Bool
isInterpretable :: Unlinked -> Bool
isInterpretable = Bool -> Bool
not forall b c a. (b -> c) -> (a -> b) -> a -> c
. Unlinked -> Bool
isObject
nameOfObject_maybe :: Unlinked -> Maybe FilePath
nameOfObject_maybe :: Unlinked -> Maybe FilePath
nameOfObject_maybe (DotO FilePath
fn) = forall a. a -> Maybe a
Just FilePath
fn
nameOfObject_maybe (DotA FilePath
fn) = forall a. a -> Maybe a
Just FilePath
fn
nameOfObject_maybe (DotDLL FilePath
fn) = forall a. a -> Maybe a
Just FilePath
fn
nameOfObject_maybe (CoreBindings {}) = forall a. Maybe a
Nothing
nameOfObject_maybe (LoadedBCOs{}) = forall a. Maybe a
Nothing
nameOfObject_maybe (BCOs {}) = forall a. Maybe a
Nothing
nameOfObject :: Unlinked -> FilePath
nameOfObject :: Unlinked -> FilePath
nameOfObject Unlinked
o = forall a. a -> Maybe a -> a
fromMaybe (forall a. HasCallStack => FilePath -> SDoc -> a
pprPanic FilePath
"nameOfObject" (forall a. Outputable a => a -> SDoc
ppr Unlinked
o)) (Unlinked -> Maybe FilePath
nameOfObject_maybe Unlinked
o)
byteCodeOfObject :: Unlinked -> [CompiledByteCode]
byteCodeOfObject :: Unlinked -> [CompiledByteCode]
byteCodeOfObject (BCOs CompiledByteCode
bc [SptEntry]
_) = [CompiledByteCode
bc]
byteCodeOfObject (LoadedBCOs [Unlinked]
ul) = forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap Unlinked -> [CompiledByteCode]
byteCodeOfObject [Unlinked]
ul
byteCodeOfObject Unlinked
other = forall a. HasCallStack => FilePath -> SDoc -> a
pprPanic FilePath
"byteCodeOfObject" (forall a. Outputable a => a -> SDoc
ppr Unlinked
other)
data LibrarySpec
= Objects [FilePath]
| Archive FilePath
| DLL String
| DLLPath FilePath
| Framework String
instance Outputable LibrarySpec where
ppr :: LibrarySpec -> SDoc
ppr (Objects [FilePath]
objs) = forall doc. IsLine doc => FilePath -> doc
text FilePath
"Objects" forall doc. IsLine doc => doc -> doc -> doc
<+> forall a. Outputable a => a -> SDoc
ppr (forall a b. (a -> b) -> [a] -> [b]
map (forall doc. IsLine doc => FilePath -> doc
text @SDoc) [FilePath]
objs)
ppr (Archive FilePath
a) = forall doc. IsLine doc => FilePath -> doc
text FilePath
"Archive" forall doc. IsLine doc => doc -> doc -> doc
<+> forall doc. IsLine doc => FilePath -> doc
text FilePath
a
ppr (DLL FilePath
s) = forall doc. IsLine doc => FilePath -> doc
text FilePath
"DLL" forall doc. IsLine doc => doc -> doc -> doc
<+> forall doc. IsLine doc => FilePath -> doc
text FilePath
s
ppr (DLLPath FilePath
f) = forall doc. IsLine doc => FilePath -> doc
text FilePath
"DLLPath" forall doc. IsLine doc => doc -> doc -> doc
<+> forall doc. IsLine doc => FilePath -> doc
text FilePath
f
ppr (Framework FilePath
s) = forall doc. IsLine doc => FilePath -> doc
text FilePath
"Framework" forall doc. IsLine doc => doc -> doc -> doc
<+> forall doc. IsLine doc => FilePath -> doc
text FilePath
s