----------------------------------------------------------------------------- -- -- Types for the Dynamic Linker -- -- (c) The University of Glasgow 2019 -- ----------------------------------------------------------------------------- module LinkerTypes ( DynLinker(..), PersistentLinkerState(..), LinkerUnitId, Linkable(..), Unlinked(..), SptEntry(..) ) where import GhcPrelude ( FilePath, String, show ) import Data.Time ( UTCTime ) import Data.Maybe ( Maybe ) import Control.Concurrent.MVar ( MVar ) import Module ( InstalledUnitId, Module ) import ByteCodeTypes ( ItblEnv, CompiledByteCode ) import Outputable import Var ( Id ) import GHC.Fingerprint.Type ( Fingerprint ) import NameEnv ( NameEnv ) import Name ( Name ) import GHCi.RemoteTypes ( ForeignHValue ) type ClosureEnv = NameEnv (Name, ForeignHValue) newtype DynLinker = DynLinker { dl_mpls :: MVar (Maybe PersistentLinkerState) } data PersistentLinkerState = PersistentLinkerState { -- Current global mapping from Names to their true values closure_env :: ClosureEnv, -- The current global mapping from RdrNames of DataCons to -- info table addresses. -- When a new Unlinked is linked into the running image, or an existing -- module in the image is replaced, the itbl_env must be updated -- appropriately. itbl_env :: !ItblEnv, -- The currently loaded interpreted modules (home package) bcos_loaded :: ![Linkable], -- And the currently-loaded compiled modules (home package) objs_loaded :: ![Linkable], -- The currently-loaded packages; always object code -- Held, as usual, in dependency order; though I am not sure if -- that is really important pkgs_loaded :: ![LinkerUnitId], -- we need to remember the name of previous temporary DLL/.so -- libraries so we can link them (see #10322) temp_sos :: ![(FilePath, String)] } -- TODO: Make this type more precise type LinkerUnitId = InstalledUnitId -- | Information we can use to dynamically link modules into the compiler data Linkable = LM { linkableTime :: UTCTime, -- ^ Time at which this linkable was built -- (i.e. when the bytecodes were produced, -- or the mod date on the files) linkableModule :: Module, -- ^ The linkable module itself linkableUnlinked :: [Unlinked] -- ^ Those files and chunks of code we have yet to link. -- -- INVARIANT: A valid linkable always has at least one 'Unlinked' item. -- If this list is empty, the Linkable represents a fake linkable, which -- is generated in HscNothing mode to avoid recompiling modules. -- -- ToDo: Do items get removed from this list when they get linked? } instance Outputable Linkable where ppr (LM when_made mod unlinkeds) = (text "LinkableM" <+> parens (text (show when_made)) <+> ppr mod) $$ nest 3 (ppr unlinkeds) -- | Objects which have yet to be linked by the compiler data Unlinked = DotO FilePath -- ^ An object file (.o) | DotA FilePath -- ^ Static archive file (.a) | DotDLL FilePath -- ^ Dynamically linked library file (.so, .dll, .dylib) | BCOs CompiledByteCode [SptEntry] -- ^ A byte-code object, lives only in memory. Also -- carries some static pointer table entries which -- should be loaded along with the BCOs. -- See Note [Grant plan for static forms] in -- StaticPtrTable. instance Outputable Unlinked where ppr (DotO path) = text "DotO" <+> text path ppr (DotA path) = text "DotA" <+> text path ppr (DotDLL path) = text "DotDLL" <+> text path ppr (BCOs bcos spt) = text "BCOs" <+> ppr bcos <+> ppr spt -- | An entry to be inserted into a module's static pointer table. -- See Note [Grand plan for static forms] in StaticPtrTable. data SptEntry = SptEntry Id Fingerprint instance Outputable SptEntry where ppr (SptEntry id fpr) = ppr id <> colon <+> ppr fpr