X-Git-Url: http://git.megacz.com/?p=ghc-hetmet.git;a=blobdiff_plain;f=compiler%2FdeSugar%2FDesugar.lhs;h=9616c62dc35c492b2623e0db8a293fe3c1400b10;hp=64fff0d0129fe1d34798e3e7f96b87ad7ebe0c2f;hb=d2ce0f52d42edf32bb9f13796e6ba6edba8bd516;hpb=0084ab49ab3c0123c4b7f9523d092af45bccfd41 diff --git a/compiler/deSugar/Desugar.lhs b/compiler/deSugar/Desugar.lhs index 64fff0d..9616c62 100644 --- a/compiler/deSugar/Desugar.lhs +++ b/compiler/deSugar/Desugar.lhs @@ -17,6 +17,7 @@ import MkIface import Id import Name import CoreSyn +import CoreSubst import PprCore import DsMonad import DsExpr @@ -27,6 +28,7 @@ import DsExpr () -- Forces DsExpr to be compiled; DsBinds only import Module import RdrName import NameSet +import NameEnv import Rules import CoreMonad ( endPass, CoreToDo(..) ) import ErrUtils @@ -35,7 +37,9 @@ import SrcLoc import Maybes import FastString import Coverage +import Util +import Data.List import Data.IORef \end{code} @@ -65,6 +69,7 @@ deSugar hsc_env tcg_warns = warns, tcg_anns = anns, tcg_binds = binds, + tcg_ev_binds = ev_binds, tcg_fords = fords, tcg_rules = rules, tcg_insts = insts, @@ -83,42 +88,51 @@ deSugar hsc_env <- case target of HscNothing -> return (emptyMessages, - Just ([], [], NoStubs, hpcInfo, emptyModBreaks)) + Just ([], [], [], NoStubs, hpcInfo, emptyModBreaks)) _ -> do (binds_cvr,ds_hpc_info, modBreaks) <- if (opt_Hpc || target == HscInterpreted) && (not (isHsBoot hsc_src)) - then addCoverageTicksToBinds dflags mod mod_loc (typeEnvTyCons type_env) binds + then addCoverageTicksToBinds dflags mod mod_loc + (typeEnvTyCons type_env) binds else return (binds, hpcInfo, emptyModBreaks) initDs hsc_env mod rdr_env type_env $ do + ds_ev_binds <- dsEvBinds ev_binds core_prs <- dsTopLHsBinds auto_scc binds_cvr (ds_fords, foreign_prs) <- dsForeigns fords let all_prs = foreign_prs ++ core_prs - ds_rules <- mapM dsRule rules - return (all_prs, catMaybes ds_rules, ds_fords, ds_hpc_info, modBreaks) + mb_rules <- mapM dsRule rules + return (ds_ev_binds, all_prs, mb_rules, ds_fords, ds_hpc_info, modBreaks) ; case mb_res of { Nothing -> return (msgs, Nothing) ; - Just (all_prs, ds_rules, ds_fords,ds_hpc_info, modBreaks) -> do + Just (ds_ev_binds, all_prs, mb_rules, ds_fords,ds_hpc_info, modBreaks) -> do { -- Add export flags to bindings keep_alive <- readIORef keep_var - ; let final_prs = addExportFlags target export_set - keep_alive all_prs - ds_binds = [Rec final_prs] + ; let (rules_for_locals, rules_for_imps) + = partition isLocalRule (catMaybes mb_rules) + final_prs = addExportFlagsAndRules target + export_set keep_alive rules_for_locals all_prs + + final_pgm = combineEvBinds ds_ev_binds final_prs -- Notice that we put the whole lot in a big Rec, even the foreign binds -- When compiling PrelFloat, which defines data Float = F# Float# -- we want F# to be in scope in the foreign marshalling code! -- You might think it doesn't matter, but the simplifier brings all top-level -- things into the in-scope set before simplifying; so we get no unfolding for F#! - -- Lint result if necessary - ; endPass dflags CoreDesugar ds_binds ds_rules + -- Lint result if necessary, and print + ; dumpIfSet_dyn dflags Opt_D_dump_ds "Desugared, before opt" $ + (vcat [ pprCoreBindings final_pgm + , pprRules rules_for_imps ]) + + ; (ds_binds, ds_rules_for_imps) <- simpleOptPgm dflags final_pgm rules_for_imps + -- The simpleOptPgm gets rid of type + -- bindings plus any stupid dead code - -- Dump output - ; doIfSet (dopt Opt_D_dump_ds dflags) - (printDump (ppr_ds_rules ds_rules)) + ; endPass dflags CoreDesugar ds_binds ds_rules_for_imps ; used_names <- mkUsedNames tcg_env ; deps <- mkDependencies tcg_env @@ -139,7 +153,7 @@ deSugar hsc_env mg_fam_insts = fam_insts, mg_inst_env = inst_env, mg_fam_inst_env = fam_inst_env, - mg_rules = ds_rules, + mg_rules = ds_rules_for_imps, mg_binds = ds_binds, mg_foreign = ds_fords, mg_hpc_info = ds_hpc_info, @@ -149,6 +163,33 @@ deSugar hsc_env ; return (msgs, Just mod_guts) }}} + +combineEvBinds :: [DsEvBind] -> [(Id,CoreExpr)] -> [CoreBind] +-- Top-level bindings can include coercion bindings, but not via superclasses +-- See Note [Top-level evidence] +combineEvBinds [] val_prs + = [Rec val_prs] +combineEvBinds (LetEvBind (NonRec b r) : bs) val_prs + | isId b = combineEvBinds bs ((b,r):val_prs) + | otherwise = NonRec b r : combineEvBinds bs val_prs +combineEvBinds (LetEvBind (Rec prs) : bs) val_prs + = combineEvBinds bs (prs ++ val_prs) +combineEvBinds (CaseEvBind x _ _ : _) _ + = pprPanic "topEvBindPairs" (ppr x) +\end{code} + +Note [Top-level evidence] +~~~~~~~~~~~~~~~~~~~~~~~~~ +Top-level evidence bindings may be mutually recursive with the top-level value +bindings, so we must put those in a Rec. But we can't put them *all* in a Rec +because the occurrence analyser doesn't teke account of type/coercion variables +when computing dependencies. + +So we pull out the type/coercion variables (which are in dependency order), +and Rec the rest. + + +\begin{code} mkAutoScc :: DynFlags -> Module -> NameSet -> AutoScc mkAutoScc dflags mod exports | not opt_SccProfilingOn -- No profiling @@ -187,36 +228,45 @@ deSugarExpr hsc_env this_mod rdr_env type_env tc_expr = do dumpIfSet_dyn dflags Opt_D_dump_ds "Desugared" (pprCoreExpr expr) return (msgs, Just expr) +\end{code} --- addExportFlags --- Set the no-discard flag if either --- a) the Id is exported --- b) it's mentioned in the RHS of an orphan rule --- c) it's in the keep-alive set --- --- It means that the binding won't be discarded EVEN if the binding --- ends up being trivial (v = w) -- the simplifier would usually just --- substitute w for v throughout, but we don't apply the substitution to --- the rules (maybe we should?), so this substitution would make the rule --- bogus. - --- You might wonder why exported Ids aren't already marked as such; --- it's just because the type checker is rather busy already and --- I didn't want to pass in yet another mapping. - -addExportFlags :: HscTarget -> NameSet -> NameSet -> [(Id, t)] - -> [(Id, t)] -addExportFlags target exports keep_alive prs - = [(add_export bndr, rhs) | (bndr,rhs) <- prs] +%************************************************************************ +%* * +%* Add rules and export flags to binders +%* * +%************************************************************************ + +\begin{code} +addExportFlagsAndRules + :: HscTarget -> NameSet -> NameSet -> [CoreRule] + -> [(Id, t)] -> [(Id, t)] +addExportFlagsAndRules target exports keep_alive rules prs + = mapFst add_one prs where - add_export bndr - | dont_discard bndr = setIdExported bndr + add_one bndr = add_rules name (add_export name bndr) + where + name = idName bndr + + ---------- Rules -------- + -- See Note [Attach rules to local ids] + -- NB: the binder might have some existing rules, + -- arising from specialisation pragmas + add_rules name bndr + | Just rules <- lookupNameEnv rule_base name + = bndr `addIdSpecialisations` rules + | otherwise + = bndr + rule_base = extendRuleBaseList emptyRuleBase rules + + ---------- Export flag -------- + -- See Note [Adding export flags] + add_export name bndr + | dont_discard name = setIdExported bndr | otherwise = bndr - dont_discard bndr = is_exported name + dont_discard :: Name -> Bool + dont_discard name = is_exported name || name `elemNameSet` keep_alive - where - name = idName bndr -- In interactive mode, we don't want to discard any top-level -- entities at all (eg. do not inline them away during @@ -228,15 +278,44 @@ addExportFlags target exports keep_alive prs is_exported :: Name -> Bool is_exported | target == HscInterpreted = isExternalName | otherwise = (`elemNameSet` exports) - -ppr_ds_rules :: [CoreRule] -> SDoc -ppr_ds_rules [] = empty -ppr_ds_rules rules - = blankLine $$ text "-------------- DESUGARED RULES -----------------" $$ - pprRules rules \end{code} +Note [Adding export flags] +~~~~~~~~~~~~~~~~~~~~~~~~~~ +Set the no-discard flag if either + a) the Id is exported + b) it's mentioned in the RHS of an orphan rule + c) it's in the keep-alive set + +It means that the binding won't be discarded EVEN if the binding +ends up being trivial (v = w) -- the simplifier would usually just +substitute w for v throughout, but we don't apply the substitution to +the rules (maybe we should?), so this substitution would make the rule +bogus. + +You might wonder why exported Ids aren't already marked as such; +it's just because the type checker is rather busy already and +I didn't want to pass in yet another mapping. + +Note [Attach rules to local ids] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Find the rules for locally-defined Ids; then we can attach them +to the binders in the top-level bindings + +Reason + - It makes the rules easier to look up + - It means that transformation rules and specialisations for + locally defined Ids are handled uniformly + - It keeps alive things that are referred to only from a rule + (the occurrence analyser knows about rules attached to Ids) + - It makes sure that, when we apply a rule, the free vars + of the RHS are more likely to be in scope + - The imported rules are carried in the in-scope set + which is extended on each iteration by the new wave of + local binders; any rules which aren't on the binding will + thereby get dropped + %************************************************************************ %* * @@ -250,23 +329,24 @@ dsRule (L loc (HsRule name act vars lhs _tv_lhs rhs _fv_rhs)) = putSrcSpanDs loc $ do { let bndrs' = [var | RuleBndr (L _ var) <- vars] - ; lhs' <- unsetOptM Opt_EnableRewriteRules $ - dsLExpr lhs -- Note [Desugaring RULE lhss] + ; lhs' <- unsetOptM Opt_EnableRewriteRules $ + dsLExpr lhs -- Note [Desugaring RULE left hand sides] - ; rhs' <- dsLExpr rhs + ; rhs' <- dsLExpr rhs -- Substitute the dict bindings eagerly, -- and take the body apart into a (f args) form - ; case decomposeRuleLhs (mkLams bndrs' lhs') of { + ; case decomposeRuleLhs lhs' of { Nothing -> do { warnDs msg; return Nothing } ; - Just (bndrs, fn_id, args) -> do + Just (fn_id, args) -> do { let local_rule = isLocalId fn_id -- NB: isLocalId is False of implicit Ids. This is good becuase -- we don't want to attach rules to the bindings of implicit Ids, -- because they don't show up in the bindings until just before code gen - fn_name = idName fn_id - rule = mkRule local_rule name act fn_name bndrs args rhs' + fn_name = idName fn_id + final_rhs = simpleOptExpr rhs' -- De-crap it + rule = mkRule local_rule name act fn_name bndrs' args final_rhs ; return (Just rule) } } } where @@ -283,3 +363,5 @@ of cons's. We can achieve that slightly indirectly by switching off EnableRewriteRules. See DsExpr.dsExplicitList. That keeps the desugaring of list comprehensions simple too. + +