Rodrigo Mesquita pushed to branch wip/romes/step-out-8 at Glasgow Haskell Compiler / GHC
Commits:
-
6986f25d
by Rodrigo Mesquita at 2025-06-27T16:19:01+01:00
-
03235e46
by Rodrigo Mesquita at 2025-06-27T16:43:36+01:00
-
5851082d
by Rodrigo Mesquita at 2025-06-27T17:21:06+01:00
-
748ddd68
by Rodrigo Mesquita at 2025-06-27T17:51:51+01:00
11 changed files:
- compiler/GHC/ByteCode/Asm.hs
- compiler/GHC/ByteCode/Breakpoints.hs
- compiler/GHC/ByteCode/Types.hs
- compiler/GHC/HsToCore/Breakpoints.hs
- compiler/GHC/Runtime/Eval.hs
- compiler/GHC/Runtime/Interpreter.hs
- compiler/GHC/Runtime/Interpreter/Types.hs
- compiler/GHC/StgToByteCode.hs
- compiler/GHC/Types/Tickish.hs
- ghc/GHCi/UI.hs
- rts/Interpreter.c
Changes:
... | ... | @@ -72,8 +72,6 @@ import GHC.Float (castFloatToWord32, castDoubleToWord64) |
72 | 72 | |
73 | 73 | import qualified Data.List as List ( any )
|
74 | 74 | import GHC.Exts
|
75 | -import GHC.HsToCore.Breakpoints (ModBreaks(..))
|
|
76 | - |
|
77 | 75 | |
78 | 76 | -- -----------------------------------------------------------------------------
|
79 | 77 | -- Unlinked BCOs
|
... | ... | @@ -110,14 +108,14 @@ assembleBCOs |
110 | 108 | -> FlatBag (ProtoBCO Name)
|
111 | 109 | -> [TyCon]
|
112 | 110 | -> [(Name, ByteString)]
|
113 | - -> Maybe (InternalModBreaks, ModBreaks)
|
|
111 | + -> InternalModBreaks
|
|
114 | 112 | -> [SptEntry]
|
115 | 113 | -> IO CompiledByteCode
|
116 | 114 | assembleBCOs profile proto_bcos tycons top_strs modbreaks spt_entries = do
|
117 | 115 | -- TODO: the profile should be bundled with the interpreter: the rts ways are
|
118 | 116 | -- fixed for an interpreter
|
119 | 117 | let itbls = mkITbls profile tycons
|
120 | - bcos <- mapM (assembleBCO (profilePlatform profile)) proto_bcos
|
|
118 | + bcos <- mapM (assembleBCO (profilePlatform profile)) proto_bcos
|
|
121 | 119 | return CompiledByteCode
|
122 | 120 | { bc_bcos = bcos
|
123 | 121 | , bc_itbls = itbls
|
... | ... | @@ -13,12 +13,17 @@ module GHC.ByteCode.Breakpoints |
13 | 13 | InternalModBreaks(..), CgBreakInfo(..)
|
14 | 14 | , mkInternalModBreaks
|
15 | 15 | |
16 | - -- ** Operations
|
|
17 | - , getInternalBreak, addInternalBreak
|
|
18 | - |
|
19 | 16 | -- ** Internal breakpoint identifier
|
20 | 17 | , InternalBreakpointId(..), BreakInfoIndex
|
21 | 18 | |
19 | + -- * Operations
|
|
20 | + |
|
21 | + -- ** Internal-level operations
|
|
22 | + , getInternalBreak, addInternalBreak
|
|
23 | + |
|
24 | + -- ** Source-level information operations
|
|
25 | + , getBreakLoc, getBreakVars, getBreakDecls, getBreakCCS
|
|
26 | + |
|
22 | 27 | -- * Utils
|
23 | 28 | , seqInternalModBreaks
|
24 | 29 | |
... | ... | @@ -26,16 +31,19 @@ module GHC.ByteCode.Breakpoints |
26 | 31 | where
|
27 | 32 | |
28 | 33 | import GHC.Prelude
|
34 | +import GHC.Types.SrcLoc
|
|
35 | +import GHC.Types.Name.Occurrence
|
|
29 | 36 | import Control.DeepSeq
|
30 | 37 | import Data.IntMap.Strict (IntMap)
|
31 | 38 | import qualified Data.IntMap.Strict as IM
|
32 | 39 | |
40 | +import GHC.HsToCore.Breakpoints
|
|
33 | 41 | import GHC.Iface.Syntax
|
34 | -import GHC.Types.Tickish
|
|
35 | 42 | |
36 | 43 | import GHC.Unit.Module (Module)
|
37 | 44 | import GHC.Utils.Outputable
|
38 | 45 | import GHC.Utils.Panic
|
46 | +import Data.Array
|
|
39 | 47 | |
40 | 48 | {-
|
41 | 49 | Note [ModBreaks vs InternalModBreaks]
|
... | ... | @@ -120,11 +128,19 @@ data InternalModBreaks = InternalModBreaks |
120 | 128 | , imodBreaks_module :: !Module
|
121 | 129 | -- ^ Also cache the module corresponding to these 'InternalModBreaks',
|
122 | 130 | -- for instance for internal sanity checks.
|
131 | + |
|
132 | + , imodBreaks_modBreaks :: !(Maybe ModBreaks)
|
|
133 | + -- ^ Store the original ModBreaks for this module, unchanged.
|
|
134 | + -- Allows us to query about source-level breakpoint information using
|
|
135 | + -- an internal breakpoint id.
|
|
123 | 136 | }
|
124 | 137 | |
125 | 138 | -- | Construct an 'InternalModBreaks'
|
126 | -mkInternalModBreaks :: Module -> IntMap CgBreakInfo -> InternalModBreaks
|
|
127 | -mkInternalModBreaks mod im = InternalModBreaks im mod
|
|
139 | +mkInternalModBreaks :: Module -> Maybe ModBreaks -> InternalModBreaks
|
|
140 | +mkInternalModBreaks mod mbs =
|
|
141 | + assertPpr (Just mod == (modBreaks_module <$> mbs))
|
|
142 | + (text "Constructing InternalModBreaks with the ModBreaks of a different module!") $
|
|
143 | + InternalModBreaks mempty mod mbs
|
|
128 | 144 | |
129 | 145 | -- | Information about a breakpoint that we know at code-generation time
|
130 | 146 | -- In order to be used, this needs to be hydrated relative to the current HscEnv by
|
... | ... | @@ -161,6 +177,34 @@ assert_modules_match ibi_mod imbs_mod = |
161 | 177 | (text "Tried to query the InternalModBreaks of module" <+> ppr imbs_mod
|
162 | 178 | <+> text "with an InternalBreakpointId for module" <+> ppr ibi_mod)
|
163 | 179 | |
180 | +--------------------------------------------------------------------------------
|
|
181 | + |
|
182 | +--------------------------------------------------------------------------------
|
|
183 | + |
|
184 | +-- | Get the source span for this breakpoint
|
|
185 | +getBreakLoc :: InternalBreakpointId -> InternalModBreaks -> Maybe SrcSpan
|
|
186 | +getBreakLoc = getBreakXXX modBreaks_locs
|
|
187 | + |
|
188 | +-- | Get the vars for this breakpoint
|
|
189 | +getBreakVars :: InternalBreakpointId -> InternalModBreaks -> Maybe [OccName]
|
|
190 | +getBreakVars = getBreakXXX modBreaks_vars
|
|
191 | + |
|
192 | +-- | Get the decls for this breakpoint
|
|
193 | +getBreakDecls :: InternalBreakpointId -> InternalModBreaks -> Maybe [String]
|
|
194 | +getBreakDecls = getBreakXXX modBreaks_decls
|
|
195 | + |
|
196 | +-- | Get the decls for this breakpoint
|
|
197 | +getBreakCCS :: InternalBreakpointId -> InternalModBreaks -> Maybe (String, String)
|
|
198 | +getBreakCCS = getBreakXXX modBreaks_ccs
|
|
199 | + |
|
200 | +-- | Internal utility to access a ModBreaks field at a particular breakpoint index
|
|
201 | +getBreakXXX :: (ModBreaks -> Array BreakTickIndex a) -> InternalBreakpointId -> InternalModBreaks -> Maybe a
|
|
202 | +getBreakXXX view (InternalBreakpointId ibi_mod ibi_ix) imbs =
|
|
203 | + assert_modules_match ibi_mod (imodBreaks_module imbs) $ do
|
|
204 | + let cgb = imodBreaks_breakInfo imbs IM.! ibi_ix
|
|
205 | + mbs <- imodBreaks_modBreaks imbs
|
|
206 | + Just $ view mbs ! bi_tick_index (cgb_tick_id cgb)
|
|
207 | + |
|
164 | 208 | --------------------------------------------------------------------------------
|
165 | 209 | -- Instances
|
166 | 210 | --------------------------------------------------------------------------------
|
... | ... | @@ -46,7 +46,6 @@ import Foreign |
46 | 46 | import Data.ByteString (ByteString)
|
47 | 47 | import qualified GHC.Exts.Heap as Heap
|
48 | 48 | import GHC.Cmm.Expr ( GlobalRegSet, emptyRegSet, regSetToList )
|
49 | -import GHC.HsToCore.Breakpoints (ModBreaks)
|
|
50 | 49 | import GHC.Unit.Module
|
51 | 50 | |
52 | 51 | -- -----------------------------------------------------------------------------
|
... | ... | @@ -62,9 +61,8 @@ data CompiledByteCode = CompiledByteCode |
62 | 61 | , bc_strs :: [(Name, ByteString)]
|
63 | 62 | -- ^ top-level strings (heap allocated)
|
64 | 63 | |
65 | - , bc_breaks :: (Maybe (InternalModBreaks, ModBreaks))
|
|
66 | - -- ^ All (internal and tick-level) breakpoint information (no information
|
|
67 | - -- if breakpoints are disabled).
|
|
64 | + , bc_breaks :: InternalModBreaks
|
|
65 | + -- ^ All breakpoint information (no information if breakpoints are disabled).
|
|
68 | 66 | --
|
69 | 67 | -- This information is used when loading a bytecode object: we will
|
70 | 68 | -- construct the arrays to be used at runtime to trigger breakpoints then
|
... | ... | @@ -74,10 +72,6 @@ data CompiledByteCode = CompiledByteCode |
74 | 72 | -- breakpoint information indexed by the internal breakpoint id here (in
|
75 | 73 | -- 'getModBreaks').
|
76 | 74 | |
77 | - -- TODO: If ModBreaks is serialized and reconstructed as part of ModDetails
|
|
78 | - -- we don't need to keep it in bc_breaks as it can be fetched from the
|
|
79 | - -- 'HomeModInfo' directly, right?
|
|
80 | - |
|
81 | 75 | , bc_spt_entries :: ![SptEntry]
|
82 | 76 | -- ^ Static pointer table entries which should be loaded along with the
|
83 | 77 | -- BCOs. See Note [Grand plan for static forms] in
|
... | ... | @@ -17,10 +17,6 @@ module GHC.HsToCore.Breakpoints |
17 | 17 | ( -- * ModBreaks
|
18 | 18 | mkModBreaks, ModBreaks(..)
|
19 | 19 | |
20 | - -- ** Queries
|
|
21 | - -- TODO: See where we could use these rather than using the arrays directly.
|
|
22 | - , getBreakLoc, getBreakVars, getBreakDecls, getBreakCCS
|
|
23 | - |
|
24 | 20 | -- ** Re-exports BreakpointId
|
25 | 21 | , BreakpointId(..), BreakTickIndex
|
26 | 22 | ) where
|
... | ... | @@ -35,7 +31,6 @@ import GHC.Types.Name (OccName) |
35 | 31 | import GHC.Types.Tickish (BreakTickIndex, BreakpointId(..))
|
36 | 32 | import GHC.Unit.Module (Module)
|
37 | 33 | import GHC.Utils.Outputable
|
38 | -import GHC.Utils.Panic
|
|
39 | 34 | import Data.List (intersperse)
|
40 | 35 | |
41 | 36 | --------------------------------------------------------------------------------
|
... | ... | @@ -103,34 +98,6 @@ mkModBreaks interpreterProfiled modl extendedMixEntries |
103 | 98 | , modBreaks_module = modl
|
104 | 99 | }
|
105 | 100 | |
106 | --- | Get the source span for this breakpoint
|
|
107 | -getBreakLoc :: BreakpointId -> ModBreaks -> SrcSpan
|
|
108 | -getBreakLoc = getBreakXXX modBreaks_locs
|
|
109 | - |
|
110 | --- | Get the vars for this breakpoint
|
|
111 | -getBreakVars :: BreakpointId -> ModBreaks -> [OccName]
|
|
112 | -getBreakVars = getBreakXXX modBreaks_vars
|
|
113 | - |
|
114 | --- | Get the decls for this breakpoint
|
|
115 | -getBreakDecls :: BreakpointId -> ModBreaks -> [String]
|
|
116 | -getBreakDecls = getBreakXXX modBreaks_decls
|
|
117 | - |
|
118 | --- | Get the decls for this breakpoint
|
|
119 | -getBreakCCS :: BreakpointId -> ModBreaks -> (String, String)
|
|
120 | -getBreakCCS = getBreakXXX modBreaks_ccs
|
|
121 | - |
|
122 | --- | Internal utility to access a ModBreaks field at a particular breakpoint index
|
|
123 | -getBreakXXX :: (ModBreaks -> Array BreakTickIndex a) -> BreakpointId -> ModBreaks -> a
|
|
124 | -getBreakXXX view (BreakpointId bid_mod ix) mbs =
|
|
125 | - assert_modules_match bid_mod (modBreaks_module mbs) $ view mbs ! ix
|
|
126 | - |
|
127 | --- | Assert that the module in the 'BreakpointId' and in 'ModBreaks' match.
|
|
128 | -assert_modules_match :: Module -> Module -> a -> a
|
|
129 | -assert_modules_match bid_mod mbs_mod =
|
|
130 | - assertPpr (bid_mod == mbs_mod)
|
|
131 | - (text "Tried to query the ModBreaks of module" <+> ppr mbs_mod
|
|
132 | - <+> text "with a BreakpointId for module" <+> ppr bid_mod)
|
|
133 | - |
|
134 | 101 | {-
|
135 | 102 | Note [Field modBreaks_decls]
|
136 | 103 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
... | ... | @@ -128,7 +128,6 @@ import GHC.Tc.Utils.Monad |
128 | 128 | |
129 | 129 | import GHC.IfaceToCore
|
130 | 130 | import GHC.HsToCore.Breakpoints
|
131 | -import GHC.ByteCode.Breakpoints
|
|
132 | 131 | |
133 | 132 | import Control.Monad
|
134 | 133 | import Data.Array
|
... | ... | @@ -157,7 +156,7 @@ getHistorySpan :: HUG.HomeUnitGraph -> History -> IO SrcSpan |
157 | 156 | getHistorySpan hug hist = do
|
158 | 157 | let bid = historyBreakpointId hist
|
159 | 158 | (_, brks) <- readModBreaks hug (bi_tick_mod bid)
|
160 | - return $ modBreaks_locs brks ! bi_tick_index bid
|
|
159 | + return $ getBreakLoc bid brks
|
|
161 | 160 | |
162 | 161 | {- | Finds the enclosing top level function name -}
|
163 | 162 | -- ToDo: a better way to do this would be to keep hold of the decl_path computed
|
... | ... | @@ -358,7 +357,7 @@ handleRunStatus step expr bindings final_ids status history0 = do |
358 | 357 | (_, tick_brks) <- liftIO $ readModBreaks hug (bi_tick_mod bid)
|
359 | 358 | breakArray <- getBreakArray interp ibi
|
360 | 359 | let
|
361 | - span = modBreaks_locs tick_brks ! bi_tick_index bid
|
|
360 | + span = getBreakLoc bid tick_brks
|
|
362 | 361 | decl = intercalate "." $ modBreaks_decls tick_brks ! bi_tick_index bid
|
363 | 362 | |
364 | 363 | -- Was this breakpoint explicitly enabled (ie. in @BreakArray@)?
|
... | ... | @@ -450,7 +449,7 @@ resumeExec step mbCnt |
450 | 449 | -- When the user specified a break ignore count, set it
|
451 | 450 | -- in the interpreter
|
452 | 451 | case (mb_brkpt, mbCnt) of
|
453 | - (Just (bid, ibi), Just cnt) ->
|
|
452 | + (Just (_bid, ibi), Just cnt) ->
|
|
454 | 453 | setupBreakpoint interp ibi cnt
|
455 | 454 | _ -> return ()
|
456 | 455 | |
... | ... | @@ -476,6 +475,7 @@ getBreakArray :: GhcMonad m => Interp -> InternalBreakpointId -> m (ForeignRef B |
476 | 475 | getBreakArray interp InternalBreakpointId{ibi_info_mod} = do
|
477 | 476 | breakArrays <- liftIO $ breakarray_env . linker_env . expectJust
|
478 | 477 | <$> Loader.getLoaderState interp
|
478 | + pprTraceM "hello" (ppr $ moduleEnvKeys breakArrays)
|
|
479 | 479 | return $ expectJust $ lookupModuleEnv breakArrays ibi_info_mod
|
480 | 480 | |
481 | 481 | back :: GhcMonad m => Int -> m ([Name], Int, SrcSpan)
|
... | ... | @@ -506,7 +506,7 @@ moveHist fn = do |
506 | 506 | Nothing -> return $ mkGeneralSrcSpan (fsLit "<unknown>")
|
507 | 507 | Just (bid, _ibi) -> liftIO $ do
|
508 | 508 | (_, brks) <- readModBreaks (hsc_HUG hsc_env) (bi_tick_mod bid)
|
509 | - return $ modBreaks_locs brks ! bi_tick_index bid -- todo: getBreakLoc
|
|
509 | + return $ getBreakLoc bid brks
|
|
510 | 510 | (hsc_env1, names) <-
|
511 | 511 | liftIO $ bindLocalsAtBreakpoint hsc_env apStack span (snd <$> mb_info)
|
512 | 512 | let ic = hsc_IC hsc_env1
|
... | ... | @@ -28,10 +28,8 @@ module GHC.Runtime.Interpreter |
28 | 28 | , whereFrom
|
29 | 29 | , getModBreaks
|
30 | 30 | , readModBreaks
|
31 | - , readModBreaksMaybe
|
|
32 | 31 | , seqHValue
|
33 | 32 | , evalBreakpointToId
|
34 | - , internalBreakIdToBreakId
|
|
35 | 33 | |
36 | 34 | -- * The object-code linker
|
37 | 35 | , initObjLinker
|
... | ... | @@ -76,7 +74,6 @@ import GHCi.Message |
76 | 74 | import GHCi.RemoteTypes
|
77 | 75 | import GHCi.ResolvedBCO
|
78 | 76 | import GHCi.BreakArray (BreakArray)
|
79 | -import GHC.HsToCore.Breakpoints
|
|
80 | 77 | import GHC.ByteCode.Breakpoints
|
81 | 78 | |
82 | 79 | import GHC.ByteCode.Types
|
... | ... | @@ -95,12 +92,10 @@ import GHC.Utils.Fingerprint |
95 | 92 | |
96 | 93 | import GHC.Unit.Module
|
97 | 94 | import GHC.Unit.Home.ModInfo
|
98 | -import GHC.Unit.Home.Graph (lookupHugByModule)
|
|
99 | 95 | import GHC.Unit.Env
|
100 | 96 | |
101 | 97 | #if defined(HAVE_INTERNAL_INTERPRETER)
|
102 | 98 | import GHCi.Run
|
103 | -import GHC.Platform.Ways
|
|
104 | 99 | #endif
|
105 | 100 | |
106 | 101 | import Control.Concurrent
|
... | ... | @@ -109,10 +104,8 @@ import Control.Monad.IO.Class |
109 | 104 | import Control.Monad.Catch as MC (mask)
|
110 | 105 | import Data.Binary
|
111 | 106 | import Data.ByteString (ByteString)
|
112 | -import Data.Array ((!))
|
|
113 | 107 | import Foreign hiding (void)
|
114 | 108 | import qualified GHC.Exts.Heap as Heap
|
115 | -import GHC.Stack.CCS (CostCentre,CostCentreStack)
|
|
116 | 109 | import System.Directory
|
117 | 110 | import System.Process
|
118 | 111 | import qualified GHC.InfoProv as InfoProv
|
... | ... | @@ -123,6 +116,7 @@ import qualified GHC.Unit.Home.Graph as HUG |
123 | 116 | |
124 | 117 | -- Standard libraries
|
125 | 118 | import GHC.Exts
|
119 | +import GHC.Stack
|
|
126 | 120 | |
127 | 121 | {- Note [Remote GHCi]
|
128 | 122 | ~~~~~~~~~~~~~~~~~~
|
... | ... | @@ -423,20 +417,6 @@ evalBreakpointToId eval_break = |
423 | 417 | , ibi_info_index = eb_info_index eval_break
|
424 | 418 | }
|
425 | 419 | |
426 | --- | An @'InternalBreakpointId'@ is an index into the @IntMap 'CgBreakInfo'@ of
|
|
427 | --- a specific module's @'ModBreaks'@.
|
|
428 | ---
|
|
429 | --- To get the @'BreakpointId'@, an index from the Core-level ticks to the
|
|
430 | --- associated SrcSpans and other source-level relevant details, lookup it up in
|
|
431 | --- the @'CgBreakInfo'@ of this internal id's module.
|
|
432 | ---
|
|
433 | --- See also Note [Breakpoint identifiers]
|
|
434 | -internalBreakIdToBreakId :: HomeUnitGraph -> InternalBreakpointId -> IO BreakpointId
|
|
435 | -internalBreakIdToBreakId hug ibi = do
|
|
436 | - (imbs, _) <- readModBreaks hug (ibi_info_mod ibi)
|
|
437 | - let CgBreakInfo{cgb_tick_id} = getInternalBreak ibi imbs
|
|
438 | - return cgb_tick_id
|
|
439 | - |
|
440 | 420 | -- | Process the result of a Seq or ResumeSeq message. #2950
|
441 | 421 | handleSeqHValueStatus :: Interp -> UnitEnv -> EvalStatus () -> IO (EvalResult ())
|
442 | 422 | handleSeqHValueStatus interp unit_env eval_status =
|
... | ... | @@ -456,16 +436,15 @@ handleSeqHValueStatus interp unit_env eval_status = |
456 | 436 | Just break -> do
|
457 | 437 | let ibi = evalBreakpointToId break
|
458 | 438 | hug = ue_home_unit_graph unit_env
|
459 | - bi <- internalBreakIdToBreakId hug ibi
|
|
460 | 439 | |
461 | 440 | -- Just case: Stopped at a breakpoint, extract SrcSpan information
|
462 | 441 | -- from the breakpoint.
|
463 | - mb_modbreaks <- getModBreaks . expectJust <$> lookupHugByModule (bi_tick_mod bi) hug
|
|
442 | + mb_modbreaks <- readModBreaks hug ibi
|
|
464 | 443 | case mb_modbreaks of
|
465 | 444 | -- Nothing case - should not occur! We should have the appropriate
|
466 | 445 | -- breakpoint information
|
467 | 446 | Nothing -> nothing_case
|
468 | - Just (_, modbreaks) -> put $ brackets . ppr $ (modBreaks_locs modbreaks) ! bi_tick_index bi
|
|
447 | + Just modbreaks -> put $ brackets . ppr $ getBreakLoc ibi modbreaks
|
|
469 | 448 | |
470 | 449 | -- resume the seq (:force) processing in the iserv process
|
471 | 450 | withForeignRef resume_ctxt_fhv $ \hval -> do
|
... | ... | @@ -751,22 +730,19 @@ wormholeRef interp _r = case interpInstance interp of |
751 | 730 | |
752 | 731 | -- | Get the breakpoint information from the ByteCode object associated to this
|
753 | 732 | -- 'HomeModInfo'.
|
754 | -getModBreaks :: HomeModInfo -> Maybe (InternalModBreaks, ModBreaks)
|
|
733 | +getModBreaks :: HomeModInfo -> Maybe InternalModBreaks
|
|
755 | 734 | getModBreaks hmi
|
756 | 735 | | Just linkable <- homeModInfoByteCode hmi,
|
757 | 736 | -- The linkable may have 'DotO's as well; only consider BCOs. See #20570.
|
758 | 737 | [cbc] <- linkableBCOs linkable
|
759 | - = bc_breaks cbc
|
|
738 | + = Just $ bc_breaks cbc
|
|
760 | 739 | | otherwise
|
761 | 740 | = Nothing -- probably object code
|
762 | 741 | |
763 | 742 | -- | Read the 'InternalModBreaks' and 'ModBreaks' of the given home 'Module'
|
764 | 743 | -- from the 'HomeUnitGraph'.
|
765 | -readModBreaks :: HomeUnitGraph -> Module -> IO (InternalModBreaks, ModBreaks)
|
|
766 | -readModBreaks hug mod = expectJust <$> readModBreaksMaybe hug mod
|
|
767 | - |
|
768 | -readModBreaksMaybe :: HomeUnitGraph -> Module -> IO (Maybe (InternalModBreaks, ModBreaks))
|
|
769 | -readModBreaksMaybe hug mod = getModBreaks . expectJust <$> HUG.lookupHugByModule mod hug
|
|
744 | +readModBreaks :: HasCallStack => HomeUnitGraph -> InternalBreakpointId -> IO (Maybe InternalModBreaks)
|
|
745 | +readModBreaks hug ibi = getModBreaks . expectJust <$> HUG.lookupHugByModule (ibi_info_mod ibi) hug
|
|
770 | 746 | |
771 | 747 | -- -----------------------------------------------------------------------------
|
772 | 748 | -- Misc utils
|
... | ... | @@ -49,6 +49,9 @@ import GHCi.RemoteTypes |
49 | 49 | import GHCi.Message ( Pipe )
|
50 | 50 | |
51 | 51 | import GHC.Platform
|
52 | +#if defined(HAVE_INTERNAL_INTERPRETER)
|
|
53 | +import GHC.Platform.Ways
|
|
54 | +#endif
|
|
52 | 55 | import GHC.Utils.TmpFs
|
53 | 56 | import GHC.Utils.Logger
|
54 | 57 | import GHC.Unit.Env
|
... | ... | @@ -124,7 +124,7 @@ byteCodeGen hsc_env this_mod binds tycs mb_modBreaks spt_entries |
124 | 124 | flattenBind (StgRec bs) = bs
|
125 | 125 | |
126 | 126 | (proto_bcos, BcM_State{..}) <-
|
127 | - runBc hsc_env this_mod $ do
|
|
127 | + runBc hsc_env this_mod mb_modBreaks $ do
|
|
128 | 128 | let flattened_binds = concatMap flattenBind (reverse lifted_binds)
|
129 | 129 | FlatBag.fromList (fromIntegral $ length flattened_binds) <$> mapM schemeTopBind flattened_binds
|
130 | 130 | |
... | ... | @@ -132,13 +132,7 @@ byteCodeGen hsc_env this_mod binds tycs mb_modBreaks spt_entries |
132 | 132 | "Proto-BCOs" FormatByteCode
|
133 | 133 | (vcat (intersperse (char ' ') (map ppr $ elemsFlatBag proto_bcos)))
|
134 | 134 | |
135 | - let all_mod_breaks = case mb_modBreaks of
|
|
136 | - Just modBreaks -> Just (internalBreaks, modBreaks)
|
|
137 | - Nothing -> Nothing
|
|
138 | - -- no modBreaks, thus drop all
|
|
139 | - -- internalBreaks? Will we ever want to have internal breakpoints in
|
|
140 | - -- a module for which we're not doing breakpoints at all? probably
|
|
141 | - cbc <- assembleBCOs profile proto_bcos tycs strings all_mod_breaks spt_entries
|
|
135 | + cbc <- assembleBCOs profile proto_bcos tycs strings internalBreaks spt_entries
|
|
142 | 136 | |
143 | 137 | -- Squash space leaks in the CompiledByteCode. This is really
|
144 | 138 | -- important, because when loading a set of modules into GHCi
|
... | ... | @@ -397,44 +391,21 @@ schemeR_wrk fvs nm original_body (args, body) |
397 | 391 | schemeER_wrk :: StackDepth -> BCEnv -> CgStgExpr -> BcM BCInstrList
|
398 | 392 | schemeER_wrk d p (StgTick (Breakpoint tick_ty tick_id fvs) rhs) = do
|
399 | 393 | code <- schemeE d 0 p rhs
|
400 | - hsc_env <- getHscEnv
|
|
401 | - current_mod <- getCurrentModule
|
|
402 | - liftIO (readModBreaksMaybe (hsc_HUG hsc_env) current_mod) >>= \case
|
|
403 | - Nothing -> pure code
|
|
404 | - Just _ -> do
|
|
405 | - platform <- profilePlatform <$> getProfile
|
|
406 | - let idOffSets = getVarOffSets platform d p fvs
|
|
407 | - ty_vars = tyCoVarsOfTypesWellScoped (tick_ty:map idType fvs)
|
|
408 | - toWord :: Maybe (Id, WordOff) -> Maybe (Id, Word)
|
|
409 | - toWord = fmap (\(i, wo) -> (i, fromIntegral wo))
|
|
410 | - breakInfo = dehydrateCgBreakInfo ty_vars (map toWord idOffSets) tick_ty tick_id
|
|
411 | - |
|
412 | - ibi <- newBreakInfo breakInfo
|
|
394 | + platform <- profilePlatform <$> getProfile
|
|
395 | + let idOffSets = getVarOffSets platform d p fvs
|
|
396 | + ty_vars = tyCoVarsOfTypesWellScoped (tick_ty:map idType fvs)
|
|
397 | + toWord :: Maybe (Id, WordOff) -> Maybe (Id, Word)
|
|
398 | + toWord = fmap (\(i, wo) -> (i, fromIntegral wo))
|
|
399 | + breakInfo = dehydrateCgBreakInfo ty_vars (map toWord idOffSets) tick_ty tick_id
|
|
400 | + |
|
401 | + -- TODO: Lookup tick_id in InternalBreakMods and if it returns Nothing then
|
|
402 | + -- we don't have Breakpoint information for this Breakpoint so might as well
|
|
403 | + -- not emit the instruction.
|
|
404 | + ibi <- newBreakInfo breakInfo
|
|
405 | + return $ BRK_FUN ibi `consOL` code
|
|
413 | 406 | |
414 | - return $ BRK_FUN ibi `consOL` code
|
|
415 | 407 | schemeER_wrk d p rhs = schemeE d 0 p rhs
|
416 | 408 | |
417 | --- TODO: WHERE TO PUT
|
|
418 | --- Determine the GHCi-allocated 'BreakArray' and module pointer for the module
|
|
419 | --- from which the breakpoint originates.
|
|
420 | --- These are stored in 'ModBreaks' as remote pointers in order to allow the BCOs
|
|
421 | --- to refer to pointers in GHCi's address space.
|
|
422 | --- They are initialized in 'GHC.HsToCore.Breakpoints.mkModBreaks', called by
|
|
423 | --- 'GHC.HsToCore.deSugar'.
|
|
424 | ---
|
|
425 | --- Breakpoints might be disabled because we're in TH, because
|
|
426 | --- @-fno-break-points@ was specified, or because a module was reloaded without
|
|
427 | --- reinitializing 'ModBreaks'.
|
|
428 | ---
|
|
429 | --- If the module stored in the breakpoint is the currently processed module, use
|
|
430 | --- the 'ModBreaks' from the state.
|
|
431 | --- If that is 'Nothing', consider breakpoints to be disabled and skip the
|
|
432 | --- instruction.
|
|
433 | ---
|
|
434 | --- If the breakpoint is inlined from another module, look it up in the HUG (home unit graph).
|
|
435 | --- If the module doesn't exist there, or if the 'ModBreaks' value is
|
|
436 | --- uninitialized, skip the instruction (i.e. return Nothing).
|
|
437 | - |
|
438 | 409 | getVarOffSets :: Platform -> StackDepth -> BCEnv -> [Id] -> [Maybe (Id, WordOff)]
|
439 | 410 | getVarOffSets platform depth env = map getOffSet
|
440 | 411 | where
|
... | ... | @@ -2630,9 +2601,9 @@ newtype BcM r = BcM (BcM_Env -> BcM_State -> IO (r, BcM_State)) |
2630 | 2601 | deriving (Functor, Applicative, Monad, MonadIO)
|
2631 | 2602 | via (ReaderT BcM_Env (StateT BcM_State IO))
|
2632 | 2603 | |
2633 | -runBc :: HscEnv -> Module -> BcM r -> IO (r, BcM_State)
|
|
2634 | -runBc hsc_env this_mod (BcM m)
|
|
2635 | - = m (BcM_Env hsc_env this_mod) (BcM_State 0 0 (mkInternalModBreaks this_mod mempty))
|
|
2604 | +runBc :: HscEnv -> Module -> Maybe ModBreaks -> BcM r -> IO (r, BcM_State)
|
|
2605 | +runBc hsc_env this_mod mbs (BcM m)
|
|
2606 | + = m (BcM_Env hsc_env this_mod) (BcM_State 0 0 (mkInternalModBreaks this_mod mbs))
|
|
2636 | 2607 | |
2637 | 2608 | instance HasDynFlags BcM where
|
2638 | 2609 | getDynFlags = hsc_dflags <$> getHscEnv
|
... | ... | @@ -45,6 +45,7 @@ import Language.Haskell.Syntax.Extension ( NoExtField ) |
45 | 45 | |
46 | 46 | import Data.Data
|
47 | 47 | import GHC.Utils.Outputable (Outputable (ppr), text, (<+>))
|
48 | +import Data.Array
|
|
48 | 49 | |
49 | 50 | {- *********************************************************************
|
50 | 51 | * *
|
... | ... | @@ -179,6 +180,8 @@ deriving instance Data (GenTickish 'TickishPassCmm) |
179 | 180 | --------------------------------------------------------------------------------
|
180 | 181 | |
181 | 182 | -- | Breakpoint tick index
|
183 | +-- newtype BreakTickIndex = BreakTickIndex Int
|
|
184 | +-- deriving (Eq, Ord, Data, Ix, NFData, Outputable)
|
|
182 | 185 | type BreakTickIndex = Int
|
183 | 186 | |
184 | 187 | -- | Breakpoint identifier.
|
... | ... | @@ -66,7 +66,8 @@ import qualified GHC |
66 | 66 | import GHC ( LoadHowMuch(..), Target(..), TargetId(..),
|
67 | 67 | Resume, SingleStep, Ghc,
|
68 | 68 | GetDocsFailure(..), pushLogHookM,
|
69 | - getModuleGraph, handleSourceError )
|
|
69 | + getModuleGraph, handleSourceError,
|
|
70 | + InternalBreakpointId(..) )
|
|
70 | 71 | import GHC.Driver.Main (hscParseModuleWithLocation, hscParseStmtWithLocation)
|
71 | 72 | import GHC.Hs.ImpExp
|
72 | 73 | import GHC.Hs
|
... | ... | @@ -78,7 +79,6 @@ import GHC.Core.TyCo.Ppr |
78 | 79 | import GHC.Types.SafeHaskell ( getSafeMode )
|
79 | 80 | import GHC.Types.SourceError ( SourceError )
|
80 | 81 | import GHC.Types.Name
|
81 | -import GHC.Types.Breakpoint
|
|
82 | 82 | import GHC.Types.Var ( varType )
|
83 | 83 | import GHC.Iface.Syntax ( showToHeader )
|
84 | 84 | import GHC.Builtin.Names
|
... | ... | @@ -1572,11 +1572,9 @@ afterRunStmt step run_result = do |
1572 | 1572 | Right names -> do
|
1573 | 1573 | show_types <- isOptionSet ShowType
|
1574 | 1574 | when show_types $ printTypeOfNames names
|
1575 | - GHC.ExecBreak names mb_info
|
|
1575 | + GHC.ExecBreak names mibi
|
|
1576 | 1576 | | first_resume : _ <- resumes
|
1577 | - -> do mbid <- maybe (pure Nothing)
|
|
1578 | - (fmap Just . liftIO . internalBreakIdToBreakId hug) mb_info
|
|
1579 | - mb_id_loc <- toBreakIdAndLocation mbid
|
|
1577 | + -> do mb_id_loc <- toBreakIdAndLocation mibi
|
|
1580 | 1578 | let bCmd = maybe "" ( \(_,l) -> onBreakCmd l ) mb_id_loc
|
1581 | 1579 | if (null bCmd)
|
1582 | 1580 | then printStoppedAtBreakInfo first_resume names
|
... | ... | @@ -1609,13 +1607,13 @@ runAllocs m = do |
1609 | 1607 | _ -> Nothing
|
1610 | 1608 | |
1611 | 1609 | toBreakIdAndLocation :: GhciMonad m
|
1612 | - => Maybe GHC.BreakpointId -> m (Maybe (Int, BreakLocation))
|
|
1610 | + => Maybe GHC.InternalBreakpointId -> m (Maybe (Int, BreakLocation))
|
|
1613 | 1611 | toBreakIdAndLocation Nothing = return Nothing
|
1614 | 1612 | toBreakIdAndLocation (Just inf) = do
|
1615 | 1613 | st <- getGHCiState
|
1616 | 1614 | return $ listToMaybe [ id_loc | id_loc@(_,loc) <- IntMap.assocs (breaks st),
|
1617 | - breakModule loc == bi_tick_mod inf,
|
|
1618 | - breakTick loc == bi_tick_index inf ]
|
|
1615 | + breakModule loc == ibi_info_mod inf,
|
|
1616 | + breakTick loc == ibi_info_index inf ]
|
|
1619 | 1617 | |
1620 | 1618 | printStoppedAtBreakInfo :: GHC.GhcMonad m => Resume -> [Name] -> m ()
|
1621 | 1619 | printStoppedAtBreakInfo res names = do
|
... | ... | @@ -3795,7 +3793,7 @@ pprStopped res = |
3795 | 3793 | <> text (GHC.resumeDecl res))
|
3796 | 3794 | <> char ',' <+> ppr (GHC.resumeSpan res)
|
3797 | 3795 | where
|
3798 | - mb_mod_name = moduleName . bi_tick_mod . fst <$> GHC.resumeBreakpointId res
|
|
3796 | + mb_mod_name = moduleName . ibi_info_mod . snd <$> GHC.resumeBreakpointId res
|
|
3799 | 3797 | |
3800 | 3798 | showUnits :: GHC.GhcMonad m => m ()
|
3801 | 3799 | showUnits = mapNonInteractiveHomeUnitsM $ \dflags -> do
|
... | ... | @@ -4350,11 +4348,11 @@ ignoreCmd argLine = withSandboxOnly ":ignore" $ do |
4350 | 4348 | case result of
|
4351 | 4349 | Left sdoc -> printForUser sdoc
|
4352 | 4350 | Right (loc, count) -> do
|
4353 | - let bi = GHC.BreakpointId
|
|
4354 | - { bi_tick_mod = breakModule loc
|
|
4355 | - , bi_tick_index = breakTick loc
|
|
4351 | + let ibi = GHC.InternalBreakpointId
|
|
4352 | + { ibi_info_mod = breakModule loc
|
|
4353 | + , ibi_info_index = breakTick loc
|
|
4356 | 4354 | }
|
4357 | - setupBreakpoint bi count
|
|
4355 | + setupBreakpoint ibi count
|
|
4358 | 4356 | |
4359 | 4357 | ignoreSwitch :: GhciMonad m => [String] -> m (Either SDoc (BreakLocation, Int))
|
4360 | 4358 | ignoreSwitch [break, count] = do
|
... | ... | @@ -4371,10 +4369,10 @@ getIgnoreCount str = |
4371 | 4369 | where
|
4372 | 4370 | sdocIgnore = text "Ignore count" <+> quotes (text str)
|
4373 | 4371 | |
4374 | -setupBreakpoint :: GhciMonad m => GHC.BreakpointId -> Int -> m()
|
|
4372 | +setupBreakpoint :: GhciMonad m => GHC.InternalBreakpointId -> Int -> m()
|
|
4375 | 4373 | setupBreakpoint loc count = do
|
4376 | 4374 | hsc_env <- GHC.getSession
|
4377 | - GHC.setupBreakpoint hsc_env loc count
|
|
4375 | + GHC.setupBreakpoint (hscInterp hsc_env) loc count
|
|
4378 | 4376 | |
4379 | 4377 | backCmd :: GhciMonad m => String -> m ()
|
4380 | 4378 | backCmd arg
|
... | ... | @@ -4450,7 +4448,7 @@ breakById inp = do |
4450 | 4448 | Left sdoc -> printForUser sdoc
|
4451 | 4449 | Right (mod, mod_info, fun_str) -> do
|
4452 | 4450 | let modBreaks = expectJust (GHC.modInfoModBreaks mod_info)
|
4453 | - findBreakAndSet mod $ \_ -> findBreakForBind fun_str modBreaks
|
|
4451 | + findBreakAndSet mod $ \_ -> findBreakForBind fun_str (snd modBreaks)
|
|
4454 | 4452 | |
4455 | 4453 | breakSyntax :: a
|
4456 | 4454 | breakSyntax = throwGhcException $ CmdLineError ("Syntax: :break [<mod>.]<func>[.<func>]\n"
|
... | ... | @@ -4729,10 +4727,10 @@ turnBreakOnOff onOff loc |
4729 | 4727 | return loc { breakEnabled = onOff }
|
4730 | 4728 | |
4731 | 4729 | setBreakFlag :: GhciMonad m => Module -> Int -> Bool ->m ()
|
4732 | -setBreakFlag md ix enaDisa = do
|
|
4730 | +setBreakFlag md ix enaDisa = do
|
|
4733 | 4731 | let enaDisaToCount True = breakOn
|
4734 | 4732 | enaDisaToCount False = breakOff
|
4735 | - setupBreakpoint (GHC.BreakpointId md ix) $ enaDisaToCount enaDisa
|
|
4733 | + setupBreakpoint (GHC.InternalBreakpointId md ix) $ enaDisaToCount enaDisa
|
|
4736 | 4734 | |
4737 | 4735 | -- ---------------------------------------------------------------------------
|
4738 | 4736 | -- User code exception handling
|
... | ... | @@ -1454,9 +1454,9 @@ run_BCO: |
1454 | 1454 | /* check for a breakpoint on the beginning of a let binding */
|
1455 | 1455 | case bci_BRK_FUN:
|
1456 | 1456 | {
|
1457 | - int arg1_brk_array, arg2_info_mod_name, arg3_info_mod_id, arg4_info_index;
|
|
1457 | + W_ arg1_brk_array, arg2_info_mod_name, arg3_info_mod_id, arg4_info_index;
|
|
1458 | 1458 | #if defined(PROFILING)
|
1459 | - int arg5_cc;
|
|
1459 | + W_ arg5_cc;
|
|
1460 | 1460 | #endif
|
1461 | 1461 | StgArrBytes *breakPoints;
|
1462 | 1462 | int returning_from_break, stop_next_breakpoint;
|
... | ... | @@ -1473,7 +1473,7 @@ run_BCO: |
1473 | 1473 | arg1_brk_array = BCO_GET_LARGE_ARG;
|
1474 | 1474 | arg2_info_mod_name = BCO_GET_LARGE_ARG;
|
1475 | 1475 | arg3_info_mod_id = BCO_GET_LARGE_ARG;
|
1476 | - arg4_info_index = BCO_GET_LARGE_ARG;
|
|
1476 | + arg4_info_index = BCO_LIT(BCO_GET_LARGE_ARG);
|
|
1477 | 1477 | #if defined(PROFILING)
|
1478 | 1478 | arg5_cc = BCO_GET_LARGE_ARG;
|
1479 | 1479 | #else
|
... | ... | @@ -1506,11 +1506,11 @@ run_BCO: |
1506 | 1506 | |
1507 | 1507 | // stop the current thread if either `stop_next_breakpoint` is
|
1508 | 1508 | // true OR if the ignore count for this particular breakpoint is zero
|
1509 | - StgInt ignore_count = ((StgInt*)breakPoints->payload)[BCO_LIT(arg4_info_index)];
|
|
1509 | + StgInt ignore_count = ((StgInt*)breakPoints->payload)[arg4_info_index];
|
|
1510 | 1510 | if (stop_next_breakpoint == false && ignore_count > 0)
|
1511 | 1511 | {
|
1512 | 1512 | // decrement and write back ignore count
|
1513 | - ((StgInt*)breakPoints->payload)[BCO_LIT(arg4_info_index)] = --ignore_count;
|
|
1513 | + ((StgInt*)breakPoints->payload)[arg4_info_index] = --ignore_count;
|
|
1514 | 1514 | }
|
1515 | 1515 | else if (stop_next_breakpoint == true || ignore_count == 0)
|
1516 | 1516 | {
|
... | ... | @@ -1560,7 +1560,7 @@ run_BCO: |
1560 | 1560 | SpW(10) = (W_)new_aps;
|
1561 | 1561 | SpW(9) = (W_)False_closure; // True <=> an exception
|
1562 | 1562 | SpW(8) = (W_)&stg_ap_ppv_info;
|
1563 | - SpW(7) = (W_)BCO_LIT(arg4_info_index);
|
|
1563 | + SpW(7) = (W_)arg4_info_index;
|
|
1564 | 1564 | SpW(6) = (W_)&stg_ap_n_info;
|
1565 | 1565 | SpW(5) = (W_)BCO_LIT(arg3_info_mod_id);
|
1566 | 1566 | SpW(4) = (W_)&stg_ap_n_info;
|