ghc-8.2.2: The GHC API

Safe Haskell | None
Language | Haskell2010

CoreSyn

Contents

- Main data types
- In/Out type synonyms
  - `Expr` construction
  - Simple `Expr` access functions and predicates
- Tick-related functions
- Unfolding data types
  - Constructing `Unfolding`s
  - Predicates and deconstruction on `Unfolding`
- Annotated expression data types
  - Operations on annotated expressions
  - Operations on annotations
- Orphanhood
- Core rule data types
  - Operations on `CoreRule`s
- Core vectorisation declarations data type

Description

CoreSyn holds all the main data types for use by for the Glasgow Haskell Compiler midsection

Synopsis

- data Expr b
  - = Var Id
  - | Lit Literal
  - | App (Expr b) (Arg b)
  - | Lam b (Expr b)
  - | Let (Bind b) (Expr b)
  - | Case (Expr b) b Type [Alt b]
  - | Cast (Expr b) Coercion
  - | Tick (Tickish Id) (Expr b)
  - | Type Type
  - | Coercion Coercion
- type Alt b = (AltCon, [b], Expr b)
- data Bind b
  - = NonRec b (Expr b)
  - | Rec [(b, Expr b)]
- data AltCon
  - = DataAlt DataCon
  - | LitAlt Literal
  - | DEFAULT
- type Arg b = Expr b
- data Tickish id
  - = ProfNote {
    - profNoteCC :: CostCentre
    - profNoteCount :: !Bool
    - profNoteScope :: !Bool
    }
  - | HpcTick {
    - tickModule :: Module
    - tickId :: !Int
    }
  - | Breakpoint {
    - breakpointId :: !Int
    - breakpointFVs :: [id]
    }
  - | SourceNote {
    - sourceSpan :: RealSrcSpan
    - sourceName :: String
    }
- data TickishScoping
  - = NoScope
  - | SoftScope
  - | CostCentreScope
- data TickishPlacement
  - = PlaceRuntime
  - | PlaceNonLam
  - | PlaceCostCentre
- type CoreProgram = [CoreBind]
- type CoreExpr = Expr CoreBndr
- type CoreAlt = Alt CoreBndr
- type CoreBind = Bind CoreBndr
- type CoreArg = Arg CoreBndr
- type CoreBndr = Var
- type TaggedExpr t = Expr (TaggedBndr t)
- type TaggedAlt t = Alt (TaggedBndr t)
- type TaggedBind t = Bind (TaggedBndr t)
- type TaggedArg t = Arg (TaggedBndr t)
- data TaggedBndr t = TB CoreBndr t
- deTagExpr :: TaggedExpr t -> CoreExpr
- type InId = Id
- type InBind = CoreBind
- type InExpr = CoreExpr
- type InAlt = CoreAlt
- type InArg = CoreArg
- type InType = Type
- type InKind = Kind
- type InBndr = CoreBndr
- type InVar = Var
- type InCoercion = Coercion
- type InTyVar = TyVar
- type InCoVar = CoVar
- type OutId = Id
- type OutBind = CoreBind
- type OutExpr = CoreExpr
- type OutAlt = CoreAlt
- type OutArg = CoreArg
- type OutType = Type
- type OutKind = Kind
- type OutBndr = CoreBndr
- type OutVar = Var
- type OutCoercion = Coercion
- type OutTyVar = TyVar
- type OutCoVar = CoVar
- mkLet :: Bind b -> Expr b -> Expr b
- mkLets :: [Bind b] -> Expr b -> Expr b
- mkLams :: [b] -> Expr b -> Expr b
- mkApps :: Expr b -> [Arg b] -> Expr b
- mkTyApps :: Expr b -> [Type] -> Expr b
- mkCoApps :: Expr b -> [Coercion] -> Expr b
- mkVarApps :: Expr b -> [Var] -> Expr b
- mkTyArg :: Type -> Expr b
- mkIntLit :: DynFlags -> Integer -> Expr b
- mkIntLitInt :: DynFlags -> Int -> Expr b
- mkWordLit :: DynFlags -> Integer -> Expr b
- mkWordLitWord :: DynFlags -> Word -> Expr b
- mkWord64LitWord64 :: Word64 -> Expr b
- mkInt64LitInt64 :: Int64 -> Expr b
- mkCharLit :: Char -> Expr b
- mkStringLit :: String -> Expr b
- mkFloatLit :: Rational -> Expr b
- mkFloatLitFloat :: Float -> Expr b
- mkDoubleLit :: Rational -> Expr b
- mkDoubleLitDouble :: Double -> Expr b
- mkConApp :: DataCon -> [Arg b] -> Expr b
- mkConApp2 :: DataCon -> [Type] -> [Var] -> Expr b
- mkTyBind :: TyVar -> Type -> CoreBind
- mkCoBind :: CoVar -> Coercion -> CoreBind
- varToCoreExpr :: CoreBndr -> Expr b
- varsToCoreExprs :: [CoreBndr] -> [Expr b]
- isId :: Var -> Bool
- cmpAltCon :: AltCon -> AltCon -> Ordering
- cmpAlt :: (AltCon, a, b) -> (AltCon, a, b) -> Ordering
- ltAlt :: (AltCon, a, b) -> (AltCon, a, b) -> Bool
- bindersOf :: Bind b -> [b]
- bindersOfBinds :: [Bind b] -> [b]
- rhssOfBind :: Bind b -> [Expr b]
- rhssOfAlts :: [Alt b] -> [Expr b]
- collectBinders :: Expr b -> ([b], Expr b)
- collectTyBinders :: CoreExpr -> ([TyVar], CoreExpr)
- collectTyAndValBinders :: CoreExpr -> ([TyVar], [Id], CoreExpr)
- collectNBinders :: Int -> Expr b -> ([b], Expr b)
- collectArgs :: Expr b -> (Expr b, [Arg b])
- collectArgsTicks :: (Tickish Id -> Bool) -> Expr b -> (Expr b, [Arg b], [Tickish Id])
- flattenBinds :: [Bind b] -> [(b, Expr b)]
- exprToType :: CoreExpr -> Type
- exprToCoercion_maybe :: CoreExpr -> Maybe Coercion
- applyTypeToArg :: Type -> CoreExpr -> Type
- isValArg :: Expr b -> Bool
- isTypeArg :: Expr b -> Bool
- isTyCoArg :: Expr b -> Bool
- valArgCount :: [Arg b] -> Int
- valBndrCount :: [CoreBndr] -> Int
- isRuntimeArg :: CoreExpr -> Bool
- isRuntimeVar :: Var -> Bool
- tickishCounts :: Tickish id -> Bool
- tickishScoped :: Tickish id -> TickishScoping
- tickishScopesLike :: Tickish id -> TickishScoping -> Bool
- tickishFloatable :: Tickish id -> Bool
- tickishCanSplit :: Tickish id -> Bool
- mkNoCount :: Tickish id -> Tickish id
- mkNoScope :: Tickish id -> Tickish id
- tickishIsCode :: Tickish id -> Bool
- tickishPlace :: Tickish id -> TickishPlacement
- tickishContains :: Eq b => Tickish b -> Tickish b -> Bool
- data Unfolding
  - = NoUnfolding
  - | BootUnfolding
  - | OtherCon [AltCon]
  - | DFunUnfolding {
    - df_bndrs :: [Var]
    - df_con :: DataCon
    - df_args :: [CoreExpr]
    }
  - | CoreUnfolding {
    - uf_tmpl :: CoreExpr
    - uf_src :: UnfoldingSource
    - uf_is_top :: Bool
    - uf_is_value :: Bool
    - uf_is_conlike :: Bool
    - uf_is_work_free :: Bool
    - uf_expandable :: Bool
    - uf_guidance :: UnfoldingGuidance
    }
