[Git][ghc/ghc][wip/romes/step-out-9] ghci: Allocate BreakArrays at link time only
by Rodrigo Mesquita (@alt-romes) 03 Jul '25
by Rodrigo Mesquita (@alt-romes) 03 Jul '25
03 Jul '25
Rodrigo Mesquita pushed to branch wip/romes/step-out-9 at Glasgow Haskell Compiler / GHC
Commits:
af76b3d2 by Rodrigo Mesquita at 2025-07-03T10:32:38+01:00
ghci: Allocate BreakArrays at link time only
Previously, a BreakArray would be allocated with a slot for every tick
in a module at `mkModBreaks`, in HsToCore. However, this approach has
a few downsides:
- It interleaves interpreter behaviour (allocating arrays for
breakpoints) within the desugarer
- It is inflexible in the sense it is impossible for the bytecode
generator to add "internal" breakpoints that can be triggered at
runtime, because those wouldn't have a source tick. (This is relevant
for our intended implementation plan of step-out in #26042)
- It ties the BreakArray indices to the *tick* indexes, while at runtime
we would rather just have the *info* indexes (currently we have both
because BreakArrays are indexed by the *tick* one).
Paving the way for #26042 and #26064, this commit moves the allocation
of BreakArrays to bytecode-loading time -- akin to what is done for CCS
arrays.
Since a BreakArray is allocated only when bytecode is linked, if a
breakpoint is set (e.g. `:break 10`) before the bytecode is linked,
there will exist no BreakArray to trigger the breakpoint in.
Therefore, the function to allocate break arrays (`allocateBreakArrays`)
is exposed and also used in GHC.Runtime.Eval to allocate a break array
when a breakpoint is set, if it doesn't exist yet (in the linker env).
- - - - -
10 changed files:
- compiler/GHC/ByteCode/Linker.hs
- compiler/GHC/HsToCore.hs
- compiler/GHC/HsToCore/Breakpoints.hs
- compiler/GHC/Linker/Loader.hs
- compiler/GHC/Linker/Types.hs
- compiler/GHC/Runtime/Eval.hs
- − compiler/GHC/Runtime/Interpreter.hs-boot
- − compiler/GHC/Runtime/Interpreter/Types.hs-boot
- testsuite/tests/count-deps/CountDepsAst.stdout
- testsuite/tests/count-deps/CountDepsParser.stdout
Changes:
=====================================
compiler/GHC/ByteCode/Linker.hs
=====================================
@@ -58,15 +58,16 @@ linkBCO
:: Interp
-> PkgsLoaded
-> LinkerEnv
+ -> LinkedBreaks
-> NameEnv Int
-> UnlinkedBCO
-> IO ResolvedBCO
-linkBCO interp pkgs_loaded le bco_ix
+linkBCO interp pkgs_loaded le lb bco_ix
(UnlinkedBCO _ arity insns bitmap lits0 ptrs0) = do
-- fromIntegral Word -> Word64 should be a no op if Word is Word64
-- otherwise it will result in a cast to longlong on 32bit systems.
- (lits :: [Word]) <- mapM (fmap fromIntegral . lookupLiteral interp pkgs_loaded le) (elemsFlatBag lits0)
- ptrs <- mapM (resolvePtr interp pkgs_loaded le bco_ix) (elemsFlatBag ptrs0)
+ (lits :: [Word]) <- mapM (fmap fromIntegral . lookupLiteral interp pkgs_loaded le lb) (elemsFlatBag lits0)
+ ptrs <- mapM (resolvePtr interp pkgs_loaded le lb bco_ix) (elemsFlatBag ptrs0)
let lits' = listArray (0 :: Int, fromIntegral (sizeFlatBag lits0)-1) lits
return $ ResolvedBCO { resolvedBCOIsLE = isLittleEndian
, resolvedBCOArity = arity
@@ -76,8 +77,8 @@ linkBCO interp pkgs_loaded le bco_ix
, resolvedBCOPtrs = addListToSS emptySS ptrs
}
-lookupLiteral :: Interp -> PkgsLoaded -> LinkerEnv -> BCONPtr -> IO Word
-lookupLiteral interp pkgs_loaded le ptr = case ptr of
+lookupLiteral :: Interp -> PkgsLoaded -> LinkerEnv -> LinkedBreaks -> BCONPtr -> IO Word
+lookupLiteral interp pkgs_loaded le lb ptr = case ptr of
BCONPtrWord lit -> return lit
BCONPtrLbl sym -> do
Ptr a# <- lookupStaticPtr interp sym
@@ -99,7 +100,7 @@ lookupLiteral interp pkgs_loaded le ptr = case ptr of
pure $ fromIntegral p
BCONPtrCostCentre BreakpointId{..}
| interpreterProfiled interp -> do
- case expectJust (lookupModuleEnv (ccs_env le) bi_tick_mod) ! bi_tick_index of
+ case expectJust (lookupModuleEnv (ccs_env lb) bi_tick_mod) ! bi_tick_index of
RemotePtr p -> pure $ fromIntegral p
| otherwise ->
case toRemotePtr nullPtr of
@@ -158,10 +159,11 @@ resolvePtr
:: Interp
-> PkgsLoaded
-> LinkerEnv
+ -> LinkedBreaks
-> NameEnv Int
-> BCOPtr
-> IO ResolvedBCOPtr
-resolvePtr interp pkgs_loaded le bco_ix ptr = case ptr of
+resolvePtr interp pkgs_loaded le lb bco_ix ptr = case ptr of
BCOPtrName nm
| Just ix <- lookupNameEnv bco_ix nm
-> return (ResolvedBCORef ix) -- ref to another BCO in this group
@@ -182,10 +184,10 @@ resolvePtr interp pkgs_loaded le bco_ix ptr = case ptr of
-> ResolvedBCOStaticPtr <$> lookupPrimOp interp pkgs_loaded op
BCOPtrBCO bco
- -> ResolvedBCOPtrBCO <$> linkBCO interp pkgs_loaded le bco_ix bco
+ -> ResolvedBCOPtrBCO <$> linkBCO interp pkgs_loaded le lb bco_ix bco
BCOPtrBreakArray tick_mod ->
- withForeignRef (expectJust (lookupModuleEnv (breakarray_env le) tick_mod)) $
+ withForeignRef (expectJust (lookupModuleEnv (breakarray_env lb) tick_mod)) $
\ba -> pure $ ResolvedBCOPtrBreakArray ba
-- | Look up the address of a Haskell symbol in the currently
=====================================
compiler/GHC/HsToCore.hs
=====================================
@@ -97,8 +97,8 @@ import GHC.Unit.Module.Deps
import Data.List (partition)
import Data.IORef
-import Data.Traversable (for)
import GHC.Iface.Make (mkRecompUsageInfo)
+import GHC.Runtime.Interpreter (interpreterProfiled)
{-
************************************************************************
@@ -162,13 +162,12 @@ deSugar hsc_env
mod mod_loc
export_set (typeEnvTyCons type_env) binds
else return (binds, Nothing)
- ; modBreaks <- for
- [ (i, s)
- | i <- hsc_interp hsc_env
- , (_, s) <- m_tickInfo
- , breakpointsAllowed dflags
- ]
- $ \(interp, specs) -> mkModBreaks interp mod specs
+ ; let modBreaks
+ | Just (_, specs) <- m_tickInfo
+ , breakpointsAllowed dflags
+ = Just $ mkModBreaks (interpreterProfiled $ hscInterp hsc_env) mod specs
+ | otherwise
+ = Nothing
; ds_hpc_info <- case m_tickInfo of
Just (orig_file2, ticks)
=====================================
compiler/GHC/HsToCore/Breakpoints.hs
=====================================
@@ -33,14 +33,6 @@ import GHC.Unit.Module (Module)
import GHC.Utils.Outputable
import Data.List (intersperse)
-import GHCi.BreakArray (BreakArray)
-import GHCi.RemoteTypes (ForeignRef)
-
--- TODO: Break this cycle
-import {-# SOURCE #-} GHC.Runtime.Interpreter.Types (Interp, interpreterProfiled)
-import {-# SOURCE #-} qualified GHC.Runtime.Interpreter as GHCi (newBreakArray)
-import Data.Array.Base (numElements)
-
--------------------------------------------------------------------------------
-- ModBreaks
--------------------------------------------------------------------------------
@@ -58,10 +50,7 @@ import Data.Array.Base (numElements)
-- and 'modBreaks_decls'.
data ModBreaks
= ModBreaks
- { modBreaks_flags :: ForeignRef BreakArray
- -- ^ The array of flags, one per breakpoint,
- -- indicating which breakpoints are enabled.
- , modBreaks_locs :: !(Array BreakTickIndex SrcSpan)
+ { modBreaks_locs :: !(Array BreakTickIndex SrcSpan)
-- ^ An array giving the source span of each breakpoint.
, modBreaks_vars :: !(Array BreakTickIndex [OccName])
-- ^ An array giving the names of the free variables at each breakpoint.
@@ -83,40 +72,31 @@ data ModBreaks
-- generator needs to encode this information for each expression, the data is
-- allocated remotely in GHCi's address space and passed to the codegen as
-- foreign pointers.
-mkModBreaks :: Interp -> Module -> SizedSeq Tick -> IO ModBreaks
-mkModBreaks interp mod extendedMixEntries
- = do
- let count = fromIntegral $ sizeSS extendedMixEntries
+mkModBreaks :: Bool {-^ Whether the interpreter is profiled and thus if we should include store a CCS array -}
+ -> Module -> SizedSeq Tick -> ModBreaks
+mkModBreaks interpreterProfiled modl extendedMixEntries
+ = let count = fromIntegral $ sizeSS extendedMixEntries
entries = ssElts extendedMixEntries
- let
- locsTicks = listArray (0,count-1) [ tick_loc t | t <- entries ]
- varsTicks = listArray (0,count-1) [ tick_ids t | t <- entries ]
- declsTicks = listArray (0,count-1) [ tick_path t | t <- entries ]
- ccs
- | interpreterProfiled interp =
- listArray
- (0, count - 1)
- [ ( concat $ intersperse "." $ tick_path t,
- renderWithContext defaultSDocContext $ ppr $ tick_loc t
- )
- | t <- entries
- ]
- | otherwise = listArray (0, -1) []
- hydrateModBreaks interp $
- ModBreaks
- { modBreaks_flags = undefined,
- modBreaks_locs = locsTicks,
- modBreaks_vars = varsTicks,
- modBreaks_decls = declsTicks,
- modBreaks_ccs = ccs,
- modBreaks_module = mod
- }
-
-hydrateModBreaks :: Interp -> ModBreaks -> IO ModBreaks
-hydrateModBreaks interp ModBreaks {..} = do
- let count = numElements modBreaks_locs
- modBreaks_flags <- GHCi.newBreakArray interp count
- pure ModBreaks {..}
+ locsTicks = listArray (0,count-1) [ tick_loc t | t <- entries ]
+ varsTicks = listArray (0,count-1) [ tick_ids t | t <- entries ]
+ declsTicks = listArray (0,count-1) [ tick_path t | t <- entries ]
+ ccs
+ | interpreterProfiled =
+ listArray
+ (0, count - 1)
+ [ ( concat $ intersperse "." $ tick_path t,
+ renderWithContext defaultSDocContext $ ppr $ tick_loc t
+ )
+ | t <- entries
+ ]
+ | otherwise = listArray (0, -1) []
+ in ModBreaks
+ { modBreaks_locs = locsTicks
+ , modBreaks_vars = varsTicks
+ , modBreaks_decls = declsTicks
+ , modBreaks_ccs = ccs
+ , modBreaks_module = modl
+ }
{-
Note [Field modBreaks_decls]
=====================================
compiler/GHC/Linker/Loader.hs
=====================================
@@ -28,6 +28,7 @@ module GHC.Linker.Loader
, extendLoadedEnv
, deleteFromLoadedEnv
-- * Internals
+ , allocateBreakArrays
, rmDupLinkables
, modifyLoaderState
, initLinkDepsOpts
@@ -122,8 +123,8 @@ import System.Win32.Info (getSystemDirectory)
import GHC.Utils.Exception
import GHC.Unit.Home.Graph (lookupHug, unitEnv_foldWithKey)
import GHC.Driver.Downsweep
-
-
+import qualified GHC.Runtime.Interpreter as GHCi
+import Data.Array.Base (numElements)
-- Note [Linkers and loaders]
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -177,13 +178,15 @@ emptyLoaderState = LoaderState
{ closure_env = emptyNameEnv
, itbl_env = emptyNameEnv
, addr_env = emptyNameEnv
- , breakarray_env = emptyModuleEnv
- , ccs_env = emptyModuleEnv
}
, pkgs_loaded = init_pkgs
, bcos_loaded = emptyModuleEnv
, objs_loaded = emptyModuleEnv
, temp_sos = []
+ , linked_breaks = LinkedBreaks
+ { breakarray_env = emptyModuleEnv
+ , ccs_env = emptyModuleEnv
+ }
}
-- Packages that don't need loading, because the compiler
-- shares them with the interpreted program.
@@ -694,28 +697,22 @@ loadDecls interp hsc_env span linkable = do
else do
-- Link the expression itself
let le = linker_env pls
+ let lb = linked_breaks pls
le2_itbl_env <- linkITbls interp (itbl_env le) (concat $ map bc_itbls cbcs)
le2_addr_env <- foldlM (\env cbc -> allocateTopStrings interp (bc_strs cbc) env) (addr_env le) cbcs
- le2_breakarray_env <-
- allocateBreakArrays
- interp
- (catMaybes $ map bc_breaks cbcs)
- (breakarray_env le)
- le2_ccs_env <-
- allocateCCS
- interp
- (catMaybes $ map bc_breaks cbcs)
- (ccs_env le)
+ le2_breakarray_env <- allocateBreakArrays interp (breakarray_env lb) (catMaybes $ map bc_breaks cbcs)
+ le2_ccs_env <- allocateCCS interp (ccs_env lb) (catMaybes $ map bc_breaks cbcs)
let le2 = le { itbl_env = le2_itbl_env
- , addr_env = le2_addr_env
- , breakarray_env = le2_breakarray_env
+ , addr_env = le2_addr_env }
+ let lb2 = lb { breakarray_env = le2_breakarray_env
, ccs_env = le2_ccs_env }
-- Link the necessary packages and linkables
- new_bindings <- linkSomeBCOs interp (pkgs_loaded pls) le2 cbcs
+ new_bindings <- linkSomeBCOs interp (pkgs_loaded pls) le2 lb2 cbcs
nms_fhvs <- makeForeignNamedHValueRefs interp new_bindings
let ce2 = extendClosureEnv (closure_env le2) nms_fhvs
- !pls2 = pls { linker_env = le2 { closure_env = ce2 } }
+ !pls2 = pls { linker_env = le2 { closure_env = ce2 }
+ , linked_breaks = lb2 }
return (pls2, (nms_fhvs, links_needed, units_needed))
where
cbcs = linkableBCOs linkable
@@ -931,17 +928,15 @@ dynLinkBCOs interp pls bcos = do
le1 = linker_env pls
+ lb1 = linked_breaks pls
ie2 <- linkITbls interp (itbl_env le1) (concatMap bc_itbls cbcs)
ae2 <- foldlM (\env cbc -> allocateTopStrings interp (bc_strs cbc) env) (addr_env le1) cbcs
- be2 <-
- allocateBreakArrays
- interp
- (catMaybes $ map bc_breaks cbcs)
- (breakarray_env le1)
- ce2 <- allocateCCS interp (catMaybes $ map bc_breaks cbcs) (ccs_env le1)
- let le2 = le1 { itbl_env = ie2, addr_env = ae2, breakarray_env = be2, ccs_env = ce2 }
+ be2 <- allocateBreakArrays interp (breakarray_env lb1) (catMaybes $ map bc_breaks cbcs)
+ ce2 <- allocateCCS interp (ccs_env lb1) (catMaybes $ map bc_breaks cbcs)
+ let le2 = le1 { itbl_env = ie2, addr_env = ae2 }
+ let lb2 = lb1 { breakarray_env = be2, ccs_env = ce2 }
- names_and_refs <- linkSomeBCOs interp (pkgs_loaded pls) le2 cbcs
+ names_and_refs <- linkSomeBCOs interp (pkgs_loaded pls) le2 lb2 cbcs
-- We only want to add the external ones to the ClosureEnv
let (to_add, to_drop) = partition (isExternalName.fst) names_and_refs
@@ -958,13 +953,14 @@ dynLinkBCOs interp pls bcos = do
linkSomeBCOs :: Interp
-> PkgsLoaded
-> LinkerEnv
+ -> LinkedBreaks
-> [CompiledByteCode]
-> IO [(Name,HValueRef)]
-- The returned HValueRefs are associated 1-1 with
-- the incoming unlinked BCOs. Each gives the
-- value of the corresponding unlinked BCO
-linkSomeBCOs interp pkgs_loaded le mods = foldr fun do_link mods []
+linkSomeBCOs interp pkgs_loaded le lb mods = foldr fun do_link mods []
where
fun CompiledByteCode{..} inner accum =
inner (Foldable.toList bc_bcos : accum)
@@ -974,7 +970,7 @@ linkSomeBCOs interp pkgs_loaded le mods = foldr fun do_link mods []
let flat = [ bco | bcos <- mods, bco <- bcos ]
names = map unlinkedBCOName flat
bco_ix = mkNameEnv (zip names [0..])
- resolved <- sequence [ linkBCO interp pkgs_loaded le bco_ix bco | bco <- flat ]
+ resolved <- sequence [ linkBCO interp pkgs_loaded le lb bco_ix bco | bco <- flat ]
hvrefs <- createBCOs interp resolved
return (zip names hvrefs)
@@ -1072,9 +1068,13 @@ unload_wkr interp keep_linkables pls@LoaderState{..} = do
keep_name n = isExternalName n &&
nameModule n `elemModuleEnv` remaining_bcos_loaded
- !new_pls = pls { linker_env = filterLinkerEnv keep_name linker_env,
- bcos_loaded = remaining_bcos_loaded,
- objs_loaded = remaining_objs_loaded }
+ keep_mod :: Module -> Bool
+ keep_mod m = m `elemModuleEnv` remaining_bcos_loaded
+
+ !new_pls = pls { linker_env = filterLinkerEnv keep_name linker_env,
+ linked_breaks = filterLinkedBreaks keep_mod linked_breaks,
+ bcos_loaded = remaining_bcos_loaded,
+ objs_loaded = remaining_objs_loaded }
return new_pls
where
@@ -1656,30 +1656,34 @@ allocateTopStrings interp topStrings prev_env = do
where
mk_entry nm ptr = (nm, (nm, AddrPtr ptr))
--- | Given a list of 'ModBreaks' collected from a list of
--- 'CompiledByteCode', allocate the 'BreakArray'.
+-- | Given a list of 'InternalModBreaks' collected from a list of
+-- 'CompiledByteCode', allocate the 'BreakArray' used to trigger breakpoints.
allocateBreakArrays ::
Interp ->
- [InternalModBreaks] ->
ModuleEnv (ForeignRef BreakArray) ->
+ [InternalModBreaks] ->
IO (ModuleEnv (ForeignRef BreakArray))
-allocateBreakArrays _interp mbs be =
+allocateBreakArrays interp =
foldlM
- ( \be0 InternalModBreaks{imodBreaks_modBreaks=ModBreaks {..}} ->
- evaluate $ extendModuleEnv be0 modBreaks_module modBreaks_flags
+ ( \be0 InternalModBreaks{imodBreaks_modBreaks=ModBreaks {..}} -> do
+ -- If no BreakArray is assigned to this module yet, create one
+ if not $ elemModuleEnv modBreaks_module be0 then do
+ let count = numElements modBreaks_locs
+ breakArray <- GHCi.newBreakArray interp count
+ evaluate $ extendModuleEnv be0 modBreaks_module breakArray
+ else
+ return be0
)
- be
- mbs
--- | Given a list of 'ModBreaks' collected from a list of
--- 'CompiledByteCode', allocate the 'CostCentre' arrays when profiling
--- is enabled.
+-- | Given a list of 'InternalModBreaks' collected from a list
+-- of 'CompiledByteCode', allocate the 'CostCentre' arrays when profiling is
+-- enabled.
allocateCCS ::
Interp ->
- [InternalModBreaks] ->
ModuleEnv (Array BreakTickIndex (RemotePtr CostCentre)) ->
+ [InternalModBreaks] ->
IO (ModuleEnv (Array BreakTickIndex (RemotePtr CostCentre)))
-allocateCCS interp mbs ce
+allocateCCS interp ce mbss
| interpreterProfiled interp =
foldlM
( \ce0 InternalModBreaks{imodBreaks_modBreaks=ModBreaks {..}} -> do
@@ -1688,12 +1692,15 @@ allocateCCS interp mbs ce
interp
(moduleNameString $ moduleName modBreaks_module)
(elems modBreaks_ccs)
- evaluate $
- extendModuleEnv ce0 modBreaks_module $
- listArray
- (0, length ccs - 1)
- ccs
+ if not $ elemModuleEnv modBreaks_module ce0 then do
+ evaluate $
+ extendModuleEnv ce0 modBreaks_module $
+ listArray
+ (0, length ccs - 1)
+ ccs
+ else
+ return ce0
)
ce
- mbs
+ mbss
| otherwise = pure ce
=====================================
compiler/GHC/Linker/Types.hs
=====================================
@@ -18,6 +18,8 @@ module GHC.Linker.Types
, ClosureEnv
, emptyClosureEnv
, extendClosureEnv
+ , LinkedBreaks(..)
+ , filterLinkedBreaks
, LinkableSet
, mkLinkableSet
, unionLinkableSet
@@ -159,6 +161,9 @@ data LoaderState = LoaderState
, temp_sos :: ![(FilePath, String)]
-- ^ We need to remember the name of previous temporary DLL/.so
-- libraries so we can link them (see #10322)
+
+ , linked_breaks :: !LinkedBreaks
+ -- ^ Mapping from loaded modules to their breakpoint arrays
}
uninitializedLoader :: IO Loader
@@ -184,20 +189,13 @@ data LinkerEnv = LinkerEnv
, addr_env :: !AddrEnv
-- ^ Like 'closure_env' and 'itbl_env', but for top-level 'Addr#' literals,
-- see Note [Generating code for top-level string literal bindings] in GHC.StgToByteCode.
-
- , breakarray_env :: !(ModuleEnv (ForeignRef BreakArray))
- -- ^ Each 'Module's remote pointer of 'BreakArray'.
-
- , ccs_env :: !(ModuleEnv (Array BreakTickIndex (RemotePtr CostCentre)))
- -- ^ Each 'Module's array of remote pointers of 'CostCentre'.
- -- Untouched when not profiling.
}
filterLinkerEnv :: (Name -> Bool) -> LinkerEnv -> LinkerEnv
-filterLinkerEnv f le = le
- { closure_env = filterNameEnv (f . fst) (closure_env le)
- , itbl_env = filterNameEnv (f . fst) (itbl_env le)
- , addr_env = filterNameEnv (f . fst) (addr_env le)
+filterLinkerEnv f (LinkerEnv closure_e itbl_e addr_e) = LinkerEnv
+ { closure_env = filterNameEnv (f . fst) closure_e
+ , itbl_env = filterNameEnv (f . fst) itbl_e
+ , addr_env = filterNameEnv (f . fst) addr_e
}
type ClosureEnv = NameEnv (Name, ForeignHValue)
@@ -209,6 +207,29 @@ extendClosureEnv :: ClosureEnv -> [(Name,ForeignHValue)] -> ClosureEnv
extendClosureEnv cl_env pairs
= extendNameEnvList cl_env [ (n, (n,v)) | (n,v) <- pairs]
+-- | 'BreakArray's and CCSs are allocated per-module at link-time.
+--
+-- Specifically, a module's 'BreakArray' is allocated either:
+-- - When a BCO for that module is linked
+-- - When :break is used on a given module *before* the BCO has been linked.
+--
+-- We keep this structure in the 'LoaderState'
+data LinkedBreaks
+ = LinkedBreaks
+ { breakarray_env :: !(ModuleEnv (ForeignRef BreakArray))
+ -- ^ Each 'Module's remote pointer of 'BreakArray'.
+
+ , ccs_env :: !(ModuleEnv (Array BreakTickIndex (RemotePtr CostCentre)))
+ -- ^ Each 'Module's array of remote pointers of 'CostCentre'.
+ -- Untouched when not profiling.
+ }
+
+filterLinkedBreaks :: (Module -> Bool) -> LinkedBreaks -> LinkedBreaks
+filterLinkedBreaks f (LinkedBreaks ba_e ccs_e) = LinkedBreaks
+ { breakarray_env = filterModuleEnv (\m _ -> f m) ba_e
+ , ccs_env = filterModuleEnv (\m _ -> f m) ccs_e
+ }
+
type PkgsLoaded = UniqDFM UnitId LoadedPkgInfo
data LoadedPkgInfo
=====================================
compiler/GHC/Runtime/Eval.hs
=====================================
@@ -64,6 +64,7 @@ import GHCi.RemoteTypes
import GHC.ByteCode.Types
import GHC.Linker.Loader as Loader
+import GHC.Linker.Types (LinkedBreaks (..))
import GHC.Hs
@@ -126,6 +127,7 @@ import GHC.Tc.Utils.Instantiate (instDFunType)
import GHC.Tc.Utils.Monad
import GHC.IfaceToCore
+import GHC.ByteCode.Breakpoints
import Control.Monad
import Data.Dynamic
@@ -134,7 +136,7 @@ import Data.List (find,intercalate)
import Data.List.NonEmpty (NonEmpty)
import Unsafe.Coerce ( unsafeCoerce )
import qualified GHC.Unit.Home.Graph as HUG
-import GHC.ByteCode.Breakpoints
+import GHCi.BreakArray (BreakArray)
-- -----------------------------------------------------------------------------
-- running a statement interactively
@@ -348,13 +350,14 @@ handleRunStatus step expr bindings final_ids status history0 = do
EvalBreak apStack_ref (Just eval_break) resume_ctxt ccs -> do
let ibi = evalBreakpointToId eval_break
let hug = hsc_HUG hsc_env
- tick_brks <- liftIO $ readModBreaks hug (ibi_tick_mod ibi)
+ tick_brks <- liftIO $ readModBreaks hug (ibi_tick_mod ibi)
+ breakArray <- getBreakArray interp (toBreakpointId ibi) tick_brks
let
span = getBreakLoc ibi tick_brks
decl = intercalate "." $ getBreakDecls ibi tick_brks
-- Was this breakpoint explicitly enabled (ie. in @BreakArray@)?
- bactive <- liftIO $ breakpointStatus interp (modBreaks_flags $ imodBreaks_modBreaks tick_brks) (ibi_tick_index ibi)
+ bactive <- liftIO $ breakpointStatus interp breakArray (ibi_tick_index ibi)
apStack_fhv <- liftIO $ mkFinalizedHValue interp apStack_ref
resume_ctxt_fhv <- liftIO $ mkFinalizedHValue interp resume_ctxt
@@ -462,9 +465,24 @@ setupBreakpoint :: GhcMonad m => Interp -> BreakpointId -> Int -> m () -- #191
setupBreakpoint interp bi cnt = do
hug <- hsc_HUG <$> getSession
modBreaks <- liftIO $ readModBreaks hug (bi_tick_mod bi)
- let breakarray = modBreaks_flags $ imodBreaks_modBreaks modBreaks
- _ <- liftIO $ GHCi.storeBreakpoint interp breakarray (bi_tick_index bi) cnt
- pure ()
+ breakArray <- getBreakArray interp bi modBreaks
+ liftIO $ GHCi.storeBreakpoint interp breakArray (bi_tick_index bi) cnt
+
+getBreakArray :: GhcMonad m => Interp -> BreakpointId -> InternalModBreaks -> m (ForeignRef BreakArray)
+getBreakArray interp BreakpointId{bi_tick_mod} imbs = do
+
+ liftIO $ modifyLoaderState interp $ \ld_st -> do
+ let lb = linked_breaks ld_st
+
+ -- Recall that BreakArrays are allocated only at BCO link time, so if we
+ -- haven't linked the BCOs we intend to break at yet, we allocate the arrays here.
+ ba_env <- allocateBreakArrays interp (breakarray_env lb) [imbs]
+
+ return
+ ( ld_st { linked_breaks = lb{breakarray_env = ba_env} }
+ , expectJust {- just computed -} $
+ lookupModuleEnv ba_env bi_tick_mod
+ )
back :: GhcMonad m => Int -> m ([Name], Int, SrcSpan)
back n = moveHist (+n)
=====================================
compiler/GHC/Runtime/Interpreter.hs-boot deleted
=====================================
@@ -1,10 +0,0 @@
-module GHC.Runtime.Interpreter where
-
-import {-# SOURCE #-} GHC.Runtime.Interpreter.Types
-import Data.Int (Int)
-import GHC.Base (IO)
-import GHCi.BreakArray (BreakArray)
-import GHCi.RemoteTypes (ForeignRef)
-
-newBreakArray :: Interp -> Int -> IO (ForeignRef BreakArray)
-
=====================================
compiler/GHC/Runtime/Interpreter/Types.hs-boot deleted
=====================================
@@ -1,6 +0,0 @@
-module GHC.Runtime.Interpreter.Types where
-
-import Data.Bool
-
-data Interp
-interpreterProfiled :: Interp -> Bool
=====================================
testsuite/tests/count-deps/CountDepsAst.stdout
=====================================
@@ -5,6 +5,7 @@ GHC.Builtin.Types
GHC.Builtin.Types.Literals
GHC.Builtin.Types.Prim
GHC.Builtin.Uniques
+GHC.ByteCode.Breakpoints
GHC.ByteCode.Types
GHC.Cmm.BlockId
GHC.Cmm.CLabel
@@ -110,6 +111,8 @@ GHC.Hs.Pat
GHC.Hs.Specificity
GHC.Hs.Type
GHC.Hs.Utils
+GHC.HsToCore.Breakpoints
+GHC.HsToCore.Ticks
GHC.Iface.Errors.Types
GHC.Iface.Ext.Fields
GHC.Iface.Flags
@@ -150,7 +153,6 @@ GHC.Tc.Zonk.Monad
GHC.Types.Annotations
GHC.Types.Avail
GHC.Types.Basic
-GHC.Types.Breakpoint
GHC.Types.CostCentre
GHC.Types.CostCentre.State
GHC.Types.Cpr
=====================================
testsuite/tests/count-deps/CountDepsParser.stdout
=====================================
@@ -5,6 +5,7 @@ GHC.Builtin.Types
GHC.Builtin.Types.Literals
GHC.Builtin.Types.Prim
GHC.Builtin.Uniques
+GHC.ByteCode.Breakpoints
GHC.ByteCode.Types
GHC.Cmm.BlockId
GHC.Cmm.CLabel
@@ -114,8 +115,10 @@ GHC.Hs.Pat
GHC.Hs.Specificity
GHC.Hs.Type
GHC.Hs.Utils
+GHC.HsToCore.Breakpoints
GHC.HsToCore.Errors.Types
GHC.HsToCore.Pmc.Solver.Types
+GHC.HsToCore.Ticks
GHC.Iface.Errors.Types
GHC.Iface.Ext.Fields
GHC.Iface.Flags
@@ -171,7 +174,6 @@ GHC.Tc.Zonk.Monad
GHC.Types.Annotations
GHC.Types.Avail
GHC.Types.Basic
-GHC.Types.Breakpoint
GHC.Types.CompleteMatch
GHC.Types.CostCentre
GHC.Types.CostCentre.State
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/af76b3d2fc321983df7be559ad5cca3…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/af76b3d2fc321983df7be559ad5cca3…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][wip/spj-apporv-Oct24] 2 commits: fix unused do binding warning error location
by Apoorv Ingle (@ani) 02 Jul '25
by Apoorv Ingle (@ani) 02 Jul '25
02 Jul '25
Apoorv Ingle pushed to branch wip/spj-apporv-Oct24 at Glasgow Haskell Compiler / GHC
Commits:
bde2465e by Apoorv Ingle at 2025-07-02T16:02:03-05:00
fix unused do binding warning error location
- - - - -
e199446b by Apoorv Ingle at 2025-07-02T16:11:44-05:00
FRRRecordUpdate message change
- - - - -
3 changed files:
- compiler/GHC/HsToCore/Expr.hs
- compiler/GHC/Tc/Types/Origin.hs
- testsuite/tests/rep-poly/RepPolyRecordUpdate.stderr
Changes:
=====================================
compiler/GHC/HsToCore/Expr.hs
=====================================
@@ -1234,8 +1234,8 @@ Other places that requires from the same treatment:
-- Warn about certain types of values discarded in monadic bindings (#3263)
warnDiscardedDoBindings :: LHsExpr GhcTc -> Type -> Type -> DsM ()
-warnDiscardedDoBindings rhs m_ty elt_ty
- = do { warn_unused <- woptM Opt_WarnUnusedDoBind
+warnDiscardedDoBindings rhs@(L rhs_loc _) m_ty elt_ty
+ = putSrcSpanDsA rhs_loc $ do { warn_unused <- woptM Opt_WarnUnusedDoBind
; warn_wrong <- woptM Opt_WarnWrongDoBind
; when (warn_unused || warn_wrong) $
do { fam_inst_envs <- dsGetFamInstEnvs
=====================================
compiler/GHC/Tc/Types/Origin.hs
=====================================
@@ -1229,11 +1229,10 @@ mkFRRUnboxedSum = FRRUnboxedSum
-- and is reported separately.
pprFixedRuntimeRepContext :: FixedRuntimeRepContext -> SDoc
pprFixedRuntimeRepContext (FRRRecordCon lbl _arg)
- = sep [ text "The field", quotes (ppr lbl)
+ = sep [ text "The field", quotes (ppr lbl) -- TODO ANI: Where does this get used? Add missing test?
, text "of the record constructor" ]
-pprFixedRuntimeRepContext (FRRRecordUpdate lbl _arg)
- = sep [ text "The record update at field"
- , quotes (ppr lbl) ]
+pprFixedRuntimeRepContext (FRRRecordUpdate lbl _)
+ = sep [ text "The field", quotes (ppr lbl) ]
pprFixedRuntimeRepContext (FRRBinder binder)
= sep [ text "The binder"
, quotes (ppr binder) ]
=====================================
testsuite/tests/rep-poly/RepPolyRecordUpdate.stderr
=====================================
@@ -13,8 +13,7 @@ RepPolyRecordUpdate.hs:7:35: error: [GHC-55287]
X a :: TYPE rep
RepPolyRecordUpdate.hs:13:9: error: [GHC-55287]
- • The argument ‘fld’ of ‘MkX’
- does not have a fixed runtime representation.
+ • The field ‘fld’ does not have a fixed runtime representation.
Its type is:
a0 :: TYPE rep0
When unifying:
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/d37adc6944a6cf04e1e57dafea3e33…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/d37adc6944a6cf04e1e57dafea3e33…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][wip/bump-win32-tarballs] rts: Fix link order between ucrt and mingwex
by Tamar Christina (@Phyx) 02 Jul '25
by Tamar Christina (@Phyx) 02 Jul '25
02 Jul '25
Tamar Christina pushed to branch wip/bump-win32-tarballs at Glasgow Haskell Compiler / GHC
Commits:
1221221c by Tamar Christina at 2025-07-02T21:28:11+01:00
rts: Fix link order between ucrt and mingwex
- - - - -
1 changed file:
- libraries/ghc-internal/ghc-internal.cabal.in
Changes:
=====================================
libraries/ghc-internal/ghc-internal.cabal.in
=====================================
@@ -493,7 +493,7 @@ Library
-- on Windows. Required because of mingw32.
extra-libraries:
wsock32, user32, shell32, mingw32, kernel32, advapi32,
- mingwex, ws2_32, shlwapi, ole32, rpcrt4, ntdll, ucrt
+ ucrt, mingwex, ws2_32, shlwapi, ole32, rpcrt4, ntdll
-- Minimum supported Windows version.
-- These numbers can be found at:
-- https://msdn.microsoft.com/en-us/library/windows/desktop/aa383745(v=vs.85).…
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/1221221c41c35a71e444ba52b1bc255…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/1221221c41c35a71e444ba52b1bc255…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][wip/sand-witch/make-set-field] 23 commits: Visible forall in GADTs (#25127)
by Andrei Borzenkov (@sand-witch) 02 Jul '25
by Andrei Borzenkov (@sand-witch) 02 Jul '25
02 Jul '25
Andrei Borzenkov pushed to branch wip/sand-witch/make-set-field at Glasgow Haskell Compiler / GHC
Commits:
fbc0b92a by Vladislav Zavialov at 2025-06-22T04:25:16+03:00
Visible forall in GADTs (#25127)
Add support for visible dependent quantification `forall a -> t` in
types of data constructors, e.g.
data KindVal a where
K :: forall k.
forall (a::k) -> -- now allowed!
k ->
KindVal a
For details, see docs/users_guide/exts/required_type_arguments.rst,
which has gained a new subsection.
DataCon in compiler/GHC/Core/DataCon.hs
---------------------------------------
The main change in this patch is that DataCon, the Core representation
of a data constructor, now uses a different type to store user-written
type variable binders:
- dcUserTyVarBinders :: [InvisTVBinder]
+ dcUserTyVarBinders :: [TyVarBinder]
where
type TyVarBinder = VarBndr TyVar ForAllTyFlag
type InvisTVBinder = VarBndr TyVar Specificity
and
data Specificity = InferredSpec | SpecifiedSpec
data ForAllTyFlag = Invisible Specificity | Required
This change necessitates some boring, mechanical changes scattered
throughout the diff:
... is now used in place of ...
-----------------+---------------
TyVarBinder | InvisTVBinder
IfaceForAllBndr | IfaceForAllSpecBndr
Specified | SpecifiedSpec
Inferred | InferredSpec
mkForAllTys | mkInvisForAllTys
additionally,
tyVarSpecToBinders -- added or removed calls
ifaceForAllSpecToBndrs -- removed calls
Visibility casts in mkDataConRep
--------------------------------
Type abstractions in Core (/\a. e) always have type (forall a. t)
because coreTyLamForAllTyFlag = Specified. This is also true of data
constructor workers. So we may be faced with the following:
data con worker: (forall a. blah)
data con wrapper: (forall a -> blah)
In this case the wrapper must use a visibility cast (e |> ForAllCo ...)
with appropriately set fco_vis{L,R}. Relevant functions:
mkDataConRep in compiler/GHC/Types/Id/Make.hs
dataConUserTyVarBindersNeedWrapper in compiler/GHC/Core/DataCon.hs
mkForAllVisCos in compiler/GHC/Core/Coercion.hs
mkCoreTyLams in compiler/GHC/Core/Make.hs
mkWpForAllCast in compiler/GHC/Tc/Types/Evidence.hs
More specifically:
- dataConUserTyVarBindersNeedWrapper has been updated to answer "yes"
if there are visible foralls in the type of the data constructor.
- mkDataConRep now uses mkCoreTyLams to generate the big lambda
abstractions (/\a b c. e) in the data con wrapper.
- mkCoreTyLams is a variant of mkCoreLams that applies visibility casts
as needed. It similar in purpose to the pre-existing mkWpForAllCast,
so the common bits have been factored out into mkForAllVisCos.
ConDecl in compiler/Language/Haskell/Syntax/Decls.hs
----------------------------------------------------
The surface syntax representation of a data constructor declaration is
ConDecl. In accordance with the proposal, only GADT syntax is extended
with support for visible forall, so we are interested in ConDeclGADT.
ConDeclGADT's field con_bndrs has been renamed to con_outer_bndrs
and is now accompanied by con_inner_bndrs:
con_outer_bndrs :: XRec pass (HsOuterSigTyVarBndrs pass)
con_inner_bndrs :: [HsForAllTelescope pass]
Visible foralls always end up in con_inner_bndrs. The outer binders are
stored and processed separately to support implicit quantification and
the forall-or-nothing rule, a design established by HsSigType.
A side effect of this change is that even in absence of visible foralls,
GHC now permits multiple invisible foralls, e.g.
data T a where { MkT :: forall a b. forall c d. ... -> T a }
But of course, this is done in service of making at least some of these
foralls visible. The entire compiler front-end has been updated to deal
with con_inner_bndrs. See the following modified or added functions:
Parser:
mkGadtDecl in compiler/GHC/Parser/PostProcess.hs
splitLHsGadtTy in compiler/GHC/Hs/Type.hs
Pretty-printer:
pprConDecl in compiler/GHC/Hs/Decls.hs
pprHsForAllTelescope in compiler/GHC/Hs/Type.hs
Renamer:
rnConDecl in compiler/GHC/Rename/Module.hs
bindHsForAllTelescopes in compiler/GHC/Rename/HsType.hs
extractHsForAllTelescopes in compiler/GHC/Rename/HsType.hs
Type checker:
tcConDecl in compiler/GHC/Tc/TyCl.hs
tcGadtConTyVarBndrs in compiler/GHC/Tc/Gen/HsType.hs
Template Haskell
----------------
The TH AST is left unchanged for the moment to avoid breakage. An
attempt to quote or reify a data constructor declaration with visible
forall in its type will result an error:
data ThRejectionReason -- in GHC/HsToCore/Errors/Types.hs
= ...
| ThDataConVisibleForall -- new error constructor
However, as noted in the previous section, GHC now permits multiple
invisible foralls, and TH was updated accordingly. Updated code:
repC in compiler/GHC/HsToCore/Quote.hs
reifyDataCon in compiler/GHC/Tc/Gen/Splice.hs
ppr @Con in libraries/ghc-boot-th/GHC/Boot/TH/Ppr.hs
Pattern matching
----------------
Everything described above concerns data constructor declarations, but
what about their use sites? Now it is trickier to type check a pattern
match fn(Con a b c)=... because we can no longer assume that a,b,c are
all value arguments. Indeed, some or all of them may very well turn out
to be required type arguments.
To that end, see the changes to:
tcDataConPat in compiler/GHC/Tc/Gen/Pat.hs
splitConTyArgs in compiler/GHC/Tc/Gen/Pat.hs
and the new helpers split_con_ty_args, zip_pats_bndrs.
This is also the reason the TcRnTooManyTyArgsInConPattern error
constructor has been removed. The new code emits TcRnArityMismatch
or TcRnIllegalInvisibleTypePattern.
Summary
-------
DataCon, ConDecl, as well as all related functions have been updated to
support required type arguments in data constructors.
Test cases:
HieGadtConSigs GadtConSigs_th_dump1 GadtConSigs_th_pprint1
T25127_data T25127_data_inst T25127_infix
T25127_newtype T25127_fail_th_quote T25127_fail_arity
TyAppPat_Tricky
Co-authored-by: mniip <mniip(a)mniip.com>
- - - - -
ae003a3a by Teo Camarasu at 2025-06-23T05:21:48-04:00
linters: lint-whitespace: bump upper-bound for containers
The version of containers was bumped in https://gitlab.haskell.org/ghc/ghc/-/merge_requests/13989
- - - - -
0fb37893 by Matthew Pickering at 2025-06-23T13:55:10-04:00
Move ModuleGraph into UnitEnv
The ModuleGraph is a piece of information associated with the
ExternalPackageState and HomeUnitGraph. Therefore we should store it
inside the HomeUnitEnv.
- - - - -
3bf6720e by soulomoon at 2025-06-23T13:55:52-04:00
Remove hptAllFamInstances usage during upsweep
Fixes #26118
This change eliminates the use of hptAllFamInstances during the upsweep phase,
as it could access non-below modules from the home package table.
The following updates were made:
* Updated checkFamInstConsistency to accept an explicit ModuleEnv FamInstEnv
parameter and removed the call to hptAllFamInstances.
* Adjusted hugInstancesBelow so we can construct ModuleEnv FamInstEnv
from its result,
* hptAllFamInstances and allFamInstances functions are removed.
- - - - -
83ee7b78 by Ben Gamari at 2025-06-24T05:02:07-04:00
configure: Don't force value of OTOOL, etc. if not present
Previously if `otool` and `install_name_tool` were not present they
would be overridden by `fp_settings.m4`. This logic was introduced in
4ff93292243888545da452ea4d4c1987f2343591 without explanation.
- - - - -
9329c9e1 by Ben Gamari at 2025-06-24T05:02:07-04:00
ghc-toolchain: Add support for otool, install_name_tool
Fixes part of ghc#23675.
- - - - -
25f5c998 by Ben Gamari at 2025-06-24T05:02:08-04:00
ghc-toolchain: Add support for llc, opt, llvm-as
Fixes #23675.
- - - - -
51d150dd by Rodrigo Mesquita at 2025-06-24T05:02:08-04:00
hadrian: Use settings-use-distro-mingw directly
The type `ToolchainSetting` only made sense when we had more settings to
fetch from the system config file. Even then "settings-use-distro-mingw"
is arguably not a toolchain setting.
With the fix for #23675, all toolchain tools were moved to the
`ghc-toolchain` `Toolchain` format. Therefore, we can inline
`settings-use-distro-mingw` accesses and delete `ToolchainSetting`.
- - - - -
dcf68a83 by Rodrigo Mesquita at 2025-06-24T05:02:08-04:00
configure: Check LlvmTarget exists for LlvmAsFlags
If LlvmTarget was empty, LlvmAsFlags would be just "--target=".
If it is empty now, simply keep LlvmAsFlags empty.
ghc-toolchain already does this right. This fix makes the two
configurations match up.
- - - - -
580a3353 by Ben Gamari at 2025-06-24T05:02:51-04:00
rts/linker/LoadArchive: Use bool
Improve type precision by using `bool` instead of `int` and `StgBool`.
- - - - -
76d1041d by Ben Gamari at 2025-06-24T05:02:51-04:00
rts/linker/LoadArchive: Don't rely on file extensions for identification
Previously archive members would be identified via their file extension,
as described in #13103. We now instead use a more principled approach,
relying on the magic number in the member's header.
As well, we refactor treatment of archive format detection to improve
code clarity and error handling.
Closes #13103.
- - - - -
4b748a99 by Teo Camarasu at 2025-06-24T15:31:07-04:00
template-haskell: improve changelog
stable -> more stable, just to clarify that this interface isn't fully stable.
errornously -> mistakenly: I typod this and also let's go for a simpler word
- - - - -
e358e477 by Sylvain Henry at 2025-06-24T15:31:58-04:00
Bump stack resolver to use GHC 9.6.7
Cf #26139
- - - - -
4bf5eb63 by fendor at 2025-06-25T17:05:43-04:00
Teach `:reload` about multiple home units
`:reload` needs to lookup the `ModuleName` and must not assume the given
`ModuleName` is in the current `HomeUnit`.
We add a new utility function which allows us to find a `HomeUnitModule`
instead of a `Module`.
Further, we introduce the `GhciCommandError` type which can be used to
abort the execution of a GHCi command.
This error is caught and printed in a human readable fashion.
- - - - -
b3d97bb3 by fendor at 2025-06-25T17:06:25-04:00
Implement `-fno-load-initial-targets` flag
We add the new flag `-fno-load-initial-targets` which doesn't load all `Target`s
immediately but only computes the module graph for all `Target`s.
The user can then decide to load modules from that module graph using
the syntax:
ghci> :reload <Mod>
This will load everything in the module graph up to `Mod`.
The user can return to the initial state by using the builtin target
`none` to unload all modules.
ghci> :reload none
Is in principle identical to starting a new session with the
`-fno-load-initial-targets` flag.
The `-fno-load-initial-targets` flag allows for faster startup time of GHCi when a
user has lots of `Target`s.
We additionally extend the `:reload` command to accept multiple
`ModuleName`s. For example:
ghci> :reload <Mod1> <Mod2>
Loads all modules up to the modules `Mod1` and `Mod2`.
- - - - -
49f44e52 by Teo Camarasu at 2025-06-26T04:19:51-04:00
Expose ghc-internal unit id through the settings file
This in combination with the unit id of the compiler library allows
cabal to know of the two unit ids that should not be reinstalled (in
specific circumstances) as:
- when using plugins, we want to link against exactly the compiler unit
id
- when using TemplateHaskell we want to link against exactly the package
that contains the TemplateHaskell interfaces, which is `ghc-internal`
See: <https://github.com/haskell/cabal/issues/10087>
Resolves #25282
- - - - -
499c4efe by Bryan Richter at 2025-06-26T04:20:33-04:00
CI: Fix and clean up capture of timings
* Fixes the typo that caused 'cat ci-timings' to report "no such file or
directory"
* Gave ci_timings.txt a file extension so it may play better with other
systems
* Fixed the use of time_it so all times are recorded
* Fixed time_it to print name along with timing
- - - - -
86c90c9e by Bryan Richter at 2025-06-26T04:20:33-04:00
CI: Update collapsible section usage
The syntax apparently changed at some point.
- - - - -
04308ee4 by Bryan Richter at 2025-06-26T04:20:33-04:00
CI: Add more collapsible sections
- - - - -
43b606bb by Florian Ragwitz at 2025-06-27T16:31:26-04:00
Tick uses of wildcard/pun field binds as if using the record selector function
Fixes #17834.
See Note [Record-selector ticks] for additional reasoning behind this as well
as an overview of the implementation details and future improvements.
- - - - -
d4952549 by Ben Gamari at 2025-06-27T16:32:08-04:00
testsuite/caller-cc: Make CallerCc[123] less sensitive
These were previously sensitive to irrelevant changes in program
structure. To avoid this we filter out all by lines emitted by the
-fcaller-cc from the profile.
- - - - -
733583e3 by Andrei Borzenkov at 2025-07-02T22:13:12+04:00
Generate SetField instances on demand (16232)
- - - - -
1d422ed1 by Andrei Borzenkov at 2025-07-02T22:14:12+04:00
Small fixes after intensive testing
- - - - -
184 changed files:
- .gitlab-ci.yml
- .gitlab/ci.sh
- .gitlab/common.sh
- .gitlab/generate-ci/gen_ci.hs
- .gitlab/jobs.yaml
- compiler/GHC.hs
- compiler/GHC/Builtin/Names.hs
- compiler/GHC/Builtin/Types.hs
- compiler/GHC/Core/Coercion.hs
- compiler/GHC/Core/ConLike.hs
- compiler/GHC/Core/DataCon.hs
- compiler/GHC/Core/DataCon.hs-boot
- compiler/GHC/Core/Make.hs
- compiler/GHC/Core/Opt/Pipeline.hs
- compiler/GHC/Core/PatSyn.hs
- compiler/GHC/Core/TyCo/Ppr.hs
- compiler/GHC/Core/TyCo/Rep.hs
- compiler/GHC/Data/List/SetOps.hs
- compiler/GHC/Driver/Backpack.hs
- compiler/GHC/Driver/DynFlags.hs
- compiler/GHC/Driver/Env.hs
- compiler/GHC/Driver/Env/Types.hs
- compiler/GHC/Driver/Flags.hs
- compiler/GHC/Driver/Main.hs
- compiler/GHC/Driver/Make.hs
- compiler/GHC/Driver/Pipeline/Execute.hs
- compiler/GHC/Driver/Session.hs
- compiler/GHC/Hs/Decls.hs
- compiler/GHC/Hs/Expr.hs
- compiler/GHC/Hs/Pat.hs
- compiler/GHC/Hs/Type.hs
- compiler/GHC/HsToCore.hs
- compiler/GHC/HsToCore/Errors/Ppr.hs
- compiler/GHC/HsToCore/Errors/Types.hs
- compiler/GHC/HsToCore/Quote.hs
- compiler/GHC/HsToCore/Ticks.hs
- compiler/GHC/Iface/Decl.hs
- compiler/GHC/Iface/Ext/Ast.hs
- compiler/GHC/Iface/Load.hs
- compiler/GHC/Iface/Make.hs
- compiler/GHC/Iface/Recomp.hs
- compiler/GHC/Iface/Syntax.hs
- compiler/GHC/Iface/Tidy.hs
- compiler/GHC/IfaceToCore.hs
- compiler/GHC/Parser/PostProcess.hs
- compiler/GHC/Parser/PostProcess/Haddock.hs
- compiler/GHC/Rename/Expr.hs
- compiler/GHC/Rename/HsType.hs
- compiler/GHC/Rename/Module.hs
- compiler/GHC/Tc/Errors/Ppr.hs
- compiler/GHC/Tc/Errors/Types.hs
- compiler/GHC/Tc/Gen/Head.hs
- compiler/GHC/Tc/Gen/HsType.hs
- compiler/GHC/Tc/Gen/Match.hs
- compiler/GHC/Tc/Gen/Pat.hs
- compiler/GHC/Tc/Gen/Splice.hs
- compiler/GHC/Tc/Instance/Class.hs
- compiler/GHC/Tc/Instance/Family.hs
- compiler/GHC/Tc/Module.hs
- compiler/GHC/Tc/TyCl.hs
- compiler/GHC/Tc/TyCl/Build.hs
- compiler/GHC/Tc/TyCl/Utils.hs
- + compiler/GHC/Tc/TyCl/Utils.hs-boot
- compiler/GHC/Tc/Types.hs
- compiler/GHC/Tc/Types/Evidence.hs
- compiler/GHC/Tc/Utils/Monad.hs
- compiler/GHC/ThToHs.hs
- compiler/GHC/Types/Error/Codes.hs
- compiler/GHC/Types/Id/Make.hs
- compiler/GHC/Types/Var.hs-boot
- compiler/GHC/Unit/Env.hs
- compiler/GHC/Unit/Home/Graph.hs
- compiler/GHC/Unit/Home/PackageTable.hs
- compiler/GHC/Unit/Module/Graph.hs
- compiler/GHC/Unit/Module/ModDetails.hs
- compiler/GHC/Unit/Module/ModGuts.hs
- compiler/GHC/Unit/Module/ModIface.hs
- compiler/Language/Haskell/Syntax/Basic.hs
- compiler/Language/Haskell/Syntax/Decls.hs
- compiler/Language/Haskell/Syntax/Pat.hs
- compiler/Setup.hs
- distrib/configure.ac.in
- docs/users_guide/9.14.1-notes.rst
- docs/users_guide/exts/gadt_syntax.rst
- docs/users_guide/exts/required_type_arguments.rst
- docs/users_guide/ghci.rst
- ghc/GHCi/UI.hs
- ghc/GHCi/UI/Exception.hs
- ghc/GHCi/UI/Print.hs
- hadrian/cfg/default.host.target.in
- hadrian/cfg/default.target.in
- hadrian/cfg/system.config.in
- hadrian/src/Builder.hs
- hadrian/src/Oracles/Setting.hs
- hadrian/src/Rules/Generate.hs
- hadrian/src/Settings/Builders/RunTest.hs
- hadrian/stack.yaml
- hadrian/stack.yaml.lock
- libraries/ghc-boot-th/GHC/Boot/TH/Ppr.hs
- libraries/ghc-internal/src/GHC/Internal/Control/Exception/Base.hs
- libraries/ghc-internal/src/GHC/Internal/Records.hs
- libraries/template-haskell/changelog.md
- linters/lint-whitespace/lint-whitespace.cabal
- m4/fp_settings.m4
- m4/ghc_toolchain.m4
- m4/prep_target_file.m4
- rts/linker/LoadArchive.c
- testsuite/tests/dependent/should_fail/T16326_Fail6.stderr
- testsuite/tests/ghc-e/should_fail/T18441fail5.stderr
- testsuite/tests/ghci/prog-mhu003/prog-mhu003.stderr
- testsuite/tests/ghci/prog-mhu004/prog-mhu004a.stderr
- + testsuite/tests/ghci/prog-mhu005/Makefile
- + testsuite/tests/ghci/prog-mhu005/a/A.hs
- + testsuite/tests/ghci/prog-mhu005/all.T
- + testsuite/tests/ghci/prog-mhu005/b/B.hs
- + testsuite/tests/ghci/prog-mhu005/prog-mhu005a.script
- + testsuite/tests/ghci/prog-mhu005/prog-mhu005a.stderr
- + testsuite/tests/ghci/prog-mhu005/prog-mhu005a.stdout
- + testsuite/tests/ghci/prog-mhu005/unitA
- + testsuite/tests/ghci/prog-mhu005/unitB
- + testsuite/tests/ghci/prog021/A.hs
- + testsuite/tests/ghci/prog021/B.hs
- + testsuite/tests/ghci/prog021/Makefile
- + testsuite/tests/ghci/prog021/all.T
- + testsuite/tests/ghci/prog021/prog021a.script
- + testsuite/tests/ghci/prog021/prog021a.stderr
- + testsuite/tests/ghci/prog021/prog021a.stdout
- + testsuite/tests/ghci/prog021/prog021b.script
- + testsuite/tests/ghci/prog021/prog021b.stderr
- + testsuite/tests/ghci/prog021/prog021b.stdout
- + testsuite/tests/ghci/prog022/A.hs
- + testsuite/tests/ghci/prog022/B.hs
- + testsuite/tests/ghci/prog022/Makefile
- + testsuite/tests/ghci/prog022/all.T
- + testsuite/tests/ghci/prog022/ghci.prog022a.script
- + testsuite/tests/ghci/prog022/ghci.prog022a.stderr
- + testsuite/tests/ghci/prog022/ghci.prog022a.stdout
- + testsuite/tests/ghci/prog022/ghci.prog022b.script
- + testsuite/tests/ghci/prog022/ghci.prog022b.stderr
- + testsuite/tests/ghci/prog022/ghci.prog022b.stdout
- testsuite/tests/ghci/scripts/ghci021.stderr
- testsuite/tests/haddock/should_compile_flag_haddock/T17544.stderr
- testsuite/tests/haddock/should_compile_flag_haddock/T17544_kw.stderr
- + testsuite/tests/hiefile/should_run/HieGadtConSigs.hs
- + testsuite/tests/hiefile/should_run/HieGadtConSigs.stdout
- testsuite/tests/hiefile/should_run/all.T
- + testsuite/tests/hpc/recsel/Makefile
- + testsuite/tests/hpc/recsel/recsel.hs
- + testsuite/tests/hpc/recsel/recsel.stdout
- + testsuite/tests/hpc/recsel/test.T
- testsuite/tests/parser/should_compile/DumpParsedAst.stderr
- testsuite/tests/parser/should_compile/DumpRenamedAst.stderr
- testsuite/tests/parser/should_compile/T15323.stderr
- testsuite/tests/printer/T18791.stderr
- testsuite/tests/profiling/should_run/caller-cc/all.T
- + testsuite/tests/th/GadtConSigs_th_dump1.hs
- + testsuite/tests/th/GadtConSigs_th_dump1.stderr
- + testsuite/tests/th/GadtConSigs_th_pprint1.hs
- + testsuite/tests/th/GadtConSigs_th_pprint1.stderr
- testsuite/tests/th/T20868.stdout
- testsuite/tests/th/all.T
- testsuite/tests/typecheck/should_compile/T23739a.hs
- + testsuite/tests/typecheck/should_compile/TyAppPat_Tricky.hs
- testsuite/tests/typecheck/should_compile/all.T
- testsuite/tests/typecheck/should_fail/T20443b.stderr
- testsuite/tests/typecheck/should_fail/TyAppPat_TooMany.stderr
- + testsuite/tests/vdq-rta/should_compile/T25127_data.hs
- + testsuite/tests/vdq-rta/should_compile/T25127_data_inst.hs
- + testsuite/tests/vdq-rta/should_compile/T25127_infix.hs
- + testsuite/tests/vdq-rta/should_compile/T25127_newtype.hs
- testsuite/tests/vdq-rta/should_compile/all.T
- testsuite/tests/vdq-rta/should_fail/T24159_type_syntax_th_fail.script
- + testsuite/tests/vdq-rta/should_fail/T25127_fail_arity.hs
- + testsuite/tests/vdq-rta/should_fail/T25127_fail_arity.stderr
- + testsuite/tests/vdq-rta/should_fail/T25127_fail_th_quote.hs
- + testsuite/tests/vdq-rta/should_fail/T25127_fail_th_quote.stderr
- testsuite/tests/vdq-rta/should_fail/all.T
- utils/check-exact/ExactPrint.hs
- utils/ghc-toolchain/exe/Main.hs
- utils/ghc-toolchain/src/GHC/Toolchain/Target.hs
- utils/haddock/haddock-api/src/Haddock/Backends/Hoogle.hs
- utils/haddock/haddock-api/src/Haddock/Convert.hs
- utils/haddock/haddock-api/src/Haddock/GhcUtils.hs
- utils/haddock/haddock-api/src/Haddock/Interface/Rename.hs
The diff was not included because it is too large.
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/88d6c41456df78c3c9529cc7e6b49f…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/88d6c41456df78c3c9529cc7e6b49f…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][wip/sand-witch/make-set-field] Small fixes after intensive testing
by Andrei Borzenkov (@sand-witch) 02 Jul '25
by Andrei Borzenkov (@sand-witch) 02 Jul '25
02 Jul '25
Andrei Borzenkov pushed to branch wip/sand-witch/make-set-field at Glasgow Haskell Compiler / GHC
Commits:
88d6c414 by Andrei Borzenkov at 2025-07-02T22:10:04+04:00
Small fixes after intensive testing
- - - - -
7 changed files:
- compiler/GHC/Builtin/Names.hs
- compiler/GHC/Core/Make.hs
- compiler/GHC/Tc/Instance/Class.hs
- compiler/GHC/Tc/Module.hs
- compiler/GHC/Tc/TyCl/Utils.hs
- compiler/GHC/Tc/Types.hs
- libraries/ghc-internal/src/GHC/Internal/Control/Exception/Base.hs
Changes:
=====================================
compiler/GHC/Builtin/Names.hs
=====================================
@@ -2308,7 +2308,7 @@ wildCardKey, absentErrorIdKey, absentConstraintErrorIdKey, augmentIdKey, appendI
noMethodBindingErrorIdKey, nonExhaustiveGuardsErrorIdKey,
impossibleErrorIdKey, impossibleConstraintErrorIdKey,
patErrorIdKey, voidPrimIdKey,
- realWorldPrimIdKey, recConErrorIdKey,
+ realWorldPrimIdKey, recConErrorIdKey, recUpdErrorIdKey,
unpackCStringUtf8IdKey, unpackCStringAppendUtf8IdKey, unpackCStringFoldrUtf8IdKey,
unpackCStringIdKey, unpackCStringAppendIdKey, unpackCStringFoldrIdKey,
typeErrorIdKey, divIntIdKey, modIntIdKey,
@@ -2409,6 +2409,7 @@ rationalToFloatIdKey = mkPreludeMiscIdUnique 132
rationalToDoubleIdKey = mkPreludeMiscIdUnique 133
seqHashKey = mkPreludeMiscIdUnique 134
+recUpdErrorIdKey = mkPreludeMiscIdUnique 135
coerceKey :: Unique
coerceKey = mkPreludeMiscIdUnique 157
=====================================
compiler/GHC/Core/Make.hs
=====================================
@@ -42,7 +42,7 @@ module GHC.Core.Make (
-- * Error Ids
mkRuntimeErrorApp, mkImpossibleExpr, mkAbsentErrorApp, errorIds,
- rEC_CON_ERROR_ID,
+ rEC_CON_ERROR_ID, rEC_UPD_ERROR_ID,
nON_EXHAUSTIVE_GUARDS_ERROR_ID, nO_METHOD_BINDING_ERROR_ID,
pAT_ERROR_ID, rEC_SEL_ERROR_ID,
tYPE_ERROR_ID, aBSENT_SUM_FIELD_ERROR_ID
@@ -897,6 +897,7 @@ errorIds
nO_METHOD_BINDING_ERROR_ID,
pAT_ERROR_ID,
rEC_CON_ERROR_ID,
+ rEC_UPD_ERROR_ID,
rEC_SEL_ERROR_ID,
iMPOSSIBLE_ERROR_ID, iMPOSSIBLE_CONSTRAINT_ERROR_ID,
aBSENT_ERROR_ID, aBSENT_CONSTRAINT_ERROR_ID,
@@ -904,13 +905,14 @@ errorIds
tYPE_ERROR_ID -- Used with Opt_DeferTypeErrors, see #10284
]
-recSelErrorName, recConErrorName, patErrorName :: Name
+recSelErrorName, recConErrorName, patErrorName, recUpdErrorName :: Name
nonExhaustiveGuardsErrorName, noMethodBindingErrorName :: Name
typeErrorName :: Name
absentSumFieldErrorName :: Name
recSelErrorName = err_nm "recSelError" recSelErrorIdKey rEC_SEL_ERROR_ID
recConErrorName = err_nm "recConError" recConErrorIdKey rEC_CON_ERROR_ID
+recUpdErrorName = err_nm "recUpdError" recUpdErrorIdKey rEC_UPD_ERROR_ID
patErrorName = err_nm "patError" patErrorIdKey pAT_ERROR_ID
typeErrorName = err_nm "typeError" typeErrorIdKey tYPE_ERROR_ID
@@ -922,11 +924,12 @@ nonExhaustiveGuardsErrorName = err_nm "nonExhaustiveGuardsError"
err_nm :: String -> Unique -> Id -> Name
err_nm str uniq id = mkWiredInIdName gHC_INTERNAL_CONTROL_EXCEPTION_BASE (fsLit str) uniq id
-rEC_SEL_ERROR_ID, rEC_CON_ERROR_ID :: Id
+rEC_SEL_ERROR_ID, rEC_CON_ERROR_ID, rEC_UPD_ERROR_ID :: Id
pAT_ERROR_ID, nO_METHOD_BINDING_ERROR_ID, nON_EXHAUSTIVE_GUARDS_ERROR_ID :: Id
tYPE_ERROR_ID, aBSENT_SUM_FIELD_ERROR_ID :: Id
rEC_SEL_ERROR_ID = mkRuntimeErrorId TypeLike recSelErrorName
rEC_CON_ERROR_ID = mkRuntimeErrorId TypeLike recConErrorName
+rEC_UPD_ERROR_ID = mkRuntimeErrorId TypeLike recUpdErrorName
pAT_ERROR_ID = mkRuntimeErrorId TypeLike patErrorName
nO_METHOD_BINDING_ERROR_ID = mkRuntimeErrorId TypeLike noMethodBindingErrorName
nON_EXHAUSTIVE_GUARDS_ERROR_ID = mkRuntimeErrorId TypeLike nonExhaustiveGuardsErrorName
=====================================
compiler/GHC/Tc/Instance/Class.hs
=====================================
@@ -1340,7 +1340,7 @@ matchSetField dflags short_cut clas tys mb_ct_loc
-- Use the equality proof to cast the selector Id to
-- type (r -> a), then use the newtype coercion to cast
-- it to a HasField dictionary.
- mk_ev (ev1:ev2:evs) = evDFunApp (dataConWrapId dCon) (tys ++ tvs)
+ mk_ev (ev1:ev2:evs) = evDFunApp (dataConWrapId dCon) tys
[ evSelector modifier_id tvs evs `Cast` co ev2
, evSelector setter_id tvs evs `Cast` co ev1
]
@@ -1395,7 +1395,7 @@ matchSetField dflags short_cut clas tys mb_ct_loc
pure (setter, modifier)
Nothing -> do
binds@((setter, _), (modifier,_)) <- mkSetFieldBinds tycon fl
- writeTcRef req_flds ((fl, binds) : reqs)
+ updTcRef req_flds ((fl, binds) : )
pure (setter, modifier)
tc_inst_setfield_binds setter_id modifier_id
=====================================
compiler/GHC/Tc/Module.hs
=====================================
@@ -579,12 +579,13 @@ tcRnSrcDecls explicit_mod_hdr export_ies decls
-- Emit Typeable bindings
; tcg_env <- setGblEnv tcg_env $
mkTypeableBinds
+
; (tcg_env, recs_lie) <- setGblEnv tcg_env $
captureTopConstraints $
tcRecSetterBinds
; rec_ev_binds <- restoreEnvs (tcg_env, tcl_env) $
- simplifyTop recs_lie -- Is that required?
+ simplifyTop recs_lie -- TODO sand-witch: Is that required?
; let new_ev_binds = main_ev_binds `mappend` rec_ev_binds
=====================================
compiler/GHC/Tc/TyCl/Utils.hs
=====================================
@@ -42,7 +42,7 @@ import GHC.Hs
import GHC.Core.TyCo.Rep( Type(..), Coercion(..), MCoercion(..) )
import GHC.Core.Multiplicity
import GHC.Core.Predicate
-import GHC.Core.Make( rEC_SEL_ERROR_ID )
+import GHC.Core.Make( rEC_SEL_ERROR_ID, rEC_UPD_ERROR_ID )
import GHC.Core.Class
import GHC.Core.Type
import GHC.Core.TyCon
@@ -868,19 +868,22 @@ mkRecSelBind (tycon, fl)
mkOneRecordSelector :: [ConLike] -> RecSelParent -> FieldLabel -> FieldSelectors
-> (Id, LHsBind GhcRn)
mkOneRecordSelector all_cons idDetails fl has_sel
- = collectFieldLabelInfo all_cons idDetails fl has_sel mkRecordSelectorBind
+ = collectFieldLabelInfo all_cons idDetails fl has_sel mkRecordSelectorBind
mkRecordSelectorBind :: RecordBindBuilder (Id, LHsBind GhcRn)
-mkRecordSelectorBind = mk_record_bind mk_sel_ty mk_match where
+mkRecordSelectorBind fl = mk_record_bind 1 err_expr mk_sel_ty mk_match fl where
+
+ err_expr = make_rec_error_expr fl rEC_SEL_ERROR_ID
+
mk_sel_ty :: Type -> Type -> Type
- mk_sel_ty data_ty field_ty =
+ mk_sel_ty data_ty field_ty =
mkVisFunTyMany data_ty $
-- Record selectors are always typed with Many. We
-- could improve on it in the case where all the
-- fields in all the constructor have multiplicity Many.
field_ty
- mk_match sel_name match_ctxt con =
+ mk_match sel_name match_ctxt con =
mkSimpleMatch match_ctxt
(L loc [L loc (mk_sel_pat con)])
(L loc (mkHsVar (L loc field_var)))
@@ -915,7 +918,7 @@ tcRecSetterBinds = do
where
remove_binds (n, ((setter, _), (modifier, _))) = (flSelector n, (setter, modifier))
get_ids_to_check [] = []
- get_ids_to_check ( (_, (setter, modifier)) : flds) =
+ get_ids_to_check ( (_, (setter, modifier)) : flds) =
setter : modifier : get_ids_to_check flds
@@ -928,41 +931,44 @@ mkSetFieldBinds tycon fl =
idDetails = RecSelData tycon
mk_field_lbl prefix uniq =
- let
+ let
lbl = flLabel fl
newOcc = mkOccNameFS varName (mkFastString prefix `mappend` field_label lbl)
- in fl {flSelector = flSelector fl `setNameUnique` uniq `tidyNameOcc` newOcc}
+ in fl { flSelector = flSelector fl `setNameUnique` uniq `tidyNameOcc` newOcc }
mk_binds cons_w_field rec_details ty_builder = do
setter_fl <- mk_field_lbl "setter_" <$> newUnique
- modifier_fd <- mk_field_lbl "modifier_" <$> newUnique
+ modifier_fl <- mk_field_lbl "modifier_" <$> newUnique
let setter_bind = mkRecordSetterBind fl setter_fl all_cons cons_w_field rec_details ty_builder
- modifier_bind = mkRecordModifierBind fl modifier_fd all_cons cons_w_field rec_details ty_builder
+ modifier_bind = mkRecordModifierBind fl modifier_fl all_cons cons_w_field rec_details ty_builder
pure (setter_bind, modifier_bind)
-
mkRecordSetterBind :: FieldLabel -> RecordBindBuilder (Id, LHsBind GhcRn)
-mkRecordSetterBind origFl fl = mk_record_bind mkRecordSetterType mk_match fl where
+mkRecordSetterBind origFl fl = mk_record_bind 2 err_expr mkRecordSetterType mk_match fl where
- mk_match =
- mk_set_fld_match (getOccName $ flSelector fl) origFl $
+ err_expr = make_rec_error_expr origFl rEC_UPD_ERROR_ID
+
+ mk_match =
+ mk_set_fld_match (getOccName $ flSelector origFl) origFl $
\_ field_var -> (genWildPat, genLHsVar field_var)
mkRecordSetterType :: Type -> Type -> Type
-mkRecordSetterType data_ty field_ty =
+mkRecordSetterType data_ty field_ty =
mkVisFunTyMany field_ty $
mkVisFunTyMany data_ty data_ty
mkRecordModifierBind :: FieldLabel -> RecordBindBuilder (Id, LHsBind GhcRn)
-mkRecordModifierBind origFl fl = mk_record_bind mkRecordModifierType mk_match fl where
+mkRecordModifierBind origFl fl = mk_record_bind 2 err_expr mkRecordModifierType mk_match fl where
+
+ err_expr = make_rec_error_expr origFl rEC_UPD_ERROR_ID
- mk_match = mk_set_fld_match (mkOccName varName "f") origFl $ \i fun_var ->
+ mk_match = mk_set_fld_match (mkOccName varName "f") origFl $ \i fun_var ->
let fld_nm = mk_set_fld_bind i fl
expr = wrapGenSpan $ HsPar noExtField $ genLHsApp (genHsVar fun_var) (genLHsVar fld_nm)
in (genVarPat fld_nm, expr)
mkRecordModifierType :: Type -> Type -> Type
-mkRecordModifierType data_ty field_ty =
+mkRecordModifierType data_ty field_ty =
mkVisFunTyMany (mkVisFunTyMany field_ty field_ty) $
mkVisFunTyMany data_ty data_ty
@@ -981,11 +987,11 @@ mk_set_fld_match occ_name fl on_fld setter_name match_ctxt con =
loc = noAnnSrcSpan (getSrcSpan setter_name)
- mk_con_arg i fld_lbl
+ mk_con_arg i fld_lbl
| fl == fld_lbl = on_fld i arg_var
| otherwise =
let fld_nm = mk_set_fld_bind i fld_lbl
- in (genVarPat fld_nm, genLHsVar fld_nm)
+ in (genVarPat fld_nm, genLHsVar fld_nm)
arg_var = mkInternalName (mkBuiltinUnique 1) occ_name loc
@@ -993,14 +999,14 @@ mk_set_fld_bind :: Int -> FieldLabel -> Name
mk_set_fld_bind i fld_lbl =
mkInternalName (mkBuiltinUnique i)
(nameOccName $ flSelector $ fld_lbl)
- generatedSrcSpan
+ generatedSrcSpan
type ConLikeWithField = ConLike
-type RecordBindBuilder r =
+type RecordBindBuilder r =
FieldLabel -> [ConLike] -> [ConLikeWithField] -> IdDetails -> ((Type -> Type -> Type) -> Type) -> r
-type FldBindMatchBuilder =
+type FldBindMatchBuilder =
Name -> HsMatchContext (LocatedN Name) -> ConLikeWithField -> LMatch GhcRn (LHsExpr GhcRn)
collectFieldLabelInfo :: [ConLike] ->
@@ -1052,7 +1058,7 @@ collectFieldLabelInfo all_cons idDetails fl has_sel k
-- A slight hack!
sel_ty | is_naughty = \_ -> unitTy -- See Note [Naughty record selectors]
- | otherwise = \mk_ty ->
+ | otherwise = \mk_ty ->
mkForAllTys (tyVarSpecToBinders sel_tvbs) $
-- Urgh! See Note [The stupid context] in GHC.Core.DataCon
mkPhiTy (conLikeStupidTheta con1) $
@@ -1060,11 +1066,21 @@ collectFieldLabelInfo all_cons idDetails fl has_sel k
mkPhiTy req_theta $
mk_ty data_ty field_ty
-mk_record_bind ::
+make_rec_error_expr :: FieldLabel -> Id -> LHsExpr GhcRn
+make_rec_error_expr fl err_id =
+ genLHsApp
+ (genHsVar (getName err_id))
+ (genLHsLit msg_lit)
+ where
+ msg_lit = HsStringPrim NoSourceText (bytesFS (field_label (flLabel fl)))
+
+mk_record_bind ::
+ Int ->
+ LHsExpr GhcRn ->
(Type -> Type -> Type) ->
FldBindMatchBuilder ->
RecordBindBuilder (Id, LHsBind GhcRn)
-mk_record_bind mk_ty mk_match fl all_cons cons_w_field rec_details ty_builder
+mk_record_bind num_args err_expr mk_ty mk_match fl all_cons cons_w_field rec_details ty_builder
= (sel_id, L loc sel_bind)
where
sel_ty = ty_builder mk_ty
@@ -1092,10 +1108,8 @@ mk_record_bind mk_ty mk_match fl all_cons cons_w_field rec_details ty_builder
-- We do this explicitly so that we get a nice error message that
-- mentions this particular record selector
deflt | all dealt_with all_cons = []
- | otherwise = [mkSimpleMatch match_ctxt (wrapGenSpan [genWildPat])
- (genLHsApp
- (genHsVar (getName rEC_SEL_ERROR_ID))
- (genLHsLit msg_lit))]
+ | otherwise = [mkSimpleMatch match_ctxt (wrapGenSpan (replicate num_args genWildPat))
+ err_expr]
-- Do not add a default case unless there are unmatched
-- constructors. We must take account of GADTs, else we
@@ -1114,7 +1128,6 @@ mk_record_bind mk_ty mk_match fl all_cons cons_w_field rec_details ty_builder
inst_tys = dataConResRepTyArgs dc
unit_rhs = mkLHsTupleExpr [] noExtField
- msg_lit = HsStringPrim NoSourceText (bytesFS (field_label (flLabel fl)))
{-
Note [Polymorphic selectors]
=====================================
compiler/GHC/Tc/Types.hs
=====================================
@@ -561,7 +561,7 @@ data TcGblEnv
-- they all have a non-empty gre_imp field.
tcg_keep :: TcRef NameSet,
- tcg_requested_fields :: TcRef [(FieldLabel, ((Id, LHsBind GhcRn), (Id, LHsBind GhcRn)))],
+ tcg_requested_fields :: TcRef [(FieldLabel, (FieldBind, FieldBind))],
tcg_th_used :: TcRef Bool,
-- ^ @True@ \<=> Template Haskell syntax used.
@@ -706,7 +706,8 @@ data TcGblEnv
-- ^ See Note [Generating fresh names for FFI wrappers]
}
-type FieldInstEnv = NameEnv (Id, Id)
+type FieldInstEnv = NameEnv (Id, Id)
+type FieldBind = (Id, LHsBind GhcRn)
-- NB: topModIdentity, not topModSemantic!
-- Definition sites of orphan identities will be identity modules, not semantic
=====================================
libraries/ghc-internal/src/GHC/Internal/Control/Exception/Base.hs
=====================================
@@ -104,7 +104,7 @@ module GHC.Internal.Control.Exception.Base (
finally,
-- * Calls for GHC runtime
- recSelError, recConError,
+ recSelError, recConError, recUpdError,
impossibleError, impossibleConstraintError,
nonExhaustiveGuardsError, patError, noMethodBindingError,
typeError,
@@ -422,12 +422,14 @@ instance Exception NoMatchingContinuationPrompt
-----
-- See Note [Compiler error functions] in ghc-internal:GHC.Internal.Prim.Panic
-recSelError, recConError, typeError,
+recSelError, recUpdError, recConError, typeError,
nonExhaustiveGuardsError, patError, noMethodBindingError
:: Addr# -> a -- All take a UTF8-encoded C string
recSelError s = throw (RecSelError ("No match in record selector "
++ unpackCStringUtf8# s)) -- No location info unfortunately
+recUpdError s = throw (RecUpdError ("No match in record update "
+ ++ unpackCStringUtf8# s)) -- No location info unfortunately
nonExhaustiveGuardsError s = throw (PatternMatchFail (untangle s "Non-exhaustive guards in"))
recConError s = throw (RecConError (untangle s "Missing field in record construction"))
noMethodBindingError s = throw (NoMethodError (untangle s "No instance nor default method for class operation"))
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/88d6c41456df78c3c9529cc7e6b49f6…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/88d6c41456df78c3c9529cc7e6b49f6…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][wip/romes/step-out-9] Deleted 1 commit: ghci: Allocate BreakArrays at link time only
by Rodrigo Mesquita (@alt-romes) 02 Jul '25
by Rodrigo Mesquita (@alt-romes) 02 Jul '25
02 Jul '25
Rodrigo Mesquita pushed to branch wip/romes/step-out-9 at Glasgow Haskell Compiler / GHC
WARNING: The push did not contain any new commits, but force pushed to delete the commits and changes below.
Deleted commits:
5178fc25 by Rodrigo Mesquita at 2025-07-02T17:24:52+01:00
ghci: Allocate BreakArrays at link time only
Previously, a BreakArray would be allocated with a slot for every tick
in a module at `mkModBreaks`, in HsToCore. However, this approach has
a few downsides:
- It interleaves interpreter behaviour (allocating arrays for
breakpoints) within the desugarer
- It is inflexible in the sense it is impossible for the bytecode
generator to add "internal" breakpoints that can be triggered at
runtime, because those wouldn't have a source tick. (This is relevant
for our intended implementation plan of step-out in #26042)
- It ties the BreakArray indices to the *tick* indexes, while at runtime
we would rather just have the *info* indexes (currently we have both
because BreakArrays are indexed by the *tick* one).
Paving the way for #26042 and #26064, this commit moves the allocation
of BreakArrays to bytecode-loading time -- akin to what is done for CCS
arrays.
Since a BreakArray is allocated only when bytecode is linked, if a
breakpoint is set (e.g. `:break 10`) before the bytecode is linked,
there will exist no BreakArray to trigger the breakpoint in.
Therefore, the function to allocate break arrays (`allocateBreakArrays`)
is exposed and also used in GHC.Runtime.Eval to allocate a break array
when a breakpoint is set, if it doesn't exist yet (in the linker env).
- - - - -
8 changed files:
- compiler/GHC/HsToCore.hs
- compiler/GHC/HsToCore/Breakpoints.hs
- compiler/GHC/Linker/Loader.hs
- compiler/GHC/Runtime/Eval.hs
- − compiler/GHC/Runtime/Interpreter.hs-boot
- − compiler/GHC/Runtime/Interpreter/Types.hs-boot
- testsuite/tests/count-deps/CountDepsAst.stdout
- testsuite/tests/count-deps/CountDepsParser.stdout
Changes:
=====================================
compiler/GHC/HsToCore.hs
=====================================
@@ -97,8 +97,8 @@ import GHC.Unit.Module.Deps
import Data.List (partition)
import Data.IORef
-import Data.Traversable (for)
import GHC.Iface.Make (mkRecompUsageInfo)
+import GHC.Runtime.Interpreter (interpreterProfiled)
{-
************************************************************************
@@ -162,13 +162,12 @@ deSugar hsc_env
mod mod_loc
export_set (typeEnvTyCons type_env) binds
else return (binds, Nothing)
- ; modBreaks <- for
- [ (i, s)
- | i <- hsc_interp hsc_env
- , (_, s) <- m_tickInfo
- , breakpointsAllowed dflags
- ]
- $ \(interp, specs) -> mkModBreaks interp mod specs
+ ; let modBreaks
+ | Just (_, specs) <- m_tickInfo
+ , breakpointsAllowed dflags
+ = Just $ mkModBreaks (interpreterProfiled $ hscInterp hsc_env) mod specs
+ | otherwise
+ = Nothing
; ds_hpc_info <- case m_tickInfo of
Just (orig_file2, ticks)
=====================================
compiler/GHC/HsToCore/Breakpoints.hs
=====================================
@@ -33,14 +33,6 @@ import GHC.Unit.Module (Module)
import GHC.Utils.Outputable
import Data.List (intersperse)
-import GHCi.BreakArray (BreakArray)
-import GHCi.RemoteTypes (ForeignRef)
-
--- TODO: Break this cycle
-import {-# SOURCE #-} GHC.Runtime.Interpreter.Types (Interp, interpreterProfiled)
-import {-# SOURCE #-} qualified GHC.Runtime.Interpreter as GHCi (newBreakArray)
-import Data.Array.Base (numElements)
-
--------------------------------------------------------------------------------
-- ModBreaks
--------------------------------------------------------------------------------
@@ -58,10 +50,7 @@ import Data.Array.Base (numElements)
-- and 'modBreaks_decls'.
data ModBreaks
= ModBreaks
- { modBreaks_flags :: ForeignRef BreakArray
- -- ^ The array of flags, one per breakpoint,
- -- indicating which breakpoints are enabled.
- , modBreaks_locs :: !(Array BreakTickIndex SrcSpan)
+ { modBreaks_locs :: !(Array BreakTickIndex SrcSpan)
-- ^ An array giving the source span of each breakpoint.
, modBreaks_vars :: !(Array BreakTickIndex [OccName])
-- ^ An array giving the names of the free variables at each breakpoint.
@@ -83,40 +72,31 @@ data ModBreaks
-- generator needs to encode this information for each expression, the data is
-- allocated remotely in GHCi's address space and passed to the codegen as
-- foreign pointers.
-mkModBreaks :: Interp -> Module -> SizedSeq Tick -> IO ModBreaks
-mkModBreaks interp mod extendedMixEntries
- = do
- let count = fromIntegral $ sizeSS extendedMixEntries
+mkModBreaks :: Bool {-^ Whether the interpreter is profiled and thus if we should include store a CCS array -}
+ -> Module -> SizedSeq Tick -> ModBreaks
+mkModBreaks interpreterProfiled modl extendedMixEntries
+ = let count = fromIntegral $ sizeSS extendedMixEntries
entries = ssElts extendedMixEntries
- let
- locsTicks = listArray (0,count-1) [ tick_loc t | t <- entries ]
- varsTicks = listArray (0,count-1) [ tick_ids t | t <- entries ]
- declsTicks = listArray (0,count-1) [ tick_path t | t <- entries ]
- ccs
- | interpreterProfiled interp =
- listArray
- (0, count - 1)
- [ ( concat $ intersperse "." $ tick_path t,
- renderWithContext defaultSDocContext $ ppr $ tick_loc t
- )
- | t <- entries
- ]
- | otherwise = listArray (0, -1) []
- hydrateModBreaks interp $
- ModBreaks
- { modBreaks_flags = undefined,
- modBreaks_locs = locsTicks,
- modBreaks_vars = varsTicks,
- modBreaks_decls = declsTicks,
- modBreaks_ccs = ccs,
- modBreaks_module = mod
- }
-
-hydrateModBreaks :: Interp -> ModBreaks -> IO ModBreaks
-hydrateModBreaks interp ModBreaks {..} = do
- let count = numElements modBreaks_locs
- modBreaks_flags <- GHCi.newBreakArray interp count
- pure ModBreaks {..}
+ locsTicks = listArray (0,count-1) [ tick_loc t | t <- entries ]
+ varsTicks = listArray (0,count-1) [ tick_ids t | t <- entries ]
+ declsTicks = listArray (0,count-1) [ tick_path t | t <- entries ]
+ ccs
+ | interpreterProfiled =
+ listArray
+ (0, count - 1)
+ [ ( concat $ intersperse "." $ tick_path t,
+ renderWithContext defaultSDocContext $ ppr $ tick_loc t
+ )
+ | t <- entries
+ ]
+ | otherwise = listArray (0, -1) []
+ in ModBreaks
+ { modBreaks_locs = locsTicks
+ , modBreaks_vars = varsTicks
+ , modBreaks_decls = declsTicks
+ , modBreaks_ccs = ccs
+ , modBreaks_module = modl
+ }
{-
Note [Field modBreaks_decls]
=====================================
compiler/GHC/Linker/Loader.hs
=====================================
@@ -28,6 +28,7 @@ module GHC.Linker.Loader
, extendLoadedEnv
, deleteFromLoadedEnv
-- * Internals
+ , allocateBreakArrays
, rmDupLinkables
, modifyLoaderState
, initLinkDepsOpts
@@ -122,8 +123,8 @@ import System.Win32.Info (getSystemDirectory)
import GHC.Utils.Exception
import GHC.Unit.Home.Graph (lookupHug, unitEnv_foldWithKey)
import GHC.Driver.Downsweep
-
-
+import qualified GHC.Runtime.Interpreter as GHCi
+import Data.Array.Base (numElements)
-- Note [Linkers and loaders]
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -696,16 +697,8 @@ loadDecls interp hsc_env span linkable = do
let le = linker_env pls
le2_itbl_env <- linkITbls interp (itbl_env le) (concat $ map bc_itbls cbcs)
le2_addr_env <- foldlM (\env cbc -> allocateTopStrings interp (bc_strs cbc) env) (addr_env le) cbcs
- le2_breakarray_env <-
- allocateBreakArrays
- interp
- (catMaybes $ map bc_breaks cbcs)
- (breakarray_env le)
- le2_ccs_env <-
- allocateCCS
- interp
- (catMaybes $ map bc_breaks cbcs)
- (ccs_env le)
+ le2_breakarray_env <- allocateBreakArrays interp (breakarray_env le) (catMaybes $ map bc_breaks cbcs)
+ le2_ccs_env <- allocateCCS interp (ccs_env le) (catMaybes $ map bc_breaks cbcs)
let le2 = le { itbl_env = le2_itbl_env
, addr_env = le2_addr_env
, breakarray_env = le2_breakarray_env
@@ -933,12 +926,8 @@ dynLinkBCOs interp pls bcos = do
le1 = linker_env pls
ie2 <- linkITbls interp (itbl_env le1) (concatMap bc_itbls cbcs)
ae2 <- foldlM (\env cbc -> allocateTopStrings interp (bc_strs cbc) env) (addr_env le1) cbcs
- be2 <-
- allocateBreakArrays
- interp
- (catMaybes $ map bc_breaks cbcs)
- (breakarray_env le1)
- ce2 <- allocateCCS interp (catMaybes $ map bc_breaks cbcs) (ccs_env le1)
+ be2 <- allocateBreakArrays interp (breakarray_env le1) (catMaybes $ map bc_breaks cbcs)
+ ce2 <- allocateCCS interp (ccs_env le1) (catMaybes $ map bc_breaks cbcs)
let le2 = le1 { itbl_env = ie2, addr_env = ae2, breakarray_env = be2, ccs_env = ce2 }
names_and_refs <- linkSomeBCOs interp (pkgs_loaded pls) le2 cbcs
@@ -1656,30 +1645,34 @@ allocateTopStrings interp topStrings prev_env = do
where
mk_entry nm ptr = (nm, (nm, AddrPtr ptr))
--- | Given a list of 'ModBreaks' collected from a list of
--- 'CompiledByteCode', allocate the 'BreakArray'.
+-- | Given a list of 'InternalModBreaks' collected from a list of
+-- 'CompiledByteCode', allocate the 'BreakArray' used to trigger breakpoints.
allocateBreakArrays ::
Interp ->
- [InternalModBreaks] ->
ModuleEnv (ForeignRef BreakArray) ->
+ [InternalModBreaks] ->
IO (ModuleEnv (ForeignRef BreakArray))
-allocateBreakArrays _interp mbs be =
+allocateBreakArrays interp =
foldlM
- ( \be0 InternalModBreaks{imodBreaks_modBreaks=ModBreaks {..}} ->
- evaluate $ extendModuleEnv be0 modBreaks_module modBreaks_flags
+ ( \be0 InternalModBreaks{imodBreaks_modBreaks=ModBreaks {..}} -> do
+ -- If no BreakArray is assigned to this module yet, create one
+ if not $ elemModuleEnv modBreaks_module be0 then do
+ let count = numElements modBreaks_locs
+ breakArray <- GHCi.newBreakArray interp count
+ evaluate $ extendModuleEnv be0 modBreaks_module breakArray
+ else
+ return be0
)
- be
- mbs
--- | Given a list of 'ModBreaks' collected from a list of
--- 'CompiledByteCode', allocate the 'CostCentre' arrays when profiling
--- is enabled.
+-- | Given a list of 'InternalModBreaks' collected from a list
+-- of 'CompiledByteCode', allocate the 'CostCentre' arrays when profiling is
+-- enabled.
allocateCCS ::
Interp ->
- [InternalModBreaks] ->
ModuleEnv (Array BreakTickIndex (RemotePtr CostCentre)) ->
+ [InternalModBreaks] ->
IO (ModuleEnv (Array BreakTickIndex (RemotePtr CostCentre)))
-allocateCCS interp mbs ce
+allocateCCS interp ce mbss
| interpreterProfiled interp =
foldlM
( \ce0 InternalModBreaks{imodBreaks_modBreaks=ModBreaks {..}} -> do
@@ -1688,12 +1681,15 @@ allocateCCS interp mbs ce
interp
(moduleNameString $ moduleName modBreaks_module)
(elems modBreaks_ccs)
- evaluate $
- extendModuleEnv ce0 modBreaks_module $
- listArray
- (0, length ccs - 1)
- ccs
+ if not $ elemModuleEnv modBreaks_module ce0 then do
+ evaluate $
+ extendModuleEnv ce0 modBreaks_module $
+ listArray
+ (0, length ccs - 1)
+ ccs
+ else
+ return ce0
)
ce
- mbs
+ mbss
| otherwise = pure ce
=====================================
compiler/GHC/Runtime/Eval.hs
=====================================
@@ -64,6 +64,7 @@ import GHCi.RemoteTypes
import GHC.ByteCode.Types
import GHC.Linker.Loader as Loader
+import GHC.Linker.Types (LinkerEnv(..))
import GHC.Hs
@@ -126,6 +127,7 @@ import GHC.Tc.Utils.Instantiate (instDFunType)
import GHC.Tc.Utils.Monad
import GHC.IfaceToCore
+import GHC.ByteCode.Breakpoints
import Control.Monad
import Data.Dynamic
@@ -134,7 +136,7 @@ import Data.List (find,intercalate)
import Data.List.NonEmpty (NonEmpty)
import Unsafe.Coerce ( unsafeCoerce )
import qualified GHC.Unit.Home.Graph as HUG
-import GHC.ByteCode.Breakpoints
+import GHCi.BreakArray (BreakArray)
-- -----------------------------------------------------------------------------
-- running a statement interactively
@@ -348,13 +350,14 @@ handleRunStatus step expr bindings final_ids status history0 = do
EvalBreak apStack_ref (Just eval_break) resume_ctxt ccs -> do
let ibi = evalBreakpointToId eval_break
let hug = hsc_HUG hsc_env
- tick_brks <- liftIO $ readModBreaks hug (ibi_tick_mod ibi)
+ tick_brks <- liftIO $ readModBreaks hug (ibi_tick_mod ibi)
+ breakArray <- getBreakArray interp (toBreakpointId ibi) tick_brks
let
span = getBreakLoc ibi tick_brks
decl = intercalate "." $ getBreakDecls ibi tick_brks
-- Was this breakpoint explicitly enabled (ie. in @BreakArray@)?
- bactive <- liftIO $ breakpointStatus interp (modBreaks_flags $ imodBreaks_modBreaks tick_brks) (ibi_tick_index ibi)
+ bactive <- liftIO $ breakpointStatus interp breakArray (ibi_tick_index ibi)
apStack_fhv <- liftIO $ mkFinalizedHValue interp apStack_ref
resume_ctxt_fhv <- liftIO $ mkFinalizedHValue interp resume_ctxt
@@ -462,9 +465,24 @@ setupBreakpoint :: GhcMonad m => Interp -> BreakpointId -> Int -> m () -- #191
setupBreakpoint interp bi cnt = do
hug <- hsc_HUG <$> getSession
modBreaks <- liftIO $ readModBreaks hug (bi_tick_mod bi)
- let breakarray = modBreaks_flags $ imodBreaks_modBreaks modBreaks
- _ <- liftIO $ GHCi.storeBreakpoint interp breakarray (bi_tick_index bi) cnt
- pure ()
+ breakArray <- getBreakArray interp bi modBreaks
+ liftIO $ GHCi.storeBreakpoint interp breakArray (bi_tick_index bi) cnt
+
+getBreakArray :: GhcMonad m => Interp -> BreakpointId -> InternalModBreaks -> m (ForeignRef BreakArray)
+getBreakArray interp BreakpointId{bi_tick_mod} imbs = do
+
+ liftIO $ modifyLoaderState interp $ \ld_st -> do
+ let le = linker_env ld_st
+
+ -- Recall that BreakArrays are allocated only at BCO link time, so if we
+ -- haven't linked the BCOs we intend to break at yet, we allocate the arrays here.
+ ba_env <- allocateBreakArrays interp (breakarray_env le) [imbs]
+
+ return
+ ( ld_st { linker_env = le{breakarray_env = ba_env} }
+ , expectJust {- just computed -} $
+ lookupModuleEnv ba_env bi_tick_mod
+ )
back :: GhcMonad m => Int -> m ([Name], Int, SrcSpan)
back n = moveHist (+n)
=====================================
compiler/GHC/Runtime/Interpreter.hs-boot deleted
=====================================
@@ -1,10 +0,0 @@
-module GHC.Runtime.Interpreter where
-
-import {-# SOURCE #-} GHC.Runtime.Interpreter.Types
-import Data.Int (Int)
-import GHC.Base (IO)
-import GHCi.BreakArray (BreakArray)
-import GHCi.RemoteTypes (ForeignRef)
-
-newBreakArray :: Interp -> Int -> IO (ForeignRef BreakArray)
-
=====================================
compiler/GHC/Runtime/Interpreter/Types.hs-boot deleted
=====================================
@@ -1,6 +0,0 @@
-module GHC.Runtime.Interpreter.Types where
-
-import Data.Bool
-
-data Interp
-interpreterProfiled :: Interp -> Bool
=====================================
testsuite/tests/count-deps/CountDepsAst.stdout
=====================================
@@ -5,6 +5,7 @@ GHC.Builtin.Types
GHC.Builtin.Types.Literals
GHC.Builtin.Types.Prim
GHC.Builtin.Uniques
+GHC.ByteCode.Breakpoints
GHC.ByteCode.Types
GHC.Cmm.BlockId
GHC.Cmm.CLabel
@@ -110,6 +111,8 @@ GHC.Hs.Pat
GHC.Hs.Specificity
GHC.Hs.Type
GHC.Hs.Utils
+GHC.HsToCore.Breakpoints
+GHC.HsToCore.Ticks
GHC.Iface.Errors.Types
GHC.Iface.Ext.Fields
GHC.Iface.Flags
@@ -150,7 +153,6 @@ GHC.Tc.Zonk.Monad
GHC.Types.Annotations
GHC.Types.Avail
GHC.Types.Basic
-GHC.Types.Breakpoint
GHC.Types.CostCentre
GHC.Types.CostCentre.State
GHC.Types.Cpr
=====================================
testsuite/tests/count-deps/CountDepsParser.stdout
=====================================
@@ -5,6 +5,7 @@ GHC.Builtin.Types
GHC.Builtin.Types.Literals
GHC.Builtin.Types.Prim
GHC.Builtin.Uniques
+GHC.ByteCode.Breakpoints
GHC.ByteCode.Types
GHC.Cmm.BlockId
GHC.Cmm.CLabel
@@ -114,8 +115,10 @@ GHC.Hs.Pat
GHC.Hs.Specificity
GHC.Hs.Type
GHC.Hs.Utils
+GHC.HsToCore.Breakpoints
GHC.HsToCore.Errors.Types
GHC.HsToCore.Pmc.Solver.Types
+GHC.HsToCore.Ticks
GHC.Iface.Errors.Types
GHC.Iface.Ext.Fields
GHC.Iface.Flags
@@ -171,7 +174,6 @@ GHC.Tc.Zonk.Monad
GHC.Types.Annotations
GHC.Types.Avail
GHC.Types.Basic
-GHC.Types.Breakpoint
GHC.Types.CompleteMatch
GHC.Types.CostCentre
GHC.Types.CostCentre.State
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/5178fc25ee63483c67ce10f3b2e57a7…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/5178fc25ee63483c67ce10f3b2e57a7…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][wip/romes/step-out-9] 3 commits: refact: Split InternalModBreaks out of ModBreaks
by Rodrigo Mesquita (@alt-romes) 02 Jul '25
by Rodrigo Mesquita (@alt-romes) 02 Jul '25
02 Jul '25
Rodrigo Mesquita pushed to branch wip/romes/step-out-9 at Glasgow Haskell Compiler / GHC
Commits:
06651a24 by Rodrigo Mesquita at 2025-07-02T17:24:52+01:00
refact: Split InternalModBreaks out of ModBreaks
There are currently two competing ways of referring to a Breakpoint:
1. Using the Tick module + Tick index
2. Using the Info module + Info index
1. The Tick index is allocated during desugaring in `mkModBreaks`. It is
used to refer to a breakpoint associated to a Core Tick. For a given
Tick module, there are N Ticks indexed by Tick index.
2. The Info index is allocated during code generation (in StgToByteCode)
and uniquely identifies the breakpoints at runtime (and is indeed used
to determine which breakpoint was hit at runtime).
Why we need both is described by Note [Breakpoint identifiers].
For every info index we used to keep a `CgBreakInfo`, a datatype containing
information relevant to ByteCode Generation, in `ModBreaks`.
This commit splits out the `IntMap CgBreakInfo` out of `ModBreaks` into
a new datatype `InternalModBreaks`.
- The purpose is to separate the `ModBreaks` datatype, which stores
data associated from tick-level information which is fixed after
desugaring, from the unrelated `IntMap CgBreakInfo` information
accumulated during bytecode generation.
- We move `ModBreaks` to GHC.HsToCore.Breakpoints
The new `InternalModBreaks` simply combines the `IntMap CgBreakInfo`
with `ModBreaks`. After code generation we construct an
`InternalModBreaks` with the `CgBreakInfo`s we accumulated and the
existing `ModBreaks` and store that in the compiled BCO in `bc_breaks`.
- Note that we previously only updated the `modBreaks_breakInfo`
field of `ModBreaks` at this exact location, and then stored the
updated `ModBreaks` in the same `bc_breaks`.
- We put this new datatype in GHC.ByteCode.Breakpoints
The rest of the pipeline for which CgBreakInfo is relevant is
accordingly updated to also use `InternalModBreaks`
- - - - -
c3f1b718 by Rodrigo Mesquita at 2025-07-02T17:24:52+01:00
cleanup: Use BreakpointIds in bytecode gen
Small clean up to use BreakpointId and InternalBreakpointId more
uniformly in bytecode generation rather than using Module + Ix pairs
- - - - -
5178fc25 by Rodrigo Mesquita at 2025-07-02T17:24:52+01:00
ghci: Allocate BreakArrays at link time only
Previously, a BreakArray would be allocated with a slot for every tick
in a module at `mkModBreaks`, in HsToCore. However, this approach has
a few downsides:
- It interleaves interpreter behaviour (allocating arrays for
breakpoints) within the desugarer
- It is inflexible in the sense it is impossible for the bytecode
generator to add "internal" breakpoints that can be triggered at
runtime, because those wouldn't have a source tick. (This is relevant
for our intended implementation plan of step-out in #26042)
- It ties the BreakArray indices to the *tick* indexes, while at runtime
we would rather just have the *info* indexes (currently we have both
because BreakArrays are indexed by the *tick* one).
Paving the way for #26042 and #26064, this commit moves the allocation
of BreakArrays to bytecode-loading time -- akin to what is done for CCS
arrays.
Since a BreakArray is allocated only when bytecode is linked, if a
breakpoint is set (e.g. `:break 10`) before the bytecode is linked,
there will exist no BreakArray to trigger the breakpoint in.
Therefore, the function to allocate break arrays (`allocateBreakArrays`)
is exposed and also used in GHC.Runtime.Eval to allocate a break array
when a breakpoint is set, if it doesn't exist yet (in the linker env).
- - - - -
26 changed files:
- compiler/GHC.hs
- compiler/GHC/ByteCode/Asm.hs
- + compiler/GHC/ByteCode/Breakpoints.hs
- compiler/GHC/ByteCode/Instr.hs
- compiler/GHC/ByteCode/Linker.hs
- compiler/GHC/ByteCode/Types.hs
- compiler/GHC/Core/Ppr.hs
- compiler/GHC/Driver/Session/Inspect.hs
- compiler/GHC/HsToCore.hs
- compiler/GHC/HsToCore/Breakpoints.hs
- compiler/GHC/HsToCore/Ticks.hs
- compiler/GHC/Iface/Syntax.hs
- compiler/GHC/Linker/Loader.hs
- compiler/GHC/Linker/Types.hs
- compiler/GHC/Runtime/Debugger/Breakpoints.hs
- compiler/GHC/Runtime/Eval.hs
- compiler/GHC/Runtime/Eval/Types.hs
- compiler/GHC/Runtime/Interpreter.hs
- compiler/GHC/StgToByteCode.hs
- − compiler/GHC/Types/Breakpoint.hs
- compiler/GHC/Types/Tickish.hs
- compiler/GHC/Unit/Module/ModGuts.hs
- compiler/ghc.cabal.in
- ghc/GHCi/UI.hs
- testsuite/tests/count-deps/CountDepsAst.stdout
- testsuite/tests/count-deps/CountDepsParser.stdout
Changes:
=====================================
compiler/GHC.hs
=====================================
@@ -201,7 +201,7 @@ module GHC (
getResumeContext,
GHC.obtainTermFromId, GHC.obtainTermFromVal, reconstructType,
modInfoModBreaks,
- ModBreaks(..), BreakIndex,
+ ModBreaks(..), BreakTickIndex,
BreakpointId(..), InternalBreakpointId(..),
GHC.Runtime.Eval.back,
GHC.Runtime.Eval.forward,
@@ -427,7 +427,6 @@ import GHC.Types.Basic
import GHC.Types.TyThing
import GHC.Types.Name.Env
import GHC.Types.TypeEnv
-import GHC.Types.Breakpoint
import GHC.Types.PkgQual
import GHC.Unit
=====================================
compiler/GHC/ByteCode/Asm.hs
=====================================
@@ -109,7 +109,7 @@ assembleBCOs
-> FlatBag (ProtoBCO Name)
-> [TyCon]
-> [(Name, ByteString)]
- -> Maybe ModBreaks
+ -> Maybe InternalModBreaks
-> [SptEntry]
-> IO CompiledByteCode
assembleBCOs profile proto_bcos tycons top_strs modbreaks spt_entries = do
@@ -841,19 +841,24 @@ assembleI platform i = case i of
W8 -> emit_ bci_OP_INDEX_ADDR_08 []
_ -> unsupported_width
- BRK_FUN tick_mod tickx info_mod infox ->
- do p1 <- ptr $ BCOPtrBreakArray tick_mod
- tick_addr <- lit1 $ BCONPtrFS $ moduleNameFS $ moduleName tick_mod
- info_addr <- lit1 $ BCONPtrFS $ moduleNameFS $ moduleName info_mod
- tick_unitid_addr <- lit1 $ BCONPtrFS $ unitIdFS $ moduleUnitId $ tick_mod
- info_unitid_addr <- lit1 $ BCONPtrFS $ unitIdFS $ moduleUnitId $ info_mod
- np <- lit1 $ BCONPtrCostCentre tick_mod $ fromIntegral tickx
- emit_ bci_BRK_FUN [ Op p1
- , Op tick_addr, Op info_addr
- , Op tick_unitid_addr, Op info_unitid_addr
- , SmallOp tickx, SmallOp infox
- , Op np
- ]
+ BRK_FUN (InternalBreakpointId tick_mod tickx info_mod infox) -> do
+ let -- cast that checks that round-tripping through Word16 doesn't change the value
+ toW16 x = let r = fromIntegral x :: Word16
+ in if fromIntegral r == x
+ then r
+ else pprPanic "schemeER_wrk: breakpoint tick/info index too large!" (ppr x)
+ p1 <- ptr $ BCOPtrBreakArray tick_mod
+ tick_addr <- lit1 $ BCONPtrFS $ moduleNameFS $ moduleName tick_mod
+ info_addr <- lit1 $ BCONPtrFS $ moduleNameFS $ moduleName info_mod
+ tick_unitid_addr <- lit1 $ BCONPtrFS $ unitIdFS $ moduleUnitId $ tick_mod
+ info_unitid_addr <- lit1 $ BCONPtrFS $ unitIdFS $ moduleUnitId $ info_mod
+ np <- lit1 $ BCONPtrCostCentre (BreakpointId tick_mod tickx)
+ emit_ bci_BRK_FUN [ Op p1
+ , Op tick_addr, Op info_addr
+ , Op tick_unitid_addr, Op info_unitid_addr
+ , SmallOp (toW16 tickx), SmallOp (toW16 infox)
+ , Op np
+ ]
BRK_ALTS active -> emit_ bci_BRK_ALTS [SmallOp (if active then 1 else 0)]
=====================================
compiler/GHC/ByteCode/Breakpoints.hs
=====================================
@@ -0,0 +1,206 @@
+{-# LANGUAGE RecordWildCards #-}
+
+-- | Breakpoint information constructed during ByteCode generation.
+--
+-- Specifically, code-generation breakpoints are referred to as "internal
+-- breakpoints", the internal breakpoint data for a module is stored in
+-- 'InternalModBreaks', and is uniquely identified at runtime by an
+-- 'InternalBreakpointId'.
+--
+-- See Note [Breakpoint identifiers]
+module GHC.ByteCode.Breakpoints
+ ( -- * Internal Mod Breaks
+ InternalModBreaks(..), CgBreakInfo(..)
+ , mkInternalModBreaks
+
+ -- ** Internal breakpoint identifier
+ , InternalBreakpointId(..), BreakInfoIndex
+
+ -- * Operations
+ , toBreakpointId
+
+ -- ** Internal-level operations
+ , getInternalBreak, addInternalBreak
+
+ -- ** Source-level information operations
+ , getBreakLoc, getBreakVars, getBreakDecls, getBreakCCS
+
+ -- * Utils
+ , seqInternalModBreaks
+
+ )
+ where
+
+import GHC.Prelude
+import GHC.Types.SrcLoc
+import GHC.Types.Name.Occurrence
+import Control.DeepSeq
+import Data.IntMap.Strict (IntMap)
+import qualified Data.IntMap.Strict as IM
+
+import GHC.HsToCore.Breakpoints
+import GHC.Iface.Syntax
+
+import GHC.Unit.Module (Module)
+import GHC.Utils.Outputable
+import GHC.Utils.Panic
+import Data.Array
+
+{-
+Note [Breakpoint identifiers]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Before optimization a breakpoint is identified uniquely with a tick module
+and a tick index. See 'BreakpointId'. A tick module contains an array, indexed
+with the tick indexes, which indicates breakpoint status.
+
+When we generate ByteCode, we collect information for every breakpoint at
+their *occurrence sites* (see CgBreakInfo) and these info
+are stored in the ModIface of the occurrence module. Because of inlining, we
+can't reuse the tick index to uniquely identify an occurrence; because of
+cross-module inlining, we can't assume that the occurrence module is the same
+as the tick module (#24712).
+
+So every breakpoint occurrence gets assigned a module-unique *info index* and
+we store it alongside the occurrence module (*info module*) in the
+'InternalBreakpointId' datatype. This is the index that we use at runtime to
+identify a breakpoint.
+-}
+
+--------------------------------------------------------------------------------
+-- * Internal breakpoint identifiers
+--------------------------------------------------------------------------------
+
+-- | Internal breakpoint info index
+type BreakInfoIndex = Int
+
+-- | Internal breakpoint identifier
+--
+-- Indexes into the structures in the @'InternalModBreaks'@ produced during ByteCode generation.
+-- See Note [Breakpoint identifiers]
+data InternalBreakpointId = InternalBreakpointId
+ { ibi_tick_mod :: !Module -- ^ Breakpoint tick module
+ , ibi_tick_index :: !Int -- ^ Breakpoint tick index
+ , ibi_info_mod :: !Module -- ^ Breakpoint tick module
+ , ibi_info_index :: !BreakInfoIndex -- ^ Breakpoint tick index
+ }
+ deriving (Eq, Ord)
+
+toBreakpointId :: InternalBreakpointId -> BreakpointId
+toBreakpointId ibi = BreakpointId
+ { bi_tick_mod = ibi_tick_mod ibi
+ , bi_tick_index = ibi_tick_index ibi
+ }
+
+--------------------------------------------------------------------------------
+-- * Internal Mod Breaks
+--------------------------------------------------------------------------------
+
+-- | Internal mod breaks store the runtime-relevant information of breakpoints.
+--
+-- Importantly, it maps 'InternalBreakpointId's to 'CgBreakInfo'.
+--
+-- 'InternalModBreaks' are constructed during bytecode generation and stored in
+-- 'CompiledByteCode' afterwards.
+data InternalModBreaks = InternalModBreaks
+ { imodBreaks_breakInfo :: !(IntMap CgBreakInfo)
+ -- ^ Access code-gen time information about a breakpoint, indexed by
+ -- 'InternalBreakpointId'.
+
+ , imodBreaks_modBreaks :: !ModBreaks
+ -- ^ Store the original ModBreaks for this module, unchanged.
+ -- Allows us to query about source-level breakpoint information using
+ -- an internal breakpoint id.
+ }
+
+-- | Construct an 'InternalModBreaks'
+mkInternalModBreaks :: Module -> IntMap CgBreakInfo -> ModBreaks -> InternalModBreaks
+mkInternalModBreaks mod im mbs =
+ assertPpr (mod == modBreaks_module mbs)
+ (text "Constructing InternalModBreaks with the ModBreaks of a different module!") $
+ InternalModBreaks im mbs
+
+-- | Information about a breakpoint that we know at code-generation time
+-- In order to be used, this needs to be hydrated relative to the current HscEnv by
+-- 'hydrateCgBreakInfo'. Everything here can be fully forced and that's critical for
+-- preventing space leaks (see #22530)
+data CgBreakInfo
+ = CgBreakInfo
+ { cgb_tyvars :: ![IfaceTvBndr] -- ^ Type variables in scope at the breakpoint
+ , cgb_vars :: ![Maybe (IfaceIdBndr, Word)]
+ , cgb_resty :: !IfaceType
+ }
+-- See Note [Syncing breakpoint info] in GHC.Runtime.Eval
+
+-- | Get an internal breakpoint info by 'InternalBreakpointId'
+getInternalBreak :: InternalBreakpointId -> InternalModBreaks -> CgBreakInfo
+getInternalBreak (InternalBreakpointId _ _ info_mod info_ix) imbs =
+ assert_modules_match info_mod (modBreaks_module $ imodBreaks_modBreaks imbs) $
+ imodBreaks_breakInfo imbs IM.! info_ix
+
+-- | Add a CgBreakInfo to an 'InternalModBreaks' at 'InternalBreakpointId'
+addInternalBreak :: InternalBreakpointId -> CgBreakInfo -> InternalModBreaks -> InternalModBreaks
+addInternalBreak (InternalBreakpointId _ _ info_mod info_ix) info imbs =
+ assert_modules_match info_mod (modBreaks_module $ imodBreaks_modBreaks imbs) $
+ imbs{imodBreaks_breakInfo = IM.insert info_ix info (imodBreaks_breakInfo imbs)}
+
+-- | Assert that the module in the 'InternalBreakpointId' and in
+-- 'InternalModBreaks' match.
+assert_modules_match :: Module -> Module -> a -> a
+assert_modules_match ibi_mod imbs_mod =
+ assertPpr (ibi_mod == imbs_mod)
+ (text "Tried to query the InternalModBreaks of module" <+> ppr imbs_mod
+ <+> text "with an InternalBreakpointId for module" <+> ppr ibi_mod)
+
+--------------------------------------------------------------------------------
+-- Tick-level Breakpoint information
+--------------------------------------------------------------------------------
+
+-- | Get the source span for this breakpoint
+getBreakLoc :: InternalBreakpointId -> InternalModBreaks -> SrcSpan
+getBreakLoc = getBreakXXX modBreaks_locs
+
+-- | Get the vars for this breakpoint
+getBreakVars :: InternalBreakpointId -> InternalModBreaks -> [OccName]
+getBreakVars = getBreakXXX modBreaks_vars
+
+-- | Get the decls for this breakpoint
+getBreakDecls :: InternalBreakpointId -> InternalModBreaks -> [String]
+getBreakDecls = getBreakXXX modBreaks_decls
+
+-- | Get the decls for this breakpoint
+getBreakCCS :: InternalBreakpointId -> InternalModBreaks -> (String, String)
+getBreakCCS = getBreakXXX modBreaks_ccs
+
+-- | Internal utility to access a ModBreaks field at a particular breakpoint index
+getBreakXXX :: (ModBreaks -> Array BreakTickIndex a) -> InternalBreakpointId -> InternalModBreaks -> a
+getBreakXXX view (InternalBreakpointId tick_mod tick_id _ _) imbs =
+ assert_modules_match tick_mod (modBreaks_module $ imodBreaks_modBreaks imbs) $ do
+ view (imodBreaks_modBreaks imbs) ! tick_id
+
+--------------------------------------------------------------------------------
+-- Instances
+--------------------------------------------------------------------------------
+
+-- | Fully force an 'InternalModBreaks' value
+seqInternalModBreaks :: InternalModBreaks -> ()
+seqInternalModBreaks InternalModBreaks{..} =
+ rnf (fmap seqCgBreakInfo imodBreaks_breakInfo)
+ where
+ seqCgBreakInfo :: CgBreakInfo -> ()
+ seqCgBreakInfo CgBreakInfo{..} =
+ rnf cgb_tyvars `seq`
+ rnf cgb_vars `seq`
+ rnf cgb_resty
+
+instance Outputable InternalBreakpointId where
+ ppr InternalBreakpointId{..} =
+ text "InternalBreakpointId" <+> ppr ibi_info_mod <+> ppr ibi_info_index
+
+instance NFData InternalBreakpointId where
+ rnf InternalBreakpointId{..} =
+ rnf ibi_info_mod `seq` rnf ibi_info_index
+
+instance Outputable CgBreakInfo where
+ ppr info = text "CgBreakInfo" <+>
+ parens (ppr (cgb_vars info) <+>
+ ppr (cgb_resty info))
=====================================
compiler/GHC/ByteCode/Instr.hs
=====================================
@@ -17,7 +17,6 @@ import GHC.ByteCode.Types
import GHC.Cmm.Type (Width)
import GHC.StgToCmm.Layout ( ArgRep(..) )
import GHC.Utils.Outputable
-import GHC.Unit.Module
import GHC.Types.Name
import GHC.Types.Literal
import GHC.Types.Unique
@@ -259,10 +258,7 @@ data BCInstr
-- Note [unboxed tuple bytecodes and tuple_BCO] in GHC.StgToByteCode
-- Breakpoints
- | BRK_FUN !Module -- breakpoint tick module
- !Word16 -- breakpoint tick index
- !Module -- breakpoint info module
- !Word16 -- breakpoint info index
+ | BRK_FUN !InternalBreakpointId
-- An internal breakpoint for triggering a break on any case alternative
-- See Note [Debugger: BRK_ALTS]
@@ -458,10 +454,10 @@ instance Outputable BCInstr where
ppr ENTER = text "ENTER"
ppr (RETURN pk) = text "RETURN " <+> ppr pk
ppr (RETURN_TUPLE) = text "RETURN_TUPLE"
- ppr (BRK_FUN _tick_mod tickx _info_mod infox)
+ ppr (BRK_FUN (InternalBreakpointId tick_mod tickx info_mod infox))
= text "BRK_FUN" <+> text "<breakarray>"
- <+> text "<tick_module>" <+> text "<tick_module_unitid>" <+> ppr tickx
- <+> text "<info_module>" <+> text "<info_module_unitid>" <+> ppr infox
+ <+> ppr tick_mod <+> ppr tickx
+ <+> ppr info_mod <+> ppr infox
<+> text "<cc>"
ppr (BRK_ALTS active) = text "BRK_ALTS" <+> ppr active
#if MIN_VERSION_rts(1,0,3)
=====================================
compiler/GHC/ByteCode/Linker.hs
=====================================
@@ -97,9 +97,9 @@ lookupLiteral interp pkgs_loaded le ptr = case ptr of
BCONPtrFFIInfo (FFIInfo {..}) -> do
RemotePtr p <- interpCmd interp $ PrepFFI ffiInfoArgs ffiInfoRet
pure $ fromIntegral p
- BCONPtrCostCentre tick_mod tick_no
- | interpreterProfiled interp ->
- case expectJust (lookupModuleEnv (ccs_env le) tick_mod) ! tick_no of
+ BCONPtrCostCentre BreakpointId{..}
+ | interpreterProfiled interp -> do
+ case expectJust (lookupModuleEnv (ccs_env le) bi_tick_mod) ! bi_tick_index of
RemotePtr p -> pure $ fromIntegral p
| otherwise ->
case toRemotePtr nullPtr of
=====================================
compiler/GHC/ByteCode/Types.hs
=====================================
@@ -18,10 +18,15 @@ module GHC.ByteCode.Types
, UnlinkedBCO(..), BCOPtr(..), BCONPtr(..)
, ItblEnv, ItblPtr(..)
, AddrEnv, AddrPtr(..)
- , CgBreakInfo(..)
- , ModBreaks (..), BreakIndex
- , CCostCentre
, FlatBag, sizeFlatBag, fromSmallArray, elemsFlatBag
+
+ -- * Mod Breaks
+ , ModBreaks (..), BreakpointId(..), BreakTickIndex
+
+ -- * Internal Mod Breaks
+ , InternalModBreaks(..), CgBreakInfo(..), seqInternalModBreaks
+ -- ** Internal breakpoint identifier
+ , InternalBreakpointId(..), BreakInfoIndex
) where
import GHC.Prelude
@@ -33,8 +38,8 @@ import GHC.Types.Name.Env
import GHC.Utils.Outputable
import GHC.Builtin.PrimOps
import GHC.Types.SptEntry
-import GHC.Types.SrcLoc
-import GHCi.BreakArray
+import GHC.HsToCore.Breakpoints
+import GHC.ByteCode.Breakpoints
import GHCi.Message
import GHCi.RemoteTypes
import GHCi.FFI
@@ -42,12 +47,9 @@ import Control.DeepSeq
import GHCi.ResolvedBCO ( BCOByteArray(..), mkBCOByteArray )
import Foreign
-import Data.Array
import Data.ByteString (ByteString)
-import Data.IntMap (IntMap)
import qualified GHC.Exts.Heap as Heap
import GHC.Cmm.Expr ( GlobalRegSet, emptyRegSet, regSetToList )
-import GHC.Iface.Syntax
import GHC.Unit.Module
-- -----------------------------------------------------------------------------
@@ -63,8 +65,12 @@ data CompiledByteCode = CompiledByteCode
, bc_strs :: [(Name, ByteString)]
-- ^ top-level strings (heap allocated)
- , bc_breaks :: Maybe ModBreaks
- -- ^ breakpoint info (Nothing if breakpoints are disabled)
+ , bc_breaks :: Maybe InternalModBreaks
+ -- ^ All breakpoint information (no information if breakpoints are disabled).
+ --
+ -- This information is used when loading a bytecode object: we will
+ -- construct the arrays to be used at runtime to trigger breakpoints at load time
+ -- from it (in 'allocateBreakArrays' and 'allocateCCS' in 'GHC.ByteCode.Loader').
, bc_spt_entries :: ![SptEntry]
-- ^ Static pointer table entries which should be loaded along with the
@@ -86,7 +92,9 @@ seqCompiledByteCode CompiledByteCode{..} =
rnf bc_bcos `seq`
rnf bc_itbls `seq`
rnf bc_strs `seq`
- rnf (fmap seqModBreaks bc_breaks)
+ case bc_breaks of
+ Nothing -> ()
+ Just ibks -> seqInternalModBreaks ibks
newtype ByteOff = ByteOff Int
deriving (Enum, Eq, Show, Integral, Num, Ord, Real, Outputable)
@@ -276,87 +284,15 @@ data BCONPtr
| BCONPtrFS !FastString
-- | A libffi ffi_cif function prototype.
| BCONPtrFFIInfo !FFIInfo
- -- | A 'CostCentre' remote pointer array's respective 'Module' and index.
- | BCONPtrCostCentre !Module !BreakIndex
+ -- | A 'CostCentre' remote pointer array's respective 'BreakpointId'
+ | BCONPtrCostCentre !BreakpointId
instance NFData BCONPtr where
rnf x = x `seq` ()
--- | Information about a breakpoint that we know at code-generation time
--- In order to be used, this needs to be hydrated relative to the current HscEnv by
--- 'hydrateCgBreakInfo'. Everything here can be fully forced and that's critical for
--- preventing space leaks (see #22530)
-data CgBreakInfo
- = CgBreakInfo
- { cgb_tyvars :: ![IfaceTvBndr] -- ^ Type variables in scope at the breakpoint
- , cgb_vars :: ![Maybe (IfaceIdBndr, Word)]
- , cgb_resty :: !IfaceType
- }
--- See Note [Syncing breakpoint info] in GHC.Runtime.Eval
-
-seqCgBreakInfo :: CgBreakInfo -> ()
-seqCgBreakInfo CgBreakInfo{..} =
- rnf cgb_tyvars `seq`
- rnf cgb_vars `seq`
- rnf cgb_resty
-
instance Outputable UnlinkedBCO where
ppr (UnlinkedBCO nm _arity _insns _bitmap lits ptrs)
= sep [text "BCO", ppr nm, text "with",
ppr (sizeFlatBag lits), text "lits",
ppr (sizeFlatBag ptrs), text "ptrs" ]
-instance Outputable CgBreakInfo where
- ppr info = text "CgBreakInfo" <+>
- parens (ppr (cgb_vars info) <+>
- ppr (cgb_resty info))
-
--- -----------------------------------------------------------------------------
--- Breakpoints
-
--- | Breakpoint index
-type BreakIndex = Int
-
--- | C CostCentre type
-data CCostCentre
-
--- | All the information about the breakpoints for a module
-data ModBreaks
- = ModBreaks
- { modBreaks_flags :: ForeignRef BreakArray
- -- ^ The array of flags, one per breakpoint,
- -- indicating which breakpoints are enabled.
- , modBreaks_locs :: !(Array BreakIndex SrcSpan)
- -- ^ An array giving the source span of each breakpoint.
- , modBreaks_vars :: !(Array BreakIndex [OccName])
- -- ^ An array giving the names of the free variables at each breakpoint.
- , modBreaks_decls :: !(Array BreakIndex [String])
- -- ^ An array giving the names of the declarations enclosing each breakpoint.
- -- See Note [Field modBreaks_decls]
- , modBreaks_ccs :: !(Array BreakIndex (String, String))
- -- ^ Array pointing to cost centre info for each breakpoint;
- -- actual 'CostCentre' allocation is done at link-time.
- , modBreaks_breakInfo :: !(IntMap CgBreakInfo)
- -- ^ info about each breakpoint from the bytecode generator
- , modBreaks_module :: !Module
- -- ^ info about the module in which we are setting the breakpoint
- }
-
-seqModBreaks :: ModBreaks -> ()
-seqModBreaks ModBreaks{..} =
- rnf modBreaks_flags `seq`
- rnf modBreaks_locs `seq`
- rnf modBreaks_vars `seq`
- rnf modBreaks_decls `seq`
- rnf modBreaks_ccs `seq`
- rnf (fmap seqCgBreakInfo modBreaks_breakInfo) `seq`
- rnf modBreaks_module
-
-{-
-Note [Field modBreaks_decls]
-~~~~~~~~~~~~~~~~~~~~~~
-A value of eg ["foo", "bar", "baz"] in a `modBreaks_decls` field means:
-The breakpoint is in the function called "baz" that is declared in a `let`
-or `where` clause of a declaration called "bar", which itself is declared
-in a `let` or `where` clause of the top-level function called "foo".
--}
=====================================
compiler/GHC/Core/Ppr.hs
=====================================
@@ -31,7 +31,6 @@ import GHC.Prelude
import GHC.Core
import GHC.Core.Stats (exprStats)
-import GHC.Types.Breakpoint
import GHC.Types.Fixity (LexicalFixity(..))
import GHC.Types.Literal( pprLiteral )
import GHC.Types.Name( pprInfixName, pprPrefixName )
=====================================
compiler/GHC/Driver/Session/Inspect.hs
=====================================
@@ -91,7 +91,7 @@ data ModuleInfo = ModuleInfo {
minf_instances :: [ClsInst],
minf_iface :: Maybe ModIface,
minf_safe :: SafeHaskellMode,
- minf_modBreaks :: Maybe ModBreaks
+ minf_modBreaks :: Maybe InternalModBreaks
}
-- We don't want HomeModInfo here, because a ModuleInfo applies
-- to package modules too.
@@ -196,6 +196,6 @@ modInfoIface = minf_iface
modInfoSafe :: ModuleInfo -> SafeHaskellMode
modInfoSafe = minf_safe
-modInfoModBreaks :: ModuleInfo -> Maybe ModBreaks
+modInfoModBreaks :: ModuleInfo -> Maybe InternalModBreaks
modInfoModBreaks = minf_modBreaks
=====================================
compiler/GHC/HsToCore.hs
=====================================
@@ -97,8 +97,8 @@ import GHC.Unit.Module.Deps
import Data.List (partition)
import Data.IORef
-import Data.Traversable (for)
import GHC.Iface.Make (mkRecompUsageInfo)
+import GHC.Runtime.Interpreter (interpreterProfiled)
{-
************************************************************************
@@ -162,13 +162,12 @@ deSugar hsc_env
mod mod_loc
export_set (typeEnvTyCons type_env) binds
else return (binds, Nothing)
- ; modBreaks <- for
- [ (i, s)
- | i <- hsc_interp hsc_env
- , (_, s) <- m_tickInfo
- , breakpointsAllowed dflags
- ]
- $ \(interp, specs) -> mkModBreaks interp mod specs
+ ; let modBreaks
+ | Just (_, specs) <- m_tickInfo
+ , breakpointsAllowed dflags
+ = Just $ mkModBreaks (interpreterProfiled $ hscInterp hsc_env) mod specs
+ | otherwise
+ = Nothing
; ds_hpc_info <- case m_tickInfo of
Just (orig_file2, ticks)
=====================================
compiler/GHC/HsToCore/Breakpoints.hs
=====================================
@@ -1,26 +1,69 @@
{-# LANGUAGE RecordWildCards #-}
+-- | Information attached to Breakpoints generated from Ticks
+--
+-- The breakpoint information stored in 'ModBreaks' is generated during
+-- desugaring from the ticks annotating the source expressions.
+--
+-- This information can be queried per-breakpoint using the 'BreakpointId'
+-- datatype, which indexes tick-level breakpoint information.
+--
+-- 'ModBreaks' and 'BreakpointId's are not to be confused with
+-- 'InternalModBreaks' and 'InternalBreakId's. The latter are constructed
+-- during bytecode generation and can be found in 'GHC.ByteCode.Breakpoints'.
+--
+-- See Note [Breakpoint identifiers]
module GHC.HsToCore.Breakpoints
- ( mkModBreaks,
- hydrateModBreaks
+ ( -- * ModBreaks
+ mkModBreaks, ModBreaks(..)
+
+ -- ** Re-exports BreakpointId
+ , BreakpointId(..), BreakTickIndex
) where
import GHC.Prelude
-
-import qualified GHC.Runtime.Interpreter as GHCi
-import GHC.Runtime.Interpreter
-import GHC.ByteCode.Types
-import GHC.Unit
+import Data.Array
import GHC.HsToCore.Ticks (Tick (..))
-
import GHC.Data.SizedSeq
-import GHC.Utils.Outputable as Outputable
-
+import GHC.Types.SrcLoc (SrcSpan)
+import GHC.Types.Name (OccName)
+import GHC.Types.Tickish (BreakTickIndex, BreakpointId(..))
+import GHC.Unit.Module (Module)
+import GHC.Utils.Outputable
import Data.List (intersperse)
-import Data.Array
-import Data.Array.Base (numElements)
-import qualified Data.IntMap as IntMap
+
+--------------------------------------------------------------------------------
+-- ModBreaks
+--------------------------------------------------------------------------------
+
+-- | All the information about the source-relevant breakpoints for a module
+--
+-- This information is constructed once during desugaring (with `mkModBreaks`)
+-- from breakpoint ticks and fixed/unchanged from there on forward. It could be
+-- exported as an abstract datatype because it should never be updated after
+-- construction, only queried.
+--
+-- The arrays can be indexed using the int in the corresponding 'BreakpointId'
+-- (i.e. the 'BreakpointId' whose 'Module' matches the 'Module' corresponding
+-- to these 'ModBreaks') with the accessors 'modBreaks_locs', 'modBreaks_vars',
+-- and 'modBreaks_decls'.
+data ModBreaks
+ = ModBreaks
+ { modBreaks_locs :: !(Array BreakTickIndex SrcSpan)
+ -- ^ An array giving the source span of each breakpoint.
+ , modBreaks_vars :: !(Array BreakTickIndex [OccName])
+ -- ^ An array giving the names of the free variables at each breakpoint.
+ , modBreaks_decls :: !(Array BreakTickIndex [String])
+ -- ^ An array giving the names of the declarations enclosing each breakpoint.
+ -- See Note [Field modBreaks_decls]
+ , modBreaks_ccs :: !(Array BreakTickIndex (String, String))
+ -- ^ Array pointing to cost centre info for each breakpoint;
+ -- actual 'CostCentre' allocation is done at link-time.
+ , modBreaks_module :: !Module
+ -- ^ The module to which this ModBreaks is associated.
+ -- We also cache this here for internal sanity checks.
+ }
-- | Initialize memory for breakpoint data that is shared between the bytecode
-- generator and the interpreter.
@@ -29,38 +72,37 @@ import qualified Data.IntMap as IntMap
-- generator needs to encode this information for each expression, the data is
-- allocated remotely in GHCi's address space and passed to the codegen as
-- foreign pointers.
-mkModBreaks :: Interp -> Module -> SizedSeq Tick -> IO ModBreaks
-mkModBreaks interp mod extendedMixEntries
- = do
- let count = fromIntegral $ sizeSS extendedMixEntries
+mkModBreaks :: Bool {-^ Whether the interpreter is profiled and thus if we should include store a CCS array -}
+ -> Module -> SizedSeq Tick -> ModBreaks
+mkModBreaks interpreterProfiled modl extendedMixEntries
+ = let count = fromIntegral $ sizeSS extendedMixEntries
entries = ssElts extendedMixEntries
- let
- locsTicks = listArray (0,count-1) [ tick_loc t | t <- entries ]
- varsTicks = listArray (0,count-1) [ tick_ids t | t <- entries ]
- declsTicks = listArray (0,count-1) [ tick_path t | t <- entries ]
- ccs
- | interpreterProfiled interp =
- listArray
- (0, count - 1)
- [ ( concat $ intersperse "." $ tick_path t,
- renderWithContext defaultSDocContext $ ppr $ tick_loc t
- )
- | t <- entries
- ]
- | otherwise = listArray (0, -1) []
- hydrateModBreaks interp $
- ModBreaks
- { modBreaks_flags = undefined,
- modBreaks_locs = locsTicks,
- modBreaks_vars = varsTicks,
- modBreaks_decls = declsTicks,
- modBreaks_ccs = ccs,
- modBreaks_breakInfo = IntMap.empty,
- modBreaks_module = mod
- }
+ locsTicks = listArray (0,count-1) [ tick_loc t | t <- entries ]
+ varsTicks = listArray (0,count-1) [ tick_ids t | t <- entries ]
+ declsTicks = listArray (0,count-1) [ tick_path t | t <- entries ]
+ ccs
+ | interpreterProfiled =
+ listArray
+ (0, count - 1)
+ [ ( concat $ intersperse "." $ tick_path t,
+ renderWithContext defaultSDocContext $ ppr $ tick_loc t
+ )
+ | t <- entries
+ ]
+ | otherwise = listArray (0, -1) []
+ in ModBreaks
+ { modBreaks_locs = locsTicks
+ , modBreaks_vars = varsTicks
+ , modBreaks_decls = declsTicks
+ , modBreaks_ccs = ccs
+ , modBreaks_module = modl
+ }
-hydrateModBreaks :: Interp -> ModBreaks -> IO ModBreaks
-hydrateModBreaks interp ModBreaks {..} = do
- let count = numElements modBreaks_locs
- modBreaks_flags <- GHCi.newBreakArray interp count
- pure ModBreaks {..}
+{-
+Note [Field modBreaks_decls]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+A value of eg ["foo", "bar", "baz"] in a `modBreaks_decls` field means:
+The breakpoint is in the function called "baz" that is declared in a `let`
+or `where` clause of a declaration called "bar", which itself is declared
+in a `let` or `where` clause of the top-level function called "foo".
+-}
=====================================
compiler/GHC/HsToCore/Ticks.hs
=====================================
@@ -34,7 +34,6 @@ import GHC.Driver.Flags (DumpFlag(..))
import GHC.Utils.Outputable as Outputable
import GHC.Utils.Panic
import GHC.Utils.Logger
-import GHC.Types.Breakpoint
import GHC.Types.SrcLoc
import GHC.Types.Basic
import GHC.Types.Id
=====================================
compiler/GHC/Iface/Syntax.hs
=====================================
@@ -56,7 +56,6 @@ import GHC.Data.BooleanFormula (pprBooleanFormula, isTrue)
import GHC.Builtin.Names ( unrestrictedFunTyConKey, liftedTypeKindTyConKey,
constraintKindTyConKey )
-import GHC.Types.Breakpoint
import GHC.Types.Unique ( hasKey )
import GHC.Iface.Type
import GHC.Iface.Recomp.Binary
@@ -75,6 +74,7 @@ import GHC.Types.Avail
import GHC.Types.ForeignCall
import GHC.Types.Annotations( AnnPayload, AnnTarget )
import GHC.Types.Basic
+import GHC.Types.Tickish
import GHC.Unit.Module
import GHC.Unit.Module.Warnings
import GHC.Types.SrcLoc
=====================================
compiler/GHC/Linker/Loader.hs
=====================================
@@ -28,6 +28,7 @@ module GHC.Linker.Loader
, extendLoadedEnv
, deleteFromLoadedEnv
-- * Internals
+ , allocateBreakArrays
, rmDupLinkables
, modifyLoaderState
, initLinkDepsOpts
@@ -122,8 +123,8 @@ import System.Win32.Info (getSystemDirectory)
import GHC.Utils.Exception
import GHC.Unit.Home.Graph (lookupHug, unitEnv_foldWithKey)
import GHC.Driver.Downsweep
-
-
+import qualified GHC.Runtime.Interpreter as GHCi
+import Data.Array.Base (numElements)
-- Note [Linkers and loaders]
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -696,16 +697,8 @@ loadDecls interp hsc_env span linkable = do
let le = linker_env pls
le2_itbl_env <- linkITbls interp (itbl_env le) (concat $ map bc_itbls cbcs)
le2_addr_env <- foldlM (\env cbc -> allocateTopStrings interp (bc_strs cbc) env) (addr_env le) cbcs
- le2_breakarray_env <-
- allocateBreakArrays
- interp
- (catMaybes $ map bc_breaks cbcs)
- (breakarray_env le)
- le2_ccs_env <-
- allocateCCS
- interp
- (catMaybes $ map bc_breaks cbcs)
- (ccs_env le)
+ le2_breakarray_env <- allocateBreakArrays interp (breakarray_env le) (catMaybes $ map bc_breaks cbcs)
+ le2_ccs_env <- allocateCCS interp (ccs_env le) (catMaybes $ map bc_breaks cbcs)
let le2 = le { itbl_env = le2_itbl_env
, addr_env = le2_addr_env
, breakarray_env = le2_breakarray_env
@@ -933,12 +926,8 @@ dynLinkBCOs interp pls bcos = do
le1 = linker_env pls
ie2 <- linkITbls interp (itbl_env le1) (concatMap bc_itbls cbcs)
ae2 <- foldlM (\env cbc -> allocateTopStrings interp (bc_strs cbc) env) (addr_env le1) cbcs
- be2 <-
- allocateBreakArrays
- interp
- (catMaybes $ map bc_breaks cbcs)
- (breakarray_env le1)
- ce2 <- allocateCCS interp (catMaybes $ map bc_breaks cbcs) (ccs_env le1)
+ be2 <- allocateBreakArrays interp (breakarray_env le1) (catMaybes $ map bc_breaks cbcs)
+ ce2 <- allocateCCS interp (ccs_env le1) (catMaybes $ map bc_breaks cbcs)
let le2 = le1 { itbl_env = ie2, addr_env = ae2, breakarray_env = be2, ccs_env = ce2 }
names_and_refs <- linkSomeBCOs interp (pkgs_loaded pls) le2 cbcs
@@ -1656,44 +1645,51 @@ allocateTopStrings interp topStrings prev_env = do
where
mk_entry nm ptr = (nm, (nm, AddrPtr ptr))
--- | Given a list of 'ModBreaks' collected from a list of
--- 'CompiledByteCode', allocate the 'BreakArray'.
+-- | Given a list of 'InternalModBreaks' collected from a list of
+-- 'CompiledByteCode', allocate the 'BreakArray' used to trigger breakpoints.
allocateBreakArrays ::
Interp ->
- [ModBreaks] ->
ModuleEnv (ForeignRef BreakArray) ->
+ [InternalModBreaks] ->
IO (ModuleEnv (ForeignRef BreakArray))
-allocateBreakArrays _interp mbs be =
+allocateBreakArrays interp =
foldlM
- ( \be0 ModBreaks {..} ->
- evaluate $ extendModuleEnv be0 modBreaks_module modBreaks_flags
+ ( \be0 InternalModBreaks{imodBreaks_modBreaks=ModBreaks {..}} -> do
+ -- If no BreakArray is assigned to this module yet, create one
+ if not $ elemModuleEnv modBreaks_module be0 then do
+ let count = numElements modBreaks_locs
+ breakArray <- GHCi.newBreakArray interp count
+ evaluate $ extendModuleEnv be0 modBreaks_module breakArray
+ else
+ return be0
)
- be
- mbs
--- | Given a list of 'ModBreaks' collected from a list of
--- 'CompiledByteCode', allocate the 'CostCentre' arrays when profiling
--- is enabled.
+-- | Given a list of 'InternalModBreaks' collected from a list
+-- of 'CompiledByteCode', allocate the 'CostCentre' arrays when profiling is
+-- enabled.
allocateCCS ::
Interp ->
- [ModBreaks] ->
- ModuleEnv (Array BreakIndex (RemotePtr CostCentre)) ->
- IO (ModuleEnv (Array BreakIndex (RemotePtr CostCentre)))
-allocateCCS interp mbs ce
+ ModuleEnv (Array BreakTickIndex (RemotePtr CostCentre)) ->
+ [InternalModBreaks] ->
+ IO (ModuleEnv (Array BreakTickIndex (RemotePtr CostCentre)))
+allocateCCS interp ce mbss
| interpreterProfiled interp =
foldlM
- ( \ce0 ModBreaks {..} -> do
+ ( \ce0 InternalModBreaks{imodBreaks_modBreaks=ModBreaks {..}} -> do
ccs <-
mkCostCentres
interp
(moduleNameString $ moduleName modBreaks_module)
(elems modBreaks_ccs)
- evaluate $
- extendModuleEnv ce0 modBreaks_module $
- listArray
- (0, length ccs - 1)
- ccs
+ if not $ elemModuleEnv modBreaks_module ce0 then do
+ evaluate $
+ extendModuleEnv ce0 modBreaks_module $
+ listArray
+ (0, length ccs - 1)
+ ccs
+ else
+ return ce0
)
ce
- mbs
+ mbss
| otherwise = pure ce
=====================================
compiler/GHC/Linker/Types.hs
=====================================
@@ -188,7 +188,7 @@ data LinkerEnv = LinkerEnv
, breakarray_env :: !(ModuleEnv (ForeignRef BreakArray))
-- ^ Each 'Module's remote pointer of 'BreakArray'.
- , ccs_env :: !(ModuleEnv (Array BreakIndex (RemotePtr CostCentre)))
+ , ccs_env :: !(ModuleEnv (Array BreakTickIndex (RemotePtr CostCentre)))
-- ^ Each 'Module's array of remote pointers of 'CostCentre'.
-- Untouched when not profiling.
}
=====================================
compiler/GHC/Runtime/Debugger/Breakpoints.hs
=====================================
@@ -16,7 +16,8 @@ import Data.Maybe
import qualified Data.List.NonEmpty as NE
import qualified Data.Semigroup as S
-import GHC.ByteCode.Types (BreakIndex, ModBreaks(..))
+import GHC.HsToCore.Breakpoints
+import GHC.ByteCode.Breakpoints
import GHC.Driver.Env
import GHC.Driver.Monad
import GHC.Driver.Session.Inspect
@@ -24,7 +25,6 @@ import GHC.Runtime.Eval
import GHC.Runtime.Eval.Utils
import GHC.Types.Name
import GHC.Types.SrcLoc
-import GHC.Types.Breakpoint
import GHC.Unit.Module
import GHC.Unit.Module.Graph
import GHC.Unit.Module.ModSummary
@@ -44,7 +44,7 @@ import qualified GHC.Data.Strict as Strict
-- - the leftmost subexpression starting on the specified line, or
-- - the rightmost subexpression enclosing the specified line
--
-findBreakByLine :: Int {-^ Line number -} -> TickArray -> Maybe (BreakIndex, RealSrcSpan)
+findBreakByLine :: Int {-^ Line number -} -> TickArray -> Maybe (BreakTickIndex, RealSrcSpan)
findBreakByLine line arr
| not (inRange (bounds arr) line) = Nothing
| otherwise =
@@ -61,7 +61,7 @@ findBreakByLine line arr
where ends_here (_,pan) = srcSpanEndLine pan == line
-- | Find a breakpoint in the 'TickArray' of a module, given a line number and a column coordinate.
-findBreakByCoord :: (Int, Int) -> TickArray -> Maybe (BreakIndex, RealSrcSpan)
+findBreakByCoord :: (Int, Int) -> TickArray -> Maybe (BreakTickIndex, RealSrcSpan)
findBreakByCoord (line, col) arr
| not (inRange (bounds arr) line) = Nothing
| otherwise =
@@ -174,7 +174,7 @@ resolveFunctionBreakpoint inp = do
-- for
-- (a) this binder only (it maybe a top-level or a nested declaration)
-- (b) that do not have an enclosing breakpoint
-findBreakForBind :: String {-^ Name of bind to break at -} -> ModBreaks -> [(BreakIndex, RealSrcSpan)]
+findBreakForBind :: String {-^ Name of bind to break at -} -> ModBreaks -> [(BreakTickIndex, RealSrcSpan)]
findBreakForBind str_name modbreaks = filter (not . enclosed) ticks
where
ticks = [ (index, span)
@@ -191,15 +191,15 @@ findBreakForBind str_name modbreaks = filter (not . enclosed) ticks
--------------------------------------------------------------------------------
-- | Maps line numbers to the breakpoint ticks existing at that line for a module.
-type TickArray = Array Int [(BreakIndex,RealSrcSpan)]
+type TickArray = Array Int [(BreakTickIndex,RealSrcSpan)]
-- | Construct the 'TickArray' for the given module.
makeModuleLineMap :: GhcMonad m => Module -> m (Maybe TickArray)
makeModuleLineMap m = do
mi <- getModuleInfo m
- return $ mkTickArray . assocs . modBreaks_locs <$> (modInfoModBreaks =<< mi)
+ return $ mkTickArray . assocs . modBreaks_locs . imodBreaks_modBreaks <$> (modInfoModBreaks =<< mi)
where
- mkTickArray :: [(BreakIndex, SrcSpan)] -> TickArray
+ mkTickArray :: [(BreakTickIndex, SrcSpan)] -> TickArray
mkTickArray ticks
= accumArray (flip (:)) [] (1, max_line)
[ (line, (nm,pan)) | (nm,RealSrcSpan pan _) <- ticks, line <- srcSpanLines pan ]
@@ -211,7 +211,7 @@ makeModuleLineMap m = do
getModBreak :: GhcMonad m => Module -> m (Maybe ModBreaks)
getModBreak m = do
mod_info <- fromMaybe (panic "getModBreak") <$> getModuleInfo m
- pure $ modInfoModBreaks mod_info
+ pure $ imodBreaks_modBreaks <$> modInfoModBreaks mod_info
--------------------------------------------------------------------------------
-- Getting current breakpoint information
=====================================
compiler/GHC/Runtime/Eval.hs
=====================================
@@ -64,6 +64,7 @@ import GHCi.RemoteTypes
import GHC.ByteCode.Types
import GHC.Linker.Loader as Loader
+import GHC.Linker.Types (LinkerEnv(..))
import GHC.Hs
@@ -111,7 +112,6 @@ import GHC.Types.Unique
import GHC.Types.Unique.Supply
import GHC.Types.Unique.DSet
import GHC.Types.TyThing
-import GHC.Types.Breakpoint
import GHC.Types.Unique.Map
import GHC.Types.Avail
@@ -127,16 +127,16 @@ import GHC.Tc.Utils.Instantiate (instDFunType)
import GHC.Tc.Utils.Monad
import GHC.IfaceToCore
+import GHC.ByteCode.Breakpoints
import Control.Monad
-import Data.Array
import Data.Dynamic
import Data.IntMap (IntMap)
-import qualified Data.IntMap as IntMap
import Data.List (find,intercalate)
import Data.List.NonEmpty (NonEmpty)
import Unsafe.Coerce ( unsafeCoerce )
import qualified GHC.Unit.Home.Graph as HUG
+import GHCi.BreakArray (BreakArray)
-- -----------------------------------------------------------------------------
-- running a statement interactively
@@ -154,7 +154,7 @@ getHistorySpan :: HUG.HomeUnitGraph -> History -> IO SrcSpan
getHistorySpan hug hist = do
let ibi = historyBreakpointId hist
brks <- readModBreaks hug (ibi_tick_mod ibi)
- return $ modBreaks_locs brks ! ibi_tick_index ibi
+ return $ getBreakLoc ibi brks
{- | Finds the enclosing top level function name -}
-- ToDo: a better way to do this would be to keep hold of the decl_path computed
@@ -163,7 +163,7 @@ getHistorySpan hug hist = do
findEnclosingDecls :: HUG.HomeUnitGraph -> InternalBreakpointId -> IO [String]
findEnclosingDecls hug ibi = do
brks <- readModBreaks hug (ibi_tick_mod ibi)
- return $ modBreaks_decls brks ! ibi_tick_index ibi
+ return $ getBreakDecls ibi brks
-- | Update fixity environment in the current interactive context.
updateFixityEnv :: GhcMonad m => FixityEnv -> m ()
@@ -350,13 +350,14 @@ handleRunStatus step expr bindings final_ids status history0 = do
EvalBreak apStack_ref (Just eval_break) resume_ctxt ccs -> do
let ibi = evalBreakpointToId eval_break
let hug = hsc_HUG hsc_env
- tick_brks <- liftIO $ readModBreaks hug (ibi_tick_mod ibi)
+ tick_brks <- liftIO $ readModBreaks hug (ibi_tick_mod ibi)
+ breakArray <- getBreakArray interp (toBreakpointId ibi) tick_brks
let
- span = modBreaks_locs tick_brks ! ibi_tick_index ibi
- decl = intercalate "." $ modBreaks_decls tick_brks ! ibi_tick_index ibi
+ span = getBreakLoc ibi tick_brks
+ decl = intercalate "." $ getBreakDecls ibi tick_brks
-- Was this breakpoint explicitly enabled (ie. in @BreakArray@)?
- bactive <- liftIO $ breakpointStatus interp (modBreaks_flags tick_brks) (ibi_tick_index ibi)
+ bactive <- liftIO $ breakpointStatus interp breakArray (ibi_tick_index ibi)
apStack_fhv <- liftIO $ mkFinalizedHValue interp apStack_ref
resume_ctxt_fhv <- liftIO $ mkFinalizedHValue interp resume_ctxt
@@ -464,9 +465,24 @@ setupBreakpoint :: GhcMonad m => Interp -> BreakpointId -> Int -> m () -- #191
setupBreakpoint interp bi cnt = do
hug <- hsc_HUG <$> getSession
modBreaks <- liftIO $ readModBreaks hug (bi_tick_mod bi)
- let breakarray = modBreaks_flags modBreaks
- _ <- liftIO $ GHCi.storeBreakpoint interp breakarray (bi_tick_index bi) cnt
- pure ()
+ breakArray <- getBreakArray interp bi modBreaks
+ liftIO $ GHCi.storeBreakpoint interp breakArray (bi_tick_index bi) cnt
+
+getBreakArray :: GhcMonad m => Interp -> BreakpointId -> InternalModBreaks -> m (ForeignRef BreakArray)
+getBreakArray interp BreakpointId{bi_tick_mod} imbs = do
+
+ liftIO $ modifyLoaderState interp $ \ld_st -> do
+ let le = linker_env ld_st
+
+ -- Recall that BreakArrays are allocated only at BCO link time, so if we
+ -- haven't linked the BCOs we intend to break at yet, we allocate the arrays here.
+ ba_env <- allocateBreakArrays interp (breakarray_env le) [imbs]
+
+ return
+ ( ld_st { linker_env = le{breakarray_env = ba_env} }
+ , expectJust {- just computed -} $
+ lookupModuleEnv ba_env bi_tick_mod
+ )
back :: GhcMonad m => Int -> m ([Name], Int, SrcSpan)
back n = moveHist (+n)
@@ -496,7 +512,7 @@ moveHist fn = do
Nothing -> return $ mkGeneralSrcSpan (fsLit "<unknown>")
Just ibi -> liftIO $ do
brks <- readModBreaks (hsc_HUG hsc_env) (ibi_tick_mod ibi)
- return $ modBreaks_locs brks ! ibi_tick_index ibi
+ return $ getBreakLoc ibi brks
(hsc_env1, names) <-
liftIO $ bindLocalsAtBreakpoint hsc_env apStack span mb_info
let ic = hsc_IC hsc_env1
@@ -559,9 +575,9 @@ bindLocalsAtBreakpoint hsc_env apStack_fhv span (Just ibi) = do
let hug = hsc_HUG hsc_env
info_brks <- readModBreaks hug (ibi_info_mod ibi)
tick_brks <- readModBreaks hug (ibi_tick_mod ibi)
- let info = expectJust $ IntMap.lookup (ibi_info_index ibi) (modBreaks_breakInfo info_brks)
+ let info = getInternalBreak ibi (info_brks)
interp = hscInterp hsc_env
- occs = modBreaks_vars tick_brks ! ibi_tick_index ibi
+ occs = getBreakVars ibi tick_brks
-- Rehydrate to understand the breakpoint info relative to the current environment.
-- This design is critical to preventing leaks (#22530)
=====================================
compiler/GHC/Runtime/Eval/Types.hs
=====================================
@@ -17,11 +17,11 @@ import GHC.Prelude
import GHCi.RemoteTypes
import GHCi.Message (EvalExpr, ResumeContext)
+import GHC.ByteCode.Types (InternalBreakpointId(..))
import GHC.Driver.Config (EvalStep(..))
import GHC.Types.Id
import GHC.Types.Name
import GHC.Types.TyThing
-import GHC.Types.Breakpoint
import GHC.Types.Name.Reader
import GHC.Types.SrcLoc
import GHC.Utils.Exception
@@ -176,7 +176,7 @@ data Resume = Resume
, resumeApStack :: ForeignHValue -- The object from which we can get
-- value of the free variables.
, resumeBreakpointId :: Maybe InternalBreakpointId
- -- ^ the breakpoint we stopped at
+ -- ^ the internal breakpoint we stopped at
-- (Nothing <=> exception)
, resumeSpan :: SrcSpan -- just a copy of the SrcSpan
-- from the ModBreaks,
=====================================
compiler/GHC/Runtime/Interpreter.hs
=====================================
@@ -74,9 +74,9 @@ import GHCi.Message
import GHCi.RemoteTypes
import GHCi.ResolvedBCO
import GHCi.BreakArray (BreakArray)
-import GHC.Types.Breakpoint
-import GHC.ByteCode.Types
+import GHC.ByteCode.Breakpoints
+import GHC.ByteCode.Types
import GHC.Linker.Types
import GHC.Data.Maybe
@@ -105,7 +105,6 @@ import Control.Monad.IO.Class
import Control.Monad.Catch as MC (mask)
import Data.Binary
import Data.ByteString (ByteString)
-import Data.Array ((!))
import Foreign hiding (void)
import qualified GHC.Exts.Heap as Heap
import GHC.Stack.CCS (CostCentre,CostCentreStack)
@@ -451,7 +450,7 @@ handleSeqHValueStatus interp unit_env eval_status =
-- Nothing case - should not occur! We should have the appropriate
-- breakpoint information
Nothing -> nothing_case
- Just modbreaks -> put $ brackets . ppr $ (modBreaks_locs modbreaks) ! ibi_tick_index bi
+ Just modbreaks -> put $ brackets . ppr $ getBreakLoc bi modbreaks
-- resume the seq (:force) processing in the iserv process
withForeignRef resume_ctxt_fhv $ \hval -> do
@@ -737,7 +736,7 @@ wormholeRef interp _r = case interpInstance interp of
-- | Get the breakpoint information from the ByteCode object associated to this
-- 'HomeModInfo'.
-getModBreaks :: HomeModInfo -> Maybe ModBreaks
+getModBreaks :: HomeModInfo -> Maybe InternalModBreaks
getModBreaks hmi
| Just linkable <- homeModInfoByteCode hmi,
-- The linkable may have 'DotO's as well; only consider BCOs. See #20570.
@@ -748,7 +747,7 @@ getModBreaks hmi
-- | Read the 'InternalModBreaks' and 'ModBreaks' of the given home 'Module'
-- from the 'HomeUnitGraph'.
-readModBreaks :: HomeUnitGraph -> Module -> IO ModBreaks
+readModBreaks :: HomeUnitGraph -> Module -> IO InternalModBreaks
readModBreaks hug modl = expectJust . getModBreaks . expectJust <$> HUG.lookupHugByModule modl hug
-- -----------------------------------------------------------------------------
=====================================
compiler/GHC/StgToByteCode.hs
=====================================
@@ -34,7 +34,6 @@ import GHC.Platform.Profile
import GHC.Runtime.Interpreter
import GHCi.FFI
import GHC.Types.Basic
-import GHC.Types.Breakpoint
import GHC.Utils.Outputable
import GHC.Types.Name
import GHC.Types.Id
@@ -71,6 +70,7 @@ import GHC.Data.OrdList
import GHC.Data.Maybe
import GHC.Types.Tickish
import GHC.Types.SptEntry
+import GHC.ByteCode.Breakpoints
import Data.List ( genericReplicate, intersperse
, partition, scanl', sortBy, zip4, zip6 )
@@ -134,9 +134,9 @@ byteCodeGen hsc_env this_mod binds tycs mb_modBreaks spt_entries
"Proto-BCOs" FormatByteCode
(vcat (intersperse (char ' ') (map ppr $ elemsFlatBag proto_bcos)))
- let mod_breaks = case modBreaks of
+ let mod_breaks = case mb_modBreaks of
Nothing -> Nothing
- Just mb -> Just mb{ modBreaks_breakInfo = breakInfo }
+ Just mb -> Just $ mkInternalModBreaks this_mod breakInfo mb
cbc <- assembleBCOs profile proto_bcos tycs strings mod_breaks spt_entries
-- Squash space leaks in the CompiledByteCode. This is really
@@ -405,7 +405,7 @@ schemeER_wrk d p (StgTick (Breakpoint tick_ty (BreakpointId tick_mod tick_no) fv
Nothing -> pure code
Just current_mod_breaks -> break_info hsc_env tick_mod current_mod mb_current_mod_breaks >>= \case
Nothing -> pure code
- Just ModBreaks {modBreaks_module = tick_mod} -> do
+ Just ModBreaks{modBreaks_module = tick_mod} -> do
platform <- profilePlatform <$> getProfile
let idOffSets = getVarOffSets platform d p fvs
ty_vars = tyCoVarsOfTypesWellScoped (tick_ty:map idType fvs)
@@ -416,12 +416,7 @@ schemeER_wrk d p (StgTick (Breakpoint tick_ty (BreakpointId tick_mod tick_no) fv
let info_mod = modBreaks_module current_mod_breaks
infox <- newBreakInfo breakInfo
- let -- cast that checks that round-tripping through Word16 doesn't change the value
- toW16 x = let r = fromIntegral x :: Word16
- in if fromIntegral r == x
- then r
- else pprPanic "schemeER_wrk: breakpoint tick/info index too large!" (ppr x)
- breakInstr = BRK_FUN tick_mod (toW16 tick_no) info_mod (toW16 infox)
+ let breakInstr = BRK_FUN (InternalBreakpointId tick_mod tick_no info_mod infox)
return $ breakInstr `consOL` code
schemeER_wrk d p rhs = schemeE d 0 p rhs
@@ -455,7 +450,7 @@ break_info hsc_env mod current_mod current_mod_breaks
= pure current_mod_breaks
| otherwise
= liftIO (HUG.lookupHugByModule mod (hsc_HUG hsc_env)) >>= \case
- Just hp -> pure $ getModBreaks hp
+ Just hp -> pure $ imodBreaks_modBreaks <$> getModBreaks hp
Nothing -> pure Nothing
getVarOffSets :: Platform -> StackDepth -> BCEnv -> [Id] -> [Maybe (Id, WordOff)]
@@ -2659,20 +2654,19 @@ typeArgReps platform = map (toArgRep platform) . typePrimRep
-- | Read only environment for generating ByteCode
data BcM_Env
= BcM_Env
- { bcm_hsc_env :: HscEnv
- , bcm_module :: Module -- current module (for breakpoints)
+ { bcm_hsc_env :: !HscEnv
+ , bcm_module :: !Module -- current module (for breakpoints)
+ , modBreaks :: !(Maybe ModBreaks)
}
data BcM_State
= BcM_State
{ nextlabel :: !Word32 -- ^ For generating local labels
, breakInfoIdx :: !Int -- ^ Next index for breakInfo array
- , modBreaks :: Maybe ModBreaks -- info about breakpoints
-
- , breakInfo :: IntMap CgBreakInfo -- ^ Info at breakpoint occurrence.
- -- Indexed with breakpoint *info* index.
- -- See Note [Breakpoint identifiers]
- -- in GHC.Types.Breakpoint
+ , breakInfo :: !(IntMap CgBreakInfo)
+ -- ^ Info at breakpoints occurrences. Indexed with
+ -- 'InternalBreakpointId'. See Note [Breakpoint identifiers] in
+ -- GHC.ByteCode.Breakpoints.
}
newtype BcM r = BcM (BcM_Env -> BcM_State -> IO (r, BcM_State))
@@ -2681,7 +2675,7 @@ newtype BcM r = BcM (BcM_Env -> BcM_State -> IO (r, BcM_State))
runBc :: HscEnv -> Module -> Maybe ModBreaks -> BcM r -> IO (r, BcM_State)
runBc hsc_env this_mod mbs (BcM m)
- = m (BcM_Env hsc_env this_mod) (BcM_State 0 0 mbs IntMap.empty)
+ = m (BcM_Env hsc_env this_mod mbs) (BcM_State 0 0 IntMap.empty)
instance HasDynFlags BcM where
getDynFlags = hsc_dflags <$> getHscEnv
@@ -2724,7 +2718,7 @@ getCurrentModule :: BcM Module
getCurrentModule = BcM $ \env st -> return (bcm_module env, st)
getCurrentModBreaks :: BcM (Maybe ModBreaks)
-getCurrentModBreaks = BcM $ \_env st -> return (modBreaks st, st)
+getCurrentModBreaks = BcM $ \env st -> return (modBreaks env, st)
tickFS :: FastString
tickFS = fsLit "ticked"
=====================================
compiler/GHC/Types/Breakpoint.hs deleted
=====================================
@@ -1,66 +0,0 @@
--- | Breakpoint related types
-module GHC.Types.Breakpoint
- ( BreakpointId (..)
- , InternalBreakpointId (..)
- , toBreakpointId
- )
-where
-
-import GHC.Prelude
-import GHC.Unit.Module
-import GHC.Utils.Outputable
-import Control.DeepSeq
-import Data.Data (Data)
-
--- | Breakpoint identifier.
---
--- See Note [Breakpoint identifiers]
-data BreakpointId = BreakpointId
- { bi_tick_mod :: !Module -- ^ Breakpoint tick module
- , bi_tick_index :: !Int -- ^ Breakpoint tick index
- }
- deriving (Eq, Ord, Data)
-
--- | Internal breakpoint identifier
---
--- See Note [Breakpoint identifiers]
-data InternalBreakpointId = InternalBreakpointId
- { ibi_tick_mod :: !Module -- ^ Breakpoint tick module
- , ibi_tick_index :: !Int -- ^ Breakpoint tick index
- , ibi_info_mod :: !Module -- ^ Breakpoint info module
- , ibi_info_index :: !Int -- ^ Breakpoint info index
- }
- deriving (Eq, Ord)
-
-toBreakpointId :: InternalBreakpointId -> BreakpointId
-toBreakpointId ibi = BreakpointId
- { bi_tick_mod = ibi_tick_mod ibi
- , bi_tick_index = ibi_tick_index ibi
- }
-
-
--- Note [Breakpoint identifiers]
--- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
---
--- Before optimization a breakpoint is identified uniquely with a tick module
--- and a tick index. See BreakpointId. A tick module contains an array, indexed
--- with the tick indexes, which indicates breakpoint status.
---
--- When we generate ByteCode, we collect information for every breakpoint at
--- their *occurrence sites* (see CgBreakInfo in GHC.ByteCode.Types) and these info
--- are stored in the ModIface of the occurrence module. Because of inlining, we
--- can't reuse the tick index to uniquely identify an occurrence; because of
--- cross-module inlining, we can't assume that the occurrence module is the same
--- as the tick module (#24712).
---
--- So every breakpoint occurrence gets assigned a module-unique *info index* and
--- we store it alongside the occurrence module (*info module*) in the
--- InternalBreakpointId datatype.
-
-instance Outputable BreakpointId where
- ppr BreakpointId{bi_tick_mod, bi_tick_index} =
- text "BreakpointId" <+> ppr bi_tick_mod <+> ppr bi_tick_index
-
-instance NFData BreakpointId where
- rnf BreakpointId{bi_tick_mod, bi_tick_index} =
- rnf bi_tick_mod `seq` rnf bi_tick_index
=====================================
compiler/GHC/Types/Tickish.hs
=====================================
@@ -21,17 +21,20 @@ module GHC.Types.Tickish (
isProfTick,
TickishPlacement(..),
tickishPlace,
- tickishContains
+ tickishContains,
+
+ -- * Breakpoint tick identifiers
+ BreakpointId(..), BreakTickIndex
) where
import GHC.Prelude
import GHC.Data.FastString
+import Control.DeepSeq
import GHC.Core.Type
import GHC.Unit.Module
-import GHC.Types.Breakpoint
import GHC.Types.CostCentre
import GHC.Types.SrcLoc ( RealSrcSpan, containsSpan )
import GHC.Types.Var
@@ -41,7 +44,7 @@ import GHC.Utils.Panic
import Language.Haskell.Syntax.Extension ( NoExtField )
import Data.Data
-import GHC.Utils.Outputable (Outputable (ppr), text)
+import GHC.Utils.Outputable (Outputable (ppr), text, (<+>))
{- *********************************************************************
* *
@@ -171,6 +174,35 @@ deriving instance Eq (GenTickish 'TickishPassCmm)
deriving instance Ord (GenTickish 'TickishPassCmm)
deriving instance Data (GenTickish 'TickishPassCmm)
+--------------------------------------------------------------------------------
+-- Tick breakpoint index
+--------------------------------------------------------------------------------
+
+-- | Breakpoint tick index
+-- newtype BreakTickIndex = BreakTickIndex Int
+-- deriving (Eq, Ord, Data, Ix, NFData, Outputable)
+type BreakTickIndex = Int
+
+-- | Breakpoint identifier.
+--
+-- Indexes into the structures in the @'ModBreaks'@ created during desugaring
+-- (after inserting the breakpoint ticks in the expressions).
+-- See Note [Breakpoint identifiers]
+data BreakpointId = BreakpointId
+ { bi_tick_mod :: !Module -- ^ Breakpoint tick module
+ , bi_tick_index :: !BreakTickIndex -- ^ Breakpoint tick index
+ }
+ deriving (Eq, Ord, Data)
+
+instance Outputable BreakpointId where
+ ppr BreakpointId{bi_tick_mod, bi_tick_index} =
+ text "BreakpointId" <+> ppr bi_tick_mod <+> ppr bi_tick_index
+
+instance NFData BreakpointId where
+ rnf BreakpointId{bi_tick_mod, bi_tick_index} =
+ rnf bi_tick_mod `seq` rnf bi_tick_index
+
+--------------------------------------------------------------------------------
-- | A "counting tick" (where tickishCounts is True) is one that
-- counts evaluations in some way. We cannot discard a counting tick,
=====================================
compiler/GHC/Unit/Module/ModGuts.hs
=====================================
@@ -7,7 +7,7 @@ where
import GHC.Prelude
-import GHC.ByteCode.Types
+import GHC.HsToCore.Breakpoints
import GHC.ForeignSrcLang
import GHC.Hs
=====================================
compiler/ghc.cabal.in
=====================================
@@ -223,6 +223,7 @@ Library
GHC.Builtin.Uniques
GHC.Builtin.Utils
GHC.ByteCode.Asm
+ GHC.ByteCode.Breakpoints
GHC.ByteCode.InfoTable
GHC.ByteCode.Instr
GHC.ByteCode.Linker
@@ -892,7 +893,6 @@ Library
GHC.Types.Annotations
GHC.Types.Avail
GHC.Types.Basic
- GHC.Types.Breakpoint
GHC.Types.CompleteMatch
GHC.Types.CostCentre
GHC.Types.CostCentre.State
=====================================
ghc/GHCi/UI.hs
=====================================
@@ -45,6 +45,7 @@ import GHC.Runtime.Eval (mkTopLevEnv)
import GHC.Runtime.Eval.Utils
-- The GHC interface
+import GHC.ByteCode.Breakpoints (imodBreaks_modBreaks)
import GHC.Runtime.Interpreter
import GHCi.RemoteTypes
import GHCi.BreakArray( breakOn, breakOff )
@@ -66,7 +67,8 @@ import qualified GHC
import GHC ( LoadHowMuch(..), Target(..), TargetId(..),
Resume, SingleStep, Ghc,
GetDocsFailure(..), pushLogHookM,
- getModuleGraph, handleSourceError )
+ getModuleGraph, handleSourceError,
+ InternalBreakpointId(..) )
import GHC.Driver.Main (hscParseModuleWithLocation, hscParseStmtWithLocation)
import GHC.Hs.ImpExp
import GHC.Hs
@@ -78,7 +80,6 @@ import GHC.Core.TyCo.Ppr
import GHC.Types.SafeHaskell ( getSafeMode )
import GHC.Types.SourceError ( SourceError )
import GHC.Types.Name
-import GHC.Types.Breakpoint
import GHC.Types.Var ( varType )
import GHC.Iface.Syntax ( showToHeader )
import GHC.Builtin.Names
@@ -4473,7 +4474,7 @@ breakById inp = do
Left sdoc -> printForUser sdoc
Right (mod, mod_info, fun_str) -> do
let modBreaks = expectJust (GHC.modInfoModBreaks mod_info)
- findBreakAndSet mod $ \_ -> findBreakForBind fun_str modBreaks
+ findBreakAndSet mod $ \_ -> findBreakForBind fun_str (imodBreaks_modBreaks modBreaks)
breakSyntax :: a
breakSyntax = throwGhcException $ CmdLineError ("Syntax: :break [<mod>.]<func>[.<func>]\n"
=====================================
testsuite/tests/count-deps/CountDepsAst.stdout
=====================================
@@ -5,6 +5,7 @@ GHC.Builtin.Types
GHC.Builtin.Types.Literals
GHC.Builtin.Types.Prim
GHC.Builtin.Uniques
+GHC.ByteCode.Breakpoints
GHC.ByteCode.Types
GHC.Cmm.BlockId
GHC.Cmm.CLabel
@@ -110,6 +111,8 @@ GHC.Hs.Pat
GHC.Hs.Specificity
GHC.Hs.Type
GHC.Hs.Utils
+GHC.HsToCore.Breakpoints
+GHC.HsToCore.Ticks
GHC.Iface.Errors.Types
GHC.Iface.Ext.Fields
GHC.Iface.Flags
@@ -150,7 +153,6 @@ GHC.Tc.Zonk.Monad
GHC.Types.Annotations
GHC.Types.Avail
GHC.Types.Basic
-GHC.Types.Breakpoint
GHC.Types.CostCentre
GHC.Types.CostCentre.State
GHC.Types.Cpr
=====================================
testsuite/tests/count-deps/CountDepsParser.stdout
=====================================
@@ -5,6 +5,7 @@ GHC.Builtin.Types
GHC.Builtin.Types.Literals
GHC.Builtin.Types.Prim
GHC.Builtin.Uniques
+GHC.ByteCode.Breakpoints
GHC.ByteCode.Types
GHC.Cmm.BlockId
GHC.Cmm.CLabel
@@ -114,8 +115,10 @@ GHC.Hs.Pat
GHC.Hs.Specificity
GHC.Hs.Type
GHC.Hs.Utils
+GHC.HsToCore.Breakpoints
GHC.HsToCore.Errors.Types
GHC.HsToCore.Pmc.Solver.Types
+GHC.HsToCore.Ticks
GHC.Iface.Errors.Types
GHC.Iface.Ext.Fields
GHC.Iface.Flags
@@ -171,7 +174,6 @@ GHC.Tc.Zonk.Monad
GHC.Types.Annotations
GHC.Types.Avail
GHC.Types.Basic
-GHC.Types.Breakpoint
GHC.Types.CompleteMatch
GHC.Types.CostCentre
GHC.Types.CostCentre.State
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/5d52d4c315944254bc09cd1922262d…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/5d52d4c315944254bc09cd1922262d…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][wip/supersven/riscv-vectors] 2 commits: Fix CheckVectorSupport
by Sven Tennie (@supersven) 02 Jul '25
by Sven Tennie (@supersven) 02 Jul '25
02 Jul '25
Sven Tennie pushed to branch wip/supersven/riscv-vectors at Glasgow Haskell Compiler / GHC
Commits:
2306dd0a by Sven Tennie at 2025-07-02T18:06:29+02:00
Fix CheckVectorSupport
- - - - -
80263d35 by Sven Tennie at 2025-07-02T18:10:13+02:00
Always configure -march=rv64gcv
- - - - -
5 changed files:
- configure.ac
- libraries/unix
- + m4/fp_riscv_march.m4
- rts/CheckVectorSupport.c
- utils/ghc-toolchain/src/GHC/Toolchain/Tools/Cc.hs
Changes:
=====================================
configure.ac
=====================================
@@ -450,6 +450,8 @@ FP_SET_CFLAGS_C99([CC_STAGE0],[CONF_CC_OPTS_STAGE0],[CONF_CPP_OPTS_STAGE0])
FP_SET_CFLAGS_C99([CC],[CONF_CC_OPTS_STAGE1],[CONF_CPP_OPTS_STAGE1])
FP_SET_CFLAGS_C99([CC],[CONF_CC_OPTS_STAGE2],[CONF_CPP_OPTS_STAGE2])
+FP_RISCV_MARCH([CONF_CC_OPTS_STAGE2])
+
dnl ** Do we have a compatible emsdk version?
dnl --------------------------------------------------------------
EMSDK_VERSION("3.1.20", "", "")
=====================================
libraries/unix
=====================================
@@ -1 +1 @@
-Subproject commit 74ae1c0d9dd1518434f7d6cd3e63d7769599e0f9
+Subproject commit 47d5fc4a8f19207819030725e7de23c65fa61a04
=====================================
m4/fp_riscv_march.m4
=====================================
@@ -0,0 +1,34 @@
+dnl --------------------------------------------------------------------------
+dnl Set RISC-V architecture with vector extension (RVV)
+dnl
+dnl This macro checks if the target is RISC-V and if so, sets -march=rv64gcv /
+dnl -march=rv32gcv (general, compressed, vector) to enable vector extension
+dnl --------------------------------------------------------------------------
+
+# FP_RISCV_MARCH(compiler_flags_var)
+# ------------------------------------------
+#
+# Example usage:
+# FP_RISCV_MARCH([CONF_CC_OPTS_STAGE2])
+#
+AC_DEFUN([FP_RISCV_MARCH],
+[
+ AC_REQUIRE([AC_CANONICAL_TARGET])
+
+ # Check if target is RISC-V
+ case "$target" in
+ riscv64*-*-*)
+ AC_MSG_NOTICE([add -march=rv64gcv to $1])
+
+ # Add vector extension flag to the specified variable
+ $1="$$1 -march=rv64gcv"
+ ;;
+
+ riscv32*-*-*)
+ AC_MSG_NOTICE([add -march=rv64gcv to $1])
+
+ # Add vector extension flag to the specified variable
+ $1="$$1 -march=rv32gcv"
+ ;;
+ esac
+])
=====================================
rts/CheckVectorSupport.c
=====================================
@@ -14,7 +14,7 @@ static void sigill_handler(int);
static void sigill_handler(__attribute__((unused)) int sig) {
// If we get here, the vector instruction caused an illegal instruction
// exception. We just swallow it.
- longjmp(jmpbuf, 1);
+ siglongjmp(jmpbuf, 1);
}
#endif
@@ -98,9 +98,9 @@ int checkVectorSupport(void) {
sigaction(SIGILL, &sa, &old_sa);
unsigned vlenb = 0;
- if (setjmp(jmpbuf) == 0) {
+ if (sigsetjmp(jmpbuf, 1) == 0) {
// Try to execute a vector instruction
- vlenb = __riscv_vlenb();
+ asm volatile("csrr %0, vlenb" : "=r" (vlenb) :: "memory");
}
// Restore original signal handler
sigaction(SIGILL, &old_sa, NULL);
=====================================
utils/ghc-toolchain/src/GHC/Toolchain/Tools/Cc.hs
=====================================
@@ -176,6 +176,8 @@ addPlatformDepCcFlags archOs cc0 = do
-- On LoongArch64, we need `-mcmodel=medium` to tell gcc to generate big
-- enough jump instruction.
return $ cc1 & _ccFlags %++ "-mcmodel=medium"
+ ArchOS ArchRISCV64 _ ->
+ return $ cc1 & _ccFlags %++ "-march=rv64gcv"
_ ->
return cc1
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/bc674b5425666a0706b31f779061e3…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/bc674b5425666a0706b31f779061e3…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][wip/26135] 31 commits: MachRegs.h: Don't define NO_ARG_REGS when a XMM register is defined
by Andreas Klebinger (@AndreasK) 02 Jul '25
by Andreas Klebinger (@AndreasK) 02 Jul '25
02 Jul '25
Andreas Klebinger pushed to branch wip/26135 at Glasgow Haskell Compiler / GHC
Commits:
e64b3f16 by ARATA Mizuki at 2025-06-17T10:13:42+09:00
MachRegs.h: Don't define NO_ARG_REGS when a XMM register is defined
On i386, MAX_REAL_VANILLA_REG is 1, but MAX_REAL_XMM_REG is 4.
If we define NO_ARG_REGS on i386, programs that use SIMD vectors may segfault.
Closes #25985
A couple of notes on the BROKEN_TESTS field:
* This fixes the segfault from T25062_V16.
* The failure from T22187_run was fixed in an earlier commit (see #25561),
but BROKEN_TESTS was missed at that time. Now should be a good time to
mark it fixed.
- - - - -
3e7c6b4d by Matthew Pickering at 2025-06-18T15:34:04-04:00
Improve error messages when implicit lifting fails
This patch concerns programs which automatically try to fix level errors
by inserting `Lift`. For example:
```
foo x = [| x |]
~>
foo x = [| $(lift x) |]
```
Before, there were two problems with the message.
1. (#26031), the location of the error was reported as the whole
quotation.
2. (#26035), the message just mentions there is no Lift instance, but
gives no indicate why the user program needed a Lift instance in the
first place.
This problem is especially bad when you disable
`ImplicitStagePersistence`, so you just end up with a confusing "No
instance for" message rather than an error message about levels
This patch fixes both these issues.
Firstly, `PendingRnSplice` differentiates between a user-written splice
and an implicit lift. Then, the Lift instance is precisely requested
with a specific origin in the typechecker. If the instance fails to be
solved, the message is reported using the `TcRnBadlyLevelled`
constructor (like a normal level error).
Fixes #26031, #26035
- - - - -
44b8cee2 by Cheng Shao at 2025-06-18T15:34:46-04:00
testsuite: add T26120 marked as broken
- - - - -
894a04f3 by Cheng Shao at 2025-06-18T15:34:46-04:00
compiler: fix GHC.SysTools.Ar archive member size writing logic
This patch fixes a long-standing bug in `GHC.SysTools.Ar` that emits
the wrong archive member size in each archive header. It should encode
the exact length of the member payload, excluding any padding byte,
otherwise malformed archive that extracts a broken object with an
extra trailing byte could be created.
Apart from the in-tree `T26120` test, I've also created an out-of-tree
testsuite at https://github.com/TerrorJack/ghc-ar-quickcheck that
contains QuickCheck roundtrip tests for `GHC.SysTools.Ar`. With this
fix, simple roundtrip tests and `writeGNUAr`/GNU `ar` roundtrip test
passes. There might be more bugs lurking in here, but this patch is
still a critical bugfix already.
Fixes #26120 #22586.
Co-authored-by: Codex <codex(a)openai.com>
- - - - -
f677ab5f by Lauren Yim at 2025-06-18T15:35:37-04:00
fix some typos in the warnings page in the user guide
- - - - -
b968e1c1 by Rodrigo Mesquita at 2025-06-18T15:36:18-04:00
Add a frozen callstack to throwGhcException
Fixes #25956
- - - - -
a5e0c3a3 by fendor at 2025-06-18T15:36:59-04:00
Update using.rst to advertise full mhu support for GHCi
- - - - -
d3e60e97 by Ryan Scott at 2025-06-18T22:29:21-04:00
Deprecate -Wdata-kinds-tc, make DataKinds issues in typechecker become errors
!11314 introduced the `-Wdata-kinds-tc` warning as part of a fix for #22141.
This was a temporary stopgap measure to allow users who were accidentally
relying on code which needed the `DataKinds` extension in order to typecheck
without having to explicitly enable the extension.
Now that some amount of time has passed, this patch deprecates
`-Wdata-kinds-tc` and upgrades any `DataKinds`-related issues in the
typechecker (which were previously warnings) into errors.
- - - - -
fd5b5177 by Ryan Hendrickson at 2025-06-18T22:30:06-04:00
haddock: Add redact-type-synonyms pragma
`{-# OPTIONS_HADDOCK redact-type-synonyms #-}` pragma will hide the RHS
of type synonyms, and display the result kind instead, if the RHS
contains any unexported types.
- - - - -
fbc0b92a by Vladislav Zavialov at 2025-06-22T04:25:16+03:00
Visible forall in GADTs (#25127)
Add support for visible dependent quantification `forall a -> t` in
types of data constructors, e.g.
data KindVal a where
K :: forall k.
forall (a::k) -> -- now allowed!
k ->
KindVal a
For details, see docs/users_guide/exts/required_type_arguments.rst,
which has gained a new subsection.
DataCon in compiler/GHC/Core/DataCon.hs
---------------------------------------
The main change in this patch is that DataCon, the Core representation
of a data constructor, now uses a different type to store user-written
type variable binders:
- dcUserTyVarBinders :: [InvisTVBinder]
+ dcUserTyVarBinders :: [TyVarBinder]
where
type TyVarBinder = VarBndr TyVar ForAllTyFlag
type InvisTVBinder = VarBndr TyVar Specificity
and
data Specificity = InferredSpec | SpecifiedSpec
data ForAllTyFlag = Invisible Specificity | Required
This change necessitates some boring, mechanical changes scattered
throughout the diff:
... is now used in place of ...
-----------------+---------------
TyVarBinder | InvisTVBinder
IfaceForAllBndr | IfaceForAllSpecBndr
Specified | SpecifiedSpec
Inferred | InferredSpec
mkForAllTys | mkInvisForAllTys
additionally,
tyVarSpecToBinders -- added or removed calls
ifaceForAllSpecToBndrs -- removed calls
Visibility casts in mkDataConRep
--------------------------------
Type abstractions in Core (/\a. e) always have type (forall a. t)
because coreTyLamForAllTyFlag = Specified. This is also true of data
constructor workers. So we may be faced with the following:
data con worker: (forall a. blah)
data con wrapper: (forall a -> blah)
In this case the wrapper must use a visibility cast (e |> ForAllCo ...)
with appropriately set fco_vis{L,R}. Relevant functions:
mkDataConRep in compiler/GHC/Types/Id/Make.hs
dataConUserTyVarBindersNeedWrapper in compiler/GHC/Core/DataCon.hs
mkForAllVisCos in compiler/GHC/Core/Coercion.hs
mkCoreTyLams in compiler/GHC/Core/Make.hs
mkWpForAllCast in compiler/GHC/Tc/Types/Evidence.hs
More specifically:
- dataConUserTyVarBindersNeedWrapper has been updated to answer "yes"
if there are visible foralls in the type of the data constructor.
- mkDataConRep now uses mkCoreTyLams to generate the big lambda
abstractions (/\a b c. e) in the data con wrapper.
- mkCoreTyLams is a variant of mkCoreLams that applies visibility casts
as needed. It similar in purpose to the pre-existing mkWpForAllCast,
so the common bits have been factored out into mkForAllVisCos.
ConDecl in compiler/Language/Haskell/Syntax/Decls.hs
----------------------------------------------------
The surface syntax representation of a data constructor declaration is
ConDecl. In accordance with the proposal, only GADT syntax is extended
with support for visible forall, so we are interested in ConDeclGADT.
ConDeclGADT's field con_bndrs has been renamed to con_outer_bndrs
and is now accompanied by con_inner_bndrs:
con_outer_bndrs :: XRec pass (HsOuterSigTyVarBndrs pass)
con_inner_bndrs :: [HsForAllTelescope pass]
Visible foralls always end up in con_inner_bndrs. The outer binders are
stored and processed separately to support implicit quantification and
the forall-or-nothing rule, a design established by HsSigType.
A side effect of this change is that even in absence of visible foralls,
GHC now permits multiple invisible foralls, e.g.
data T a where { MkT :: forall a b. forall c d. ... -> T a }
But of course, this is done in service of making at least some of these
foralls visible. The entire compiler front-end has been updated to deal
with con_inner_bndrs. See the following modified or added functions:
Parser:
mkGadtDecl in compiler/GHC/Parser/PostProcess.hs
splitLHsGadtTy in compiler/GHC/Hs/Type.hs
Pretty-printer:
pprConDecl in compiler/GHC/Hs/Decls.hs
pprHsForAllTelescope in compiler/GHC/Hs/Type.hs
Renamer:
rnConDecl in compiler/GHC/Rename/Module.hs
bindHsForAllTelescopes in compiler/GHC/Rename/HsType.hs
extractHsForAllTelescopes in compiler/GHC/Rename/HsType.hs
Type checker:
tcConDecl in compiler/GHC/Tc/TyCl.hs
tcGadtConTyVarBndrs in compiler/GHC/Tc/Gen/HsType.hs
Template Haskell
----------------
The TH AST is left unchanged for the moment to avoid breakage. An
attempt to quote or reify a data constructor declaration with visible
forall in its type will result an error:
data ThRejectionReason -- in GHC/HsToCore/Errors/Types.hs
= ...
| ThDataConVisibleForall -- new error constructor
However, as noted in the previous section, GHC now permits multiple
invisible foralls, and TH was updated accordingly. Updated code:
repC in compiler/GHC/HsToCore/Quote.hs
reifyDataCon in compiler/GHC/Tc/Gen/Splice.hs
ppr @Con in libraries/ghc-boot-th/GHC/Boot/TH/Ppr.hs
Pattern matching
----------------
Everything described above concerns data constructor declarations, but
what about their use sites? Now it is trickier to type check a pattern
match fn(Con a b c)=... because we can no longer assume that a,b,c are
all value arguments. Indeed, some or all of them may very well turn out
to be required type arguments.
To that end, see the changes to:
tcDataConPat in compiler/GHC/Tc/Gen/Pat.hs
splitConTyArgs in compiler/GHC/Tc/Gen/Pat.hs
and the new helpers split_con_ty_args, zip_pats_bndrs.
This is also the reason the TcRnTooManyTyArgsInConPattern error
constructor has been removed. The new code emits TcRnArityMismatch
or TcRnIllegalInvisibleTypePattern.
Summary
-------
DataCon, ConDecl, as well as all related functions have been updated to
support required type arguments in data constructors.
Test cases:
HieGadtConSigs GadtConSigs_th_dump1 GadtConSigs_th_pprint1
T25127_data T25127_data_inst T25127_infix
T25127_newtype T25127_fail_th_quote T25127_fail_arity
TyAppPat_Tricky
Co-authored-by: mniip <mniip(a)mniip.com>
- - - - -
ae003a3a by Teo Camarasu at 2025-06-23T05:21:48-04:00
linters: lint-whitespace: bump upper-bound for containers
The version of containers was bumped in https://gitlab.haskell.org/ghc/ghc/-/merge_requests/13989
- - - - -
0fb37893 by Matthew Pickering at 2025-06-23T13:55:10-04:00
Move ModuleGraph into UnitEnv
The ModuleGraph is a piece of information associated with the
ExternalPackageState and HomeUnitGraph. Therefore we should store it
inside the HomeUnitEnv.
- - - - -
3bf6720e by soulomoon at 2025-06-23T13:55:52-04:00
Remove hptAllFamInstances usage during upsweep
Fixes #26118
This change eliminates the use of hptAllFamInstances during the upsweep phase,
as it could access non-below modules from the home package table.
The following updates were made:
* Updated checkFamInstConsistency to accept an explicit ModuleEnv FamInstEnv
parameter and removed the call to hptAllFamInstances.
* Adjusted hugInstancesBelow so we can construct ModuleEnv FamInstEnv
from its result,
* hptAllFamInstances and allFamInstances functions are removed.
- - - - -
83ee7b78 by Ben Gamari at 2025-06-24T05:02:07-04:00
configure: Don't force value of OTOOL, etc. if not present
Previously if `otool` and `install_name_tool` were not present they
would be overridden by `fp_settings.m4`. This logic was introduced in
4ff93292243888545da452ea4d4c1987f2343591 without explanation.
- - - - -
9329c9e1 by Ben Gamari at 2025-06-24T05:02:07-04:00
ghc-toolchain: Add support for otool, install_name_tool
Fixes part of ghc#23675.
- - - - -
25f5c998 by Ben Gamari at 2025-06-24T05:02:08-04:00
ghc-toolchain: Add support for llc, opt, llvm-as
Fixes #23675.
- - - - -
51d150dd by Rodrigo Mesquita at 2025-06-24T05:02:08-04:00
hadrian: Use settings-use-distro-mingw directly
The type `ToolchainSetting` only made sense when we had more settings to
fetch from the system config file. Even then "settings-use-distro-mingw"
is arguably not a toolchain setting.
With the fix for #23675, all toolchain tools were moved to the
`ghc-toolchain` `Toolchain` format. Therefore, we can inline
`settings-use-distro-mingw` accesses and delete `ToolchainSetting`.
- - - - -
dcf68a83 by Rodrigo Mesquita at 2025-06-24T05:02:08-04:00
configure: Check LlvmTarget exists for LlvmAsFlags
If LlvmTarget was empty, LlvmAsFlags would be just "--target=".
If it is empty now, simply keep LlvmAsFlags empty.
ghc-toolchain already does this right. This fix makes the two
configurations match up.
- - - - -
580a3353 by Ben Gamari at 2025-06-24T05:02:51-04:00
rts/linker/LoadArchive: Use bool
Improve type precision by using `bool` instead of `int` and `StgBool`.
- - - - -
76d1041d by Ben Gamari at 2025-06-24T05:02:51-04:00
rts/linker/LoadArchive: Don't rely on file extensions for identification
Previously archive members would be identified via their file extension,
as described in #13103. We now instead use a more principled approach,
relying on the magic number in the member's header.
As well, we refactor treatment of archive format detection to improve
code clarity and error handling.
Closes #13103.
- - - - -
4b748a99 by Teo Camarasu at 2025-06-24T15:31:07-04:00
template-haskell: improve changelog
stable -> more stable, just to clarify that this interface isn't fully stable.
errornously -> mistakenly: I typod this and also let's go for a simpler word
- - - - -
e358e477 by Sylvain Henry at 2025-06-24T15:31:58-04:00
Bump stack resolver to use GHC 9.6.7
Cf #26139
- - - - -
4bf5eb63 by fendor at 2025-06-25T17:05:43-04:00
Teach `:reload` about multiple home units
`:reload` needs to lookup the `ModuleName` and must not assume the given
`ModuleName` is in the current `HomeUnit`.
We add a new utility function which allows us to find a `HomeUnitModule`
instead of a `Module`.
Further, we introduce the `GhciCommandError` type which can be used to
abort the execution of a GHCi command.
This error is caught and printed in a human readable fashion.
- - - - -
b3d97bb3 by fendor at 2025-06-25T17:06:25-04:00
Implement `-fno-load-initial-targets` flag
We add the new flag `-fno-load-initial-targets` which doesn't load all `Target`s
immediately but only computes the module graph for all `Target`s.
The user can then decide to load modules from that module graph using
the syntax:
ghci> :reload <Mod>
This will load everything in the module graph up to `Mod`.
The user can return to the initial state by using the builtin target
`none` to unload all modules.
ghci> :reload none
Is in principle identical to starting a new session with the
`-fno-load-initial-targets` flag.
The `-fno-load-initial-targets` flag allows for faster startup time of GHCi when a
user has lots of `Target`s.
We additionally extend the `:reload` command to accept multiple
`ModuleName`s. For example:
ghci> :reload <Mod1> <Mod2>
Loads all modules up to the modules `Mod1` and `Mod2`.
- - - - -
49f44e52 by Teo Camarasu at 2025-06-26T04:19:51-04:00
Expose ghc-internal unit id through the settings file
This in combination with the unit id of the compiler library allows
cabal to know of the two unit ids that should not be reinstalled (in
specific circumstances) as:
- when using plugins, we want to link against exactly the compiler unit
id
- when using TemplateHaskell we want to link against exactly the package
that contains the TemplateHaskell interfaces, which is `ghc-internal`
See: <https://github.com/haskell/cabal/issues/10087>
Resolves #25282
- - - - -
499c4efe by Bryan Richter at 2025-06-26T04:20:33-04:00
CI: Fix and clean up capture of timings
* Fixes the typo that caused 'cat ci-timings' to report "no such file or
directory"
* Gave ci_timings.txt a file extension so it may play better with other
systems
* Fixed the use of time_it so all times are recorded
* Fixed time_it to print name along with timing
- - - - -
86c90c9e by Bryan Richter at 2025-06-26T04:20:33-04:00
CI: Update collapsible section usage
The syntax apparently changed at some point.
- - - - -
04308ee4 by Bryan Richter at 2025-06-26T04:20:33-04:00
CI: Add more collapsible sections
- - - - -
43b606bb by Florian Ragwitz at 2025-06-27T16:31:26-04:00
Tick uses of wildcard/pun field binds as if using the record selector function
Fixes #17834.
See Note [Record-selector ticks] for additional reasoning behind this as well
as an overview of the implementation details and future improvements.
- - - - -
d4952549 by Ben Gamari at 2025-06-27T16:32:08-04:00
testsuite/caller-cc: Make CallerCc[123] less sensitive
These were previously sensitive to irrelevant changes in program
structure. To avoid this we filter out all by lines emitted by the
-fcaller-cc from the profile.
- - - - -
0ebc60f5 by Zubin Duggal at 2025-07-02T16:03:50+00:00
compiler: Export a version of `newNameCache` that is not prone to footguns.
`newNameCache` must be initialized with both a non-"reserved" unique tag, as well
as a list of known key names. Failing to do so results in hard to debug unique conflicts.
It is difficult for API users to tell which unique tags are safe to use. So instead of leaving
this up to the user to decide, we now export a version of `newNameCache` which uses a guaranteed
non-reserved unique tag. In fact, this is now the way the unique tag is initialized for all invocations
of the compiler.
The original version of `newNameCache` is now exported as `newNameCache'` for advanced users.
We also deprecate `initNameCache` as it is also prone to footguns and is completely subsumed in
functionality by `newNameCache` and `newNameCache'`.
Fixes #26135 and #26055
- - - - -
249 changed files:
- .gitlab-ci.yml
- .gitlab/ci.sh
- .gitlab/common.sh
- .gitlab/generate-ci/gen_ci.hs
- .gitlab/jobs.yaml
- compiler/GHC.hs
- compiler/GHC/Builtin/Types.hs
- compiler/GHC/Core/Coercion.hs
- compiler/GHC/Core/ConLike.hs
- compiler/GHC/Core/DataCon.hs
- compiler/GHC/Core/DataCon.hs-boot
- compiler/GHC/Core/Make.hs
- compiler/GHC/Core/Opt/Pipeline.hs
- compiler/GHC/Core/PatSyn.hs
- compiler/GHC/Core/TyCo/Ppr.hs
- compiler/GHC/Core/TyCo/Rep.hs
- compiler/GHC/Driver/Backpack.hs
- compiler/GHC/Driver/DynFlags.hs
- compiler/GHC/Driver/Env.hs
- compiler/GHC/Driver/Env/Types.hs
- compiler/GHC/Driver/Flags.hs
- compiler/GHC/Driver/Main.hs
- compiler/GHC/Driver/Make.hs
- compiler/GHC/Driver/Pipeline/Execute.hs
- compiler/GHC/Driver/Session.hs
- compiler/GHC/Hs/Decls.hs
- compiler/GHC/Hs/Expr.hs
- compiler/GHC/Hs/Pat.hs
- compiler/GHC/Hs/Type.hs
- compiler/GHC/HsToCore/Errors/Ppr.hs
- compiler/GHC/HsToCore/Errors/Types.hs
- compiler/GHC/HsToCore/Quote.hs
- compiler/GHC/HsToCore/Ticks.hs
- compiler/GHC/Iface/Decl.hs
- compiler/GHC/Iface/Ext/Ast.hs
- compiler/GHC/Iface/Load.hs
- compiler/GHC/Iface/Syntax.hs
- compiler/GHC/Parser/PostProcess.hs
- compiler/GHC/Parser/PostProcess/Haddock.hs
- compiler/GHC/Rename/HsType.hs
- compiler/GHC/Rename/Module.hs
- compiler/GHC/Rename/Splice.hs
- compiler/GHC/SysTools/Ar.hs
- compiler/GHC/Tc/Errors.hs
- compiler/GHC/Tc/Errors/Ppr.hs
- compiler/GHC/Tc/Errors/Types.hs
- compiler/GHC/Tc/Gen/Head.hs
- compiler/GHC/Tc/Gen/HsType.hs
- compiler/GHC/Tc/Gen/Match.hs
- compiler/GHC/Tc/Gen/Pat.hs
- compiler/GHC/Tc/Gen/Splice.hs
- compiler/GHC/Tc/Instance/Family.hs
- compiler/GHC/Tc/Module.hs
- compiler/GHC/Tc/Solver/Monad.hs
- compiler/GHC/Tc/TyCl.hs
- compiler/GHC/Tc/TyCl/Build.hs
- compiler/GHC/Tc/TyCl/Utils.hs
- compiler/GHC/Tc/Types/Evidence.hs
- compiler/GHC/Tc/Types/Origin.hs
- compiler/GHC/Tc/Validity.hs
- compiler/GHC/ThToHs.hs
- compiler/GHC/Types/Error/Codes.hs
- compiler/GHC/Types/Id/Make.hs
- compiler/GHC/Types/Name/Cache.hs
- compiler/GHC/Types/Var.hs-boot
- compiler/GHC/Unit/Env.hs
- compiler/GHC/Unit/Home/Graph.hs
- compiler/GHC/Unit/Home/PackageTable.hs
- compiler/GHC/Unit/Module/Graph.hs
- compiler/GHC/Utils/Panic.hs
- compiler/Language/Haskell/Syntax/Decls.hs
- compiler/Language/Haskell/Syntax/Pat.hs
- compiler/Setup.hs
- distrib/configure.ac.in
- docs/users_guide/9.14.1-notes.rst
- docs/users_guide/exts/gadt_syntax.rst
- docs/users_guide/exts/required_type_arguments.rst
- docs/users_guide/ghci.rst
- docs/users_guide/using-warnings.rst
- docs/users_guide/using.rst
- ghc/GHCi/UI.hs
- ghc/GHCi/UI/Exception.hs
- ghc/GHCi/UI/Print.hs
- hadrian/cfg/default.host.target.in
- hadrian/cfg/default.target.in
- hadrian/cfg/system.config.in
- hadrian/src/Builder.hs
- hadrian/src/Oracles/Setting.hs
- hadrian/src/Rules/Generate.hs
- hadrian/src/Settings/Builders/RunTest.hs
- hadrian/stack.yaml
- hadrian/stack.yaml.lock
- libraries/ghc-boot-th/GHC/Boot/TH/Ppr.hs
- libraries/template-haskell/changelog.md
- linters/lint-whitespace/lint-whitespace.cabal
- m4/fp_settings.m4
- m4/ghc_toolchain.m4
- m4/prep_target_file.m4
- rts/include/stg/MachRegs.h
- rts/linker/LoadArchive.c
- testsuite/tests/annotations/should_fail/annfail03.stderr
- testsuite/tests/annotations/should_fail/annfail09.stderr
- testsuite/tests/dependent/should_fail/T16326_Fail6.stderr
- + testsuite/tests/ghc-api/T26120.hs
- + testsuite/tests/ghc-api/T26120.stdout
- testsuite/tests/ghc-api/all.T
- testsuite/tests/ghc-e/should_fail/T18441fail5.stderr
- testsuite/tests/ghci/prog-mhu003/prog-mhu003.stderr
- testsuite/tests/ghci/prog-mhu004/prog-mhu004a.stderr
- + testsuite/tests/ghci/prog-mhu005/Makefile
- + testsuite/tests/ghci/prog-mhu005/a/A.hs
- + testsuite/tests/ghci/prog-mhu005/all.T
- + testsuite/tests/ghci/prog-mhu005/b/B.hs
- + testsuite/tests/ghci/prog-mhu005/prog-mhu005a.script
- + testsuite/tests/ghci/prog-mhu005/prog-mhu005a.stderr
- + testsuite/tests/ghci/prog-mhu005/prog-mhu005a.stdout
- + testsuite/tests/ghci/prog-mhu005/unitA
- + testsuite/tests/ghci/prog-mhu005/unitB
- + testsuite/tests/ghci/prog021/A.hs
- + testsuite/tests/ghci/prog021/B.hs
- + testsuite/tests/ghci/prog021/Makefile
- + testsuite/tests/ghci/prog021/all.T
- + testsuite/tests/ghci/prog021/prog021a.script
- + testsuite/tests/ghci/prog021/prog021a.stderr
- + testsuite/tests/ghci/prog021/prog021a.stdout
- + testsuite/tests/ghci/prog021/prog021b.script
- + testsuite/tests/ghci/prog021/prog021b.stderr
- + testsuite/tests/ghci/prog021/prog021b.stdout
- + testsuite/tests/ghci/prog022/A.hs
- + testsuite/tests/ghci/prog022/B.hs
- + testsuite/tests/ghci/prog022/Makefile
- + testsuite/tests/ghci/prog022/all.T
- + testsuite/tests/ghci/prog022/ghci.prog022a.script
- + testsuite/tests/ghci/prog022/ghci.prog022a.stderr
- + testsuite/tests/ghci/prog022/ghci.prog022a.stdout
- + testsuite/tests/ghci/prog022/ghci.prog022b.script
- + testsuite/tests/ghci/prog022/ghci.prog022b.stderr
- + testsuite/tests/ghci/prog022/ghci.prog022b.stdout
- testsuite/tests/ghci/scripts/ghci021.stderr
- testsuite/tests/haddock/should_compile_flag_haddock/T17544.stderr
- testsuite/tests/haddock/should_compile_flag_haddock/T17544_kw.stderr
- + testsuite/tests/hiefile/should_run/HieGadtConSigs.hs
- + testsuite/tests/hiefile/should_run/HieGadtConSigs.stdout
- testsuite/tests/hiefile/should_run/TestUtils.hs
- testsuite/tests/hiefile/should_run/all.T
- + testsuite/tests/hpc/recsel/Makefile
- + testsuite/tests/hpc/recsel/recsel.hs
- + testsuite/tests/hpc/recsel/recsel.stdout
- + testsuite/tests/hpc/recsel/test.T
- testsuite/tests/parser/should_compile/DumpParsedAst.stderr
- testsuite/tests/parser/should_compile/DumpRenamedAst.stderr
- testsuite/tests/parser/should_compile/T15323.stderr
- testsuite/tests/printer/T18791.stderr
- testsuite/tests/profiling/should_run/caller-cc/all.T
- testsuite/tests/quasiquotation/qq001/qq001.stderr
- testsuite/tests/quasiquotation/qq002/qq002.stderr
- testsuite/tests/quasiquotation/qq003/qq003.stderr
- testsuite/tests/quasiquotation/qq004/qq004.stderr
- + testsuite/tests/quotes/LiftErrMsg.hs
- + testsuite/tests/quotes/LiftErrMsg.stderr
- + testsuite/tests/quotes/LiftErrMsgDefer.hs
- + testsuite/tests/quotes/LiftErrMsgDefer.stderr
- + testsuite/tests/quotes/LiftErrMsgTyped.hs
- + testsuite/tests/quotes/LiftErrMsgTyped.stderr
- testsuite/tests/quotes/T10384.stderr
- testsuite/tests/quotes/TH_localname.stderr
- testsuite/tests/quotes/all.T
- testsuite/tests/splice-imports/SI03.stderr
- testsuite/tests/splice-imports/SI05.stderr
- testsuite/tests/splice-imports/SI16.stderr
- testsuite/tests/splice-imports/SI18.stderr
- testsuite/tests/splice-imports/SI20.stderr
- testsuite/tests/splice-imports/SI25.stderr
- testsuite/tests/splice-imports/SI28.stderr
- testsuite/tests/splice-imports/SI31.stderr
- + testsuite/tests/th/GadtConSigs_th_dump1.hs
- + testsuite/tests/th/GadtConSigs_th_dump1.stderr
- + testsuite/tests/th/GadtConSigs_th_pprint1.hs
- + testsuite/tests/th/GadtConSigs_th_pprint1.stderr
- testsuite/tests/th/T16976z.stderr
- testsuite/tests/th/T17820a.stderr
- testsuite/tests/th/T17820b.stderr
- testsuite/tests/th/T17820c.stderr
- testsuite/tests/th/T17820d.stderr
- testsuite/tests/th/T17820e.stderr
- testsuite/tests/th/T20868.stdout
- testsuite/tests/th/T23829_hasty.stderr
- testsuite/tests/th/T23829_hasty_b.stderr
- testsuite/tests/th/T5795.stderr
- testsuite/tests/th/all.T
- + testsuite/tests/typecheck/should_compile/T20873c.hs
- − testsuite/tests/typecheck/should_compile/T22141a.stderr
- − testsuite/tests/typecheck/should_compile/T22141b.stderr
- − testsuite/tests/typecheck/should_compile/T22141c.stderr
- − testsuite/tests/typecheck/should_compile/T22141d.stderr
- − testsuite/tests/typecheck/should_compile/T22141e.stderr
- testsuite/tests/typecheck/should_compile/T23739a.hs
- + testsuite/tests/typecheck/should_compile/TyAppPat_Tricky.hs
- testsuite/tests/typecheck/should_compile/all.T
- testsuite/tests/typecheck/should_fail/T20443b.stderr
- − testsuite/tests/typecheck/should_fail/T20873c.hs
- − testsuite/tests/typecheck/should_fail/T20873c.stderr
- testsuite/tests/typecheck/should_compile/T22141a.hs → testsuite/tests/typecheck/should_fail/T22141a.hs
- testsuite/tests/typecheck/should_fail/T22141a.stderr
- testsuite/tests/typecheck/should_compile/T22141b.hs → testsuite/tests/typecheck/should_fail/T22141b.hs
- testsuite/tests/typecheck/should_fail/T22141b.stderr
- testsuite/tests/typecheck/should_compile/T22141c.hs → testsuite/tests/typecheck/should_fail/T22141c.hs
- testsuite/tests/typecheck/should_fail/T22141c.stderr
- testsuite/tests/typecheck/should_compile/T22141d.hs → testsuite/tests/typecheck/should_fail/T22141d.hs
- testsuite/tests/typecheck/should_fail/T22141d.stderr
- testsuite/tests/typecheck/should_compile/T22141e.hs → testsuite/tests/typecheck/should_fail/T22141e.hs
- testsuite/tests/typecheck/should_fail/T22141e.stderr
- testsuite/tests/typecheck/should_compile/T22141e_Aux.hs → testsuite/tests/typecheck/should_fail/T22141e_Aux.hs
- testsuite/tests/typecheck/should_fail/TyAppPat_TooMany.stderr
- testsuite/tests/typecheck/should_fail/all.T
- + testsuite/tests/vdq-rta/should_compile/T25127_data.hs
- + testsuite/tests/vdq-rta/should_compile/T25127_data_inst.hs
- + testsuite/tests/vdq-rta/should_compile/T25127_infix.hs
- + testsuite/tests/vdq-rta/should_compile/T25127_newtype.hs
- testsuite/tests/vdq-rta/should_compile/all.T
- testsuite/tests/vdq-rta/should_fail/T23739_fail_case.hs
- testsuite/tests/vdq-rta/should_fail/T23739_fail_case.stderr
- testsuite/tests/vdq-rta/should_fail/T24159_type_syntax_th_fail.script
- + testsuite/tests/vdq-rta/should_fail/T25127_fail_arity.hs
- + testsuite/tests/vdq-rta/should_fail/T25127_fail_arity.stderr
- + testsuite/tests/vdq-rta/should_fail/T25127_fail_th_quote.hs
- + testsuite/tests/vdq-rta/should_fail/T25127_fail_th_quote.stderr
- testsuite/tests/vdq-rta/should_fail/all.T
- utils/check-exact/ExactPrint.hs
- utils/ghc-toolchain/exe/Main.hs
- utils/ghc-toolchain/src/GHC/Toolchain/Target.hs
- utils/haddock/CHANGES.md
- utils/haddock/doc/cheatsheet/haddocks.md
- utils/haddock/doc/markup.rst
- utils/haddock/haddock-api/src/Haddock/Backends/Hoogle.hs
- utils/haddock/haddock-api/src/Haddock/Backends/LaTeX.hs
- utils/haddock/haddock-api/src/Haddock/Backends/Xhtml/Decl.hs
- utils/haddock/haddock-api/src/Haddock/Convert.hs
- utils/haddock/haddock-api/src/Haddock/GhcUtils.hs
- utils/haddock/haddock-api/src/Haddock/Interface.hs
- utils/haddock/haddock-api/src/Haddock/Interface/AttachInstances.hs
- utils/haddock/haddock-api/src/Haddock/Interface/Create.hs
- utils/haddock/haddock-api/src/Haddock/Interface/Rename.hs
- utils/haddock/haddock-api/src/Haddock/InterfaceFile.hs
- utils/haddock/haddock-api/src/Haddock/Types.hs
- + utils/haddock/html-test/ref/RedactTypeSynonyms.html
- + utils/haddock/html-test/src/RedactTypeSynonyms.hs
- + utils/haddock/latex-test/ref/RedactTypeSynonyms/RedactTypeSynonyms.tex
- + utils/haddock/latex-test/src/RedactTypeSynonyms/RedactTypeSynonyms.hs
The diff was not included because it is too large.
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/6997abfc3ef8622eeee8d69696746b…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/6997abfc3ef8622eeee8d69696746b…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][wip/romes/step-out-9] 23 commits: Teach `:reload` about multiple home units
by Rodrigo Mesquita (@alt-romes) 02 Jul '25
by Rodrigo Mesquita (@alt-romes) 02 Jul '25
02 Jul '25
Rodrigo Mesquita pushed to branch wip/romes/step-out-9 at Glasgow Haskell Compiler / GHC
Commits:
4bf5eb63 by fendor at 2025-06-25T17:05:43-04:00
Teach `:reload` about multiple home units
`:reload` needs to lookup the `ModuleName` and must not assume the given
`ModuleName` is in the current `HomeUnit`.
We add a new utility function which allows us to find a `HomeUnitModule`
instead of a `Module`.
Further, we introduce the `GhciCommandError` type which can be used to
abort the execution of a GHCi command.
This error is caught and printed in a human readable fashion.
- - - - -
b3d97bb3 by fendor at 2025-06-25T17:06:25-04:00
Implement `-fno-load-initial-targets` flag
We add the new flag `-fno-load-initial-targets` which doesn't load all `Target`s
immediately but only computes the module graph for all `Target`s.
The user can then decide to load modules from that module graph using
the syntax:
ghci> :reload <Mod>
This will load everything in the module graph up to `Mod`.
The user can return to the initial state by using the builtin target
`none` to unload all modules.
ghci> :reload none
Is in principle identical to starting a new session with the
`-fno-load-initial-targets` flag.
The `-fno-load-initial-targets` flag allows for faster startup time of GHCi when a
user has lots of `Target`s.
We additionally extend the `:reload` command to accept multiple
`ModuleName`s. For example:
ghci> :reload <Mod1> <Mod2>
Loads all modules up to the modules `Mod1` and `Mod2`.
- - - - -
49f44e52 by Teo Camarasu at 2025-06-26T04:19:51-04:00
Expose ghc-internal unit id through the settings file
This in combination with the unit id of the compiler library allows
cabal to know of the two unit ids that should not be reinstalled (in
specific circumstances) as:
- when using plugins, we want to link against exactly the compiler unit
id
- when using TemplateHaskell we want to link against exactly the package
that contains the TemplateHaskell interfaces, which is `ghc-internal`
See: <https://github.com/haskell/cabal/issues/10087>
Resolves #25282
- - - - -
499c4efe by Bryan Richter at 2025-06-26T04:20:33-04:00
CI: Fix and clean up capture of timings
* Fixes the typo that caused 'cat ci-timings' to report "no such file or
directory"
* Gave ci_timings.txt a file extension so it may play better with other
systems
* Fixed the use of time_it so all times are recorded
* Fixed time_it to print name along with timing
- - - - -
86c90c9e by Bryan Richter at 2025-06-26T04:20:33-04:00
CI: Update collapsible section usage
The syntax apparently changed at some point.
- - - - -
04308ee4 by Bryan Richter at 2025-06-26T04:20:33-04:00
CI: Add more collapsible sections
- - - - -
43b606bb by Florian Ragwitz at 2025-06-27T16:31:26-04:00
Tick uses of wildcard/pun field binds as if using the record selector function
Fixes #17834.
See Note [Record-selector ticks] for additional reasoning behind this as well
as an overview of the implementation details and future improvements.
- - - - -
d4952549 by Ben Gamari at 2025-06-27T16:32:08-04:00
testsuite/caller-cc: Make CallerCc[123] less sensitive
These were previously sensitive to irrelevant changes in program
structure. To avoid this we filter out all by lines emitted by the
-fcaller-cc from the profile.
- - - - -
0f404726 by Rodrigo Mesquita at 2025-07-02T10:40:51+01:00
debugger/rts: Allow toggling step-in per thread
The RTS global flag `rts_stop_next_breakpoint` globally sets the
interpreter to stop at the immediate next breakpoint.
With this commit, single step mode can additionally be set per thread in
the TSO flag (TSO_STOP_NEXT_BREAKPOINT).
Being able to toggle "stop at next breakpoint" per thread is an
important requirement for implementing "stepping out" of a function in a
multi-threaded context.
And, more generally, having a per-thread flag for single-stepping paves the
way for multi-threaded debugging.
That said, when we want to enable "single step" mode for the whole
interpreted program we still want to stop at the immediate next
breakpoint, whichever thread it belongs to.
That's why we also keep the global `rts_stop_next_breakpoint` flag, with
`rts_enableStopNextBreakpointAll` and `rts_disableStopNextBreakpointAll` helpers.
Preparation for #26042
- - - - -
c727a0ff by Rodrigo Mesquita at 2025-07-02T10:40:51+01:00
docs: Case continuation BCOs
This commit documents a subtle interaction between frames for case BCOs
and their parents frames. Namely, case continuation BCOs may refer to
(non-local) variables that are part of the parent's frame.
The note expanding a bit on these details is called [Case continuation BCOs]
- - - - -
1dc2b741 by Rodrigo Mesquita at 2025-07-02T10:40:53+01:00
debugger: Implement step-out feature
Implements support for stepping-out of a function (aka breaking right after
returning from a function) in the interactive debugger.
It also introduces a GHCi command :stepout to step-out of a function
being debugged in the interpreter. The feature is described as:
Stop at the first breakpoint immediately after returning from the current
function scope.
Known limitations: because a function tail-call does not push a stack
frame, if step-out is used inside of a function that was tail-called,
execution will not be returned to its caller, but rather its caller's
first non-tail caller. On the other hand, it means the debugger
follows the more realistic execution of the program.
In the following example:
.. code-block:: none
f = do
a
b <--- (1) set breakpoint then step in here
c
b = do
...
d <--- (2) step-into this tail call
d = do
...
something <--- (3) step-out here
...
Stepping-out will stop execution at the `c` invokation in `f`, rather than
stopping at `b`.
The key idea is simple: When step-out is enabled, traverse the runtime
stack until a continuation BCO is found -- and enable the breakpoint
heading that BCO explicitly using its tick-index.
The details are specified in `Note [Debugger: Step-out]` in `rts/Interpreter.c`.
Since PUSH_ALTS BCOs (representing case continuations) were never headed
by a breakpoint (unlike the case alternatives they push), we introduced
the BRK_ALTS instruction to allow the debugger to set a case
continuation to stop at the breakpoint heading the alternative that is
taken. This is further described in `Note [Debugger: BRK_ALTS]`.
Fixes #26042
- - - - -
caabafee by Rodrigo Mesquita at 2025-07-02T10:40:53+01:00
debugger: Filter step-out stops by SrcSpan
To implement step-out, the RTS looks for the first continuation frame on
the stack and explicitly enables its entry breakpoint. However, some
continuations will be contained in the function from which step-out was
initiated (trivial example is a case expression).
Similarly to steplocal, we will filter the breakpoints at which the RTS
yields to the debugger based on the SrcSpan. When doing step-out, only
stop if the breakpoint is /not/ contained in the function from which we
initiated it.
This is especially relevant in monadic statements such as IO which is
compiled to a long chain of case expressions.
See Note [Debugger: Filtering step-out stops]
- - - - -
b3cb024a by Cheng Shao at 2025-07-02T10:57:13+01:00
compiler: make ModBreaks serializable
- - - - -
a8772d44 by Rodrigo Mesquita at 2025-07-02T10:57:13+01:00
refactor: "Inspecting the session" moved from GHC
Moved utilities for inspecting the session from the GHC module to
GHC.Driver.Session.Inspect
Purely a clean up
- - - - -
855417e1 by Rodrigo Mesquita at 2025-07-02T10:57:14+01:00
cleanup: Pass the HUG to readModBreaks, not HscEnv
A minor cleanup. The associated history and setupBreakpoint functions
are changed accordingly.
- - - - -
6ed3ad45 by Rodrigo Mesquita at 2025-07-02T10:57:14+01:00
cleanup: Move readModBreaks to GHC.Runtime.Interpreter
With some small docs changes
- - - - -
f0ed1d22 by Rodrigo Mesquita at 2025-07-02T10:57:14+01:00
cleanup: Move interpreterProfiled to Interp.Types
Moves interpreterProfiled and interpreterDynamic to
GHC.Runtime.Interpreter.Types from GHC.Runtime.Interpreter.
- - - - -
27330c5d by Rodrigo Mesquita at 2025-07-02T10:57:14+01:00
cleanup: Don't import GHC in Debugger.Breakpoints
Remove the top-level
import GHC
from GHC.Runtime.Debugger.Breakpoints
This makes the module dependencies more granular and cleans up the
qualified imports from the code.
- - - - -
d5981938 by Rodrigo Mesquita at 2025-07-02T10:57:14+01:00
refactor: Use BreakpointId in Core and Ifaces
- - - - -
914cf7a7 by Rodrigo Mesquita at 2025-07-02T10:57:14+01:00
stg2bc: Derive BcM via ReaderT StateT
A small refactor that simplifies GHC.StgToByteCode by deriving-via the
Monad instances for BcM. This is done along the lines of previous
similar refactors like 72b54c0760bbf85be1f73c1a364d4701e5720465.
- - - - -
25f7a096 by Rodrigo Mesquita at 2025-07-02T10:57:14+01:00
refact: Split InternalModBreaks out of ModBreaks
There are currently two competing ways of referring to a Breakpoint:
1. Using the Tick module + Tick index
2. Using the Info module + Info index
1. The Tick index is allocated during desugaring in `mkModBreaks`. It is
used to refer to a breakpoint associated to a Core Tick. For a given
Tick module, there are N Ticks indexed by Tick index.
2. The Info index is allocated during code generation (in StgToByteCode)
and uniquely identifies the breakpoints at runtime (and is indeed used
to determine which breakpoint was hit at runtime).
Why we need both is described by Note [Breakpoint identifiers].
For every info index we used to keep a `CgBreakInfo`, a datatype containing
information relevant to ByteCode Generation, in `ModBreaks`.
This commit splits out the `IntMap CgBreakInfo` out of `ModBreaks` into
a new datatype `InternalModBreaks`.
- The purpose is to separate the `ModBreaks` datatype, which stores
data associated from tick-level information which is fixed after
desugaring, from the unrelated `IntMap CgBreakInfo` information
accumulated during bytecode generation.
- We move `ModBreaks` to GHC.HsToCore.Breakpoints
The new `InternalModBreaks` simply combines the `IntMap CgBreakInfo`
with `ModBreaks`. After code generation we construct an
`InternalModBreaks` with the `CgBreakInfo`s we accumulated and the
existing `ModBreaks` and store that in the compiled BCO in `bc_breaks`.
- Note that we previously only updated the `modBreaks_breakInfo`
field of `ModBreaks` at this exact location, and then stored the
updated `ModBreaks` in the same `bc_breaks`.
- We put this new datatype in GHC.ByteCode.Breakpoints
The rest of the pipeline for which CgBreakInfo is relevant is
accordingly updated to also use `InternalModBreaks`
- - - - -
7623dacb by Rodrigo Mesquita at 2025-07-02T10:57:15+01:00
cleanup: Use BreakpointIds in bytecode gen
Small clean up to use BreakpointId and InternalBreakpointId more
uniformly in bytecode generation rather than using Module + Ix pairs
- - - - -
5d52d4c3 by Rodrigo Mesquita at 2025-07-02T10:57:15+01:00
ghci: Allocate BreakArrays at link time only
Previously, a BreakArray would be allocated with a slot for every tick
in a module at `mkModBreaks`, in HsToCore. However, this approach has
a few downsides:
- It interleaves interpreter behaviour (allocating arrays for
breakpoints) within the desugarer
- It is inflexible in the sense it is impossible for the bytecode
generator to add "internal" breakpoints that can be triggered at
runtime, because those wouldn't have a source tick. (This is relevant
for our intended implementation plan of step-out in #26042)
- It ties the BreakArray indices to the *tick* indexes, while at runtime
we would rather just have the *info* indexes (currently we have both
because BreakArrays are indexed by the *tick* one).
Paving the way for #26042 and #26064, this commit moves the allocation
of BreakArrays to bytecode-loading time -- akin to what is done for CCS
arrays.
Since a BreakArray is allocated only when bytecode is linked, if a
breakpoint is set (e.g. `:break 10`) before the bytecode is linked,
there will exist no BreakArray to trigger the breakpoint in.
Therefore, the function to allocate break arrays (`allocateBreakArrays`)
is exposed and also used in GHC.Runtime.Eval to allocate a break array
when a breakpoint is set, if it doesn't exist yet (in the linker env).
- - - - -
134 changed files:
- .gitlab-ci.yml
- .gitlab/ci.sh
- .gitlab/common.sh
- .gitlab/generate-ci/gen_ci.hs
- .gitlab/jobs.yaml
- compiler/GHC.hs
- compiler/GHC/ByteCode/Asm.hs
- + compiler/GHC/ByteCode/Breakpoints.hs
- compiler/GHC/ByteCode/Instr.hs
- compiler/GHC/ByteCode/Linker.hs
- compiler/GHC/ByteCode/Types.hs
- compiler/GHC/Core/FVs.hs
- compiler/GHC/Core/Lint.hs
- compiler/GHC/Core/Map/Expr.hs
- compiler/GHC/Core/Opt/OccurAnal.hs
- compiler/GHC/Core/Opt/Simplify/Iteration.hs
- compiler/GHC/Core/Ppr.hs
- compiler/GHC/Core/Subst.hs
- compiler/GHC/Core/Tidy.hs
- compiler/GHC/Core/Utils.hs
- compiler/GHC/CoreToIface.hs
- compiler/GHC/CoreToStg.hs
- compiler/GHC/CoreToStg/Prep.hs
- compiler/GHC/Driver/Config.hs
- compiler/GHC/Driver/DynFlags.hs
- compiler/GHC/Driver/Flags.hs
- compiler/GHC/Driver/Make.hs
- compiler/GHC/Driver/Session.hs
- + compiler/GHC/Driver/Session/Inspect.hs
- compiler/GHC/HsToCore.hs
- compiler/GHC/HsToCore/Breakpoints.hs
- compiler/GHC/HsToCore/Ticks.hs
- compiler/GHC/Iface/Syntax.hs
- compiler/GHC/Iface/Tidy.hs
- compiler/GHC/IfaceToCore.hs
- compiler/GHC/Linker/Loader.hs
- compiler/GHC/Linker/Types.hs
- compiler/GHC/Runtime/Debugger/Breakpoints.hs
- compiler/GHC/Runtime/Eval.hs
- compiler/GHC/Runtime/Eval/Types.hs
- compiler/GHC/Runtime/Interpreter.hs
- compiler/GHC/Runtime/Interpreter/Types.hs
- compiler/GHC/Stg/BcPrep.hs
- compiler/GHC/Stg/FVs.hs
- compiler/GHC/StgToByteCode.hs
- − compiler/GHC/Types/Breakpoint.hs
- compiler/GHC/Types/Tickish.hs
- compiler/GHC/Unit/Module/Graph.hs
- compiler/GHC/Unit/Module/ModGuts.hs
- compiler/Setup.hs
- compiler/ghc.cabal.in
- docs/users_guide/9.14.1-notes.rst
- docs/users_guide/ghci.rst
- ghc/GHCi/UI.hs
- ghc/GHCi/UI/Exception.hs
- ghc/GHCi/UI/Print.hs
- hadrian/src/Rules/Generate.hs
- libraries/ghc-heap/GHC/Exts/Heap/Closures.hs
- libraries/ghc-heap/GHC/Exts/Heap/FFIClosures_ProfilingDisabled.hsc
- libraries/ghc-heap/GHC/Exts/Heap/FFIClosures_ProfilingEnabled.hsc
- libraries/ghc-heap/tests/parse_tso_flags.hs
- + libraries/ghci/GHCi/Debugger.hs
- libraries/ghci/GHCi/Message.hs
- libraries/ghci/GHCi/Run.hs
- libraries/ghci/ghci.cabal.in
- rts/Disassembler.c
- rts/Interpreter.c
- rts/Interpreter.h
- rts/RtsSymbols.c
- rts/StgMiscClosures.cmm
- rts/include/rts/Bytecodes.h
- rts/include/rts/Constants.h
- rts/include/rts/storage/Closures.h
- testsuite/tests/count-deps/CountDepsAst.stdout
- testsuite/tests/count-deps/CountDepsParser.stdout
- testsuite/tests/ghc-e/should_fail/T18441fail5.stderr
- + testsuite/tests/ghci.debugger/scripts/T26042b.hs
- + testsuite/tests/ghci.debugger/scripts/T26042b.script
- + testsuite/tests/ghci.debugger/scripts/T26042b.stdout
- + testsuite/tests/ghci.debugger/scripts/T26042c.hs
- + testsuite/tests/ghci.debugger/scripts/T26042c.script
- + testsuite/tests/ghci.debugger/scripts/T26042c.stdout
- + testsuite/tests/ghci.debugger/scripts/T26042d.hs
- + testsuite/tests/ghci.debugger/scripts/T26042d.script
- + testsuite/tests/ghci.debugger/scripts/T26042d.stdout
- + testsuite/tests/ghci.debugger/scripts/T26042e.hs
- + testsuite/tests/ghci.debugger/scripts/T26042e.script
- + testsuite/tests/ghci.debugger/scripts/T26042e.stdout
- + testsuite/tests/ghci.debugger/scripts/T26042f.hs
- + testsuite/tests/ghci.debugger/scripts/T26042f.script
- + testsuite/tests/ghci.debugger/scripts/T26042f1.stderr
- + testsuite/tests/ghci.debugger/scripts/T26042f1.stdout
- + testsuite/tests/ghci.debugger/scripts/T26042f2.stdout
- + testsuite/tests/ghci.debugger/scripts/T26042g.hs
- + testsuite/tests/ghci.debugger/scripts/T26042g.script
- + testsuite/tests/ghci.debugger/scripts/T26042g.stdout
- testsuite/tests/ghci.debugger/scripts/all.T
- testsuite/tests/ghci/prog-mhu003/prog-mhu003.stderr
- testsuite/tests/ghci/prog-mhu004/prog-mhu004a.stderr
- + testsuite/tests/ghci/prog-mhu005/Makefile
- + testsuite/tests/ghci/prog-mhu005/a/A.hs
- + testsuite/tests/ghci/prog-mhu005/all.T
- + testsuite/tests/ghci/prog-mhu005/b/B.hs
- + testsuite/tests/ghci/prog-mhu005/prog-mhu005a.script
- + testsuite/tests/ghci/prog-mhu005/prog-mhu005a.stderr
- + testsuite/tests/ghci/prog-mhu005/prog-mhu005a.stdout
- + testsuite/tests/ghci/prog-mhu005/unitA
- + testsuite/tests/ghci/prog-mhu005/unitB
- + testsuite/tests/ghci/prog021/A.hs
- + testsuite/tests/ghci/prog021/B.hs
- + testsuite/tests/ghci/prog021/Makefile
- + testsuite/tests/ghci/prog021/all.T
- + testsuite/tests/ghci/prog021/prog021a.script
- + testsuite/tests/ghci/prog021/prog021a.stderr
- + testsuite/tests/ghci/prog021/prog021a.stdout
- + testsuite/tests/ghci/prog021/prog021b.script
- + testsuite/tests/ghci/prog021/prog021b.stderr
- + testsuite/tests/ghci/prog021/prog021b.stdout
- + testsuite/tests/ghci/prog022/A.hs
- + testsuite/tests/ghci/prog022/B.hs
- + testsuite/tests/ghci/prog022/Makefile
- + testsuite/tests/ghci/prog022/all.T
- + testsuite/tests/ghci/prog022/ghci.prog022a.script
- + testsuite/tests/ghci/prog022/ghci.prog022a.stderr
- + testsuite/tests/ghci/prog022/ghci.prog022a.stdout
- + testsuite/tests/ghci/prog022/ghci.prog022b.script
- + testsuite/tests/ghci/prog022/ghci.prog022b.stderr
- + testsuite/tests/ghci/prog022/ghci.prog022b.stdout
- testsuite/tests/ghci/scripts/ghci021.stderr
- + testsuite/tests/hpc/recsel/Makefile
- + testsuite/tests/hpc/recsel/recsel.hs
- + testsuite/tests/hpc/recsel/recsel.stdout
- + testsuite/tests/hpc/recsel/test.T
- testsuite/tests/profiling/should_run/caller-cc/all.T
The diff was not included because it is too large.
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/b14013c33b49d893efdb6f07f09a8e…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/b14013c33b49d893efdb6f07f09a8e…
You're receiving this email because of your account on gitlab.haskell.org.
1
0