ghci/LinkerTypes.hs

    -----------------------------------------------------------------------------
    --
    -- 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