{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE DerivingVia #-}

-- | 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
  , InternalBreakLoc(..)

    -- * Operations

    -- ** Internal-level operations
  , getInternalBreak

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

    -- * 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.Binary
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 -> Either InternalBreakLoc BreakpointId
cgb_tick_id :: !(Either InternalBreakLoc 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].
     --
     -- If there is no original tick identifier (that is, the breakpoint was
     -- created during code generation), we re-use the BreakpointId of something else.
     -- It would also be reasonable to have an @Either something BreakpointId@
     -- for @cgb_tick_id@, but currently we can always re-use a source-level BreakpointId.
     -- In the case of step-out, see Note [Debugger: Stepout internal break locs]
   }
-- See Note [Syncing breakpoint info] in GHC.Runtime.Eval

-- | Breakpoints created during code generation don't have a source-level tick
-- location. Instead, we re-use an existing one.
newtype InternalBreakLoc = InternalBreakLoc { InternalBreakLoc -> BreakpointId
internalBreakLoc :: BreakpointId }
  deriving newtype (InternalBreakLoc -> InternalBreakLoc -> Bool
(InternalBreakLoc -> InternalBreakLoc -> Bool)
-> (InternalBreakLoc -> InternalBreakLoc -> Bool)
-> Eq InternalBreakLoc
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: InternalBreakLoc -> InternalBreakLoc -> Bool
== :: InternalBreakLoc -> InternalBreakLoc -> Bool
$c/= :: InternalBreakLoc -> InternalBreakLoc -> Bool
/= :: InternalBreakLoc -> InternalBreakLoc -> Bool
Eq, InternalBreakLoc -> ()
(InternalBreakLoc -> ()) -> NFData InternalBreakLoc
forall a. (a -> ()) -> NFData a
$crnf :: InternalBreakLoc -> ()
rnf :: InternalBreakLoc -> ()
NFData, InternalBreakLoc -> SDoc
(InternalBreakLoc -> SDoc) -> Outputable InternalBreakLoc
forall a. (a -> SDoc) -> Outputable a
$cppr :: InternalBreakLoc -> SDoc
ppr :: InternalBreakLoc -> SDoc
Outputable)

-- | 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 (InternalBreakLoc -> BreakpointId)
-> (BreakpointId -> BreakpointId)
-> Either InternalBreakLoc BreakpointId
-> BreakpointId
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either InternalBreakLoc -> BreakpointId
internalBreakLoc BreakpointId -> BreakpointId
forall a. a -> a
id (CgBreakInfo -> Either InternalBreakLoc BreakpointId
cgb_tick_id CgBreakInfo
cgb)

-- | Get the source module for this breakpoint (where the breakpoint is defined)
getBreakSourceMod :: InternalBreakpointId -> InternalModBreaks -> Module
getBreakSourceMod :: InternalBreakpointId -> InternalModBreaks -> Module
getBreakSourceMod (InternalBreakpointId Module
ibi_mod BreakInfoIndex
ibi_ix) InternalModBreaks
imbs =
  Module -> Module -> Module -> Module
