Rodrigo Mesquita pushed to branch wip/romes/step-out-11 at Glasgow Haskell Compiler / GHC

Commits:

21 changed files:

Changes:

  • compiler/GHC/ByteCode/Asm.hs
    ... ... @@ -854,8 +854,6 @@ assembleI platform i = case i of
    854 854
         emit_ bci_BRK_FUN [ Op p1, Op info_addr, Op info_unitid_addr
    
    855 855
                           , SmallOp (toW16 infox), Op np ]
    
    856 856
     
    
    857
    -  BRK_ALTS active -> emit_ bci_BRK_ALTS [SmallOp (if active then 1 else 0)]
    
    858
    -
    
    859 857
     #if MIN_VERSION_rts(1,0,3)
    
    860 858
       BCO_NAME name            -> do np <- lit1 (BCONPtrStr name)
    
    861 859
                                      emit_ bci_BCO_NAME [Op np]
    

  • compiler/GHC/ByteCode/Breakpoints.hs
    1 1
     {-# LANGUAGE RecordWildCards #-}
    
    2
    +{-# LANGUAGE DerivingStrategies #-}
    
    2 3
     
    
    3 4
     -- | Breakpoint information constructed during ByteCode generation.
    
    4 5
     --
    
    ... ... @@ -15,6 +16,7 @@ module GHC.ByteCode.Breakpoints
    15 16
     
    
    16 17
         -- ** Internal breakpoint identifier
    
    17 18
       , InternalBreakpointId(..), BreakInfoIndex
    
    19
    +  , InternalBreakLoc(..)
    
    18 20
     
    
    19 21
         -- * Operations
    
    20 22
     
    
    ... ... @@ -23,7 +25,7 @@ module GHC.ByteCode.Breakpoints
    23 25
     
    
    24 26
         -- ** Source-level information operations
    
    25 27
       , getBreakLoc, getBreakVars, getBreakDecls, getBreakCCS
    
    26
    -  , getBreakSourceId
    
    28
    +  , getBreakSourceId, getBreakSourceMod
    
    27 29
     
    
    28 30
         -- * Utils
    
    29 31
       , seqInternalModBreaks
    
    ... ... @@ -165,7 +167,7 @@ data CgBreakInfo
    165 167
        { cgb_tyvars  :: ![IfaceTvBndr] -- ^ Type variables in scope at the breakpoint
    
    166 168
        , cgb_vars    :: ![Maybe (IfaceIdBndr, Word)]
    
    167 169
        , cgb_resty   :: !IfaceType
    
    168
    -   , cgb_tick_id :: !BreakpointId
    
    170
    +   , cgb_tick_id :: !(Either InternalBreakLoc BreakpointId)
    
    169 171
          -- ^ This field records the original breakpoint tick identifier for this
    
    170 172
          -- internal breakpoint info. It is used to convert a breakpoint
    
    171 173
          -- *occurrence* index ('InternalBreakpointId') into a *definition* index
    
    ... ... @@ -173,9 +175,18 @@ data CgBreakInfo
    173 175
          --
    
    174 176
          -- The modules of breakpoint occurrence and breakpoint definition are not
    
    175 177
          -- necessarily the same: See Note [Breakpoint identifiers].
    
    178
    +     --
    
    179
    +     -- If there is no original tick identifier (that is, the breakpoint was
    
    180
    +     -- created during code generation), instead refer directly to the SrcSpan
    
    181
    +     -- we want to use for it.
    
    176 182
        }
    
    177 183
     -- See Note [Syncing breakpoint info] in GHC.Runtime.Eval
    
    178 184
     
    
    185
    +-- | Breakpoints created during code generation don't have a source-level tick
    
    186
    +-- location. Instead, we come up with one ourselves.
    
    187
    +newtype InternalBreakLoc = InternalBreakLoc SrcSpan
    
    188
    +  deriving newtype (Eq, Show, NFData, Outputable)
    
    189
    +
    
    179 190
     -- | Get an internal breakpoint info by 'InternalBreakpointId'
    
    180 191
     getInternalBreak :: InternalBreakpointId -> InternalModBreaks -> CgBreakInfo
    
    181 192
     getInternalBreak (InternalBreakpointId mod ix) imbs =
    
    ... ... @@ -196,27 +207,36 @@ assert_modules_match ibi_mod imbs_mod =
    196 207
     
    
    197 208
     -- | Get the source module and tick index for this breakpoint
    
    198 209
     -- (as opposed to the module where this breakpoint occurs, which is in 'InternalBreakpointId')
    
    199
    -getBreakSourceId :: InternalBreakpointId -> InternalModBreaks -> BreakpointId
    
    210
    +getBreakSourceId :: InternalBreakpointId -> InternalModBreaks -> Either InternalBreakLoc BreakpointId
    
    200 211
     getBreakSourceId (InternalBreakpointId ibi_mod ibi_ix) imbs =
    
    201 212
       assert_modules_match ibi_mod (imodBreaks_module imbs) $
    
    202 213
         let cgb = imodBreaks_breakInfo imbs IM.! ibi_ix
    
    203 214
          in cgb_tick_id cgb
    
    204 215
     
    
    216
    +-- | Get the source module for this breakpoint (where the breakpoint is defined)
    
    217
    +getBreakSourceMod :: InternalBreakpointId -> InternalModBreaks -> Module
    
    218
    +getBreakSourceMod (InternalBreakpointId ibi_mod ibi_ix) imbs =
    
    219
    +  assert_modules_match ibi_mod (imodBreaks_module imbs) $
    
    220
    +    let cgb = imodBreaks_breakInfo imbs IM.! ibi_ix
    
    221
    +     in case cgb_tick_id cgb of
    
    222
    +      Left InternalBreakLoc{} -> imodBreaks_module imbs
    
    223
    +      Right BreakpointId{bi_tick_mod} -> bi_tick_mod
    
    224
    +
    
    205 225
     -- | Get the source span for this breakpoint
    
    206 226
     getBreakLoc :: (Module -> IO ModBreaks) -> InternalBreakpointId -> InternalModBreaks -> IO SrcSpan
    
    207
    -getBreakLoc = getBreakXXX modBreaks_locs
    
    227
    +getBreakLoc = getBreakXXX modBreaks_locs (\(InternalBreakLoc x) -> x)
    
    208 228
     
    
    209 229
     -- | Get the vars for this breakpoint
    
    210 230
     getBreakVars :: (Module -> IO ModBreaks) -> InternalBreakpointId -> InternalModBreaks -> IO [OccName]
    
    211
    -getBreakVars = getBreakXXX modBreaks_vars
    
    231
    +getBreakVars = getBreakXXX modBreaks_vars (const [])
    
    212 232
     
    
    213 233
     -- | Get the decls for this breakpoint
    
    214 234
     getBreakDecls :: (Module -> IO ModBreaks) -> InternalBreakpointId -> InternalModBreaks -> IO [String]
    
    215
    -getBreakDecls = getBreakXXX modBreaks_decls
    
    235
    +getBreakDecls = getBreakXXX modBreaks_decls (const [])
    
    216 236
     
    
    217 237
     -- | Get the decls for this breakpoint
    
    218
    -getBreakCCS :: (Module -> IO ModBreaks) -> InternalBreakpointId -> InternalModBreaks -> IO (String, String)
    
    219
    -getBreakCCS = getBreakXXX modBreaks_ccs
    
    238
    +getBreakCCS :: (Module -> IO ModBreaks) -> InternalBreakpointId -> InternalModBreaks -> IO (Maybe (String, String))
    
    239
    +getBreakCCS = getBreakXXX (fmap Just . modBreaks_ccs) (const Nothing)
    
    220 240
     
    
    221 241
     -- | Internal utility to access a ModBreaks field at a particular breakpoint index
    
    222 242
     --
    
    ... ... @@ -228,14 +248,17 @@ getBreakCCS = getBreakXXX modBreaks_ccs
    228 248
     -- 'ModBreaks'. When the tick module is different, we need to look up the
    
    229 249
     -- 'ModBreaks' in the HUG for that other module.
    
    230 250
     --
    
    251
    +-- When there is no tick module (the breakpoint was generated at codegen), use
    
    252
    +-- the function on internal mod breaks.
    
    253
    +--
    
    231 254
     -- To avoid cyclic dependencies, we instead receive a function that looks up
    
    232 255
     -- the 'ModBreaks' given a 'Module'
    
    233
    -getBreakXXX :: (ModBreaks -> Array BreakTickIndex a) -> (Module -> IO ModBreaks) -> InternalBreakpointId -> InternalModBreaks -> IO a
    
    234
    -getBreakXXX view lookupModule (InternalBreakpointId ibi_mod ibi_ix) imbs =
    
    256
    +getBreakXXX :: (ModBreaks -> Array BreakTickIndex a) -> (InternalBreakLoc -> a) -> (Module -> IO ModBreaks) -> InternalBreakpointId -> InternalModBreaks -> IO a
    
    257
    +getBreakXXX view viewInternal lookupModule (InternalBreakpointId ibi_mod ibi_ix) imbs =
    
    235 258
       assert_modules_match ibi_mod (imodBreaks_module imbs) $ do
    
    236 259
         let cgb = imodBreaks_breakInfo imbs IM.! ibi_ix
    
    237 260
         case cgb_tick_id cgb of
    
    238
    -      BreakpointId{bi_tick_mod, bi_tick_index}
    
    261
    +      Right BreakpointId{bi_tick_mod, bi_tick_index}
    
    239 262
             | bi_tick_mod == ibi_mod
    
    240 263
             -> do
    
    241 264
               let these_mbs = imodBreaks_modBreaks imbs
    
    ... ... @@ -244,6 +267,8 @@ getBreakXXX view lookupModule (InternalBreakpointId ibi_mod ibi_ix) imbs =
    244 267
             -> do
    
    245 268
               other_mbs <- lookupModule bi_tick_mod
    
    246 269
               return $ view other_mbs ! bi_tick_index
    
    270
    +      Left l ->
    
    271
    +          return $ viewInternal l
    
    247 272
     
    
    248 273
     --------------------------------------------------------------------------------
    
    249 274
     -- Instances
    

  • compiler/GHC/ByteCode/Instr.hs
    ... ... @@ -260,10 +260,6 @@ data BCInstr
    260 260
        -- Breakpoints
    
    261 261
        | BRK_FUN          !InternalBreakpointId
    
    262 262
     
    
    263
    -   -- An internal breakpoint for triggering a break on any case alternative
    
    264
    -   -- See Note [Debugger: BRK_ALTS]
    
    265
    -   | BRK_ALTS         !Bool {- enabled? -}
    
    266
    -
    
    267 263
     #if MIN_VERSION_rts(1,0,3)
    
    268 264
        -- | A "meta"-instruction for recording the name of a BCO for debugging purposes.
    
    269 265
        -- These are ignored by the interpreter but helpfully printed by the disassmbler.
    
    ... ... @@ -458,7 +454,6 @@ instance Outputable BCInstr where
    458 454
                                  = text "BRK_FUN" <+> text "<breakarray>"
    
    459 455
                                    <+> ppr info_mod <+> ppr infox
    
    460 456
                                    <+> text "<cc>"
    
    461
    -   ppr (BRK_ALTS active)     = text "BRK_ALTS" <+> ppr active
    
    462 457
     #if MIN_VERSION_rts(1,0,3)
    
    463 458
        ppr (BCO_NAME nm)         = text "BCO_NAME" <+> text (show nm)
    
    464 459
     #endif
    
    ... ... @@ -584,7 +579,6 @@ bciStackUse OP_INDEX_ADDR{} = 0
    584 579
     
    
    585 580
     bciStackUse SWIZZLE{}             = 0
    
    586 581
     bciStackUse BRK_FUN{}             = 0
    
    587
    -bciStackUse BRK_ALTS{}            = 0
    
    588 582
     
    
    589 583
     -- These insns actually reduce stack use, but we need the high-tide level,
    
    590 584
     -- so can't use this info.  Not that it matters much.
    

  • compiler/GHC/Linker/Loader.hs
    ... ... @@ -58,6 +58,7 @@ import GHCi.RemoteTypes
    58 58
     import GHC.Iface.Load
    
    59 59
     import GHCi.Message (ConInfoTable(..), LoadedDLL)
    
    60 60
     
    
    61
    +import GHC.ByteCode.Breakpoints
    
    61 62
     import GHC.ByteCode.Linker
    
    62 63
     import GHC.ByteCode.Asm
    
    63 64
     import GHC.ByteCode.Types
    
    ... ... @@ -1711,8 +1712,10 @@ allocateCCS interp ce mbss
    1711 1712
                   let count = 1 + (maybe 0 fst $ IM.lookupMax imodBreaks_breakInfo)
    
    1712 1713
                   let ccs = IM.map
    
    1713 1714
                         (\info ->
    
    1714
    -                      fromMaybe (toRemotePtr nullPtr)
    
    1715
    -                        (M.lookup (cgb_tick_id info) ccss)
    
    1715
    +                      case cgb_tick_id info of
    
    1716
    +                        Right bi -> fromMaybe (toRemotePtr nullPtr)
    
    1717
    +                          (M.lookup bi ccss)
    
    1718
    +                        Left InternalBreakLoc{} -> toRemotePtr nullPtr
    
    1716 1719
                         )
    
    1717 1720
                         imodBreaks_breakInfo
    
    1718 1721
                   assertPpr (count == length ccs)
    

  • compiler/GHC/Runtime/Debugger/Breakpoints.hs
    ... ... @@ -253,8 +253,11 @@ mkBreakpointOccurrences = do
    253 253
           let imod = modBreaks_module $ imodBreaks_modBreaks ibrks
    
    254 254
           IntMap.foldrWithKey (\info_ix cgi bmp -> do
    
    255 255
               let ibi = InternalBreakpointId imod info_ix
    
    256
    -          let BreakpointId tick_mod tick_ix = cgb_tick_id cgi
    
    257
    -          extendModuleEnvWith (IntMap.unionWith (S.<>)) bmp tick_mod (IntMap.singleton tick_ix [ibi])
    
    256
    +          case cgb_tick_id cgi of
    
    257
    +            Right (BreakpointId tick_mod tick_ix)
    
    258
    +              -> extendModuleEnvWith (IntMap.unionWith (S.<>)) bmp tick_mod (IntMap.singleton tick_ix [ibi])
    
    259
    +            Left _
    
    260
    +              -> bmp
    
    258 261
             ) bmp0 (imodBreaks_breakInfo ibrks)
    
    259 262
     
    
    260 263
     --------------------------------------------------------------------------------
    
    ... ... @@ -287,7 +290,7 @@ getCurrentBreakModule = do
    287 290
             Nothing -> pure Nothing
    
    288 291
             Just ibi -> do
    
    289 292
               brks <- readIModBreaks hug ibi
    
    290
    -          return $ Just $ bi_tick_mod $ getBreakSourceId ibi brks
    
    293
    +          return $ Just $ getBreakSourceMod ibi brks
    
    291 294
           ix ->
    
    292 295
               Just <$> getHistoryModule hug (resumeHistory r !! (ix-1))
    
    293 296
     

  • compiler/GHC/Runtime/Eval.hs
    ... ... @@ -151,7 +151,7 @@ getHistoryModule :: HUG.HomeUnitGraph -> History -> IO Module
    151 151
     getHistoryModule hug hist = do
    
    152 152
       let ibi = historyBreakpointId hist
    
    153 153
       brks <- readIModBreaks hug ibi
    
    154
    -  return $ bi_tick_mod $ getBreakSourceId ibi brks
    
    154
    +  return $ getBreakSourceMod ibi brks
    
    155 155
     
    
    156 156
     getHistorySpan :: HUG.HomeUnitGraph -> History -> IO SrcSpan
    
    157 157
     getHistorySpan hug hist = do
    

  • compiler/GHC/StgToByteCode.hs
    ... ... @@ -63,7 +63,7 @@ import GHC.StgToCmm.Closure ( NonVoid(..), fromNonVoid, idPrimRepU,
    63 63
                                   assertNonVoidIds, assertNonVoidStgArgs )
    
    64 64
     import GHC.StgToCmm.Layout
    
    65 65
     import GHC.Runtime.Heap.Layout hiding (WordOff, ByteOff, wordsToBytes)
    
    66
    -import GHC.Runtime.Interpreter ( interpreterProfiled )
    
    66
    +import GHC.Runtime.Interpreter ( interpreterProfiled, readIModModBreaks )
    
    67 67
     import GHC.Data.Bitmap
    
    68 68
     import GHC.Data.FlatBag as FlatBag
    
    69 69
     import GHC.Data.OrdList
    
    ... ... @@ -99,6 +99,7 @@ import GHC.CoreToIface
    99 99
     import Control.Monad.IO.Class
    
    100 100
     import Control.Monad.Trans.Reader (ReaderT(..))
    
    101 101
     import Control.Monad.Trans.State  (StateT(..))
    
    102
    +import Data.Array ((!))
    
    102 103
     
    
    103 104
     -- -----------------------------------------------------------------------------
    
    104 105
     -- Generating byte code for a complete module
    
    ... ... @@ -393,26 +394,26 @@ schemeR_wrk fvs nm original_body (args, body)
    393 394
     -- | Introduce break instructions for ticked expressions.
    
    394 395
     -- If no breakpoint information is available, the instruction is omitted.
    
    395 396
     schemeER_wrk :: StackDepth -> BCEnv -> CgStgExpr -> BcM BCInstrList
    
    396
    -schemeER_wrk d p (StgTick (Breakpoint tick_ty tick_id fvs) rhs) = do
    
    397
    -  code <- schemeE d 0 p rhs
    
    398
    -  mb_current_mod_breaks <- getCurrentModBreaks
    
    399
    -  case mb_current_mod_breaks of
    
    400
    -    -- if we're not generating ModBreaks for this module for some reason, we
    
    401
    -    -- can't store breakpoint occurrence information.
    
    402
    -    Nothing -> pure code
    
    403
    -    Just current_mod_breaks -> do
    
    404
    -      platform <- profilePlatform <$> getProfile
    
    405
    -      let idOffSets = getVarOffSets platform d p fvs
    
    406
    -          ty_vars   = tyCoVarsOfTypesWellScoped (tick_ty:map idType fvs)
    
    407
    -          toWord :: Maybe (Id, WordOff) -> Maybe (Id, Word)
    
    408
    -          toWord = fmap (\(i, wo) -> (i, fromIntegral wo))
    
    409
    -          breakInfo = dehydrateCgBreakInfo ty_vars (map toWord idOffSets) tick_ty tick_id
    
    397
    +schemeER_wrk d p (StgTick bp@(Breakpoint tick_ty tick_id fvs) rhs) = do
    
    398
    +  platform <- profilePlatform <$> getProfile
    
    399
    +
    
    400
    +  -- When we find a tick we update the "last breakpoint location".
    
    401
    +  -- We use it when constructing step-out BRK_FUNs in doCase
    
    402
    +  -- See Note [Stepout breakpoint locations]
    
    403
    +  code <- withBreakTick bp $ schemeE d 0 p rhs
    
    404
    +
    
    405
    +  let idOffSets = getVarOffSets platform d p fvs
    
    406
    +      ty_vars   = tyCoVarsOfTypesWellScoped (tick_ty:map idType fvs)
    
    407
    +      toWord :: Maybe (Id, WordOff) -> Maybe (Id, Word)
    
    408
    +      toWord = fmap (\(i, wo) -> (i, fromIntegral wo))
    
    409
    +      breakInfo = dehydrateCgBreakInfo ty_vars (map toWord idOffSets) tick_ty (Right tick_id)
    
    410 410
     
    
    411
    -      let info_mod = modBreaks_module current_mod_breaks
    
    412
    -      infox <- newBreakInfo breakInfo
    
    411
    +  mibi <- newBreakInfo breakInfo
    
    412
    +
    
    413
    +  return $ case mibi of
    
    414
    +    Nothing  -> code
    
    415
    +    Just ibi -> BRK_FUN ibi `consOL` code
    
    413 416
     
    
    414
    -      let breakInstr = BRK_FUN (InternalBreakpointId info_mod infox)
    
    415
    -      return $ breakInstr `consOL` code
    
    416 417
     schemeER_wrk d p rhs = schemeE d 0 p rhs
    
    417 418
     
    
    418 419
     getVarOffSets :: Platform -> StackDepth -> BCEnv -> [Id] -> [Maybe (Id, WordOff)]
    
    ... ... @@ -748,12 +749,21 @@ doTailCall init_d s p fn args = do
    748 749
     
    
    749 750
       where
    
    750 751
       do_pushes !d [] reps = do
    
    751
    -        assert (null reps) return ()
    
    752
    -        (push_fn, sz) <- pushAtom d p (StgVarArg fn)
    
    753 752
             platform <- profilePlatform <$> getProfile
    
    754
    -        assert (sz == wordSize platform) return ()
    
    755
    -        let slide = mkSlideB platform (d - init_d + wordSize platform) (init_d - s)
    
    756
    -        return (push_fn `appOL` (slide `appOL` unitOL ENTER))
    
    753
    +        assert (null reps) return ()
    
    754
    +        case lookupBCEnv_maybe fn p of
    
    755
    +          Just d_v
    
    756
    +            | d - d_v == 0  -- shortcut; the first thing on the stack is what we want to enter,
    
    757
    +            , d_v <= init_d -- and it is between init_d and sequel (which would be dropped)
    
    758
    +            -> do
    
    759
    +              let slide = mkSlideB platform (d - init_d + wordSize platform)
    
    760
    +                                            (init_d - s - wordSize platform)
    
    761
    +              return (slide `appOL` unitOL ENTER)
    
    762
    +          _ -> do
    
    763
    +              (push_fn, sz) <- pushAtom d p (StgVarArg fn)
    
    764
    +              assert (sz == wordSize platform) return ()
    
    765
    +              let slide = mkSlideB platform (d - init_d + wordSize platform) (init_d - s)
    
    766
    +              return (push_fn `appOL` (slide `appOL` unitOL ENTER))
    
    757 767
       do_pushes !d args reps = do
    
    758 768
           let (push_apply, n, rest_of_reps) = findPushSeq reps
    
    759 769
               (these_args, rest_of_args) = splitAt n args
    
    ... ... @@ -1325,19 +1335,35 @@ doCase d s p scrut bndr alts
    1325 1335
                | ubx_tuple_frame    = SLIDE 0 3 `consOL` alt_final1
    
    1326 1336
                | otherwise          = SLIDE 0 1 `consOL` alt_final1
    
    1327 1337
     
    
    1328
    -         -- When entering a case continuation BCO, the stack is always headed
    
    1329
    -         -- by the stg_ret frame and the stg_ctoi frame that returned to it.
    
    1330
    -         -- See Note [Stack layout when entering run_BCO]
    
    1331
    -         --
    
    1332
    -         -- Right after the breakpoint instruction, a case continuation BCO
    
    1333
    -         -- drops the stg_ret and stg_ctoi frame headers (see alt_final1,
    
    1334
    -         -- alt_final2), leaving the stack with the scrutinee followed by the
    
    1335
    -         -- free variables (with depth==d_bndr)
    
    1336
    -         alt_final
    
    1337
    -           | gopt Opt_InsertBreakpoints (hsc_dflags hsc_env)
    
    1338
    -                                -- See Note [Debugger: BRK_ALTS]
    
    1339
    -                                = BRK_ALTS False `consOL` alt_final2
    
    1340
    -           | otherwise          = alt_final2
    
    1338
    +     -- When entering a case continuation BCO, the stack is always headed
    
    1339
    +     -- by the stg_ret frame and the stg_ctoi frame that returned to it.
    
    1340
    +     -- See Note [Stack layout when entering run_BCO]
    
    1341
    +     --
    
    1342
    +     -- Right after the breakpoint instruction, a case continuation BCO
    
    1343
    +     -- drops the stg_ret and stg_ctoi frame headers (see alt_final1,
    
    1344
    +     -- alt_final2), leaving the stack with the scrutinee followed by the
    
    1345
    +     -- free variables (with depth==d_bndr)
    
    1346
    +     alt_final <- getLastBreakTick >>= \case
    
    1347
    +       Just (Breakpoint tick_ty tick_id fvs)
    
    1348
    +         | gopt Opt_InsertBreakpoints (hsc_dflags hsc_env)
    
    1349
    +         -- Construct an internal breakpoint to put at the start of this case
    
    1350
    +         -- continuation BCO, for step-out.
    
    1351
    +         -- See Note [Debugger: Stepout internal break locs]
    
    1352
    +         -> do
    
    1353
    +          internal_tick_loc <- makeCaseInternalBreakLoc tick_id
    
    1354
    +
    
    1355
    +          -- same fvs available in the case expression are available in the case continuation
    
    1356
    +          let idOffSets = getVarOffSets platform d p fvs
    
    1357
    +              ty_vars   = tyCoVarsOfTypesWellScoped (tick_ty:map idType fvs)
    
    1358
    +              toWord :: Maybe (Id, WordOff) -> Maybe (Id, Word)
    
    1359
    +              toWord = fmap (\(i, wo) -> (i, fromIntegral wo))
    
    1360
    +              breakInfo = dehydrateCgBreakInfo ty_vars (map toWord idOffSets) tick_ty (Left internal_tick_loc)
    
    1361
    +
    
    1362
    +          mibi <- newBreakInfo breakInfo
    
    1363
    +          return $ case mibi of
    
    1364
    +            Nothing  -> alt_final2
    
    1365
    +            Just ibi -> BRK_FUN ibi `consOL` alt_final2
    
    1366
    +       _ -> pure alt_final2
    
    1341 1367
     
    
    1342 1368
          add_bco_name <- shouldAddBcoName
    
    1343 1369
          let
    
    ... ... @@ -1357,72 +1383,122 @@ doCase d s p scrut bndr alts
    1357 1383
                       _     -> panic "schemeE(StgCase).push_alts"
    
    1358 1384
                 in return (PUSH_ALTS alt_bco scrut_rep `consOL` scrut_code)
    
    1359 1385
     
    
    1386
    +-- | Come up with an 'InternalBreakLoc' from the location of the given 'BreakpointId'.
    
    1387
    +-- See also Note [Debugger: Stepout internal break locs]
    
    1388
    +makeCaseInternalBreakLoc :: BreakpointId -> BcM InternalBreakLoc
    
    1389
    +makeCaseInternalBreakLoc bid = do
    
    1390
    +  hug         <- hsc_HUG <$> getHscEnv
    
    1391
    +  curr_mod    <- getCurrentModule
    
    1392
    +  mb_mod_brks <- getCurrentModBreaks
    
    1393
    +
    
    1394
    +  InternalBreakLoc <$> case bid of
    
    1395
    +    BreakpointId{bi_tick_mod, bi_tick_index}
    
    1396
    +      | bi_tick_mod == curr_mod
    
    1397
    +      , Just these_mbs <- mb_mod_brks
    
    1398
    +      -> do
    
    1399
    +        return $ modBreaks_locs these_mbs ! bi_tick_index
    
    1400
    +      | otherwise
    
    1401
    +      -> do
    
    1402
    +        other_mbs <- liftIO $ readIModModBreaks hug bi_tick_mod
    
    1403
    +        return $ modBreaks_locs other_mbs ! bi_tick_index
    
    1404
    +
    
    1360 1405
     {-
    
    1361
    -Note [Debugger: BRK_ALTS]
    
    1362
    -~~~~~~~~~~~~~~~~~~~~~~~~~
    
    1363
    -As described in Note [Debugger: Step-out] in rts/Interpreter.c, to implement
    
    1364
    -the stepping-out debugger feature we traverse the stack at runtime, identify
    
    1365
    -the first continuation BCO, and explicitly enable that BCO's breakpoint thus
    
    1366
    -ensuring that we stop exactly when we return to the continuation.
    
    1367
    -
    
    1368
    -However, case continuation BCOs (produced by PUSH_ALTS and which merely compute
    
    1369
    -which case alternative BCO to enter next) contain no user-facing breakpoint
    
    1370
    -ticks (BRK_FUN). While we could in principle add breakpoints in case continuation
    
    1371
    -BCOs, there are a few reasons why this is not an attractive option:
    
    1372
    -
    
    1373
    -  1) It's not useful to a user stepping through the program to always have a
    
    1374
    -  breakpoint after the scrutinee is evaluated but before the case alternative
    
    1375
    -  is selected. The source span associated with such a breakpoint would also be
    
    1376
    -  slightly awkward to choose.
    
    1377
    -
    
    1378
    -  2) It's not easy to add a breakpoint tick before the case alternatives because in
    
    1379
    -  essentially all internal representations they are given as a list of Alts
    
    1380
    -  rather than an expression.
    
    1381
    -
    
    1382
    -To provide the debugger a way to break in a case continuation
    
    1383
    -despite the BCOs' lack of BRK_FUNs, we introduce an alternative
    
    1384
    -type of breakpoint, represented by the BRK_ALTS instruction,
    
    1385
    -at the start of every case continuation BCO. For instance,
    
    1386
    -
    
    1387
    -    case x of
    
    1388
    -      0# -> ...
    
    1389
    -      _  -> ...
    
    1390
    -
    
    1391
    -will produce a continuation of the form (N.B. the below bytecode
    
    1392
    -is simplified):
    
    1393
    -
    
    1394
    -    PUSH_ALTS P
    
    1395
    -      BRK_ALTS 0
    
    1396
    -      TESTEQ_I 0 lblA
    
    1397
    -      PUSH_BCO
    
    1398
    -        BRK_FUN 0
    
    1399
    -        -- body of 0# alternative
    
    1400
    -      ENTER
    
    1401
    -
    
    1402
    -      lblA:
    
    1403
    -      PUSH_BCO
    
    1404
    -        BRK_FUN 1
    
    1405
    -        -- body of wildcard alternative
    
    1406
    -      ENTER
    
    1407
    -
    
    1408
    -When enabled (by its single boolean operand), the BRK_ALTS instruction causes
    
    1409
    -the program to break at the next encountered breakpoint (implemented
    
    1410
    -by setting the TSO's TSO_STOP_NEXT_BREAKPOINT flag). Since the case
    
    1411
    -continuation BCO will ultimately jump to one of the alternatives (each of
    
    1412
    -which having its own BRK_FUN) we are guaranteed to stop in the taken alternative.
    
    1413
    -
    
    1414
    -It's important that BRK_ALTS (just like BRK_FUN) is the first instruction of
    
    1415
    -the BCO, since that's where the debugger will look to enable it at runtime.
    
    1416
    -
    
    1417
    -KNOWN ISSUES:
    
    1418
    --------------
    
    1419
    -This implementation of BRK_ALTS that modifies the first argument of the
    
    1420
    -bytecode to enable it does not allow multi-threaded debugging because the BCO
    
    1421
    -object is shared across threads and enabling the breakpoint in one will enable
    
    1422
    -it in all other threads too. This will have to change to support multi-threads
    
    1423
    -debugging.
    
    1424
    -
    
    1425
    -The progress towards multi-threaded debugging is tracked by #26064
    
    1406
    +Note [Debugger: Stepout internal break locs]
    
    1407
    +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    1408
    +Step-out tells the interpreter to run until the current function
    
    1409
    +returns to where it was called from, and stop there.
    
    1410
    +
    
    1411
    +This is achieved by enabling the BRK_FUN found on the first RET_BCO
    
    1412
    +frame on the stack (See [Note Debugger: Step-out]).
    
    1413
    +
    
    1414
    +Case continuation BCOs (which select an alternative branch) must
    
    1415
    +therefore be headed by a BRK_FUN. An example:
    
    1416
    +
    
    1417
    +    f x = case g x of <--- end up here
    
    1418
    +        1 -> ...
    
    1419
    +        2 -> ...
    
    1420
    +
    
    1421
    +    g y = ... <--- step out from here
    
    1422
    +
    
    1423
    +- `g` will return a value to the case continuation BCO in `f`
    
    1424
    +- The case continuation BCO will receive the value returned from g
    
    1425
    +- Match on it and push the alternative continuation for that branch
    
    1426
    +- And then enter that alternative.
    
    1427
    +
    
    1428
    +If we step-out of `g`, the first RET_BCO on the stack is the case
    
    1429
    +continuation of `f` -- execution should stop at its start, before
    
    1430
    +selecting an alternative. (One might ask, "why not enable the breakpoint
    
    1431
    +in the alternative instead?", because the alternative continuation is
    
    1432
    +only pushed to the stack *after* it is selected by the case cont. BCO)
    
    1433
    +
    
    1434
    +However, the case cont. BCO is not associated with any source-level
    
    1435
    +tick, it is merely the glue code which selects alternatives which do
    
    1436
    +have source level ticks. Therefore, we have to come up at code
    
    1437
    +generation time with a breakpoint location ('InternalBreakLoc') to
    
    1438
    +display to the user when it is stopped there.
    
    1439
    +
    
    1440
    +Our solution is to use the last tick seen just before reaching the case
    
    1441
    +continuation. This is robust because a case continuation will thus
    
    1442
    +always have a relevant breakpoint location:
    
    1443
    +
    
    1444
    +    - The source location will be the last source-relevant expression
    
    1445
    +      executed before the continuation is pushed
    
    1446
    +
    
    1447
    +    - So the source location will point to the thing you've just stepped
    
    1448
    +      out of
    
    1449
    +
    
    1450
    +    - Doing :step-local from there will put you on the selected
    
    1451
    +      alternative (which at the source level may also be the e.g. next
    
    1452
    +      line in a do-block)
    
    1453
    +
    
    1454
    +Examples, using angle brackets (<<...>>) to denote the breakpoint span:
    
    1455
    +
    
    1456
    +    f x = case <<g x>> {- step in here -} of
    
    1457
    +        1 -> ...
    
    1458
    +        2 -> ...>
    
    1459
    +
    
    1460
    +    g y = <<...>> <--- step out from here
    
    1461
    +
    
    1462
    +    ...
    
    1463
    +
    
    1464
    +    f x = <<case g x of <--- end up here, whole case highlighted
    
    1465
    +        1 -> ...
    
    1466
    +        2 -> ...>>
    
    1467
    +
    
    1468
    +    doing :step-local ...
    
    1469
    +
    
    1470
    +    f x = case g x of
    
    1471
    +        1 -> <<...>> <--- stop in the alternative
    
    1472
    +        2 -> ...
    
    1473
    +
    
    1474
    +A second example based on T26042d2, where the source is a do-block IO
    
    1475
    +action, optimised to a chain of `case expressions`.
    
    1476
    +
    
    1477
    +    main = do
    
    1478
    +      putStrLn "hello1"
    
    1479
    +      <<f>> <--- step-in here
    
    1480
    +      putStrLn "hello3"
    
    1481
    +      putStrLn "hello4"
    
    1482
    +
    
    1483
    +    f = do
    
    1484
    +      <<putStrLn "hello2.1">> <--- step-out from here
    
    1485
    +      putStrLn "hello2.2"
    
    1486
    +
    
    1487
    +    ...
    
    1488
    +
    
    1489
    +    main = do
    
    1490
    +      putStrLn "hello1"
    
    1491
    +      <<f>> <--- end up here again, the previously executed expression
    
    1492
    +      putStrLn "hello3"
    
    1493
    +      putStrLn "hello4"
    
    1494
    +
    
    1495
    +    doing step/step-local ...
    
    1496
    +
    
    1497
    +    main = do
    
    1498
    +      putStrLn "hello1"
    
    1499
    +      f
    
    1500
    +      <<putStrLn "hello3">> <--- straight to the next line
    
    1501
    +      putStrLn "hello4"
    
    1426 1502
     -}
    
    1427 1503
     
    
    1428 1504
     -- -----------------------------------------------------------------------------
    
    ... ... @@ -2625,6 +2701,7 @@ data BcM_Env
    2625 2701
             { bcm_hsc_env    :: !HscEnv
    
    2626 2702
             , bcm_module     :: !Module -- current module (for breakpoints)
    
    2627 2703
             , modBreaks      :: !(Maybe ModBreaks)
    
    2704
    +        , last_bp_tick   :: !(Maybe StgTickish)
    
    2628 2705
             }
    
    2629 2706
     
    
    2630 2707
     data BcM_State
    
    ... ... @@ -2643,7 +2720,7 @@ newtype BcM r = BcM (BcM_Env -> BcM_State -> IO (r, BcM_State))
    2643 2720
     
    
    2644 2721
     runBc :: HscEnv -> Module -> Maybe ModBreaks -> BcM r -> IO (r, BcM_State)
    
    2645 2722
     runBc hsc_env this_mod mbs (BcM m)
    
    2646
    -   = m (BcM_Env hsc_env this_mod mbs) (BcM_State 0 0 IntMap.empty)
    
    2723
    +   = m (BcM_Env hsc_env this_mod mbs Nothing) (BcM_State 0 0 IntMap.empty)
    
    2647 2724
     
    
    2648 2725
     instance HasDynFlags BcM where
    
    2649 2726
         getDynFlags = hsc_dflags <$> getHscEnv
    
    ... ... @@ -2673,14 +2750,19 @@ getLabelsBc n = BcM $ \_ st ->
    2673 2750
       let ctr = nextlabel st
    
    2674 2751
        in return (coerce [ctr .. ctr+n-1], st{nextlabel = ctr+n})
    
    2675 2752
     
    
    2676
    -newBreakInfo :: CgBreakInfo -> BcM Int
    
    2677
    -newBreakInfo info = BcM $ \_ st ->
    
    2678
    -  let ix = breakInfoIdx st
    
    2679
    -      st' = st
    
    2680
    -        { breakInfo = IntMap.insert ix info (breakInfo st)
    
    2681
    -        , breakInfoIdx = ix + 1
    
    2682
    -        }
    
    2683
    -  in return (ix, st')
    
    2753
    +newBreakInfo :: CgBreakInfo -> BcM (Maybe InternalBreakpointId)
    
    2754
    +newBreakInfo info = BcM $ \env st -> do
    
    2755
    +  -- if we're not generating ModBreaks for this module for some reason, we
    
    2756
    +  -- can't store breakpoint occurrence information.
    
    2757
    +  case modBreaks env of
    
    2758
    +    Nothing -> pure (Nothing, st)
    
    2759
    +    Just modBreaks -> do
    
    2760
    +      let ix = breakInfoIdx st
    
    2761
    +          st' = st
    
    2762
    +            { breakInfo = IntMap.insert ix info (breakInfo st)
    
    2763
    +            , breakInfoIdx = ix + 1
    
    2764
    +            }
    
    2765
    +      return (Just $ InternalBreakpointId (modBreaks_module modBreaks) ix, st')
    
    2684 2766
     
    
    2685 2767
     getCurrentModule :: BcM Module
    
    2686 2768
     getCurrentModule = BcM $ \env st -> return (bcm_module env, st)
    
    ... ... @@ -2688,12 +2770,20 @@ getCurrentModule = BcM $ \env st -> return (bcm_module env, st)
    2688 2770
     getCurrentModBreaks :: BcM (Maybe ModBreaks)
    
    2689 2771
     getCurrentModBreaks = BcM $ \env st -> return (modBreaks env, st)
    
    2690 2772
     
    
    2773
    +withBreakTick :: StgTickish -> BcM a -> BcM a
    
    2774
    +withBreakTick bp (BcM act) = BcM $ \env st ->
    
    2775
    +  act env{last_bp_tick=Just bp} st
    
    2776
    +
    
    2777
    +getLastBreakTick :: BcM (Maybe StgTickish)
    
    2778
    +getLastBreakTick = BcM $ \env st ->
    
    2779
    +  pure (last_bp_tick env, st)
    
    2780
    +
    
    2691 2781
     tickFS :: FastString
    
    2692 2782
     tickFS = fsLit "ticked"
    
    2693 2783
     
    
    2694 2784
     -- Dehydrating CgBreakInfo
    
    2695 2785
     
    
    2696
    -dehydrateCgBreakInfo :: [TyVar] -> [Maybe (Id, Word)] -> Type -> BreakpointId -> CgBreakInfo
    
    2786
    +dehydrateCgBreakInfo :: [TyVar] -> [Maybe (Id, Word)] -> Type -> Either InternalBreakLoc BreakpointId -> CgBreakInfo
    
    2697 2787
     dehydrateCgBreakInfo ty_vars idOffSets tick_ty bid =
    
    2698 2788
               CgBreakInfo
    
    2699 2789
                 { cgb_tyvars = map toIfaceTvBndr ty_vars
    

  • ghc/GHCi/UI.hs
    ... ... @@ -45,7 +45,7 @@ import GHC.Runtime.Eval (mkTopLevEnv)
    45 45
     import GHC.Runtime.Eval.Utils
    
    46 46
     
    
    47 47
     -- The GHC interface
    
    48
    -import GHC.ByteCode.Breakpoints (imodBreaks_modBreaks, InternalBreakpointId(..), getBreakSourceId)
    
    48
    +import GHC.ByteCode.Breakpoints (imodBreaks_modBreaks, InternalBreakpointId(..), getBreakSourceId, getBreakSourceMod)
    
    49 49
     import GHC.Runtime.Interpreter
    
    50 50
     import GHCi.RemoteTypes
    
    51 51
     import GHCi.BreakArray( breakOn, breakOff )
    
    ... ... @@ -1621,7 +1621,7 @@ toBreakIdAndLocation (Just inf) = do
    1621 1621
       brks <- liftIO $ readIModBreaks hug inf
    
    1622 1622
       let bi = getBreakSourceId inf brks
    
    1623 1623
       return $ listToMaybe [ id_loc | id_loc@(_,loc) <- IntMap.assocs (breaks st),
    
    1624
    -                                  breakId loc == bi ]
    
    1624
    +                                  Right (breakId loc) == bi ]
    
    1625 1625
     
    
    1626 1626
     printStoppedAtBreakInfo :: GHC.GhcMonad m => Resume -> [Name] -> m ()
    
    1627 1627
     printStoppedAtBreakInfo res names = do
    
    ... ... @@ -3825,7 +3825,7 @@ pprStopped res = do
    3825 3825
           hug <- hsc_HUG <$> GHC.getSession
    
    3826 3826
           brks <- liftIO $ readIModBreaks hug ibi
    
    3827 3827
           return $ Just $ moduleName $
    
    3828
    -        bi_tick_mod $ getBreakSourceId ibi brks
    
    3828
    +        getBreakSourceMod ibi brks
    
    3829 3829
       return $
    
    3830 3830
         text "Stopped in"
    
    3831 3831
           <+> ((case mb_mod_name of
    

  • rts/Disassembler.c
    ... ... @@ -101,9 +101,6 @@ disInstr ( StgBCO *bco, int pc )
    101 101
              }
    
    102 102
              debugBelch("\n");
    
    103 103
              break; }
    
    104
    -      case bci_BRK_ALTS:
    
    105
    -         debugBelch ("BRK_ALTS %d\n", BCO_NEXT);
    
    106
    -         break;
    
    107 104
           case bci_SWIZZLE: {
    
    108 105
              W_     stkoff = BCO_GET_LARGE_ARG;
    
    109 106
              StgInt by     = BCO_GET_LARGE_ARG;
    

  • rts/Interpreter.c
    ... ... @@ -370,16 +370,11 @@ to the continuation.
    370 370
     To achieve this, when the flag is set as the interpreter is re-entered:
    
    371 371
       (1) Traverse the stack until a RET_BCO frame is found or we otherwise hit the
    
    372 372
           bottom (STOP_FRAME).
    
    373
    -  (2) Look for a breakpoint instruction heading the BCO instructions (a
    
    373
    +  (2) Look for a BRK_FUN instruction heading the BCO instructions (a
    
    374 374
           breakpoint, when present, is always the first instruction in a BCO)
    
    375 375
     
    
    376
    -      (2a) For PUSH_ALT BCOs, the breakpoint instruction will be BRK_ALTS
    
    377
    -          (as explained in Note [Debugger: BRK_ALTS]) and it can be enabled by
    
    378
    -          setting its first operand to 1.
    
    379
    -
    
    380
    -      (2b) Otherwise, the instruction will be BRK_FUN and the breakpoint can be
    
    381
    -           enabled by setting the associated BreakArray at the associated tick
    
    382
    -           index to 0.
    
    376
    +      The breakpoint can be enabled by setting the associated BreakArray at the
    
    377
    +      associated internal breakpoint index to 0.
    
    383 378
     
    
    384 379
     By simply enabling the breakpoint heading the continuation we can ensure that
    
    385 380
     when it is returned to we will stop there without additional work -- it
    
    ... ... @@ -740,8 +735,8 @@ interpretBCO (Capability* cap)
    740 735
             int bciPtr = 0;
    
    741 736
             StgWord16 bci = BCO_NEXT;
    
    742 737
     
    
    743
    -        /* A breakpoint instruction (BRK_FUN or BRK_ALTS) is always the first
    
    744
    -         * instruction in a BCO */
    
    738
    +        /* A breakpoint instruction (BRK_FUN) can only be the first instruction
    
    739
    +         * in a BCO */
    
    745 740
             if ((bci & 0xFF) == bci_BRK_FUN) {
    
    746 741
     
    
    747 742
                 W_ arg1_brk_array, arg4_info_index;
    
    ... ... @@ -756,10 +751,6 @@ interpretBCO (Capability* cap)
    756 751
                 // ACTIVATE the breakpoint by tick index
    
    757 752
                 ((StgInt*)breakPoints->payload)[arg4_info_index] = 0;
    
    758 753
             }
    
    759
    -        else if ((bci & 0xFF) == bci_BRK_ALTS) {
    
    760
    -            // ACTIVATE BRK_ALTS by setting its only argument to ON
    
    761
    -            instrs[1] = 1;
    
    762
    -        }
    
    763 754
             // else: if there is no BRK instruction perhaps we should keep
    
    764 755
             // traversing; that said, the continuation should always have a BRK
    
    765 756
           }
    
    ... ... @@ -1804,17 +1795,6 @@ run_BCO:
    1804 1795
                 goto nextInsn;
    
    1805 1796
             }
    
    1806 1797
     
    
    1807
    -        /* See Note [Debugger: BRK_ALTS] */
    
    1808
    -        case bci_BRK_ALTS:
    
    1809
    -        {
    
    1810
    -          StgWord16 active = BCO_NEXT;
    
    1811
    -          if (active) {
    
    1812
    -            cap->r.rCurrentTSO->flags |= TSO_STOP_NEXT_BREAKPOINT;
    
    1813
    -          }
    
    1814
    -
    
    1815
    -          goto nextInsn;
    
    1816
    -        }
    
    1817
    -
    
    1818 1798
             case bci_STKCHECK: {
    
    1819 1799
                 // Explicit stack check at the beginning of a function
    
    1820 1800
                 // *only* (stack checks in case alternatives are
    

  • rts/include/rts/Bytecodes.h
    ... ... @@ -214,8 +214,6 @@
    214 214
     #define bci_OP_INDEX_ADDR_32           242
    
    215 215
     #define bci_OP_INDEX_ADDR_64           243
    
    216 216
     
    
    217
    -#define bci_BRK_ALTS                   244
    
    218
    -
    
    219 217
     
    
    220 218
     /* If you need to go past 255 then you will run into the flags */
    
    221 219
     
    

  • testsuite/tests/ghci.debugger/scripts/T26042b.stdout
    ... ... @@ -8,35 +8,32 @@ _result ::
    8 8
     10  foo True  i = return i
    
    9 9
                       ^^^^^^^^
    
    10 10
     11  foo False _ = do
    
    11
    -Stopped in Main.bar, T26042b.hs:21:3-10
    
    11
    +Stopped in Main., T26042b.hs:20:3-17
    
    12 12
     _result ::
    
    13 13
       GHC.Internal.Prim.State# GHC.Internal.Prim.RealWorld
    
    14 14
       -> (# GHC.Internal.Prim.State# GHC.Internal.Prim.RealWorld,
    
    15 15
             Int #) = _
    
    16
    -y :: Int = _
    
    16
    +19    let t = z * 2
    
    17 17
     20    y <- foo True t
    
    18
    +      ^^^^^^^^^^^^^^^
    
    18 19
     21    return y
    
    19
    -      ^^^^^^^^
    
    20
    -22  
    
    21
    -Stopped in Main.foo, T26042b.hs:15:3-10
    
    20
    +Stopped in Main., T26042b.hs:14:3-18
    
    22 21
     _result ::
    
    23 22
       GHC.Internal.Prim.State# GHC.Internal.Prim.RealWorld
    
    24 23
       -> (# GHC.Internal.Prim.State# GHC.Internal.Prim.RealWorld,
    
    25 24
             Int #) = _
    
    26
    -n :: Int = _
    
    25
    +13        y = 4
    
    27 26
     14    n <- bar (x + y)
    
    27
    +      ^^^^^^^^^^^^^^^^
    
    28 28
     15    return n
    
    29
    -      ^^^^^^^^
    
    30
    -16  
    
    31
    -Stopped in Main.main, T26042b.hs:6:3-9
    
    29
    +Stopped in Main., T26042b.hs:5:3-26
    
    32 30
     _result ::
    
    33 31
       GHC.Internal.Prim.State# GHC.Internal.Prim.RealWorld
    
    34 32
       -> (# GHC.Internal.Prim.State# GHC.Internal.Prim.RealWorld,
    
    35 33
             () #) = _
    
    36
    -a :: Int = _
    
    34
    +4  main = do
    
    37 35
     5    a <- foo False undefined
    
    36
    +     ^^^^^^^^^^^^^^^^^^^^^^^^
    
    38 37
     6    print a
    
    39
    -     ^^^^^^^
    
    40
    -7    print a
    
    41 38
     14
    
    42 39
     14

  • testsuite/tests/ghci.debugger/scripts/T26042c.script
    ... ... @@ -14,15 +14,7 @@ main
    14 14
     -- we go straight to `main`.
    
    15 15
     :stepout
    
    16 16
     :list
    
    17
    --- stepping out from here will stop in the thunk (TODO: WHY?)
    
    18
    -:stepout
    
    19
    -:list
    
    20
    -
    
    21
    --- bring us back to main from the thunk (why were we stopped there?...)
    
    22
    -:stepout
    
    23
    -:list
    
    24
    -
    
    25
    --- and finally out
    
    17
    +-- stepping out from here will exit main
    
    26 18
     :stepout
    
    27 19
     
    
    28 20
     -- this test is also run with optimisation to make sure the IO bindings inline and we can stop at them

  • testsuite/tests/ghci.debugger/scripts/T26042c.stdout
    ... ... @@ -8,17 +8,14 @@ _result ::
    8 8
     10  foo True  i = return i
    
    9 9
                       ^^^^^^^^
    
    10 10
     11  foo False _ = do
    
    11
    -Stopped in Main.main, T26042c.hs:6:3-9
    
    11
    +Stopped in Main., T26042c.hs:5:3-26
    
    12 12
     _result ::
    
    13 13
       GHC.Internal.Prim.State# GHC.Internal.Prim.RealWorld
    
    14 14
       -> (# GHC.Internal.Prim.State# GHC.Internal.Prim.RealWorld,
    
    15 15
             () #) = _
    
    16
    -a :: Int = _
    
    16
    +4  main = do
    
    17 17
     5    a <- foo False undefined
    
    18
    +     ^^^^^^^^^^^^^^^^^^^^^^^^
    
    18 19
     6    print a
    
    19
    -     ^^^^^^^
    
    20
    -7    print a
    
    21 20
     14
    
    22 21
     14
    23
    -not stopped at a breakpoint
    
    24
    -not stopped at a breakpoint

  • testsuite/tests/ghci.debugger/scripts/T26042d2.hs
    1
    +
    
    2
    +module Main where
    
    3
    +
    
    4
    +main = do
    
    5
    +  putStrLn "hello1"
    
    6
    +  f
    
    7
    +  putStrLn "hello3"
    
    8
    +  putStrLn "hello4"
    
    9
    +
    
    10
    +f = do
    
    11
    +  putStrLn "hello2.1"
    
    12
    +  putStrLn "hello2.2"
    
    13
    +{-# NOINLINE f #-}

  • testsuite/tests/ghci.debugger/scripts/T26042d2.script
    1
    +:load T26042d2.hs
    
    2
    +
    
    3
    +:break 11
    
    4
    +main
    
    5
    +:list
    
    6
    +:stepout
    
    7
    +:list
    
    8
    +:stepout
    
    9
    +
    
    10
    +-- should exit! we compile this test case with -O1 to make sure the monad >> are inlined
    
    11
    +-- and thus the test relies on the filtering behavior based on SrcSpans for stepout
    
    12
    +

  • testsuite/tests/ghci.debugger/scripts/T26042d2.stdout
    1
    +Breakpoint 0 activated at T26042d2.hs:11:3-21
    
    2
    +hello1
    
    3
    +Stopped in Main.f, T26042d2.hs:11:3-21
    
    4
    +_result ::
    
    5
    +  GHC.Internal.Prim.State# GHC.Internal.Prim.RealWorld
    
    6
    +  -> (# GHC.Internal.Prim.State# GHC.Internal.Prim.RealWorld,
    
    7
    +        () #) = _
    
    8
    +10  f = do
    
    9
    +11    putStrLn "hello2.1"
    
    10
    +      ^^^^^^^^^^^^^^^^^^^
    
    11
    +12    putStrLn "hello2.2"
    
    12
    +hello2.1
    
    13
    +hello2.2
    
    14
    +Stopped in Main., T26042d2.hs:6:3
    
    15
    +_result ::
    
    16
    +  GHC.Internal.Prim.State# GHC.Internal.Prim.RealWorld
    
    17
    +  -> (# GHC.Internal.Prim.State# GHC.Internal.Prim.RealWorld,
    
    18
    +        () #) = _
    
    19
    +5    putStrLn "hello1"
    
    20
    +6    f
    
    21
    +     ^
    
    22
    +7    putStrLn "hello3"
    
    23
    +hello3
    
    24
    +hello4

  • testsuite/tests/ghci.debugger/scripts/T26042e.stdout
    ... ... @@ -7,14 +7,12 @@ y :: [a1] -> Int = _
    7 7
     11    let !z = y x
    
    8 8
           ^^^^^^^^^^^^
    
    9 9
     12    let !t = y ['b']
    
    10
    -Stopped in T7.main, T26042e.hs:19:3-11
    
    10
    +Stopped in T7., T26042e.hs:18:3-17
    
    11 11
     _result :: IO () = _
    
    12
    -x :: Int = _
    
    13
    -y :: Int = _
    
    12
    +17  main = do
    
    14 13
     18    let !(x, y) = a
    
    14
    +      ^^^^^^^^^^^^^^^
    
    15 15
     19    print '1'
    
    16
    -      ^^^^^^^^^
    
    17
    -20    print '2'
    
    18 16
     '1'
    
    19 17
     '2'
    
    20 18
     '3'
    

  • testsuite/tests/ghci.debugger/scripts/T26042f2.stdout
    ... ... @@ -8,18 +8,16 @@ x :: Int = 450
    8 8
     21    pure (x + 3)
    
    9 9
                       ^^
    
    10 10
     22  {-# OPAQUE t #-}
    
    11
    -Stopped in T8.g, T26042f.hs:15:3-17
    
    11
    +Stopped in T8., T26042f.hs:14:3-14
    
    12 12
     _result :: Identity Int = _
    
    13
    -a :: Int = 453
    
    13
    +13  g x = do
    
    14 14
     14    a <- t (x*2)
    
    15
    +      ^^^^^^^^^^^^
    
    15 16
     15    n <- pure (a+a)
    
    16
    -      ^^^^^^^^^^^^^^^
    
    17
    -16    return (n+n)
    
    18
    -Stopped in T8.f, T26042f.hs:9:3-17
    
    17
    +Stopped in T8., T26042f.hs:8:3-14
    
    19 18
     _result :: Identity Int = _
    
    20
    -b :: Int = 1812
    
    19
    +7  f x = do
    
    21 20
     8    b <- g (x*x)
    
    21
    +     ^^^^^^^^^^^^
    
    22 22
     9    y <- pure (b+b)
    
    23
    -     ^^^^^^^^^^^^^^^
    
    24
    -10    return (y+y)
    
    25 23
     7248

  • testsuite/tests/ghci.debugger/scripts/T26042g.stdout
    ... ... @@ -6,10 +6,13 @@ x :: Int = 14
    6 6
     11  succ x = (-) (x - 2) (x + 1)
    
    7 7
                  ^^^^^^^^^^^^^^^^^^^
    
    8 8
     12  
    
    9
    -Stopped in T9.top, T26042g.hs:8:10-21
    
    9
    +Stopped in T9., T26042g.hs:(6,3)-(8,21)
    
    10 10
     _result :: Int = _
    
    11
    +5  top = do
    
    12
    +   vv
    
    13
    +6    case succ 14 of
    
    11 14
     7      5 -> 5
    
    12 15
     8      _ -> 6 + other 55
    
    13
    -            ^^^^^^^^^^^^
    
    16
    +                        ^^
    
    14 17
     9  
    
    15 18
     171

  • testsuite/tests/ghci.debugger/scripts/all.T
    ... ... @@ -147,8 +147,9 @@ test('T25932', extra_files(['T25932.hs']), ghci_script, ['T25932.script'])
    147 147
     
    
    148 148
     # Step out tests
    
    149 149
     test('T26042b', [extra_hc_opts('-O -fno-unoptimized-core-for-interpreter'), extra_files(['T26042b.hs'])], ghci_script, ['T26042b.script'])
    
    150
    -test('T26042c', [expect_broken(26042),extra_hc_opts('-O -fno-unoptimized-core-for-interpreter'), extra_files(['T26042c.hs'])], ghci_script, ['T26042c.script'])
    
    150
    +test('T26042c', [extra_hc_opts('-O -fno-unoptimized-core-for-interpreter'), extra_files(['T26042c.hs'])], ghci_script, ['T26042c.script'])
    
    151 151
     test('T26042d', [extra_hc_opts('-O -fno-unoptimized-core-for-interpreter'), extra_files(['T26042d.hs'])], ghci_script, ['T26042d.script'])
    
    152
    +test('T26042d2', [extra_hc_opts('-O -fno-unoptimized-core-for-interpreter'), extra_files(['T26042d2.hs'])], ghci_script, ['T26042d2.script'])
    
    152 153
     test('T26042e', extra_files(['T26042e.hs']), ghci_script, ['T26042e.script'])
    
    153 154
     test('T26042f1', extra_files(['T26042f.hs', 'T26042f.script']), ghci_script, ['T26042f.script']) # >> is not inlined, so stepout has nowhere to stop
    
    154 155
     test('T26042f2', [extra_hc_opts('-O -fno-unoptimized-core-for-interpreter'), extra_files(['T26042f.hs', 'T26042f.script'])], ghci_script, ['T26042f.script'])