Rodrigo Mesquita pushed to branch wip/romes/step-out-9 at Glasgow Haskell Compiler / GHC
Commits:
-
5989a722
by Rodrigo Mesquita at 2025-06-30T19:08:43+01:00
-
ff7d68ab
by Rodrigo Mesquita at 2025-06-30T19:08:43+01:00
-
cc8a6cd8
by Rodrigo Mesquita at 2025-06-30T19:08:43+01:00
-
56218cbf
by Rodrigo Mesquita at 2025-06-30T19:08:43+01:00
-
e60ece5d
by Rodrigo Mesquita at 2025-06-30T19:08:43+01:00
-
de60ae45
by Rodrigo Mesquita at 2025-06-30T19:08:43+01:00
28 changed files:
- compiler/GHC.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/Session/Inspect.hs
- compiler/GHC/HsToCore/Ticks.hs
- compiler/GHC/Iface/Syntax.hs
- compiler/GHC/Iface/Tidy.hs
- compiler/GHC/IfaceToCore.hs
- compiler/GHC/Runtime/Debugger/Breakpoints.hs
- compiler/GHC/Runtime/Eval.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.cabal.in
Changes:
| ... | ... | @@ -346,6 +346,7 @@ import GHC.Driver.Errors |
| 346 | 346 | import GHC.Driver.Errors.Types
|
| 347 | 347 | import GHC.Driver.CmdLine
|
| 348 | 348 | import GHC.Driver.Session
|
| 349 | +import GHC.Driver.Session.Inspect
|
|
| 349 | 350 | import GHC.Driver.Backend
|
| 350 | 351 | import GHC.Driver.Config.Finder (initFinderOpts)
|
| 351 | 352 | import GHC.Driver.Config.Parser (initParserOpts)
|
| ... | ... | @@ -378,7 +379,7 @@ import GHC.Builtin.Types.Prim ( alphaTyVars ) |
| 378 | 379 | import GHC.Data.StringBuffer
|
| 379 | 380 | import GHC.Data.FastString
|
| 380 | 381 | import qualified GHC.LanguageExtensions as LangExt
|
| 381 | -import GHC.Rename.Names (renamePkgQual, renameRawPkgQual, gresFromAvails)
|
|
| 382 | +import GHC.Rename.Names (renamePkgQual, renameRawPkgQual)
|
|
| 382 | 383 | |
| 383 | 384 | import GHC.Tc.Utils.Monad ( finalSafeMode, fixSafeInstances, initIfaceTcRn )
|
| 384 | 385 | import GHC.Tc.Types
|
| ... | ... | @@ -425,14 +426,12 @@ import GHC.Types.Target |
| 425 | 426 | import GHC.Types.Basic
|
| 426 | 427 | import GHC.Types.TyThing
|
| 427 | 428 | import GHC.Types.Name.Env
|
| 428 | -import GHC.Types.Name.Ppr
|
|
| 429 | 429 | import GHC.Types.TypeEnv
|
| 430 | 430 | import GHC.Types.Breakpoint
|
| 431 | 431 | import GHC.Types.PkgQual
|
| 432 | 432 | |
| 433 | 433 | import GHC.Unit
|
| 434 | 434 | import GHC.Unit.Env as UnitEnv
|
| 435 | -import GHC.Unit.External
|
|
| 436 | 435 | import GHC.Unit.Finder
|
| 437 | 436 | import GHC.Unit.Module.ModIface
|
| 438 | 437 | import GHC.Unit.Module.ModGuts
|
| ... | ... | @@ -1570,169 +1569,6 @@ compileCore simplify fn = do |
| 1570 | 1569 | cm_safe = safe_mode
|
| 1571 | 1570 | }
|
| 1572 | 1571 | |
| 1573 | --- %************************************************************************
|
|
| 1574 | --- %* *
|
|
| 1575 | --- Inspecting the session
|
|
| 1576 | --- %* *
|
|
| 1577 | --- %************************************************************************
|
|
| 1578 | - |
|
| 1579 | --- | Get the module dependency graph.
|
|
| 1580 | -getModuleGraph :: GhcMonad m => m ModuleGraph -- ToDo: DiGraph ModSummary
|
|
| 1581 | -getModuleGraph = liftM hsc_mod_graph getSession
|
|
| 1582 | - |
|
| 1583 | -{-# DEPRECATED isLoaded "Prefer 'isLoadedModule' and 'isLoadedHomeModule'" #-}
|
|
| 1584 | --- | Return @True@ \<==> module is loaded.
|
|
| 1585 | -isLoaded :: GhcMonad m => ModuleName -> m Bool
|
|
| 1586 | -isLoaded m = withSession $ \hsc_env -> liftIO $ do
|
|
| 1587 | - hmis <- HUG.lookupAllHug (hsc_HUG hsc_env) m
|
|
| 1588 | - return $! not (null hmis)
|
|
| 1589 | - |
|
| 1590 | --- | Check whether a 'ModuleName' is found in the 'HomePackageTable'
|
|
| 1591 | --- for the given 'UnitId'.
|
|
| 1592 | -isLoadedModule :: GhcMonad m => UnitId -> ModuleName -> m Bool
|
|
| 1593 | -isLoadedModule uid m = withSession $ \hsc_env -> liftIO $ do
|
|
| 1594 | - hmi <- HUG.lookupHug (hsc_HUG hsc_env) uid m
|
|
| 1595 | - return $! isJust hmi
|
|
| 1596 | - |
|
| 1597 | --- | Check whether 'Module' is part of the 'HomeUnitGraph'.
|
|
| 1598 | ---
|
|
| 1599 | --- Similar to 'isLoadedModule', but for 'Module's.
|
|
| 1600 | -isLoadedHomeModule :: GhcMonad m => Module -> m Bool
|
|
| 1601 | -isLoadedHomeModule m = withSession $ \hsc_env -> liftIO $ do
|
|
| 1602 | - hmi <- HUG.lookupHugByModule m (hsc_HUG hsc_env)
|
|
| 1603 | - return $! isJust hmi
|
|
| 1604 | - |
|
| 1605 | --- | Return the bindings for the current interactive session.
|
|
| 1606 | -getBindings :: GhcMonad m => m [TyThing]
|
|
| 1607 | -getBindings = withSession $ \hsc_env ->
|
|
| 1608 | - return $ icInScopeTTs $ hsc_IC hsc_env
|
|
| 1609 | - |
|
| 1610 | --- | Return the instances for the current interactive session.
|
|
| 1611 | -getInsts :: GhcMonad m => m ([ClsInst], [FamInst])
|
|
| 1612 | -getInsts = withSession $ \hsc_env ->
|
|
| 1613 | - let (inst_env, fam_env) = ic_instances (hsc_IC hsc_env)
|
|
| 1614 | - in return (instEnvElts inst_env, fam_env)
|
|
| 1615 | - |
|
| 1616 | -getNamePprCtx :: GhcMonad m => m NamePprCtx
|
|
| 1617 | -getNamePprCtx = withSession $ \hsc_env -> do
|
|
| 1618 | - return $ icNamePprCtx (hsc_unit_env hsc_env) (hsc_IC hsc_env)
|
|
| 1619 | - |
|
| 1620 | --- | Container for information about a 'Module'.
|
|
| 1621 | -data ModuleInfo = ModuleInfo {
|
|
| 1622 | - minf_type_env :: TypeEnv,
|
|
| 1623 | - minf_exports :: [AvailInfo],
|
|
| 1624 | - minf_instances :: [ClsInst],
|
|
| 1625 | - minf_iface :: Maybe ModIface,
|
|
| 1626 | - minf_safe :: SafeHaskellMode,
|
|
| 1627 | - minf_modBreaks :: Maybe ModBreaks
|
|
| 1628 | - }
|
|
| 1629 | - -- We don't want HomeModInfo here, because a ModuleInfo applies
|
|
| 1630 | - -- to package modules too.
|
|
| 1631 | - |
|
| 1632 | - |
|
| 1633 | --- | Request information about a loaded 'Module'
|
|
| 1634 | -getModuleInfo :: GhcMonad m => Module -> m (Maybe ModuleInfo) -- XXX: Maybe X
|
|
| 1635 | -getModuleInfo mdl = withSession $ \hsc_env -> do
|
|
| 1636 | - if HUG.memberHugUnit (moduleUnit mdl) (hsc_HUG hsc_env)
|
|
| 1637 | - then liftIO $ getHomeModuleInfo hsc_env mdl
|
|
| 1638 | - else liftIO $ getPackageModuleInfo hsc_env mdl
|
|
| 1639 | - |
|
| 1640 | -getPackageModuleInfo :: HscEnv -> Module -> IO (Maybe ModuleInfo)
|
|
| 1641 | -getPackageModuleInfo hsc_env mdl
|
|
| 1642 | - = do eps <- hscEPS hsc_env
|
|
| 1643 | - iface <- hscGetModuleInterface hsc_env mdl
|
|
| 1644 | - let
|
|
| 1645 | - avails = mi_exports iface
|
|
| 1646 | - pte = eps_PTE eps
|
|
| 1647 | - tys = [ ty | name <- concatMap availNames avails,
|
|
| 1648 | - Just ty <- [lookupTypeEnv pte name] ]
|
|
| 1649 | - |
|
| 1650 | - return (Just (ModuleInfo {
|
|
| 1651 | - minf_type_env = mkTypeEnv tys,
|
|
| 1652 | - minf_exports = avails,
|
|
| 1653 | - minf_instances = error "getModuleInfo: instances for package module unimplemented",
|
|
| 1654 | - minf_iface = Just iface,
|
|
| 1655 | - minf_safe = getSafeMode $ mi_trust iface,
|
|
| 1656 | - minf_modBreaks = Nothing
|
|
| 1657 | - }))
|
|
| 1658 | - |
|
| 1659 | -availsToGlobalRdrEnv :: HasDebugCallStack => HscEnv -> Module -> [AvailInfo] -> IfGlobalRdrEnv
|
|
| 1660 | -availsToGlobalRdrEnv hsc_env mod avails
|
|
| 1661 | - = forceGlobalRdrEnv rdr_env
|
|
| 1662 | - -- See Note [Forcing GREInfo] in GHC.Types.GREInfo.
|
|
| 1663 | - where
|
|
| 1664 | - rdr_env = mkGlobalRdrEnv (gresFromAvails hsc_env (Just imp_spec) avails)
|
|
| 1665 | - -- We're building a GlobalRdrEnv as if the user imported
|
|
| 1666 | - -- all the specified modules into the global interactive module
|
|
| 1667 | - imp_spec = ImpSpec { is_decl = decl, is_item = ImpAll}
|
|
| 1668 | - decl = ImpDeclSpec { is_mod = mod, is_as = moduleName mod,
|
|
| 1669 | - is_qual = False, is_isboot = NotBoot, is_pkg_qual = NoPkgQual,
|
|
| 1670 | - is_dloc = srcLocSpan interactiveSrcLoc,
|
|
| 1671 | - is_level = NormalLevel }
|
|
| 1672 | - |
|
| 1673 | -getHomeModuleInfo :: HscEnv -> Module -> IO (Maybe ModuleInfo)
|
|
| 1674 | -getHomeModuleInfo hsc_env mdl =
|
|
| 1675 | - HUG.lookupHugByModule mdl (hsc_HUG hsc_env) >>= \case
|
|
| 1676 | - Nothing -> return Nothing
|
|
| 1677 | - Just hmi -> do
|
|
| 1678 | - let details = hm_details hmi
|
|
| 1679 | - iface = hm_iface hmi
|
|
| 1680 | - return (Just (ModuleInfo {
|
|
| 1681 | - minf_type_env = md_types details,
|
|
| 1682 | - minf_exports = md_exports details,
|
|
| 1683 | - -- NB: already forced. See Note [Forcing GREInfo] in GHC.Types.GREInfo.
|
|
| 1684 | - minf_instances = instEnvElts $ md_insts details,
|
|
| 1685 | - minf_iface = Just iface,
|
|
| 1686 | - minf_safe = getSafeMode $ mi_trust iface
|
|
| 1687 | - ,minf_modBreaks = getModBreaks hmi
|
|
| 1688 | - }))
|
|
| 1689 | - |
|
| 1690 | --- | The list of top-level entities defined in a module
|
|
| 1691 | -modInfoTyThings :: ModuleInfo -> [TyThing]
|
|
| 1692 | -modInfoTyThings minf = typeEnvElts (minf_type_env minf)
|
|
| 1693 | - |
|
| 1694 | -modInfoExports :: ModuleInfo -> [Name]
|
|
| 1695 | -modInfoExports minf = concatMap availNames $! minf_exports minf
|
|
| 1696 | - |
|
| 1697 | -modInfoExportsWithSelectors :: ModuleInfo -> [Name]
|
|
| 1698 | -modInfoExportsWithSelectors minf = concatMap availNames $! minf_exports minf
|
|
| 1699 | - |
|
| 1700 | --- | Returns the instances defined by the specified module.
|
|
| 1701 | --- Warning: currently unimplemented for package modules.
|
|
| 1702 | -modInfoInstances :: ModuleInfo -> [ClsInst]
|
|
| 1703 | -modInfoInstances = minf_instances
|
|
| 1704 | - |
|
| 1705 | -modInfoIsExportedName :: ModuleInfo -> Name -> Bool
|
|
| 1706 | -modInfoIsExportedName minf name = elemNameSet name (availsToNameSet (minf_exports minf))
|
|
| 1707 | - |
|
| 1708 | -mkNamePprCtxForModule ::
|
|
| 1709 | - GhcMonad m =>
|
|
| 1710 | - Module ->
|
|
| 1711 | - ModuleInfo ->
|
|
| 1712 | - m NamePprCtx
|
|
| 1713 | -mkNamePprCtxForModule mod minf = withSession $ \hsc_env -> do
|
|
| 1714 | - let name_ppr_ctx = mkNamePprCtx ptc (hsc_unit_env hsc_env) (availsToGlobalRdrEnv hsc_env mod (minf_exports minf))
|
|
| 1715 | - ptc = initPromotionTickContext (hsc_dflags hsc_env)
|
|
| 1716 | - return name_ppr_ctx
|
|
| 1717 | - |
|
| 1718 | -modInfoLookupName :: GhcMonad m =>
|
|
| 1719 | - ModuleInfo -> Name
|
|
| 1720 | - -> m (Maybe TyThing) -- XXX: returns a Maybe X
|
|
| 1721 | -modInfoLookupName minf name = withSession $ \hsc_env -> do
|
|
| 1722 | - case lookupTypeEnv (minf_type_env minf) name of
|
|
| 1723 | - Just tyThing -> return (Just tyThing)
|
|
| 1724 | - Nothing -> liftIO (lookupType hsc_env name)
|
|
| 1725 | - |
|
| 1726 | -modInfoIface :: ModuleInfo -> Maybe ModIface
|
|
| 1727 | -modInfoIface = minf_iface
|
|
| 1728 | - |
|
| 1729 | --- | Retrieve module safe haskell mode
|
|
| 1730 | -modInfoSafe :: ModuleInfo -> SafeHaskellMode
|
|
| 1731 | -modInfoSafe = minf_safe
|
|
| 1732 | - |
|
| 1733 | -modInfoModBreaks :: ModuleInfo -> Maybe ModBreaks
|
|
| 1734 | -modInfoModBreaks = minf_modBreaks
|
|
| 1735 | - |
|
| 1736 | 1572 | isDictonaryId :: Id -> Bool
|
| 1737 | 1573 | isDictonaryId id = isDictTy (idType id)
|
| 1738 | 1574 | |
| ... | ... | @@ -2063,7 +1899,7 @@ getGHCiMonad :: GhcMonad m => m Name |
| 2063 | 1899 | getGHCiMonad = fmap (ic_monad . hsc_IC) getSession
|
| 2064 | 1900 | |
| 2065 | 1901 | getHistorySpan :: GhcMonad m => History -> m SrcSpan
|
| 2066 | -getHistorySpan h = withSession $ \hsc_env -> liftIO $ GHC.Runtime.Eval.getHistorySpan hsc_env h
|
|
| 1902 | +getHistorySpan h = withSession $ \hsc_env -> liftIO $ GHC.Runtime.Eval.getHistorySpan (hsc_HUG hsc_env) h
|
|
| 2067 | 1903 | |
| 2068 | 1904 | obtainTermFromVal :: GhcMonad m => Int -> Bool -> Type -> a -> m Term
|
| 2069 | 1905 | obtainTermFromVal bound force ty a = withSession $ \hsc_env ->
|
| ... | ... | @@ -287,7 +287,7 @@ exprs_fvs :: [CoreExpr] -> FV |
| 287 | 287 | exprs_fvs exprs = mapUnionFV expr_fvs exprs
|
| 288 | 288 | |
| 289 | 289 | tickish_fvs :: CoreTickish -> FV
|
| 290 | -tickish_fvs (Breakpoint _ _ ids _) = FV.mkFVs ids
|
|
| 290 | +tickish_fvs (Breakpoint _ _ ids) = FV.mkFVs ids
|
|
| 291 | 291 | tickish_fvs _ = emptyFV
|
| 292 | 292 | |
| 293 | 293 | {- **********************************************************************
|
| ... | ... | @@ -759,8 +759,8 @@ freeVars = go |
| 759 | 759 | , AnnTick tickish expr2 )
|
| 760 | 760 | where
|
| 761 | 761 | expr2 = go expr
|
| 762 | - tickishFVs (Breakpoint _ _ ids _) = mkDVarSet ids
|
|
| 763 | - tickishFVs _ = emptyDVarSet
|
|
| 762 | + tickishFVs (Breakpoint _ _ ids) = mkDVarSet ids
|
|
| 763 | + tickishFVs _ = emptyDVarSet
|
|
| 764 | 764 | |
| 765 | 765 | go (Type ty) = (tyCoVarsOfTypeDSet ty, AnnType ty)
|
| 766 | 766 | go (Coercion co) = (tyCoVarsOfCoDSet co, AnnCoercion co) |
| ... | ... | @@ -897,8 +897,8 @@ lintCoreExpr (Cast expr co) |
| 897 | 897 | |
| 898 | 898 | lintCoreExpr (Tick tickish expr)
|
| 899 | 899 | = do { case tickish of
|
| 900 | - Breakpoint _ _ ids _ -> forM_ ids $ \id -> lintIdOcc id 0
|
|
| 901 | - _ -> return ()
|
|
| 900 | + Breakpoint _ _ ids -> forM_ ids $ \id -> lintIdOcc id 0
|
|
| 901 | + _ -> return ()
|
|
| 902 | 902 | ; markAllJoinsBadIf block_joins $ lintCoreExpr expr }
|
| 903 | 903 | where
|
| 904 | 904 | block_joins = not (tickish `tickishScopesLike` SoftScope)
|
| ... | ... | @@ -198,11 +198,10 @@ eqDeBruijnExpr (D env1 e1) (D env2 e2) = go e1 e2 where |
| 198 | 198 | |
| 199 | 199 | eqDeBruijnTickish :: DeBruijn CoreTickish -> DeBruijn CoreTickish -> Bool
|
| 200 | 200 | eqDeBruijnTickish (D env1 t1) (D env2 t2) = go t1 t2 where
|
| 201 | - go (Breakpoint lext lid lids lmod) (Breakpoint rext rid rids rmod)
|
|
| 201 | + go (Breakpoint lext lid lids) (Breakpoint rext rid rids)
|
|
| 202 | 202 | = lid == rid
|
| 203 | 203 | && D env1 lids == D env2 rids
|
| 204 | 204 | && lext == rext
|
| 205 | - && lmod == rmod
|
|
| 206 | 205 | go l r = l == r
|
| 207 | 206 | |
| 208 | 207 | -- Compares for equality, modulo alpha
|
| ... | ... | @@ -2501,7 +2501,7 @@ occAnal env (Tick tickish body) |
| 2501 | 2501 | -- For a non-soft tick scope, we can inline lambdas only, so we
|
| 2502 | 2502 | -- abandon tail calls, and do markAllInsideLam too: usage_lam
|
| 2503 | 2503 | |
| 2504 | - | Breakpoint _ _ ids _ <- tickish
|
|
| 2504 | + | Breakpoint _ _ ids <- tickish
|
|
| 2505 | 2505 | = -- Never substitute for any of the Ids in a Breakpoint
|
| 2506 | 2506 | addManyOccs usage_lam (mkVarSet ids)
|
| 2507 | 2507 |
| ... | ... | @@ -1461,8 +1461,8 @@ simplTick env tickish expr cont |
| 1461 | 1461 | |
| 1462 | 1462 | |
| 1463 | 1463 | simplTickish env tickish
|
| 1464 | - | Breakpoint ext n ids modl <- tickish
|
|
| 1465 | - = Breakpoint ext n (mapMaybe (getDoneId . substId env) ids) modl
|
|
| 1464 | + | Breakpoint ext bid ids <- tickish
|
|
| 1465 | + = Breakpoint ext bid (mapMaybe (getDoneId . substId env) ids)
|
|
| 1466 | 1466 | | otherwise = tickish
|
| 1467 | 1467 | |
| 1468 | 1468 | -- Push type application and coercion inside a tick
|
| ... | ... | @@ -31,6 +31,7 @@ import GHC.Prelude |
| 31 | 31 | |
| 32 | 32 | import GHC.Core
|
| 33 | 33 | import GHC.Core.Stats (exprStats)
|
| 34 | +import GHC.Types.Breakpoint
|
|
| 34 | 35 | import GHC.Types.Fixity (LexicalFixity(..))
|
| 35 | 36 | import GHC.Types.Literal( pprLiteral )
|
| 36 | 37 | import GHC.Types.Name( pprInfixName, pprPrefixName )
|
| ... | ... | @@ -694,10 +695,10 @@ instance Outputable (XTickishId pass) => Outputable (GenTickish pass) where |
| 694 | 695 | ppr modl, comma,
|
| 695 | 696 | ppr ix,
|
| 696 | 697 | text ">"]
|
| 697 | - ppr (Breakpoint _ext ix vars modl) =
|
|
| 698 | + ppr (Breakpoint _ext bid vars) =
|
|
| 698 | 699 | hcat [text "break<",
|
| 699 | - ppr modl, comma,
|
|
| 700 | - ppr ix,
|
|
| 700 | + ppr (bi_tick_mod bid), comma,
|
|
| 701 | + ppr (bi_tick_index bid),
|
|
| 701 | 702 | text ">",
|
| 702 | 703 | parens (hcat (punctuate comma (map ppr vars)))]
|
| 703 | 704 | ppr (ProfNote { profNoteCC = cc,
|
| ... | ... | @@ -602,8 +602,8 @@ substDVarSet subst@(Subst _ _ tv_env cv_env) fvs |
| 602 | 602 | ------------------
|
| 603 | 603 | -- | Drop free vars from the breakpoint if they have a non-variable substitution.
|
| 604 | 604 | substTickish :: Subst -> CoreTickish -> CoreTickish
|
| 605 | -substTickish subst (Breakpoint ext n ids modl)
|
|
| 606 | - = Breakpoint ext n (mapMaybe do_one ids) modl
|
|
| 605 | +substTickish subst (Breakpoint ext bid ids)
|
|
| 606 | + = Breakpoint ext bid (mapMaybe do_one ids)
|
|
| 607 | 607 | where
|
| 608 | 608 | do_one = getIdFromTrivialExpr_maybe . lookupIdSubst subst
|
| 609 | 609 |
| ... | ... | @@ -235,8 +235,8 @@ tidyAlt env (Alt con vs rhs) |
| 235 | 235 | |
| 236 | 236 | ------------ Tickish --------------
|
| 237 | 237 | tidyTickish :: TidyEnv -> CoreTickish -> CoreTickish
|
| 238 | -tidyTickish env (Breakpoint ext ix ids modl)
|
|
| 239 | - = Breakpoint ext ix (map (tidyVarOcc env) ids) modl
|
|
| 238 | +tidyTickish env (Breakpoint ext bid ids)
|
|
| 239 | + = Breakpoint ext bid (map (tidyVarOcc env) ids)
|
|
| 240 | 240 | tidyTickish _ other_tickish = other_tickish
|
| 241 | 241 | |
| 242 | 242 | ------------ Rules --------------
|
| ... | ... | @@ -2492,11 +2492,10 @@ cheapEqExpr' ignoreTick e1 e2 |
| 2492 | 2492 | |
| 2493 | 2493 | -- Used by diffBinds, which is itself only used in GHC.Core.Lint.lintAnnots
|
| 2494 | 2494 | eqTickish :: RnEnv2 -> CoreTickish -> CoreTickish -> Bool
|
| 2495 | -eqTickish env (Breakpoint lext lid lids lmod) (Breakpoint rext rid rids rmod)
|
|
| 2495 | +eqTickish env (Breakpoint lext lid lids) (Breakpoint rext rid rids)
|
|
| 2496 | 2496 | = lid == rid &&
|
| 2497 | 2497 | map (rnOccL env) lids == map (rnOccR env) rids &&
|
| 2498 | - lext == rext &&
|
|
| 2499 | - lmod == rmod
|
|
| 2498 | + lext == rext
|
|
| 2500 | 2499 | eqTickish _ l r = l == r
|
| 2501 | 2500 | |
| 2502 | 2501 | -- | Finds differences between core bindings, see @diffExpr@.
|
| ... | ... | @@ -586,8 +586,8 @@ toIfaceTickish (ProfNote cc tick push) = IfaceSCC cc tick push |
| 586 | 586 | toIfaceTickish (HpcTick modl ix) = IfaceHpcTick modl ix
|
| 587 | 587 | toIfaceTickish (SourceNote src (LexicalFastString names)) =
|
| 588 | 588 | IfaceSource src names
|
| 589 | -toIfaceTickish (Breakpoint _ ix fv m) =
|
|
| 590 | - IfaceBreakpoint ix (toIfaceVar <$> fv) m
|
|
| 589 | +toIfaceTickish (Breakpoint _ ix fv) =
|
|
| 590 | + IfaceBreakpoint ix (toIfaceVar <$> fv)
|
|
| 591 | 591 | |
| 592 | 592 | ---------------------
|
| 593 | 593 | toIfaceBind :: Bind Id -> IfaceBinding IfaceLetBndr
|
| ... | ... | @@ -643,10 +643,10 @@ coreToStgArgs (arg : args) = do -- Non-type argument |
| 643 | 643 | coreToStgTick :: Type -- type of the ticked expression
|
| 644 | 644 | -> CoreTickish
|
| 645 | 645 | -> StgTickish
|
| 646 | -coreToStgTick _ty (HpcTick m i) = HpcTick m i
|
|
| 647 | -coreToStgTick _ty (SourceNote span nm) = SourceNote span nm
|
|
| 648 | -coreToStgTick _ty (ProfNote cc cnt scope) = ProfNote cc cnt scope
|
|
| 649 | -coreToStgTick !ty (Breakpoint _ bid fvs modl) = Breakpoint ty bid fvs modl
|
|
| 646 | +coreToStgTick _ty (HpcTick m i) = HpcTick m i
|
|
| 647 | +coreToStgTick _ty (SourceNote span nm) = SourceNote span nm
|
|
| 648 | +coreToStgTick _ty (ProfNote cc cnt scope) = ProfNote cc cnt scope
|
|
| 649 | +coreToStgTick !ty (Breakpoint _ bid fvs) = Breakpoint ty bid fvs
|
|
| 650 | 650 | |
| 651 | 651 | -- ---------------------------------------------------------------------------
|
| 652 | 652 | -- The magic for lets:
|
| ... | ... | @@ -842,9 +842,9 @@ cpeRhsE env (Tick tickish expr) |
| 842 | 842 | = do { body <- cpeBodyNF env expr
|
| 843 | 843 | ; return (emptyFloats, mkTick tickish' body) }
|
| 844 | 844 | where
|
| 845 | - tickish' | Breakpoint ext n fvs modl <- tickish
|
|
| 845 | + tickish' | Breakpoint ext bid fvs <- tickish
|
|
| 846 | 846 | -- See also 'substTickish'
|
| 847 | - = Breakpoint ext n (map (getIdFromTrivialExpr . lookupCorePrepEnv env) fvs) modl
|
|
| 847 | + = Breakpoint ext bid (map (getIdFromTrivialExpr . lookupCorePrepEnv env) fvs)
|
|
| 848 | 848 | | otherwise
|
| 849 | 849 | = tickish
|
| 850 | 850 |
| 1 | +{-# LANGUAGE LambdaCase #-}
|
|
| 2 | + |
|
| 3 | +-- | GHC API utilities for inspecting the GHC session
|
|
| 4 | +module GHC.Driver.Session.Inspect where
|
|
| 5 | + |
|
| 6 | +import GHC.Prelude
|
|
| 7 | +import GHC.Data.Maybe
|
|
| 8 | +import Control.Monad
|
|
| 9 | + |
|
| 10 | +import GHC.ByteCode.Types
|
|
| 11 | +import GHC.Core.FamInstEnv
|
|
| 12 | +import GHC.Core.InstEnv
|
|
| 13 | +import GHC.Driver.Env
|
|
| 14 | +import GHC.Driver.Main
|
|
| 15 | +import GHC.Driver.Monad
|
|
| 16 | +import GHC.Driver.Session
|
|
| 17 | +import GHC.Rename.Names
|
|
| 18 | +import GHC.Runtime.Context
|
|
| 19 | +import GHC.Runtime.Interpreter
|
|
| 20 | +import GHC.Types.Avail
|
|
| 21 | +import GHC.Types.Name
|
|
| 22 | +import GHC.Types.Name.Ppr
|
|
| 23 | +import GHC.Types.Name.Reader
|
|
| 24 | +import GHC.Types.Name.Set
|
|
| 25 | +import GHC.Types.PkgQual
|
|
| 26 | +import GHC.Types.SafeHaskell
|
|
| 27 | +import GHC.Types.SrcLoc
|
|
| 28 | +import GHC.Types.TyThing
|
|
| 29 | +import GHC.Types.TypeEnv
|
|
| 30 | +import GHC.Unit.External
|
|
| 31 | +import GHC.Unit.Home.ModInfo
|
|
| 32 | +import GHC.Unit.Module
|
|
| 33 | +import GHC.Unit.Module.Graph
|
|
| 34 | +import GHC.Unit.Module.ModDetails
|
|
| 35 | +import GHC.Unit.Module.ModIface
|
|
| 36 | +import GHC.Utils.Misc
|
|
| 37 | +import GHC.Utils.Outputable
|
|
| 38 | +import qualified GHC.Unit.Home.Graph as HUG
|
|
| 39 | + |
|
| 40 | +-- %************************************************************************
|
|
| 41 | +-- %* *
|
|
| 42 | +-- Inspecting the session
|
|
| 43 | +-- %* *
|
|
| 44 | +-- %************************************************************************
|
|
| 45 | + |
|
| 46 | +-- | Get the module dependency graph.
|
|
| 47 | +getModuleGraph :: GhcMonad m => m ModuleGraph -- ToDo: DiGraph ModSummary
|
|
| 48 | +getModuleGraph = liftM hsc_mod_graph getSession
|
|
| 49 | + |
|
| 50 | +{-# DEPRECATED isLoaded "Prefer 'isLoadedModule' and 'isLoadedHomeModule'" #-}
|
|
| 51 | +-- | Return @True@ \<==> module is loaded.
|
|
| 52 | +isLoaded :: GhcMonad m => ModuleName -> m Bool
|
|
| 53 | +isLoaded m = withSession $ \hsc_env -> liftIO $ do
|
|
| 54 | + hmis <- HUG.lookupAllHug (hsc_HUG hsc_env) m
|
|
| 55 | + return $! not (null hmis)
|
|
| 56 | + |
|
| 57 | +-- | Check whether a 'ModuleName' is found in the 'HomePackageTable'
|
|
| 58 | +-- for the given 'UnitId'.
|
|
| 59 | +isLoadedModule :: GhcMonad m => UnitId -> ModuleName -> m Bool
|
|
| 60 | +isLoadedModule uid m = withSession $ \hsc_env -> liftIO $ do
|
|
| 61 | + hmi <- HUG.lookupHug (hsc_HUG hsc_env) uid m
|
|
| 62 | + return $! isJust hmi
|
|
| 63 | + |
|
| 64 | +-- | Check whether 'Module' is part of the 'HomeUnitGraph'.
|
|
| 65 | +--
|
|
| 66 | +-- Similar to 'isLoadedModule', but for 'Module's.
|
|
| 67 | +isLoadedHomeModule :: GhcMonad m => Module -> m Bool
|
|
| 68 | +isLoadedHomeModule m = withSession $ \hsc_env -> liftIO $ do
|
|
| 69 | + hmi <- HUG.lookupHugByModule m (hsc_HUG hsc_env)
|
|
| 70 | + return $! isJust hmi
|
|
| 71 | + |
|
| 72 | +-- | Return the bindings for the current interactive session.
|
|
| 73 | +getBindings :: GhcMonad m => m [TyThing]
|
|
| 74 | +getBindings = withSession $ \hsc_env ->
|
|
| 75 | + return $ icInScopeTTs $ hsc_IC hsc_env
|
|
| 76 | + |
|
| 77 | +-- | Return the instances for the current interactive session.
|
|
| 78 | +getInsts :: GhcMonad m => m ([ClsInst], [FamInst])
|
|
| 79 | +getInsts = withSession $ \hsc_env ->
|
|
| 80 | + let (inst_env, fam_env) = ic_instances (hsc_IC hsc_env)
|
|
| 81 | + in return (instEnvElts inst_env, fam_env)
|
|
| 82 | + |
|
| 83 | +getNamePprCtx :: GhcMonad m => m NamePprCtx
|
|
| 84 | +getNamePprCtx = withSession $ \hsc_env -> do
|
|
| 85 | + return $ icNamePprCtx (hsc_unit_env hsc_env) (hsc_IC hsc_env)
|
|
| 86 | + |
|
| 87 | +-- | Container for information about a 'Module'.
|
|
| 88 | +data ModuleInfo = ModuleInfo {
|
|
| 89 | + minf_type_env :: TypeEnv,
|
|
| 90 | + minf_exports :: [AvailInfo],
|
|
| 91 | + minf_instances :: [ClsInst],
|
|
| 92 | + minf_iface :: Maybe ModIface,
|
|
| 93 | + minf_safe :: SafeHaskellMode,
|
|
| 94 | + minf_modBreaks :: Maybe ModBreaks
|
|
| 95 | + }
|
|
| 96 | + -- We don't want HomeModInfo here, because a ModuleInfo applies
|
|
| 97 | + -- to package modules too.
|
|
| 98 | + |
|
| 99 | +-- | Request information about a loaded 'Module'
|
|
| 100 | +getModuleInfo :: GhcMonad m => Module -> m (Maybe ModuleInfo) -- XXX: Maybe X
|
|
| 101 | +getModuleInfo mdl = withSession $ \hsc_env -> do
|
|
| 102 | + if HUG.memberHugUnit (moduleUnit mdl) (hsc_HUG hsc_env)
|
|
| 103 | + then liftIO $ getHomeModuleInfo hsc_env mdl
|
|
| 104 | + else liftIO $ getPackageModuleInfo hsc_env mdl
|
|
| 105 | + |
|
| 106 | +getPackageModuleInfo :: HscEnv -> Module -> IO (Maybe ModuleInfo)
|
|
| 107 | +getPackageModuleInfo hsc_env mdl
|
|
| 108 | + = do eps <- hscEPS hsc_env
|
|
| 109 | + iface <- hscGetModuleInterface hsc_env mdl
|
|
| 110 | + let
|
|
| 111 | + avails = mi_exports iface
|
|
| 112 | + pte = eps_PTE eps
|
|
| 113 | + tys = [ ty | name <- concatMap availNames avails,
|
|
| 114 | + Just ty <- [lookupTypeEnv pte name] ]
|
|
| 115 | + |
|
| 116 | + return (Just (ModuleInfo {
|
|
| 117 | + minf_type_env = mkTypeEnv tys,
|
|
| 118 | + minf_exports = avails,
|
|
| 119 | + minf_instances = error "getModuleInfo: instances for package module unimplemented",
|
|
| 120 | + minf_iface = Just iface,
|
|
| 121 | + minf_safe = getSafeMode $ mi_trust iface,
|
|
| 122 | + minf_modBreaks = Nothing
|
|
| 123 | + }))
|
|
| 124 | + |
|
| 125 | +availsToGlobalRdrEnv :: HasDebugCallStack => HscEnv -> Module -> [AvailInfo] -> IfGlobalRdrEnv
|
|
| 126 | +availsToGlobalRdrEnv hsc_env mod avails
|
|
| 127 | + = forceGlobalRdrEnv rdr_env
|
|
| 128 | + -- See Note [Forcing GREInfo] in GHC.Types.GREInfo.
|
|
| 129 | + where
|
|
| 130 | + rdr_env = mkGlobalRdrEnv (gresFromAvails hsc_env (Just imp_spec) avails)
|
|
| 131 | + -- We're building a GlobalRdrEnv as if the user imported
|
|
| 132 | + -- all the specified modules into the global interactive module
|
|
| 133 | + imp_spec = ImpSpec { is_decl = decl, is_item = ImpAll}
|
|
| 134 | + decl = ImpDeclSpec { is_mod = mod, is_as = moduleName mod,
|
|
| 135 | + is_qual = False, is_isboot = NotBoot, is_pkg_qual = NoPkgQual,
|
|
| 136 | + is_dloc = srcLocSpan interactiveSrcLoc,
|
|
| 137 | + is_level = NormalLevel }
|
|
| 138 | + |
|
| 139 | +getHomeModuleInfo :: HscEnv -> Module -> IO (Maybe ModuleInfo)
|
|
| 140 | +getHomeModuleInfo hsc_env mdl =
|
|
| 141 | + HUG.lookupHugByModule mdl (hsc_HUG hsc_env) >>= \case
|
|
| 142 | + Nothing -> return Nothing
|
|
| 143 | + Just hmi -> do
|
|
| 144 | + let details = hm_details hmi
|
|
| 145 | + iface = hm_iface hmi
|
|
| 146 | + return (Just (ModuleInfo {
|
|
| 147 | + minf_type_env = md_types details,
|
|
| 148 | + minf_exports = md_exports details,
|
|
| 149 | + -- NB: already forced. See Note [Forcing GREInfo] in GHC.Types.GREInfo.
|
|
| 150 | + minf_instances = instEnvElts $ md_insts details,
|
|
| 151 | + minf_iface = Just iface,
|
|
| 152 | + minf_safe = getSafeMode $ mi_trust iface,
|
|
| 153 | + minf_modBreaks = getModBreaks hmi
|
|
| 154 | + }))
|
|
| 155 | + |
|
| 156 | +-- | The list of top-level entities defined in a module
|
|
| 157 | +modInfoTyThings :: ModuleInfo -> [TyThing]
|
|
| 158 | +modInfoTyThings minf = typeEnvElts (minf_type_env minf)
|
|
| 159 | + |
|
| 160 | +modInfoExports :: ModuleInfo -> [Name]
|
|
| 161 | +modInfoExports minf = concatMap availNames $! minf_exports minf
|
|
| 162 | + |
|
| 163 | +modInfoExportsWithSelectors :: ModuleInfo -> [Name]
|
|
| 164 | +modInfoExportsWithSelectors minf = concatMap availNames $! minf_exports minf
|
|
| 165 | + |
|
| 166 | +-- | Returns the instances defined by the specified module.
|
|
| 167 | +-- Warning: currently unimplemented for package modules.
|
|
| 168 | +modInfoInstances :: ModuleInfo -> [ClsInst]
|
|
| 169 | +modInfoInstances = minf_instances
|
|
| 170 | + |
|
| 171 | +modInfoIsExportedName :: ModuleInfo -> Name -> Bool
|
|
| 172 | +modInfoIsExportedName minf name = elemNameSet name (availsToNameSet (minf_exports minf))
|
|
| 173 | + |
|
| 174 | +mkNamePprCtxForModule ::
|
|
| 175 | + GhcMonad m =>
|
|
| 176 | + Module ->
|
|
| 177 | + ModuleInfo ->
|
|
| 178 | + m NamePprCtx
|
|
| 179 | +mkNamePprCtxForModule mod minf = withSession $ \hsc_env -> do
|
|
| 180 | + let name_ppr_ctx = mkNamePprCtx ptc (hsc_unit_env hsc_env) (availsToGlobalRdrEnv hsc_env mod (minf_exports minf))
|
|
| 181 | + ptc = initPromotionTickContext (hsc_dflags hsc_env)
|
|
| 182 | + return name_ppr_ctx
|
|
| 183 | + |
|
| 184 | +modInfoLookupName :: GhcMonad m =>
|
|
| 185 | + ModuleInfo -> Name
|
|
| 186 | + -> m (Maybe TyThing) -- XXX: returns a Maybe X
|
|
| 187 | +modInfoLookupName minf name = withSession $ \hsc_env -> do
|
|
| 188 | + case lookupTypeEnv (minf_type_env minf) name of
|
|
| 189 | + Just tyThing -> return (Just tyThing)
|
|
| 190 | + Nothing -> liftIO (lookupType hsc_env name)
|
|
| 191 | + |
|
| 192 | +modInfoIface :: ModuleInfo -> Maybe ModIface
|
|
| 193 | +modInfoIface = minf_iface
|
|
| 194 | + |
|
| 195 | +-- | Retrieve module safe haskell mode
|
|
| 196 | +modInfoSafe :: ModuleInfo -> SafeHaskellMode
|
|
| 197 | +modInfoSafe = minf_safe
|
|
| 198 | + |
|
| 199 | +modInfoModBreaks :: ModuleInfo -> Maybe ModBreaks
|
|
| 200 | +modInfoModBreaks = minf_modBreaks
|
|
| 201 | + |
| ... | ... | @@ -35,6 +35,7 @@ import GHC.Driver.Flags (DumpFlag(..)) |
| 35 | 35 | import GHC.Utils.Outputable as Outputable
|
| 36 | 36 | import GHC.Utils.Panic
|
| 37 | 37 | import GHC.Utils.Logger
|
| 38 | +import GHC.Types.Breakpoint
|
|
| 38 | 39 | import GHC.Types.SrcLoc
|
| 39 | 40 | import GHC.Types.Basic
|
| 40 | 41 | import GHC.Types.Id
|
| ... | ... | @@ -1235,7 +1236,7 @@ mkTickish boxLabel countEntries topOnly pos fvs decl_path = do |
| 1235 | 1236 | |
| 1236 | 1237 | Breakpoints -> do
|
| 1237 | 1238 | i <- addMixEntry me
|
| 1238 | - pure (Breakpoint noExtField i ids (this_mod env))
|
|
| 1239 | + pure (Breakpoint noExtField (BreakpointId (this_mod env) i) ids)
|
|
| 1239 | 1240 | |
| 1240 | 1241 | SourceNotes | RealSrcSpan pos' _ <- pos ->
|
| 1241 | 1242 | return $ SourceNote pos' $ LexicalFastString cc_name
|
| ... | ... | @@ -56,6 +56,7 @@ import GHC.Data.BooleanFormula (pprBooleanFormula, isTrue) |
| 56 | 56 | |
| 57 | 57 | import GHC.Builtin.Names ( unrestrictedFunTyConKey, liftedTypeKindTyConKey,
|
| 58 | 58 | constraintKindTyConKey )
|
| 59 | +import GHC.Types.Breakpoint
|
|
| 59 | 60 | import GHC.Types.Unique ( hasKey )
|
| 60 | 61 | import GHC.Iface.Type
|
| 61 | 62 | import GHC.Iface.Recomp.Binary
|
| ... | ... | @@ -699,7 +700,7 @@ data IfaceTickish |
| 699 | 700 | = IfaceHpcTick Module Int -- from HpcTick x
|
| 700 | 701 | | IfaceSCC CostCentre Bool Bool -- from ProfNote
|
| 701 | 702 | | IfaceSource RealSrcSpan FastString -- from SourceNote
|
| 702 | - | IfaceBreakpoint Int [IfaceExpr] Module -- from Breakpoint
|
|
| 703 | + | IfaceBreakpoint BreakpointId [IfaceExpr] -- from Breakpoint
|
|
| 703 | 704 | |
| 704 | 705 | data IfaceAlt = IfaceAlt IfaceConAlt [IfLclName] IfaceExpr
|
| 705 | 706 | -- Note: IfLclName, not IfaceBndr (and same with the case binder)
|
| ... | ... | @@ -1848,7 +1849,7 @@ pprIfaceTickish (IfaceSCC cc tick scope) |
| 1848 | 1849 | = braces (pprCostCentreCore cc <+> ppr tick <+> ppr scope)
|
| 1849 | 1850 | pprIfaceTickish (IfaceSource src _names)
|
| 1850 | 1851 | = braces (pprUserRealSpan True src)
|
| 1851 | -pprIfaceTickish (IfaceBreakpoint m ix fvs)
|
|
| 1852 | +pprIfaceTickish (IfaceBreakpoint (BreakpointId m ix) fvs)
|
|
| 1852 | 1853 | = braces (text "break" <+> ppr m <+> ppr ix <+> ppr fvs)
|
| 1853 | 1854 | |
| 1854 | 1855 | ------------------
|
| ... | ... | @@ -2198,7 +2199,7 @@ freeNamesIfaceTyConParent (IfDataInstance ax tc tys) |
| 2198 | 2199 | = unitNameSet ax &&& freeNamesIfTc tc &&& freeNamesIfAppArgs tys
|
| 2199 | 2200 | |
| 2200 | 2201 | freeNamesIfTickish :: IfaceTickish -> NameSet
|
| 2201 | -freeNamesIfTickish (IfaceBreakpoint _ fvs _) =
|
|
| 2202 | +freeNamesIfTickish (IfaceBreakpoint _ fvs) =
|
|
| 2202 | 2203 | fnList freeNamesIfExpr fvs
|
| 2203 | 2204 | freeNamesIfTickish _ = emptyNameSet
|
| 2204 | 2205 | |
| ... | ... | @@ -2919,7 +2920,7 @@ instance Binary IfaceTickish where |
| 2919 | 2920 | put_ bh (srcSpanEndLine src)
|
| 2920 | 2921 | put_ bh (srcSpanEndCol src)
|
| 2921 | 2922 | put_ bh name
|
| 2922 | - put_ bh (IfaceBreakpoint m ix fvs) = do
|
|
| 2923 | + put_ bh (IfaceBreakpoint (BreakpointId m ix) fvs) = do
|
|
| 2923 | 2924 | putByte bh 3
|
| 2924 | 2925 | put_ bh m
|
| 2925 | 2926 | put_ bh ix
|
| ... | ... | @@ -2947,7 +2948,7 @@ instance Binary IfaceTickish where |
| 2947 | 2948 | 3 -> do m <- get bh
|
| 2948 | 2949 | ix <- get bh
|
| 2949 | 2950 | fvs <- get bh
|
| 2950 | - return (IfaceBreakpoint m ix fvs)
|
|
| 2951 | + return (IfaceBreakpoint (BreakpointId m ix) fvs)
|
|
| 2951 | 2952 | _ -> panic ("get IfaceTickish " ++ show h)
|
| 2952 | 2953 | |
| 2953 | 2954 | instance Binary IfaceConAlt where
|
| ... | ... | @@ -3206,7 +3207,7 @@ instance NFData IfaceTickish where |
| 3206 | 3207 | IfaceHpcTick m i -> rnf m `seq` rnf i
|
| 3207 | 3208 | IfaceSCC cc b1 b2 -> rnf cc `seq` rnf b1 `seq` rnf b2
|
| 3208 | 3209 | IfaceSource src str -> rnf src `seq` rnf str
|
| 3209 | - IfaceBreakpoint m i fvs -> rnf m `seq` rnf i `seq` rnf fvs
|
|
| 3210 | + IfaceBreakpoint i fvs -> rnf i `seq` rnf fvs
|
|
| 3210 | 3211 | |
| 3211 | 3212 | instance NFData IfaceConAlt where
|
| 3212 | 3213 | rnf = \case
|
| ... | ... | @@ -955,7 +955,7 @@ dffvExpr :: CoreExpr -> DFFV () |
| 955 | 955 | dffvExpr (Var v) = insert v
|
| 956 | 956 | dffvExpr (App e1 e2) = dffvExpr e1 >> dffvExpr e2
|
| 957 | 957 | dffvExpr (Lam v e) = extendScope v (dffvExpr e)
|
| 958 | -dffvExpr (Tick (Breakpoint _ _ ids _) e) = mapM_ insert ids >> dffvExpr e
|
|
| 958 | +dffvExpr (Tick (Breakpoint _ _ ids) e) = mapM_ insert ids >> dffvExpr e
|
|
| 959 | 959 | dffvExpr (Tick _other e) = dffvExpr e
|
| 960 | 960 | dffvExpr (Cast e _) = dffvExpr e
|
| 961 | 961 | dffvExpr (Let (NonRec x r) e) = dffvBind (x,r) >> extendScope x (dffvExpr e)
|
| ... | ... | @@ -1732,9 +1732,9 @@ tcIfaceTickish :: IfaceTickish -> IfL CoreTickish |
| 1732 | 1732 | tcIfaceTickish (IfaceHpcTick modl ix) = return (HpcTick modl ix)
|
| 1733 | 1733 | tcIfaceTickish (IfaceSCC cc tick push) = return (ProfNote cc tick push)
|
| 1734 | 1734 | tcIfaceTickish (IfaceSource src name) = return (SourceNote src (LexicalFastString name))
|
| 1735 | -tcIfaceTickish (IfaceBreakpoint ix fvs modl) = do
|
|
| 1735 | +tcIfaceTickish (IfaceBreakpoint bid fvs) = do
|
|
| 1736 | 1736 | fvs' <- mapM tcIfaceExpr fvs
|
| 1737 | - return (Breakpoint NoExtField ix [f | Var f <- fvs'] modl)
|
|
| 1737 | + return (Breakpoint NoExtField bid [f | Var f <- fvs'])
|
|
| 1738 | 1738 | |
| 1739 | 1739 | -------------------------
|
| 1740 | 1740 | tcIfaceLit :: Literal -> IfL Literal
|
| 1 | + |
|
| 1 | 2 | -- | GHC API debugger module for finding and setting breakpoints.
|
| 2 | 3 | --
|
| 3 | 4 | -- This module is user facing and is at least used by `GHCi` and `ghc-debugger`
|
| 4 | 5 | -- to find and set breakpoints.
|
| 5 | 6 | module GHC.Runtime.Debugger.Breakpoints where
|
| 6 | 7 | |
| 8 | +import GHC.Prelude
|
|
| 9 | + |
|
| 7 | 10 | import Control.Monad.Catch
|
| 8 | 11 | import Control.Monad
|
| 9 | 12 | import Data.Array
|
| ... | ... | @@ -13,10 +16,18 @@ import Data.Maybe |
| 13 | 16 | import qualified Data.List.NonEmpty as NE
|
| 14 | 17 | import qualified Data.Semigroup as S
|
| 15 | 18 | |
| 16 | -import GHC
|
|
| 17 | -import GHC.Prelude
|
|
| 19 | +import GHC.ByteCode.Types (BreakIndex, ModBreaks(..))
|
|
| 20 | +import GHC.Driver.Env
|
|
| 21 | +import GHC.Driver.Monad
|
|
| 22 | +import GHC.Driver.Session.Inspect
|
|
| 23 | +import GHC.Runtime.Eval
|
|
| 18 | 24 | import GHC.Runtime.Eval.Utils
|
| 25 | +import GHC.Types.Name
|
|
| 19 | 26 | import GHC.Types.SrcLoc
|
| 27 | +import GHC.Types.Breakpoint
|
|
| 28 | +import GHC.Unit.Module
|
|
| 29 | +import GHC.Unit.Module.Graph
|
|
| 30 | +import GHC.Unit.Module.ModSummary
|
|
| 20 | 31 | import GHC.Utils.Outputable
|
| 21 | 32 | import GHC.Utils.Panic
|
| 22 | 33 | import qualified GHC.Data.Strict as Strict
|
| ... | ... | @@ -44,10 +55,10 @@ findBreakByLine line arr |
| 44 | 55 | ticks = arr ! line
|
| 45 | 56 | |
| 46 | 57 | starts_here = [ (ix,pan) | (ix, pan) <- ticks,
|
| 47 | - GHC.srcSpanStartLine pan == line ]
|
|
| 58 | + srcSpanStartLine pan == line ]
|
|
| 48 | 59 | |
| 49 | 60 | (comp, incomp) = partition ends_here starts_here
|
| 50 | - where ends_here (_,pan) = GHC.srcSpanEndLine pan == line
|
|
| 61 | + where ends_here (_,pan) = srcSpanEndLine pan == line
|
|
| 51 | 62 | |
| 52 | 63 | -- | Find a breakpoint in the 'TickArray' of a module, given a line number and a column coordinate.
|
| 53 | 64 | findBreakByCoord :: (Int, Int) -> TickArray -> Maybe (BreakIndex, RealSrcSpan)
|
| ... | ... | @@ -63,8 +74,8 @@ findBreakByCoord (line, col) arr |
| 63 | 74 | contains = [ tick | tick@(_,pan) <- ticks, RealSrcSpan pan Strict.Nothing `spans` (line,col) ]
|
| 64 | 75 | |
| 65 | 76 | after_here = [ tick | tick@(_,pan) <- ticks,
|
| 66 | - GHC.srcSpanStartLine pan == line,
|
|
| 67 | - GHC.srcSpanStartCol pan >= col ]
|
|
| 77 | + srcSpanStartLine pan == line,
|
|
| 78 | + srcSpanStartCol pan >= col ]
|
|
| 68 | 79 | |
| 69 | 80 | leftmostLargestRealSrcSpan :: RealSrcSpan -> RealSrcSpan -> Ordering
|
| 70 | 81 | leftmostLargestRealSrcSpan = on compare realSrcSpanStart S.<> on (flip compare) realSrcSpanEnd
|
| ... | ... | @@ -112,7 +123,7 @@ resolveFunctionBreakpoint inp = do |
| 112 | 123 | Nothing -> do
|
| 113 | 124 | -- No errors found, go and return the module info
|
| 114 | 125 | let mod = fromMaybe (panic "resolveFunctionBreakpoint") mb_mod
|
| 115 | - mb_mod_info <- GHC.getModuleInfo mod
|
|
| 126 | + mb_mod_info <- getModuleInfo mod
|
|
| 116 | 127 | case mb_mod_info of
|
| 117 | 128 | Nothing -> pure . Left $
|
| 118 | 129 | text "Could not find ModuleInfo of " <> ppr mod
|
| ... | ... | @@ -120,16 +131,16 @@ resolveFunctionBreakpoint inp = do |
| 120 | 131 | where
|
| 121 | 132 | -- Try to lookup the module for an identifier that is in scope.
|
| 122 | 133 | -- `parseName` throws an exception, if the identifier is not in scope
|
| 123 | - lookupModuleInscope :: GHC.GhcMonad m => String -> m (Maybe Module)
|
|
| 134 | + lookupModuleInscope :: GhcMonad m => String -> m (Maybe Module)
|
|
| 124 | 135 | lookupModuleInscope mod_top_lvl = do
|
| 125 | - names <- GHC.parseName mod_top_lvl
|
|
| 126 | - pure $ Just $ NE.head $ GHC.nameModule <$> names
|
|
| 136 | + names <- parseName mod_top_lvl
|
|
| 137 | + pure $ Just $ NE.head $ nameModule <$> names
|
|
| 127 | 138 | |
| 128 | 139 | -- Lookup the Module of a module name in the module graph
|
| 129 | - lookupModuleInGraph :: GHC.GhcMonad m => String -> m (Maybe Module)
|
|
| 140 | + lookupModuleInGraph :: GhcMonad m => String -> m (Maybe Module)
|
|
| 130 | 141 | lookupModuleInGraph mod_str = do
|
| 131 | - graph <- GHC.getModuleGraph
|
|
| 132 | - let hmods = ms_mod <$> GHC.mgModSummaries graph
|
|
| 142 | + graph <- getModuleGraph
|
|
| 143 | + let hmods = ms_mod <$> mgModSummaries graph
|
|
| 133 | 144 | pure $ find ((== mod_str) . moduleNameString . moduleName) hmods
|
| 134 | 145 | |
| 135 | 146 | -- Check validity of an identifier to set a breakpoint:
|
| ... | ... | @@ -137,21 +148,21 @@ resolveFunctionBreakpoint inp = do |
| 137 | 148 | -- 2. the identifier must be in an interpreted module
|
| 138 | 149 | -- 3. the ModBreaks array for module `mod` must have an entry
|
| 139 | 150 | -- for the function
|
| 140 | - validateBP :: GHC.GhcMonad m => String -> String -> Maybe Module
|
|
| 151 | + validateBP :: GhcMonad m => String -> String -> Maybe Module
|
|
| 141 | 152 | -> m (Maybe SDoc)
|
| 142 | 153 | validateBP mod_str fun_str Nothing = pure $ Just $ quotes (text
|
| 143 | 154 | (combineModIdent mod_str (takeWhile (/= '.') fun_str)))
|
| 144 | 155 | <+> text "not in scope"
|
| 145 | 156 | validateBP _ "" (Just _) = pure $ Just $ text "Function name is missing"
|
| 146 | 157 | validateBP _ fun_str (Just modl) = do
|
| 147 | - isInterpr <- GHC.moduleIsInterpreted modl
|
|
| 158 | + isInterpr <- moduleIsInterpreted modl
|
|
| 148 | 159 | mb_err_msg <- case isInterpr of
|
| 149 | 160 | False -> pure $ Just $ text "Module" <+> quotes (ppr modl) <+> text "is not interpreted"
|
| 150 | 161 | True -> do
|
| 151 | 162 | mb_modbreaks <- getModBreak modl
|
| 152 | 163 | let found = case mb_modbreaks of
|
| 153 | 164 | Nothing -> False
|
| 154 | - Just mb -> fun_str `elem` (intercalate "." <$> elems (GHC.modBreaks_decls mb))
|
|
| 165 | + Just mb -> fun_str `elem` (intercalate "." <$> elems (modBreaks_decls mb))
|
|
| 155 | 166 | if found
|
| 156 | 167 | then pure Nothing
|
| 157 | 168 | else pure $ Just $ text "No breakpoint found for" <+> quotes (text fun_str)
|
| ... | ... | @@ -163,13 +174,13 @@ resolveFunctionBreakpoint inp = do |
| 163 | 174 | -- for
|
| 164 | 175 | -- (a) this binder only (it maybe a top-level or a nested declaration)
|
| 165 | 176 | -- (b) that do not have an enclosing breakpoint
|
| 166 | -findBreakForBind :: String {-^ Name of bind to break at -} -> GHC.ModBreaks -> [(BreakIndex, RealSrcSpan)]
|
|
| 177 | +findBreakForBind :: String {-^ Name of bind to break at -} -> ModBreaks -> [(BreakIndex, RealSrcSpan)]
|
|
| 167 | 178 | findBreakForBind str_name modbreaks = filter (not . enclosed) ticks
|
| 168 | 179 | where
|
| 169 | 180 | ticks = [ (index, span)
|
| 170 | - | (index, decls) <- assocs (GHC.modBreaks_decls modbreaks),
|
|
| 181 | + | (index, decls) <- assocs (modBreaks_decls modbreaks),
|
|
| 171 | 182 | str_name == intercalate "." decls,
|
| 172 | - RealSrcSpan span _ <- [GHC.modBreaks_locs modbreaks ! index] ]
|
|
| 183 | + RealSrcSpan span _ <- [modBreaks_locs modbreaks ! index] ]
|
|
| 173 | 184 | enclosed (_,sp0) = any subspan ticks
|
| 174 | 185 | where subspan (_,sp) = sp /= sp0 &&
|
| 175 | 186 | realSrcSpanStart sp <= realSrcSpanStart sp0 &&
|
| ... | ... | @@ -180,53 +191,53 @@ findBreakForBind str_name modbreaks = filter (not . enclosed) ticks |
| 180 | 191 | --------------------------------------------------------------------------------
|
| 181 | 192 | |
| 182 | 193 | -- | Maps line numbers to the breakpoint ticks existing at that line for a module.
|
| 183 | -type TickArray = Array Int [(GHC.BreakIndex,RealSrcSpan)]
|
|
| 194 | +type TickArray = Array Int [(BreakIndex,RealSrcSpan)]
|
|
| 184 | 195 | |
| 185 | 196 | -- | Construct the 'TickArray' for the given module.
|
| 186 | 197 | makeModuleLineMap :: GhcMonad m => Module -> m (Maybe TickArray)
|
| 187 | 198 | makeModuleLineMap m = do
|
| 188 | - mi <- GHC.getModuleInfo m
|
|
| 189 | - return $ mkTickArray . assocs . GHC.modBreaks_locs <$> (GHC.modInfoModBreaks =<< mi)
|
|
| 199 | + mi <- getModuleInfo m
|
|
| 200 | + return $ mkTickArray . assocs . modBreaks_locs <$> (modInfoModBreaks =<< mi)
|
|
| 190 | 201 | where
|
| 191 | 202 | mkTickArray :: [(BreakIndex, SrcSpan)] -> TickArray
|
| 192 | 203 | mkTickArray ticks
|
| 193 | 204 | = accumArray (flip (:)) [] (1, max_line)
|
| 194 | 205 | [ (line, (nm,pan)) | (nm,RealSrcSpan pan _) <- ticks, line <- srcSpanLines pan ]
|
| 195 | 206 | where
|
| 196 | - max_line = foldr max 0 [ GHC.srcSpanEndLine sp | (_, RealSrcSpan sp _) <- ticks ]
|
|
| 197 | - srcSpanLines pan = [ GHC.srcSpanStartLine pan .. GHC.srcSpanEndLine pan ]
|
|
| 207 | + max_line = foldr max 0 [ srcSpanEndLine sp | (_, RealSrcSpan sp _) <- ticks ]
|
|
| 208 | + srcSpanLines pan = [ srcSpanStartLine pan .. srcSpanEndLine pan ]
|
|
| 198 | 209 | |
| 199 | 210 | -- | Get the 'ModBreaks' of the given 'Module' when available
|
| 200 | -getModBreak :: GHC.GhcMonad m
|
|
| 201 | - => Module -> m (Maybe ModBreaks)
|
|
| 211 | +getModBreak :: GhcMonad m => Module -> m (Maybe ModBreaks)
|
|
| 202 | 212 | getModBreak m = do
|
| 203 | - mod_info <- fromMaybe (panic "getModBreak") <$> GHC.getModuleInfo m
|
|
| 204 | - pure $ GHC.modInfoModBreaks mod_info
|
|
| 213 | + mod_info <- fromMaybe (panic "getModBreak") <$> getModuleInfo m
|
|
| 214 | + pure $ modInfoModBreaks mod_info
|
|
| 205 | 215 | |
| 206 | 216 | --------------------------------------------------------------------------------
|
| 207 | 217 | -- Getting current breakpoint information
|
| 208 | 218 | --------------------------------------------------------------------------------
|
| 209 | 219 | |
| 210 | -getCurrentBreakSpan :: GHC.GhcMonad m => m (Maybe SrcSpan)
|
|
| 220 | +getCurrentBreakSpan :: GhcMonad m => m (Maybe SrcSpan)
|
|
| 211 | 221 | getCurrentBreakSpan = do
|
| 212 | - resumes <- GHC.getResumeContext
|
|
| 222 | + hug <- hsc_HUG <$> getSession
|
|
| 223 | + resumes <- getResumeContext
|
|
| 213 | 224 | case resumes of
|
| 214 | 225 | [] -> return Nothing
|
| 215 | 226 | (r:_) -> do
|
| 216 | - let ix = GHC.resumeHistoryIx r
|
|
| 227 | + let ix = resumeHistoryIx r
|
|
| 217 | 228 | if ix == 0
|
| 218 | - then return (Just (GHC.resumeSpan r))
|
|
| 229 | + then return (Just (resumeSpan r))
|
|
| 219 | 230 | else do
|
| 220 | - let hist = GHC.resumeHistory r !! (ix-1)
|
|
| 221 | - pan <- GHC.getHistorySpan hist
|
|
| 231 | + let hist = resumeHistory r !! (ix-1)
|
|
| 232 | + pan <- liftIO $ getHistorySpan hug hist
|
|
| 222 | 233 | return (Just pan)
|
| 223 | 234 | |
| 224 | -getCurrentBreakModule :: GHC.GhcMonad m => m (Maybe Module)
|
|
| 235 | +getCurrentBreakModule :: GhcMonad m => m (Maybe Module)
|
|
| 225 | 236 | getCurrentBreakModule = do
|
| 226 | - resumes <- GHC.getResumeContext
|
|
| 237 | + resumes <- getResumeContext
|
|
| 227 | 238 | return $ case resumes of
|
| 228 | 239 | [] -> Nothing
|
| 229 | - (r:_) -> case GHC.resumeHistoryIx r of
|
|
| 230 | - 0 -> ibi_tick_mod <$> GHC.resumeBreakpointId r
|
|
| 231 | - ix -> Just $ GHC.getHistoryModule $ GHC.resumeHistory r !! (ix-1)
|
|
| 240 | + (r:_) -> case resumeHistoryIx r of
|
|
| 241 | + 0 -> ibi_tick_mod <$> resumeBreakpointId r
|
|
| 242 | + ix -> Just $ getHistoryModule $ resumeHistory r !! (ix-1)
|
|
| 232 | 243 |
| ... | ... | @@ -144,25 +144,25 @@ import qualified GHC.Unit.Home.Graph as HUG |
| 144 | 144 | getResumeContext :: GhcMonad m => m [Resume]
|
| 145 | 145 | getResumeContext = withSession (return . ic_resume . hsc_IC)
|
| 146 | 146 | |
| 147 | -mkHistory :: HscEnv -> ForeignHValue -> InternalBreakpointId -> IO History
|
|
| 148 | -mkHistory hsc_env hval ibi = History hval ibi <$> findEnclosingDecls hsc_env ibi
|
|
| 147 | +mkHistory :: HUG.HomeUnitGraph -> ForeignHValue -> InternalBreakpointId -> IO History
|
|
| 148 | +mkHistory hug hval ibi = History hval ibi <$> findEnclosingDecls hug ibi
|
|
| 149 | 149 | |
| 150 | 150 | getHistoryModule :: History -> Module
|
| 151 | 151 | getHistoryModule = ibi_tick_mod . historyBreakpointId
|
| 152 | 152 | |
| 153 | -getHistorySpan :: HscEnv -> History -> IO SrcSpan
|
|
| 154 | -getHistorySpan hsc_env hist = do
|
|
| 153 | +getHistorySpan :: HUG.HomeUnitGraph -> History -> IO SrcSpan
|
|
| 154 | +getHistorySpan hug hist = do
|
|
| 155 | 155 | let ibi = historyBreakpointId hist
|
| 156 | - brks <- readModBreaks hsc_env (ibi_tick_mod ibi)
|
|
| 156 | + brks <- readModBreaks hug (ibi_tick_mod ibi)
|
|
| 157 | 157 | return $ modBreaks_locs brks ! ibi_tick_index ibi
|
| 158 | 158 | |
| 159 | 159 | {- | Finds the enclosing top level function name -}
|
| 160 | 160 | -- ToDo: a better way to do this would be to keep hold of the decl_path computed
|
| 161 | 161 | -- by the coverage pass, which gives the list of lexically-enclosing bindings
|
| 162 | 162 | -- for each tick.
|
| 163 | -findEnclosingDecls :: HscEnv -> InternalBreakpointId -> IO [String]
|
|
| 164 | -findEnclosingDecls hsc_env ibi = do
|
|
| 165 | - brks <- readModBreaks hsc_env (ibi_tick_mod ibi)
|
|
| 163 | +findEnclosingDecls :: HUG.HomeUnitGraph -> InternalBreakpointId -> IO [String]
|
|
| 164 | +findEnclosingDecls hug ibi = do
|
|
| 165 | + brks <- readModBreaks hug (ibi_tick_mod ibi)
|
|
| 166 | 166 | return $ modBreaks_decls brks ! ibi_tick_index ibi
|
| 167 | 167 | |
| 168 | 168 | -- | Update fixity environment in the current interactive context.
|
| ... | ... | @@ -349,7 +349,8 @@ handleRunStatus step expr bindings final_ids status history0 = do |
| 349 | 349 | -- - or one of the stepping options in @EvalOpts@ caused us to stop at one
|
| 350 | 350 | EvalBreak apStack_ref (Just eval_break) resume_ctxt ccs -> do
|
| 351 | 351 | let ibi = evalBreakpointToId eval_break
|
| 352 | - tick_brks <- liftIO $ readModBreaks hsc_env (ibi_tick_mod ibi)
|
|
| 352 | + let hug = hsc_HUG hsc_env
|
|
| 353 | + tick_brks <- liftIO $ readModBreaks hug (ibi_tick_mod ibi)
|
|
| 353 | 354 | let
|
| 354 | 355 | span = modBreaks_locs tick_brks ! ibi_tick_index ibi
|
| 355 | 356 | decl = intercalate "." $ modBreaks_decls tick_brks ! ibi_tick_index ibi
|
| ... | ... | @@ -390,7 +391,7 @@ handleRunStatus step expr bindings final_ids status history0 = do |
| 390 | 391 | let eval_opts = initEvalOpts dflags (enableGhcStepMode step)
|
| 391 | 392 | status <- liftIO $ GHCi.resumeStmt interp eval_opts resume_ctxt_fhv
|
| 392 | 393 | history <- if not tracing then pure history0 else do
|
| 393 | - history1 <- liftIO $ mkHistory hsc_env apStack_fhv ibi
|
|
| 394 | + history1 <- liftIO $ mkHistory hug apStack_fhv ibi
|
|
| 394 | 395 | let !history' = history1 `consBL` history0
|
| 395 | 396 | -- history is strict, otherwise our BoundedList is pointless.
|
| 396 | 397 | return history'
|
| ... | ... | @@ -443,27 +444,27 @@ resumeExec step mbCnt |
| 443 | 444 | -- When the user specified a break ignore count, set it
|
| 444 | 445 | -- in the interpreter
|
| 445 | 446 | case (mb_brkpt, mbCnt) of
|
| 446 | - (Just brkpt, Just cnt) -> setupBreakpoint hsc_env (toBreakpointId brkpt) cnt
|
|
| 447 | + (Just brkpt, Just cnt) -> setupBreakpoint interp (toBreakpointId brkpt) cnt
|
|
| 447 | 448 | _ -> return ()
|
| 448 | 449 | |
| 449 | 450 | let eval_opts = initEvalOpts dflags (enableGhcStepMode step)
|
| 450 | 451 | status <- liftIO $ GHCi.resumeStmt interp eval_opts fhv
|
| 451 | 452 | let prevHistoryLst = fromListBL 50 hist
|
| 453 | + hug = hsc_HUG hsc_env
|
|
| 452 | 454 | hist' = case mb_brkpt of
|
| 453 | 455 | Nothing -> pure prevHistoryLst
|
| 454 | 456 | Just bi
|
| 455 | 457 | | breakHere False step span -> do
|
| 456 | - hist1 <- liftIO (mkHistory hsc_env apStack bi)
|
|
| 458 | + hist1 <- liftIO (mkHistory hug apStack bi)
|
|
| 457 | 459 | return $ hist1 `consBL` fromListBL 50 hist
|
| 458 | 460 | | otherwise -> pure prevHistoryLst
|
| 459 | 461 | handleRunStatus step expr bindings final_ids status =<< hist'
|
| 460 | 462 | |
| 461 | -setupBreakpoint :: GhcMonad m => HscEnv -> BreakpointId -> Int -> m () -- #19157
|
|
| 462 | -setupBreakpoint hsc_env bi cnt = do
|
|
| 463 | - let modl = bi_tick_mod bi
|
|
| 464 | - modBreaks <- liftIO $ readModBreaks hsc_env modl
|
|
| 463 | +setupBreakpoint :: GhcMonad m => Interp -> BreakpointId -> Int -> m () -- #19157
|
|
| 464 | +setupBreakpoint interp bi cnt = do
|
|
| 465 | + hug <- hsc_HUG <$> getSession
|
|
| 466 | + modBreaks <- liftIO $ readModBreaks hug (bi_tick_mod bi)
|
|
| 465 | 467 | let breakarray = modBreaks_flags modBreaks
|
| 466 | - interp = hscInterp hsc_env
|
|
| 467 | 468 | _ <- liftIO $ GHCi.storeBreakpoint interp breakarray (bi_tick_index bi) cnt
|
| 468 | 469 | pure ()
|
| 469 | 470 | |
| ... | ... | @@ -494,7 +495,7 @@ moveHist fn = do |
| 494 | 495 | span <- case mb_info of
|
| 495 | 496 | Nothing -> return $ mkGeneralSrcSpan (fsLit "<unknown>")
|
| 496 | 497 | Just ibi -> liftIO $ do
|
| 497 | - brks <- readModBreaks hsc_env (ibi_tick_mod ibi)
|
|
| 498 | + brks <- readModBreaks (hsc_HUG hsc_env) (ibi_tick_mod ibi)
|
|
| 498 | 499 | return $ modBreaks_locs brks ! ibi_tick_index ibi
|
| 499 | 500 | (hsc_env1, names) <-
|
| 500 | 501 | liftIO $ bindLocalsAtBreakpoint hsc_env apStack span mb_info
|
| ... | ... | @@ -525,11 +526,6 @@ moveHist fn = do |
| 525 | 526 | result_fs :: FastString
|
| 526 | 527 | result_fs = fsLit "_result"
|
| 527 | 528 | |
| 528 | --- | Read the 'ModBreaks' of the given home 'Module' from the 'HomeUnitGraph'.
|
|
| 529 | -readModBreaks :: HscEnv -> Module -> IO ModBreaks
|
|
| 530 | -readModBreaks hsc_env mod = expectJust . getModBreaks . expectJust <$> HUG.lookupHugByModule mod (hsc_HUG hsc_env)
|
|
| 531 | - |
|
| 532 | - |
|
| 533 | 529 | bindLocalsAtBreakpoint
|
| 534 | 530 | :: HscEnv
|
| 535 | 531 | -> ForeignHValue
|
| ... | ... | @@ -560,8 +556,9 @@ bindLocalsAtBreakpoint hsc_env apStack span Nothing = do |
| 560 | 556 | -- Just case: we stopped at a breakpoint, we have information about the location
|
| 561 | 557 | -- of the breakpoint and the free variables of the expression.
|
| 562 | 558 | bindLocalsAtBreakpoint hsc_env apStack_fhv span (Just ibi) = do
|
| 563 | - info_brks <- readModBreaks hsc_env (ibi_info_mod ibi)
|
|
| 564 | - tick_brks <- readModBreaks hsc_env (ibi_tick_mod ibi)
|
|
| 559 | + let hug = hsc_HUG hsc_env
|
|
| 560 | + info_brks <- readModBreaks hug (ibi_info_mod ibi)
|
|
| 561 | + tick_brks <- readModBreaks hug (ibi_tick_mod ibi)
|
|
| 565 | 562 | let info = expectJust $ IntMap.lookup (ibi_info_index ibi) (modBreaks_breakInfo info_brks)
|
| 566 | 563 | interp = hscInterp hsc_env
|
| 567 | 564 | occs = modBreaks_vars tick_brks ! ibi_tick_index ibi
|
| ... | ... | @@ -27,10 +27,9 @@ module GHC.Runtime.Interpreter |
| 27 | 27 | , getClosure
|
| 28 | 28 | , whereFrom
|
| 29 | 29 | , getModBreaks
|
| 30 | + , readModBreaks
|
|
| 30 | 31 | , seqHValue
|
| 31 | 32 | , evalBreakpointToId
|
| 32 | - , interpreterDynamic
|
|
| 33 | - , interpreterProfiled
|
|
| 34 | 33 | |
| 35 | 34 | -- * The object-code linker
|
| 36 | 35 | , initObjLinker
|
| ... | ... | @@ -98,7 +97,6 @@ import GHC.Unit.Env |
| 98 | 97 | |
| 99 | 98 | #if defined(HAVE_INTERNAL_INTERPRETER)
|
| 100 | 99 | import GHCi.Run
|
| 101 | -import GHC.Platform.Ways
|
|
| 102 | 100 | #endif
|
| 103 | 101 | |
| 104 | 102 | import Control.Concurrent
|
| ... | ... | @@ -117,6 +115,7 @@ import qualified GHC.InfoProv as InfoProv |
| 117 | 115 | |
| 118 | 116 | import GHC.Builtin.Names
|
| 119 | 117 | import GHC.Types.Name
|
| 118 | +import qualified GHC.Unit.Home.Graph as HUG
|
|
| 120 | 119 | |
| 121 | 120 | -- Standard libraries
|
| 122 | 121 | import GHC.Exts
|
| ... | ... | @@ -732,13 +731,12 @@ wormholeRef interp _r = case interpInstance interp of |
| 732 | 731 | ExternalInterp {}
|
| 733 | 732 | -> throwIO (InstallationError "this operation requires -fno-external-interpreter")
|
| 734 | 733 | |
| 735 | --- -----------------------------------------------------------------------------
|
|
| 736 | --- Misc utils
|
|
| 737 | - |
|
| 738 | -fromEvalResult :: EvalResult a -> IO a
|
|
| 739 | -fromEvalResult (EvalException e) = throwIO (fromSerializableException e)
|
|
| 740 | -fromEvalResult (EvalSuccess a) = return a
|
|
| 734 | +--------------------------------------------------------------------------------
|
|
| 735 | +-- * Finding breakpoint information
|
|
| 736 | +--------------------------------------------------------------------------------
|
|
| 741 | 737 | |
| 738 | +-- | Get the breakpoint information from the ByteCode object associated to this
|
|
| 739 | +-- 'HomeModInfo'.
|
|
| 742 | 740 | getModBreaks :: HomeModInfo -> Maybe ModBreaks
|
| 743 | 741 | getModBreaks hmi
|
| 744 | 742 | | Just linkable <- homeModInfoByteCode hmi,
|
| ... | ... | @@ -748,24 +746,15 @@ getModBreaks hmi |
| 748 | 746 | | otherwise
|
| 749 | 747 | = Nothing -- probably object code
|
| 750 | 748 | |
| 751 | --- | Interpreter uses Profiling way
|
|
| 752 | -interpreterProfiled :: Interp -> Bool
|
|
| 753 | -interpreterProfiled interp = case interpInstance interp of
|
|
| 754 | -#if defined(HAVE_INTERNAL_INTERPRETER)
|
|
| 755 | - InternalInterp -> hostIsProfiled
|
|
| 756 | -#endif
|
|
| 757 | - ExternalInterp ext -> case ext of
|
|
| 758 | - ExtIServ i -> iservConfProfiled (interpConfig i)
|
|
| 759 | - ExtJS {} -> False -- we don't support profiling yet in the JS backend
|
|
| 760 | - ExtWasm i -> wasmInterpProfiled $ interpConfig i
|
|
| 761 | - |
|
| 762 | --- | Interpreter uses Dynamic way
|
|
| 763 | -interpreterDynamic :: Interp -> Bool
|
|
| 764 | -interpreterDynamic interp = case interpInstance interp of
|
|
| 765 | -#if defined(HAVE_INTERNAL_INTERPRETER)
|
|
| 766 | - InternalInterp -> hostIsDynamic
|
|
| 767 | -#endif
|
|
| 768 | - ExternalInterp ext -> case ext of
|
|
| 769 | - ExtIServ i -> iservConfDynamic (interpConfig i)
|
|
| 770 | - ExtJS {} -> False -- dynamic doesn't make sense for JS
|
|
| 771 | - ExtWasm {} -> True -- wasm dyld can only load dynamic code |
|
| 749 | +-- | Read the 'InternalModBreaks' and 'ModBreaks' of the given home 'Module'
|
|
| 750 | +-- from the 'HomeUnitGraph'.
|
|
| 751 | +readModBreaks :: HomeUnitGraph -> Module -> IO ModBreaks
|
|
| 752 | +readModBreaks hug modl = expectJust . getModBreaks . expectJust <$> HUG.lookupHugByModule modl hug
|
|
| 753 | + |
|
| 754 | +-- -----------------------------------------------------------------------------
|
|
| 755 | +-- Misc utils
|
|
| 756 | + |
|
| 757 | +fromEvalResult :: EvalResult a -> IO a
|
|
| 758 | +fromEvalResult (EvalException e) = throwIO (fromSerializableException e)
|
|
| 759 | +fromEvalResult (EvalSuccess a) = return a
|
|
| 760 | + |
| ... | ... | @@ -24,7 +24,8 @@ module GHC.Runtime.Interpreter.Types |
| 24 | 24 | , interpSymbolSuffix
|
| 25 | 25 | , eliminateInterpSymbol
|
| 26 | 26 | , interpretedInterpSymbol
|
| 27 | - |
|
| 27 | + , interpreterProfiled
|
|
| 28 | + , interpreterDynamic
|
|
| 28 | 29 | |
| 29 | 30 | -- * IServ
|
| 30 | 31 | , IServ
|
| ... | ... | @@ -48,6 +49,9 @@ import GHCi.RemoteTypes |
| 48 | 49 | import GHCi.Message ( Pipe )
|
| 49 | 50 | |
| 50 | 51 | import GHC.Platform
|
| 52 | +#if defined(HAVE_INTERNAL_INTERPRETER)
|
|
| 53 | +import GHC.Platform.Ways
|
|
| 54 | +#endif
|
|
| 51 | 55 | import GHC.Utils.TmpFs
|
| 52 | 56 | import GHC.Utils.Logger
|
| 53 | 57 | import GHC.Unit.Env
|
| ... | ... | @@ -136,6 +140,28 @@ data ExtInterpInstance c = ExtInterpInstance |
| 136 | 140 | -- ^ Instance specific extra fields
|
| 137 | 141 | }
|
| 138 | 142 | |
| 143 | +-- | Interpreter uses Profiling way
|
|
| 144 | +interpreterProfiled :: Interp -> Bool
|
|
| 145 | +interpreterProfiled interp = case interpInstance interp of
|
|
| 146 | +#if defined(HAVE_INTERNAL_INTERPRETER)
|
|
| 147 | + InternalInterp -> hostIsProfiled
|
|
| 148 | +#endif
|
|
| 149 | + ExternalInterp ext -> case ext of
|
|
| 150 | + ExtIServ i -> iservConfProfiled (interpConfig i)
|
|
| 151 | + ExtJS {} -> False -- we don't support profiling yet in the JS backend
|
|
| 152 | + ExtWasm i -> wasmInterpProfiled $ interpConfig i
|
|
| 153 | + |
|
| 154 | +-- | Interpreter uses Dynamic way
|
|
| 155 | +interpreterDynamic :: Interp -> Bool
|
|
| 156 | +interpreterDynamic interp = case interpInstance interp of
|
|
| 157 | +#if defined(HAVE_INTERNAL_INTERPRETER)
|
|
| 158 | + InternalInterp -> hostIsDynamic
|
|
| 159 | +#endif
|
|
| 160 | + ExternalInterp ext -> case ext of
|
|
| 161 | + ExtIServ i -> iservConfDynamic (interpConfig i)
|
|
| 162 | + ExtJS {} -> False -- dynamic doesn't make sense for JS
|
|
| 163 | + ExtWasm {} -> True -- wasm dyld can only load dynamic code
|
|
| 164 | + |
|
| 139 | 165 | ------------------------
|
| 140 | 166 | -- JS Stuff
|
| 141 | 167 | ------------------------
|
| ... | ... | @@ -49,7 +49,7 @@ bcPrepRHS con@StgRhsCon{} = pure con |
| 49 | 49 | |
| 50 | 50 | bcPrepExpr :: StgExpr -> BcPrepM StgExpr
|
| 51 | 51 | -- explicitly match all constructors so we get a warning if we miss any
|
| 52 | -bcPrepExpr (StgTick bp@(Breakpoint tick_ty _ _ _) rhs)
|
|
| 52 | +bcPrepExpr (StgTick bp@(Breakpoint tick_ty _ _) rhs)
|
|
| 53 | 53 | | isLiftedTypeKind (typeKind tick_ty) = do
|
| 54 | 54 | id <- newId tick_ty
|
| 55 | 55 | rhs' <- bcPrepExpr rhs
|
| ... | ... | @@ -257,8 +257,8 @@ exprFVs env = go |
| 257 | 257 | , let lcl_fvs' = unionDVarSet (tickish tick) lcl_fvs
|
| 258 | 258 | = (StgTick tick e', imp_fvs, top_fvs, lcl_fvs')
|
| 259 | 259 | where
|
| 260 | - tickish (Breakpoint _ _ ids _) = mkDVarSet ids
|
|
| 261 | - tickish _ = emptyDVarSet
|
|
| 260 | + tickish (Breakpoint _ _ ids) = mkDVarSet ids
|
|
| 261 | + tickish _ = emptyDVarSet
|
|
| 262 | 262 | |
| 263 | 263 | go_bind dc bind body = (dc bind' body', imp_fvs, top_fvs, lcl_fvs)
|
| 264 | 264 | where
|
| ... | ... | @@ -33,6 +33,7 @@ import GHC.Platform.Profile |
| 33 | 33 | import GHC.Runtime.Interpreter
|
| 34 | 34 | import GHCi.FFI
|
| 35 | 35 | import GHC.Types.Basic
|
| 36 | +import GHC.Types.Breakpoint
|
|
| 36 | 37 | import GHC.Utils.Outputable
|
| 37 | 38 | import GHC.Types.Name
|
| 38 | 39 | import GHC.Types.Id
|
| ... | ... | @@ -388,7 +389,7 @@ schemeR_wrk fvs nm original_body (args, body) |
| 388 | 389 | -- | Introduce break instructions for ticked expressions.
|
| 389 | 390 | -- If no breakpoint information is available, the instruction is omitted.
|
| 390 | 391 | schemeER_wrk :: StackDepth -> BCEnv -> CgStgExpr -> BcM BCInstrList
|
| 391 | -schemeER_wrk d p (StgTick (Breakpoint tick_ty tick_no fvs tick_mod) rhs) = do
|
|
| 392 | +schemeER_wrk d p (StgTick (Breakpoint tick_ty (BreakpointId tick_mod tick_no) fvs) rhs) = do
|
|
| 392 | 393 | code <- schemeE d 0 p rhs
|
| 393 | 394 | hsc_env <- getHscEnv
|
| 394 | 395 | current_mod <- getCurrentModule
|
| ... | ... | @@ -640,10 +641,9 @@ schemeE d s p (StgLet _ext binds body) = do |
| 640 | 641 | thunk_codes <- sequence compile_binds
|
| 641 | 642 | return (alloc_code `appOL` concatOL thunk_codes `appOL` body_code)
|
| 642 | 643 | |
| 643 | -schemeE _d _s _p (StgTick (Breakpoint _ bp_id _ _) _rhs)
|
|
| 644 | - = panic ("schemeE: Breakpoint without let binding: " ++
|
|
| 645 | - show bp_id ++
|
|
| 646 | - " forgot to run bcPrep?")
|
|
| 644 | +schemeE _d _s _p (StgTick (Breakpoint _ bp_id _) _rhs)
|
|
| 645 | + = pprPanic "schemeE: Breakpoint without let binding: " $
|
|
| 646 | + ppr bp_id <> text " forgot to run bcPrep?"
|
|
| 647 | 647 | |
| 648 | 648 | -- ignore other kinds of tick
|
| 649 | 649 | schemeE d s p (StgTick _ rhs) = schemeE d s p rhs
|
| ... | ... | @@ -8,6 +8,9 @@ where |
| 8 | 8 | |
| 9 | 9 | import GHC.Prelude
|
| 10 | 10 | import GHC.Unit.Module
|
| 11 | +import GHC.Utils.Outputable
|
|
| 12 | +import Control.DeepSeq
|
|
| 13 | +import Data.Data (Data)
|
|
| 11 | 14 | |
| 12 | 15 | -- | Breakpoint identifier.
|
| 13 | 16 | --
|
| ... | ... | @@ -16,7 +19,7 @@ data BreakpointId = BreakpointId |
| 16 | 19 | { bi_tick_mod :: !Module -- ^ Breakpoint tick module
|
| 17 | 20 | , bi_tick_index :: !Int -- ^ Breakpoint tick index
|
| 18 | 21 | }
|
| 19 | - deriving (Eq, Ord)
|
|
| 22 | + deriving (Eq, Ord, Data)
|
|
| 20 | 23 | |
| 21 | 24 | -- | Internal breakpoint identifier
|
| 22 | 25 | --
|
| ... | ... | @@ -53,3 +56,11 @@ toBreakpointId ibi = BreakpointId |
| 53 | 56 | -- So every breakpoint occurrence gets assigned a module-unique *info index* and
|
| 54 | 57 | -- we store it alongside the occurrence module (*info module*) in the
|
| 55 | 58 | -- InternalBreakpointId datatype.
|
| 59 | + |
|
| 60 | +instance Outputable BreakpointId where
|
|
| 61 | + ppr BreakpointId{bi_tick_mod, bi_tick_index} =
|
|
| 62 | + text "BreakpointId" <+> ppr bi_tick_mod <+> ppr bi_tick_index
|
|
| 63 | + |
|
| 64 | +instance NFData BreakpointId where
|
|
| 65 | + rnf BreakpointId{bi_tick_mod, bi_tick_index} =
|
|
| 66 | + rnf bi_tick_mod `seq` rnf bi_tick_index |
| ... | ... | @@ -31,6 +31,7 @@ import GHC.Core.Type |
| 31 | 31 | |
| 32 | 32 | import GHC.Unit.Module
|
| 33 | 33 | |
| 34 | +import GHC.Types.Breakpoint
|
|
| 34 | 35 | import GHC.Types.CostCentre
|
| 35 | 36 | import GHC.Types.SrcLoc ( RealSrcSpan, containsSpan )
|
| 36 | 37 | import GHC.Types.Var
|
| ... | ... | @@ -128,7 +129,7 @@ data GenTickish pass = |
| 128 | 129 | -- and (b) substituting (don't substitute for them)
|
| 129 | 130 | | Breakpoint
|
| 130 | 131 | { breakpointExt :: XBreakpoint pass
|
| 131 | - , breakpointId :: !Int
|
|
| 132 | + , breakpointId :: !BreakpointId
|
|
| 132 | 133 | , breakpointFVs :: [XTickishId pass]
|
| 133 | 134 | -- ^ the order of this list is important:
|
| 134 | 135 | -- it matches the order of the lists in the
|
| ... | ... | @@ -136,7 +137,6 @@ data GenTickish pass = |
| 136 | 137 | --
|
| 137 | 138 | -- Careful about substitution! See
|
| 138 | 139 | -- Note [substTickish] in "GHC.Core.Subst".
|
| 139 | - , breakpointModule :: Module
|
|
| 140 | 140 | }
|
| 141 | 141 | |
| 142 | 142 | -- | A source note.
|
| ... | ... | @@ -548,6 +548,7 @@ Library |
| 548 | 548 | GHC.Driver.Plugins.External
|
| 549 | 549 | GHC.Driver.Ppr
|
| 550 | 550 | GHC.Driver.Session
|
| 551 | + GHC.Driver.Session.Inspect
|
|
| 551 | 552 | GHC.Driver.Session.Units
|
| 552 | 553 | GHC.Hs
|
| 553 | 554 | GHC.Hs.Basic
|