{-# LANGUAGE RecordWildCards #-}

-- | Breakpoint information constructed during ByteCode generation.
--
-- Specifically, code-generation breakpoints are referred to as "internal
-- breakpoints", the internal breakpoint data for a module is stored in
-- 'InternalModBreaks', and is uniquely identified at runtime by an
-- 'InternalBreakpointId'.
--
-- See Note [ModBreaks vs InternalModBreaks] and Note [Breakpoint identifiers]
module GHC.ByteCode.Breakpoints
  ( -- * Internal Mod Breaks
    InternalModBreaks(..), CgBreakInfo(..)
  , mkInternalModBreaks, imodBreaks_module

    -- ** Internal breakpoint identifier
  , InternalBreakpointId(..), BreakInfoIndex

    -- * Operations

    -- ** Internal-level operations
  , getInternalBreak

    -- ** Source-level information operations
  , getBreakLoc, getBreakVars, getBreakDecls, getBreakCCS
  , getBreakSourceId

    -- * Utils
  , seqInternalModBreaks

  )
  where

import GHC.Prelude
import GHC.Types.SrcLoc
import GHC.Types.Name.Occurrence
import Control.DeepSeq
import Data.IntMap.Strict (IntMap)
import qualified Data.IntMap.Strict as IM

import GHC.HsToCore.Breakpoints
import GHC.Iface.Syntax

import GHC.Unit.Module (Module)
import GHC.Utils.Outputable
import GHC.Utils.Panic
import Data.Array

{-
Note [ModBreaks vs InternalModBreaks]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
'ModBreaks' and 'BreakpointId's must not to be confused with
'InternalModBreaks' and 'InternalBreakId's.

'ModBreaks' is constructed once during HsToCore from the information attached
to source-level breakpoint ticks and is never changed afterwards. A 'ModBreaks'
can be queried using 'BreakpointId's, which uniquely identifies a breakpoint
within the list of breakpoint information for a given module's 'ModBreaks'.

'InternalModBreaks' are constructed during bytecode generation and are indexed
by a 'InternalBreakpointId'. They contain all the information relevant to a
breakpoint for code generation that can be accessed during runtime execution
(such as a 'BreakArray' for triggering breakpoints). 'InternalBreakpointId's
are used at runtime to trigger and inspect breakpoints -- a 'BRK_FUN'
instruction receives 'InternalBreakpointId' as an argument.

We keep a mapping from 'InternalModBreaks' to a 'BreakpointId', which can then be used
to get source-level information about a breakpoint via the corresponding 'ModBreaks'.

Notably, 'InternalModBreaks' can contain entries for so-called internal
breakpoints, which do not necessarily have a source-level location attached to
it (i.e. do not have a matching entry in 'ModBreaks'). We may leverage this to
introduce breakpoints during code generation for features such as stepping-out.

Note [Breakpoint identifiers]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Before optimization a breakpoint is identified uniquely with a tick module
and a tick index. See 'BreakpointId'. A tick module contains an array, indexed
with the tick indexes, which indicates breakpoint status.

When we generate ByteCode, we collect information for every breakpoint at
their *occurrence sites* (see CgBreakInfo) and these info
are stored in the ModIface of the occurrence module. Because of inlining, we
can't reuse the tick index to uniquely identify an occurrence; because of
cross-module inlining, we can't assume that the occurrence module is the same
as the tick module (#24712).

So every breakpoint occurrence gets assigned a module-unique *info index* and
we store it alongside the occurrence module (*info module*) in the
'InternalBreakpointId' datatype. This is the index that we use at runtime to
identify a breakpoint.

When the internal breakpoint has a matching tick-level breakpoint we can fetch
the related tick-level information by first looking up a mapping
@'InternalBreakpointId' -> 'BreakpointId'@ in @'CgBreakInfo'@.
-}

--------------------------------------------------------------------------------
-- * Internal breakpoint identifiers
--------------------------------------------------------------------------------

-- | Internal breakpoint info index
type BreakInfoIndex = Int

-- | Internal breakpoint identifier
--
-- Indexes into the structures in the @'InternalModBreaks'@ produced during ByteCode generation.
-- See Note [Breakpoint identifiers]
data InternalBreakpointId = InternalBreakpointId
  { InternalBreakpointId -> Module
ibi_info_mod   :: !Module         -- ^ Breakpoint info module
  , InternalBreakpointId -> BreakInfoIndex
ibi_info_index :: !BreakInfoIndex -- ^ Breakpoint info index
  }
  deriving (InternalBreakpointId -> InternalBreakpointId -> Bool
(InternalBreakpointId -> InternalBreakpointId -> Bool)
-> (InternalBreakpointId -> InternalBreakpointId -> Bool)
-> Eq InternalBreakpointId
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: InternalBreakpointId -> InternalBreakpointId -> Bool
== :: InternalBreakpointId -> InternalBreakpointId -> Bool
$c/= :: InternalBreakpointId -> InternalBreakpointId -> Bool
/= :: InternalBreakpointId -> InternalBreakpointId -> Bool
Eq, Eq InternalBreakpointId
Eq InternalBreakpointId =>
(InternalBreakpointId -> InternalBreakpointId -> Ordering)
-> (InternalBreakpointId -> InternalBreakpointId -> Bool)
-> (InternalBreakpointId -> InternalBreakpointId -> Bool)
-> (InternalBreakpointId -> InternalBreakpointId -> Bool)
-> (InternalBreakpointId -> InternalBreakpointId -> Bool)
-> (InternalBreakpointId
    -> InternalBreakpointId -> InternalBreakpointId)
-> (InternalBreakpointId
    -> InternalBreakpointId -> InternalBreakpointId)
-> Ord InternalBreakpointId
InternalBreakpointId -> InternalBreakpointId -> Bool
InternalBreakpointId -> InternalBreakpointId -> Ordering
InternalBreakpointId
-> InternalBreakpointId -> InternalBreakpointId
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: InternalBreakpointId -> InternalBreakpointId -> Ordering
compare :: InternalBreakpointId -> InternalBreakpointId -> Ordering
$c< :: InternalBreakpointId -> InternalBreakpointId -> Bool
< :: InternalBreakpointId -> InternalBreakpointId -> Bool
$c<= :: InternalBreakpointId -> InternalBreakpointId -> Bool
<= :: InternalBreakpointId -> InternalBreakpointId -> Bool
$c> :: InternalBreakpointId -> InternalBreakpointId -> Bool
> :: InternalBreakpointId -> InternalBreakpointId -> Bool
$c>= :: InternalBreakpointId -> InternalBreakpointId -> Bool
>= :: InternalBreakpointId -> InternalBreakpointId -> Bool
$cmax :: InternalBreakpointId
-> InternalBreakpointId -> InternalBreakpointId
max :: InternalBreakpointId
-> InternalBreakpointId -> InternalBreakpointId
$cmin :: InternalBreakpointId
-> InternalBreakpointId -> InternalBreakpointId
min :: InternalBreakpointId
-> InternalBreakpointId -> InternalBreakpointId
Ord)

--------------------------------------------------------------------------------
-- * Internal Mod Breaks
--------------------------------------------------------------------------------

-- | Internal mod breaks store the runtime-relevant information of breakpoints.
--
-- Importantly, it maps 'InternalBreakpointId's to 'CgBreakInfo'.
--
-- 'InternalModBreaks' are constructed during bytecode generation and stored in
-- 'CompiledByteCode' afterwards.
data InternalModBreaks = InternalModBreaks
      { InternalModBreaks -> IntMap CgBreakInfo
imodBreaks_breakInfo :: !(IntMap CgBreakInfo)
        -- ^ Access code-gen time information about a breakpoint, indexed by
        -- 'InternalBreakpointId'.

      , InternalModBreaks -> ModBreaks
imodBreaks_modBreaks :: !ModBreaks
        -- ^ Store the ModBreaks for this module
        --
        -- Recall Note [Breakpoint identifiers]: for some module A, an
        -- *occurrence* of a breakpoint in A may have been inlined from some
        -- breakpoint *defined* in module B.
        --
        -- This 'ModBreaks' contains information regarding all the breakpoints
        -- defined in the module this 'InternalModBreaks' corresponds to. It
        -- /does not/ necessarily have information regarding all the breakpoint
        -- occurrences registered in 'imodBreaks_breakInfo'. Some of those
        -- occurrences may refer breakpoints inlined from other modules.
      }

-- | Construct an 'InternalModBreaks'.
--
-- INVARIANT: The given 'ModBreaks' correspond to the same module as this
-- 'InternalModBreaks' module (the first argument) and its breakpoint infos
-- (the @IntMap CgBreakInfo@ argument)
mkInternalModBreaks :: Module -> IntMap CgBreakInfo -> ModBreaks -> InternalModBreaks
mkInternalModBreaks :: Module -> IntMap CgBreakInfo -> ModBreaks -> InternalModBreaks
mkInternalModBreaks Module
mod IntMap CgBreakInfo
im ModBreaks
mbs =
  Bool -> SDoc -> InternalModBreaks -> InternalModBreaks
forall a. HasCallStack => Bool -> SDoc -> a -> a
assertPpr (Module
mod Module -> Module -> Bool
forall a. Eq a => a -> a -> Bool
== ModBreaks -> Module
modBreaks_module ModBreaks
mbs)
    (String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"Constructing InternalModBreaks with the ModBreaks of a different module!") (InternalModBreaks -> InternalModBreaks)
-> InternalModBreaks -> InternalModBreaks
forall a b. (a -> b) -> a -> b
$
      IntMap CgBreakInfo -> ModBreaks -> InternalModBreaks
InternalModBreaks IntMap CgBreakInfo
im ModBreaks
mbs

-- | Get the module to which these 'InternalModBreaks' correspond
imodBreaks_module :: InternalModBreaks -> Module
imodBreaks_module :: InternalModBreaks -> Module
imodBreaks_module = ModBreaks -> Module
modBreaks_module (ModBreaks -> Module)
-> (InternalModBreaks -> ModBreaks) -> InternalModBreaks -> Module
forall b c a. (b -> c) -> (a -> b) -> a -> c
. InternalModBreaks -> ModBreaks
imodBreaks_modBreaks

-- | Information about a breakpoint that we know at code-generation time
-- In order to be used, this needs to be hydrated relative to the current HscEnv by
-- 'hydrateCgBreakInfo'. Everything here can be fully forced and that's critical for
-- preventing space leaks (see #22530)
data CgBreakInfo
   = CgBreakInfo
   { CgBreakInfo -> [IfaceTvBndr]
cgb_tyvars  :: ![IfaceTvBndr] -- ^ Type variables in scope at the breakpoint
   , CgBreakInfo -> [Maybe (IfaceIdBndr, Word)]
cgb_vars    :: ![Maybe (IfaceIdBndr, Word)]
   , CgBreakInfo -> IfaceType
cgb_resty   :: !IfaceType
   , CgBreakInfo -> BreakpointId
cgb_tick_id :: !BreakpointId
     -- ^ This field records the original breakpoint tick identifier for this
     -- internal breakpoint info. It is used to convert a breakpoint
     -- *occurrence* index ('InternalBreakpointId') into a *definition* index
     -- ('BreakpointId').
     --
     -- The modules of breakpoint occurrence and breakpoint definition are not
     -- necessarily the same: See Note [Breakpoint identifiers].
   }
-- See Note [Syncing breakpoint info] in GHC.Runtime.Eval

-- | Get an internal breakpoint info by 'InternalBreakpointId'
getInternalBreak :: InternalBreakpointId -> InternalModBreaks -> CgBreakInfo
getInternalBreak :: InternalBreakpointId -> InternalModBreaks -> CgBreakInfo
getInternalBreak (InternalBreakpointId Module
mod BreakInfoIndex
ix) InternalModBreaks
imbs =
  Module -> Module -> CgBreakInfo -> CgBreakInfo
forall a. Module -> Module -> a -> a
assert_modules_match Module
mod (InternalModBreaks -> Module
imodBreaks_module InternalModBreaks
imbs) (CgBreakInfo -> CgBreakInfo) -> CgBreakInfo -> CgBreakInfo
forall a b. (a -> b) -> a -> b
$
    InternalModBreaks -> IntMap CgBreakInfo
imodBreaks_breakInfo InternalModBreaks
imbs IntMap CgBreakInfo -> BreakInfoIndex -> CgBreakInfo
forall a. IntMap a -> BreakInfoIndex -> a
IM.! BreakInfoIndex
ix

-- | Assert that the module in the 'InternalBreakpointId' and in
-- 'InternalModBreaks' match.
assert_modules_match :: Module -> Module -> a -> a
assert_modules_match :: forall a. Module -> Module -> a -> a
assert_modules_match Module
ibi_mod Module
imbs_mod =
  Bool -> SDoc -> a -> a
forall a. HasCallStack => Bool -> SDoc -> a -> a
assertPpr (Module
ibi_mod Module -> Module -> Bool
forall a. Eq a => a -> a -> Bool
== Module
imbs_mod)
    (String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"Tried to query the InternalModBreaks of module" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> Module -> SDoc
forall a. Outputable a => a -> SDoc
ppr Module
imbs_mod
        SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"with an InternalBreakpointId for module" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> Module -> SDoc
forall a. Outputable a => a -> SDoc
ppr Module
ibi_mod)

--------------------------------------------------------------------------------
-- Tick-level Breakpoint information
--------------------------------------------------------------------------------

-- | Get the source module and tick index for this breakpoint
-- (as opposed to the module where this breakpoint occurs, which is in 'InternalBreakpointId')
getBreakSourceId :: InternalBreakpointId -> InternalModBreaks -> BreakpointId
getBreakSourceId :: InternalBreakpointId -> InternalModBreaks -> BreakpointId
getBreakSourceId (InternalBreakpointId Module
ibi_mod BreakInfoIndex
ibi_ix) InternalModBreaks
imbs =
  Module -> Module -> BreakpointId -> BreakpointId
forall a. Module -> Module -> a -> a
assert_modules_match Module
ibi_mod (InternalModBreaks -> Module
imodBreaks_module InternalModBreaks
imbs) (BreakpointId -> BreakpointId) -> BreakpointId -> BreakpointId
forall a b. (a -> b) -> a -> b
$
    let cgb :: CgBreakInfo
cgb = InternalModBreaks -> IntMap CgBreakInfo
imodBreaks_breakInfo InternalModBreaks
imbs IntMap CgBreakInfo -> BreakInfoIndex -> CgBreakInfo
forall a. IntMap a -> BreakInfoIndex -> a
IM.! BreakInfoIndex
ibi_ix
     in CgBreakInfo -> BreakpointId
cgb_tick_id CgBreakInfo
cgb

-- | Get the source span for this breakpoint
getBreakLoc :: (Module -> IO ModBreaks) -> InternalBreakpointId -> InternalModBreaks -> IO SrcSpan
getBreakLoc :: (Module -> IO ModBreaks)
-> InternalBreakpointId -> InternalModBreaks -> IO SrcSpan
getBreakLoc = (ModBreaks -> Array BreakInfoIndex SrcSpan)
-> (Module -> IO ModBreaks)
-> InternalBreakpointId
-> InternalModBreaks
-> IO SrcSpan
forall a.
(ModBreaks -> Array BreakInfoIndex a)
-> (Module -> IO ModBreaks)
-> InternalBreakpointId
-> InternalModBreaks
-> IO a
getBreakXXX ModBreaks -> Array BreakInfoIndex SrcSpan
modBreaks_locs

-- | Get the vars for this breakpoint
getBreakVars :: (Module -> IO ModBreaks) -> InternalBreakpointId -> InternalModBreaks -> IO [OccName]
getBreakVars :: (Module -> IO ModBreaks)
-> InternalBreakpointId -> InternalModBreaks -> IO [OccName]
getBreakVars = (ModBreaks -> Array BreakInfoIndex [OccName])
-> (Module -> IO ModBreaks)
-> InternalBreakpointId
-> InternalModBreaks
-> IO [OccName]
forall a.
(ModBreaks -> Array BreakInfoIndex a)
-> (Module -> IO ModBreaks)
-> InternalBreakpointId
-> InternalModBreaks
-> IO a
getBreakXXX ModBreaks -> Array BreakInfoIndex [OccName]
modBreaks_vars

-- | Get the decls for this breakpoint
getBreakDecls :: (Module -> IO ModBreaks) -> InternalBreakpointId -> InternalModBreaks -> IO [String]
getBreakDecls :: (Module -> IO ModBreaks)
-> InternalBreakpointId -> InternalModBreaks -> IO [String]
getBreakDecls = (ModBreaks -> Array BreakInfoIndex [String])
-> (Module -> IO ModBreaks)
-> InternalBreakpointId
-> InternalModBreaks
-> IO [String]
forall a.
(ModBreaks -> Array BreakInfoIndex a)
-> (Module -> IO ModBreaks)
-> InternalBreakpointId
-> InternalModBreaks
-> IO a
getBreakXXX ModBreaks -> Array BreakInfoIndex [String]
modBreaks_decls

-- | Get the decls for this breakpoint
getBreakCCS :: (Module -> IO ModBreaks) -> InternalBreakpointId -> InternalModBreaks -> IO (String, String)
getBreakCCS :: (Module -> IO ModBreaks)
-> InternalBreakpointId -> InternalModBreaks -> IO (String, String)
getBreakCCS = (ModBreaks -> Array BreakInfoIndex (String, String))
-> (Module -> IO ModBreaks)
-> InternalBreakpointId
-> InternalModBreaks
-> IO (String, String)
forall a.
(ModBreaks -> Array BreakInfoIndex a)
-> (Module -> IO ModBreaks)
-> InternalBreakpointId
-> InternalModBreaks
-> IO a
getBreakXXX ModBreaks -> Array BreakInfoIndex (String, String)
modBreaks_ccs

-- | Internal utility to access a ModBreaks field at a particular breakpoint index
--
-- Recall Note [Breakpoint identifiers]: the internal breakpoint module (the
-- *occurrence* module) doesn't necessarily match the module where the
-- tick breakpoint was defined with the relevant 'ModBreaks'.
--
-- When the tick module is the same as the internal module, we use the stored
-- 'ModBreaks'. When the tick module is different, we need to look up the
-- 'ModBreaks' in the HUG for that other module.
--
-- To avoid cyclic dependencies, we instead receive a function that looks up
-- the 'ModBreaks' given a 'Module'
getBreakXXX :: (ModBreaks -> Array BreakTickIndex a) -> (Module -> IO ModBreaks) -> InternalBreakpointId -> InternalModBreaks -> IO a
getBreakXXX :: forall a.
(ModBreaks -> Array BreakInfoIndex a)
-> (Module -> IO ModBreaks)
-> InternalBreakpointId
-> InternalModBreaks
-> IO a
getBreakXXX ModBreaks -> Array BreakInfoIndex a
view Module -> IO ModBreaks
lookupModule (InternalBreakpointId Module
ibi_mod BreakInfoIndex
ibi_ix) InternalModBreaks
imbs =
  Module -> Module -> IO a -> IO a
forall a. Module -> Module -> a -> a
assert_modules_match Module
ibi_mod (InternalModBreaks -> Module
imodBreaks_module InternalModBreaks
imbs) (IO a -> IO a) -> IO a -> IO a
forall a b. (a -> b) -> a -> b
$ do
    let cgb :: CgBreakInfo
cgb = InternalModBreaks -> IntMap CgBreakInfo
imodBreaks_breakInfo InternalModBreaks
imbs IntMap CgBreakInfo -> BreakInfoIndex -> CgBreakInfo
forall a. IntMap a -> BreakInfoIndex -> a
IM.! BreakInfoIndex
ibi_ix
    case CgBreakInfo -> BreakpointId
cgb_tick_id CgBreakInfo
cgb of
      BreakpointId{Module
bi_tick_mod :: Module
bi_tick_mod :: BreakpointId -> Module
bi_tick_mod, BreakInfoIndex
bi_tick_index :: BreakInfoIndex
bi_tick_index :: BreakpointId -> BreakInfoIndex
bi_tick_index}
        | Module
bi_tick_mod Module -> Module -> Bool
forall a. Eq a => a -> a -> Bool
== Module
ibi_mod
        -> do
          let these_mbs :: ModBreaks
these_mbs = InternalModBreaks -> ModBreaks
imodBreaks_modBreaks InternalModBreaks
imbs
          a -> IO a
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (a -> IO a) -> a -> IO a
forall a b. (a -> b) -> a -> b
$ ModBreaks -> Array BreakInfoIndex a
view ModBreaks
these_mbs Array BreakInfoIndex a -> BreakInfoIndex -> a
forall i e. Ix i => Array i e -> i -> e
! BreakInfoIndex
bi_tick_index
        | Bool
otherwise
        -> do
          other_mbs <- Module -> IO ModBreaks
lookupModule Module
bi_tick_mod
          return $ view other_mbs ! bi_tick_index

--------------------------------------------------------------------------------
-- Instances
--------------------------------------------------------------------------------

-- | Fully force an 'InternalModBreaks' value
seqInternalModBreaks :: InternalModBreaks -> ()
seqInternalModBreaks :: InternalModBreaks -> ()
seqInternalModBreaks InternalModBreaks{IntMap CgBreakInfo
ModBreaks
imodBreaks_breakInfo :: InternalModBreaks -> IntMap CgBreakInfo
imodBreaks_modBreaks :: InternalModBreaks -> ModBreaks
imodBreaks_breakInfo :: IntMap CgBreakInfo
imodBreaks_modBreaks :: ModBreaks
..} =
    IntMap () -> ()
forall a. NFData a => a -> ()
rnf ((CgBreakInfo -> ()) -> IntMap CgBreakInfo -> IntMap ()
forall a b. (a -> b) -> IntMap a -> IntMap b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap CgBreakInfo -> ()
seqCgBreakInfo IntMap CgBreakInfo
imodBreaks_breakInfo)
  where
    seqCgBreakInfo :: CgBreakInfo -> ()
    seqCgBreakInfo :: CgBreakInfo -> ()
seqCgBreakInfo CgBreakInfo{[Maybe (IfaceIdBndr, Word)]
[IfaceTvBndr]
IfaceType
BreakpointId
cgb_tyvars :: CgBreakInfo -> [IfaceTvBndr]
cgb_vars :: CgBreakInfo -> [Maybe (IfaceIdBndr, Word)]
cgb_resty :: CgBreakInfo -> IfaceType
cgb_tick_id :: CgBreakInfo -> BreakpointId
cgb_tyvars :: [IfaceTvBndr]
cgb_vars :: [Maybe (IfaceIdBndr, Word)]
cgb_resty :: IfaceType
cgb_tick_id :: BreakpointId
..} =
        [IfaceTvBndr] -> ()
forall a. NFData a => a -> ()
rnf [IfaceTvBndr]
cgb_tyvars () -> () -> ()
forall a b. a -> b -> b
`seq`
        [Maybe (IfaceIdBndr, Word)] -> ()
forall a. NFData a => a -> ()
rnf [Maybe (IfaceIdBndr, Word)]
cgb_vars () -> () -> ()
forall a b. a -> b -> b
`seq`
        IfaceType -> ()
forall a. NFData a => a -> ()
rnf IfaceType
cgb_resty () -> () -> ()
forall a b. a -> b -> b
`seq`
        BreakpointId -> ()
forall a. NFData a => a -> ()
rnf BreakpointId
cgb_tick_id

instance Outputable InternalBreakpointId where
  ppr :: InternalBreakpointId -> SDoc
ppr InternalBreakpointId{BreakInfoIndex
Module
ibi_info_mod :: InternalBreakpointId -> Module
ibi_info_index :: InternalBreakpointId -> BreakInfoIndex
ibi_info_mod :: Module
ibi_info_index :: BreakInfoIndex
..} =
    String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"InternalBreakpointId" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> Module -> SDoc
forall a. Outputable a => a -> SDoc
ppr Module
ibi_info_mod SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> BreakInfoIndex -> SDoc
forall a. Outputable a => a -> SDoc
ppr BreakInfoIndex
ibi_info_index

instance NFData InternalBreakpointId where
  rnf :: InternalBreakpointId -> ()
rnf InternalBreakpointId{BreakInfoIndex
Module
ibi_info_mod :: InternalBreakpointId -> Module
ibi_info_index :: InternalBreakpointId -> BreakInfoIndex
ibi_info_mod :: Module
ibi_info_index :: BreakInfoIndex
..} =
    Module -> ()
forall a. NFData a => a -> ()
rnf Module
ibi_info_mod () -> () -> ()
forall a b. a -> b -> b
`seq` BreakInfoIndex -> ()
forall a. NFData a => a -> ()
rnf BreakInfoIndex
ibi_info_index

instance Outputable CgBreakInfo where
   ppr :: CgBreakInfo -> SDoc
ppr CgBreakInfo
info = String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"CgBreakInfo" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+>
              SDoc -> SDoc
forall doc. IsLine doc => doc -> doc
parens ([Maybe (IfaceIdBndr, Word)] -> SDoc
forall a. Outputable a => a -> SDoc
ppr (CgBreakInfo -> [Maybe (IfaceIdBndr, Word)]
cgb_vars CgBreakInfo
info) SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+>
                      IfaceType -> SDoc
forall a. Outputable a => a -> SDoc
ppr (CgBreakInfo -> IfaceType
cgb_resty CgBreakInfo
info) SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+>
                      BreakpointId -> SDoc
forall a. Outputable a => a -> SDoc
ppr (CgBreakInfo -> BreakpointId
cgb_tick_id CgBreakInfo
info))