Marge Bot pushed to branch master at Glasgow Haskell Compiler / GHC
Commits:
-
e9de9e0b
by Sylvain Henry at 2025-05-23T15:12:34-04:00
8 changed files:
- compiler/GHC.hs
- compiler/GHC/ByteCode/Types.hs
- compiler/GHC/HsToCore/Breakpoints.hs
- compiler/GHC/Runtime/Debugger/Breakpoints.hs
- compiler/GHC/Runtime/Eval.hs
- compiler/GHC/Runtime/Interpreter.hs
- compiler/GHC/StgToByteCode.hs
- ghc/GHCi/UI.hs
Changes:
... | ... | @@ -1307,7 +1307,7 @@ typecheckModule pmod = do |
1307 | 1307 | minf_instances = fixSafeInstances safe $ instEnvElts $ md_insts details,
|
1308 | 1308 | minf_iface = Nothing,
|
1309 | 1309 | minf_safe = safe,
|
1310 | - minf_modBreaks = emptyModBreaks
|
|
1310 | + minf_modBreaks = Nothing
|
|
1311 | 1311 | }}
|
1312 | 1312 | |
1313 | 1313 | -- | Desugar a typechecked module.
|
... | ... | @@ -1461,7 +1461,7 @@ data ModuleInfo = ModuleInfo { |
1461 | 1461 | minf_instances :: [ClsInst],
|
1462 | 1462 | minf_iface :: Maybe ModIface,
|
1463 | 1463 | minf_safe :: SafeHaskellMode,
|
1464 | - minf_modBreaks :: ModBreaks
|
|
1464 | + minf_modBreaks :: Maybe ModBreaks
|
|
1465 | 1465 | }
|
1466 | 1466 | -- We don't want HomeModInfo here, because a ModuleInfo applies
|
1467 | 1467 | -- to package modules too.
|
... | ... | @@ -1490,7 +1490,7 @@ getPackageModuleInfo hsc_env mdl |
1490 | 1490 | minf_instances = error "getModuleInfo: instances for package module unimplemented",
|
1491 | 1491 | minf_iface = Just iface,
|
1492 | 1492 | minf_safe = getSafeMode $ mi_trust iface,
|
1493 | - minf_modBreaks = emptyModBreaks
|
|
1493 | + minf_modBreaks = Nothing
|
|
1494 | 1494 | }))
|
1495 | 1495 | |
1496 | 1496 | availsToGlobalRdrEnv :: HasDebugCallStack => HscEnv -> Module -> [AvailInfo] -> IfGlobalRdrEnv
|
... | ... | @@ -1567,7 +1567,7 @@ modInfoIface = minf_iface |
1567 | 1567 | modInfoSafe :: ModuleInfo -> SafeHaskellMode
|
1568 | 1568 | modInfoSafe = minf_safe
|
1569 | 1569 | |
1570 | -modInfoModBreaks :: ModuleInfo -> ModBreaks
|
|
1570 | +modInfoModBreaks :: ModuleInfo -> Maybe ModBreaks
|
|
1571 | 1571 | modInfoModBreaks = minf_modBreaks
|
1572 | 1572 | |
1573 | 1573 | isDictonaryId :: Id -> Bool
|
... | ... | @@ -19,7 +19,7 @@ module GHC.ByteCode.Types |
19 | 19 | , ItblEnv, ItblPtr(..)
|
20 | 20 | , AddrEnv, AddrPtr(..)
|
21 | 21 | , CgBreakInfo(..)
|
22 | - , ModBreaks (..), BreakIndex, emptyModBreaks
|
|
22 | + , ModBreaks (..), BreakIndex
|
|
23 | 23 | , CCostCentre
|
24 | 24 | , FlatBag, sizeFlatBag, fromSmallArray, elemsFlatBag
|
25 | 25 | ) where
|
... | ... | @@ -45,12 +45,11 @@ import Foreign |
45 | 45 | import Data.Array
|
46 | 46 | import Data.ByteString (ByteString)
|
47 | 47 | import Data.IntMap (IntMap)
|
48 | -import qualified Data.IntMap as IntMap
|
|
49 | 48 | import qualified GHC.Exts.Heap as Heap
|
50 | 49 | import GHC.Stack.CCS
|
51 | 50 | import GHC.Cmm.Expr ( GlobalRegSet, emptyRegSet, regSetToList )
|
52 | 51 | import GHC.Iface.Syntax
|
53 | -import Language.Haskell.Syntax.Module.Name (ModuleName, mkModuleNameFS)
|
|
52 | +import Language.Haskell.Syntax.Module.Name (ModuleName)
|
|
54 | 53 | import GHC.Unit.Types (UnitId(..))
|
55 | 54 | |
56 | 55 | -- -----------------------------------------------------------------------------
|
... | ... | @@ -250,7 +249,7 @@ data CCostCentre |
250 | 249 | -- | All the information about the breakpoints for a module
|
251 | 250 | data ModBreaks
|
252 | 251 | = ModBreaks
|
253 | - { modBreaks_flags :: ForeignRef BreakArray
|
|
252 | + { modBreaks_flags :: !(ForeignRef BreakArray)
|
|
254 | 253 | -- ^ The array of flags, one per breakpoint,
|
255 | 254 | -- indicating which breakpoints are enabled.
|
256 | 255 | , modBreaks_locs :: !(Array BreakIndex SrcSpan)
|
... | ... | @@ -281,20 +280,6 @@ seqModBreaks ModBreaks{..} = |
281 | 280 | rnf modBreaks_module `seq`
|
282 | 281 | rnf modBreaks_module_unitid
|
283 | 282 | |
284 | --- | Construct an empty ModBreaks
|
|
285 | -emptyModBreaks :: ModBreaks
|
|
286 | -emptyModBreaks = ModBreaks
|
|
287 | - { modBreaks_flags = error "ModBreaks.modBreaks_array not initialised"
|
|
288 | - -- ToDo: can we avoid this?
|
|
289 | - , modBreaks_locs = array (0,-1) []
|
|
290 | - , modBreaks_vars = array (0,-1) []
|
|
291 | - , modBreaks_decls = array (0,-1) []
|
|
292 | - , modBreaks_ccs = array (0,-1) []
|
|
293 | - , modBreaks_breakInfo = IntMap.empty
|
|
294 | - , modBreaks_module = mkModuleNameFS nilFS
|
|
295 | - , modBreaks_module_unitid = UnitId nilFS
|
|
296 | - }
|
|
297 | - |
|
298 | 283 | {-
|
299 | 284 | Note [Field modBreaks_decls]
|
300 | 285 | ~~~~~~~~~~~~~~~~~~~~~~
|
... | ... | @@ -18,6 +18,7 @@ import GHC.Utils.Outputable as Outputable |
18 | 18 | |
19 | 19 | import Data.List (intersperse)
|
20 | 20 | import Data.Array
|
21 | +import qualified Data.IntMap as IntMap
|
|
21 | 22 | |
22 | 23 | -- | Initialize memory for breakpoint data that is shared between the bytecode
|
23 | 24 | -- generator and the interpreter.
|
... | ... | @@ -38,15 +39,16 @@ mkModBreaks interp mod extendedMixEntries |
38 | 39 | locsTicks = listArray (0,count-1) [ tick_loc t | t <- entries ]
|
39 | 40 | varsTicks = listArray (0,count-1) [ tick_ids t | t <- entries ]
|
40 | 41 | declsTicks = listArray (0,count-1) [ tick_path t | t <- entries ]
|
41 | - return $ emptyModBreaks
|
|
42 | - { modBreaks_flags = breakArray
|
|
43 | - , modBreaks_locs = locsTicks
|
|
44 | - , modBreaks_vars = varsTicks
|
|
45 | - , modBreaks_decls = declsTicks
|
|
46 | - , modBreaks_ccs = ccs
|
|
47 | - , modBreaks_module = moduleName mod
|
|
48 | - , modBreaks_module_unitid = toUnitId $ moduleUnit mod
|
|
49 | - }
|
|
42 | + return $ ModBreaks
|
|
43 | + { modBreaks_flags = breakArray
|
|
44 | + , modBreaks_locs = locsTicks
|
|
45 | + , modBreaks_vars = varsTicks
|
|
46 | + , modBreaks_decls = declsTicks
|
|
47 | + , modBreaks_ccs = ccs
|
|
48 | + , modBreaks_breakInfo = IntMap.empty
|
|
49 | + , modBreaks_module = moduleName mod
|
|
50 | + , modBreaks_module_unitid = toUnitId $ moduleUnit mod
|
|
51 | + }
|
|
50 | 52 | |
51 | 53 | mkCCSArray
|
52 | 54 | :: Interp -> Module -> Int -> [Tick]
|
... | ... | @@ -145,15 +145,17 @@ resolveFunctionBreakpoint inp = do |
145 | 145 | validateBP _ "" (Just _) = pure $ Just $ text "Function name is missing"
|
146 | 146 | validateBP _ fun_str (Just modl) = do
|
147 | 147 | isInterpr <- GHC.moduleIsInterpreted modl
|
148 | - (_, decls) <- getModBreak modl
|
|
149 | 148 | mb_err_msg <- case isInterpr of
|
150 | - False -> pure $ Just $ text "Module" <+> quotes (ppr modl)
|
|
151 | - <+> text "is not interpreted"
|
|
152 | - True -> case fun_str `elem` (intercalate "." <$> elems decls) of
|
|
153 | - False -> pure $ Just $
|
|
154 | - text "No breakpoint found for" <+> quotes (text fun_str)
|
|
155 | - <+> text "in module" <+> quotes (ppr modl)
|
|
156 | - True -> pure Nothing
|
|
149 | + False -> pure $ Just $ text "Module" <+> quotes (ppr modl) <+> text "is not interpreted"
|
|
150 | + True -> do
|
|
151 | + mb_modbreaks <- getModBreak modl
|
|
152 | + let found = case mb_modbreaks of
|
|
153 | + Nothing -> False
|
|
154 | + Just mb -> fun_str `elem` (intercalate "." <$> elems (GHC.modBreaks_decls mb))
|
|
155 | + if found
|
|
156 | + then pure Nothing
|
|
157 | + else pure $ Just $ text "No breakpoint found for" <+> quotes (text fun_str)
|
|
158 | + <+> text "in module" <+> quotes (ppr modl)
|
|
157 | 159 | pure mb_err_msg
|
158 | 160 | |
159 | 161 | -- | The aim of this function is to find the breakpoints for all the RHSs of
|
... | ... | @@ -184,8 +186,7 @@ type TickArray = Array Int [(GHC.BreakIndex,RealSrcSpan)] |
184 | 186 | makeModuleLineMap :: GhcMonad m => Module -> m (Maybe TickArray)
|
185 | 187 | makeModuleLineMap m = do
|
186 | 188 | mi <- GHC.getModuleInfo m
|
187 | - return $
|
|
188 | - mkTickArray . assocs . GHC.modBreaks_locs . GHC.modInfoModBreaks <$> mi
|
|
189 | + return $ mkTickArray . assocs . GHC.modBreaks_locs <$> (GHC.modInfoModBreaks =<< mi)
|
|
189 | 190 | where
|
190 | 191 | mkTickArray :: [(BreakIndex, SrcSpan)] -> TickArray
|
191 | 192 | mkTickArray ticks
|
... | ... | @@ -195,15 +196,12 @@ makeModuleLineMap m = do |
195 | 196 | max_line = foldr max 0 [ GHC.srcSpanEndLine sp | (_, RealSrcSpan sp _) <- ticks ]
|
196 | 197 | srcSpanLines pan = [ GHC.srcSpanStartLine pan .. GHC.srcSpanEndLine pan ]
|
197 | 198 | |
198 | --- | Get the 'modBreaks_locs' and 'modBreaks_decls' of the given 'Module'
|
|
199 | +-- | Get the 'ModBreaks' of the given 'Module' when available
|
|
199 | 200 | getModBreak :: GHC.GhcMonad m
|
200 | - => Module -> m (Array Int SrcSpan, Array Int [String])
|
|
201 | + => Module -> m (Maybe ModBreaks)
|
|
201 | 202 | getModBreak m = do
|
202 | 203 | mod_info <- fromMaybe (panic "getModBreak") <$> GHC.getModuleInfo m
|
203 | - let modBreaks = GHC.modInfoModBreaks mod_info
|
|
204 | - let ticks = GHC.modBreaks_locs modBreaks
|
|
205 | - let decls = GHC.modBreaks_decls modBreaks
|
|
206 | - return (ticks, decls)
|
|
204 | + pure $ GHC.modInfoModBreaks mod_info
|
|
207 | 205 | |
208 | 206 | --------------------------------------------------------------------------------
|
209 | 207 | -- Getting current breakpoint information
|
... | ... | @@ -522,9 +522,8 @@ result_fs = fsLit "_result" |
522 | 522 | |
523 | 523 | -- | Read the 'ModBreaks' of the given home 'Module' from the 'HomeUnitGraph'.
|
524 | 524 | readModBreaks :: HscEnv -> Module -> IO ModBreaks
|
525 | -readModBreaks hsc_env mod =
|
|
526 | - getModBreaks . expectJust <$>
|
|
527 | - HUG.lookupHugByModule mod (hsc_HUG hsc_env)
|
|
525 | +readModBreaks hsc_env mod = expectJust . getModBreaks . expectJust <$> HUG.lookupHugByModule mod (hsc_HUG hsc_env)
|
|
526 | + |
|
528 | 527 | |
529 | 528 | bindLocalsAtBreakpoint
|
530 | 529 | :: HscEnv
|
... | ... | @@ -435,22 +435,24 @@ handleSeqHValueStatus interp unit_env eval_status = |
435 | 435 | resume_ctxt_fhv <- liftIO $ mkFinalizedHValue interp resume_ctxt
|
436 | 436 | |
437 | 437 | let put x = putStrLn ("*** Ignoring breakpoint " ++ (showSDocUnsafe x))
|
438 | + let nothing_case = put $ brackets . ppr $ mkGeneralSrcSpan (fsLit "<unknown>")
|
|
438 | 439 | case maybe_break of
|
439 | - Nothing ->
|
|
440 | + Nothing -> nothing_case
|
|
440 | 441 | -- Nothing case - should not occur!
|
441 | 442 | -- Reason: Setting of flags in libraries/ghci/GHCi/Run.hs:evalOptsSeq
|
442 | - put $ brackets . ppr $
|
|
443 | - mkGeneralSrcSpan (fsLit "<unknown>")
|
|
444 | 443 | |
445 | 444 | Just break -> do
|
446 | 445 | let bi = evalBreakpointToId break
|
447 | 446 | |
448 | 447 | -- Just case: Stopped at a breakpoint, extract SrcSpan information
|
449 | 448 | -- from the breakpoint.
|
450 | - breaks_tick <- getModBreaks . expectJust <$>
|
|
449 | + mb_modbreaks <- getModBreaks . expectJust <$>
|
|
451 | 450 | lookupHugByModule (ibi_tick_mod bi) (ue_home_unit_graph unit_env)
|
452 | - put $ brackets . ppr $
|
|
453 | - (modBreaks_locs breaks_tick) ! ibi_tick_index bi
|
|
451 | + case mb_modbreaks of
|
|
452 | + -- Nothing case - should not occur! We should have the appropriate
|
|
453 | + -- breakpoint information
|
|
454 | + Nothing -> nothing_case
|
|
455 | + Just modbreaks -> put $ brackets . ppr $ (modBreaks_locs modbreaks) ! ibi_tick_index bi
|
|
454 | 456 | |
455 | 457 | -- resume the seq (:force) processing in the iserv process
|
456 | 458 | withForeignRef resume_ctxt_fhv $ \hval -> do
|
... | ... | @@ -737,14 +739,14 @@ fromEvalResult :: EvalResult a -> IO a |
737 | 739 | fromEvalResult (EvalException e) = throwIO (fromSerializableException e)
|
738 | 740 | fromEvalResult (EvalSuccess a) = return a
|
739 | 741 | |
740 | -getModBreaks :: HomeModInfo -> ModBreaks
|
|
742 | +getModBreaks :: HomeModInfo -> Maybe ModBreaks
|
|
741 | 743 | getModBreaks hmi
|
742 | 744 | | Just linkable <- homeModInfoByteCode hmi,
|
743 | 745 | -- The linkable may have 'DotO's as well; only consider BCOs. See #20570.
|
744 | 746 | [cbc] <- linkableBCOs linkable
|
745 | - = fromMaybe emptyModBreaks (bc_breaks cbc)
|
|
747 | + = bc_breaks cbc
|
|
746 | 748 | | otherwise
|
747 | - = emptyModBreaks -- probably object code
|
|
749 | + = Nothing -- probably object code
|
|
748 | 750 | |
749 | 751 | -- | Interpreter uses Profiling way
|
750 | 752 | interpreterProfiled :: Interp -> Bool
|
... | ... | @@ -439,8 +439,8 @@ schemeER_wrk d p rhs = schemeE d 0 p rhs |
439 | 439 | --
|
440 | 440 | -- If the breakpoint is inlined from another module, look it up in the home
|
441 | 441 | -- package table.
|
442 | --- If the module doesn't exist there, or its module pointer is null (which means
|
|
443 | --- that the 'ModBreaks' value is uninitialized), skip the instruction.
|
|
442 | +-- If the module doesn't exist there, or if the 'ModBreaks' value is
|
|
443 | +-- uninitialized, skip the instruction (i.e. return Nothing).
|
|
444 | 444 | break_info ::
|
445 | 445 | HscEnv ->
|
446 | 446 | Module ->
|
... | ... | @@ -449,18 +449,11 @@ break_info :: |
449 | 449 | BcM (Maybe ModBreaks)
|
450 | 450 | break_info hsc_env mod current_mod current_mod_breaks
|
451 | 451 | | mod == current_mod
|
452 | - = pure $ check_mod_ptr =<< current_mod_breaks
|
|
452 | + = pure current_mod_breaks
|
|
453 | 453 | | otherwise
|
454 | 454 | = ioToBc (lookupHpt (hsc_HPT hsc_env) (moduleName mod)) >>= \case
|
455 | - Just hp -> pure $ check_mod_ptr (getModBreaks hp)
|
|
455 | + Just hp -> pure $ getModBreaks hp
|
|
456 | 456 | Nothing -> pure Nothing
|
457 | - where
|
|
458 | - check_mod_ptr mb
|
|
459 | - | mod_ptr <- modBreaks_module mb
|
|
460 | - , not $ nullFS $ moduleNameFS mod_ptr
|
|
461 | - = Just mb
|
|
462 | - | otherwise
|
|
463 | - = Nothing
|
|
464 | 457 | |
465 | 458 | getVarOffSets :: Platform -> StackDepth -> BCEnv -> [Id] -> [Maybe (Id, WordOff)]
|
466 | 459 | getVarOffSets platform depth env = map getOffSet
|
... | ... | @@ -3629,8 +3629,10 @@ completeBreakpoint = wrapCompleter spaces $ \w -> do -- #3000 |
3629 | 3629 | -- Return all possible bids for a given Module
|
3630 | 3630 | bidsByModule :: GhciMonad m => [ModuleName] -> Module -> m [String]
|
3631 | 3631 | bidsByModule nonquals mod = do
|
3632 | - (_, decls) <- getModBreak mod
|
|
3633 | - let bids = nub $ declPath <$> elems decls
|
|
3632 | + mb_decls <- fmap GHC.modBreaks_decls <$> getModBreak mod
|
|
3633 | + let bids = case mb_decls of
|
|
3634 | + Just decls -> nub $ declPath <$> elems decls
|
|
3635 | + Nothing -> []
|
|
3634 | 3636 | pure $ case (moduleName mod) `elem` nonquals of
|
3635 | 3637 | True -> bids
|
3636 | 3638 | False -> (combineModIdent (showModule mod)) <$> bids
|
... | ... | @@ -3656,11 +3658,14 @@ completeBreakpoint = wrapCompleter spaces $ \w -> do -- #3000 |
3656 | 3658 | -- declarations. See Note [Field modBreaks_decls] in GHC.ByteCode.Types
|
3657 | 3659 | addNestedDecls :: GhciMonad m => (String, Module) -> m [String]
|
3658 | 3660 | addNestedDecls (ident, mod) = do
|
3659 | - (_, decls) <- getModBreak mod
|
|
3660 | - let (mod_str, topLvl, _) = splitIdent ident
|
|
3661 | - ident_decls = [ elm | elm@(el : _) <- elems decls, el == topLvl ]
|
|
3662 | - bids = nub $ declPath <$> ident_decls
|
|
3663 | - pure $ map (combineModIdent mod_str) bids
|
|
3661 | + mb_decls <- fmap GHC.modBreaks_decls <$> getModBreak mod
|
|
3662 | + case mb_decls of
|
|
3663 | + Nothing -> pure []
|
|
3664 | + Just decls -> do
|
|
3665 | + let (mod_str, topLvl, _) = splitIdent ident
|
|
3666 | + ident_decls = [ elm | elm@(el : _) <- elems decls, el == topLvl ]
|
|
3667 | + bids = nub $ declPath <$> ident_decls
|
|
3668 | + pure $ map (combineModIdent mod_str) bids
|
|
3664 | 3669 | |
3665 | 3670 | completeModule = wrapIdentCompleterMod $ \w -> do
|
3666 | 3671 | hsc_env <- GHC.getSession
|
... | ... | @@ -4066,7 +4071,7 @@ breakById inp = do |
4066 | 4071 | case mb_error of
|
4067 | 4072 | Left sdoc -> printForUser sdoc
|
4068 | 4073 | Right (mod, mod_info, fun_str) -> do
|
4069 | - let modBreaks = GHC.modInfoModBreaks mod_info
|
|
4074 | + let modBreaks = expectJust (GHC.modInfoModBreaks mod_info)
|
|
4070 | 4075 | findBreakAndSet mod $ \_ -> findBreakForBind fun_str modBreaks
|
4071 | 4076 | |
4072 | 4077 | breakSyntax :: a
|