{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE RecordWildCards #-}

module GHC.Types.Tickish (
  GenTickish(..),
  CoreTickish, StgTickish, CmmTickish,
  XTickishId,
  tickishCounts,
  tickishHasNoScope,
  tickishHasSoftScope,
  tickishFloatable,
  tickishCanSplit,
  mkNoCount,
  mkNoScope,
  tickishIsCode,
  isProfTick,
  TickishPlacement(..),
  tickishPlace,
  tickishContains,

  -- * Breakpoint tick identifiers
  BreakpointId(..), BreakTickIndex
) where

import GHC.Prelude
import GHC.Data.FastString
import Control.DeepSeq

import GHC.Core.Type

import GHC.Unit.Module

import GHC.Types.CostCentre
import GHC.Types.SrcLoc ( RealSrcSpan, containsSpan )
import GHC.Types.Var

import GHC.Utils.Panic

import Language.Haskell.Syntax.Extension ( NoExtField )

import Data.Data
import GHC.Utils.Binary
import GHC.Utils.Outputable (Outputable (ppr), text, (<+>))

{- *********************************************************************
*                                                                      *
              Ticks
*                                                                      *
************************************************************************
-}

-- | Allows attaching extra information to points in expressions

{- | Used as a data type index for the GenTickish annotations.
     See Note [Tickish passes]
 -}
data TickishPass
  = TickishPassCore
  | TickishPassStg
  | TickishPassCmm

{-
   Note [Tickish passes]
   ~~~~~~~~~~~~~~~~~~~~~
   Tickish annotations store different information depending on
   where they are used. Here's a summary of the differences
   between the passes.

   - CoreTickish: Haskell and Core
         The tickish annotations store the free variables of
         breakpoints.

   - StgTickish: Stg
         The GHCi bytecode generator (GHC.StgToByteCode) needs
         to know the type of each breakpoint in addition to its
         free variables. Since we cannot compute the type from
         an STG expression, the tickish annotations store the
         type of breakpoints in addition to the free variables.

   - CmmTickish: Cmm
         Breakpoints are unsupported and no free variables or
         type are stored.
 -}

type family XBreakpoint (pass :: TickishPass)
type instance XBreakpoint 'TickishPassCore = NoExtField
-- | Keep track of the type of breakpoints in STG, for GHCi
type instance XBreakpoint 'TickishPassStg  = Type
type instance XBreakpoint 'TickishPassCmm  = NoExtField

type family XTickishId (pass :: TickishPass)
type instance XTickishId 'TickishPassCore = Id
type instance XTickishId 'TickishPassStg = Id
type instance XTickishId 'TickishPassCmm = NoExtField

type CoreTickish = GenTickish 'TickishPassCore
type StgTickish = GenTickish 'TickishPassStg
-- | Tickish in Cmm context (annotations only)
type CmmTickish = GenTickish 'TickishPassCmm

-- If you edit this type, you may need to update the GHC formalism
-- See Note [GHC Formalism] in GHC.Core.Lint
data GenTickish pass =
    -- | An @{-# SCC #-}@ profiling annotation, either automatically
    -- added by the desugarer as a result of -auto-all, or added by
    -- the user.
    ProfNote {
      forall (pass :: TickishPass). GenTickish pass -> CostCentre
profNoteCC    :: CostCentre, -- ^ the cost centre

      forall (pass :: TickishPass). GenTickish pass -> Bool
profNoteCount :: !Bool,      -- ^ bump the entry count?
      forall (pass :: TickishPass). GenTickish pass -> Bool
profNoteScope :: !Bool       -- ^ scopes over the enclosed expression
                                   -- (i.e. not just a tick)
      -- Invariant: the False/False case never happens
    }

  -- | A "tick" used by HPC to track the execution of each
  -- subexpression in the original source code.
  | HpcTick {
      forall (pass :: TickishPass). GenTickish pass -> Module
tickModule :: Module,
      forall (pass :: TickishPass). GenTickish pass -> Int
tickId     :: !Int
    }

  -- | A breakpoint for the GHCi debugger.  This behaves like an HPC
  -- tick, but has a list of free variables which will be available
  -- for inspection in GHCi when the program stops at the breakpoint.
  --
  -- NB. we must take account of these Ids when (a) counting free variables,
  -- and (b) substituting (don't substitute for them)
  | Breakpoint
    { forall (pass :: TickishPass). GenTickish pass -> XBreakpoint pass
breakpointExt    :: XBreakpoint pass
    , forall (pass :: TickishPass). GenTickish pass -> BreakpointId
breakpointId     :: !BreakpointId
    , forall (pass :: TickishPass). GenTickish pass -> [XTickishId pass]
breakpointFVs    :: [XTickishId pass]
                                -- ^ the order of this list is important:
                                -- it matches the order of the lists in the
                                -- appropriate entry in 'GHC.ByteCode.Types.ModBreaks'.
                                --
                                -- Careful about substitution!  See
                                -- Note [substTickish] in "GHC.Core.Subst".
    }

  -- | A source note.
  --
  -- Source notes are pure annotations: Their presence should neither
  -- influence compilation nor execution. The semantics are given by
  -- causality: The presence of a source note means that a local
  -- change in the referenced source code span will possibly provoke
  -- the generated code to change. On the flip-side, the functionality
  -- of annotated code *must* be invariant against changes to all
  -- source code *except* the spans referenced in the source notes
  -- (see "Causality of optimized Haskell" paper for details).
  --
  -- Therefore extending the scope of any given source note is always
  -- valid. Note that it is still undesirable though, as this reduces
  -- their usefulness for debugging and profiling. Therefore we will
  -- generally try only to make use of this property where it is
  -- necessary to enable optimizations.
  | SourceNote
    { forall (pass :: TickishPass). GenTickish pass -> RealSrcSpan
sourceSpan :: RealSrcSpan -- ^ Source covered
    , forall (pass :: TickishPass). GenTickish pass -> LexicalFastString
sourceName :: LexicalFastString  -- ^ Name for source location
                                       --   (uses same names as CCs)
    }

deriving instance Eq (GenTickish 'TickishPassCore)
deriving instance Ord (GenTickish 'TickishPassCore)
deriving instance Data (GenTickish 'TickishPassCore)

deriving instance Data (GenTickish 'TickishPassStg)

deriving instance Eq (GenTickish 'TickishPassCmm)
deriving instance Ord (GenTickish 'TickishPassCmm)
deriving instance Data (GenTickish 'TickishPassCmm)

--------------------------------------------------------------------------------
-- Tick breakpoint index
--------------------------------------------------------------------------------

-- | Breakpoint tick index
-- newtype BreakTickIndex = BreakTickIndex Int
--   deriving (Eq, Ord, Data, Ix, NFData, Outputable)
type BreakTickIndex = Int

-- | Breakpoint identifier.
--
-- Indexes into the structures in the @'ModBreaks'@ created during desugaring
-- (after inserting the breakpoint ticks in the expressions).
-- See Note [Breakpoint identifiers]
data BreakpointId = BreakpointId
  { BreakpointId -> Module
bi_tick_mod   :: !Module         -- ^ Breakpoint tick module
  , BreakpointId -> Int
bi_tick_index :: !BreakTickIndex -- ^ Breakpoint tick index
  }
  deriving (BreakpointId -> BreakpointId -> Bool
(BreakpointId -> BreakpointId -> Bool)
-> (BreakpointId -> BreakpointId -> Bool) -> Eq BreakpointId
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: BreakpointId -> BreakpointId -> Bool
== :: BreakpointId -> BreakpointId -> Bool
$c/= :: BreakpointId -> BreakpointId -> Bool
/= :: BreakpointId -> BreakpointId -> Bool
Eq, Eq BreakpointId
Eq BreakpointId =>
(BreakpointId -> BreakpointId -> Ordering)
-> (BreakpointId -> BreakpointId -> Bool)
-> (BreakpointId -> BreakpointId -> Bool)
-> (BreakpointId -> BreakpointId -> Bool)
-> (BreakpointId -> BreakpointId -> Bool)
-> (BreakpointId -> BreakpointId -> BreakpointId)
-> (BreakpointId -> BreakpointId -> BreakpointId)
-> Ord BreakpointId
BreakpointId -> BreakpointId -> Bool
BreakpointId -> BreakpointId -> Ordering
BreakpointId -> BreakpointId -> BreakpointId
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 :: BreakpointId -> BreakpointId -> Ordering
compare :: BreakpointId -> BreakpointId -> Ordering
$c< :: BreakpointId -> BreakpointId -> Bool
< :: BreakpointId -> BreakpointId -> Bool
$c<= :: BreakpointId -> BreakpointId -> Bool
<= :: BreakpointId -> BreakpointId -> Bool
$c> :: BreakpointId -> BreakpointId -> Bool
> :: BreakpointId -> BreakpointId -> Bool
$c>= :: BreakpointId -> BreakpointId -> Bool
>= :: BreakpointId -> BreakpointId -> Bool
$cmax :: BreakpointId -> BreakpointId -> BreakpointId
max :: BreakpointId -> BreakpointId -> BreakpointId
$cmin :: BreakpointId -> BreakpointId -> BreakpointId
min :: BreakpointId -> BreakpointId -> BreakpointId
Ord, Typeable BreakpointId
Typeable BreakpointId =>
(forall (c :: * -> *).
 (forall d b. Data d => c (d -> b) -> d -> c b)
 -> (forall g. g -> c g) -> BreakpointId -> c BreakpointId)
-> (forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c BreakpointId)
-> (BreakpointId -> Constr)
-> (BreakpointId -> DataType)
-> (forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c BreakpointId))
-> (forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e))
    -> Maybe (c BreakpointId))
-> ((forall b. Data b => b -> b) -> BreakpointId -> BreakpointId)
-> (forall r r'.
    (r -> r' -> r)
    -> r -> (forall d. Data d => d -> r') -> BreakpointId -> r)
-> (forall r r'.
    (r' -> r -> r)
    -> r -> (forall d. Data d => d -> r') -> BreakpointId -> r)
-> (forall u. (forall d. Data d => d -> u) -> BreakpointId -> [u])
-> (forall u.
    Int -> (forall d. Data d => d -> u) -> BreakpointId -> u)
-> (forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> BreakpointId -> m BreakpointId)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> BreakpointId -> m BreakpointId)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> BreakpointId -> m BreakpointId)
-> Data BreakpointId
BreakpointId -> Constr
BreakpointId -> DataType
(forall b. Data b => b -> b) -> BreakpointId -> BreakpointId
forall a.
Typeable a =>
(forall (c :: * -> *).
 (forall d b. Data d => c (d -> b) -> d -> c b)
 -> (forall g. g -> c g) -> a -> c a)
-> (forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c a)
-> (a -> Constr)
-> (a -> DataType)
-> (forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c a))
-> (forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c a))
-> ((forall b. Data b => b -> b) -> a -> a)
-> (forall r r'.
    (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall r r'.
    (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall u. (forall d. Data d => d -> u) -> a -> [u])
-> (forall u. Int -> (forall d. Data d => d -> u) -> a -> u)
-> (forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> Data a
forall u. Int -> (forall d. Data d => d -> u) -> BreakpointId -> u
forall u. (forall d. Data d => d -> u) -> BreakpointId -> [u]
forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> BreakpointId -> r
forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> BreakpointId -> r
forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> BreakpointId -> m BreakpointId
forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> BreakpointId -> m BreakpointId
forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c BreakpointId
forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> BreakpointId -> c BreakpointId
forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c BreakpointId)
forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e))
-> Maybe (c BreakpointId)
$cgfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> BreakpointId -> c BreakpointId
gfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> BreakpointId -> c BreakpointId
$cgunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c BreakpointId
gunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c BreakpointId
$ctoConstr :: BreakpointId -> Constr
toConstr :: BreakpointId -> Constr
$cdataTypeOf :: BreakpointId -> DataType
dataTypeOf :: BreakpointId -> DataType
$cdataCast1 :: forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c BreakpointId)
dataCast1 :: forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c BreakpointId)
$cdataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e))
-> Maybe (c BreakpointId)
dataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e))
-> Maybe (c BreakpointId)
$cgmapT :: (forall b. Data b => b -> b) -> BreakpointId -> BreakpointId
gmapT :: (forall b. Data b => b -> b) -> BreakpointId -> BreakpointId
$cgmapQl :: forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> BreakpointId -> r
gmapQl :: forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> BreakpointId -> r
$cgmapQr :: forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> BreakpointId -> r
gmapQr :: forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> BreakpointId -> r
$cgmapQ :: forall u. (forall d. Data d => d -> u) -> BreakpointId -> [u]
gmapQ :: forall u. (forall d. Data d => d -> u) -> BreakpointId -> [u]
$cgmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> BreakpointId -> u
gmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> BreakpointId -> u
$cgmapM :: forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> BreakpointId -> m BreakpointId
gmapM :: forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> BreakpointId -> m BreakpointId
$cgmapMp :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> BreakpointId -> m BreakpointId
gmapMp :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> BreakpointId -> m BreakpointId
$cgmapMo :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> BreakpointId -> m BreakpointId
gmapMo :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> BreakpointId -> m BreakpointId
Data)

instance Outputable BreakpointId where
  ppr :: BreakpointId -> SDoc
ppr BreakpointId{Module
bi_tick_mod :: BreakpointId -> Module
bi_tick_mod :: Module
bi_tick_mod, Int
bi_tick_index :: BreakpointId -> Int
bi_tick_index :: Int
bi_tick_index} =
    String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"BreakpointId" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> Module -> SDoc
forall a. Outputable a => a -> SDoc
ppr Module
bi_tick_mod SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> Int -> SDoc
forall a. Outputable a => a -> SDoc
ppr Int
bi_tick_index

instance NFData BreakpointId where
  rnf :: BreakpointId -> ()
rnf BreakpointId{Module
bi_tick_mod :: BreakpointId -> Module
bi_tick_mod :: Module
bi_tick_mod, Int
bi_tick_index :: BreakpointId -> Int
bi_tick_index :: Int
bi_tick_index} =
    Module -> ()
forall a. NFData a => a -> ()
rnf Module
bi_tick_mod () -> () -> ()
forall a b. a -> b -> b
`seq` Int -> ()
forall a. NFData a => a -> ()
rnf Int
bi_tick_index

instance Binary BreakpointId where
  get :: ReadBinHandle -> IO BreakpointId
get ReadBinHandle
bh = Module -> Int -> BreakpointId
Module -> Int -> BreakpointId
BreakpointId (Module -> Int -> BreakpointId)
-> IO Module -> IO (Int -> BreakpointId)
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 (Int -> BreakpointId) -> IO Int -> IO BreakpointId
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 Int
forall a. Binary a => ReadBinHandle -> IO a
get ReadBinHandle
bh

  put_ :: WriteBinHandle -> BreakpointId -> IO ()
put_ WriteBinHandle
bh BreakpointId {Int
Module
bi_tick_mod :: BreakpointId -> Module
bi_tick_index :: BreakpointId -> Int
bi_tick_mod :: Module
bi_tick_index :: Int
..} = WriteBinHandle -> Module -> IO ()
forall a. Binary a => WriteBinHandle -> a -> IO ()
put_ WriteBinHandle
bh Module
bi_tick_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 -> Int -> IO ()
forall a. Binary a => WriteBinHandle -> a -> IO ()
put_ WriteBinHandle
bh Int
bi_tick_index

--------------------------------------------------------------------------------

-- | A "counting tick" (for which 'tickishCounts' is True) is one that
-- counts evaluations in some way.  We cannot discard a counting tick,
-- and the compiler should preserve the number of counting ticks (as
-- far as possible).
--
-- See Note [Counting ticks]
tickishCounts :: GenTickish pass -> Bool
tickishCounts :: forall (pass :: TickishPass). GenTickish pass -> Bool
tickishCounts = \case
  ProfNote { profNoteCount :: forall (pass :: TickishPass). GenTickish pass -> Bool
profNoteCount = Bool
counts } -> Bool
counts
  HpcTick {}                          -> Bool
True
  Breakpoint {}                       -> Bool
True
  SourceNote {}                       -> Bool
False

-- | Is this a non-scoping tick, for which we don't care about precisely
-- the extent of code that the tick encompasses?
--
-- See Note [Scoped ticks]
tickishHasNoScope :: GenTickish pass -> Bool
tickishHasNoScope :: forall (pass :: TickishPass). GenTickish pass -> Bool
tickishHasNoScope = \case
  ProfNote { profNoteScope :: forall (pass :: TickishPass). GenTickish pass -> Bool
profNoteScope = Bool
scopes } -> Bool -> Bool
not Bool
scopes
  HpcTick {}                          -> Bool
True
  Breakpoint {}                       -> Bool
False
  SourceNote {}                       -> Bool
False

-- | A "tick with soft scoping" (for which 'tickishHasSoftScope' is True) is
-- one that either does not scope at all (for which 'tickishHasNoScope' is True),
-- or that has a "soft" scope: we allow new code to be floated into to the scope,
-- as long as all code that was covered remains covered.
--
-- See Note [Scoped ticks]
tickishHasSoftScope :: GenTickish pass -> Bool
tickishHasSoftScope :: forall (pass :: TickishPass). GenTickish pass -> Bool
tickishHasSoftScope = \case
  ProfNote { profNoteScope :: forall (pass :: TickishPass). GenTickish pass -> Bool
profNoteScope = Bool
scopes } -> Bool -> Bool
not Bool
scopes
  HpcTick {}                          -> Bool
True
  Breakpoint {}                       -> Bool
False
  SourceNote {}                       -> Bool
True

{- Note [Scoping ticks and counting ticks]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Ticks have two independent attributes:

  * Whether the tick /counts/.
    Counting ticks are used when we want a counter to be bumped, e.g. counting
    how many times a function is called.

    See Note [Counting ticks]

  * What kind of /scope/ the tick has:
     * Cost-centre scope: you cannot move a redex into the scope of the tick,
                          nor can you float a redex out.
     * Soft scope: you can move a redex /into/ the scope of a tick,
                   but you cannot float a redex /out/
     * No scope: there are no restrictions on floating in or out.

     See Note [Scoped ticks]

Note [Counting ticks]
~~~~~~~~~~~~~~~~~~~~
The following ticks count:
  - ProfNote ticks with profNoteCounts = True
  - HPC ticks
  - Breakpoints

Going past a counting tick implies bumping a counter.
Generally, the simplifier attempts to preserve counts when transforming
programs and moving ticks, for example by transforming:

  case <tick> e of
    alt1 -> rhs1
    alt2 -> rhs2

to

  case e of
    alt1 -> <tick> rhs1
    alt2 -> <tick> rhs2

which preserves the total count (as exactly one branch of the case
will be taken).

However, we still allow the simplifier to increase or decrease
sharing, so in practice the actual number of ticks may vary, except
that we never change the value from zero to non-zero or vice-versa.

Note [Scoped ticks]
~~~~~~~~~~~~~~~~~~~~
The following ticks are scoped:
  - ProfNote ticks with profNoteScope = True
  - Breakpoints
  - Source notes

A scoped tick is one that scopes over a portion of code. For example,
an SCC anotation sets the cost centre for the code within; any allocations
within that piece of code should get attributed to that cost centre.

When the simplifier deals with a scoping tick, it ensures that all code that
was covered remains covered. For example

  let x = tick<...> (let y = foo in bar) in baz
    ===>
  let x = tick<...> bar; y = tick<...> foo in baz

is a valid transformation as far as "bar" and "foo" are concerned, because
both still are scoped over by the tick. One might object to the "let" not
being covered by the tick any more. However, we are generally lax with this;
constant costs don't matter too much, and given that the "let" was effectively
merged we can view it as having lost its identity anyway.

Perhaps surprisingly, breakpoints are considered to be scoped, because we
don't want the simplifier to move them around, changing their result type (see #1531).

We specifically forbid floating code outside of a scoping tick, as cost
associated with the floated-out code would no longer be attributed to the
appropriate scope.

Whether we are allowed to float in additional cost depends on the tick:

  Cost-centre scope ticks
    - ProfNote with profNoteScope = True
    - Breakpoints

    A tick with cost-centre scope is one for which we can neither move
    redexes into or move redexes outside of the tick. For example, we don't
    want profiling costs to move to other cost-centre stacks.
    Morever, we also object to changing the order in which such ticks
    are applied.

    A rule of thumb is that we don't want any code to gain new
    lexically-enclosing ticks. For example, we should not transform:

      f (scctick<foo> a)  ==>  scctick<foo> (f a)

    as this would attribute the cost of evaluating the application 'f a'
    to the cost centre 'foo'.

    However, there are notable exceptions, for example:

      let f = \y -> foo in tick<...> ... (f x) ...
        ==>
      tick<...> ... foo[x/y] ...

    Inlining lambdas like this is always legal, because inlining a function
    does not change the cost-centre stack when the function is called.

  Soft scope ticks
    - Source notes

    A tick with soft scope is one for which we can move redexes inside the
    tick, but cannot float redexes outside the tick. This is a slightly more
    lenient notion of scoping than cost-centres, and is used only for source
    note ticks (they are used to provide DWARF debug symbols, and for those
    it matters less if code from outside gets moved under the tick).

    Examples:

      - FloatIn (GHC.Core.Opt.FloatIn.fiExpr)

          let x = rhs in <tick> body
            ==>
          <tick> (let x = rhs in body)

      - Moving a tick outside of a case or of an application
        (GHC.Core.Opt.Simplify.Iteration.simplTick)

          case <tick> e of alts  ==>  <tick> case e of alts

          (<tick> e1) e2         ==>  <tick> (e1 e2)

    While these transformations are legal, we want to make a best effort to
    only make use of them where it exposes transformation opportunities.
-}

-- | Returns @True@ for ticks that can be floated upwards easily even
-- where it might change execution counts, such as:
--
--   Just (tick<...> foo)
--     ==>
--   tick<...> (Just foo)
--
-- This is a combination of @tickishHasSoftScope@ and @tickishCounts@.
-- Note that in principle splittable ticks can become floatable using @mkNoTick@,
-- even though there's currently no tickish for which that is the case.
tickishFloatable :: GenTickish pass -> Bool
tickishFloatable :: forall (pass :: TickishPass). GenTickish pass -> Bool
tickishFloatable GenTickish pass
t = GenTickish pass -> Bool
forall (pass :: TickishPass). GenTickish pass -> Bool
tickishHasSoftScope GenTickish pass
t Bool -> Bool -> Bool
&& Bool -> Bool
not (GenTickish pass -> Bool
forall (pass :: TickishPass). GenTickish pass -> Bool
tickishCounts GenTickish pass
t)

-- | Returns @True@ for a tick that is both counting /and/ scoping and
-- can be split into its (tick, scope) parts using 'mkNoScope' and
-- 'mkNoTick' respectively.
tickishCanSplit :: GenTickish pass -> Bool
tickishCanSplit :: forall (pass :: TickishPass). GenTickish pass -> Bool
tickishCanSplit ProfNote{profNoteScope :: forall (pass :: TickishPass). GenTickish pass -> Bool
profNoteScope = Bool
True, profNoteCount :: forall (pass :: TickishPass). GenTickish pass -> Bool
profNoteCount = Bool
True}
                   = Bool
True
tickishCanSplit GenTickish pass
_  = Bool
False

mkNoCount :: GenTickish pass -> GenTickish pass
mkNoCount :: forall (pass :: TickishPass). GenTickish pass -> GenTickish pass
mkNoCount GenTickish pass
n | Bool -> Bool
not (GenTickish pass -> Bool
forall (pass :: TickishPass). GenTickish pass -> Bool
tickishCounts GenTickish pass
n)   = GenTickish pass
n
            | Bool -> Bool
not (GenTickish pass -> Bool
forall (pass :: TickishPass). GenTickish pass -> Bool
tickishCanSplit GenTickish pass
n) = String -> GenTickish pass
forall a. HasCallStack => String -> a
panic String
"mkNoCount: Cannot split!"
mkNoCount n :: GenTickish pass
n@ProfNote{}                = let n' :: GenTickish pass
n' = GenTickish pass
n {profNoteCount = False}
                                        in Bool -> GenTickish pass -> GenTickish pass
forall a. HasCallStack => Bool -> a -> a
assert (GenTickish pass -> Bool
forall (pass :: TickishPass). GenTickish pass -> Bool
profNoteCount GenTickish pass
n) GenTickish pass
n'
mkNoCount GenTickish pass
_                           = String -> GenTickish pass
forall a. HasCallStack => String -> a
panic String
"mkNoCount: Undefined split!"

mkNoScope :: GenTickish pass -> GenTickish pass
mkNoScope :: forall (pass :: TickishPass). GenTickish pass -> GenTickish pass
mkNoScope GenTickish pass
n | GenTickish pass -> Bool
forall (pass :: TickishPass). GenTickish pass -> Bool
tickishHasNoScope GenTickish pass
n         = GenTickish pass
n
            | Bool -> Bool
not (GenTickish pass -> Bool
forall (pass :: TickishPass). GenTickish pass -> Bool
tickishCanSplit GenTickish pass
n)     = String -> GenTickish pass
forall a. HasCallStack => String -> a
panic String
"mkNoScope: Cannot split!"
mkNoScope n :: GenTickish pass
n@ProfNote{}                    = let n' :: GenTickish pass
n' = GenTickish pass
n {profNoteScope = False}
                                            in Bool -> GenTickish pass -> GenTickish pass
forall a. HasCallStack => Bool -> a -> a
assert (GenTickish pass -> Bool
forall (pass :: TickishPass). GenTickish pass -> Bool
profNoteCount GenTickish pass
n) GenTickish pass
n'
mkNoScope GenTickish pass
_                               = String -> GenTickish pass
forall a. HasCallStack => String -> a
panic String
"mkNoScope: Undefined split!"

-- | Return @True@ if this source annotation compiles to some backend
-- code. Without this flag, the tickish is seen as a simple annotation
-- that does not have any associated evaluation code.
--
-- What this means that we are allowed to disregard the tick if doing
-- so means that we can skip generating any code in the first place. A
-- typical example is top-level bindings:
--
--   foo = tick<...> \y -> ...
--     ==>
--   foo = \y -> tick<...> ...
--
-- Here there is just no operational difference between the first and
-- the second version. Therefore code generation should simply
-- translate the code as if it found the latter.
tickishIsCode :: GenTickish pass -> Bool
tickishIsCode :: forall (pass :: TickishPass). GenTickish pass -> Bool
tickishIsCode SourceNote{} = Bool
False
tickishIsCode ProfNote{}   = Bool
True
tickishIsCode Breakpoint{} = Bool
True
tickishIsCode HpcTick{}    = Bool
True

isProfTick :: GenTickish pass -> Bool
isProfTick :: forall (pass :: TickishPass). GenTickish pass -> Bool
isProfTick ProfNote{} = Bool
True
isProfTick GenTickish pass
_          = Bool
False

-- | Governs the kind of expression that the tick gets placed on when
-- annotating for example using @mkTick@. If we find that we want to
-- put a tickish on an expression ruled out here, we try to float it
-- inwards until we find a suitable expression.
data TickishPlacement =

    -- | Place ticks exactly on run-time expressions. We can still
    -- move the tick through pure compile-time constructs such as
    -- other ticks, casts or type lambdas. This is the most
    -- restrictive placement rule for ticks, as all tickishs have in
    -- common that they want to track runtime processes. The only
    -- legal placement rule for counting ticks.
    -- NB: We generally try to move these as close to the relevant
    -- runtime expression as possible. This means they get pushed through
    -- tyoe arguments. E.g. we create `(tick f) @Bool` instead of `tick (f @Bool)`.
    PlaceRuntime

    -- | As @PlaceRuntime@, but we float the tick through all
    -- lambdas. This makes sense where there is little difference
    -- between annotating the lambda and annotating the lambda's code.
  | PlaceNonLam

    -- | In addition to floating through lambdas, cost-centre style
    -- tickishs can also be moved from constructors, non-function
    -- variables and literals. For example:
    --
    --   let x = scc<...> C (scc<...> y) (scc<...> 3) in ...
    --
    -- Neither the constructor application, the variable or the
    -- literal are likely to have any cost worth mentioning. And even
    -- if y names a thunk, the call would not care about the
    -- evaluation context. Therefore removing all annotations in the
    -- above example is safe.
  | PlaceCostCentre

  deriving (TickishPlacement -> TickishPlacement -> Bool
(TickishPlacement -> TickishPlacement -> Bool)
-> (TickishPlacement -> TickishPlacement -> Bool)
-> Eq TickishPlacement
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: TickishPlacement -> TickishPlacement -> Bool
== :: TickishPlacement -> TickishPlacement -> Bool
$c/= :: TickishPlacement -> TickishPlacement -> Bool
/= :: TickishPlacement -> TickishPlacement -> Bool
Eq,Int -> TickishPlacement -> ShowS
[TickishPlacement] -> ShowS
TickishPlacement -> String
(Int -> TickishPlacement -> ShowS)
-> (TickishPlacement -> String)
-> ([TickishPlacement] -> ShowS)
-> Show TickishPlacement
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> TickishPlacement -> ShowS
showsPrec :: Int -> TickishPlacement -> ShowS
$cshow :: TickishPlacement -> String
show :: TickishPlacement -> String
$cshowList :: [TickishPlacement] -> ShowS
showList :: [TickishPlacement] -> ShowS
Show)

instance Outputable TickishPlacement where
  ppr :: TickishPlacement -> SDoc
ppr = String -> SDoc
forall doc. IsLine doc => String -> doc
text (String -> SDoc)
-> (TickishPlacement -> String) -> TickishPlacement -> SDoc
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TickishPlacement -> String
forall a. Show a => a -> String
show

-- | Placement behaviour we want for the ticks
tickishPlace :: GenTickish pass -> TickishPlacement
tickishPlace :: forall (pass :: TickishPass). GenTickish pass -> TickishPlacement
tickishPlace n :: GenTickish pass
n@ProfNote{}
  | GenTickish pass -> Bool
forall (pass :: TickishPass). GenTickish pass -> Bool
profNoteCount GenTickish pass
n        = TickishPlacement
PlaceRuntime
  | Bool
otherwise              = TickishPlacement
PlaceCostCentre
tickishPlace HpcTick{}     = TickishPlacement
PlaceRuntime
tickishPlace Breakpoint{}  = TickishPlacement
PlaceRuntime
tickishPlace SourceNote{}  = TickishPlacement
PlaceNonLam

-- | Returns whether one tick "contains" the other one, therefore
-- making the second tick redundant.
tickishContains :: Eq (GenTickish pass)
                => GenTickish pass -> GenTickish pass -> Bool
tickishContains :: forall (pass :: TickishPass).
Eq (GenTickish pass) =>
GenTickish pass -> GenTickish pass -> Bool
tickishContains (SourceNote RealSrcSpan
sp1 LexicalFastString
n1) (SourceNote RealSrcSpan
sp2 LexicalFastString
n2)
  = RealSrcSpan -> RealSrcSpan -> Bool
containsSpan RealSrcSpan
sp1 RealSrcSpan
sp2 Bool -> Bool -> Bool
&& LexicalFastString
n1 LexicalFastString -> LexicalFastString -> Bool
forall a. Eq a => a -> a -> Bool
== LexicalFastString
n2
    -- compare the String last
tickishContains GenTickish pass
t1 GenTickish pass
t2
  = GenTickish pass
t1 GenTickish pass -> GenTickish pass -> Bool
forall a. Eq a => a -> a -> Bool
== GenTickish pass
t2