Hannes Siebenhandl pushed to branch wip/fendor/linkable-usage at Glasgow Haskell Compiler / GHC
Commits:
-
31a3cbc3
by fendor at 2026-03-16T14:56:24+01:00
25 changed files:
- + compiler/GHC/ByteCode/Binary.hs
- + compiler/GHC/ByteCode/Recomp/Binary.hs
- compiler/GHC/ByteCode/Serialize.hs
- compiler/GHC/Driver/Hooks.hs
- compiler/GHC/Driver/Main.hs
- compiler/GHC/Driver/Pipeline.hs
- compiler/GHC/Driver/Plugins.hs
- compiler/GHC/HsToCore/Usage.hs
- compiler/GHC/Iface/Recomp.hs
- compiler/GHC/Iface/Recomp/Types.hs
- compiler/GHC/Linker/ByteCode.hs
- compiler/GHC/Linker/Deps.hs
- compiler/GHC/Linker/Loader.hs
- compiler/GHC/Linker/Types.hs
- compiler/GHC/Runtime/Loader.hs
- compiler/GHC/Tc/Types.hs
- compiler/GHC/Tc/Utils/Monad.hs
- compiler/GHC/Unit/Home/ModInfo.hs
- compiler/GHC/Unit/Module/Deps.hs
- compiler/GHC/Unit/Module/Status.hs
- compiler/ghc.cabal.in
- ghc/GHCi/Leak.hs
- testsuite/tests/count-deps/CountDepsAst.stdout
- testsuite/tests/count-deps/CountDepsParser.stdout
- testsuite/tests/driver/multipleHomeUnits/multipleHomeUnits_recomp_th.stdout
Changes:
| 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 | +-- |
| 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 | + ] |
| ... | ... | @@ -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) |
| ... | ... | @@ -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))
|
| ... | ... | @@ -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
|
| ... | ... | @@ -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 |
| ... | ... | @@ -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 | }
|
| ... | ... | @@ -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
|
| ... | ... | @@ -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
|
| ... | ... | @@ -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 " -/ " |
| ... | ... | @@ -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) |
| ... | ... | @@ -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 | }
|
| ... | ... | @@ -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 | --
|
| ... | ... | @@ -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
|
| ... | ... | @@ -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
|
| ... | ... | @@ -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 |
| ... | ... | @@ -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) ->
|
| ... | ... | @@ -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 |
| ... | ... | @@ -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 |
| ... | ... | @@ -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) |
| ... | ... | @@ -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
|
| ... | ... | @@ -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
|
| ... | ... | @@ -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
|
| ... | ... | @@ -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
|
| ... | ... | @@ -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. |