%
+% (c) The University of Glasgow 2006
% (c) The GRASP/AQUA Project, Glasgow University, 1992-1998
%
-\section[DsBinds]{Pattern-matching bindings (HsBinds and MonoBinds)}
+
+Pattern-matching bindings (HsBinds and MonoBinds)
Handles @HsBinds@; those at the top level require different handling,
in that the @Rec@/@NonRec@/etc structure is thrown away (whereas at
#include "HsVersions.h"
-
import {-# SOURCE #-} DsExpr( dsLExpr, dsExpr )
import {-# SOURCE #-} Match( matchWrapper )
import DsMonad
-import DsGRHSs ( dsGuarded )
+import DsGRHSs
import DsUtils
import HsSyn -- lots of things
import CoreSyn -- lots of things
-import CoreUtils ( exprType, mkInlineMe, mkSCC )
-
-import StaticFlags ( opt_AutoSccsOnAllToplevs,
- opt_AutoSccsOnExportedToplevs )
-import OccurAnal ( occurAnalyseExpr )
-import CostCentre ( mkAutoCC, IsCafCC(..) )
-import Id ( Id, DictId, idType, idName, isExportedId, mkLocalId, setInlinePragma )
-import Rules ( addIdSpecialisations, mkLocalRule )
-import Var ( TyVar, Var, isGlobalId, setIdNotExported )
+import CoreUtils
+
+import OccurAnal
+import CostCentre
+import Module
+import Id
+import Rules
+import Var ( TyVar, Var )
import VarEnv
-import Type ( mkTyVarTy, substTyWith )
-import TysWiredIn ( voidTy )
+import Type
+import TysWiredIn
import Outputable
-import SrcLoc ( Located(..) )
-import Maybes ( isJust, catMaybes, orElse )
-import Bag ( bagToList )
-import BasicTypes ( Activation(..), InlineSpec(..), isAlwaysActive )
-import Monad ( foldM )
-import FastString ( mkFastString )
-import List ( (\\) )
+import SrcLoc
+import Maybes
+import Bag
+import BasicTypes hiding ( TopLevel )
+import FastString
import Util ( mapSnd )
+
+import Control.Monad
+import Data.List
\end{code}
%************************************************************************
dsHsBind auto_scc rest (FunBind { fun_id = L _ fun, fun_matches = matches, fun_co_fn = co_fn })
= matchWrapper (FunRhs (idName fun)) matches `thenDs` \ (args, body) ->
dsCoercion co_fn (return (mkLams args body)) `thenDs` \ rhs ->
- addAutoScc auto_scc (fun, rhs) `thenDs` \ pair ->
- returnDs (pair : rest)
+ returnDs ((fun,rhs) : rest)
dsHsBind auto_scc rest (PatBind { pat_lhs = pat, pat_rhs = grhss, pat_rhs_ty = ty })
= dsGuarded grhss ty `thenDs` \ body_expr ->
mkSelectorBinds pat body_expr `thenDs` \ sel_binds ->
- mappM (addAutoScc auto_scc) sel_binds `thenDs` \ sel_binds ->
returnDs (sel_binds ++ rest)
-- Note [Rules and inlining]
-- M.f = f_lcl -- Generated from "exports"
-- But we don't want that, because if M.f isn't exported,
-- it'll be inlined unconditionally at every call site (its rhs is
--- trivial). That woudl be ok unless it has RULES, which would
+-- trivial). That would be ok unless it has RULES, which would
-- thereby be completely lost. Bad, bad, bad.
--
-- Instead we want to generate
-- float the f_lcl binding out and then inline M.f at its call site
dsHsBind auto_scc rest (AbsBinds [] [] exports binds)
- = do { core_prs <- ds_lhs_binds (addSccs auto_scc exports) binds
- ; let env = mkVarEnv [ (lcl_id, (gbl_id, prags))
- | (_, gbl_id, lcl_id, prags) <- exports]
+ = do { core_prs <- ds_lhs_binds NoSccs binds
+ ; let env = mkABEnv exports
do_one (lcl_id, rhs) | Just (gbl_id, prags) <- lookupVarEnv env lcl_id
- = addInlinePrags prags gbl_id rhs
+ = addInlinePrags prags gbl_id $
+ addAutoScc auto_scc gbl_id rhs
| otherwise = (lcl_id, rhs)
locals' = [(lcl_id, Var gbl_id) | (_, gbl_id, lcl_id, _) <- exports]
; return (map do_one core_prs ++ locals' ++ rest) }
dsHsBind auto_scc rest
(AbsBinds all_tyvars dicts exports@[(tyvars, global, local, prags)] binds)
= ASSERT( all (`elem` tyvars) all_tyvars )
- ds_lhs_binds (addSccs auto_scc exports) binds `thenDs` \ core_prs ->
+ ds_lhs_binds NoSccs binds `thenDs` \ core_prs ->
let
-- Always treat the binds as recursive, because the typechecker
-- makes rather mixed-up dictionary bindings
(spec_binds, rules) = unzip (catMaybes mb_specs)
global' = addIdSpecialisations global rules
rhs' = mkLams tyvars $ mkLams dicts $ Let core_bind (Var local)
+ bind = addInlinePrags prags global' $ addAutoScc auto_scc global' rhs'
in
- returnDs (addInlinePrags prags global' rhs' : spec_binds ++ rest)
+ returnDs (bind : spec_binds ++ rest)
dsHsBind auto_scc rest (AbsBinds all_tyvars dicts exports binds)
- = ds_lhs_binds (addSccs auto_scc exports) binds `thenDs` \ core_prs ->
- let
- add_inline (bndr,rhs) | Just prags <- lookupVarEnv inline_env bndr
- = addInlinePrags prags bndr rhs
- | otherwise = (bndr,rhs)
- inline_env = mkVarEnv [(lcl_id, prags) | (_, _, lcl_id, prags) <- exports]
-
- -- Rec because of mixed-up dictionary bindings
- core_bind = Rec (map add_inline core_prs)
-
- tup_expr = mkTupleExpr locals
- tup_ty = exprType tup_expr
- poly_tup_expr = mkLams all_tyvars $ mkLams dicts $
- Let core_bind tup_expr
- locals = [local | (_, _, local, _) <- exports]
- local_tys = map idType locals
- in
- newSysLocalDs (exprType poly_tup_expr) `thenDs` \ poly_tup_id ->
- let
- dict_args = map Var dicts
-
- mk_bind ((tyvars, global, local, prags), n) -- locals !! n == local
- = -- Need to make fresh locals to bind in the selector, because
- -- some of the tyvars will be bound to voidTy
- newSysLocalsDs (map substitute local_tys) `thenDs` \ locals' ->
- newSysLocalDs (substitute tup_ty) `thenDs` \ tup_id ->
- mapM (dsSpec all_tyvars dicts tyvars global local core_bind)
- prags `thenDs` \ mb_specs ->
- let
- (spec_binds, rules) = unzip (catMaybes mb_specs)
- global' = addIdSpecialisations global rules
- rhs = mkLams tyvars $ mkLams dicts $
- mkTupleSelector locals' (locals' !! n) tup_id $
- mkApps (mkTyApps (Var poly_tup_id) ty_args) dict_args
- in
- returnDs ((global', rhs) : spec_binds)
- where
- mk_ty_arg all_tyvar | all_tyvar `elem` tyvars = mkTyVarTy all_tyvar
- | otherwise = voidTy
- ty_args = map mk_ty_arg all_tyvars
- substitute = substTyWith all_tyvars ty_args
- in
- mappM mk_bind (exports `zip` [0..]) `thenDs` \ export_binds_s ->
- -- don't scc (auto-)annotate the tuple itself.
+ = do { core_prs <- ds_lhs_binds NoSccs binds
+ ; let env = mkABEnv exports
+ do_one (lcl_id,rhs) | Just (gbl_id, prags) <- lookupVarEnv env lcl_id
+ = addInlinePrags prags lcl_id $
+ addAutoScc auto_scc gbl_id rhs
+ | otherwise = (lcl_id,rhs)
+
+ -- Rec because of mixed-up dictionary bindings
+ core_bind = Rec (map do_one core_prs)
+
+ tup_expr = mkTupleExpr locals
+ tup_ty = exprType tup_expr
+ poly_tup_expr = mkLams all_tyvars $ mkLams dicts $
+ Let core_bind tup_expr
+ locals = [local | (_, _, local, _) <- exports]
+ local_tys = map idType locals
+
+ ; poly_tup_id <- newSysLocalDs (exprType poly_tup_expr)
+
+ ; let dict_args = map Var dicts
+
+ mk_bind ((tyvars, global, local, prags), n) -- locals !! n == local
+ = -- Need to make fresh locals to bind in the selector, because
+ -- some of the tyvars will be bound to voidTy
+ do { locals' <- newSysLocalsDs (map substitute local_tys)
+ ; tup_id <- newSysLocalDs (substitute tup_ty)
+ ; mb_specs <- mapM (dsSpec all_tyvars dicts tyvars global local core_bind)
+ prags
+ ; let (spec_binds, rules) = unzip (catMaybes mb_specs)
+ global' = addIdSpecialisations global rules
+ rhs = mkLams tyvars $ mkLams dicts $
+ mkTupleSelector locals' (locals' !! n) tup_id $
+ mkApps (mkTyApps (Var poly_tup_id) ty_args) dict_args
+ ; returnDs ((global', rhs) : spec_binds) }
+ where
+ mk_ty_arg all_tyvar | all_tyvar `elem` tyvars = mkTyVarTy all_tyvar
+ | otherwise = voidTy
+ ty_args = map mk_ty_arg all_tyvars
+ substitute = substTyWith all_tyvars ty_args
+
+ ; export_binds_s <- mappM mk_bind (exports `zip` [0..])
+ -- don't scc (auto-)annotate the tuple itself.
+
+ ; returnDs ((poly_tup_id, poly_tup_expr) :
+ (concat export_binds_s ++ rest)) }
+
+mkABEnv :: [([TyVar], Id, Id, [Prag])] -> VarEnv (Id, [Prag])
+-- Takes the exports of a AbsBinds, and returns a mapping
+-- lcl_id -> (gbl_id, prags)
+mkABEnv exports = mkVarEnv [ (lcl_id, (gbl_id, prags))
+ | (_, gbl_id, lcl_id, prags) <- exports]
- returnDs ((poly_tup_id, poly_tup_expr) : (concat export_binds_s ++ rest))
dsSpec :: [TyVar] -> [DictId] -> [TyVar]
-> Id -> Id -- Global, local
%************************************************************************
\begin{code}
-data AutoScc
- = TopLevel
- | TopLevelAddSccs (Id -> Maybe Id)
- | NoSccs
-
-addSccs :: AutoScc -> [(a,Id,Id,[Prag])] -> AutoScc
-addSccs auto_scc@(TopLevelAddSccs _) exports = auto_scc
-addSccs NoSccs exports = NoSccs
-addSccs TopLevel exports
- = TopLevelAddSccs (\id -> case [ exp | (_,exp,loc,_) <- exports, loc == id ] of
- (exp:_) | opt_AutoSccsOnAllToplevs ||
- (isExportedId exp &&
- opt_AutoSccsOnExportedToplevs)
- -> Just exp
- _ -> Nothing)
-
-addAutoScc :: AutoScc -- if needs be, decorate toplevs?
- -> (Id, CoreExpr)
- -> DsM (Id, CoreExpr)
-
-addAutoScc (TopLevelAddSccs auto_scc_fn) pair@(bndr, core_expr)
- | do_auto_scc
- = getModuleDs `thenDs` \ mod ->
- returnDs (bndr, mkSCC (mkAutoCC top_bndr mod NotCafCC) core_expr)
- where do_auto_scc = isJust maybe_auto_scc
- maybe_auto_scc = auto_scc_fn bndr
- (Just top_bndr) = maybe_auto_scc
-
-addAutoScc _ pair
- = returnDs pair
+data AutoScc = NoSccs
+ | AddSccs Module (Id -> Bool)
+-- The (Id->Bool) says which Ids to add SCCs to
+
+addAutoScc :: AutoScc
+ -> Id -- Binder
+ -> CoreExpr -- Rhs
+ -> CoreExpr -- Scc'd Rhs
+
+addAutoScc NoSccs _ rhs
+ = rhs
+addAutoScc (AddSccs mod add_scc) id rhs
+ | add_scc id = mkSCC (mkAutoCC id mod NotCafCC) rhs
+ | otherwise = rhs
\end{code}
If profiling and dealing with a dict binding,
\begin{code}
-dsCoercion :: ExprCoFn -> DsM CoreExpr -> DsM CoreExpr
-dsCoercion CoHole thing_inside = thing_inside
-dsCoercion (CoCompose c1 c2) thing_inside = dsCoercion c1 (dsCoercion c2 thing_inside)
-dsCoercion (ExprCoFn co) thing_inside = do { expr <- thing_inside
+dsCoercion :: HsWrapper -> DsM CoreExpr -> DsM CoreExpr
+dsCoercion WpHole thing_inside = thing_inside
+dsCoercion (WpCompose c1 c2) thing_inside = dsCoercion c1 (dsCoercion c2 thing_inside)
+dsCoercion (WpCo co) thing_inside = do { expr <- thing_inside
; return (Cast expr co) }
-dsCoercion (CoLam id) thing_inside = do { expr <- thing_inside
+dsCoercion (WpLam id) thing_inside = do { expr <- thing_inside
; return (Lam id expr) }
-dsCoercion (CoTyLam tv) thing_inside = do { expr <- thing_inside
+dsCoercion (WpTyLam tv) thing_inside = do { expr <- thing_inside
; return (Lam tv expr) }
-dsCoercion (CoApp id) thing_inside = do { expr <- thing_inside
+dsCoercion (WpApp id) thing_inside = do { expr <- thing_inside
; return (App expr (Var id)) }
-dsCoercion (CoTyApp ty) thing_inside = do { expr <- thing_inside
+dsCoercion (WpTyApp ty) thing_inside = do { expr <- thing_inside
; return (App expr (Type ty)) }
-dsCoercion (CoLet bs) thing_inside = do { prs <- dsLHsBinds bs
+dsCoercion (WpLet bs) thing_inside = do { prs <- dsLHsBinds bs
; expr <- thing_inside
; return (Let (Rec prs) expr) }
\end{code}
-
-