Hannes Siebenhandl pushed to branch wip/fendor/linkable-usage at Glasgow Haskell Compiler / GHC

Commits:

25 changed files:

Changes:

  • compiler/GHC/ByteCode/Binary.hs
    1
    +{-# LANGUAGE MultiWayIf #-}
    
    2
    +{-# LANGUAGE RecordWildCards #-}
    
    3
    +{-# OPTIONS_GHC -Wno-orphans #-}
    
    4
    +
    
    5
    +module GHC.ByteCode.Binary (
    
    6
    +  -- * ByteCode objects on disk and intermediate representations
    
    7
    +  OnDiskModuleByteCode(..),
    
    8
    +  BytecodeLibX(..),
    
    9
    +  BytecodeLib,
    
    10
    +  OnDiskBytecodeLib,
    
    11
    +  InterpreterLibrary(..),
    
    12
    +  InterpreterLibraryContents(..),
    
    13
    +  -- * Binary 'Name' serializers
    
    14
    +  BytecodeNameEnv(..),
    
    15
    +  addBinNameWriter,
    
    16
    +  addBinNameReader,
    
    17
    +) where
    
    18
    +
    
    19
    +import GHC.Prelude
    
    20
    +
    
    21
    +import GHC.ByteCode.Types
    
    22
    +import GHC.Data.FastString
    
    23
    +import GHC.Types.Name
    
    24
    +import GHC.Types.Name.Cache
    
    25
    +import GHC.Types.Name.Env
    
    26
    +import GHC.Types.SrcLoc
    
    27
    +import GHC.Unit.Types
    
    28
    +import GHC.Utils.Binary
    
    29
    +import GHC.Utils.Exception
    
    30
    +import GHC.Utils.Panic
    
    31
    +import GHC.Utils.Outputable
    
    32
    +import GHC.Utils.Fingerprint (Fingerprint)
    
    33
    +
    
    34
    +import Control.Monad
    
    35
    +import Data.Binary qualified as Binary
    
    36
    +import Data.ByteString (ByteString)
    
    37
    +import Data.Foldable
    
    38
    +import Data.IORef
    
    39
    +import Data.Proxy
    
    40
    +import Data.Word
    
    41
    +import System.IO.Unsafe (unsafeInterleaveIO)
    
    42
    +
    
    43
    +-- | The on-disk representation of a bytecode object for a specific module.
    
    44
    +--
    
    45
    +-- This is the representation which we serialise and write to disk.
    
    46
    +-- The difference from 'ModuleByteCode' is that the contents of the object files
    
    47
    +-- contained by 'ModuleByteCode' are stored in-memory rather than as file paths to
    
    48
    +-- temporary files.
    
    49
    +data OnDiskModuleByteCode = OnDiskModuleByteCode { odgbc_module :: Module
    
    50
    +                                                 , odgbc_hash :: Fingerprint
    
    51
    +                                                 , odgbc_compiled_byte_code :: CompiledByteCode
    
    52
    +                                                 , odgbc_foreign :: [ByteString]  -- ^ Contents of object files
    
    53
    +                                                 }
    
    54
    +
    
    55
    +type OnDiskBytecodeLib = BytecodeLibX (Maybe InterpreterLibraryContents)
    
    56
    +
    
    57
    +instance Outputable a => Outputable (BytecodeLibX a) where
    
    58
    +  ppr (BytecodeLib {..}) = vcat [
    
    59
    +    (text "BytecodeLib" <+> ppr bytecodeLibUnitId),
    
    60
    +    (text "Files" <+> ppr bytecodeLibFiles),
    
    61
    +    (text "Foreign" <+> ppr bytecodeLibForeign) ]
    
    62
    +
    
    63
    +type BytecodeLib = BytecodeLibX (Maybe InterpreterLibrary)
    
    64
    +
    
    65
    +-- | A bytecode library is a collection of CompiledByteCode objects and a .so file containing the combination of foreign stubs
    
    66
    +data BytecodeLibX a = BytecodeLib {
    
    67
    +    bytecodeLibUnitId :: UnitId,
    
    68
    +    bytecodeLibFiles :: [CompiledByteCode],
    
    69
    +    bytecodeLibForeign :: a -- A library file containing the combination of foreign stubs. (Ie arising from CApiFFI)
    
    70
    +}
    
    71
    +
    
    72
    +data InterpreterLibrary = InterpreterSharedObject { getSharedObjectFilePath :: FilePath, getSharedObjectDir :: FilePath, getSharedObjectLibName :: String }
    
    73
    +                         | InterpreterStaticObjects { getStaticObjects :: [FilePath] }
    
    74
    +
    
    75
    +
    
    76
    +instance Outputable InterpreterLibrary where
    
    77
    +  ppr (InterpreterSharedObject path dir name) = text "SharedObject" <+> text path <+> text dir <+> text name
    
    78
    +  ppr (InterpreterStaticObjects paths) = text "StaticObjects" <+> text (show paths)
    
    79
    +
    
    80
    +
    
    81
    +data InterpreterLibraryContents = InterpreterLibrarySharedContents { interpreterLibraryContents :: ByteString }
    
    82
    +                                | InterpreterLibraryStaticContents { interpreterLibraryStaticContents :: [ByteString] }
    
    83
    +
    
    84
    +instance Binary InterpreterLibraryContents where
    
    85
    +  get bh = do
    
    86
    +    t <- getByte bh
    
    87
    +    case t of
    
    88
    +      0 -> InterpreterLibrarySharedContents <$> get bh
    
    89
    +      1 -> InterpreterLibraryStaticContents <$> get bh
    
    90
    +      _ -> panic "Binary InterpreterLibraryContents: invalid byte"
    
    91
    +  put_ bh (InterpreterLibrarySharedContents contents) = do
    
    92
    +    putByte bh 0
    
    93
    +    put_ bh contents
    
    94
    +  put_ bh (InterpreterLibraryStaticContents contents) = do
    
    95
    +    putByte bh 1
    
    96
    +    put_ bh contents
    
    97
    +
    
    98
    +instance Binary OnDiskModuleByteCode where
    
    99
    +  get bh = do
    
    100
    +    odgbc_hash <- get bh
    
    101
    +    odgbc_module <- get bh
    
    102
    +    odgbc_compiled_byte_code <- get bh
    
    103
    +    odgbc_foreign <- get bh
    
    104
    +    pure OnDiskModuleByteCode {..}
    
    105
    +
    
    106
    +  put_ bh OnDiskModuleByteCode {..} = do
    
    107
    +    put_ bh odgbc_hash
    
    108
    +    put_ bh odgbc_module
    
    109
    +    put_ bh odgbc_compiled_byte_code
    
    110
    +    put_ bh odgbc_foreign
    
    111
    +
    
    112
    +instance Binary OnDiskBytecodeLib where
    
    113
    +  get bh = do
    
    114
    +    bytecodeLibUnitId <- get bh
    
    115
    +    bytecodeLibFiles <- get bh
    
    116
    +    bytecodeLibForeign <- get bh
    
    117
    +    pure BytecodeLib {..}
    
    118
    +
    
    119
    +  put_ bh BytecodeLib {..} = do
    
    120
    +    put_ bh bytecodeLibUnitId
    
    121
    +    put_ bh bytecodeLibFiles
    
    122
    +    put_ bh bytecodeLibForeign
    
    123
    +
    
    124
    +instance Binary CompiledByteCode where
    
    125
    +  get bh = do
    
    126
    +    bc_bcos <- get bh
    
    127
    +    bc_itbls_len <- get bh
    
    128
    +    bc_itbls <- replicateM bc_itbls_len $ do
    
    129
    +      nm <- getViaBinName bh
    
    130
    +      itbl <- get bh
    
    131
    +      pure (nm, itbl)
    
    132
    +    bc_strs_len <- get bh
    
    133
    +    bc_strs <-
    
    134
    +      replicateM bc_strs_len $ (,) <$> getViaBinName bh <*> get bh
    
    135
    +    bc_breaks <- get bh
    
    136
    +    bc_spt_entries <- get bh
    
    137
    +    return $
    
    138
    +      CompiledByteCode
    
    139
    +        { bc_bcos,
    
    140
    +          bc_itbls,
    
    141
    +          bc_strs,
    
    142
    +          bc_breaks,
    
    143
    +          bc_spt_entries
    
    144
    +        }
    
    145
    +
    
    146
    +  put_ bh CompiledByteCode {..} = do
    
    147
    +    put_ bh bc_bcos
    
    148
    +    put_ bh $ length bc_itbls
    
    149
    +    for_ bc_itbls $ \(nm, itbl) -> do
    
    150
    +      putViaBinName bh nm
    
    151
    +      put_ bh itbl
    
    152
    +    put_ bh $ length bc_strs
    
    153
    +    for_ bc_strs $ \(nm, str) -> putViaBinName bh nm *> put_ bh str
    
    154
    +    put_ bh bc_breaks
    
    155
    +    put_ bh bc_spt_entries
    
    156
    +
    
    157
    +instance Binary UnlinkedBCO where
    
    158
    +  get bh =
    
    159
    +    UnlinkedBCO
    
    160
    +      <$> getViaBinName bh
    
    161
    +      <*> get bh
    
    162
    +      <*> (Binary.decode <$> get bh)
    
    163
    +      <*> (Binary.decode <$> get bh)
    
    164
    +      <*> get bh
    
    165
    +      <*> get bh
    
    166
    +
    
    167
    +  put_ bh UnlinkedBCO {..} = do
    
    168
    +    putViaBinName bh unlinkedBCOName
    
    169
    +    put_ bh unlinkedBCOArity
    
    170
    +    put_ bh $ Binary.encode unlinkedBCOInstrs
    
    171
    +    put_ bh $ Binary.encode unlinkedBCOBitmap
    
    172
    +    put_ bh unlinkedBCOLits
    
    173
    +    put_ bh unlinkedBCOPtrs
    
    174
    +
    
    175
    +instance Binary BCOPtr where
    
    176
    +  get bh = do
    
    177
    +    t <- getByte bh
    
    178
    +    case t of
    
    179
    +      0 -> BCOPtrName <$> getViaBinName bh
    
    180
    +      1 -> BCOPtrPrimOp <$> get bh
    
    181
    +      2 -> BCOPtrBCO <$> get bh
    
    182
    +      3 -> BCOPtrBreakArray <$> get bh
    
    183
    +      _ -> panic "Binary BCOPtr: invalid byte"
    
    184
    +
    
    185
    +  put_ bh ptr = case ptr of
    
    186
    +    BCOPtrName nm -> putByte bh 0 *> putViaBinName bh nm
    
    187
    +    BCOPtrPrimOp op -> putByte bh 1 *> put_ bh op
    
    188
    +    BCOPtrBCO bco -> putByte bh 2 *> put_ bh bco
    
    189
    +    BCOPtrBreakArray info_mod -> putByte bh 3 *> put_ bh info_mod
    
    190
    +
    
    191
    +instance Binary BCONPtr where
    
    192
    +  get bh = do
    
    193
    +    t <- getByte bh
    
    194
    +    case t of
    
    195
    +      0 -> BCONPtrWord . fromIntegral <$> (get bh :: IO Word64)
    
    196
    +      1 -> BCONPtrLbl <$> get bh
    
    197
    +      2 -> BCONPtrItbl <$> getViaBinName bh
    
    198
    +      3 -> BCONPtrAddr <$> getViaBinName bh
    
    199
    +      4 -> BCONPtrStr <$> get bh
    
    200
    +      5 -> BCONPtrFS <$> get bh
    
    201
    +      6 -> BCONPtrFFIInfo <$> get bh
    
    202
    +      7 -> BCONPtrCostCentre <$> get bh
    
    203
    +      _ -> panic "Binary BCONPtr: invalid byte"
    
    204
    +
    
    205
    +  put_ bh ptr = case ptr of
    
    206
    +    BCONPtrWord lit -> putByte bh 0 *> put_ bh (fromIntegral lit :: Word64)
    
    207
    +    BCONPtrLbl sym -> putByte bh 1 *> put_ bh sym
    
    208
    +    BCONPtrItbl nm -> putByte bh 2 *> putViaBinName bh nm
    
    209
    +    BCONPtrAddr nm -> putByte bh 3 *> putViaBinName bh nm
    
    210
    +    BCONPtrStr str -> putByte bh 4 *> put_ bh str
    
    211
    +    BCONPtrFS fs -> putByte bh 5 *> put_ bh fs
    
    212
    +    BCONPtrFFIInfo ffi -> putByte bh 6 *> put_ bh ffi
    
    213
    +    BCONPtrCostCentre ibi -> putByte bh 7 *> put_ bh ibi
    
    214
    +
    
    215
    +newtype BinName = BinName {unBinName :: Name}
    
    216
    +
    
    217
    +getViaBinName :: ReadBinHandle -> IO Name
    
    218
    +getViaBinName bh = case findUserDataReader Proxy bh of
    
    219
    +  BinaryReader f -> unBinName <$> f bh
    
    220
    +
    
    221
    +putViaBinName :: WriteBinHandle -> Name -> IO ()
    
    222
    +putViaBinName bh nm = case findUserDataWriter Proxy bh of
    
    223
    +  BinaryWriter f -> f bh $ BinName nm
    
    224
    +
    
    225
    +-- | NameEnv for serialising Names in 'CompiledByteCode'.
    
    226
    +--
    
    227
    +-- See Note [Serializing Names in bytecode]
    
    228
    +
    
    229
    +data BytecodeNameEnv = ByteCodeNameEnv { _bytecode_next_id :: !Word64
    
    230
    +                                       , _bytecode_name_subst :: NameEnv Word64
    
    231
    +                                       }
    
    232
    +
    
    233
    +addBinNameWriter :: WriteBinHandle -> IO WriteBinHandle
    
    234
    +addBinNameWriter bh' = do
    
    235
    +  env_ref <- newIORef (ByteCodeNameEnv 0 emptyNameEnv)
    
    236
    +  evaluate
    
    237
    +    $ flip addWriterToUserData bh'
    
    238
    +    $ BinaryWriter
    
    239
    +    $ \bh (BinName nm) ->
    
    240
    +      if
    
    241
    +        | isExternalName nm -> do
    
    242
    +            putByte bh 0
    
    243
    +            put_ bh nm
    
    244
    +        | otherwise -> do
    
    245
    +            putByte bh 1
    
    246
    +            key <- getBinNameKey env_ref nm
    
    247
    +            -- Delimit the OccName from the deterministic counter to keep the
    
    248
    +            -- encoding injective, avoiding collisions like "foo1" vs "foo#1".
    
    249
    +            put_ bh (occNameFS (occName nm) `appendFS` mkFastString ('#' : show key))
    
    250
    +  where
    
    251
    +    -- Find a deterministic key for local names. This
    
    252
    +    getBinNameKey ref name = do
    
    253
    +      atomicModifyIORef ref (\b@(ByteCodeNameEnv next subst) ->
    
    254
    +        case lookupNameEnv subst name of
    
    255
    +          Just idx -> (b, idx)
    
    256
    +          Nothing  -> (ByteCodeNameEnv (next + 1) (extendNameEnv subst name next), next))
    
    257
    +
    
    258
    +addBinNameReader :: NameCache -> ReadBinHandle -> IO ReadBinHandle
    
    259
    +addBinNameReader nc bh' = do
    
    260
    +  env_ref <- newIORef emptyOccEnv
    
    261
    +  pure $ flip addReaderToUserData bh' $ BinaryReader $ \bh -> do
    
    262
    +    t <- getByte bh
    
    263
    +    case t of
    
    264
    +      0 -> do
    
    265
    +        nm <- get bh
    
    266
    +        pure $ BinName nm
    
    267
    +      1 -> do
    
    268
    +        occ <- mkVarOccFS <$> get bh
    
    269
    +        -- We don't want to get a new unique from the NameCache each time we
    
    270
    +        -- see a name.
    
    271
    +        nm' <- unsafeInterleaveIO $ do
    
    272
    +          u <- takeUniqFromNameCache nc
    
    273
    +          evaluate $ mkInternalName u occ noSrcSpan
    
    274
    +        fmap BinName $ atomicModifyIORef' env_ref $ \env ->
    
    275
    +          case lookupOccEnv env occ of
    
    276
    +            Just nm -> (env, nm)
    
    277
    +            _ -> nm' `seq` (extendOccEnv env occ nm', nm')
    
    278
    +      _ -> panic "Binary BinName: invalid byte"
    
    279
    +
    
    280
    +-- Note [Serializing Names in bytecode]
    
    281
    +-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    282
    +-- The bytecode related types contain various Names which we need to
    
    283
    +-- serialize. Unfortunately, we can't directly use the Binary instance
    
    284
    +-- of Name: it is only meant to be used for serializing external Names
    
    285
    +-- in BinIface logic, but bytecode does contain internal Names.
    
    286
    +--
    
    287
    +-- We also need to maintain the invariant that: any pair of internal
    
    288
    +-- Names with equal/different uniques must also be deserialized to
    
    289
    +-- have the same equality. Therefore when we write the names to the interface, we
    
    290
    +-- use an incrementing counter to give each local name it's own unique number. A substitution
    
    291
    +-- is maintained to give each occurence of the Name the same unique key. When the interface
    
    292
    +-- is read, a reverse mapping is used from these unique keys to a Name.
    
    293
    +--

  • compiler/GHC/ByteCode/Recomp/Binary.hs
    1
    +module GHC.ByteCode.Recomp.Binary (
    
    2
    +  -- * Fingerprinting ByteCode objects
    
    3
    +  computeFingerprint,
    
    4
    +) where
    
    5
    +
    
    6
    +import GHC.Prelude
    
    7
    +
    
    8
    +import GHC.ByteCode.Binary (addBinNameWriter)
    
    9
    +import GHC.Iface.Binary
    
    10
    +import GHC.Iface.Recomp.Binary (putNameLiterally, fingerprintBinMem)
    
    11
    +import GHC.Types.Name
    
    12
    +import GHC.Utils.Fingerprint
    
    13
    +import GHC.Utils.Binary
    
    14
    +
    
    15
    +import System.IO.Unsafe
    
    16
    +
    
    17
    +-- | Create a 'Fingerprint' using the appropriate serializers
    
    18
    +-- for 'ModuleByteCode'.
    
    19
    +--
    
    20
    +computeFingerprint :: (Binary a)
    
    21
    +                   => (WriteBinHandle -> Name -> IO ())
    
    22
    +                   -> a
    
    23
    +                   -> Fingerprint
    
    24
    +computeFingerprint put_nonbinding_name a = unsafePerformIO $ do
    
    25
    +    bh <- fmap set_user_data $ openBinMem (3*1024) -- just less than a block
    
    26
    +    bh' <- addBinNameWriter bh
    
    27
    +    putWithUserData QuietBinIFace NormalCompression bh' a
    
    28
    +    fingerprintBinMem bh'
    
    29
    +  where
    
    30
    +    set_user_data bh = setWriterUserData bh $ mkWriterUserData
    
    31
    +      [ mkSomeBinaryWriter $ mkWriter put_nonbinding_name
    
    32
    +      , mkSomeBinaryWriter $ simpleBindingNameWriter $ mkWriter putNameLiterally
    
    33
    +      , mkSomeBinaryWriter $ mkWriter putFS
    
    34
    +      ]

  • compiler/GHC/ByteCode/Serialize.hs
    ... ... @@ -2,11 +2,11 @@
    2 2
     {-# LANGUAGE RecordWildCards #-}
    
    3 3
     -- Orphans are here since the Binary instances use an ad-hoc means of serialising
    
    4 4
     -- names which we don't want to pollute the rest of the codebase with.
    
    5
    -{-# OPTIONS_GHC -Wno-orphans #-}
    
    6 5
     {- | This module implements the serialization of bytecode objects to and from disk.
    
    7 6
     -}
    
    8 7
     module GHC.ByteCode.Serialize
    
    9
    -  ( writeBinByteCode, readBinByteCode, ModuleByteCode(..)
    
    8
    +  ( writeBinByteCode, readBinByteCode
    
    9
    +  , ModuleByteCode(..)
    
    10 10
       , BytecodeLibX(..)
    
    11 11
       , BytecodeLib
    
    12 12
       , OnDiskBytecodeLib
    
    ... ... @@ -14,41 +14,34 @@ module GHC.ByteCode.Serialize
    14 14
       , InterpreterLibraryContents(..)
    
    15 15
       , writeBytecodeLib
    
    16 16
       , readBytecodeLib
    
    17
    +  , mkModuleByteCode
    
    18
    +  , fingerprintModuleByteCodeContents
    
    17 19
       , decodeOnDiskModuleByteCode
    
    18 20
       , decodeOnDiskBytecodeLib
    
    19 21
       )
    
    20 22
     where
    
    21 23
     
    
    22
    -import Control.Monad
    
    23
    -import Data.Binary qualified as Binary
    
    24
    -import Data.Foldable
    
    25
    -import Data.IORef
    
    26
    -import Data.Proxy
    
    27
    -import Data.Word
    
    24
    +import GHC.Prelude
    
    25
    +
    
    26
    +import GHC.ByteCode.Binary
    
    28 27
     import GHC.ByteCode.Types
    
    29
    -import GHC.Data.FastString
    
    28
    +import GHC.ByteCode.Recomp.Binary (computeFingerprint)
    
    29
    +import Data.ByteString (ByteString)
    
    30 30
     import GHC.Driver.Env
    
    31
    +import GHC.Driver.DynFlags
    
    31 32
     import GHC.Iface.Binary
    
    32
    -import GHC.Prelude
    
    33
    -import GHC.Types.Name
    
    34
    -import GHC.Types.Name.Cache
    
    35
    -import GHC.Types.SrcLoc
    
    33
    +import GHC.Iface.Recomp.Binary (putNameLiterally)
    
    34
    +import GHC.Linker.Types
    
    35
    +import GHC.Unit.Types
    
    36 36
     import GHC.Utils.Binary
    
    37
    -import GHC.Utils.Exception
    
    38
    -import GHC.Utils.Panic
    
    39 37
     import GHC.Utils.TmpFs
    
    40
    -import System.FilePath
    
    41
    -import GHC.Unit.Types
    
    42
    -import GHC.Driver.DynFlags
    
    43
    -import System.Directory
    
    44
    -import Data.ByteString (ByteString)
    
    38
    +import GHC.Utils.Logger
    
    39
    +import GHC.Utils.Fingerprint (Fingerprint)
    
    40
    +
    
    45 41
     import qualified Data.ByteString as BS
    
    46 42
     import Data.Traversable
    
    47
    -import GHC.Utils.Logger
    
    48
    -import GHC.Linker.Types
    
    49
    -import System.IO.Unsafe (unsafeInterleaveIO)
    
    50
    -import GHC.Utils.Outputable
    
    51
    -import GHC.Types.Name.Env
    
    43
    +import System.Directory
    
    44
    +import System.FilePath
    
    52 45
     
    
    53 46
     {- Note [Overview of persistent bytecode]
    
    54 47
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    ... ... @@ -88,74 +81,6 @@ See Note [Recompilation avoidance with bytecode objects]
    88 81
     
    
    89 82
     -}
    
    90 83
     
    
    91
    --- | The on-disk representation of a bytecode object for a specific module.
    
    92
    ---
    
    93
    --- This is the representation which we serialise and write to disk.
    
    94
    --- The difference from 'ModuleByteCode' is that the contents of the object files
    
    95
    --- contained by 'ModuleByteCode' are stored in-memory rather than as file paths to
    
    96
    --- temporary files.
    
    97
    -data OnDiskModuleByteCode = OnDiskModuleByteCode { odgbc_module :: Module
    
    98
    -                                                 , odgbc_compiled_byte_code :: CompiledByteCode
    
    99
    -                                                 , odgbc_foreign :: [ByteString]  -- ^ Contents of object files
    
    100
    -                                                 }
    
    101
    -
    
    102
    -type OnDiskBytecodeLib = BytecodeLibX (Maybe InterpreterLibraryContents)
    
    103
    -
    
    104
    -instance Outputable a => Outputable (BytecodeLibX a) where
    
    105
    -  ppr (BytecodeLib {..}) = vcat [
    
    106
    -    (text "BytecodeLib" <+> ppr bytecodeLibUnitId),
    
    107
    -    (text "Files" <+> ppr bytecodeLibFiles),
    
    108
    -    (text "Foreign" <+> ppr bytecodeLibForeign) ]
    
    109
    -
    
    110
    -type BytecodeLib = BytecodeLibX (Maybe InterpreterLibrary)
    
    111
    -
    
    112
    --- | A bytecode library is a collection of CompiledByteCode objects and a .so file containing the combination of foreign stubs
    
    113
    -data BytecodeLibX a = BytecodeLib {
    
    114
    -    bytecodeLibUnitId :: UnitId,
    
    115
    -    bytecodeLibFiles :: [CompiledByteCode],
    
    116
    -    bytecodeLibForeign :: a -- A library file containing the combination of foreign stubs. (Ie arising from CApiFFI)
    
    117
    -}
    
    118
    -
    
    119
    -data InterpreterLibrary = InterpreterSharedObject { getSharedObjectFilePath :: FilePath, getSharedObjectDir :: FilePath, getSharedObjectLibName :: String }
    
    120
    -                         | InterpreterStaticObjects { getStaticObjects :: [FilePath] }
    
    121
    -
    
    122
    -
    
    123
    -instance Outputable InterpreterLibrary where
    
    124
    -  ppr (InterpreterSharedObject path dir name) = text "SharedObject" <+> text path <+> text dir <+> text name
    
    125
    -  ppr (InterpreterStaticObjects paths) = text "StaticObjects" <+> text (show paths)
    
    126
    -
    
    127
    -
    
    128
    -data InterpreterLibraryContents = InterpreterLibrarySharedContents { interpreterLibraryContents :: ByteString }
    
    129
    -                                | InterpreterLibraryStaticContents { interpreterLibraryStaticContents :: [ByteString] }
    
    130
    -
    
    131
    -instance Binary InterpreterLibraryContents where
    
    132
    -  get bh = do
    
    133
    -    t <- getByte bh
    
    134
    -    case t of
    
    135
    -      0 -> InterpreterLibrarySharedContents <$> get bh
    
    136
    -      1 -> InterpreterLibraryStaticContents <$> get bh
    
    137
    -      _ -> panic "Binary InterpreterLibraryContents: invalid byte"
    
    138
    -  put_ bh (InterpreterLibrarySharedContents contents) = do
    
    139
    -    putByte bh 0
    
    140
    -    put_ bh contents
    
    141
    -  put_ bh (InterpreterLibraryStaticContents contents) = do
    
    142
    -    putByte bh 1
    
    143
    -    put_ bh contents
    
    144
    -
    
    145
    -instance Binary OnDiskBytecodeLib where
    
    146
    -  get bh = do
    
    147
    -    bytecodeLibUnitId <- get bh
    
    148
    -    bytecodeLibFiles <- get bh
    
    149
    -    bytecodeLibForeign <- get bh
    
    150
    -    pure BytecodeLib {..}
    
    151
    -
    
    152
    -  put_ bh BytecodeLib {..} = do
    
    153
    -    put_ bh bytecodeLibUnitId
    
    154
    -    put_ bh bytecodeLibFiles
    
    155
    -    put_ bh bytecodeLibForeign
    
    156
    -
    
    157
    -
    
    158
    -
    
    159 84
     writeBytecodeLib :: BytecodeLib -> FilePath -> IO ()
    
    160 85
     writeBytecodeLib lib path = do
    
    161 86
       odbco <- encodeBytecodeLib lib
    
    ... ... @@ -168,22 +93,10 @@ writeBytecodeLib lib path = do
    168 93
     readBytecodeLib :: HscEnv -> FilePath -> IO OnDiskBytecodeLib
    
    169 94
     readBytecodeLib hsc_env path = do
    
    170 95
       bh' <- readBinMem path
    
    171
    -  bh <- addBinNameReader hsc_env bh'
    
    96
    +  bh <- addBinNameReader (hsc_NC hsc_env) bh'
    
    172 97
       res <- getWithUserData (hsc_NC hsc_env) bh
    
    173 98
       pure res
    
    174 99
     
    
    175
    -instance Binary OnDiskModuleByteCode where
    
    176
    -  get bh = do
    
    177
    -    odgbc_module <- get bh
    
    178
    -    odgbc_compiled_byte_code <- get bh
    
    179
    -    odgbc_foreign <- get bh
    
    180
    -    pure OnDiskModuleByteCode {..}
    
    181
    -
    
    182
    -  put_ bh OnDiskModuleByteCode {..} = do
    
    183
    -    put_ bh odgbc_module
    
    184
    -    put_ bh odgbc_compiled_byte_code
    
    185
    -    put_ bh odgbc_foreign
    
    186
    -
    
    187 100
     -- | Convert an 'OnDiskModuleByteCode' to an 'ModuleByteCode'.
    
    188 101
     -- 'OnDiskModuleByteCode' is the representation which we read from a file,
    
    189 102
     -- the 'ModuleByteCode' is the representation which is manipulated by program logic.
    
    ... ... @@ -198,7 +111,8 @@ decodeOnDiskModuleByteCode hsc_env odbco = do
    198 111
       pure $ ModuleByteCode {
    
    199 112
         gbc_module = odgbc_module odbco,
    
    200 113
         gbc_compiled_byte_code = odgbc_compiled_byte_code odbco,
    
    201
    -    gbc_foreign_files = foreign_files
    
    114
    +    gbc_foreign_files = foreign_files,
    
    115
    +    gbc_hash = odgbc_hash odbco
    
    202 116
        }
    
    203 117
     
    
    204 118
     decodeOnDiskBytecodeLib :: HscEnv -> OnDiskBytecodeLib -> IO BytecodeLib
    
    ... ... @@ -257,7 +171,8 @@ encodeOnDiskModuleByteCode bco = do
    257 171
       pure $ OnDiskModuleByteCode {
    
    258 172
         odgbc_module = gbc_module bco,
    
    259 173
         odgbc_compiled_byte_code = gbc_compiled_byte_code bco,
    
    260
    -    odgbc_foreign = foreign_contents
    
    174
    +    odgbc_foreign = foreign_contents,
    
    175
    +    odgbc_hash = gbc_hash bco
    
    261 176
        }
    
    262 177
     
    
    263 178
     -- | Read a 'ModuleByteCode' from a file.
    
    ... ... @@ -269,7 +184,7 @@ readBinByteCode hsc_env f = do
    269 184
     readOnDiskModuleByteCode :: HscEnv -> FilePath -> IO OnDiskModuleByteCode
    
    270 185
     readOnDiskModuleByteCode hsc_env f = do
    
    271 186
       bh' <- readBinMem f
    
    272
    -  bh <- addBinNameReader hsc_env bh'
    
    187
    +  bh <- addBinNameReader (hsc_NC hsc_env) bh'
    
    273 188
       getWithUserData (hsc_NC hsc_env) bh
    
    274 189
     
    
    275 190
     -- | Write a 'ModuleByteCode' to a file.
    
    ... ... @@ -282,169 +197,12 @@ writeBinByteCode f cbc = do
    282 197
       putWithUserData QuietBinIFace NormalCompression bh odbco
    
    283 198
       writeBinMem bh f
    
    284 199
     
    
    285
    -instance Binary CompiledByteCode where
    
    286
    -  get bh = do
    
    287
    -    bc_bcos <- get bh
    
    288
    -    bc_itbls_len <- get bh
    
    289
    -    bc_itbls <- replicateM bc_itbls_len $ do
    
    290
    -      nm <- getViaBinName bh
    
    291
    -      itbl <- get bh
    
    292
    -      pure (nm, itbl)
    
    293
    -    bc_strs_len <- get bh
    
    294
    -    bc_strs <-
    
    295
    -      replicateM bc_strs_len $ (,) <$> getViaBinName bh <*> get bh
    
    296
    -    bc_breaks <- get bh
    
    297
    -    bc_spt_entries <- get bh
    
    298
    -    return $
    
    299
    -      CompiledByteCode
    
    300
    -        { bc_bcos,
    
    301
    -          bc_itbls,
    
    302
    -          bc_strs,
    
    303
    -          bc_breaks,
    
    304
    -          bc_spt_entries
    
    305
    -        }
    
    306
    -
    
    307
    -  put_ bh CompiledByteCode {..} = do
    
    308
    -    put_ bh bc_bcos
    
    309
    -    put_ bh $ length bc_itbls
    
    310
    -    for_ bc_itbls $ \(nm, itbl) -> do
    
    311
    -      putViaBinName bh nm
    
    312
    -      put_ bh itbl
    
    313
    -    put_ bh $ length bc_strs
    
    314
    -    for_ bc_strs $ \(nm, str) -> putViaBinName bh nm *> put_ bh str
    
    315
    -    put_ bh bc_breaks
    
    316
    -    put_ bh bc_spt_entries
    
    317
    -
    
    318
    -instance Binary UnlinkedBCO where
    
    319
    -  get bh =
    
    320
    -    UnlinkedBCO
    
    321
    -      <$> getViaBinName bh
    
    322
    -      <*> get bh
    
    323
    -      <*> (Binary.decode <$> get bh)
    
    324
    -      <*> (Binary.decode <$> get bh)
    
    325
    -      <*> get bh
    
    326
    -      <*> get bh
    
    327
    -
    
    328
    -  put_ bh UnlinkedBCO {..} = do
    
    329
    -    putViaBinName bh unlinkedBCOName
    
    330
    -    put_ bh unlinkedBCOArity
    
    331
    -    put_ bh $ Binary.encode unlinkedBCOInstrs
    
    332
    -    put_ bh $ Binary.encode unlinkedBCOBitmap
    
    333
    -    put_ bh unlinkedBCOLits
    
    334
    -    put_ bh unlinkedBCOPtrs
    
    200
    +mkModuleByteCode :: Module -> CompiledByteCode -> [FilePath] -> IO ModuleByteCode
    
    201
    +mkModuleByteCode modl cbc foreign_files = do
    
    202
    +  !bcos_hash <- fingerprintModuleByteCodeContents modl cbc foreign_files
    
    203
    +  return $! ModuleByteCode modl cbc foreign_files bcos_hash
    
    335 204
     
    
    336
    -instance Binary BCOPtr where
    
    337
    -  get bh = do
    
    338
    -    t <- getByte bh
    
    339
    -    case t of
    
    340
    -      0 -> BCOPtrName <$> getViaBinName bh
    
    341
    -      1 -> BCOPtrPrimOp <$> get bh
    
    342
    -      2 -> BCOPtrBCO <$> get bh
    
    343
    -      3 -> BCOPtrBreakArray <$> get bh
    
    344
    -      _ -> panic "Binary BCOPtr: invalid byte"
    
    345
    -
    
    346
    -  put_ bh ptr = case ptr of
    
    347
    -    BCOPtrName nm -> putByte bh 0 *> putViaBinName bh nm
    
    348
    -    BCOPtrPrimOp op -> putByte bh 1 *> put_ bh op
    
    349
    -    BCOPtrBCO bco -> putByte bh 2 *> put_ bh bco
    
    350
    -    BCOPtrBreakArray info_mod -> putByte bh 3 *> put_ bh info_mod
    
    351
    -
    
    352
    -instance Binary BCONPtr where
    
    353
    -  get bh = do
    
    354
    -    t <- getByte bh
    
    355
    -    case t of
    
    356
    -      0 -> BCONPtrWord . fromIntegral <$> (get bh :: IO Word64)
    
    357
    -      1 -> BCONPtrLbl <$> get bh
    
    358
    -      2 -> BCONPtrItbl <$> getViaBinName bh
    
    359
    -      3 -> BCONPtrAddr <$> getViaBinName bh
    
    360
    -      4 -> BCONPtrStr <$> get bh
    
    361
    -      5 -> BCONPtrFS <$> get bh
    
    362
    -      6 -> BCONPtrFFIInfo <$> get bh
    
    363
    -      7 -> BCONPtrCostCentre <$> get bh
    
    364
    -      _ -> panic "Binary BCONPtr: invalid byte"
    
    365
    -
    
    366
    -  put_ bh ptr = case ptr of
    
    367
    -    BCONPtrWord lit -> putByte bh 0 *> put_ bh (fromIntegral lit :: Word64)
    
    368
    -    BCONPtrLbl sym -> putByte bh 1 *> put_ bh sym
    
    369
    -    BCONPtrItbl nm -> putByte bh 2 *> putViaBinName bh nm
    
    370
    -    BCONPtrAddr nm -> putByte bh 3 *> putViaBinName bh nm
    
    371
    -    BCONPtrStr str -> putByte bh 4 *> put_ bh str
    
    372
    -    BCONPtrFS fs -> putByte bh 5 *> put_ bh fs
    
    373
    -    BCONPtrFFIInfo ffi -> putByte bh 6 *> put_ bh ffi
    
    374
    -    BCONPtrCostCentre ibi -> putByte bh 7 *> put_ bh ibi
    
    375
    -
    
    376
    -newtype BinName = BinName {unBinName :: Name}
    
    377
    -
    
    378
    -getViaBinName :: ReadBinHandle -> IO Name
    
    379
    -getViaBinName bh = case findUserDataReader Proxy bh of
    
    380
    -  BinaryReader f -> unBinName <$> f bh
    
    381
    -
    
    382
    -putViaBinName :: WriteBinHandle -> Name -> IO ()
    
    383
    -putViaBinName bh nm = case findUserDataWriter Proxy bh of
    
    384
    -  BinaryWriter f -> f bh $ BinName nm
    
    385
    -
    
    386
    -data BytecodeNameEnv = ByteCodeNameEnv { _bytecode_next_id :: !Word64
    
    387
    -                                       , _bytecode_name_subst :: NameEnv Word64
    
    388
    -                                       }
    
    389
    -
    
    390
    -addBinNameWriter :: WriteBinHandle -> IO WriteBinHandle
    
    391
    -addBinNameWriter bh' = do
    
    392
    -  env_ref <- newIORef (ByteCodeNameEnv 0 emptyNameEnv)
    
    393
    -  evaluate
    
    394
    -    $ flip addWriterToUserData bh'
    
    395
    -    $ BinaryWriter
    
    396
    -    $ \bh (BinName nm) ->
    
    397
    -      if
    
    398
    -        | isExternalName nm -> do
    
    399
    -            putByte bh 0
    
    400
    -            put_ bh nm
    
    401
    -        | otherwise -> do
    
    402
    -            putByte bh 1
    
    403
    -            key <- getBinNameKey env_ref nm
    
    404
    -            -- Delimit the OccName from the deterministic counter to keep the
    
    405
    -            -- encoding injective, avoiding collisions like "foo1" vs "foo#1".
    
    406
    -            put_ bh (occNameFS (occName nm) `appendFS` mkFastString ('#' : show key))
    
    407
    -  where
    
    408
    -    -- Find a deterministic key for local names. This
    
    409
    -    getBinNameKey ref name = do
    
    410
    -      atomicModifyIORef ref (\b@(ByteCodeNameEnv next subst) ->
    
    411
    -        case lookupNameEnv subst name of
    
    412
    -          Just idx -> (b, idx)
    
    413
    -          Nothing  -> (ByteCodeNameEnv (next + 1) (extendNameEnv subst name next), next))
    
    414
    -
    
    415
    -addBinNameReader :: HscEnv -> ReadBinHandle -> IO ReadBinHandle
    
    416
    -addBinNameReader HscEnv {..} bh' = do
    
    417
    -  env_ref <- newIORef emptyOccEnv
    
    418
    -  pure $ flip addReaderToUserData bh' $ BinaryReader $ \bh -> do
    
    419
    -    t <- getByte bh
    
    420
    -    case t of
    
    421
    -      0 -> do
    
    422
    -        nm <- get bh
    
    423
    -        pure $ BinName nm
    
    424
    -      1 -> do
    
    425
    -        occ <- mkVarOccFS <$> get bh
    
    426
    -        -- We don't want to get a new unique from the NameCache each time we
    
    427
    -        -- see a name.
    
    428
    -        nm' <- unsafeInterleaveIO $ do
    
    429
    -          u <- takeUniqFromNameCache hsc_NC
    
    430
    -          evaluate $ mkInternalName u occ noSrcSpan
    
    431
    -        fmap BinName $ atomicModifyIORef' env_ref $ \env ->
    
    432
    -          case lookupOccEnv env occ of
    
    433
    -            Just nm -> (env, nm)
    
    434
    -            _ -> nm' `seq` (extendOccEnv env occ nm', nm')
    
    435
    -      _ -> panic "Binary BinName: invalid byte"
    
    436
    -
    
    437
    --- Note [Serializing Names in bytecode]
    
    438
    --- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    439
    --- The bytecode related types contain various Names which we need to
    
    440
    --- serialize. Unfortunately, we can't directly use the Binary instance
    
    441
    --- of Name: it is only meant to be used for serializing external Names
    
    442
    --- in BinIface logic, but bytecode does contain internal Names.
    
    443
    ---
    
    444
    --- We also need to maintain the invariant that: any pair of internal
    
    445
    --- Names with equal/different uniques must also be deserialized to
    
    446
    --- have the same equality. Therefore when we write the names to the interface, we
    
    447
    --- use an incrementing counter to give each local name it's own unique number. A substitution
    
    448
    --- is maintained to give each occurence of the Name the same unique key. When the interface
    
    449
    --- is read, a reverse mapping is used from these unique keys to a Name.
    
    450
    ---
    205
    +fingerprintModuleByteCodeContents :: Module -> CompiledByteCode -> [FilePath] -> IO Fingerprint
    
    206
    +fingerprintModuleByteCodeContents modl cbc foreign_files = do
    
    207
    +  foreign_contents <- readObjectFiles foreign_files
    
    208
    +  pure $ computeFingerprint putNameLiterally (modl, cbc, foreign_contents)

  • compiler/GHC/Driver/Hooks.hs
    ... ... @@ -137,7 +137,7 @@ data Hooks = Hooks
    137 137
       , tcForeignExportsHook   :: !(Maybe ([LForeignDecl GhcRn]
    
    138 138
                 -> TcM (LHsBinds GhcTc, [LForeignDecl GhcTc], Bag GlobalRdrElt)))
    
    139 139
       , hscFrontendHook        :: !(Maybe (ModSummary -> Hsc FrontendResult))
    
    140
    -  , hscCompileCoreExprHook :: !(Maybe (HscEnv -> SrcSpan -> CoreExpr -> IO (ForeignHValue, [Linkable], PkgsLoaded)))
    
    140
    +  , hscCompileCoreExprHook :: !(Maybe (HscEnv -> SrcSpan -> CoreExpr -> IO (ForeignHValue, [LinkableUsage], PkgsLoaded)))
    
    141 141
       , ghcPrimIfaceHook       :: !(Maybe ModIface)
    
    142 142
       , runPhaseHook           :: !(Maybe PhaseHook)
    
    143 143
       , runMetaHook            :: !(Maybe (MetaHook TcM))
    
    ... ... @@ -145,7 +145,7 @@ data Hooks = Hooks
    145 145
                                              -> HomePackageTable -> IO SuccessFlag))
    
    146 146
       , runRnSpliceHook        :: !(Maybe (HsUntypedSplice GhcRn -> RnM (HsUntypedSplice GhcRn)))
    
    147 147
       , getValueSafelyHook     :: !(Maybe (HscEnv -> Name -> Type
    
    148
    -                                         -> IO (Either Type (HValue, [Linkable], PkgsLoaded))))
    
    148
    +                                         -> IO (Either Type (HValue, [LinkableUsage], PkgsLoaded))))
    
    149 149
       , createIservProcessHook :: !(Maybe (CreateProcess -> IO ProcessHandle))
    
    150 150
       , stgToCmmHook           :: !(Maybe (StgToCmmConfig -> InfoTableProvMap -> [TyCon] -> CollectedCCs
    
    151 151
                                      -> [CgStgTopBinding] -> CgStream CmmGroup ModuleLFInfos))
    

  • compiler/GHC/Driver/Main.hs
    ... ... @@ -301,8 +301,7 @@ import GHC.Cmm.Config (CmmConfig)
    301 301
     import Data.Bifunctor
    
    302 302
     import qualified GHC.Unit.Home.Graph as HUG
    
    303 303
     import GHC.Unit.Home.PackageTable
    
    304
    -
    
    305
    -import GHC.ByteCode.Serialize
    
    304
    +import qualified GHC.ByteCode.Serialize as ByteCode
    
    306 305
     
    
    307 306
     {- **********************************************************************
    
    308 307
     %*                                                                      *
    
    ... ... @@ -866,7 +865,7 @@ hscRecompStatus
    866 865
                | otherwise -> do
    
    867 866
                    -- Check the status of all the linkable types we might need.
    
    868 867
                    -- 1. The in-memory linkable we had at hand.
    
    869
    -               bc_in_memory_linkable <- checkByteCodeInMemory hsc_env mod_summary (homeMod_bytecode old_linkable)
    
    868
    +               bc_in_memory_linkable <- checkByteCodeInMemory hsc_env mod_summary (homeModLinkableByteCode old_linkable)
    
    870 869
                    -- 2. The bytecode object file
    
    871 870
                    bc_obj_linkable <- checkByteCodeFromObject hsc_env mod_summary
    
    872 871
                    -- 3. Bytecode from an interface's whole core bindings.
    
    ... ... @@ -1013,7 +1012,7 @@ checkByteCodeFromObject hsc_env mod_sum = do
    1013 1012
               -- Don't force this if we reuse the linkable already loaded into memory, but we have to check
    
    1014 1013
               -- that the one we have on disk would be suitable as well.
    
    1015 1014
               linkable <- unsafeInterleaveIO $ do
    
    1016
    -            bco <- readBinByteCode hsc_env obj_fn
    
    1015
    +            bco <- ByteCode.readBinByteCode hsc_env obj_fn
    
    1017 1016
                 return $ mkModuleByteCodeLinkable obj_date bco
    
    1018 1017
               return $ UpToDateItem linkable
    
    1019 1018
         _ -> return $ outOfDateItemBecause MissingBytecode Nothing
    
    ... ... @@ -1098,7 +1097,7 @@ loadIfaceByteCodeLazy ::
    1098 1097
       ModIface ->
    
    1099 1098
       ModLocation ->
    
    1100 1099
       TypeEnv ->
    
    1101
    -  IO (Maybe Linkable)
    
    1100
    +  IO (Maybe (LinkableWith ModuleByteCode))
    
    1102 1101
     loadIfaceByteCodeLazy hsc_env iface location type_env =
    
    1103 1102
       case iface_core_bindings iface location of
    
    1104 1103
         Nothing -> return Nothing
    
    ... ... @@ -1106,8 +1105,9 @@ loadIfaceByteCodeLazy hsc_env iface location type_env =
    1106 1105
           Just <$> compile wcb
    
    1107 1106
       where
    
    1108 1107
         compile decls = do
    
    1109
    -      bco <- unsafeInterleaveIO $ compileWholeCoreBindings hsc_env type_env decls
    
    1110
    -      linkable $ NE.singleton (DotGBC bco)
    
    1108
    +      bco <- unsafeInterleaveIO $ do
    
    1109
    +          compileWholeCoreBindings hsc_env type_env decls
    
    1110
    +      linkable bco
    
    1111 1111
     
    
    1112 1112
         linkable parts = do
    
    1113 1113
           if_time <- modificationTimeIfExists (ml_hi_file_ospath location)
    
    ... ... @@ -1148,14 +1148,14 @@ initWholeCoreBindings hsc_env iface details (RecompLinkables bc o) = do
    1148 1148
       where
    
    1149 1149
         type_env = md_types details
    
    1150 1150
     
    
    1151
    -    go :: RecompBytecodeLinkable -> IO (Maybe Linkable)
    
    1151
    +    go :: RecompBytecodeLinkable -> IO (Maybe (LinkableWith ModuleByteCode))
    
    1152 1152
         go (NormalLinkable l) = pure l
    
    1153 1153
         go (WholeCoreBindingsLinkable wcbl) =
    
    1154 1154
           fmap Just $ for wcbl $ \wcb -> do
    
    1155 1155
             add_iface_to_hpt iface details hsc_env
    
    1156
    -        bco <- unsafeInterleaveIO $
    
    1157
    -                       compileWholeCoreBindings hsc_env type_env wcb
    
    1158
    -        pure $ NE.singleton (DotGBC bco)
    
    1156
    +        bco <- unsafeInterleaveIO $ do
    
    1157
    +            compileWholeCoreBindings hsc_env type_env wcb
    
    1158
    +        pure bco
    
    1159 1159
     
    
    1160 1160
     -- | Hydrate interface Core bindings and compile them to bytecode.
    
    1161 1161
     --
    
    ... ... @@ -2217,7 +2217,7 @@ generateAndWriteByteCode hsc_env cgguts mod_location = do
    2217 2217
       -- See Note [-fwrite-byte-code is not the default]
    
    2218 2218
       when (gopt Opt_WriteByteCode dflags) $ do
    
    2219 2219
         let bc_path = ml_bytecode_file mod_location
    
    2220
    -    writeBinByteCode bc_path comp_bc
    
    2220
    +    ByteCode.writeBinByteCode bc_path comp_bc
    
    2221 2221
       return comp_bc
    
    2222 2222
     
    
    2223 2223
     {-
    
    ... ... @@ -2232,20 +2232,20 @@ make user's opt into writing the files.
    2232 2232
     -}
    
    2233 2233
     
    
    2234 2234
     -- | Generate a 'ModuleByteCode' and write it to disk if `-fwrite-byte-code` is enabled.
    
    2235
    -generateAndWriteByteCodeLinkable :: HscEnv -> CgInteractiveGuts -> ModLocation -> IO Linkable
    
    2235
    +generateAndWriteByteCodeLinkable :: HscEnv -> CgInteractiveGuts -> ModLocation -> IO (LinkableWith ModuleByteCode)
    
    2236 2236
     generateAndWriteByteCodeLinkable hsc_env cgguts mod_location = do
    
    2237 2237
       bco_object <- generateAndWriteByteCode hsc_env cgguts mod_location
    
    2238 2238
       -- Either, get the same time as the .gbc file if it exists, or just the current time.
    
    2239 2239
       -- It's important the time of the linkable matches the time of the .gbc file for recompilation
    
    2240 2240
       -- checking.
    
    2241 2241
       bco_time <- maybe getCurrentTime pure =<< modificationTimeIfExists (ml_bytecode_file_ospath mod_location)
    
    2242
    -  return $ mkModuleByteCodeLinkable bco_time bco_object
    
    2242
    +  return $ mkOnlyModuleByteCodeLinkable bco_time bco_object
    
    2243 2243
     
    
    2244 2244
     mkModuleByteCode :: HscEnv -> Module -> ModLocation -> CgInteractiveGuts -> IO ModuleByteCode
    
    2245 2245
     mkModuleByteCode hsc_env mod mod_location cgguts = do
    
    2246 2246
       bcos <- hscGenerateByteCode hsc_env cgguts mod_location
    
    2247 2247
       objs <- outputAndCompileForeign hsc_env mod mod_location (cgi_foreign_files cgguts) (cgi_foreign cgguts)
    
    2248
    -  return $! ModuleByteCode mod bcos objs
    
    2248
    +  ByteCode.mkModuleByteCode mod bcos objs
    
    2249 2249
     
    
    2250 2250
     -- | Generate a fresh 'ModuleByteCode' for a given module but do not write it to disk.
    
    2251 2251
     generateFreshByteCodeLinkable :: HscEnv
    
    ... ... @@ -2767,13 +2767,13 @@ hscTidy hsc_env guts = do
    2767 2767
     %*                                                                      *
    
    2768 2768
     %********************************************************************* -}
    
    2769 2769
     
    
    2770
    -hscCompileCoreExpr :: HscEnv -> SrcSpan -> CoreExpr -> IO (ForeignHValue, [Linkable], PkgsLoaded)
    
    2770
    +hscCompileCoreExpr :: HscEnv -> SrcSpan -> CoreExpr -> IO (ForeignHValue, [LinkableUsage], PkgsLoaded)
    
    2771 2771
     hscCompileCoreExpr hsc_env loc expr =
    
    2772 2772
       case hscCompileCoreExprHook (hsc_hooks hsc_env) of
    
    2773 2773
           Nothing -> hscCompileCoreExpr' hsc_env loc expr
    
    2774 2774
           Just h  -> h                   hsc_env loc expr
    
    2775 2775
     
    
    2776
    -hscCompileCoreExpr' :: HscEnv -> SrcSpan -> CoreExpr -> IO (ForeignHValue, [Linkable], PkgsLoaded)
    
    2776
    +hscCompileCoreExpr' :: HscEnv -> SrcSpan -> CoreExpr -> IO (ForeignHValue, [LinkableUsage], PkgsLoaded)
    
    2777 2777
     hscCompileCoreExpr' hsc_env srcspan ds_expr = do
    
    2778 2778
       {- Simplify it -}
    
    2779 2779
       -- Question: should we call SimpleOpt.simpleOptExpr here instead?
    
    ... ... @@ -2859,8 +2859,9 @@ hscCompileCoreExpr' hsc_env srcspan ds_expr = do
    2859 2859
     
    
    2860 2860
           {- load it -}
    
    2861 2861
           bco_time <- getCurrentTime
    
    2862
    +      !mbc <- ByteCode.mkModuleByteCode this_mod bcos []
    
    2862 2863
           (mods_needed, units_needed) <- loadDecls interp hsc_env srcspan $
    
    2863
    -        Linkable bco_time this_mod $ NE.singleton $ DotGBC (ModuleByteCode this_mod bcos [])
    
    2864
    +        Linkable bco_time this_mod $ NE.singleton (DotGBC mbc)
    
    2864 2865
           -- Get the foreign reference to the name we should have just loaded.
    
    2865 2866
           mhvs <- lookupFromLoadedEnv interp (idName binding_id)
    
    2866 2867
           {- Get the HValue for the root -}
    
    ... ... @@ -2876,7 +2877,7 @@ jsCodeGen
    2876 2877
       -> Module
    
    2877 2878
       -> [(CgStgTopBinding,IdSet)]
    
    2878 2879
       -> Id
    
    2879
    -  -> IO (ForeignHValue, [Linkable], PkgsLoaded)
    
    2880
    +  -> IO (ForeignHValue, [LinkableUsage], PkgsLoaded)
    
    2880 2881
     jsCodeGen hsc_env srcspan i this_mod stg_binds_with_deps binding_id = do
    
    2881 2882
       let logger           = hsc_logger hsc_env
    
    2882 2883
           tmpfs            = hsc_tmpfs hsc_env
    

  • compiler/GHC/Driver/Pipeline.hs
    ... ... @@ -430,7 +430,7 @@ link' hsc_env batch_attempt_linking mHscMessager hpt
    430 430
                     let obj_files = concatMap linkableObjs linkables
    
    431 431
                     in action obj_files
    
    432 432
                 linkBytecodeLinkable action =
    
    433
    -              checkLinkablesUpToDate hsc_env mHscMessager home_mods pkg_deps staticLink checkBytecodeLibraryLinkingNeeded homeMod_bytecode $ \linkables ->
    
    433
    +              checkLinkablesUpToDate hsc_env mHscMessager home_mods pkg_deps staticLink checkBytecodeLibraryLinkingNeeded homeModLinkableByteCode $ \linkables ->
    
    434 434
                     let bytecode = concatMap linkableModuleByteCodes linkables
    
    435 435
                     in action bytecode
    
    436 436
     
    

  • compiler/GHC/Driver/Plugins.hs
    ... ... @@ -342,7 +342,7 @@ data Plugins = Plugins
    342 342
           -- The purpose of this field is to cache the plugins so they
    
    343 343
           -- don't have to be loaded each time they are needed.  See
    
    344 344
           -- 'GHC.Runtime.Loader.initializePlugins'.
    
    345
    -  , loadedPluginDeps :: !([Linkable], PkgsLoaded)
    
    345
    +  , loadedPluginDeps :: !([LinkableUsage], PkgsLoaded)
    
    346 346
       -- ^ The object files required by the loaded plugins
    
    347 347
       -- See Note [Plugin dependencies]
    
    348 348
       }
    

  • compiler/GHC/HsToCore/Usage.hs
    ... ... @@ -7,8 +7,6 @@ module GHC.HsToCore.Usage (
    7 7
     
    
    8 8
     import GHC.Prelude
    
    9 9
     
    
    10
    -import GHC.Driver.Env
    
    11
    -
    
    12 10
     import GHC.Tc.Types
    
    13 11
     
    
    14 12
     import GHC.Iface.Load
    
    ... ... @@ -27,7 +25,6 @@ import GHC.Types.Unique.Set
    27 25
     
    
    28 26
     import GHC.Unit
    
    29 27
     import GHC.Unit.Env
    
    30
    -import GHC.Unit.External
    
    31 28
     import GHC.Unit.Module.Imported
    
    32 29
     import GHC.Unit.Module.ModIface
    
    33 30
     import GHC.Unit.Module.Deps
    
    ... ... @@ -35,18 +32,17 @@ import GHC.Unit.Module.Deps
    35 32
     import GHC.Data.Maybe
    
    36 33
     import GHC.Data.FastString
    
    37 34
     
    
    38
    -import Data.IORef
    
    39 35
     import Data.List (sortBy)
    
    40 36
     import Data.Map (Map)
    
    41 37
     import qualified Data.Map as Map
    
    42 38
     import qualified Data.Set as Set
    
    43
    -import qualified Data.List.NonEmpty as NE
    
    44 39
     
    
    45 40
     import GHC.Linker.Types
    
    46 41
     import GHC.Unit.Finder
    
    47 42
     import GHC.Types.Unique.DFM
    
    48 43
     import GHC.Driver.Plugins
    
    49 44
     import qualified GHC.Unit.Home.Graph as HUG
    
    45
    +import qualified Data.List.NonEmpty as NE
    
    50 46
     
    
    51 47
     {- Note [Module self-dependency]
    
    52 48
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    ... ... @@ -75,19 +71,17 @@ data UsageConfig = UsageConfig
    75 71
     
    
    76 72
     mkUsageInfo :: UsageConfig -> Plugins -> FinderCache -> UnitEnv
    
    77 73
                 -> Module -> ImportedMods -> [ImportUserSpec] -> NameSet
    
    78
    -            -> [FilePath] -> [FilePath] -> [(Module, Fingerprint)] -> [Linkable] -> PkgsLoaded
    
    74
    +            -> [FilePath] -> [FilePath] -> [(Module, Fingerprint)] -> [LinkableUsage] -> PkgsLoaded
    
    79 75
                 -> IfG [Usage]
    
    80 76
     mkUsageInfo uc plugins fc unit_env
    
    81 77
       this_mod dir_imp_mods imp_decls used_names
    
    82 78
       dependent_files dependent_dirs merged needed_links needed_pkgs
    
    83 79
       = do
    
    84
    -    eps <- liftIO $ readIORef (euc_eps (ue_eps unit_env))
    
    85 80
         file_hashes <- liftIO $ mapM getFileHash dependent_files
    
    86 81
         dirs_hashes <- liftIO $ mapM getDirHash dependent_dirs
    
    87 82
         let hu = ue_unsafeHomeUnit unit_env
    
    88
    -        hug = ue_home_unit_graph unit_env
    
    89 83
         -- Dependencies on object files due to TH and plugins
    
    90
    -    object_usages <- liftIO $ mkObjectUsage (eps_PIT eps) plugins fc hug needed_links needed_pkgs
    
    84
    +    object_usages <- liftIO $ mkObjectUsage plugins fc needed_links needed_pkgs
    
    91 85
         let all_home_ids = HUG.allUnits (ue_home_unit_graph unit_env)
    
    92 86
         mod_usages <- mk_mod_usage_info uc hu all_home_ids this_mod
    
    93 87
                                            dir_imp_mods imp_decls used_names
    
    ... ... @@ -176,44 +170,39 @@ For bytecode objects there are also two forms of dependencies.
    176 170
     1. The existence of the .gbc file for the module you are currently compiling.
    
    177 171
     2. The usage of bytecode to evaluate TH splices (similar to Note [Object File Dependencies])
    
    178 172
     
    
    179
    -In situation (2), we would ideally want to record the hash of the `CompiledByteCode` which
    
    180
    -was used when evaluating the TH splice. This was a bit tricky to implement so it's tracked as a future
    
    181
    -improvement to the recompilation checking for bytecode objects.
    
    182
    -
    
    183
    -For now, the interface hash is used as a proxy to determine if the BCO will have changed
    
    184
    -for a module or not. This is similar to how the recompilation checking for the legacy
    
    185
    -`-fwrite-if-simplified-core` code path which generated bytecode from core bindings used to work.
    
    186
    -
    
    173
    +In both cases, we record the hash of the 'CompiledByteCode' which was used when evaluating
    
    174
    +the TH splice.
    
    187 175
     -}
    
    188 176
     
    
    189 177
     
    
    190 178
     
    
    191 179
     -- | Find object files corresponding to the transitive closure of given home
    
    192 180
     -- modules and direct object files for pkg dependencies
    
    193
    -mkObjectUsage :: PackageIfaceTable -> Plugins -> FinderCache -> HomeUnitGraph-> [Linkable] -> PkgsLoaded -> IO [Usage]
    
    194
    -mkObjectUsage pit plugins fc hug th_links_needed th_pkgs_needed = do
    
    181
    +mkObjectUsage :: Plugins -> FinderCache -> [LinkableUsage] -> PkgsLoaded -> IO [Usage]
    
    182
    +mkObjectUsage plugins fc th_links_needed th_pkgs_needed = do
    
    195 183
           let ls = ordNubOn linkableModule (th_links_needed ++ plugins_links_needed)
    
    196 184
               ds = concatMap loaded_pkg_hs_objs $ eltsUDFM (plusUDFM th_pkgs_needed plugin_pkgs_needed) -- TODO possibly record loaded_pkg_non_hs_objs as well
    
    197 185
               (plugins_links_needed, plugin_pkgs_needed) = loadedPluginDeps plugins
    
    198 186
           concat <$> sequence (map linkableToUsage ls ++ map librarySpecToUsage ds)
    
    199 187
       where
    
    200
    -    linkableToUsage (Linkable _ m uls) = mapM (partToUsage m) (NE.toList uls)
    
    188
    +    linkableToUsage (Linkable _ _m parts) = traverse partToUsage (NE.toList parts)
    
    201 189
     
    
    202 190
         msg m = moduleNameString (moduleName m) ++ "[TH] changed"
    
    203 191
     
    
    204
    -    fing mmsg fn = UsageFile (mkFastString fn) <$> lookupFileCache fc fn <*> pure mmsg
    
    192
    +    partToUsage link_usage =
    
    193
    +      case link_usage of
    
    194
    +        FileLinkablePartUsage{flu_file, flu_module} -> do
    
    195
    +          fing (Just $ msg flu_module) flu_file
    
    205 196
     
    
    206
    -    partToUsage m part =
    
    207
    -      case linkablePartPath part of
    
    208
    -        Just fn -> fing (Just (msg m)) fn
    
    209
    -        Nothing ->  do
    
    210
    -          -- This should only happen for home package things but oneshot puts
    
    211
    -          -- home package ifaces in the PIT.
    
    212
    -          miface <- lookupIfaceByModule hug pit m
    
    213
    -          case miface of
    
    214
    -            Nothing -> pprPanic "linkableToUsage" (ppr m)
    
    215
    -            Just iface ->
    
    216
    -              return $ UsageHomeModuleInterface (moduleName m) (toUnitId $ moduleUnit m) (mi_iface_hash iface)
    
    197
    +        ByteCodeLinkablePartUsage{bclu_module, bclu_hash} ->
    
    198
    +          pure $
    
    199
    +            UsageHomeModuleBytecode
    
    200
    +              { usg_mod_name = moduleName bclu_module
    
    201
    +              , usg_unit_id = toUnitId $ moduleUnit bclu_module
    
    202
    +              , usg_bytecode_hash = bclu_hash
    
    203
    +              }
    
    204
    +
    
    205
    +    fing mmsg fn = UsageFile (mkFastString fn) <$> lookupFileCache fc fn <*> pure mmsg
    
    217 206
     
    
    218 207
         librarySpecToUsage :: LibrarySpec -> IO [Usage]
    
    219 208
         librarySpecToUsage (Objects os) = traverse (fing Nothing) os
    

  • compiler/GHC/Iface/Recomp.hs
    ... ... @@ -88,6 +88,10 @@ import GHC.Iface.Errors.Ppr
    88 88
     import Data.Functor
    
    89 89
     import Data.Bifunctor (first)
    
    90 90
     import GHC.Types.PkgQual
    
    91
    +import GHC.ByteCode.Serialize (ModuleByteCode, gbc_hash)
    
    92
    +import GHC.Unit.Home.Graph (lookupHugByModule)
    
    93
    +import GHC.Unit.Home.ModInfo (HomeModLinkable(..), HomeModInfo (..))
    
    94
    +import GHC.Linker.Types (linkableParts)
    
    91 95
     
    
    92 96
     {-
    
    93 97
       -----------------------------------------------
    
    ... ... @@ -190,6 +194,7 @@ data RecompReason
    190 194
       | ModuleAdded (ImportLevel, UnitId, ModuleName)
    
    191 195
       | ModuleChangedRaw ModuleName
    
    192 196
       | ModuleChangedIface ModuleName
    
    197
    +  | ModuleChangedBytecode ModuleName
    
    193 198
       | FileChanged FilePath
    
    194 199
       | DirChanged FilePath
    
    195 200
       | CustomReason String
    
    ... ... @@ -225,6 +230,7 @@ instance Outputable RecompReason where
    225 230
         ModuleChanged m          -> ppr m <+> text "changed"
    
    226 231
         ModuleChangedRaw m       -> ppr m <+> text "changed (raw)"
    
    227 232
         ModuleChangedIface m     -> ppr m <+> text "changed (interface)"
    
    233
    +    ModuleChangedBytecode m     -> ppr m <+> text "changed (bytecode)"
    
    228 234
         ModuleRemoved (_st, _uid, m)   -> ppr m <+> text "removed"
    
    229 235
         ModuleAdded (_st, _uid, m)     -> ppr m <+> text "added"
    
    230 236
         FileChanged fp           -> text fp <+> text "changed"
    
    ... ... @@ -718,6 +724,15 @@ needInterface mod continue
    718 724
             Nothing -> return $ NeedsRecompile MustCompile
    
    719 725
             Just iface -> liftIO $ continue iface
    
    720 726
     
    
    727
    +needBytecode :: Module -> (ModuleByteCode -> IO RecompileRequired)
    
    728
    +             -> IfG RecompileRequired
    
    729
    +needBytecode mod continue
    
    730
    +  = do
    
    731
    +      mb_recomp <- tryGetBytecode mod
    
    732
    +      case mb_recomp of
    
    733
    +        Nothing -> return $ NeedsRecompile MustCompile
    
    734
    +        Just mbc -> liftIO $ continue mbc
    
    735
    +
    
    721 736
     tryGetModIface :: String -> Module -> IfG (Maybe ModIface)
    
    722 737
     tryGetModIface doc_msg mod
    
    723 738
       = do  -- Load the imported interface if possible
    
    ... ... @@ -739,6 +754,27 @@ tryGetModIface doc_msg mod
    739 754
                       -- import and it's been deleted
    
    740 755
           Succeeded iface -> pure $ Just iface
    
    741 756
     
    
    757
    +tryGetBytecode :: Module -> IfG (Maybe ModuleByteCode)
    
    758
    +tryGetBytecode mod
    
    759
    +  = do  -- Load the imported bytecode if possible
    
    760
    +    logger <- getLogger
    
    761
    +    liftIO $ trace_hi_diffs logger (text "Checking bytecode hash for module" <+> ppr mod <+> ppr (moduleUnit mod))
    
    762
    +
    
    763
    +    mb_module_bytecode <- do
    
    764
    +      env <- getTopEnv
    
    765
    +      liftIO (lookupHugByModule mod (hsc_HUG env)) >>= \ case
    
    766
    +        Nothing -> pure Nothing
    
    767
    +        Just hmi ->
    
    768
    +          case homeMod_bytecode (hm_linkable hmi) of
    
    769
    +            Nothing -> pure Nothing
    
    770
    +            Just gbc_linkable -> pure $ Just $ linkableParts gbc_linkable
    
    771
    +
    
    772
    +    case mb_module_bytecode of
    
    773
    +      Nothing -> do
    
    774
    +        liftIO $ trace_hi_diffs logger (sep [text "Couldn't find bytecode for module", ppr mod])
    
    775
    +        return Nothing
    
    776
    +      Just module_bytecode -> pure $ Just module_bytecode
    
    777
    +
    
    742 778
     -- | Given the usage information extracted from the old
    
    743 779
     -- M.hi file for the module being compiled, figure out
    
    744 780
     -- whether M needs to be recompiled.
    
    ... ... @@ -760,14 +796,14 @@ checkModUsage _ UsageMergedRequirement{ usg_mod = mod, usg_mod_hash = old_mod_ha
    760 796
       needInterface mod $ \iface -> do
    
    761 797
         let reason = ModuleChangedRaw (moduleName mod)
    
    762 798
         checkModuleFingerprint logger reason old_mod_hash (mi_mod_hash iface)
    
    763
    -checkModUsage _  UsageHomeModuleInterface{ usg_mod_name = mod_name
    
    799
    +checkModUsage _  UsageHomeModuleBytecode{ usg_mod_name = mod_name
    
    764 800
                                                      , usg_unit_id = uid
    
    765
    -                                                 , usg_iface_hash = old_mod_hash } = do
    
    801
    +                                                 , usg_bytecode_hash = old_bytecode_hash } = do
    
    766 802
       let mod = mkModule (RealUnit (Definite uid)) mod_name
    
    767 803
       logger <- getLogger
    
    768
    -  needInterface mod $ \iface -> do
    
    769
    -    let reason = ModuleChangedIface mod_name
    
    770
    -    checkIfaceFingerprint logger reason old_mod_hash (mi_iface_hash iface)
    
    804
    +  needBytecode mod $ \cbc -> do
    
    805
    +    let reason = ModuleChangedBytecode mod_name
    
    806
    +    checkBytecodeFingerprint logger reason old_bytecode_hash (gbc_hash cbc)
    
    771 807
     
    
    772 808
     checkModUsage _ UsageHomeModule{
    
    773 809
                                     usg_mod_name = mod_name,
    
    ... ... @@ -1032,19 +1068,18 @@ checkModuleFingerprint logger reason old_mod_hash new_mod_hash
    1032 1068
       = out_of_date_hash logger reason (text "  Module fingerprint has changed")
    
    1033 1069
                          old_mod_hash new_mod_hash
    
    1034 1070
     
    
    1035
    -checkIfaceFingerprint
    
    1071
    +checkBytecodeFingerprint
    
    1036 1072
       :: Logger
    
    1037 1073
       -> RecompReason
    
    1038 1074
       -> Fingerprint
    
    1039 1075
       -> Fingerprint
    
    1040 1076
       -> IO RecompileRequired
    
    1041
    -checkIfaceFingerprint logger reason old_mod_hash new_mod_hash
    
    1042
    -  | new_mod_hash == old_mod_hash
    
    1043
    -  = up_to_date logger (text "Iface fingerprint unchanged")
    
    1044
    -
    
    1077
    +checkBytecodeFingerprint logger reason old_bytecode_hash new_bytecode_hash
    
    1078
    +  | old_bytecode_hash == new_bytecode_hash
    
    1079
    +  = up_to_date logger (text "Bytecode fingerprint unchanged")
    
    1045 1080
       | otherwise
    
    1046
    -  = out_of_date_hash logger reason (text "  Iface fingerprint has changed")
    
    1047
    -                     old_mod_hash new_mod_hash
    
    1081
    +  = out_of_date_hash logger reason (text "  Bytecode fingerprint has changed")
    
    1082
    +                     old_bytecode_hash new_bytecode_hash
    
    1048 1083
     
    
    1049 1084
     ------------------------
    
    1050 1085
     checkEntityUsage :: Logger
    

  • compiler/GHC/Iface/Recomp/Types.hs
    ... ... @@ -146,10 +146,10 @@ pprUsage usage@UsageDirectory{}
    146 146
               ppr (usg_dir_hash usage)]
    
    147 147
     pprUsage usage@UsageMergedRequirement{}
    
    148 148
       = hsep [text "merged", ppr (usg_mod usage), ppr (usg_mod_hash usage)]
    
    149
    -pprUsage usage@UsageHomeModuleInterface{}
    
    150
    -  = hsep [text "implementation", ppr (usg_mod_name usage)
    
    149
    +pprUsage usage@UsageHomeModuleBytecode{}
    
    150
    +  = hsep [text "Bytecode", ppr (usg_mod_name usage)
    
    151 151
                                    , ppr (usg_unit_id usage)
    
    152
    -                               , ppr (usg_iface_hash usage)]
    
    152
    +                               , ppr (usg_bytecode_hash usage)]
    
    153 153
     
    
    154 154
     pprUsageImport :: Outputable mod => mod -> Fingerprint -> IsSafeImport -> SDoc
    
    155 155
     pprUsageImport mod hash safe
    
    ... ... @@ -157,4 +157,4 @@ pprUsageImport mod hash safe
    157 157
              , ppr hash ]
    
    158 158
         where
    
    159 159
             pp_safe | safe      = text "safe"
    
    160
    -                | otherwise = text " -/ "
    \ No newline at end of file
    160
    +                | otherwise = text " -/ "

  • compiler/GHC/Linker/ByteCode.hs
    ... ... @@ -31,7 +31,7 @@ linkBytecodeLib hsc_env gbcs = do
    31 31
     
    
    32 32
       on_disk_bcos <- mapM (readBinByteCode hsc_env) bytecodeObjects
    
    33 33
     
    
    34
    -  let (all_cbcs, foreign_stubs) = unzip [ (bs, fs) | ModuleByteCode _m bs fs <- on_disk_bcos ++ gbcs]
    
    34
    +  let (all_cbcs, foreign_stubs) = unzip [ (bs, fs) | ModuleByteCode _m bs fs _hash <- on_disk_bcos ++ gbcs]
    
    35 35
     
    
    36 36
       interpreter_foreign_lib <- mkInterpreterLib hsc_env (concat foreign_stubs ++ objectFiles)
    
    37 37
     
    
    ... ... @@ -67,4 +67,4 @@ mkInterpreterLib hsc_env files =
    67 67
               return $ Just (InterpreterSharedObject foreign_stub_lib_path foreign_stub_lib_dir foreign_stub_lib_name)
    
    68 68
             Nothing -> pure Nothing
    
    69 69
         False -> do
    
    70
    -      pure $ Just (InterpreterStaticObjects files)
    \ No newline at end of file
    70
    +      pure $ Just (InterpreterStaticObjects files)

  • compiler/GHC/Linker/Deps.hs
    ... ... @@ -63,7 +63,7 @@ data LinkDepsOpts = LinkDepsOpts
    63 63
     
    
    64 64
     data LinkDeps = LinkDeps
    
    65 65
       { ldNeededLinkables :: [Linkable]
    
    66
    -  , ldAllLinkables    :: [Linkable]
    
    66
    +  , ldAllLinkables    :: [LinkableUsage]
    
    67 67
       , ldUnits           :: [UnitId]
    
    68 68
       , ldNeededUnits     :: UniqDSet UnitId
    
    69 69
       }
    
    ... ... @@ -126,7 +126,7 @@ get_link_deps opts pls maybe_normal_osuf span mods = do
    126 126
     
    
    127 127
           return $ LinkDeps
    
    128 128
             { ldNeededLinkables = lnks_needed
    
    129
    -        , ldAllLinkables    = links_got ++ lnks_needed
    
    129
    +        , ldAllLinkables    = links_got ++ mkLinkablesUsage lnks_needed
    
    130 130
             , ldUnits           = pkgs_needed
    
    131 131
             , ldNeededUnits     = pkgs_s
    
    132 132
             }
    

  • compiler/GHC/Linker/Loader.hs
    ... ... @@ -228,7 +228,7 @@ lookupFromLoadedEnv interp name = do
    228 228
     -- | Load the module containing the given Name and get its associated 'HValue'.
    
    229 229
     --
    
    230 230
     -- Throws a 'ProgramError' if loading fails or the name cannot be found.
    
    231
    -loadName :: Interp -> HscEnv -> Name -> IO (ForeignHValue, [Linkable], PkgsLoaded)
    
    231
    +loadName :: Interp -> HscEnv -> Name -> IO (ForeignHValue, [LinkableUsage], PkgsLoaded)
    
    232 232
     loadName interp hsc_env name = do
    
    233 233
       initLoaderState interp hsc_env
    
    234 234
       modifyLoaderState interp $ \pls0 -> do
    
    ... ... @@ -258,7 +258,7 @@ loadDependencies
    258 258
       -> LoaderState
    
    259 259
       -> SrcSpan
    
    260 260
       -> [Module]
    
    261
    -  -> IO (LoaderState, SuccessFlag, [Linkable], PkgsLoaded) -- ^ returns the set of linkables required
    
    261
    +  -> IO (LoaderState, SuccessFlag, [LinkableUsage], PkgsLoaded) -- ^ returns the set of linkables required
    
    262 262
     -- When called, the loader state must have been initialized (see `initLoaderState`)
    
    263 263
     loadDependencies interp hsc_env pls span needed_mods = do
    
    264 264
        let opts = initLinkDepsOpts hsc_env
    
    ... ... @@ -645,7 +645,7 @@ initLinkDepsOpts hsc_env = opts
    645 645
         dflags = hsc_dflags hsc_env
    
    646 646
     
    
    647 647
         ldLoadByteCode mod locn = do
    
    648
    -      bytecode_linkable <-  findBytecodeLinkableMaybe hsc_env mod locn
    
    648
    +      bytecode_linkable <-  findBytecodeLinkableMaybe hsc_env locn
    
    649 649
           case bytecode_linkable of
    
    650 650
             Nothing -> findWholeCoreBindings hsc_env mod
    
    651 651
             Just bco -> return (Just bco)
    
    ... ... @@ -659,19 +659,14 @@ findWholeCoreBindings hsc_env mod = do
    659 659
           sequence (lookupModuleEnv eps_iface_bytecode mod)
    
    660 660
     
    
    661 661
     
    
    662
    -findBytecodeLinkableMaybe :: HscEnv -> Module -> ModLocation -> IO (Maybe Linkable)
    
    663
    -findBytecodeLinkableMaybe hsc_env mod locn = do
    
    662
    +findBytecodeLinkableMaybe :: HscEnv -> ModLocation -> IO (Maybe Linkable)
    
    663
    +findBytecodeLinkableMaybe hsc_env locn = do
    
    664 664
       let bytecode_fn    = ml_bytecode_file locn
    
    665 665
           bytecode_fn_os = ml_bytecode_file_ospath locn
    
    666 666
       maybe_bytecode_time <- modificationTimeIfExists bytecode_fn_os
    
    667 667
       case maybe_bytecode_time of
    
    668 668
         Nothing -> return Nothing
    
    669 669
         Just bytecode_time -> do
    
    670
    -      -- Also load the interface, for reasons to do with recompilation avoidance.
    
    671
    -      -- See Note [Recompilation avoidance with bytecode objects]
    
    672
    -      _ <- initIfaceLoad hsc_env $
    
    673
    -             loadInterface (text "get_reachable_nodes" <+> parens (ppr mod))
    
    674
    -                 mod ImportBySystem
    
    675 670
           bco <- readBinByteCode hsc_env bytecode_fn
    
    676 671
           return $ Just $ mkModuleByteCodeLinkable bytecode_time bco
    
    677 672
     
    
    ... ... @@ -723,7 +718,7 @@ get_reachable_nodes hsc_env mods
    723 718
       ********************************************************************* -}
    
    724 719
     
    
    725 720
     -- | Load the dependencies of a linkable, and then load the linkable itself.
    
    726
    -loadDecls :: Interp -> HscEnv -> SrcSpan -> Linkable -> IO ([Linkable], PkgsLoaded)
    
    721
    +loadDecls :: Interp -> HscEnv -> SrcSpan -> Linkable -> IO ([LinkableUsage], PkgsLoaded)
    
    727 722
     loadDecls interp hsc_env span linkable = do
    
    728 723
         -- Initialise the linker (if it's not been done already)
    
    729 724
         initLoaderState interp hsc_env
    
    ... ... @@ -823,7 +818,7 @@ loadModuleLinkables interp hsc_env pls keep_spec linkables
    823 818
         (objs, bcos) = partitionLinkables linkables
    
    824 819
     
    
    825 820
     
    
    826
    -linkableInSet :: Linkable -> LinkableSet -> Bool
    
    821
    +linkableInSet :: Linkable -> LinkableSet LinkableUsage -> Bool
    
    827 822
     linkableInSet l objs_loaded =
    
    828 823
       case lookupModuleEnv objs_loaded (linkableModule l) of
    
    829 824
             Nothing -> False
    
    ... ... @@ -952,17 +947,17 @@ dynLoadObjs interp hsc_env pls objs = do
    952 947
                             then addWay WayProf
    
    953 948
                             else id
    
    954 949
     
    
    955
    -rmDupLinkables :: LinkableSet    -- Already loaded
    
    956
    -               -> [Linkable]    -- New linkables
    
    957
    -               -> (LinkableSet,  -- New loaded set (including new ones)
    
    950
    +rmDupLinkables :: LinkableSet LinkableUsage  -- ^ Already loaded
    
    951
    +               -> [Linkable]    -- ^ New linkables
    
    952
    +               -> (LinkableSet LinkableUsage,  -- New loaded set (including new ones)
    
    958 953
                        [Linkable])  -- New linkables (excluding dups)
    
    959 954
     rmDupLinkables already ls
    
    960 955
       = go already [] ls
    
    961 956
       where
    
    962
    -    go already extras [] = (already, extras)
    
    963
    -    go already extras (l:ls)
    
    957
    +    go !already extras [] = (already, extras)
    
    958
    +    go !already extras (l:ls)
    
    964 959
             | linkableInSet l already = go already     extras     ls
    
    965
    -        | otherwise               = go (extendModuleEnv already (linkableModule l) l) (l:extras) ls
    
    960
    +        | otherwise               = go (extendModuleEnv already (linkableModule l) $! mkLinkableUsage l) (l:extras) ls
    
    966 961
     
    
    967 962
     {- **********************************************************************
    
    968 963
     
    
    ... ... @@ -1115,7 +1110,7 @@ unload_wkr interp pls@LoaderState{..} = do
    1115 1110
     
    
    1116 1111
       -- If we unloaded any object files at all, we need to purge the cache
    
    1117 1112
       -- of lookupSymbol results.
    
    1118
    -  when (not (null (filter (not . null . linkableObjs) linkables_to_unload))) $
    
    1113
    +  when (not (null (filter (not . null . linkableUsageObjs) linkables_to_unload))) $
    
    1119 1114
         purgeLookupSymbolCache interp
    
    1120 1115
     
    
    1121 1116
       let !new_pls = pls { bco_loader_state = modifyHomePackageBytecodeState bco_loader_state $ \_ -> emptyBytecodeState,
    
    ... ... @@ -1125,7 +1120,7 @@ unload_wkr interp pls@LoaderState{..} = do
    1125 1120
     
    
    1126 1121
       return new_pls
    
    1127 1122
       where
    
    1128
    -    unloadObjs :: Linkable -> IO ()
    
    1123
    +    unloadObjs :: LinkableUsage -> IO ()
    
    1129 1124
         unloadObjs lnk
    
    1130 1125
           | interpreterDynamic interp = return ()
    
    1131 1126
             -- We don't do any cleanup when linking objects with the
    
    ... ... @@ -1133,7 +1128,7 @@ unload_wkr interp pls@LoaderState{..} = do
    1133 1128
             -- not much benefit.
    
    1134 1129
     
    
    1135 1130
           | otherwise
    
    1136
    -      = mapM_ (unloadObj interp) (linkableObjs lnk)
    
    1131
    +      = mapM_ (unloadObj interp) (linkableUsageObjs lnk)
    
    1137 1132
                     -- The components of a BCO linkable may contain
    
    1138 1133
                     -- dot-o files (generated from C stubs).
    
    1139 1134
                     --
    

  • compiler/GHC/Linker/Types.hs
    ... ... @@ -49,6 +49,7 @@ module GHC.Linker.Types
    49 49
        , WholeCoreBindingsLinkable
    
    50 50
        , LinkableWith(..)
    
    51 51
        , mkModuleByteCodeLinkable
    
    52
    +   , mkOnlyModuleByteCodeLinkable
    
    52 53
        , LinkablePart(..)
    
    53 54
        , LinkableObjectSort (..)
    
    54 55
        , linkableIsNativeCodeOnly
    
    ... ... @@ -67,6 +68,11 @@ module GHC.Linker.Types
    67 68
        , linkableFilterNative
    
    68 69
        , partitionLinkables
    
    69 70
     
    
    71
    +   , LinkableUsage
    
    72
    +   , linkableUsageObjs
    
    73
    +   , mkLinkablesUsage
    
    74
    +   , mkLinkableUsage
    
    75
    +
    
    70 76
        , ModuleByteCode(..)
    
    71 77
        )
    
    72 78
     where
    
    ... ... @@ -78,26 +84,29 @@ import GHCi.BreakArray
    78 84
     import GHCi.RemoteTypes
    
    79 85
     import GHCi.Message            ( LoadedDLL )
    
    80 86
     
    
    87
    +import qualified GHC.Data.OsPath as OsPath
    
    88
    +import qualified GHC.Data.FlatBag as FlatBag
    
    89
    +import GHC.Fingerprint (Fingerprint)
    
    81 90
     import GHC.Stack.CCS
    
    82 91
     import GHC.Types.Name.Env      ( NameEnv, emptyNameEnv, extendNameEnvList, lookupNameEnv )
    
    83 92
     import GHC.Types.Name          ( Name )
    
    84 93
     import GHC.Types.SptEntry
    
    94
    +import GHC.Types.Unique.DSet
    
    95
    +import GHC.Types.Unique.DFM
    
    96
    +import GHC.Unit.Module.Deps (LinkablePartUsage (..), linkablePartUsageObjectPaths)
    
    97
    +import GHC.Unit.Module.Env
    
    98
    +import GHC.Unit.Module.WholeCoreBindings
    
    85 99
     
    
    86 100
     import GHC.Utils.Outputable
    
    87 101
     
    
    102
    +import Control.Applicative ((<|>))
    
    88 103
     import Control.Concurrent.MVar
    
    89 104
     import Data.Array
    
    105
    +import Data.Functor.Identity
    
    90 106
     import Data.Time               ( UTCTime )
    
    91
    -import GHC.Unit.Module.Env
    
    92
    -import GHC.Types.Unique.DSet
    
    93
    -import GHC.Types.Unique.DFM
    
    94
    -import GHC.Unit.Module.WholeCoreBindings
    
    95 107
     import Data.Maybe (mapMaybe)
    
    96 108
     import Data.List.NonEmpty (NonEmpty, nonEmpty)
    
    97 109
     import qualified Data.List.NonEmpty as NE
    
    98
    -import Control.Applicative ((<|>))
    
    99
    -import Data.Functor.Identity
    
    100
    -
    
    101 110
     
    
    102 111
     {- **********************************************************************
    
    103 112
     
    
    ... ... @@ -172,10 +181,10 @@ data LoaderState = LoaderState
    172 181
             -- ^ Information about bytecode objects we have loaded into the
    
    173 182
             -- interpreter.
    
    174 183
     
    
    175
    -    , bcos_loaded :: !LinkableSet
    
    184
    +    , bcos_loaded :: !(LinkableSet LinkableUsage)
    
    176 185
             -- ^ The currently loaded interpreted modules (home package)
    
    177 186
     
    
    178
    -    , objs_loaded :: !LinkableSet
    
    187
    +    , objs_loaded :: !(LinkableSet LinkableUsage)
    
    179 188
             -- ^ And the currently-loaded compiled modules (home package)
    
    180 189
     
    
    181 190
         , pkgs_loaded :: !PkgsLoaded
    
    ... ... @@ -384,15 +393,17 @@ type Linkable = LinkableWith (NonEmpty LinkablePart)
    384 393
     
    
    385 394
     type WholeCoreBindingsLinkable = LinkableWith WholeCoreBindings
    
    386 395
     
    
    387
    -type LinkableSet = ModuleEnv Linkable
    
    396
    +type LinkableUsage = LinkableWith (NonEmpty LinkablePartUsage)
    
    388 397
     
    
    389
    -mkLinkableSet :: [Linkable] -> LinkableSet
    
    398
    +type LinkableSet = ModuleEnv
    
    399
    +
    
    400
    +mkLinkableSet :: [Linkable] -> LinkableSet Linkable
    
    390 401
     mkLinkableSet ls = mkModuleEnv [(linkableModule l, l) | l <- ls]
    
    391 402
     
    
    392 403
     -- | Union of LinkableSets.
    
    393 404
     --
    
    394 405
     -- In case of conflict, keep the most recent Linkable (as per linkableTime)
    
    395
    -unionLinkableSet :: LinkableSet -> LinkableSet -> LinkableSet
    
    406
    +unionLinkableSet :: LinkableSet (LinkableWith a) -> LinkableSet (LinkableWith a) -> LinkableSet (LinkableWith a)
    
    396 407
     unionLinkableSet = plusModuleEnv_C go
    
    397 408
       where
    
    398 409
         go l1 l2
    
    ... ... @@ -435,8 +446,9 @@ data LinkablePart
    435 446
       | DotDLL FilePath
    
    436 447
           -- ^ Dynamically linked library file (.so, .dll, .dylib)
    
    437 448
     
    
    438
    -  | DotGBC ModuleByteCode
    
    439
    -    -- ^ A byte-code object, lives only in memory.
    
    449
    +  | DotGBC
    
    450
    +      -- ^ A byte-code object, lives only in memory.
    
    451
    +      ModuleByteCode
    
    440 452
     
    
    441 453
     
    
    442 454
     -- | The in-memory representation of a bytecode object
    
    ... ... @@ -444,14 +456,19 @@ data LinkablePart
    444 456
     data ModuleByteCode = ModuleByteCode { gbc_module :: Module
    
    445 457
                                           , gbc_compiled_byte_code :: CompiledByteCode
    
    446 458
                                           , gbc_foreign_files :: [FilePath]  -- ^ Path to object files
    
    459
    +                                      , gbc_hash :: !Fingerprint
    
    447 460
                                           }
    
    448 461
     
    
    449 462
     mkModuleByteCodeLinkable :: UTCTime -> ModuleByteCode -> Linkable
    
    450
    -mkModuleByteCodeLinkable linkable_time bco =
    
    463
    +mkModuleByteCodeLinkable linkable_time bco = do
    
    451 464
       Linkable linkable_time (gbc_module bco) (pure (DotGBC bco))
    
    452 465
     
    
    466
    +mkOnlyModuleByteCodeLinkable :: UTCTime -> ModuleByteCode -> LinkableWith ModuleByteCode
    
    467
    +mkOnlyModuleByteCodeLinkable linkable_time bco = do
    
    468
    +  Linkable linkable_time (gbc_module bco) bco
    
    469
    +
    
    453 470
     instance Outputable ModuleByteCode where
    
    454
    -  ppr (ModuleByteCode mod _cbc _fos) = text "ModuleByteCode" <+> ppr mod
    
    471
    +  ppr (ModuleByteCode mod _cbc _fos _) = text "ModuleByteCode" <+> ppr mod
    
    455 472
     
    
    456 473
     instance Outputable LinkablePart where
    
    457 474
       ppr (DotO path sort)   = text "DotO" <+> text path <+> pprSort sort
    
    ... ... @@ -544,8 +561,8 @@ linkablePartObjectPaths = \case
    544 561
     -- Contrary to linkableBCOs, this includes byte-code from LazyBCOs.
    
    545 562
     linkablePartBCOs :: LinkablePart -> [CompiledByteCode]
    
    546 563
     linkablePartBCOs = \case
    
    547
    -  DotGBC bco    -> [gbc_compiled_byte_code bco]
    
    548
    -  _           -> []
    
    564
    +  DotGBC bco -> [gbc_compiled_byte_code bco]
    
    565
    +  _          -> []
    
    549 566
     
    
    550 567
     linkableFilter :: (LinkablePart -> [LinkablePart]) -> Linkable -> Maybe Linkable
    
    551 568
     linkableFilter f linkable = do
    
    ... ... @@ -586,6 +603,59 @@ partitionLinkables linkables =
    586 603
         mapMaybe linkableFilterByteCode linkables
    
    587 604
       )
    
    588 605
     
    
    606
    +-- | Turn a 'Linkable' into a 'LinkableUsage'.
    
    607
    +-- This stores much less information than 'Linkable' and allows us
    
    608
    +-- to free the fields of the 'Linkable'.
    
    609
    +--
    
    610
    +-- Each 'LinkablePartUsage' is fully evaluated to avoid retaining any reference
    
    611
    +-- to the original 'LinkablePart'.
    
    612
    +mkLinkableUsage :: Linkable -> LinkableUsage
    
    613
    +mkLinkableUsage lnk =
    
    614
    +  let
    
    615
    +    linkablesWithUsage = NE.map (go (linkableModule lnk)) (linkableParts lnk)
    
    616
    +    lnkUsage = lnk
    
    617
    +      { linkableParts =
    
    618
    +          -- We force the elements intentionally to whnf.
    
    619
    +          --
    
    620
    +          elemsToWhnf linkablesWithUsage `seq` linkablesWithUsage
    
    621
    +      }
    
    622
    +  in
    
    623
    +    linkableParts lnkUsage `seq` lnkUsage
    
    624
    +  where
    
    625
    +    -- Make sure 'LinkableUsagePart' is evaluated to whnf
    
    626
    +    elemsToWhnf :: NonEmpty a -> ()
    
    627
    +    elemsToWhnf = foldr seq ()
    
    628
    +
    
    629
    +
    
    630
    +    mkFileLinkablePartUsage m fp objs =
    
    631
    +      FileLinkablePartUsage
    
    632
    +        { flu_file = fp
    
    633
    +        , flu_module = m
    
    634
    +        , flu_linkable_objs =
    
    635
    +            FlatBag.fromList (strictGenericLength objs) [ OsPath.unsafeEncodeUtf obj | obj <- objs  ]
    
    636
    +        }
    
    637
    +
    
    638
    +    mkByteCodeLinkablePartUsage m fp objs =
    
    639
    +      ByteCodeLinkablePartUsage
    
    640
    +        { bclu_module = m
    
    641
    +        , bclu_hash = fp
    
    642
    +        , bclu_linkable_objs =
    
    643
    +            FlatBag.fromList (strictGenericLength objs) [ OsPath.unsafeEncodeUtf obj | obj <- objs  ]
    
    644
    +        }
    
    645
    +
    
    646
    +    go :: Module -> LinkablePart -> LinkablePartUsage
    
    647
    +    go m lnkPart = case lnkPart of
    
    648
    +      DotO fn _ -> mkFileLinkablePartUsage m fn (linkablePartObjectPaths lnkPart)
    
    649
    +      DotA fn -> mkFileLinkablePartUsage m fn (linkablePartObjectPaths lnkPart)
    
    650
    +      DotDLL fn -> mkFileLinkablePartUsage m fn (linkablePartObjectPaths lnkPart)
    
    651
    +      DotGBC mbc -> mkByteCodeLinkablePartUsage m (gbc_hash mbc) (linkablePartObjectPaths lnkPart)
    
    652
    +
    
    653
    +mkLinkablesUsage :: [Linkable] -> [LinkableUsage]
    
    654
    +mkLinkablesUsage linkables = map mkLinkableUsage linkables
    
    655
    +
    
    656
    +linkableUsageObjs :: LinkableUsage -> [FilePath]
    
    657
    +linkableUsageObjs lnkWithUsage = concatMap linkablePartUsageObjectPaths (linkableParts lnkWithUsage)
    
    658
    +
    
    589 659
     {- **********************************************************************
    
    590 660
     
    
    591 661
                     Loading packages
    

  • compiler/GHC/Runtime/Loader.hs
    ... ... @@ -153,7 +153,7 @@ initializePlugins hsc_env
    153 153
           ([]  , _ )  -> False -- some external plugin added
    
    154 154
           (p:ps,s:ss) -> check_external_plugin p s && check_external_plugins ps ss
    
    155 155
     
    
    156
    -loadPlugins :: HscEnv -> IO ([LoadedPlugin], [Linkable], PkgsLoaded)
    
    156
    +loadPlugins :: HscEnv -> IO ([LoadedPlugin], [LinkableUsage], PkgsLoaded)
    
    157 157
     loadPlugins hsc_env
    
    158 158
       = do { unless (null to_load) $
    
    159 159
                checkExternalInterpreter hsc_env
    
    ... ... @@ -173,7 +173,7 @@ loadPlugins hsc_env
    173 173
         loadPlugin = loadPlugin' (mkVarOccFS (fsLit "plugin")) pluginTyConName hsc_env
    
    174 174
     
    
    175 175
     
    
    176
    -loadFrontendPlugin :: HscEnv -> ModuleName -> IO (FrontendPlugin, [Linkable], PkgsLoaded)
    
    176
    +loadFrontendPlugin :: HscEnv -> ModuleName -> IO (FrontendPlugin, [LinkableUsage], PkgsLoaded)
    
    177 177
     loadFrontendPlugin hsc_env mod_name = do
    
    178 178
         checkExternalInterpreter hsc_env
    
    179 179
         (plugin, _iface, links, pkgs)
    
    ... ... @@ -188,7 +188,7 @@ checkExternalInterpreter hsc_env = case interpInstance <$> hsc_interp hsc_env of
    188 188
         -> throwIO (InstallationError "Plugins require -fno-external-interpreter")
    
    189 189
       _ -> pure ()
    
    190 190
     
    
    191
    -loadPlugin' :: OccName -> Name -> HscEnv -> ModuleName -> IO (a, ModIface, [Linkable], PkgsLoaded)
    
    191
    +loadPlugin' :: OccName -> Name -> HscEnv -> ModuleName -> IO (a, ModIface, [LinkableUsage], PkgsLoaded)
    
    192 192
     loadPlugin' occ_name plugin_name hsc_env mod_name
    
    193 193
       = do { let plugin_rdr_name = mkRdrQual mod_name occ_name
    
    194 194
                  dflags = hsc_dflags hsc_env
    
    ... ... @@ -266,7 +266,7 @@ forceLoadTyCon hsc_env con_name = do
    266 266
     -- * If the Name does not exist in the module
    
    267 267
     -- * If the link failed
    
    268 268
     
    
    269
    -getValueSafely :: HscEnv -> Name -> Type -> IO (Either Type (a, [Linkable], PkgsLoaded))
    
    269
    +getValueSafely :: HscEnv -> Name -> Type -> IO (Either Type (a, [LinkableUsage], PkgsLoaded))
    
    270 270
     getValueSafely hsc_env val_name expected_type = do
    
    271 271
       eith_hval <- case getValueSafelyHook hooks of
    
    272 272
         Nothing -> getHValueSafely interp hsc_env val_name expected_type
    
    ... ... @@ -281,7 +281,7 @@ getValueSafely hsc_env val_name expected_type = do
    281 281
         logger = hsc_logger hsc_env
    
    282 282
         hooks  = hsc_hooks hsc_env
    
    283 283
     
    
    284
    -getHValueSafely :: Interp -> HscEnv -> Name -> Type -> IO (Either Type (HValue, [Linkable], PkgsLoaded))
    
    284
    +getHValueSafely :: Interp -> HscEnv -> Name -> Type -> IO (Either Type (HValue, [LinkableUsage], PkgsLoaded))
    
    285 285
     getHValueSafely interp hsc_env val_name expected_type = do
    
    286 286
         forceLoadNameModuleInterface hsc_env (text "contains a name used in an invocation of getHValueSafely") val_name
    
    287 287
         -- Now look up the names for the value and type constructor in the type environment
    

  • compiler/GHC/Tc/Types.hs
    ... ... @@ -562,7 +562,7 @@ data TcGblEnv
    562 562
               -- is implicit rather than explicit, so we have to zap a
    
    563 563
               -- mutable variable.
    
    564 564
     
    
    565
    -        tcg_th_needed_deps :: TcRef ([Linkable], PkgsLoaded),
    
    565
    +        tcg_th_needed_deps :: TcRef ([LinkableUsage], PkgsLoaded),
    
    566 566
               -- ^ The set of runtime dependencies required by this module
    
    567 567
               -- See Note [Object File Dependencies]
    
    568 568
     
    

  • compiler/GHC/Tc/Utils/Monad.hs
    ... ... @@ -2259,7 +2259,7 @@ fillCoercionHole (CH { ch_ref = ref, ch_co_var = cv }) co
    2259 2259
     recordThUse :: TcM ()
    
    2260 2260
     recordThUse = do { env <- getGblEnv; writeTcRef (tcg_th_used env) True }
    
    2261 2261
     
    
    2262
    -recordThNeededRuntimeDeps :: [Linkable] -> PkgsLoaded -> TcM ()
    
    2262
    +recordThNeededRuntimeDeps :: [LinkableUsage] -> PkgsLoaded -> TcM ()
    
    2263 2263
     recordThNeededRuntimeDeps new_links new_pkgs
    
    2264 2264
       = do { env <- getGblEnv
    
    2265 2265
            ; updTcRef (tcg_th_needed_deps env) $ \(needed_links, needed_pkgs) ->
    

  • compiler/GHC/Unit/Home/ModInfo.hs
    ... ... @@ -3,9 +3,11 @@
    3 3
     module GHC.Unit.Home.ModInfo
    
    4 4
        (
    
    5 5
          HomeModInfo (..)
    
    6
    -   , HomeModLinkable (..)
    
    7 6
        , homeModInfoObject
    
    8 7
        , homeModInfoByteCode
    
    8
    +   , HomeModLinkable (..)
    
    9
    +   , homeModLinkableByteCode
    
    10
    +   , homeModLinkableObject
    
    9 11
        , emptyHomeModInfoLinkable
    
    10 12
        )
    
    11 13
     where
    
    ... ... @@ -15,9 +17,10 @@ import GHC.Prelude
    15 17
     import GHC.Unit.Module.ModIface
    
    16 18
     import GHC.Unit.Module.ModDetails
    
    17 19
     
    
    18
    -import GHC.Linker.Types ( Linkable )
    
    20
    +import GHC.Linker.Types ( Linkable, LinkableWith, ModuleByteCode, LinkablePart (..) )
    
    19 21
     
    
    20 22
     import GHC.Utils.Outputable
    
    23
    +import qualified Data.List.NonEmpty as NE
    
    21 24
     
    
    22 25
     -- | Information about modules in the package being compiled
    
    23 26
     data HomeModInfo = HomeModInfo
    
    ... ... @@ -48,18 +51,24 @@ data HomeModInfo = HomeModInfo
    48 51
        }
    
    49 52
     
    
    50 53
     homeModInfoByteCode :: HomeModInfo -> Maybe Linkable
    
    51
    -homeModInfoByteCode = homeMod_bytecode . hm_linkable
    
    54
    +homeModInfoByteCode = homeModLinkableByteCode . hm_linkable
    
    52 55
     
    
    53 56
     homeModInfoObject :: HomeModInfo -> Maybe Linkable
    
    54
    -homeModInfoObject = homeMod_object . hm_linkable
    
    57
    +homeModInfoObject = homeModLinkableObject . hm_linkable
    
    55 58
     
    
    56 59
     emptyHomeModInfoLinkable :: HomeModLinkable
    
    57 60
     emptyHomeModInfoLinkable = HomeModLinkable Nothing Nothing
    
    58 61
     
    
    59 62
     -- See Note [Home module build products]
    
    60
    -data HomeModLinkable = HomeModLinkable { homeMod_bytecode :: !(Maybe Linkable)
    
    63
    +data HomeModLinkable = HomeModLinkable { homeMod_bytecode :: !(Maybe (LinkableWith ModuleByteCode))
    
    61 64
                                            , homeMod_object   :: !(Maybe Linkable) }
    
    62 65
     
    
    66
    +homeModLinkableByteCode :: HomeModLinkable -> Maybe Linkable
    
    67
    +homeModLinkableByteCode = fmap (fmap (NE.singleton . DotGBC)) . homeMod_bytecode
    
    68
    +
    
    69
    +homeModLinkableObject :: HomeModLinkable -> Maybe Linkable
    
    70
    +homeModLinkableObject = homeMod_object
    
    71
    +
    
    63 72
     instance Outputable HomeModLinkable where
    
    64 73
       ppr (HomeModLinkable l1 l2) = ppr l1 $$ ppr l2
    
    65 74
     
    

  • compiler/GHC/Unit/Module/Deps.hs
    ... ... @@ -22,16 +22,22 @@ module GHC.Unit.Module.Deps
    22 22
        , ImportAvails (..)
    
    23 23
        , IfaceImportLevel(..)
    
    24 24
        , tcImportLevel
    
    25
    +   , LinkablePartUsage(..)
    
    26
    +   , linkablePartUsageObjectPaths
    
    25 27
        )
    
    26 28
     where
    
    27 29
     
    
    28 30
     import GHC.Prelude
    
    29 31
     
    
    30 32
     import GHC.Data.FastString
    
    33
    +import GHC.Data.FlatBag
    
    34
    +import GHC.Data.OsPath
    
    35
    +import qualified GHC.Data.OsPath as OsPath
    
    31 36
     
    
    32 37
     import GHC.Types.Avail
    
    33 38
     import GHC.Types.SafeHaskell
    
    34 39
     import GHC.Types.Name
    
    40
    +import GHC.Types.Name.Set
    
    35 41
     import GHC.Types.Basic
    
    36 42
     
    
    37 43
     import GHC.Unit.Module.Imported
    
    ... ... @@ -43,13 +49,12 @@ import GHC.Utils.Fingerprint
    43 49
     import GHC.Utils.Binary
    
    44 50
     import GHC.Utils.Outputable
    
    45 51
     
    
    52
    +import Control.DeepSeq
    
    53
    +import Data.Bifunctor
    
    54
    +import qualified Data.Foldable as Foldable
    
    46 55
     import Data.List (sortBy, sort, partition)
    
    47 56
     import Data.Set (Set)
    
    48 57
     import qualified Data.Set as Set
    
    49
    -import Data.Bifunctor
    
    50
    -import Control.DeepSeq
    
    51
    -import GHC.Types.Name.Set
    
    52
    -
    
    53 58
     
    
    54 59
     
    
    55 60
     -- | Dependency information about ALL modules and packages below this one
    
    ... ... @@ -372,12 +377,12 @@ data Usage
    372 377
             -- we won't spot it here. If you do want to spot that, the caller
    
    373 378
             -- should recursively add them to their useage.
    
    374 379
       }
    
    375
    -  | UsageHomeModuleInterface {
    
    380
    +  | UsageHomeModuleBytecode {
    
    376 381
             usg_mod_name :: ModuleName
    
    377 382
             -- ^ Name of the module
    
    378 383
             , usg_unit_id :: UnitId
    
    379 384
             -- ^ UnitId of the HomeUnit the module is from
    
    380
    -        , usg_iface_hash :: Fingerprint
    
    385
    +        , usg_bytecode_hash :: Fingerprint
    
    381 386
             -- ^ The *interface* hash of the module, not the ABI hash.
    
    382 387
             -- This changes when anything about the interface (and hence the
    
    383 388
             -- module) has changed.
    
    ... ... @@ -412,7 +417,7 @@ instance NFData Usage where
    412 417
       rnf (UsageFile file hash label) = rnf file `seq` rnf hash `seq` rnf label `seq` ()
    
    413 418
       rnf (UsageDirectory dir hash label) = rnf dir `seq` rnf hash `seq` rnf label `seq` ()
    
    414 419
       rnf (UsageMergedRequirement mod hash) = rnf mod `seq` rnf hash `seq` ()
    
    415
    -  rnf (UsageHomeModuleInterface mod uid hash) = rnf mod `seq` rnf uid `seq` rnf hash `seq` ()
    
    420
    +  rnf (UsageHomeModuleBytecode mod uid hash) = rnf mod `seq` rnf uid `seq` rnf hash `seq` ()
    
    416 421
     
    
    417 422
     instance Binary Usage where
    
    418 423
         put_ bh usg@UsagePackageModule{} = do
    
    ... ... @@ -441,11 +446,11 @@ instance Binary Usage where
    441 446
             put_ bh (usg_mod      usg)
    
    442 447
             put_ bh (usg_mod_hash usg)
    
    443 448
     
    
    444
    -    put_ bh usg@UsageHomeModuleInterface{} = do
    
    449
    +    put_ bh usg@UsageHomeModuleBytecode{} = do
    
    445 450
             putByte bh 4
    
    446 451
             put_ bh (usg_mod_name usg)
    
    447 452
             put_ bh (usg_unit_id  usg)
    
    448
    -        put_ bh (usg_iface_hash usg)
    
    453
    +        put_ bh (usg_bytecode_hash usg)
    
    449 454
     
    
    450 455
         put_ bh usg@UsageDirectory{} = do
    
    451 456
             putByte bh 5
    
    ... ... @@ -483,7 +488,7 @@ instance Binary Usage where
    483 488
                 mod <- get bh
    
    484 489
                 uid <- get bh
    
    485 490
                 hash <- get bh
    
    486
    -            return UsageHomeModuleInterface { usg_mod_name = mod, usg_unit_id = uid, usg_iface_hash = hash }
    
    491
    +            return UsageHomeModuleBytecode { usg_mod_name = mod, usg_unit_id = uid, usg_bytecode_hash = hash }
    
    487 492
               5 -> do
    
    488 493
                 dp    <- get bh
    
    489 494
                 hash  <- get bh
    
    ... ... @@ -695,3 +700,33 @@ data ImportAvails
    695 700
               -- ^ Family instance modules below us in the import tree (and maybe
    
    696 701
               -- including us for imported modules)
    
    697 702
           }
    
    703
    +
    
    704
    +-- | Record usage of a 'LinkablePart'.
    
    705
    +data LinkablePartUsage
    
    706
    +  = FileLinkablePartUsage
    
    707
    +    { flu_file :: !FilePath
    
    708
    +    , flu_module :: !Module
    
    709
    +    , flu_linkable_objs :: !(FlatBag OsPath)
    
    710
    +    }
    
    711
    +  | ByteCodeLinkablePartUsage
    
    712
    +    { bclu_module :: !Module
    
    713
    +    , bclu_hash :: !Fingerprint
    
    714
    +    , bclu_linkable_objs :: !(FlatBag OsPath)
    
    715
    +    }
    
    716
    +
    
    717
    +instance Outputable LinkablePartUsage where
    
    718
    +  ppr = \ case
    
    719
    +    FileLinkablePartUsage fp modl _objs ->
    
    720
    +      text "FileLinkableUsage" <+> text fp <+> ppr modl
    
    721
    +
    
    722
    +    ByteCodeLinkablePartUsage modl hash _objs ->
    
    723
    +      text "ByteCodeLinkableUsage" <+> ppr modl <+> ppr hash
    
    724
    +
    
    725
    +linkablePartUsageObjectPaths :: LinkablePartUsage -> [FilePath]
    
    726
    +linkablePartUsageObjectPaths lnkUsage =
    
    727
    +  map OsPath.unsafeDecodeUtf . Foldable.toList $ linkableUsageObjectOsPaths lnkUsage
    
    728
    +
    
    729
    +linkableUsageObjectOsPaths :: LinkablePartUsage -> FlatBag OsPath
    
    730
    +linkableUsageObjectOsPaths lnkUsage = case lnkUsage of
    
    731
    +  FileLinkablePartUsage{flu_linkable_objs} -> flu_linkable_objs
    
    732
    +  ByteCodeLinkablePartUsage{bclu_linkable_objs} -> bclu_linkable_objs

  • compiler/GHC/Unit/Module/Status.hs
    ... ... @@ -18,11 +18,12 @@ import GHC.Unit.Home.ModInfo
    18 18
     import GHC.Unit.Module.ModGuts
    
    19 19
     import GHC.Unit.Module.ModIface
    
    20 20
     
    
    21
    -import GHC.Linker.Types ( Linkable, WholeCoreBindingsLinkable, linkableIsNativeCodeOnly )
    
    21
    +import GHC.Linker.Types ( Linkable, WholeCoreBindingsLinkable, linkableIsNativeCodeOnly, ModuleByteCode, LinkableWith, linkableModuleByteCodes )
    
    22 22
     
    
    23 23
     import GHC.Utils.Fingerprint
    
    24 24
     import GHC.Utils.Outputable
    
    25 25
     import GHC.Utils.Panic
    
    26
    +import GHC.Stack.Types (HasCallStack)
    
    26 27
     
    
    27 28
     -- | Status of a module in incremental compilation
    
    28 29
     data HscRecompStatus
    
    ... ... @@ -59,7 +60,7 @@ data RecompLinkables = RecompLinkables { recompLinkables_bytecode :: !RecompByte
    59 60
                                            , recompLinkables_object   :: !(Maybe Linkable) }
    
    60 61
     
    
    61 62
     data RecompBytecodeLinkable
    
    62
    -  = NormalLinkable !(Maybe Linkable)
    
    63
    +  = NormalLinkable !(Maybe (LinkableWith ModuleByteCode))
    
    63 64
       | WholeCoreBindingsLinkable !WholeCoreBindingsLinkable
    
    64 65
     
    
    65 66
     instance Outputable HscRecompStatus where
    
    ... ... @@ -86,8 +87,11 @@ safeCastHomeModLinkable (HomeModLinkable bc o) = RecompLinkables (NormalLinkable
    86 87
     justBytecode :: Either Linkable WholeCoreBindingsLinkable -> RecompLinkables
    
    87 88
     justBytecode = \case
    
    88 89
       Left lm ->
    
    90
    +    let
    
    91
    +      mbc = expectSingletonGbcLinkable lm
    
    92
    +    in
    
    89 93
         assertPpr (not (linkableIsNativeCodeOnly lm)) (ppr lm)
    
    90
    -      $ emptyRecompLinkables { recompLinkables_bytecode = NormalLinkable (Just lm) }
    
    94
    +      $ emptyRecompLinkables { recompLinkables_bytecode = NormalLinkable (Just mbc) }
    
    91 95
       Right lm -> emptyRecompLinkables { recompLinkables_bytecode = WholeCoreBindingsLinkable lm }
    
    92 96
     
    
    93 97
     justObjects :: Linkable -> RecompLinkables
    
    ... ... @@ -98,8 +102,17 @@ justObjects lm =
    98 102
     bytecodeAndObjects :: Either Linkable WholeCoreBindingsLinkable -> Linkable -> RecompLinkables
    
    99 103
     bytecodeAndObjects either_bc o = case either_bc of
    
    100 104
       Left bc ->
    
    101
    -    assertPpr (not (linkableIsNativeCodeOnly bc) && linkableIsNativeCodeOnly o) (ppr bc $$ ppr o)
    
    102
    -      $ RecompLinkables (NormalLinkable (Just bc)) (Just o)
    
    105
    +    let
    
    106
    +      mbc = expectSingletonGbcLinkable bc
    
    107
    +    in
    
    108
    +      assertPpr (not (linkableIsNativeCodeOnly bc) && linkableIsNativeCodeOnly o) (ppr bc $$ ppr o)
    
    109
    +        $ RecompLinkables (NormalLinkable (Just mbc)) (Just o)
    
    103 110
       Right bc ->
    
    104 111
         assertPpr (linkableIsNativeCodeOnly o) (ppr o)
    
    105 112
           $ RecompLinkables (WholeCoreBindingsLinkable bc) (Just o)
    
    113
    +
    
    114
    +expectSingletonGbcLinkable :: HasCallStack => Linkable -> LinkableWith ModuleByteCode
    
    115
    +expectSingletonGbcLinkable lm = case linkableModuleByteCodes lm of
    
    116
    +  [] -> pprPanic "Expected 1 ModuleByteCode in Linkable" (ppr lm)
    
    117
    +  [mbc] -> mbc <$ lm
    
    118
    +  _ -> pprPanic "Expected 1 in Linkable" (ppr lm)

  • compiler/ghc.cabal.in
    ... ... @@ -210,10 +210,12 @@ Library
    210 210
             GHC.Builtin.Uniques
    
    211 211
             GHC.Builtin.Utils
    
    212 212
             GHC.ByteCode.Asm
    
    213
    +        GHC.ByteCode.Binary
    
    213 214
             GHC.ByteCode.Breakpoints
    
    214 215
             GHC.ByteCode.InfoTable
    
    215 216
             GHC.ByteCode.Instr
    
    216 217
             GHC.ByteCode.Linker
    
    218
    +        GHC.ByteCode.Recomp.Binary
    
    217 219
             GHC.ByteCode.Serialize
    
    218 220
             GHC.ByteCode.Types
    
    219 221
             GHC.Cmm
    

  • ghc/GHCi/Leak.hs
    ... ... @@ -52,8 +52,11 @@ getLeakIndicators hsc_env =
    52 52
           return $ LeakModIndicators{..}
    
    53 53
       where
    
    54 54
         mkWeakLinkables :: HomeModLinkable -> IO [Maybe (Weak Linkable)]
    
    55
    -    mkWeakLinkables (HomeModLinkable mbc mo) =
    
    56
    -      mapM (\ln -> traverse (flip mkWeakPtr Nothing <=< evaluate) ln) [mbc, mo]
    
    55
    +    mkWeakLinkables hml =
    
    56
    +      mapM (\ln -> traverse (flip mkWeakPtr Nothing <=< evaluate) ln)
    
    57
    +        [ homeModLinkableByteCode hml
    
    58
    +        , homeModLinkableObject hml
    
    59
    +        ]
    
    57 60
     
    
    58 61
     -- | Look at the LeakIndicators collected by an earlier call to
    
    59 62
     -- `getLeakIndicators`, and print messasges if any of them are still
    

  • testsuite/tests/count-deps/CountDepsAst.stdout
    ... ... @@ -60,6 +60,7 @@ GHC.Data.FastMutInt
    60 60
     GHC.Data.FastString
    
    61 61
     GHC.Data.FastString.Env
    
    62 62
     GHC.Data.FiniteMap
    
    63
    +GHC.Data.FlatBag
    
    63 64
     GHC.Data.Graph.Directed
    
    64 65
     GHC.Data.Graph.Directed.Internal
    
    65 66
     GHC.Data.Graph.UnVar
    

  • testsuite/tests/count-deps/CountDepsParser.stdout
    ... ... @@ -61,6 +61,7 @@ GHC.Data.FastMutInt
    61 61
     GHC.Data.FastString
    
    62 62
     GHC.Data.FastString.Env
    
    63 63
     GHC.Data.FiniteMap
    
    64
    +GHC.Data.FlatBag
    
    64 65
     GHC.Data.Graph.Directed
    
    65 66
     GHC.Data.Graph.Directed.Internal
    
    66 67
     GHC.Data.Graph.Directed.Reachability
    

  • testsuite/tests/driver/multipleHomeUnits/multipleHomeUnits_recomp_th.stdout
    ... ... @@ -3,6 +3,6 @@ GHCi, version 9.15.20260122: https://www.haskell.org/ghc/ :? for help
    3 3
     [2 of 2] Compiling RecompTH         ( RecompTH.hs, interpreted )[recomp]
    
    4 4
     Ok, two modules loaded.
    
    5 5
     ghci> ghci> ghci> [1 of 2] Compiling Dep              ( Dep.hs, interpreted )[dep] [Source file changed]
    
    6
    -[2 of 2] Compiling RecompTH         ( RecompTH.hs, interpreted )[recomp] [Dep changed (interface)]
    
    6
    +[2 of 2] Compiling RecompTH         ( RecompTH.hs, interpreted )[recomp] [Dep changed (bytecode)]
    
    7 7
     Ok, two modules reloaded.
    
    8 8
     ghci> Leaving GHCi.