forall a. Module -> Module -> a -> a
assert_modules_match Module
ibi_mod (InternalModBreaks -> Module
imodBreaks_module InternalModBreaks
imbs) (Module -> Module) -> Module -> Module
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 (InternalBreakLoc -> Module)
-> (BreakpointId -> Module)
-> Either InternalBreakLoc BreakpointId
-> Module
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either (BreakpointId -> Module
bi_tick_mod (BreakpointId -> Module)
-> (InternalBreakLoc -> BreakpointId) -> InternalBreakLoc -> Module
forall b c a. (b -> c) -> (a -> b) -> a -> c
. InternalBreakLoc -> BreakpointId
internalBreakLoc) BreakpointId -> Module
bi_tick_mod (CgBreakInfo -> Either InternalBreakLoc 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.
--
-- When there is no tick module (the breakpoint was generated at codegen), use
-- the function on internal mod breaks.
--
-- 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 (InternalBreakLoc -> BreakpointId)
-> (BreakpointId -> BreakpointId)
-> Either InternalBreakLoc BreakpointId
-> BreakpointId
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either InternalBreakLoc -> BreakpointId
internalBreakLoc BreakpointId -> BreakpointId
forall a. a -> a
id (CgBreakInfo -> Either InternalBreakLoc BreakpointId
cgb_tick_id CgBreakInfo
cgb) of
      BreakpointId{Module
bi_tick_mod :: BreakpointId -> Module
bi_tick_mod :: 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]
Either InternalBreakLoc BreakpointId
IfaceType
cgb_tyvars :: CgBreakInfo -> [IfaceTvBndr]
cgb_vars :: CgBreakInfo -> [Maybe (IfaceIdBndr, Word)]
cgb_resty :: CgBreakInfo -> IfaceType
cgb_tick_id :: CgBreakInfo -> Either InternalBreakLoc BreakpointId
cgb_tyvars :: [IfaceTvBndr]
cgb_vars :: [Maybe (IfaceIdBndr, Word)]
cgb_resty :: IfaceType
cgb_tick_id :: Either InternalBreakLoc 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`
        Either InternalBreakLoc BreakpointId -> ()
forall a. NFData a => a -> ()
rnf Either InternalBreakLoc 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
<+>
                      Either InternalBreakLoc BreakpointId -> SDoc
forall a. Outputable a => a -> SDoc
ppr (CgBreakInfo -> Either InternalBreakLoc BreakpointId
cgb_tick_id CgBreakInfo
info))

instance Binary CgBreakInfo where
  put_ :: WriteBinHandle -> CgBreakInfo -> IO ()
put_ WriteBinHandle
bh CgBreakInfo {[Maybe (IfaceIdBndr, Word)]
[IfaceTvBndr]
Either InternalBreakLoc BreakpointId
IfaceType
cgb_tyvars :: CgBreakInfo -> [IfaceTvBndr]
cgb_vars :: CgBreakInfo -> [Maybe (IfaceIdBndr, Word)]
cgb_resty :: CgBreakInfo -> IfaceType
cgb_tick_id :: CgBreakInfo -> Either InternalBreakLoc BreakpointId
cgb_tyvars :: [IfaceTvBndr]
cgb_vars :: [Maybe (IfaceIdBndr, Word)]
cgb_resty :: IfaceType
cgb_tick_id :: Either InternalBreakLoc BreakpointId
..} =
    WriteBinHandle -> [IfaceTvBndr] -> IO ()
forall a. Binary a => WriteBinHandle -> a -> IO ()
put_ WriteBinHandle
bh [IfaceTvBndr]
cgb_tyvars
      IO () -> IO () -> IO ()
forall a b. IO a -> IO b -> IO b
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> WriteBinHandle -> [Maybe (IfaceIdBndr, Word)] -> IO ()
forall a. Binary a => WriteBinHandle -> a -> IO ()
put_ WriteBinHandle
bh [Maybe (IfaceIdBndr, Word)]
cgb_vars
      IO () -> IO () -> IO ()
forall a b. IO a -> IO b -> IO b
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> WriteBinHandle -> IfaceType -> IO ()
forall a. Binary a => WriteBinHandle -> a -> IO ()
put_ WriteBinHandle
bh IfaceType
cgb_resty
      IO () -> IO () -> IO ()
forall a b. IO a -> IO b -> IO b
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> WriteBinHandle -> Either InternalBreakLoc BreakpointId -> IO ()
forall a. Binary a => WriteBinHandle -> a -> IO ()
put_ WriteBinHandle
bh Either InternalBreakLoc BreakpointId
cgb_tick_id

  get :: ReadBinHandle -> IO CgBreakInfo
get ReadBinHandle
bh = [IfaceTvBndr]
-> [Maybe (IfaceIdBndr, Word)]
-> IfaceType
-> Either InternalBreakLoc BreakpointId
-> CgBreakInfo
CgBreakInfo ([IfaceTvBndr]
 -> [Maybe (IfaceIdBndr, Word)]
 -> IfaceType
 -> Either InternalBreakLoc BreakpointId
 -> CgBreakInfo)
-> IO [IfaceTvBndr]
-> IO
     ([Maybe (IfaceIdBndr, Word)]
      -> IfaceType
      -> Either InternalBreakLoc BreakpointId
      -> CgBreakInfo)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ReadBinHandle -> IO [IfaceTvBndr]
forall a. Binary a => ReadBinHandle -> IO a
get ReadBinHandle
bh IO
  ([Maybe (IfaceIdBndr, Word)]
   -> IfaceType
   -> Either InternalBreakLoc BreakpointId
   -> CgBreakInfo)
-> IO [Maybe (IfaceIdBndr, Word)]
-> IO
     (IfaceType -> Either InternalBreakLoc BreakpointId -> CgBreakInfo)
forall a b. IO (a -> b) -> IO a -> IO b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> ReadBinHandle -> IO [Maybe (IfaceIdBndr, Word)]
forall a. Binary a => ReadBinHandle -> IO a
get ReadBinHandle
bh IO
  (IfaceType -> Either InternalBreakLoc BreakpointId -> CgBreakInfo)
-> IO IfaceType
-> IO (Either InternalBreakLoc BreakpointId -> CgBreakInfo)
forall a b. IO (a -> b) -> IO a -> IO b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> ReadBinHandle -> IO IfaceType
forall a. Binary a => ReadBinHandle -> IO a
get ReadBinHandle
bh IO (Either InternalBreakLoc BreakpointId -> CgBreakInfo)
-> IO (Either InternalBreakLoc BreakpointId) -> IO CgBreakInfo
forall a b. IO (a -> b) -> IO a -> IO b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> ReadBinHandle -> IO (Either InternalBreakLoc BreakpointId)
forall a. Binary a => ReadBinHandle -> IO a
get ReadBinHandle
bh

instance Binary InternalModBreaks where
  get :: ReadBinHandle -> IO InternalModBreaks
get ReadBinHandle
bh = IntMap CgBreakInfo -> ModBreaks -> InternalModBreaks
InternalModBreaks (IntMap CgBreakInfo -> ModBreaks -> InternalModBreaks)
-> IO (IntMap CgBreakInfo) -> IO (ModBreaks -> InternalModBreaks)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ReadBinHandle -> IO (IntMap CgBreakInfo)
forall a. Binary a => ReadBinHandle -> IO a
get ReadBinHandle
bh IO (ModBreaks -> InternalModBreaks)
-> IO ModBreaks -> IO InternalModBreaks
forall a b. IO (a -> b) -> IO a -> IO b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> ReadBinHandle -> IO ModBreaks
forall a. Binary a => ReadBinHandle -> IO a
get ReadBinHandle
bh

  put_ :: WriteBinHandle -> InternalModBreaks -> IO ()
put_ WriteBinHandle
bh InternalModBreaks {IntMap CgBreakInfo
ModBreaks
imodBreaks_breakInfo :: InternalModBreaks -> IntMap CgBreakInfo
imodBreaks_modBreaks :: InternalModBreaks -> ModBreaks
imodBreaks_breakInfo :: IntMap CgBreakInfo
imodBreaks_modBreaks :: ModBreaks
..} =
    WriteBinHandle -> IntMap CgBreakInfo -> IO ()
forall a. Binary a => WriteBinHandle -> a -> IO ()
put_ WriteBinHandle
bh IntMap CgBreakInfo
imodBreaks_breakInfo IO () -> IO () -> IO ()
forall a b. IO a -> IO b -> IO b
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> WriteBinHandle -> ModBreaks -> IO ()
forall a. Binary a => WriteBinHandle -> a -> IO ()
put_ WriteBinHandle
bh ModBreaks
imodBreaks_modBreaks

deriving via BreakpointId instance Binary InternalBreakLoc

instance Binary InternalBreakpointId where
  get :: ReadBinHandle -> IO InternalBreakpointId
get ReadBinHandle
bh = Module -> BreakInfoIndex -> InternalBreakpointId
InternalBreakpointId (Module -> BreakInfoIndex -> InternalBreakpointId)
-> IO Module -> IO (BreakInfoIndex -> InternalBreakpointId)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ReadBinHandle -> IO Module
forall a. Binary a => ReadBinHandle -> IO a
get ReadBinHandle
bh IO (BreakInfoIndex -> InternalBreakpointId)
-> IO BreakInfoIndex -> IO InternalBreakpointId
forall a b. IO (a -> b) -> IO a -> IO b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> ReadBinHandle -> IO BreakInfoIndex
forall a. Binary a => ReadBinHandle -> IO a
get ReadBinHandle
bh

  put_ :: WriteBinHandle -> InternalBreakpointId -> IO ()
put_ WriteBinHandle
bh InternalBreakpointId {BreakInfoIndex
Module
ibi_info_mod :: InternalBreakpointId -> Module
ibi_info_index :: InternalBreakpointId -> BreakInfoIndex
ibi_info_mod :: Module
ibi_info_index :: BreakInfoIndex
..} =
    WriteBinHandle -> Module -> IO ()
forall a. Binary a => WriteBinHandle -> a -> IO ()
put_ WriteBinHandle
bh Module
ibi_info_mod IO () -> IO () -> IO ()
forall a b. IO a -> IO b -> IO b
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> WriteBinHandle -> BreakInfoIndex -> IO ()
forall a. Binary a => WriteBinHandle -> a -> IO ()
put_ WriteBinHandle
bh BreakInfoIndex
ibi_info_index