- data UnfoldingGuidance
  - = UnfWhen {
    - ug_arity :: Arity
    - ug_unsat_ok :: Bool
    - ug_boring_ok :: Bool
    }
  - | UnfIfGoodArgs {
    - ug_args :: [Int]
    - ug_size :: Int
    - ug_res :: Int
    }
  - | UnfNever
- data UnfoldingSource
  - = InlineRhs
  - | InlineStable
  - | InlineCompulsory
- noUnfolding :: Unfolding
- bootUnfolding :: Unfolding
- evaldUnfolding :: Unfolding
- mkOtherCon :: [AltCon] -> Unfolding
- unSaturatedOk :: Bool
- needSaturated :: Bool
- boringCxtOk :: Bool
- boringCxtNotOk :: Bool
- unfoldingTemplate :: Unfolding -> CoreExpr
- expandUnfolding_maybe :: Unfolding -> Maybe CoreExpr
- maybeUnfoldingTemplate :: Unfolding -> Maybe CoreExpr
- otherCons :: Unfolding -> [AltCon]
- isValueUnfolding :: Unfolding -> Bool
- isEvaldUnfolding :: Unfolding -> Bool
- isCheapUnfolding :: Unfolding -> Bool
- isExpandableUnfolding :: Unfolding -> Bool
- isConLikeUnfolding :: Unfolding -> Bool
- isCompulsoryUnfolding :: Unfolding -> Bool
- isStableUnfolding :: Unfolding -> Bool
- isFragileUnfolding :: Unfolding -> Bool
- hasSomeUnfolding :: Unfolding -> Bool
- isBootUnfolding :: Unfolding -> Bool
- canUnfold :: Unfolding -> Bool
- neverUnfoldGuidance :: UnfoldingGuidance -> Bool
- isStableSource :: UnfoldingSource -> Bool
- type AnnExpr bndr annot = (annot, AnnExpr' bndr annot)
- data AnnExpr' bndr annot
  - = AnnVar Id
  - | AnnLit Literal
  - | AnnLam bndr (AnnExpr bndr annot)
  - | AnnApp (AnnExpr bndr annot) (AnnExpr bndr annot)
  - | AnnCase (AnnExpr bndr annot) bndr Type [AnnAlt bndr annot]
  - | AnnLet (AnnBind bndr annot) (AnnExpr bndr annot)
  - | AnnCast (AnnExpr bndr annot) (annot, Coercion)
  - | AnnTick (Tickish Id) (AnnExpr bndr annot)
  - | AnnType Type
  - | AnnCoercion Coercion
- data AnnBind bndr annot
  - = AnnNonRec bndr (AnnExpr bndr annot)
  - | AnnRec [(bndr, AnnExpr bndr annot)]
- type AnnAlt bndr annot = (AltCon, [bndr], AnnExpr bndr annot)
- collectAnnArgs :: AnnExpr b a -> (AnnExpr b a, [AnnExpr b a])
- collectAnnArgsTicks :: (Tickish Var -> Bool) -> AnnExpr b a -> (AnnExpr b a, [AnnExpr b a], [Tickish Var])
- deAnnotate :: AnnExpr bndr annot -> Expr bndr
- deAnnotate' :: AnnExpr' bndr annot -> Expr bndr
- deAnnAlt :: AnnAlt bndr annot -> Alt bndr
- collectAnnBndrs :: AnnExpr bndr annot -> ([bndr], AnnExpr bndr annot)
- collectNAnnBndrs :: Int -> AnnExpr bndr annot -> ([bndr], AnnExpr bndr annot)
- data IsOrphan
  - = IsOrphan
  - | NotOrphan OccName
- isOrphan :: IsOrphan -> Bool
- notOrphan :: IsOrphan -> Bool
- chooseOrphanAnchor :: NameSet -> IsOrphan
- data CoreRule
  - = Rule {
    - ru_name :: RuleName
    - ru_act :: Activation
    - ru_fn :: Name
    - ru_rough :: [Maybe Name]
    - ru_bndrs :: [CoreBndr]
    - ru_args :: [CoreExpr]
    - ru_rhs :: CoreExpr
    - ru_auto :: Bool
    - ru_origin :: !Module
    - ru_orphan :: !IsOrphan
    - ru_local :: Bool
    }
  - | BuiltinRule {
    - ru_name :: RuleName
    - ru_fn :: Name
    - ru_nargs :: Int
    - ru_try :: RuleFun
    }
- type RuleBase = NameEnv [CoreRule]
- type RuleName = FastString
- type RuleFun = DynFlags -> InScopeEnv -> Id -> [CoreExpr] -> Maybe CoreExpr
- type IdUnfoldingFun = Id -> Unfolding
- type InScopeEnv = (InScopeSet, IdUnfoldingFun)
- data RuleEnv = RuleEnv {
  - re_base :: RuleBase
  - re_visible_orphs :: ModuleSet
  }
- mkRuleEnv :: RuleBase -> [Module] -> RuleEnv
- emptyRuleEnv :: RuleEnv
- ruleArity :: CoreRule -> Int
- ruleName :: CoreRule -> RuleName
- ruleIdName :: CoreRule -> Name
- ruleActivation :: CoreRule -> Activation
- setRuleIdName :: Name -> CoreRule -> CoreRule
- ruleModule :: CoreRule -> Maybe Module
- isBuiltinRule :: CoreRule -> Bool
- isLocalRule :: CoreRule -> Bool
- isAutoRule :: CoreRule -> Bool
- data CoreVect
  - = Vect Id CoreExpr
  - | NoVect Id
  - | VectType Bool TyCon (Maybe TyCon)
  - | VectClass TyCon
  - | VectInst Id

# Main data types

data Expr b #

This is the data type that represents GHCs core intermediate language. Currently GHC uses System FC https://www.microsoft.com/en-us/research/publication/system-f-with-type-equality-coercions/ for this purpose, which is closely related to the simpler and better known System F http://en.wikipedia.org/wiki/System_F.

We get from Haskell source to this Core language in a number of stages:

1. The source code is parsed into an abstract syntax tree, which is represented by the data type `HsExpr` with the names being `RdrNames`
2. This syntax tree is renamed, which attaches a `Unique` to every `RdrName` (yielding a `Name`) to disambiguate identifiers which are lexically identical. For example, this program:

         f x = let f x = x + 1
               in f (x - 2)

Would be renamed by having `Unique`s attached so it looked something like this:

         f_1 x_2 = let f_3 x_4 = x_4 + 1
                   in f_3 (x_2 - 2)

But see Note [Shadowing] below.

1. The resulting syntax tree undergoes type checking (which also deals with instantiating type class arguments) to yield a `HsExpr` type that has `Id` as it's names.
2. Finally the syntax tree is desugared from the expressive `HsExpr` type into this `Expr` type, which has far fewer constructors and hence is easier to perform optimization, analysis and code generation on.

The type parameter `b` is for the type of binders in the expression tree.

The language consists of the following elements:

- Variables
- Primitive literals
- Applications: note that the argument may be a `Type`. See Note [CoreSyn let/app invariant] See Note [Levity polymorphism invariants]
- Lambda abstraction See Note [Levity polymorphism invariants]
- Recursive and non recursive `let`s. Operationally this corresponds to allocating a thunk for the things bound and then executing the sub-expression.

The right hand sides of all top-level and recursive `let`s must be of lifted type (see Type for the meaning of lifted vs. unlifted). There is one exception to this rule, top-level `let`s are allowed to bind primitive string literals, see Note [CoreSyn top-level string literals].

See Note [CoreSyn let/app invariant] See Note [Levity polymorphism invariants]

We allow a non-recursive let to bind a type variable, thus:

    Let (NonRec tv (Type ty)) body

This can be very convenient for postponing type substitutions until the next run of the simplifier.

At the moment, the rest of the compiler only deals with type-let in a Let expression, rather than at top level. We may want to revist this choice.

- Case expression. Operationally this corresponds to evaluating the scrutinee (expression examined) to weak head normal form and then examining at most one level of resulting constructor (i.e. you cannot do nested pattern matching directly with this).

The binder gets bound to the value of the scrutinee, and the `Type` must be that of all the case alternatives

This is one of the more complicated elements of the Core language, and comes with a number of restrictions:

1. The list of alternatives may be empty; See Note [Empty case alternatives]
2. The `DEFAULT` case alternative must be first in the list, if it occurs at all.
3. The remaining cases are in order of increasing tag (for `DataAlts`) or lit (for `LitAlts`). This makes finding the relevant constructor easy, and makes comparison easier too.
4. The list of alternatives must be exhaustive. An exhaustive case does not necessarily mention all constructors:

               data Foo = Red | Green | Blue
          ... case x of
               Red   -> True
               other -> f (case x of
                               Green -> ...
                               Blue  -> ... ) ...

The inner case does not need a `Red` alternative, because `x` can't be `Red` at that program point.

1. Floating-point values must not be scrutinised against literals. See Trac #9238 and Note [Rules for floating-point comparisons] in PrelRules for rationale.

- Cast an expression to a particular type. This is used to implement `newtype`s (a `newtype` constructor or destructor just becomes a `Cast` in Core) and GADTs.
- Notes. These allow general information to be added to expressions in the syntax tree
- A type: this should only show up at the top level of an Arg
- A coercion

Constructors

Var Id |
Lit Literal |
App (Expr b) (Arg b) infixl 4 |
Lam b (Expr b) |
Let (Bind b) (Expr b) |
Case (Expr b) b Type [Alt b] |
Cast (Expr b) Coercion |
Tick (Tickish Id) (Expr b) |
Type Type |
Coercion Coercion |

Instances

Data b => Data (Expr b) # |

Methods

gfoldl :: (forall d a. Data d => c (d -> a) -> d -> c a) -> (forall g. g -> c g) -> Expr b -> c (Expr b) Source #

gunfold :: (forall a r. Data a => c (a -> r) -> c r) -> (forall r. r -> c r) -> Constr -> c (Expr b) Source #

toConstr :: Expr b -> Constr Source #

dataTypeOf :: Expr b -> DataType Source #

dataCast1 :: Typeable (* -> *) t => (forall d. Data d => c (t d)) -> Maybe (c (Expr b)) Source #

dataCast2 :: Typeable (* -> * -> *) t => (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c (Expr b)) Source #

gmapT :: (forall a. Data a => a -> a) -> Expr b -> Expr b Source #

gmapQl :: (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> Expr b -> r Source #

gmapQr :: (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> Expr b -> r Source #

gmapQ :: (forall d. Data d => d -> u) -> Expr b -> [u] Source #

gmapQi :: Int -> (forall d. Data d => d -> u) -> Expr b -> u Source #

gmapM :: Monad m => (forall d. Data d => d -> m d) -> Expr b -> m (Expr b) Source #

gmapMp :: MonadPlus m => (forall d. Data d => d -> m d) -> Expr b -> m (Expr b) Source #

gmapMo :: MonadPlus m => (forall d. Data d => d -> m d) -> Expr b -> m (Expr b) Source #

type Alt b = (AltCon, [b], Expr b) #

A case split alternative. Consists of the constructor leading to the alternative, the variables bound from the constructor, and the expression to be executed given that binding. The default alternative is `(DEFAULT, [], rhs)`

data Bind b #

Binding, used for top level bindings in a module and local bindings in a `let`.

Constructors

NonRec b (Expr b) |
Rec [(b, Expr b)] |

Instances

Data b => Data (Bind b) # |

Methods

gfoldl :: (forall d a. Data d => c (d -> a) -> d -> c a) -> (forall g. g -> c g) -> Bind b -> c (Bind b) Source #

gunfold :: (forall a r. Data a => c (a -> r) -> c r) -> (forall r. r -> c r) -> Constr -> c (Bind b) Source #

toConstr :: Bind b -> Constr Source #

dataTypeOf :: Bind b -> DataType Source #

dataCast1 :: Typeable (* -> *) t => (forall d. Data d => c (t d)) -> Maybe (c (Bind b)) Source #

dataCast2 :: Typeable (* -> * -> *) t => (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c (Bind b)) Source #

gmapT :: (forall a. Data a => a -> a) -> Bind b -> Bind b Source #

gmapQl :: (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> Bind b -> r Source #

gmapQr :: (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> Bind b -> r Source #

gmapQ :: (forall d. Data d => d -> u) -> Bind b -> [u] Source #

gmapQi :: Int -> (forall d. Data d => d -> u) -> Bind b -> u Source #

gmapM :: Monad m => (forall d. Data d => d -> m d) -> Bind b -> m (Bind b) Source #

gmapMp :: MonadPlus m => (forall d. Data d => d -> m d) -> Bind b -> m (Bind b) Source #

gmapMo :: MonadPlus m => (forall d. Data d => d -> m d) -> Bind b -> m (Bind b) Source #

data AltCon #

A case alternative constructor (i.e. pattern match)

Constructors

DataAlt DataCon |
LitAlt Literal | A literal: `case e of { 1 -> ... }` Invariant: always an *unlifted* literal See Note [Literal alternatives]
DEFAULT | Trivial alternative: `case e of { _ -> ... }`

Instances

Eq AltCon # |
Methods (==) :: AltCon -> AltCon -> Bool # (/=) :: AltCon -> AltCon -> Bool #
Data AltCon # |

Methods

gfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b) -> (forall g. g -> c g) -> AltCon -> c AltCon Source #

gunfold :: (forall b r. Data b => c (b -> r) -> c r) -> (forall r. r -> c r) -> Constr -> c AltCon Source #

toConstr :: AltCon -> Constr Source #

dataTypeOf :: AltCon -> DataType Source #

dataCast1 :: Typeable (* -> *) t => (forall d. Data d => c (t d)) -> Maybe (c AltCon) Source #

dataCast2 :: Typeable (* -> * -> *) t => (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c AltCon) Source #

gmapT :: (forall b. Data b => b -> b) -> AltCon -> AltCon Source #

gmapQl :: (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> AltCon -> r Source #

gmapQr :: (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> AltCon -> r Source #

gmapQ :: (forall d. Data d => d -> u) -> AltCon -> [u] Source #

gmapQi :: Int -> (forall d. Data d => d -> u) -> AltCon -> u Source #

gmapM :: Monad m => (forall d. Data d => d -> m d) -> AltCon -> m AltCon Source #

gmapMp :: MonadPlus m => (forall d. Data d => d -> m d) -> AltCon -> m AltCon Source #

gmapMo :: MonadPlus m => (forall d. Data d => d -> m d) -> AltCon -> m AltCon Source #

Outputable AltCon # |
Methods ppr :: AltCon -> SDoc # pprPrec :: Rational -> AltCon -> SDoc #

type Arg b = Expr b #

Type synonym for expressions that occur in function argument positions. Only `Arg` should contain a `Type` at top level, general `Expr` should not

data Tickish id #

Allows attaching extra information to points in expressions

Constructors

ProfNote | An `{--}` profiling annotation, either automatically added by the desugarer as a result of -auto-all, or added by the user.

Fields

- profNoteCC :: CostCentre

  the cost centre

- profNoteCount :: !Bool

  bump the entry count?

- profNoteScope :: !Bool

  scopes over the enclosed expression (i.e. not just a tick)

HpcTick | A "tick" used by HPC to track the execution of each subexpression in the original source code.

Fields

- tickModule :: Module
- tickId :: !Int

Breakpoint | 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)

Fields

- breakpointId :: !Int
- breakpointFVs :: [id]

  the order of this list is important: it matches the order of the lists in the appropriate entry in HscTypes.ModBreaks.

  Careful about substitution! See Note [substTickish] in CoreSubst.

SourceNote

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.

Fields

- sourceSpan :: RealSrcSpan

  Source covered

- sourceName :: String

  Name for source location (uses same names as CCs)

Instances

Eq id => Eq (Tickish id) # |
Methods (==) :: Tickish id -> Tickish id -> Bool # (/=) :: Tickish id -> Tickish id -> Bool #
Data id => Data (Tickish id) # |

Methods

gfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b) -> (forall g. g -> c g) -> Tickish id -> c (Tickish id) Source #

gunfold :: (forall b r. Data b => c (b -> r) -> c r) -> (forall r. r -> c r) -> Constr -> c (Tickish id) Source #

toConstr :: Tickish id -> Constr Source #

dataTypeOf :: Tickish id -> DataType Source #

dataCast1 :: Typeable (* -> *) t => (forall d. Data d => c (t d)) -> Maybe (c (Tickish id)) Source #

dataCast2 :: Typeable (* -> * -> *) t => (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c (Tickish id)) Source #

gmapT :: (forall b. Data b => b -> b) -> Tickish id -> Tickish id Source #

gmapQl :: (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> Tickish id -> r Source #

gmapQr :: (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> Tickish id -> r Source #

gmapQ :: (forall d. Data d => d -> u) -> Tickish id -> [u] Source #

gmapQi :: Int -> (forall d. Data d => d -> u) -> Tickish id -> u Source #

gmapM :: Monad m => (forall d. Data d => d -> m d) -> Tickish id -> m (Tickish id) Source #

gmapMp :: MonadPlus m => (forall d. Data d => d -> m d) -> Tickish id -> m (Tickish id) Source #

gmapMo :: MonadPlus m => (forall d. Data d => d -> m d) -> Tickish id -> m (Tickish id) Source #

Ord id => Ord (Tickish id) # |
Methods compare :: Tickish id -> Tickish id -> Ordering # (<) :: Tickish id -> Tickish id -> Bool # (<=) :: Tickish id -> Tickish id -> Bool # (>) :: Tickish id -> Tickish id -> Bool # (>=) :: Tickish id -> Tickish id -> Bool # max :: Tickish id -> Tickish id -> Tickish id # min :: Tickish id -> Tickish id -> Tickish id #

data TickishScoping #

Specifies the scoping behaviour of ticks. This governs the behaviour of ticks that care about the covered code and the cost associated with it. Important for ticks relating to profiling.

Constructors

NoScope | No scoping: The tick does not care about what code it covers. Transformations can freely move code inside as well as outside without any additional annotation obligations

SoftScope

Soft scoping: We want all code that is covered to stay covered. Note that this scope type does not forbid transformations from happening, as as long as all results of the transformations are still covered by this tick or a copy of it. 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" is concerned, because both still are scoped over by the tick.

Note though that 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.

Also note that this scoping behaviour allows floating a tick "upwards" in pretty much any situation. For example:

case foo of x -> tick... bar ==> tick... case foo of x -> bar

While this is always leagl, we want to make a best effort to only make us of this where it exposes transformation opportunities.

CostCentreScope

Cost centre scoping: We don't want any costs to move to other cost-centre stacks. This means we not only want no code or cost to get moved out of their cost centres, but we also object to code getting associated with new cost-centre ticks - or changing the order in which they get applied.

A rule of thumb is that we don't want any code to gain new annotations. However, there are notable exceptions, for example:

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

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

Instances

Eq TickishScoping # |
Methods (==) :: TickishScoping -> TickishScoping -> Bool # (/=) :: TickishScoping -> TickishScoping -> Bool #

data TickishPlacement #

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.

Constructors

PlaceRuntime | 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.
PlaceNonLam | 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.

PlaceCostCentre

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.

Instances

Eq TickishPlacement # |
Methods (==) :: TickishPlacement -> TickishPlacement -> Bool # (/=) :: TickishPlacement -> TickishPlacement -> Bool #

type CoreProgram = [CoreBind] #

type CoreExpr = Expr CoreBndr #

Expressions where binders are `CoreBndr`s

type CoreAlt = Alt CoreBndr #

Case alternatives where binders are `CoreBndr`s

type CoreBind = Bind CoreBndr #

Binding groups where binders are `CoreBndr`s

type CoreArg = Arg CoreBndr #

Argument expressions where binders are `CoreBndr`s

type CoreBndr = Var #

The common case for the type of binders and variables when we are manipulating the Core language within GHC

type TaggedExpr t = Expr (TaggedBndr t) #

type TaggedAlt t = Alt (TaggedBndr t) #

type TaggedBind t = Bind (TaggedBndr t) #

type TaggedArg t = Arg (TaggedBndr t) #

data TaggedBndr t #

Binders are tagged with a t

Constructors

TB CoreBndr t |

Instances

Outputable b => Outputable (TaggedBndr b) # |
Methods ppr :: TaggedBndr b -> SDoc # pprPrec :: Rational -> TaggedBndr b -> SDoc #

deTagExpr :: TaggedExpr t -> CoreExpr #

# In/Out type synonyms

type InId = Id #

type InBind = CoreBind #

type InExpr = CoreExpr #

type InAlt = CoreAlt #

type InArg = CoreArg #

type InType = Type #

type InKind = Kind #

type InBndr = CoreBndr #

type InVar = Var #

type InCoercion = Coercion #

type InTyVar = TyVar #

type InCoVar = CoVar #

type OutId = Id #

type OutBind = CoreBind #

type OutExpr = CoreExpr #

type OutAlt = CoreAlt #

type OutArg = CoreArg #

type OutType = Type #

type OutKind = Kind #

type OutBndr = CoreBndr #

type OutVar = Var #

type OutCoercion = Coercion #

type OutTyVar = TyVar #

type OutCoVar = CoVar #

## `Expr` construction

mkLet :: Bind b -> Expr b -> Expr b #

mkLets :: [Bind b] -> Expr b -> Expr b #

Bind all supplied binding groups over an expression in a nested let expression. Assumes that the rhs satisfies the let/app invariant. Prefer to use `mkCoreLets` if possible, which does guarantee the invariant

mkLams :: [b] -> Expr b -> Expr b #

Bind all supplied binders over an expression in a nested lambda expression. Prefer to use `mkCoreLams` if possible

mkApps :: Expr b -> [Arg b] -> Expr b infixl 4 #

Apply a list of argument expressions to a function expression in a nested fashion. Prefer to use `mkCoreApps` if possible

mkTyApps :: Expr b -> [Type] -> Expr b infixl 4 #

Apply a list of type argument expressions to a function expression in a nested fashion

mkCoApps :: Expr b -> [Coercion] -> Expr b infixl 4 #

Apply a list of coercion argument expressions to a function expression in a nested fashion

mkVarApps :: Expr b -> [Var] -> Expr b infixl 4 #

Apply a list of type or value variables to a function expression in a nested fashion

mkTyArg :: Type -> Expr b #

mkIntLit :: DynFlags -> Integer -> Expr b #

Create a machine integer literal expression of type `Int#` from an `Integer`. If you want an expression of type `Int` use `mkIntExpr`

mkIntLitInt :: DynFlags -> Int -> Expr b #

Create a machine integer literal expression of type `Int#` from an `Int`. If you want an expression of type `Int` use `mkIntExpr`

mkWordLit :: DynFlags -> Integer -> Expr b #

Create a machine word literal expression of type `Word#` from an `Integer`. If you want an expression of type `Word` use `mkWordExpr`

mkWordLitWord :: DynFlags -> Word -> Expr b #

Create a machine word literal expression of type `Word#` from a `Word`. If you want an expression of type `Word` use `mkWordExpr`

mkWord64LitWord64 :: Word64 -> Expr b #

mkInt64LitInt64 :: Int64 -> Expr b #

mkCharLit :: Char -> Expr b #

Create a machine character literal expression of type `Char#`. If you want an expression of type `Char` use `mkCharExpr`

mkStringLit :: String -> Expr b #

Create a machine string literal expression of type `Addr#`. If you want an expression of type `String` use `mkStringExpr`

mkFloatLit :: Rational -> Expr b #

Create a machine single precision literal expression of type `Float#` from a `Rational`. If you want an expression of type `Float` use `mkFloatExpr`

mkFloatLitFloat :: Float -> Expr b #

Create a machine single precision literal expression of type `Float#` from a `Float`. If you want an expression of type `Float` use `mkFloatExpr`

mkDoubleLit :: Rational -> Expr b #

Create a machine double precision literal expression of type `Double#` from a `Rational`. If you want an expression of type `Double` use `mkDoubleExpr`

mkDoubleLitDouble :: Double -> Expr b #

Create a machine double precision literal expression of type `Double#` from a `Double`. If you want an expression of type `Double` use `mkDoubleExpr`

mkConApp :: DataCon -> [Arg b] -> Expr b #

Apply a list of argument expressions to a data constructor in a nested fashion. Prefer to use `mkCoreConApps` if possible

mkConApp2 :: DataCon -> [Type] -> [Var] -> Expr b #

mkTyBind :: TyVar -> Type -> CoreBind #

Create a binding group where a type variable is bound to a type. Per CoreSyn, this can only be used to bind something in a non-recursive `let` expression

mkCoBind :: CoVar -> Coercion -> CoreBind #

Create a binding group where a type variable is bound to a type. Per CoreSyn, this can only be used to bind something in a non-recursive `let` expression

varToCoreExpr :: CoreBndr -> Expr b #

Convert a binder into either a `Var` or `Type` `Expr` appropriately

varsToCoreExprs :: [CoreBndr] -> [Expr b] #

isId :: Var -> Bool #

cmpAltCon :: AltCon -> AltCon -> Ordering #

Compares `AltCon`s within a single list of alternatives

cmpAlt :: (AltCon, a, b) -> (AltCon, a, b) -> Ordering #

ltAlt :: (AltCon, a, b) -> (AltCon, a, b) -> Bool #

## Simple `Expr` access functions and predicates

bindersOf :: Bind b -> [b] #

Extract every variable by this group

bindersOfBinds :: [Bind b] -> [b] #

`bindersOf` applied to a list of binding groups

rhssOfBind :: Bind b -> [Expr b] #

rhssOfAlts :: [Alt b] -> [Expr b] #

collectBinders :: Expr b -> ([b], Expr b) #

We often want to strip off leading lambdas before getting down to business. Variants are `collectTyBinders`, `collectValBinders`, and `collectTyAndValBinders`

collectTyBinders :: CoreExpr -> ([TyVar], CoreExpr) #

collectTyAndValBinders :: CoreExpr -> ([TyVar], [Id], CoreExpr) #

collectNBinders :: Int -> Expr b -> ([b], Expr b) #

Strip off exactly N leading lambdas (type or value). Good for use with join points.

collectArgs :: Expr b -> (Expr b, [Arg b]) #

Takes a nested application expression and returns the the function being applied and the arguments to which it is applied

collectArgsTicks :: (Tickish Id -> Bool) -> Expr b -> (Expr b, [Arg b], [Tickish Id]) #

Like `collectArgs`, but also collects looks through floatable ticks if it means that we can find more arguments.

flattenBinds :: [Bind b] -> [(b, Expr b)] #

Collapse all the bindings in the supplied groups into a single list of lhs/rhs pairs suitable for binding in a `Rec` binding group

exprToType :: CoreExpr -> Type #

If the expression is a `Type`, converts. Otherwise, panics. NB: This does not convert `Coercion` to `CoercionTy`.

exprToCoercion_maybe :: CoreExpr -> Maybe Coercion #

If the expression is a `Coercion`, converts.

applyTypeToArg :: Type -> CoreExpr -> Type #

Determines the type resulting from applying an expression with given type to a given argument expression

isValArg :: Expr b -> Bool #

Returns `True` for value arguments, false for type args NB: coercions are value arguments (zero width, to be sure, like State#, but still value args).

isTypeArg :: Expr b -> Bool #

Returns `True` iff the expression is a `Type` expression at its top level. Note this does NOT include `Coercion`s.

isTyCoArg :: Expr b -> Bool #

Returns `True` iff the expression is a `Type` or `Coercion` expression at its top level

valArgCount :: [Arg b] -> Int #

The number of argument expressions that are values rather than types at their top level

valBndrCount :: [CoreBndr] -> Int #

The number of binders that bind values rather than types

isRuntimeArg :: CoreExpr -> Bool #

Will this argument expression exist at runtime?

isRuntimeVar :: Var -> Bool #

Will this variable exist at runtime?

# Tick-related functions

tickishCounts :: Tickish id -> Bool #

A "counting tick" (where 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.

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.

tickishScoped :: Tickish id -> TickishScoping #

Returns the intended scoping rule for a Tickish

tickishScopesLike :: Tickish id -> TickishScoping -> Bool #

Returns whether the tick scoping rule is at least as permissive as the given scoping rule.

tickishFloatable :: Tickish id -> Bool #

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 `tickishSoftScope` 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.

tickishCanSplit :: Tickish id -> Bool #

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.

mkNoCount :: Tickish id -> Tickish id #

mkNoScope :: Tickish id -> Tickish id #

tickishIsCode :: Tickish id -> Bool #

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.

tickishPlace :: Tickish id -> TickishPlacement #

Placement behaviour we want for the ticks

tickishContains :: Eq b => Tickish b -> Tickish b -> Bool #

Returns whether one tick "contains" the other one, therefore making the second tick redundant.

# Unfolding data types

data Unfolding #

Records the unfolding of an identifier, which is approximately the form the identifier would have if we substituted its definition in for the identifier. This type should be treated as abstract everywhere except in CoreUnfold

Constructors

NoUnfolding | We have no information about the unfolding.
BootUnfolding | We have no information about the unfolding, because this `Id` came from an `hi-boot` file. See Note [Inlining and hs-boot files] in ToIface for what this is used for.

OtherCon [AltCon]

It ain't one of these constructors. `OtherCon xs` also indicates that something has been evaluated and hence there's no point in re-evaluating it. `OtherCon []` is used even for non-data-type values to indicated evaluated-ness. Notably:

    data C = C !(Int -> Int)
    case x of { C f -> ... }

Here, `f` gets an `OtherCon []` unfolding.

DFunUnfolding |

Fields

- df_bndrs :: [Var]
- df_con :: DataCon
- df_args :: [CoreExpr]

CoreUnfolding

An unfolding with redundant cached information. Parameters:

uf_tmpl: Template used to perform unfolding; NB: Occurrence info is guaranteed correct: see Note [OccInfo in unfoldings and rules]

uf_is_top: Is this a top level binding?

uf_is_value: `exprIsHNF` template (cached); it is ok to discard a `seq` on this variable

uf_is_work_free: Does this waste only a little work if we expand it inside an inlining? Basically this is a cached version of `exprIsWorkFree`

uf_guidance: Tells us about the size of the unfolding template

Fields

- uf_tmpl :: CoreExpr
- uf_src :: UnfoldingSource
- uf_is_top :: Bool
- uf_is_value :: Bool
- uf_is_conlike :: Bool
- uf_is_work_free :: Bool
- uf_expandable :: Bool
- uf_guidance :: UnfoldingGuidance

data UnfoldingGuidance #

`UnfoldingGuidance` says when unfolding should take place

Constructors

UnfWhen |

Fields

- ug_arity :: Arity
- ug_unsat_ok :: Bool
- ug_boring_ok :: Bool

UnfIfGoodArgs |

Fields

- ug_args :: [Int]
- ug_size :: Int
- ug_res :: Int

UnfNever |

Instances

Eq UnfoldingGuidance # |
Methods (==) :: UnfoldingGuidance -> UnfoldingGuidance -> Bool # (/=) :: UnfoldingGuidance -> UnfoldingGuidance -> Bool #

data UnfoldingSource #

Constructors

InlineRhs |
InlineStable |
InlineCompulsory |

## Constructing `Unfolding`s

noUnfolding :: Unfolding #

There is no known `Unfolding`

bootUnfolding :: Unfolding #

There is no known `Unfolding`, because this came from an hi-boot file.

evaldUnfolding :: Unfolding #

This unfolding marks the associated thing as being evaluated

mkOtherCon :: [AltCon] -> Unfolding #

unSaturatedOk :: Bool #

needSaturated :: Bool #

boringCxtOk :: Bool #

boringCxtNotOk :: Bool #

## Predicates and deconstruction on `Unfolding`

unfoldingTemplate :: Unfolding -> CoreExpr #

Retrieves the template of an unfolding: panics if none is known

expandUnfolding_maybe :: Unfolding -> Maybe CoreExpr #

maybeUnfoldingTemplate :: Unfolding -> Maybe CoreExpr #

Retrieves the template of an unfolding if possible maybeUnfoldingTemplate is used mainly wnen specialising, and we do want to specialise DFuns, so it's important to return a template for DFunUnfoldings

otherCons :: Unfolding -> [AltCon] #

The constructors that the unfolding could never be: returns `[]` if no information is available

isValueUnfolding :: Unfolding -> Bool #

Determines if it is certainly the case that the unfolding will yield a value (something in HNF): returns `False` if unsure

isEvaldUnfolding :: Unfolding -> Bool #

Determines if it possibly the case that the unfolding will yield a value. Unlike `isValueUnfolding` it returns `True` for `OtherCon`

isCheapUnfolding :: Unfolding -> Bool #

Is the thing we will unfold into certainly cheap?

isExpandableUnfolding :: Unfolding -> Bool #

isConLikeUnfolding :: Unfolding -> Bool #

`True` if the unfolding is a constructor application, the application of a CONLIKE function or `OtherCon`

isCompulsoryUnfolding :: Unfolding -> Bool #

isStableUnfolding :: Unfolding -> Bool #

isFragileUnfolding :: Unfolding -> Bool #

hasSomeUnfolding :: Unfolding -> Bool #

Only returns False if there is no unfolding information available at all

isBootUnfolding :: Unfolding -> Bool #

canUnfold :: Unfolding -> Bool #

neverUnfoldGuidance :: UnfoldingGuidance -> Bool #

isStableSource :: UnfoldingSource -> Bool #

# Annotated expression data types

type AnnExpr bndr annot = (annot, AnnExpr' bndr annot) #

Annotated core: allows annotation at every node in the tree

data AnnExpr' bndr annot #

A clone of the `Expr` type but allowing annotation at every tree node

Constructors

AnnVar Id |
AnnLit Literal |
AnnLam bndr (AnnExpr bndr annot) |
AnnApp (AnnExpr bndr annot) (AnnExpr bndr annot) |
AnnCase (AnnExpr bndr annot) bndr Type [AnnAlt bndr annot] |
AnnLet (AnnBind bndr annot) (AnnExpr bndr annot) |
AnnCast (AnnExpr bndr annot) (annot, Coercion) |
AnnTick (Tickish Id) (AnnExpr bndr annot) |
AnnType Type |
AnnCoercion Coercion |

data AnnBind bndr annot #

A clone of the `Bind` type but allowing annotation at every tree node

Constructors

AnnNonRec bndr (AnnExpr bndr annot) |
AnnRec [(bndr, AnnExpr bndr annot)] |

type AnnAlt bndr annot = (AltCon, [bndr], AnnExpr bndr annot) #

A clone of the `Alt` type but allowing annotation at every tree node

## Operations on annotated expressions

collectAnnArgs :: AnnExpr b a -> (AnnExpr b a, [AnnExpr b a]) #

Takes a nested application expression and returns the the function being applied and the arguments to which it is applied

collectAnnArgsTicks :: (Tickish Var -> Bool) -> AnnExpr b a -> (AnnExpr b a, [AnnExpr b a], [Tickish Var]) #

## Operations on annotations

deAnnotate :: AnnExpr bndr annot -> Expr bndr #

deAnnotate' :: AnnExpr' bndr annot -> Expr bndr #

deAnnAlt :: AnnAlt bndr annot -> Alt bndr #

collectAnnBndrs :: AnnExpr bndr annot -> ([bndr], AnnExpr bndr annot) #

As `collectBinders` but for `AnnExpr` rather than `Expr`

collectNAnnBndrs :: Int -> AnnExpr bndr annot -> ([bndr], AnnExpr bndr annot) #

As `collectNBinders` but for `AnnExpr` rather than `Expr`

# Orphanhood

data IsOrphan #

Is this instance an orphan? If it is not an orphan, contains an `OccName` witnessing the instance's non-orphanhood. See Note [Orphans]

Constructors

IsOrphan |
NotOrphan OccName |

Instances

Data IsOrphan # |

Methods

gfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b) -> (forall g. g -> c g) -> IsOrphan -> c IsOrphan Source #

gunfold :: (forall b r. Data b => c (b -> r) -> c r) -> (forall r. r -> c r) -> Constr -> c IsOrphan Source #

toConstr :: IsOrphan -> Constr Source #

dataTypeOf :: IsOrphan -> DataType Source #

dataCast1 :: Typeable (* -> *) t => (forall d. Data d => c (t d)) -> Maybe (c IsOrphan) Source #

dataCast2 :: Typeable (* -> * -> *) t => (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c IsOrphan) Source #

gmapT :: (forall b. Data b => b -> b) -> IsOrphan -> IsOrphan Source #

gmapQl :: (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> IsOrphan -> r Source #

gmapQr :: (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> IsOrphan -> r Source #

gmapQ :: (forall d. Data d => d -> u) -> IsOrphan -> [u] Source #

gmapQi :: Int -> (forall d. Data d => d -> u) -> IsOrphan -> u Source #

gmapM :: Monad m => (forall d. Data d => d -> m d) -> IsOrphan -> m IsOrphan Source #

gmapMp :: MonadPlus m => (forall d. Data d => d -> m d) -> IsOrphan -> m IsOrphan Source #

gmapMo :: MonadPlus m => (forall d. Data d => d -> m d) -> IsOrphan -> m IsOrphan Source #

Binary IsOrphan # |
Methods put_ :: BinHandle -> IsOrphan -> IO () # put :: BinHandle -> IsOrphan -> IO (Bin * IsOrphan) # get :: BinHandle -> IO IsOrphan #

isOrphan :: IsOrphan -> Bool #

Returns true if `IsOrphan` is orphan.

notOrphan :: IsOrphan -> Bool #

Returns true if `IsOrphan` is not an orphan.

chooseOrphanAnchor :: NameSet -> IsOrphan #

# Core rule data types

data CoreRule #

A `CoreRule` is:

- "Local" if the function it is a rule for is defined in the same module as the rule itself.
- "Orphan" if nothing on the LHS is defined in the same module as the rule itself

Constructors

Rule |

Fields

- ru_name :: RuleName

  Name of the rule, for communication with the user

- ru_act :: Activation

  When the rule is active

- ru_fn :: Name

  Name of the `Id` at the head of this rule

- ru_rough :: [Maybe Name]

  Name at the head of each argument to the left hand side

- ru_bndrs :: [CoreBndr]

  Variables quantified over

- ru_args :: [CoreExpr]

  Left hand side arguments

- ru_rhs :: CoreExpr

  Right hand side of the rule Occurrence info is guaranteed correct See Note [OccInfo in unfoldings and rules]

- ru_auto :: Bool

  `True` = this rule is auto-generated (notably by Specialise or SpecConstr) `False` = generated at the user's behest See Note [Trimming auto-rules] in TidyPgm for the sole purpose of this field.

- ru_origin :: !Module

  `Module` the rule was defined in, used to test if we should see an orphan rule.

- ru_orphan :: !IsOrphan

  Whether or not the rule is an orphan.

- ru_local :: Bool

  `True` iff the fn at the head of the rule is defined in the same module as the rule and is not an implicit `Id` (like a record selector, class operation, or data constructor). This is different from `ru_orphan`, where a rule can avoid being an orphan if *any* Name in LHS of the rule was defined in the same module as the rule.

BuiltinRule | Built-in rules are used for constant folding and suchlike. They have no free variables. A built-in rule is always visible (there is no such thing as an orphan built-in rule.)

Fields

- ru_name :: RuleName

  Name of the rule, for communication with the user

- ru_fn :: Name

  Name of the `Id` at the head of this rule

- ru_nargs :: Int

  Number of arguments that `ru_try` consumes, if it fires, including type arguments

- ru_try :: RuleFun

  This function does the rewrite. It given too many arguments, it simply discards them; the returned `CoreExpr` is just the rewrite of `ru_fn` applied to the first `ru_nargs` args

type RuleBase = NameEnv [CoreRule] #

Gathers a collection of `CoreRule`s. Maps (the name of) an `Id` to its rules

type RuleName = FastString #

type RuleFun = DynFlags -> InScopeEnv -> Id -> [CoreExpr] -> Maybe CoreExpr #

type IdUnfoldingFun = Id -> Unfolding #

type InScopeEnv = (InScopeSet, IdUnfoldingFun) #

data RuleEnv #

A full rule environment which we can apply rules from. Like a `RuleBase`, but it also includes the set of visible orphans we use to filter out orphan rules which are not visible (even though we can see them...)

Constructors

RuleEnv |

Fields

- re_base :: RuleBase
- re_visible_orphs :: ModuleSet

mkRuleEnv :: RuleBase -> [Module] -> RuleEnv #

emptyRuleEnv :: RuleEnv #

## Operations on `CoreRule`s

ruleArity :: CoreRule -> Int #

The number of arguments the `ru_fn` must be applied to before the rule can match on it

ruleName :: CoreRule -> RuleName #

ruleIdName :: CoreRule -> Name #

The `Name` of the `Id` at the head of the rule left hand side

ruleActivation :: CoreRule -> Activation #

setRuleIdName :: Name -> CoreRule -> CoreRule #

Set the `Name` of the `Id` at the head of the rule left hand side

ruleModule :: CoreRule -> Maybe Module #

isBuiltinRule :: CoreRule -> Bool #

isLocalRule :: CoreRule -> Bool #

isAutoRule :: CoreRule -> Bool #

# Core vectorisation declarations data type

data CoreVect #

Constructors

Vect Id CoreExpr |
NoVect Id |
VectType Bool TyCon (Maybe TyCon) |
VectClass TyCon |
VectInst Id |