Torsten Schmits pushed to branch wip/torsten.schmits/worker-gbc at Glasgow Haskell Compiler / GHC
Commits:
-
373fc0f2
by Torsten Schmits at 2026-09-29T00:09:36+02:00
5 changed files:
- compiler/GHC/Driver/Env/Types.hs
- compiler/GHC/Driver/Main.hs
- compiler/GHC/Linker/Deps.hs
- compiler/GHC/Linker/Loader.hs
- compiler/GHC/Linker/Types.hs
Changes:
| ... | ... | @@ -29,6 +29,7 @@ import Control.Monad.Trans.Reader |
| 29 | 29 | import Control.Monad.Trans.State
|
| 30 | 30 | import Data.IORef
|
| 31 | 31 | import GHC.Driver.Env.KnotVars
|
| 32 | +import GHC.Linker.Types (LoaderState, Linkables)
|
|
| 32 | 33 | |
| 33 | 34 | -- | The Hsc monad: Passing an environment and diagnostic state
|
| 34 | 35 | newtype Hsc a = Hsc (HscEnv -> Messages GhcMessage -> IO (a, Messages GhcMessage))
|
| ... | ... | @@ -50,7 +51,6 @@ instance ContainsDynFlags HscEnv where |
| 50 | 51 | instance HasLogger Hsc where
|
| 51 | 52 | getLogger = Hsc $ \e w -> return (hsc_logger e, w)
|
| 52 | 53 | |
| 53 | - |
|
| 54 | 54 | -- | HscEnv is like 'GHC.Driver.Monad.Session', except that some of the fields are immutable.
|
| 55 | 55 | -- An HscEnv is used to compile a single module from plain Haskell source
|
| 56 | 56 | -- code (after preprocessing) to either C, assembly or C--. It's also used
|
| ... | ... | @@ -90,6 +90,8 @@ data HscEnv |
| 90 | 90 | -- ^ target code interpreter (if any) to use for TH and GHCi.
|
| 91 | 91 | -- See Note [Target code interpreter]
|
| 92 | 92 | |
| 93 | + , hsc_linkables :: HscEnv -> LoaderState -> IO Linkables
|
|
| 94 | + |
|
| 93 | 95 | , hsc_plugins :: !Plugins
|
| 94 | 96 | -- ^ Plugins
|
| 95 | 97 |
| ... | ... | @@ -342,6 +342,7 @@ newHscEnvWithHUG top_dir top_dynflags cur_unit home_unit_graph = do |
| 342 | 342 | , hsc_FC = fc_var
|
| 343 | 343 | , hsc_type_env_vars = emptyKnotVars
|
| 344 | 344 | , hsc_interp = Nothing
|
| 345 | + , hsc_linkables = linkablesDefault
|
|
| 345 | 346 | , hsc_unit_env = unit_env
|
| 346 | 347 | , hsc_plugins = emptyPlugins
|
| 347 | 348 | , hsc_hooks = emptyHooks
|
| ... | ... | @@ -2936,10 +2937,10 @@ jsCodeGen hsc_env srcspan i this_mod stg_binds_with_deps binding_id = do |
| 2936 | 2937 | |
| 2937 | 2938 | -- Take lock for the actual work.
|
| 2938 | 2939 | (dep_linkables, dep_units) <- modifyLoaderState interp $ \pls -> do
|
| 2939 | - let link_opts = initLinkDepsOpts hsc_env
|
|
| 2940 | 2940 | |
| 2941 | 2941 | -- Find what packages and linkables are required
|
| 2942 | - deps <- getLinkDeps link_opts interp pls srcspan needed_mods
|
|
| 2942 | + linkables <- hsc_linkables hsc_env hsc_env pls
|
|
| 2943 | + deps <- linkablesGet linkables srcspan needed_mods
|
|
| 2943 | 2944 | -- We update the LinkerState even if the JS interpreter maintains its linker
|
| 2944 | 2945 | -- state independently to load new objects here.
|
| 2945 | 2946 |
| ... | ... | @@ -11,6 +11,9 @@ module GHC.Linker.Deps |
| 11 | 11 | ( LinkDepsOpts (..)
|
| 12 | 12 | , LinkDeps (..)
|
| 13 | 13 | , getLinkDeps
|
| 14 | + , Linkables (..)
|
|
| 15 | + , resolveLinkDeps
|
|
| 16 | + , selectLinkDeps
|
|
| 14 | 17 | )
|
| 15 | 18 | where
|
| 16 | 19 | |
| ... | ... | @@ -62,13 +65,6 @@ data LinkDepsOpts = LinkDepsOpts |
| 62 | 65 | , ldGetDependencies :: !([Module] -> IO ([Module], UniqDSet UnitId))
|
| 63 | 66 | }
|
| 64 | 67 | |
| 65 | -data LinkDeps = LinkDeps
|
|
| 66 | - { ldNeededLinkables :: [Linkable]
|
|
| 67 | - , ldAllLinkables :: [LinkableUsage]
|
|
| 68 | - , ldUnits :: [UnitId]
|
|
| 69 | - , ldNeededUnits :: UniqDSet UnitId
|
|
| 70 | - }
|
|
| 71 | - |
|
| 72 | 68 | -- | Find all the packages and linkables that a set of modules depends on
|
| 73 | 69 | --
|
| 74 | 70 | -- Return the module and package dependencies for the needed modules.
|
| ... | ... | @@ -84,22 +80,20 @@ getLinkDeps |
| 84 | 80 | -> [Module] -- If you need these
|
| 85 | 81 | -> IO LinkDeps -- ... then link these first
|
| 86 | 82 | getLinkDeps opts interp pls span mods = do
|
| 87 | - -- The interpreter and dynamic linker can only handle object code built
|
|
| 88 | - -- the "normal" way, i.e. no non-std ways like profiling or ticky-ticky.
|
|
| 89 | - -- So here we check the build tag: if we're building a non-standard way
|
|
| 90 | - -- then we need to find & link object files built the "normal" way.
|
|
| 91 | - maybe_normal_osuf <- checkNonStdWay opts interp span
|
|
| 92 | - |
|
| 93 | - get_link_deps opts pls maybe_normal_osuf span mods
|
|
| 83 | + linkables <- resolveLinkDeps opts pls span mods
|
|
| 84 | + selectLinkDeps opts interp span linkables
|
|
| 94 | 85 | |
| 95 | -get_link_deps
|
|
| 86 | +-- | Compute the transitive dependencies of the given modules and split them
|
|
| 87 | +-- into those that are already loaded and those that need to be linked.
|
|
| 88 | +--
|
|
| 89 | +-- Returns @(loaded linkables, needed modules, needed units, all units)@.
|
|
| 90 | +resolveLinkDeps
|
|
| 96 | 91 | :: LinkDepsOpts
|
| 97 | 92 | -> LoaderState
|
| 98 | - -> Maybe FilePath -- replace object suffixes?
|
|
| 99 | 93 | -> SrcSpan
|
| 100 | 94 | -> [Module]
|
| 101 | - -> IO LinkDeps
|
|
| 102 | -get_link_deps opts pls maybe_normal_osuf span mods = do
|
|
| 95 | + -> IO ([LinkableUsage], [Module], [UnitId], UniqDSet UnitId)
|
|
| 96 | +resolveLinkDeps opts pls _span mods = do
|
|
| 103 | 97 | |
| 104 | 98 | -- Three step process:
|
| 105 | 99 | |
| ... | ... | @@ -120,6 +114,33 @@ get_link_deps opts pls maybe_normal_osuf span mods = do |
| 120 | 114 | Just linkable -> Right linkable
|
| 121 | 115 | Nothing -> Left mod
|
| 122 | 116 | |
| 117 | + pure (links_got, mods_needed, pkgs_needed, pkgs_s)
|
|
| 118 | + where
|
|
| 119 | + relevant_mods = filterOut isInteractiveModule mods
|
|
| 120 | + |
|
| 121 | +-- | Find the linkables for the modules that need to be loaded, as determined
|
|
| 122 | +-- by 'resolveLinkDeps'.
|
|
| 123 | +selectLinkDeps
|
|
| 124 | + :: LinkDepsOpts
|
|
| 125 | + -> Interp
|
|
| 126 | + -> SrcSpan -- for error messages
|
|
| 127 | + -> ([LinkableUsage], [Module], [UnitId], UniqDSet UnitId)
|
|
| 128 | + -> IO LinkDeps -- ... then link these first
|
|
| 129 | +selectLinkDeps opts interp span linkables = do
|
|
| 130 | + -- The interpreter and dynamic linker can only handle object code built
|
|
| 131 | + -- the "normal" way, i.e. no non-std ways like profiling or ticky-ticky.
|
|
| 132 | + -- So here we check the build tag: if we're building a non-standard way
|
|
| 133 | + -- then we need to find & link object files built the "normal" way.
|
|
| 134 | + maybe_normal_osuf <- checkNonStdWay opts interp span
|
|
| 135 | + select_link_deps opts maybe_normal_osuf span linkables
|
|
| 136 | + |
|
| 137 | +select_link_deps
|
|
| 138 | + :: LinkDepsOpts
|
|
| 139 | + -> Maybe FilePath -- replace object suffixes?
|
|
| 140 | + -> SrcSpan
|
|
| 141 | + -> ([LinkableUsage], [Module], [UnitId], UniqDSet UnitId)
|
|
| 142 | + -> IO LinkDeps
|
|
| 143 | +select_link_deps opts maybe_normal_osuf span (links_got, mods_needed, pkgs_needed, pkgs_s) = do
|
|
| 123 | 144 | -- 3. For each dependent module, find its linkable
|
| 124 | 145 | -- This will either be in the HPT or (in the case of one-shot
|
| 125 | 146 | -- compilation) we may need to use maybe_getFileLinkable
|
| ... | ... | @@ -139,7 +160,6 @@ get_link_deps opts pls maybe_normal_osuf span mods = do |
| 139 | 160 | return link_deps
|
| 140 | 161 | where
|
| 141 | 162 | unit_env = ldUnitEnv opts
|
| 142 | - relevant_mods = filterOut isInteractiveModule mods
|
|
| 143 | 163 | |
| 144 | 164 | no_obj :: Outputable a => a -> IO b
|
| 145 | 165 | no_obj mod = dieWith opts span $
|
| ... | ... | @@ -36,6 +36,7 @@ module GHC.Linker.Loader |
| 36 | 36 | , initLinkDepsOpts
|
| 37 | 37 | , getGccSearchDirectory
|
| 38 | 38 | , mkDynLoadLib
|
| 39 | + , linkablesDefault
|
|
| 39 | 40 | )
|
| 40 | 41 | where
|
| 41 | 42 | |
| ... | ... | @@ -253,10 +254,10 @@ loadDependencies |
| 253 | 254 | -> IO (LoaderState, SuccessFlag, [LinkableUsage], PkgsLoaded) -- ^ returns the set of linkables required
|
| 254 | 255 | -- When called, the loader state must have been initialized (see `initLoaderState`)
|
| 255 | 256 | loadDependencies interp hsc_env pls span needed_mods = do
|
| 256 | - let opts = initLinkDepsOpts hsc_env
|
|
| 257 | + linkables <- hsc_linkables hsc_env hsc_env pls
|
|
| 257 | 258 | |
| 258 | 259 | -- Find what packages and linkables are required
|
| 259 | - deps <- getLinkDeps opts interp pls span needed_mods
|
|
| 260 | + deps <- linkablesGet linkables span needed_mods
|
|
| 260 | 261 | |
| 261 | 262 | let this_pkgs_needed = ldNeededUnits deps
|
| 262 | 263 | |
| ... | ... | @@ -651,6 +652,18 @@ findWholeCoreBindings hsc_env mod = do |
| 651 | 652 | sequence (lookupModuleEnv eps_iface_bytecode mod)
|
| 652 | 653 | |
| 653 | 654 | |
| 655 | +linkablesDefault ::
|
|
| 656 | + HscEnv ->
|
|
| 657 | + LoaderState ->
|
|
| 658 | + IO Linkables
|
|
| 659 | +linkablesDefault hsc_env pls =
|
|
| 660 | + pure Linkables {
|
|
| 661 | + linkablesResolve = resolveLinkDeps opts pls,
|
|
| 662 | + linkablesSelect = selectLinkDeps opts (hscInterp hsc_env)
|
|
| 663 | + }
|
|
| 664 | + where
|
|
| 665 | + opts = initLinkDepsOpts hsc_env
|
|
| 666 | + |
|
| 654 | 667 | findBytecodeLinkableMaybe :: HscEnv -> ModLocation -> IO (Maybe Linkable)
|
| 655 | 668 | findBytecodeLinkableMaybe hsc_env locn = do
|
| 656 | 669 | let bytecode_fn = ml_bytecode_file locn
|
| 1 | 1 | {-# LANGUAGE TypeApplications #-}
|
| 2 | 2 | {-# LANGUAGE LambdaCase #-}
|
| 3 | 3 | {-# LANGUAGE DeriveTraversable #-}
|
| 4 | +{-# LANGUAGE RecordWildCards #-}
|
|
| 5 | +{-# LANGUAGE GADTs #-}
|
|
| 4 | 6 | |
| 5 | 7 | -----------------------------------------------------------------------------
|
| 6 | 8 | --
|
| ... | ... | @@ -78,6 +80,9 @@ module GHC.Linker.Types |
| 78 | 80 | , mkLinkableUsage
|
| 79 | 81 | |
| 80 | 82 | , ModuleByteCode(..)
|
| 83 | + , LinkDeps (..)
|
|
| 84 | + , Linkables (..)
|
|
| 85 | + , linkablesGet
|
|
| 81 | 86 | )
|
| 82 | 87 | where
|
| 83 | 88 | |
| ... | ... | @@ -95,6 +100,7 @@ import GHC.Stack.CCS |
| 95 | 100 | import GHC.Types.Name.Env ( NameEnv, emptyNameEnv, extendNameEnvList, lookupNameEnv )
|
| 96 | 101 | import GHC.Types.Name ( Name )
|
| 97 | 102 | import GHC.Types.SptEntry
|
| 103 | +import GHC.Types.SrcLoc (SrcSpan)
|
|
| 98 | 104 | import GHC.Types.Unique.DSet
|
| 99 | 105 | import GHC.Types.Unique.DFM
|
| 100 | 106 | import GHC.Unit.Module.Deps (LinkablePartUsage (..), linkablePartUsageObjectPaths)
|
| ... | ... | @@ -693,3 +699,23 @@ instance Outputable LibrarySpec where |
| 693 | 699 | ppr (DLLPath f) = text "DLLPath" <+> text f
|
| 694 | 700 | ppr (Framework s) = text "Framework" <+> text s
|
| 695 | 701 | ppr (BytecodeLibrary f) = text "BytecodeLibrary" <+> text f
|
| 702 | + |
|
| 703 | +data LinkDeps = LinkDeps
|
|
| 704 | + { ldNeededLinkables :: [Linkable]
|
|
| 705 | + , ldAllLinkables :: [LinkableUsage]
|
|
| 706 | + , ldUnits :: [UnitId]
|
|
| 707 | + , ldNeededUnits :: UniqDSet UnitId
|
|
| 708 | + }
|
|
| 709 | + |
|
| 710 | +-- | Customizable procedure for determining the linkables required by a set of
|
|
| 711 | +-- modules, split into a resolution phase and a selection phase with an
|
|
| 712 | +-- intermediate representation that is opaque to consumers.
|
|
| 713 | +data Linkables where
|
|
| 714 | + Linkables :: {
|
|
| 715 | + linkablesResolve :: SrcSpan -> [Module] -> IO a,
|
|
| 716 | + linkablesSelect :: SrcSpan -> a -> IO LinkDeps
|
|
| 717 | + } -> Linkables
|
|
| 718 | + |
|
| 719 | +linkablesGet :: Linkables -> SrcSpan -> [Module] -> IO LinkDeps
|
|
| 720 | +linkablesGet Linkables {..} span mods =
|
|
| 721 | + linkablesSelect span =<< linkablesResolve span mods |