    {-# LANGUAGE MagicHash, RecordWildCards, GeneralizedNewtypeDeriving #-}
    --
    --  (c) The University of Glasgow 2002-2006
    --

    -- | Bytecode assembler types
    module GHC.ByteCode.Types
      ( CompiledByteCode(..), seqCompiledByteCode, FFIInfo(..)
      , UnlinkedBCO(..), BCOPtr(..), BCONPtr(..)
      , ItblEnv, ItblPtr(..)
      , CgBreakInfo(..)
      , ModBreaks (..), BreakIndex, emptyModBreaks
      , CCostCentre
      ) where

    import GHC.Prelude

    import GHC.Data.FastString
    import GHC.Types.Id
    import GHC.Types.Name
    import GHC.Types.Name.Env
    import GHC.Utils.Outputable
    import GHC.Builtin.PrimOps
    import SizedSeq
    import GHC.Core.Type
    import GHC.Types.SrcLoc
    import GHCi.BreakArray
    import GHCi.RemoteTypes
    import GHCi.FFI
    import Control.DeepSeq

    import Foreign
    import Data.Array
    import Data.Array.Base  ( UArray(..) )
    import Data.ByteString (ByteString)
    import Data.IntMap (IntMap)
    import qualified Data.IntMap as IntMap
    import Data.Maybe (catMaybes)
    import GHC.Exts.Heap
    import GHC.Stack.CCS

    -- -----------------------------------------------------------------------------
    -- Compiled Byte Code

    data CompiledByteCode = CompiledByteCode
      { CompiledByteCode -> [UnlinkedBCO]
    bc_bcos   :: [UnlinkedBCO]  -- Bunch of interpretable bindings
      , CompiledByteCode -> ItblEnv
    bc_itbls  :: ItblEnv        -- A mapping from DataCons to their itbls
      , CompiledByteCode -> [FFIInfo]
    bc_ffis   :: [FFIInfo]      -- ffi blocks we allocated
      , CompiledByteCode -> [RemotePtr ()]
    bc_strs   :: [RemotePtr ()] -- malloc'd strings
      , CompiledByteCode -> Maybe ModBreaks
    bc_breaks :: Maybe ModBreaks -- breakpoint info (Nothing if we're not
                                     -- creating breakpoints, for some reason)
      }
                    -- ToDo: we're not tracking strings that we malloc'd
    newtype FFIInfo = FFIInfo (RemotePtr C_ffi_cif)
      deriving (BreakIndex -> FFIInfo -> ShowS
    [FFIInfo] -> ShowS
    FFIInfo -> String
    (BreakIndex -> FFIInfo -> ShowS)
    -> (FFIInfo -> String) -> ([FFIInfo] -> ShowS) -> Show FFIInfo
    forall a.
    (BreakIndex -> a -> ShowS)
    -> (a -> String) -> ([a] -> ShowS) -> Show a
    showList :: [FFIInfo] -> ShowS
    $cshowList :: [FFIInfo] -> ShowS
    show :: FFIInfo -> String
    $cshow :: FFIInfo -> String
    showsPrec :: BreakIndex -> FFIInfo -> ShowS
    $cshowsPrec :: BreakIndex -> FFIInfo -> ShowS
    Show, FFIInfo -> ()
    (FFIInfo -> ()) -> NFData FFIInfo
    forall a. (a -> ()) -> NFData a
    rnf :: FFIInfo -> ()
    $crnf :: FFIInfo -> ()
    NFData)

    instance Outputable CompiledByteCode where
      ppr :: CompiledByteCode -> SDoc
    ppr CompiledByteCode{[RemotePtr ()]
    [FFIInfo]
    [UnlinkedBCO]
    Maybe ModBreaks
    ItblEnv
    bc_breaks :: Maybe ModBreaks
    bc_strs :: [RemotePtr ()]
    bc_ffis :: [FFIInfo]
    bc_itbls :: ItblEnv
    bc_bcos :: [UnlinkedBCO]
    bc_breaks :: CompiledByteCode -> Maybe ModBreaks
    bc_strs :: CompiledByteCode -> [RemotePtr ()]
    bc_ffis :: CompiledByteCode -> [FFIInfo]
    bc_itbls :: CompiledByteCode -> ItblEnv
    bc_bcos :: CompiledByteCode -> [UnlinkedBCO]
    ..} = [UnlinkedBCO] -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr [UnlinkedBCO]
    bc_bcos

    -- Not a real NFData instance, because ModBreaks contains some things
    -- we can't rnf
    seqCompiledByteCode :: CompiledByteCode -> ()
    seqCompiledByteCode :: CompiledByteCode -> ()
    seqCompiledByteCode CompiledByteCode{[RemotePtr ()]
    [FFIInfo]
    [UnlinkedBCO]
    Maybe ModBreaks
    ItblEnv
    bc_breaks :: Maybe ModBreaks
    bc_strs :: [RemotePtr ()]
    bc_ffis :: [FFIInfo]
    bc_itbls :: ItblEnv
    bc_bcos :: [UnlinkedBCO]
    bc_breaks :: CompiledByteCode -> Maybe ModBreaks
    bc_strs :: CompiledByteCode -> [RemotePtr ()]
    bc_ffis :: CompiledByteCode -> [FFIInfo]
    bc_itbls :: CompiledByteCode -> ItblEnv
    bc_bcos :: CompiledByteCode -> [UnlinkedBCO]
    ..} =
      [UnlinkedBCO] -> ()
    forall a. NFData a => a -> ()
    rnf [UnlinkedBCO]
    bc_bcos () -> () -> ()
    `seq`
      [(Name, ItblPtr)] -> ()
    forall a. NFData a => a -> ()
    rnf (ItblEnv -> [(Name, ItblPtr)]
    forall a. NameEnv a -> [a]
    nameEnvElts ItblEnv
    bc_itbls) () -> () -> ()
    `seq`
      [FFIInfo] -> ()
    forall a. NFData a => a -> ()
    rnf [FFIInfo]
    bc_ffis () -> () -> ()
    `seq`
      [RemotePtr ()] -> ()
    forall a. NFData a => a -> ()
    rnf [RemotePtr ()]
    bc_strs () -> () -> ()
    `seq`
      Maybe () -> ()
    forall a. NFData a => a -> ()
    rnf ((ModBreaks -> ()) -> Maybe ModBreaks -> Maybe ()
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap ModBreaks -> ()
    seqModBreaks Maybe ModBreaks
    bc_breaks)

    type ItblEnv = NameEnv (Name, ItblPtr)
            -- We need the Name in the range so we know which
            -- elements to filter out when unloading a module

    newtype ItblPtr = ItblPtr (RemotePtr StgInfoTable)
      deriving (BreakIndex -> ItblPtr -> ShowS
    [ItblPtr] -> ShowS
    ItblPtr -> String
    (BreakIndex -> ItblPtr -> ShowS)
    -> (ItblPtr -> String) -> ([ItblPtr] -> ShowS) -> Show ItblPtr
    forall a.
    (BreakIndex -> a -> ShowS)
    -> (a -> String) -> ([a] -> ShowS) -> Show a
    showList :: [ItblPtr] -> ShowS
    $cshowList :: [ItblPtr] -> ShowS
    show :: ItblPtr -> String
    $cshow :: ItblPtr -> String
    showsPrec :: BreakIndex -> ItblPtr -> ShowS
    $cshowsPrec :: BreakIndex -> ItblPtr -> ShowS
    Show, ItblPtr -> ()
    (ItblPtr -> ()) -> NFData ItblPtr
    forall a. (a -> ()) -> NFData a
    rnf :: ItblPtr -> ()
    $crnf :: ItblPtr -> ()
    NFData)

    data UnlinkedBCO
       = UnlinkedBCO {
            UnlinkedBCO -> Name
    unlinkedBCOName   :: !Name,
            UnlinkedBCO -> BreakIndex
    unlinkedBCOArity  :: {-# UNPACK #-} !Int,
            UnlinkedBCO -> UArray BreakIndex Word16
    unlinkedBCOInstrs :: !(UArray Int Word16),      -- insns
            UnlinkedBCO -> UArray BreakIndex Word64
    unlinkedBCOBitmap :: !(UArray Int Word64),      -- bitmap
            UnlinkedBCO -> SizedSeq BCONPtr
    unlinkedBCOLits   :: !(SizedSeq BCONPtr),       -- non-ptrs
            UnlinkedBCO -> SizedSeq BCOPtr
    unlinkedBCOPtrs   :: !(SizedSeq BCOPtr)         -- ptrs
       }

    instance NFData UnlinkedBCO where
      rnf :: UnlinkedBCO -> ()
    rnf UnlinkedBCO{BreakIndex
    UArray BreakIndex Word16
    UArray BreakIndex Word64
    SizedSeq BCONPtr
    SizedSeq BCOPtr
    Name
    unlinkedBCOPtrs :: SizedSeq BCOPtr
    unlinkedBCOLits :: SizedSeq BCONPtr
    unlinkedBCOBitmap :: UArray BreakIndex Word64
    unlinkedBCOInstrs :: UArray BreakIndex Word16
    unlinkedBCOArity :: BreakIndex
    unlinkedBCOName :: Name
    unlinkedBCOPtrs :: UnlinkedBCO -> SizedSeq BCOPtr
    unlinkedBCOLits :: UnlinkedBCO -> SizedSeq BCONPtr
    unlinkedBCOBitmap :: UnlinkedBCO -> UArray BreakIndex Word64
    unlinkedBCOInstrs :: UnlinkedBCO -> UArray BreakIndex Word16
    unlinkedBCOArity :: UnlinkedBCO -> BreakIndex
    unlinkedBCOName :: UnlinkedBCO -> Name
    ..} =
        SizedSeq BCONPtr -> ()
    forall a. NFData a => a -> ()
    rnf SizedSeq BCONPtr
    unlinkedBCOLits () -> () -> ()
    `seq`
        SizedSeq BCOPtr -> ()
    forall a. NFData a => a -> ()
    rnf SizedSeq BCOPtr
    unlinkedBCOPtrs

    data BCOPtr
      = BCOPtrName   !Name
      | BCOPtrPrimOp !PrimOp
      | BCOPtrBCO    !UnlinkedBCO
      | BCOPtrBreakArray  -- a pointer to this module's BreakArray

    instance NFData BCOPtr where
      rnf :: BCOPtr -> ()
    rnf (BCOPtrBCO UnlinkedBCO
    bco) = UnlinkedBCO -> ()
    forall a. NFData a => a -> ()
    rnf UnlinkedBCO
    bco
      rnf BCOPtr
    x = BCOPtr
    x BCOPtr -> () -> ()
    `seq` ()

    data BCONPtr
      = BCONPtrWord  {-# UNPACK #-} !Word
      | BCONPtrLbl   !FastString
      | BCONPtrItbl  !Name
      | BCONPtrStr   !ByteString

    instance NFData BCONPtr where
      rnf :: BCONPtr -> ()
    rnf BCONPtr
    x = BCONPtr
    x BCONPtr -> () -> ()
    `seq` ()

    -- | Information about a breakpoint that we know at code-generation time
    data CgBreakInfo
       = CgBreakInfo
       { CgBreakInfo -> [Maybe (Id, Word16)]
    cgb_vars   :: [Maybe (Id,Word16)]
       , CgBreakInfo -> Type
    cgb_resty  :: Type
       }
    -- See Note [Syncing breakpoint info] in GHC.Runtime.Eval

    -- Not a real NFData instance because we can't rnf Id or Type
    seqCgBreakInfo :: CgBreakInfo -> ()
    seqCgBreakInfo :: CgBreakInfo -> ()
    seqCgBreakInfo CgBreakInfo{[Maybe (Id, Word16)]
    Type
    cgb_resty :: Type
    cgb_vars :: [Maybe (Id, Word16)]
    cgb_resty :: CgBreakInfo -> Type
    cgb_vars :: CgBreakInfo -> [Maybe (Id, Word16)]
    ..} =
      [Word16] -> ()
    forall a. NFData a => a -> ()
    rnf (((Id, Word16) -> Word16) -> [(Id, Word16)] -> [Word16]
    forall a b. (a -> b) -> [a] -> [b]
    map (Id, Word16) -> Word16
    forall a b. (a, b) -> b
    snd ([Maybe (Id, Word16)] -> [(Id, Word16)]
    forall a. [Maybe a] -> [a]
    catMaybes ([Maybe (Id, Word16)]
    cgb_vars))) () -> () -> ()
    `seq`
      Type -> ()
    seqType Type
    cgb_resty

    instance Outputable UnlinkedBCO where
       ppr :: UnlinkedBCO -> SDoc
    ppr (UnlinkedBCO Name
    nm BreakIndex
    _arity UArray BreakIndex Word16
    _insns UArray BreakIndex Word64
    _bitmap SizedSeq BCONPtr
    lits SizedSeq BCOPtr
    ptrs)
          = [SDoc] -> SDoc
    sep [String -> SDoc
    text String
    "BCO", Name -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr Name
    nm, String -> SDoc
    text String
    "with",
                 Word -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr (SizedSeq BCONPtr -> Word
    forall a. SizedSeq a -> Word
    sizeSS SizedSeq BCONPtr
    lits), String -> SDoc
    text String
    "lits",
                 Word -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr (SizedSeq BCOPtr -> Word
    forall a. SizedSeq a -> Word
    sizeSS SizedSeq BCOPtr
    ptrs), String -> SDoc
    text String
    "ptrs" ]

    instance Outputable CgBreakInfo where
       ppr :: CgBreakInfo -> SDoc
    ppr CgBreakInfo
    info = String -> SDoc
    text String
    "CgBreakInfo" SDoc -> SDoc -> SDoc
    <+>
                  SDoc -> SDoc
    parens ([Maybe (Id, Word16)] -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr (CgBreakInfo -> [Maybe (Id, Word16)]
    cgb_vars CgBreakInfo
    info) SDoc -> SDoc -> SDoc
    <+>
                          Type -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr (CgBreakInfo -> Type
    cgb_resty CgBreakInfo
    info))

    -- -----------------------------------------------------------------------------
    -- Breakpoints

    -- | Breakpoint index
    type BreakIndex = Int

    -- | C CostCentre type
    data CCostCentre

    -- | All the information about the breakpoints for a module
    data ModBreaks
       = ModBreaks
       { ModBreaks -> ForeignRef BreakArray
    modBreaks_flags :: ForeignRef BreakArray
            -- ^ The array of flags, one per breakpoint,
            -- indicating which breakpoints are enabled.
       , ModBreaks -> Array BreakIndex SrcSpan
    modBreaks_locs :: !(Array BreakIndex SrcSpan)
            -- ^ An array giving the source span of each breakpoint.
       , ModBreaks -> Array BreakIndex [OccName]
    modBreaks_vars :: !(Array BreakIndex [OccName])
            -- ^ An array giving the names of the free variables at each breakpoint.
       , ModBreaks -> Array BreakIndex [String]
    modBreaks_decls :: !(Array BreakIndex [String])
            -- ^ An array giving the names of the declarations enclosing each breakpoint.
            -- See Note [Field modBreaks_decls]
       , ModBreaks -> Array BreakIndex (RemotePtr CostCentre)
    modBreaks_ccs :: !(Array BreakIndex (RemotePtr CostCentre))
            -- ^ Array pointing to cost centre for each breakpoint
       , ModBreaks -> IntMap CgBreakInfo
    modBreaks_breakInfo :: IntMap CgBreakInfo
            -- ^ info about each breakpoint from the bytecode generator
       }

    seqModBreaks :: ModBreaks -> ()
    seqModBreaks :: ModBreaks -> ()
    seqModBreaks ModBreaks{Array BreakIndex [String]
    Array BreakIndex [OccName]
    Array BreakIndex (RemotePtr CostCentre)
    Array BreakIndex SrcSpan
    IntMap CgBreakInfo
    ForeignRef BreakArray
    modBreaks_breakInfo :: IntMap CgBreakInfo
    modBreaks_ccs :: Array BreakIndex (RemotePtr CostCentre)
    modBreaks_decls :: Array BreakIndex [String]
    modBreaks_vars :: Array BreakIndex [OccName]
    modBreaks_locs :: Array BreakIndex SrcSpan
    modBreaks_flags :: ForeignRef BreakArray
    modBreaks_breakInfo :: ModBreaks -> IntMap CgBreakInfo
    modBreaks_ccs :: ModBreaks -> Array BreakIndex (RemotePtr CostCentre)
    modBreaks_decls :: ModBreaks -> Array BreakIndex [String]
    modBreaks_vars :: ModBreaks -> Array BreakIndex [OccName]
    modBreaks_locs :: ModBreaks -> Array BreakIndex SrcSpan
    modBreaks_flags :: ModBreaks -> ForeignRef BreakArray
    ..} =
      ForeignRef BreakArray -> ()
    forall a. NFData a => a -> ()
    rnf ForeignRef BreakArray
    modBreaks_flags () -> () -> ()
    `seq`
      Array BreakIndex SrcSpan -> ()
    forall a. NFData a => a -> ()
    rnf Array BreakIndex SrcSpan
    modBreaks_locs () -> () -> ()
    `seq`
      Array BreakIndex [OccName] -> ()
    forall a. NFData a => a -> ()
    rnf Array BreakIndex [OccName]
    modBreaks_vars () -> () -> ()
    `seq`
      Array BreakIndex [String] -> ()
    forall a. NFData a => a -> ()
    rnf Array BreakIndex [String]
    modBreaks_decls () -> () -> ()
    `seq`
      Array BreakIndex (RemotePtr CostCentre) -> ()
    forall a. NFData a => a -> ()
    rnf Array BreakIndex (RemotePtr CostCentre)
    modBreaks_ccs () -> () -> ()
    `seq`
      IntMap () -> ()
    forall a. NFData a => a -> ()
    rnf ((CgBreakInfo -> ()) -> IntMap CgBreakInfo -> IntMap ()
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap CgBreakInfo -> ()
    seqCgBreakInfo IntMap CgBreakInfo
    modBreaks_breakInfo)

    -- | Construct an empty ModBreaks
    emptyModBreaks :: ModBreaks
    emptyModBreaks :: ModBreaks
    emptyModBreaks = ModBreaks :: ForeignRef BreakArray
    -> Array BreakIndex SrcSpan
    -> Array BreakIndex [OccName]
    -> Array BreakIndex [String]
    -> Array BreakIndex (RemotePtr CostCentre)
    -> IntMap CgBreakInfo
    -> ModBreaks
    ModBreaks
       { modBreaks_flags :: ForeignRef BreakArray
    modBreaks_flags = String -> ForeignRef BreakArray
    forall a. HasCallStack => String -> a
    error String
    "ModBreaks.modBreaks_array not initialised"
             -- ToDo: can we avoid this?
       , modBreaks_locs :: Array BreakIndex SrcSpan
    modBreaks_locs  = (BreakIndex, BreakIndex)
    -> [(BreakIndex, SrcSpan)] -> Array BreakIndex SrcSpan
    forall i e. Ix i => (i, i) -> [(i, e)] -> Array i e
    array (BreakIndex
    0,-BreakIndex
    1) []
       , modBreaks_vars :: Array BreakIndex [OccName]
    modBreaks_vars  = (BreakIndex, BreakIndex)
    -> [(BreakIndex, [OccName])] -> Array BreakIndex [OccName]
    forall i e. Ix i => (i, i) -> [(i, e)] -> Array i e
    array (BreakIndex
    0,-BreakIndex
    1) []
       , modBreaks_decls :: Array BreakIndex [String]
    modBreaks_decls = (BreakIndex, BreakIndex)
    -> [(BreakIndex, [String])] -> Array BreakIndex [String]
    forall i e. Ix i => (i, i) -> [(i, e)] -> Array i e
    array (BreakIndex
    0,-BreakIndex
    1) []
       , modBreaks_ccs :: Array BreakIndex (RemotePtr CostCentre)
    modBreaks_ccs = (BreakIndex, BreakIndex)
    -> [(BreakIndex, RemotePtr CostCentre)]
    -> Array BreakIndex (RemotePtr CostCentre)
    forall i e. Ix i => (i, i) -> [(i, e)] -> Array i e
    array (BreakIndex
    0,-BreakIndex
    1) []
       , modBreaks_breakInfo :: IntMap CgBreakInfo
    modBreaks_breakInfo = IntMap CgBreakInfo
    forall a. IntMap a
    IntMap.empty
       }

    {-
    Note [Field modBreaks_decls]
    ~~~~~~~~~~~~~~~~~~~~~~
    A value of eg ["foo", "bar", "baz"] in a `modBreaks_decls` field means:
    The breakpoint is in the function called "baz" that is declared in a `let`
    or `where` clause of a declaration called "bar", which itself is declared
    in a `let` or `where` clause of the top-level function called "foo".
    -}