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

Commits:

23 changed files:

Changes:

  • compiler/GHC/ByteCode/Serialize.hs
    ... ... @@ -14,6 +14,7 @@ module GHC.ByteCode.Serialize
    14 14
       , InterpreterLibraryContents(..)
    
    15 15
       , writeBytecodeLib
    
    16 16
       , readBytecodeLib
    
    17
    +  , fingerprintModuleByteCodeContents
    
    17 18
       , decodeOnDiskModuleByteCode
    
    18 19
       , decodeOnDiskBytecodeLib
    
    19 20
       )
    
    ... ... @@ -48,6 +49,7 @@ import GHC.Utils.Logger
    48 49
     import GHC.Linker.Types
    
    49 50
     import System.IO.Unsafe (unsafeInterleaveIO)
    
    50 51
     import GHC.Utils.Outputable
    
    52
    +import GHC.Utils.Fingerprint (Fingerprint, fingerprintByteString)
    
    51 53
     
    
    52 54
     {- Note [Overview of persistent bytecode]
    
    53 55
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    ... ... @@ -94,6 +96,7 @@ See Note [Recompilation avoidance with bytecode objects]
    94 96
     -- contained by 'ModuleByteCode' are stored in-memory rather than as file paths to
    
    95 97
     -- temporary files.
    
    96 98
     data OnDiskModuleByteCode = OnDiskModuleByteCode { odgbc_module :: Module
    
    99
    +                                                 , odgbc_hash :: Fingerprint
    
    97 100
                                                      , odgbc_compiled_byte_code :: CompiledByteCode
    
    98 101
                                                      , odgbc_foreign :: [ByteString]  -- ^ Contents of object files
    
    99 102
                                                      }
    
    ... ... @@ -154,7 +157,6 @@ instance Binary OnDiskBytecodeLib where
    154 157
         put_ bh bytecodeLibForeign
    
    155 158
     
    
    156 159
     
    
    157
    -
    
    158 160
     writeBytecodeLib :: BytecodeLib -> FilePath -> IO ()
    
    159 161
     writeBytecodeLib lib path = do
    
    160 162
       odbco <- encodeBytecodeLib lib
    
    ... ... @@ -174,12 +176,14 @@ readBytecodeLib hsc_env path = do
    174 176
     instance Binary OnDiskModuleByteCode where
    
    175 177
       get bh = do
    
    176 178
         odgbc_module <- get bh
    
    179
    +    odgbc_hash <- get bh
    
    177 180
         odgbc_compiled_byte_code <- get bh
    
    178 181
         odgbc_foreign <- get bh
    
    179 182
         pure OnDiskModuleByteCode {..}
    
    180 183
     
    
    181 184
       put_ bh OnDiskModuleByteCode {..} = do
    
    182 185
         put_ bh odgbc_module
    
    186
    +    put_ bh odgbc_hash
    
    183 187
         put_ bh odgbc_compiled_byte_code
    
    184 188
         put_ bh odgbc_foreign
    
    185 189
     
    
    ... ... @@ -197,7 +201,8 @@ decodeOnDiskModuleByteCode hsc_env odbco = do
    197 201
       pure $ ModuleByteCode {
    
    198 202
         gbc_module = odgbc_module odbco,
    
    199 203
         gbc_compiled_byte_code = odgbc_compiled_byte_code odbco,
    
    200
    -    gbc_foreign_files = foreign_files
    
    204
    +    gbc_foreign_files = foreign_files,
    
    205
    +    gbc_hash = odgbc_hash odbco
    
    201 206
        }
    
    202 207
     
    
    203 208
     decodeOnDiskBytecodeLib :: HscEnv -> OnDiskBytecodeLib -> IO BytecodeLib
    
    ... ... @@ -256,7 +261,8 @@ encodeOnDiskModuleByteCode bco = do
    256 261
       pure $ OnDiskModuleByteCode {
    
    257 262
         odgbc_module = gbc_module bco,
    
    258 263
         odgbc_compiled_byte_code = gbc_compiled_byte_code bco,
    
    259
    -    odgbc_foreign = foreign_contents
    
    264
    +    odgbc_foreign = foreign_contents,
    
    265
    +    odgbc_hash = gbc_hash bco
    
    260 266
        }
    
    261 267
     
    
    262 268
     -- | Read a 'ModuleByteCode' from a file.
    
    ... ... @@ -281,6 +287,15 @@ writeBinByteCode f cbc = do
    281 287
       putWithUserData QuietBinIFace NormalCompression bh odbco
    
    282 288
       writeBinMem bh f
    
    283 289
     
    
    290
    +fingerprintModuleByteCodeContents :: Module -> CompiledByteCode -> [FilePath] -> IO Fingerprint
    
    291
    +fingerprintModuleByteCodeContents modl cbc foreign_files = do
    
    292
    +  bh' <- openBinMem (1024 * 1024)
    
    293
    +  bh <- addBinNameWriter bh'
    
    294
    +  foreign_contents <- readObjectFiles foreign_files
    
    295
    +  putWithUserData QuietBinIFace NormalCompression bh
    
    296
    +    (modl, cbc, foreign_contents)
    
    297
    +  withBinBuffer bh (pure . fingerprintByteString)
    
    298
    +
    
    284 299
     instance Binary CompiledByteCode where
    
    285 300
       get bh = do
    
    286 301
         bc_bcos <- get bh
    

  • 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, [LinkableWithUsage], 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, [LinkableWithUsage], 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
    ... ... @@ -866,7 +866,7 @@ hscRecompStatus
    866 866
                | otherwise -> do
    
    867 867
                    -- Check the status of all the linkable types we might need.
    
    868 868
                    -- 1. The in-memory linkable we had at hand.
    
    869
    -               bc_in_memory_linkable <- checkByteCodeInMemory hsc_env mod_summary (homeMod_bytecode old_linkable)
    
    869
    +               bc_in_memory_linkable <- checkByteCodeInMemory hsc_env mod_summary (homeModLinkableByteCode old_linkable)
    
    870 870
                    -- 2. The bytecode object file
    
    871 871
                    bc_obj_linkable <- checkByteCodeFromObject hsc_env mod_summary
    
    872 872
                    -- 3. Bytecode from an interface's whole core bindings.
    
    ... ... @@ -1098,7 +1098,7 @@ loadIfaceByteCodeLazy ::
    1098 1098
       ModIface ->
    
    1099 1099
       ModLocation ->
    
    1100 1100
       TypeEnv ->
    
    1101
    -  IO (Maybe Linkable)
    
    1101
    +  IO (Maybe (LinkableWith ModuleByteCode))
    
    1102 1102
     loadIfaceByteCodeLazy hsc_env iface location type_env =
    
    1103 1103
       case iface_core_bindings iface location of
    
    1104 1104
         Nothing -> return Nothing
    
    ... ... @@ -1106,8 +1106,9 @@ loadIfaceByteCodeLazy hsc_env iface location type_env =
    1106 1106
           Just <$> compile wcb
    
    1107 1107
       where
    
    1108 1108
         compile decls = do
    
    1109
    -      bco <- unsafeInterleaveIO $ compileWholeCoreBindings hsc_env type_env decls
    
    1110
    -      linkable $ NE.singleton (DotGBC bco)
    
    1109
    +      bco <- unsafeInterleaveIO $ do
    
    1110
    +          compileWholeCoreBindings hsc_env type_env decls
    
    1111
    +      linkable bco
    
    1111 1112
     
    
    1112 1113
         linkable parts = do
    
    1113 1114
           if_time <- modificationTimeIfExists (ml_hi_file_ospath location)
    
    ... ... @@ -1148,14 +1149,14 @@ initWholeCoreBindings hsc_env iface details (RecompLinkables bc o) = do
    1148 1149
       where
    
    1149 1150
         type_env = md_types details
    
    1150 1151
     
    
    1151
    -    go :: RecompBytecodeLinkable -> IO (Maybe Linkable)
    
    1152
    +    go :: RecompBytecodeLinkable -> IO (Maybe (LinkableWith ModuleByteCode))
    
    1152 1153
         go (NormalLinkable l) = pure l
    
    1153 1154
         go (WholeCoreBindingsLinkable wcbl) =
    
    1154 1155
           fmap Just $ for wcbl $ \wcb -> do
    
    1155 1156
             add_iface_to_hpt iface details hsc_env
    
    1156
    -        bco <- unsafeInterleaveIO $
    
    1157
    -                       compileWholeCoreBindings hsc_env type_env wcb
    
    1158
    -        pure $ NE.singleton (DotGBC bco)
    
    1157
    +        bco <- unsafeInterleaveIO $ do
    
    1158
    +            compileWholeCoreBindings hsc_env type_env wcb
    
    1159
    +        pure bco
    
    1159 1160
     
    
    1160 1161
     -- | Hydrate interface Core bindings and compile them to bytecode.
    
    1161 1162
     --
    
    ... ... @@ -2232,20 +2233,21 @@ make user's opt into writing the files.
    2232 2233
     -}
    
    2233 2234
     
    
    2234 2235
     -- | Generate a 'ModuleByteCode' and write it to disk if `-fwrite-byte-code` is enabled.
    
    2235
    -generateAndWriteByteCodeLinkable :: HscEnv -> CgInteractiveGuts -> ModLocation -> IO Linkable
    
    2236
    +generateAndWriteByteCodeLinkable :: HscEnv -> CgInteractiveGuts -> ModLocation -> IO (LinkableWith ModuleByteCode)
    
    2236 2237
     generateAndWriteByteCodeLinkable hsc_env cgguts mod_location = do
    
    2237 2238
       bco_object <- generateAndWriteByteCode hsc_env cgguts mod_location
    
    2238 2239
       -- Either, get the same time as the .gbc file if it exists, or just the current time.
    
    2239 2240
       -- It's important the time of the linkable matches the time of the .gbc file for recompilation
    
    2240 2241
       -- checking.
    
    2241 2242
       bco_time <- maybe getCurrentTime pure =<< modificationTimeIfExists (ml_bytecode_file_ospath mod_location)
    
    2242
    -  return $ mkModuleByteCodeLinkable bco_time bco_object
    
    2243
    +  return $ mkOnlyModuleByteCodeLinkable bco_time bco_object
    
    2243 2244
     
    
    2244 2245
     mkModuleByteCode :: HscEnv -> Module -> ModLocation -> CgInteractiveGuts -> IO ModuleByteCode
    
    2245 2246
     mkModuleByteCode hsc_env mod mod_location cgguts = do
    
    2246 2247
       bcos <- hscGenerateByteCode hsc_env cgguts mod_location
    
    2247 2248
       objs <- outputAndCompileForeign hsc_env mod mod_location (cgi_foreign_files cgguts) (cgi_foreign cgguts)
    
    2248
    -  return $! ModuleByteCode mod bcos objs
    
    2249
    +  !bcos_hash <- fingerprintModuleByteCodeContents mod bcos objs
    
    2250
    +  return $! ModuleByteCode mod bcos objs bcos_hash
    
    2249 2251
     
    
    2250 2252
     -- | Generate a fresh 'ModuleByteCode' for a given module but do not write it to disk.
    
    2251 2253
     generateFreshByteCodeLinkable :: HscEnv
    
    ... ... @@ -2767,13 +2769,13 @@ hscTidy hsc_env guts = do
    2767 2769
     %*                                                                      *
    
    2768 2770
     %********************************************************************* -}
    
    2769 2771
     
    
    2770
    -hscCompileCoreExpr :: HscEnv -> SrcSpan -> CoreExpr -> IO (ForeignHValue, [Linkable], PkgsLoaded)
    
    2772
    +hscCompileCoreExpr :: HscEnv -> SrcSpan -> CoreExpr -> IO (ForeignHValue, [LinkableWithUsage], PkgsLoaded)
    
    2771 2773
     hscCompileCoreExpr hsc_env loc expr =
    
    2772 2774
       case hscCompileCoreExprHook (hsc_hooks hsc_env) of
    
    2773 2775
           Nothing -> hscCompileCoreExpr' hsc_env loc expr
    
    2774 2776
           Just h  -> h                   hsc_env loc expr
    
    2775 2777
     
    
    2776
    -hscCompileCoreExpr' :: HscEnv -> SrcSpan -> CoreExpr -> IO (ForeignHValue, [Linkable], PkgsLoaded)
    
    2778
    +hscCompileCoreExpr' :: HscEnv -> SrcSpan -> CoreExpr -> IO (ForeignHValue, [LinkableWithUsage], PkgsLoaded)
    
    2777 2779
     hscCompileCoreExpr' hsc_env srcspan ds_expr = do
    
    2778 2780
       {- Simplify it -}
    
    2779 2781
       -- Question: should we call SimpleOpt.simpleOptExpr here instead?
    
    ... ... @@ -2859,8 +2861,10 @@ hscCompileCoreExpr' hsc_env srcspan ds_expr = do
    2859 2861
     
    
    2860 2862
           {- load it -}
    
    2861 2863
           bco_time <- getCurrentTime
    
    2864
    +      !bco_hash <- fingerprintModuleByteCodeContents this_mod bcos []
    
    2865
    +      let mbc = ModuleByteCode this_mod bcos [] bco_hash
    
    2862 2866
           (mods_needed, units_needed) <- loadDecls interp hsc_env srcspan $
    
    2863
    -        Linkable bco_time this_mod $ NE.singleton $ DotGBC (ModuleByteCode this_mod bcos [])
    
    2867
    +        Linkable bco_time this_mod $ NE.singleton (DotGBC mbc)
    
    2864 2868
           -- Get the foreign reference to the name we should have just loaded.
    
    2865 2869
           mhvs <- lookupFromLoadedEnv interp (idName binding_id)
    
    2866 2870
           {- Get the HValue for the root -}
    
    ... ... @@ -2876,7 +2880,7 @@ jsCodeGen
    2876 2880
       -> Module
    
    2877 2881
       -> [(CgStgTopBinding,IdSet)]
    
    2878 2882
       -> Id
    
    2879
    -  -> IO (ForeignHValue, [Linkable], PkgsLoaded)
    
    2883
    +  -> IO (ForeignHValue, [LinkableWithUsage], PkgsLoaded)
    
    2880 2884
     jsCodeGen hsc_env srcspan i this_mod stg_binds_with_deps binding_id = do
    
    2881 2885
       let logger           = hsc_logger hsc_env
    
    2882 2886
           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 :: !([LinkableWithUsage], 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)] -> [LinkableWithUsage] -> 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
    
    ... ... @@ -190,31 +184,31 @@ for a module or not. This is similar to how the recompilation checking for the l
    190 184
     
    
    191 185
     -- | Find object files corresponding to the transitive closure of given home
    
    192 186
     -- 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
    
    195
    -      let ls = ordNubOn linkableModule (th_links_needed ++ plugins_links_needed)
    
    187
    +mkObjectUsage :: Plugins -> FinderCache -> [LinkableWithUsage] -> PkgsLoaded -> IO [Usage]
    
    188
    +mkObjectUsage plugins fc th_links_needed th_pkgs_needed = do
    
    189
    +      let ls = th_links_needed ++ plugins_links_needed
    
    196 190
               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 191
               (plugins_links_needed, plugin_pkgs_needed) = loadedPluginDeps plugins
    
    198 192
           concat <$> sequence (map linkableToUsage ls ++ map librarySpecToUsage ds)
    
    199 193
       where
    
    200
    -    linkableToUsage (Linkable _ m uls) = mapM (partToUsage m) (NE.toList uls)
    
    201
    -
    
    202
    -    msg m = moduleNameString (moduleName m) ++ "[TH] changed"
    
    194
    +    linkableToUsage :: LinkableWithUsage -> IO [Usage]
    
    195
    +    linkableToUsage (Linkable _ _m parts) = traverse partToUsage (NE.toList parts)
    
    196
    +
    
    197
    +    partToUsage link_usage =
    
    198
    +      case link_usage of
    
    199
    +        FileLinkableUsage{flu_file, flu_message} -> do
    
    200
    +          fing flu_message flu_file
    
    201
    +
    
    202
    +        ByteCodeLinkableUsage{bclu_module, bclu_hash} ->
    
    203
    +          pure $
    
    204
    +            UsageHomeModuleBytecode
    
    205
    +              { usg_mod_name = moduleName bclu_module
    
    206
    +              , usg_unit_id = toUnitId $ moduleUnit bclu_module
    
    207
    +              , usg_bytecode_hash = bclu_hash
    
    208
    +              }
    
    203 209
     
    
    204 210
         fing mmsg fn = UsageFile (mkFastString fn) <$> lookupFileCache fc fn <*> pure mmsg
    
    205 211
     
    
    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)
    
    217
    -
    
    218 212
         librarySpecToUsage :: LibrarySpec -> IO [Usage]
    
    219 213
         librarySpecToUsage (Objects os) = traverse (fing Nothing) os
    
    220 214
         librarySpecToUsage (Archive fn) = traverse (fing Nothing) [fn]
    

  • 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
    
    ... ... @@ -224,7 +229,8 @@ instance Outputable RecompReason where
    224 229
         SigsMergeChanged         -> text "Signatures to merge in changed"
    
    225 230
         ModuleChanged m          -> ppr m <+> text "changed"
    
    226 231
         ModuleChangedRaw m       -> ppr m <+> text "changed (raw)"
    
    227
    -    ModuleChangedIface m     -> ppr m <+> text "changed (interface)"
    
    232
    +    ModuleChangedIface m     -> ppr m <+> text "changed (bytecode)"
    
    233
    +    ModuleChangedBytecode m     -> ppr m <+> text "changed (interface)"
    
    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    :: [LinkableWithUsage]
    
    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, [LinkableWithUsage], 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, [LinkableWithUsage], 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
    
    ... ... @@ -667,6 +667,7 @@ findBytecodeLinkableMaybe hsc_env mod locn = do
    667 667
       case maybe_bytecode_time of
    
    668 668
         Nothing -> return Nothing
    
    669 669
         Just bytecode_time -> do
    
    670
    +      -- TODO: @fendor This must go
    
    670 671
           -- Also load the interface, for reasons to do with recompilation avoidance.
    
    671 672
           -- See Note [Recompilation avoidance with bytecode objects]
    
    672 673
           _ <- initIfaceLoad hsc_env $
    
    ... ... @@ -723,7 +724,7 @@ get_reachable_nodes hsc_env mods
    723 724
       ********************************************************************* -}
    
    724 725
     
    
    725 726
     -- | Load the dependencies of a linkable, and then load the linkable itself.
    
    726
    -loadDecls :: Interp -> HscEnv -> SrcSpan -> Linkable -> IO ([Linkable], PkgsLoaded)
    
    727
    +loadDecls :: Interp -> HscEnv -> SrcSpan -> Linkable -> IO ([LinkableWithUsage], PkgsLoaded)
    
    727 728
     loadDecls interp hsc_env span linkable = do
    
    728 729
         -- Initialise the linker (if it's not been done already)
    
    729 730
         initLoaderState interp hsc_env
    
    ... ... @@ -823,7 +824,7 @@ loadModuleLinkables interp hsc_env pls keep_spec linkables
    823 824
         (objs, bcos) = partitionLinkables linkables
    
    824 825
     
    
    825 826
     
    
    826
    -linkableInSet :: Linkable -> LinkableSet -> Bool
    
    827
    +linkableInSet :: Linkable -> LinkableSet LinkableWithUsage -> Bool
    
    827 828
     linkableInSet l objs_loaded =
    
    828 829
       case lookupModuleEnv objs_loaded (linkableModule l) of
    
    829 830
             Nothing -> False
    
    ... ... @@ -952,9 +953,9 @@ dynLoadObjs interp hsc_env pls objs = do
    952 953
                             then addWay WayProf
    
    953 954
                             else id
    
    954 955
     
    
    955
    -rmDupLinkables :: LinkableSet    -- Already loaded
    
    956
    +rmDupLinkables :: LinkableSet LinkableWithUsage    -- Already loaded
    
    956 957
                    -> [Linkable]    -- New linkables
    
    957
    -               -> (LinkableSet,  -- New loaded set (including new ones)
    
    958
    +               -> (LinkableSet LinkableWithUsage,  -- New loaded set (including new ones)
    
    958 959
                        [Linkable])  -- New linkables (excluding dups)
    
    959 960
     rmDupLinkables already ls
    
    960 961
       = go already [] ls
    
    ... ... @@ -962,7 +963,7 @@ rmDupLinkables already ls
    962 963
         go already extras [] = (already, extras)
    
    963 964
         go already extras (l:ls)
    
    964 965
             | linkableInSet l already = go already     extras     ls
    
    965
    -        | otherwise               = go (extendModuleEnv already (linkableModule l) l) (l:extras) ls
    
    966
    +        | otherwise               = go (extendModuleEnv already (linkableModule l) (mkLinkableUsage l)) (l:extras) ls
    
    966 967
     
    
    967 968
     {- **********************************************************************
    
    968 969
     
    
    ... ... @@ -974,7 +975,7 @@ rmDupLinkables already ls
    974 975
     dynLinkBCOs :: Interp -> LoaderState -> KeepModuleLinkableDefinitions -> [Linkable] -> IO LoaderState
    
    975 976
     dynLinkBCOs interp pls keep_spec bcos =
    
    976 977
     
    
    977
    -        let (bcos_loaded', new_bcos) = rmDupLinkables (bcos_loaded pls) bcos
    
    978
    +        let (bcos_loaded', new_bcos) = rmDupLinkables (bcos_loaded pls) bcos -- TODO: @fendor, convert to linkable usage here?
    
    978 979
                 pls1                     = pls { bcos_loaded = bcos_loaded' }
    
    979 980
     
    
    980 981
                 cbcs :: [CompiledByteCode]
    
    ... ... @@ -1109,13 +1110,13 @@ unload_wkr interp pls@LoaderState{..} = do
    1109 1110
       -- we're unloading some code.  -fghci-leak-check with the tests in
    
    1110 1111
       -- testsuite/ghci can detect space leaks here.
    
    1111 1112
     
    
    1112
    -  let linkables_to_unload = moduleEnvElts objs_loaded ++ moduleEnvElts bcos_loaded
    
    1113
    +  let linkables_to_unload = moduleEnvElts objs_loaded ++ moduleEnvElts bcos_loaded -- TODO: @fendor LinkableUsage here already?
    
    1113 1114
     
    
    1114 1115
       mapM_ unloadObjs linkables_to_unload
    
    1115 1116
     
    
    1116 1117
       -- If we unloaded any object files at all, we need to purge the cache
    
    1117 1118
       -- of lookupSymbol results.
    
    1118
    -  when (not (null (filter (not . null . linkableObjs) linkables_to_unload))) $
    
    1119
    +  when (not (null (filter (not . null . linkableUsageObjs) linkables_to_unload))) $
    
    1119 1120
         purgeLookupSymbolCache interp
    
    1120 1121
     
    
    1121 1122
       let !new_pls = pls { bco_loader_state = modifyHomePackageBytecodeState bco_loader_state $ \_ -> emptyBytecodeState,
    
    ... ... @@ -1125,7 +1126,7 @@ unload_wkr interp pls@LoaderState{..} = do
    1125 1126
     
    
    1126 1127
       return new_pls
    
    1127 1128
       where
    
    1128
    -    unloadObjs :: Linkable -> IO ()
    
    1129
    +    unloadObjs :: LinkableWithUsage -> IO ()
    
    1129 1130
         unloadObjs lnk
    
    1130 1131
           | interpreterDynamic interp = return ()
    
    1131 1132
             -- We don't do any cleanup when linking objects with the
    
    ... ... @@ -1133,7 +1134,7 @@ unload_wkr interp pls@LoaderState{..} = do
    1133 1134
             -- not much benefit.
    
    1134 1135
     
    
    1135 1136
           | otherwise
    
    1136
    -      = mapM_ (unloadObj interp) (linkableObjs lnk)
    
    1137
    +      = mapM_ (unloadObj interp) (linkableUsageObjs lnk)
    
    1137 1138
                     -- The components of a BCO linkable may contain
    
    1138 1139
                     -- dot-o files (generated from C stubs).
    
    1139 1140
                     --
    

  • 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,12 +68,17 @@ module GHC.Linker.Types
    67 68
        , linkableFilterNative
    
    68 69
        , partitionLinkables
    
    69 70
     
    
    71
    +   , LinkableWithUsage
    
    72
    +   , linkableUsageObjs
    
    73
    +   , mkLinkablesUsage
    
    74
    +   , mkLinkableUsage
    
    75
    +
    
    70 76
        , ModuleByteCode(..)
    
    71 77
        )
    
    72 78
     where
    
    73 79
     
    
    74 80
     import GHC.Prelude
    
    75
    -import GHC.Unit                ( UnitId, Module )
    
    81
    +import GHC.Unit                ( UnitId, Module, moduleNameString, moduleName )
    
    76 82
     import GHC.ByteCode.Types
    
    77 83
     import GHCi.BreakArray
    
    78 84
     import GHCi.RemoteTypes
    
    ... ... @@ -97,6 +103,10 @@ import Data.List.NonEmpty (NonEmpty, nonEmpty)
    97 103
     import qualified Data.List.NonEmpty as NE
    
    98 104
     import Control.Applicative ((<|>))
    
    99 105
     import Data.Functor.Identity
    
    106
    +import GHC.Unit.Module.Deps (LinkableUsage (..), linkableUsageObjectPaths)
    
    107
    +import GHC.Fingerprint (Fingerprint)
    
    108
    +import qualified GHC.Data.OsPath as OsPath
    
    109
    +import qualified GHC.Data.FlatBag as FlatBag
    
    100 110
     
    
    101 111
     
    
    102 112
     {- **********************************************************************
    
    ... ... @@ -172,10 +182,10 @@ data LoaderState = LoaderState
    172 182
             -- ^ Information about bytecode objects we have loaded into the
    
    173 183
             -- interpreter.
    
    174 184
     
    
    175
    -    , bcos_loaded :: !LinkableSet
    
    185
    +    , bcos_loaded :: !(LinkableSet LinkableWithUsage)
    
    176 186
             -- ^ The currently loaded interpreted modules (home package)
    
    177 187
     
    
    178
    -    , objs_loaded :: !LinkableSet
    
    188
    +    , objs_loaded :: !(LinkableSet LinkableWithUsage)
    
    179 189
             -- ^ And the currently-loaded compiled modules (home package)
    
    180 190
     
    
    181 191
         , pkgs_loaded :: !PkgsLoaded
    
    ... ... @@ -384,15 +394,17 @@ type Linkable = LinkableWith (NonEmpty LinkablePart)
    384 394
     
    
    385 395
     type WholeCoreBindingsLinkable = LinkableWith WholeCoreBindings
    
    386 396
     
    
    387
    -type LinkableSet = ModuleEnv Linkable
    
    397
    +type LinkableWithUsage = LinkableWith (NonEmpty LinkableUsage)
    
    398
    +
    
    399
    +type LinkableSet = ModuleEnv
    
    388 400
     
    
    389
    -mkLinkableSet :: [Linkable] -> LinkableSet
    
    401
    +mkLinkableSet :: [Linkable] -> LinkableSet Linkable
    
    390 402
     mkLinkableSet ls = mkModuleEnv [(linkableModule l, l) | l <- ls]
    
    391 403
     
    
    392 404
     -- | Union of LinkableSets.
    
    393 405
     --
    
    394 406
     -- In case of conflict, keep the most recent Linkable (as per linkableTime)
    
    395
    -unionLinkableSet :: LinkableSet -> LinkableSet -> LinkableSet
    
    407
    +unionLinkableSet :: LinkableSet (LinkableWith a) -> LinkableSet (LinkableWith a) -> LinkableSet (LinkableWith a)
    
    396 408
     unionLinkableSet = plusModuleEnv_C go
    
    397 409
       where
    
    398 410
         go l1 l2
    
    ... ... @@ -435,8 +447,9 @@ data LinkablePart
    435 447
       | DotDLL FilePath
    
    436 448
           -- ^ Dynamically linked library file (.so, .dll, .dylib)
    
    437 449
     
    
    438
    -  | DotGBC ModuleByteCode
    
    439
    -    -- ^ A byte-code object, lives only in memory.
    
    450
    +  | DotGBC
    
    451
    +      -- ^ A byte-code object, lives only in memory.
    
    452
    +      ModuleByteCode
    
    440 453
     
    
    441 454
     
    
    442 455
     -- | The in-memory representation of a bytecode object
    
    ... ... @@ -444,14 +457,19 @@ data LinkablePart
    444 457
     data ModuleByteCode = ModuleByteCode { gbc_module :: Module
    
    445 458
                                           , gbc_compiled_byte_code :: CompiledByteCode
    
    446 459
                                           , gbc_foreign_files :: [FilePath]  -- ^ Path to object files
    
    460
    +                                      , gbc_hash :: !Fingerprint
    
    447 461
                                           }
    
    448 462
     
    
    449 463
     mkModuleByteCodeLinkable :: UTCTime -> ModuleByteCode -> Linkable
    
    450
    -mkModuleByteCodeLinkable linkable_time bco =
    
    464
    +mkModuleByteCodeLinkable linkable_time bco = do
    
    451 465
       Linkable linkable_time (gbc_module bco) (pure (DotGBC bco))
    
    452 466
     
    
    467
    +mkOnlyModuleByteCodeLinkable :: UTCTime -> ModuleByteCode -> LinkableWith ModuleByteCode
    
    468
    +mkOnlyModuleByteCodeLinkable linkable_time bco = do
    
    469
    +  Linkable linkable_time (gbc_module bco) bco
    
    470
    +
    
    453 471
     instance Outputable ModuleByteCode where
    
    454
    -  ppr (ModuleByteCode mod _cbc _fos) = text "ModuleByteCode" <+> ppr mod
    
    472
    +  ppr (ModuleByteCode mod _cbc _fos _) = text "ModuleByteCode" <+> ppr mod
    
    455 473
     
    
    456 474
     instance Outputable LinkablePart where
    
    457 475
       ppr (DotO path sort)   = text "DotO" <+> text path <+> pprSort sort
    
    ... ... @@ -544,8 +562,8 @@ linkablePartObjectPaths = \case
    544 562
     -- Contrary to linkableBCOs, this includes byte-code from LazyBCOs.
    
    545 563
     linkablePartBCOs :: LinkablePart -> [CompiledByteCode]
    
    546 564
     linkablePartBCOs = \case
    
    547
    -  DotGBC bco    -> [gbc_compiled_byte_code bco]
    
    548
    -  _           -> []
    
    565
    +  DotGBC bco -> [gbc_compiled_byte_code bco]
    
    566
    +  _          -> []
    
    549 567
     
    
    550 568
     linkableFilter :: (LinkablePart -> [LinkablePart]) -> Linkable -> Maybe Linkable
    
    551 569
     linkableFilter f linkable = do
    
    ... ... @@ -586,6 +604,48 @@ partitionLinkables linkables =
    586 604
         mapMaybe linkableFilterByteCode linkables
    
    587 605
       )
    
    588 606
     
    
    607
    +
    
    608
    +mkLinkableUsage :: Linkable -> LinkableWithUsage
    
    609
    +mkLinkableUsage linkables = do
    
    610
    +  linkableUsage linkables
    
    611
    +  where
    
    612
    +    msg m = moduleNameString (moduleName m) ++ "[TH] changed"
    
    613
    +
    
    614
    +    linkableUsage lnk@Linkable{linkableParts} =
    
    615
    +      setLinkableParts lnk linkableParts
    
    616
    +
    
    617
    +    mkFileLinkableUsage m fp objs =
    
    618
    +      FileLinkableUsage
    
    619
    +        { flu_file = fp
    
    620
    +        , flu_message = Just $ msg m
    
    621
    +        , flu_linkable_objs = FlatBag.fromList (strictGenericLength objs) [ OsPath.unsafeEncodeUtf obj | obj <- objs  ]
    
    622
    +        }
    
    623
    +
    
    624
    +    mkByteCodeLinkableUsage m fp objs =
    
    625
    +      ByteCodeLinkableUsage
    
    626
    +        { bclu_module = m
    
    627
    +        , bclu_hash = fp
    
    628
    +        , bclu_linkable_objs = FlatBag.fromList (strictGenericLength objs) [ OsPath.unsafeEncodeUtf obj | obj <- objs  ]
    
    629
    +        }
    
    630
    +
    
    631
    +    setLinkableParts lnk@(Linkable{linkableModule}) parts =
    
    632
    +      lnk
    
    633
    +        { linkableParts = fmap (go linkableModule) parts
    
    634
    +        }
    
    635
    +
    
    636
    +    go :: Module -> LinkablePart -> LinkableUsage
    
    637
    +    go m lnkPart = case lnkPart of
    
    638
    +      DotO fn _ -> mkFileLinkableUsage m fn (linkablePartObjectPaths lnkPart)
    
    639
    +      DotA fn -> mkFileLinkableUsage m fn (linkablePartObjectPaths lnkPart)
    
    640
    +      DotDLL fn -> mkFileLinkableUsage m fn (linkablePartObjectPaths lnkPart)
    
    641
    +      DotGBC mbc -> mkByteCodeLinkableUsage m (gbc_hash mbc) (linkablePartObjectPaths lnkPart)
    
    642
    +
    
    643
    +mkLinkablesUsage :: [Linkable] -> [LinkableWithUsage]
    
    644
    +mkLinkablesUsage linkables = map mkLinkableUsage linkables
    
    645
    +
    
    646
    +linkableUsageObjs :: LinkableWithUsage -> [FilePath]
    
    647
    +linkableUsageObjs lnkWithUsage = concatMap linkableUsageObjectPaths (linkableParts lnkWithUsage)
    
    648
    +
    
    589 649
     {- **********************************************************************
    
    590 650
     
    
    591 651
                     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], [LinkableWithUsage], 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, [LinkableWithUsage], 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, [LinkableWithUsage], 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, [LinkableWithUsage], 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, [LinkableWithUsage], 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
    ... ... @@ -563,7 +563,7 @@ data TcGblEnv
    563 563
               -- is implicit rather than explicit, so we have to zap a
    
    564 564
               -- mutable variable.
    
    565 565
     
    
    566
    -        tcg_th_needed_deps :: TcRef ([Linkable], PkgsLoaded),
    
    566
    +        tcg_th_needed_deps :: TcRef ([LinkableWithUsage], PkgsLoaded),
    
    567 567
               -- ^ The set of runtime dependencies required by this module
    
    568 568
               -- See Note [Object File Dependencies]
    
    569 569
     
    

  • compiler/GHC/Tc/Utils/Monad.hs
    ... ... @@ -2266,7 +2266,7 @@ fillCoercionHole (CH { ch_ref = ref, ch_co_var = cv }) co
    2266 2266
     recordThUse :: TcM ()
    
    2267 2267
     recordThUse = do { env <- getGblEnv; writeTcRef (tcg_th_used env) True }
    
    2268 2268
     
    
    2269
    -recordThNeededRuntimeDeps :: [Linkable] -> PkgsLoaded -> TcM ()
    
    2269
    +recordThNeededRuntimeDeps :: [LinkableWithUsage] -> PkgsLoaded -> TcM ()
    
    2270 2270
     recordThNeededRuntimeDeps new_links new_pkgs
    
    2271 2271
       = do { env <- getGblEnv
    
    2272 2272
            ; 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,6 +22,10 @@ module GHC.Unit.Module.Deps
    22 22
        , ImportAvails (..)
    
    23 23
        , IfaceImportLevel(..)
    
    24 24
        , tcImportLevel
    
    25
    +   , LinkableUsage(..)
    
    26
    +   , linkableUsageObjectPaths
    
    27
    +   , noLinkableUsage
    
    28
    +   , combineLinkableUsage
    
    25 29
        )
    
    26 30
     where
    
    27 31
     
    
    ... ... @@ -49,7 +53,10 @@ import qualified Data.Set as Set
    49 53
     import Data.Bifunctor
    
    50 54
     import Control.DeepSeq
    
    51 55
     import GHC.Types.Name.Set
    
    52
    -
    
    56
    +import GHC.ByteCode.Types (FlatBag)
    
    57
    +import GHC.Data.OsPath
    
    58
    +import qualified Data.Foldable as Foldable
    
    59
    +import qualified GHC.Data.OsPath as OsPath
    
    53 60
     
    
    54 61
     
    
    55 62
     -- | Dependency information about ALL modules and packages below this one
    
    ... ... @@ -372,12 +379,12 @@ data Usage
    372 379
             -- we won't spot it here. If you do want to spot that, the caller
    
    373 380
             -- should recursively add them to their useage.
    
    374 381
       }
    
    375
    -  | UsageHomeModuleInterface {
    
    382
    +  | UsageHomeModuleBytecode {
    
    376 383
             usg_mod_name :: ModuleName
    
    377 384
             -- ^ Name of the module
    
    378 385
             , usg_unit_id :: UnitId
    
    379 386
             -- ^ UnitId of the HomeUnit the module is from
    
    380
    -        , usg_iface_hash :: Fingerprint
    
    387
    +        , usg_bytecode_hash :: Fingerprint
    
    381 388
             -- ^ The *interface* hash of the module, not the ABI hash.
    
    382 389
             -- This changes when anything about the interface (and hence the
    
    383 390
             -- module) has changed.
    
    ... ... @@ -412,7 +419,7 @@ instance NFData Usage where
    412 419
       rnf (UsageFile file hash label) = rnf file `seq` rnf hash `seq` rnf label `seq` ()
    
    413 420
       rnf (UsageDirectory dir hash label) = rnf dir `seq` rnf hash `seq` rnf label `seq` ()
    
    414 421
       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` ()
    
    422
    +  rnf (UsageHomeModuleBytecode mod uid hash) = rnf mod `seq` rnf uid `seq` rnf hash `seq` ()
    
    416 423
     
    
    417 424
     instance Binary Usage where
    
    418 425
         put_ bh usg@UsagePackageModule{} = do
    
    ... ... @@ -441,11 +448,11 @@ instance Binary Usage where
    441 448
             put_ bh (usg_mod      usg)
    
    442 449
             put_ bh (usg_mod_hash usg)
    
    443 450
     
    
    444
    -    put_ bh usg@UsageHomeModuleInterface{} = do
    
    451
    +    put_ bh usg@UsageHomeModuleBytecode{} = do
    
    445 452
             putByte bh 4
    
    446 453
             put_ bh (usg_mod_name usg)
    
    447 454
             put_ bh (usg_unit_id  usg)
    
    448
    -        put_ bh (usg_iface_hash usg)
    
    455
    +        put_ bh (usg_bytecode_hash usg)
    
    449 456
     
    
    450 457
         put_ bh usg@UsageDirectory{} = do
    
    451 458
             putByte bh 5
    
    ... ... @@ -483,7 +490,7 @@ instance Binary Usage where
    483 490
                 mod <- get bh
    
    484 491
                 uid <- get bh
    
    485 492
                 hash <- get bh
    
    486
    -            return UsageHomeModuleInterface { usg_mod_name = mod, usg_unit_id = uid, usg_iface_hash = hash }
    
    493
    +            return UsageHomeModuleBytecode { usg_mod_name = mod, usg_unit_id = uid, usg_bytecode_hash = hash }
    
    487 494
               5 -> do
    
    488 495
                 dp    <- get bh
    
    489 496
                 hash  <- get bh
    
    ... ... @@ -695,3 +702,38 @@ data ImportAvails
    695 702
               -- ^ Family instance modules below us in the import tree (and maybe
    
    696 703
               -- including us for imported modules)
    
    697 704
           }
    
    705
    +
    
    706
    +data LinkableUsage
    
    707
    +  = FileLinkableUsage
    
    708
    +    { flu_file :: !FilePath
    
    709
    +    , flu_message :: !(Maybe String)
    
    710
    +    , flu_linkable_objs :: !(FlatBag OsPath)
    
    711
    +    }
    
    712
    +  | ByteCodeLinkableUsage
    
    713
    +    { bclu_module :: !Module
    
    714
    +    , bclu_hash :: !Fingerprint
    
    715
    +    , bclu_linkable_objs :: !(FlatBag OsPath)
    
    716
    +    }
    
    717
    +
    
    718
    +instance Outputable LinkableUsage where
    
    719
    +  ppr = \ case
    
    720
    +    FileLinkableUsage fp mmsg _objs ->
    
    721
    +      text "FileLinkableUsage" <+> text fp <> maybe empty (\ msg -> text " " <> text msg) mmsg
    
    722
    +    ByteCodeLinkableUsage modl hash _objs ->
    
    723
    +      text "ByteCodeLinkableUsage" <+> ppr modl <+> ppr hash
    
    724
    +
    
    725
    +
    
    726
    +linkableUsageObjectPaths :: LinkableUsage -> [FilePath]
    
    727
    +linkableUsageObjectPaths lnkUsage =
    
    728
    +  map OsPath.unsafeDecodeUtf . Foldable.toList $ linkableUsageObjectOsPaths lnkUsage
    
    729
    +
    
    730
    +linkableUsageObjectOsPaths :: LinkableUsage -> FlatBag OsPath
    
    731
    +linkableUsageObjectOsPaths lnkUsage = case lnkUsage of
    
    732
    +  FileLinkableUsage{flu_linkable_objs} -> flu_linkable_objs
    
    733
    +  ByteCodeLinkableUsage{bclu_linkable_objs} -> bclu_linkable_objs
    
    734
    +
    
    735
    +noLinkableUsage :: [LinkableUsage]
    
    736
    +noLinkableUsage = []
    
    737
    +
    
    738
    +combineLinkableUsage :: [LinkableUsage] -> [LinkableUsage] -> [LinkableUsage]
    
    739
    +combineLinkableUsage a b = a ++ b

  • compiler/GHC/Unit/Module/Status.hs
    ... ... @@ -18,7 +18,7 @@ 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, linkableBCOs, linkableModuleByteCodes )
    
    22 22
     
    
    23 23
     import GHC.Utils.Fingerprint
    
    24 24
     import GHC.Utils.Outputable
    
    ... ... @@ -59,7 +59,7 @@ data RecompLinkables = RecompLinkables { recompLinkables_bytecode :: !RecompByte
    59 59
                                            , recompLinkables_object   :: !(Maybe Linkable) }
    
    60 60
     
    
    61 61
     data RecompBytecodeLinkable
    
    62
    -  = NormalLinkable !(Maybe Linkable)
    
    62
    +  = NormalLinkable !(Maybe (LinkableWith ModuleByteCode))
    
    63 63
       | WholeCoreBindingsLinkable !WholeCoreBindingsLinkable
    
    64 64
     
    
    65 65
     instance Outputable HscRecompStatus where
    
    ... ... @@ -87,7 +87,8 @@ justBytecode :: Either Linkable WholeCoreBindingsLinkable -> RecompLinkables
    87 87
     justBytecode = \case
    
    88 88
       Left lm ->
    
    89 89
         assertPpr (not (linkableIsNativeCodeOnly lm)) (ppr lm)
    
    90
    -      $ emptyRecompLinkables { recompLinkables_bytecode = NormalLinkable (Just lm) }
    
    90
    +      $ assertPpr (length (linkableBCOs lm) == 1) (text "Expected 1 DotGBC linkable" $$ ppr lm )
    
    91
    +      $ emptyRecompLinkables { recompLinkables_bytecode = NormalLinkable (Just (head (linkableModuleByteCodes lm) <$ lm)) }
    
    91 92
       Right lm -> emptyRecompLinkables { recompLinkables_bytecode = WholeCoreBindingsLinkable lm }
    
    92 93
     
    
    93 94
     justObjects :: Linkable -> RecompLinkables
    
    ... ... @@ -99,7 +100,8 @@ bytecodeAndObjects :: Either Linkable WholeCoreBindingsLinkable -> Linkable -> R
    99 100
     bytecodeAndObjects either_bc o = case either_bc of
    
    100 101
       Left bc ->
    
    101 102
         assertPpr (not (linkableIsNativeCodeOnly bc) && linkableIsNativeCodeOnly o) (ppr bc $$ ppr o)
    
    102
    -      $ RecompLinkables (NormalLinkable (Just bc)) (Just o)
    
    103
    +      $ assertPpr (length (linkableBCOs bc) == 1) (text "Expected 1 DotGBC linkable" $$ ppr bc )
    
    104
    +      $ RecompLinkables (NormalLinkable (Just (head (linkableModuleByteCodes bc) <$ bc))) (Just o)
    
    103 105
       Right bc ->
    
    104 106
         assertPpr (linkableIsNativeCodeOnly o) (ppr o)
    
    105 107
           $ RecompLinkables (WholeCoreBindingsLinkable bc) (Just o)

  • compiler/GHC/Utils/Binary.hs
    ... ... @@ -37,6 +37,7 @@ module GHC.Utils.Binary
    37 37
        tellBinWriter,
    
    38 38
        castBin,
    
    39 39
        withBinBuffer,
    
    40
    +   withReadBinBuffer,
    
    40 41
        freezeWriteHandle,
    
    41 42
        shrinkBinBuffer,
    
    42 43
        thawReadHandle,
    
    ... ... @@ -348,6 +349,12 @@ withBinBuffer (WriteBinMem _ ix_r _ arr_r) action = do
    348 349
       arr <- readIORef arr_r
    
    349 350
       action $ BS.fromForeignPtr arr 0 ix
    
    350 351
     
    
    352
    +-- | Get access to the underlying buffer.
    
    353
    +withReadBinBuffer :: ReadBinHandle -> (ByteString -> IO a) -> IO a
    
    354
    +withReadBinBuffer (ReadBinMem _ ix_r _ arr) action = do
    
    355
    +  ix <- readFastMutInt ix_r
    
    356
    +  action $ BS.fromForeignPtr arr 0 ix
    
    357
    +
    
    351 358
     unsafeUnpackBinBuffer :: ByteString -> IO ReadBinHandle
    
    352 359
     unsafeUnpackBinBuffer (BS.BS arr len) = do
    
    353 360
       ix_r <- newFastMutInt 0
    

  • 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/bytecode/TLinkable/Makefile
    1
    +TOP=../../..
    
    2
    +include $(TOP)/mk/boilerplate.mk
    
    3
    +include $(TOP)/mk/test.mk
    
    4
    +
    
    5
    +.PHONY: TLinkable_Prep
    
    6
    +TLinkable_Prep:
    
    7
    +	./genSplices
    
    8
    +	'$(TEST_HC)' $(TEST_HC_OPTS) $(ghcThWayFlags) --make -fprefer-byte-code -v0 TLinkable.hs
    
    9
    +
    
    10
    +.PHONY: TLinkable2Pre
    
    11
    +TLinkable2Pre:
    
    12
    +	./genSplices
    
    13
    +	'$(TEST_HC)' $(TEST_HC_OPTS) $(ghcThWayFlags) --make -fprefer-byte-code -fwrite-byte-code -v0 THMain.hs
    
    14
    +
    
    15
    +.PHONY: TLinkable2
    
    16
    +TLinkable2:
    
    17
    +	'$(TEST_HC)' $(TEST_HC_OPTS) $(ghcThWayFlags) -c -fprefer-byte-code -fwrite-byte-code -v0 THMain.hs

  • testsuite/tests/bytecode/TLinkable/all.T
    1
    +# Test ideas
    
    2
    +# Bytecode libraries
    
    3
    +# Depend on that bytecode, look at the bytecode library tests to make sure this ends up in the EPS
    
    4
    +
    
    5
    +# test('TLinkable',
    
    6
    +#      [ collect_compiler_stats('bytes allocated',2),
    
    7
    +#        pre_cmd('$MAKE -s --no-print-directory TLinkablePre'),
    
    8
    +#        extra_files(['genSplices']),
    
    9
    +#      ],
    
    10
    +#      makefile_test,
    
    11
    +#      ['TLinkable'])
    
    12
    +
    
    13
    +# A performance test for calculating link dependencies in -c mode.
    
    14
    +test('TLinkable',
    
    15
    +     [ collect_compiler_stats('bytes allocated',2),
    
    16
    +       pre_cmd('$MAKE -s --no-print-directory TLinkable_Prep'),
    
    17
    +       extra_files(['genSplices']),
    
    18
    +       compile_timeout_multiplier(5),
    
    19
    +       when(arch('wasm32'), fragile(25336)),
    
    20
    +     ],
    
    21
    +     compile,
    
    22
    +     ['-fforce-recomp ' + config.ghc_th_way_flags])

  • testsuite/tests/bytecode/TLinkable/genSplices
    1
    +#!/bin/bash
    
    2
    +
    
    3
    +# Generate NMOD Haskell modules, each with NDEF NOINLINE functions
    
    4
    +# Usage: ./genSplices <NMOD> <NDEF>
    
    5
    +
    
    6
    +NMOD=${1:-20}  # Default 20 modules
    
    7
    +NDEF=${2:-50} # Default 50 functions per module
    
    8
    +
    
    9
    +# Generate the modules
    
    10
    +for ((i=1; i<=NMOD; i++)); do
    
    11
    +    module_name="Module$(printf "%03d" $i)"
    
    12
    +    file_path="${module_name}.hs"
    
    13
    +
    
    14
    +    cat > "$file_path" << EOF
    
    15
    +module ${module_name} where
    
    16
    +
    
    17
    +EOF
    
    18
    +
    
    19
    +    for ((j=1; j<=NDEF; j++)); do
    
    20
    +        func_name="func$(printf "%03d" $j)"
    
    21
    +        cat >> "$file_path" << EOF
    
    22
    +{-# NOINLINE ${func_name} #-}
    
    23
    +${func_name} :: Int -> Int
    
    24
    +${func_name} x = x + ${j}
    
    25
    +
    
    26
    +EOF
    
    27
    +    done
    
    28
    +done
    
    29
    +
    
    30
    +# Generate imports section
    
    31
    +imports=""
    
    32
    +for ((i=1; i<=NMOD; i++)); do
    
    33
    +    imports="${imports}import Module$(printf "%03d" $i)
    
    34
    +"
    
    35
    +done
    
    36
    +
    
    37
    +# Generate the hard-coded TH expression
    
    38
    +# Build: Module001.func001 1 + Module001.func002 2 + ... + Module{NMOD}.func{NDEF} {NMOD*NDEF}
    
    39
    +expression=""
    
    40
    +count=1
    
    41
    +for ((i=1; i<=NMOD; i++)); do
    
    42
    +    mod_name="Module$(printf "%03d" $i)"
    
    43
    +    for ((j=1; j<=NDEF; j++)); do
    
    44
    +        func_name="func$(printf "%03d" $j)"
    
    45
    +        if [ $count -gt 1 ]; then
    
    46
    +            expression="${expression} + "
    
    47
    +        fi
    
    48
    +        expression="${expression}${mod_name}.${func_name} ${count}"
    
    49
    +        ((count++))
    
    50
    +    done
    
    51
    +done
    
    52
    +
    
    53
    +# Generate the TH splice file
    
    54
    +cat > TLinkable.hs << EOF
    
    55
    +{-# LANGUAGE TemplateHaskell #-}
    
    56
    +
    
    57
    +module TLinkable where
    
    58
    +import Language.Haskell.TH.Syntax (Lift(..))
    
    59
    +
    
    60
    +-- Import all generated modules
    
    61
    +${imports}
    
    62
    +-- Hard-coded splice that references ALL functions from ALL modules
    
    63
    +result :: Int
    
    64
    +result = \$(lift \$ ${expression})
    
    65
    +
    
    66
    +main :: IO ()
    
    67
    +main = do
    
    68
    +    putStrLn \$ "Result: " ++ show result
    
    69
    +EOF