2 % (c) The GRASP/AQUA Project, Glasgow University, 1992-1996
4 Taken quite directly from the Peyton Jones/Lester paper.
8 -- Cheap and cheerful variant...
9 exprFreeVars, exprFreeTyVars,
11 -- Complicated and expensive variant for float-out
13 freeVarsOf, freeTyVarsOf,
14 CoreExprWithFVs, -- For the above functions
16 FVInfo(..), LeakInfo(..)
19 #include "HsVersions.h"
21 import AnnCoreSyn -- output
24 import CoreUtils ( idSpecVars )
25 import Id ( idType, getIdArity, isBottomingId,
26 emptyIdSet, unitIdSet, mkIdSet, unionIdSets,
27 elementOfIdSet, minusIdSet, unionManyIdSets,
30 import IdInfo ( ArityInfo(..) )
31 import PrimOp ( PrimOp(..) )
32 import Type ( tyVarsOfType, Type )
33 import TyVar ( emptyTyVarSet, unitTyVarSet, minusTyVarSet,
34 intersectTyVarSets, unionManyTyVarSets,
37 import BasicTypes ( Unused )
38 import UniqSet ( unionUniqSets, addOneToUniqSet, delOneFromUniqSet )
39 import Util ( panic, assertPanic )
43 %************************************************************************
45 \section[freevars-everywhere]{Attaching free variables to every sub-expression
47 %************************************************************************
49 The free variable pass annotates every node in the expression with its
50 NON-GLOBAL free variables and type variables.
52 The ``free type variables'' are defined to be those which are mentioned
53 in type applications, {\em not} ones which lie buried in the types of Ids.
55 *** ALAS: we *do* need to collect tyvars from lambda-bound ids. ***
56 I've half-convinced myself we don't for case- and letrec bound ids
57 but I might be wrong. (SLPJ, date unknown)
60 type CoreExprWithFVs = AnnCoreExpr Id Id Unused FVInfo
62 type TyVarCands = TyVarSet -- for when we carry around lists of
63 type IdCands = IdSet -- "candidate" TyVars/Ids.
64 noTyVarCands = emptyTyVarSet
65 noIdCands = emptyIdSet
68 = FVInfo IdSet -- Free ids
69 TyVarSet -- Free tyvars
72 noFreeIds = emptyIdSet
73 noFreeTyVars = emptyTyVarSet
74 noFreeAnything = (noFreeIds, noFreeTyVars)
75 aFreeId i = unitIdSet i
76 aFreeTyVar t = unitTyVarSet t
77 is_among = elementOfIdSet
78 munge_id_ty i = tyVarsOfType (idType i)
79 combine = unionUniqSets -- used both for {Id,TyVar}Sets
80 without = delOneFromUniqSet
83 combineFVInfo (FVInfo fvs1 tfvs1 leak1) (FVInfo fvs2 tfvs2 leak2)
84 = FVInfo (fvs1 `combine` fvs2)
85 (tfvs1 `combine` tfvs2)
86 (leak1 `orLeak` leak2)
89 Leak-free-ness is based only on the value, not the type. In
90 particular, nested collections of constructors are guaranteed leak
91 free. Function applications are not, except for PAPs.
93 Applications of error gets (LeakFree bigArity) -- a hack!
98 | LeakFree Int -- Leak free, and guarantees to absorb this # of
99 -- args before becoming leaky.
101 lEAK_FREE_0 = LeakFree 0
102 lEAK_FREE_BIG = LeakFree bigArity
104 bigArity = 1000::Int -- NB: arbitrary
106 orLeak :: LeakInfo -> LeakInfo -> LeakInfo
107 orLeak MightLeak _ = MightLeak
108 orLeak _ MightLeak = MightLeak
109 orLeak (LeakFree n) (LeakFree m) = LeakFree (n `min` m)
112 Main public interface:
114 freeVars :: CoreExpr -> CoreExprWithFVs
116 freeVars expr = fvExpr noIdCands noTyVarCands expr
120 %************************************************************************
122 \subsection{Free variables (and types)}
124 %************************************************************************
126 We do the free-variable stuff by passing around ``candidates lists''
127 of @Ids@ and @TyVars@ that may be considered free. This is useful,
128 e.g., to avoid considering top-level binders as free variables---don't
129 put them on the candidates list.
133 fvExpr :: IdCands -- In-scope Ids
134 -> TyVarCands -- In-scope tyvars
138 fvExpr id_cands tyvar_cands (Var v)
139 = (FVInfo fvs noFreeTyVars leakiness, AnnVar v)
142 ToDo: insert motivating example for why we *need*
143 to include the idSpecVars in the FV list.
145 fvs = fvs_v `unionIdSets` mkIdSet (idSpecVars v)
148 | v `is_among` id_cands = aFreeId v
149 | otherwise = noFreeIds
152 | isBottomingId v = lEAK_FREE_BIG -- Hack
153 | otherwise = case getIdArity v of
154 UnknownArity -> lEAK_FREE_0
155 ArityAtLeast arity -> LeakFree arity
156 ArityExactly arity -> LeakFree arity
158 fvExpr id_cands tyvar_cands (Lit k)
159 = (FVInfo noFreeIds noFreeTyVars lEAK_FREE_0, AnnLit k)
161 fvExpr id_cands tyvar_cands (Con c args)
162 = (FVInfo args_fvs tfvs lEAK_FREE_0, AnnCon c args)
164 (args_fvs, tfvs) = freeArgs id_cands tyvar_cands args
166 fvExpr id_cands tyvar_cands (Prim op args)
167 = (FVInfo args_fvs tfvs lEAK_FREE_0, AnnPrim op args)
169 (args_fvs, tfvs) = freeArgs id_cands tyvar_cands args_to_use{-NB-}
172 CCallOp _ _ _ _ res_ty -> TyArg res_ty : args
175 -- this Lam stuff could probably be improved by rewriting (WDP 96/03)
177 fvExpr id_cands tyvar_cands (Lam b@(ValBinder binder) body)
178 = (FVInfo (freeVarsOf body2 `minusIdSet` unitIdSet binder)
179 (freeTyVarsOf body2 `combine` munge_id_ty binder)
183 -- We need to collect free tyvars from the binders
184 body2 = fvExpr (unitIdSet binder `combine` id_cands) tyvar_cands body
186 leakiness = case leakinessOf body2 of
187 MightLeak -> LeakFree 1
188 LeakFree n -> LeakFree (n + 1)
190 fvExpr id_cands tyvar_cands (Lam b@(TyBinder tyvar) body)
191 = (FVInfo (freeVarsOf body2)
192 (freeTyVarsOf body2 `minusTyVarSet` aFreeTyVar tyvar)
196 body2 = fvExpr id_cands (aFreeTyVar tyvar `combine` tyvar_cands) body
198 -- ditto on rewriting this App stuff (WDP 96/03)
200 fvExpr id_cands tyvar_cands (App fun arg)
201 = (FVInfo (freeVarsOf fun2 `combine` fvs_arg)
202 (freeTyVarsOf fun2 `combine` tfvs_arg)
206 fun2 = fvExpr id_cands tyvar_cands fun
207 fun2_leakiness = leakinessOf fun2
209 (fvs_arg, tfvs_arg) = freeArgs id_cands tyvar_cands [arg]
211 leakiness = if (notValArg arg) then
214 case fun2_leakiness of
215 LeakFree n | n>1 -> LeakFree (n-1) -- Note > not >=
218 fvExpr id_cands tyvar_cands (Case expr alts)
219 = (combineFVInfo expr_fvinfo alts_fvinfo,
222 expr2@(expr_fvinfo,_) = fvExpr id_cands tyvar_cands expr
223 (alts_fvinfo, alts') = annotate_alts alts
225 annotate_alts (AlgAlts alts deflt)
226 = (fvinfo, AnnAlgAlts alts' deflt')
228 (alts_fvinfo_s, alts') = unzip (map ann_boxed_alt alts)
229 (deflt_fvinfo, deflt') = annotate_default deflt
230 fvinfo = foldr combineFVInfo deflt_fvinfo alts_fvinfo_s
232 ann_boxed_alt (con, params, rhs)
233 = (FVInfo (freeVarsOf rhs' `minusIdSet` mkIdSet params)
234 (freeTyVarsOf rhs' `combine` param_ftvs)
238 rhs' = fvExpr (mkIdSet params `combine` id_cands) tyvar_cands rhs
239 param_ftvs = foldr (combine . munge_id_ty) noFreeTyVars params
240 -- We need to collect free tyvars from the binders
242 annotate_alts (PrimAlts alts deflt)
243 = (fvinfo, AnnPrimAlts alts' deflt')
245 (alts_fvinfo_s, alts') = unzip (map ann_unboxed_alt alts)
246 (deflt_fvinfo, deflt') = annotate_default deflt
247 fvinfo = foldr combineFVInfo deflt_fvinfo alts_fvinfo_s
249 ann_unboxed_alt (lit, rhs) = (rhs_info, (lit, rhs'))
251 rhs'@(rhs_info,_) = fvExpr id_cands tyvar_cands rhs
253 annotate_default NoDefault = (FVInfo noFreeIds noFreeTyVars lEAK_FREE_BIG,
256 annotate_default (BindDefault binder rhs)
257 = (FVInfo (freeVarsOf rhs' `minusIdSet` aFreeId binder)
258 (freeTyVarsOf rhs' `combine` binder_ftvs)
260 AnnBindDefault binder rhs')
262 rhs' = fvExpr (aFreeId binder `combine` id_cands) tyvar_cands rhs
263 binder_ftvs = munge_id_ty binder
264 -- We need to collect free tyvars from the binder
266 -- Don't forget to notice that the idSpecVars of the binder
267 -- are free in the whole expression; albeit not in the RHS or body
269 fvExpr id_cands tyvar_cands (Let (NonRec binder rhs) body)
270 = (FVInfo (freeVarsOf rhs' `combine` body_fvs `combine` mkIdSet (idSpecVars binder))
271 (freeTyVarsOf rhs' `combine` freeTyVarsOf body2 `combine` binder_ftvs)
272 (leakinessOf rhs' `orLeak` leakinessOf body2),
273 AnnLet (AnnNonRec binder rhs') body2)
275 rhs' = fvRhs id_cands tyvar_cands (binder, rhs)
276 body2 = fvExpr (aFreeId binder `combine` id_cands) tyvar_cands body
277 body_fvs = freeVarsOf body2 `minusIdSet` aFreeId binder
278 binder_ftvs = munge_id_ty binder
279 -- We need to collect free tyvars from the binder
281 fvExpr id_cands tyvar_cands (Let (Rec binds) body)
282 = (FVInfo (binds_fvs `combine` body_fvs)
283 (rhss_tfvs `combine` freeTyVarsOf body2 `combine` binders_ftvs)
284 (leakiness_of_rhss `orLeak` leakinessOf body2),
285 AnnLet (AnnRec (binders `zip` rhss')) body2)
287 (binders, rhss) = unzip binds
288 new_id_cands = binders_set `combine` id_cands
289 binders_set = mkIdSet binders
290 rhss' = map (fvRhs new_id_cands tyvar_cands) binds
292 FVInfo rhss_fvs rhss_tfvs leakiness_of_rhss
293 = foldr1 combineFVInfo [info | (info,_) <- rhss']
295 -- Don't forget to notice that the idSpecVars of the binder
296 -- are free in the whole expression; albeit not in the RHS or body
297 binds_fvs = (foldr (unionIdSets . mkIdSet . idSpecVars) rhss_fvs binders)
301 body2 = fvExpr new_id_cands tyvar_cands body
302 body_fvs = freeVarsOf body2 `minusIdSet` binders_set
303 binders_ftvs = foldr (combine . munge_id_ty) noFreeTyVars binders
304 -- We need to collect free tyvars from the binders
306 fvExpr id_cands tyvar_cands (Note (Coerce to_ty from_ty) expr)
307 = (FVInfo (freeVarsOf expr2)
308 (freeTyVarsOf expr2 `combine` tfvs1 `combine` tfvs2)
310 AnnNote (Coerce to_ty from_ty) expr2)
312 expr2 = fvExpr id_cands tyvar_cands expr
313 tfvs1 = freeTy tyvar_cands from_ty
314 tfvs2 = freeTy tyvar_cands to_ty
316 fvExpr id_cands tyvar_cands (Note other_note expr)
317 = (fvinfo, AnnNote other_note expr2)
319 expr2@(fvinfo,_) = fvExpr id_cands tyvar_cands expr
321 fvRhs id_cands tyvar_cands (bndr,rhs)
322 = fvExpr id_cands tyvar_cands rhs
326 freeArgs :: IdCands -> TyVarCands
330 freeArgs icands tcands [] = noFreeAnything
331 freeArgs icands tcands (arg:args)
332 -- this code is written this funny way only for "efficiency" purposes
334 free_first_arg@(arg_fvs, tfvs) = free_arg arg
339 case (freeArgs icands tcands args) of { (irest, trest) ->
340 (arg_fvs `combine` irest, tfvs `combine` trest) }
342 free_arg (LitArg _) = noFreeAnything
343 free_arg (TyArg ty) = (noFreeIds, freeTy tcands ty)
345 | v `is_among` icands = (aFreeId v, noFreeTyVars)
346 | otherwise = noFreeAnything
349 freeTy :: TyVarCands -> Type -> TyVarSet
351 freeTy cands ty = tyVarsOfType ty `intersectTyVarSets` cands
353 freeVarsOf :: CoreExprWithFVs -> IdSet
354 freeVarsOf (FVInfo free_vars _ _, _) = free_vars
356 freeTyVarsOf :: CoreExprWithFVs -> TyVarSet
357 freeTyVarsOf (FVInfo _ free_tyvars _, _) = free_tyvars
359 leakinessOf :: CoreExprWithFVs -> LeakInfo
360 leakinessOf (FVInfo _ _ leakiness, _) = leakiness
364 %************************************************************************
366 \section{Finding the free variables of an expression}
368 %************************************************************************
370 This function simply finds the free variables of an expression.
373 type InterestingIdFun
374 = Id -- The Id being looked at
375 -> Bool -- True <=> interesting
377 exprFreeVars :: InterestingIdFun -> CoreExpr -> IdSet
378 exprFreeVars fv_cand e = expr_fvs fv_cand emptyIdSet e
383 expr_fvs :: InterestingIdFun -- "Interesting id" predicate
384 -> IdSet -- In scope ids
388 expr_fvs fv_cand in_scope (Var v) = id_fvs fv_cand in_scope v
389 expr_fvs fv_cand in_scope (Lit lit) = noFreeIds
390 expr_fvs fv_cand in_scope (Con con args) = args_fvs fv_cand in_scope args
391 expr_fvs fv_cand in_scope (Prim op args) = args_fvs fv_cand in_scope args
392 expr_fvs fv_cand in_scope (Note _ expr) = expr_fvs fv_cand in_scope expr
393 expr_fvs fv_cand in_scope (App fun arg) = expr_fvs fv_cand in_scope fun `combine`
394 arg_fvs fv_cand in_scope arg
397 expr_fvs fv_cand in_scope (Lam (ValBinder b) body)
398 = (expr_fvs fv_cand (in_scope `add` b) body)
399 expr_fvs fv_cand in_scope (Lam (TyBinder b) body)
400 = expr_fvs fv_cand in_scope body
402 expr_fvs fv_cand in_scope (Case scrut alts)
403 = expr_fvs fv_cand in_scope scrut `combine` alts_fvs
407 AlgAlts alg_alts deflt -> unionManyIdSets (deflt_fvs : alt_fvs)
409 alt_fvs = map do_alg_alt alg_alts
410 deflt_fvs = do_deflt deflt
412 PrimAlts prim_alts deflt -> unionManyIdSets (deflt_fvs : alt_fvs)
414 alt_fvs = map do_prim_alt prim_alts
415 deflt_fvs = do_deflt deflt
417 do_alg_alt :: (Id, [Id], CoreExpr) -> IdSet
418 do_alg_alt (con, args, rhs) = expr_fvs fv_cand new_in_scope rhs
420 new_in_scope = in_scope `combine` mkIdSet args
422 do_prim_alt (lit, rhs) = expr_fvs fv_cand in_scope rhs
424 do_deflt NoDefault = noFreeIds
425 do_deflt (BindDefault b rhs) = expr_fvs fv_cand (in_scope `add` b) rhs
427 expr_fvs fv_cand in_scope (Let (NonRec b r) body)
428 = expr_fvs fv_cand in_scope r `combine`
429 expr_fvs fv_cand (in_scope `add` b) body
431 expr_fvs fv_cand in_scope (Let (Rec pairs) body)
432 = foldr (combine . expr_fvs fv_cand in_scope' . snd) noFreeIds pairs `combine`
433 expr_fvs fv_cand in_scope' body
435 in_scope' = in_scope `combine` mkIdSet (map fst pairs)
440 --------------------------------------
441 arg_fvs fv_cand in_scope (VarArg v) = id_fvs fv_cand in_scope v
442 arg_fvs fv_cand in_scope other_arg = noFreeIds
444 --------------------------------------
445 args_fvs fv_cand in_scope args = foldr (combine . arg_fvs fv_cand in_scope) noFreeIds args
448 --------------------------------------
449 id_fvs fv_cand in_scope v
450 | v `elementOfIdSet` in_scope = noFreeIds
451 | fv_cand v = aFreeId v
452 | otherwise = noFreeIds
457 exprFreeTyVars :: CoreExpr -> TyVarSet
458 exprFreeTyVars = expr_ftvs
460 expr_ftvs :: CoreExpr -> TyVarSet
461 expr_ftvs (Var v) = noFreeTyVars
462 expr_ftvs (Lit lit) = noFreeTyVars
463 expr_ftvs (Con con args) = args_ftvs args
464 expr_ftvs (Prim op args) = args_ftvs args
465 expr_ftvs (Note _ expr) = expr_ftvs expr
466 expr_ftvs (App fun arg) = expr_ftvs fun `combine` arg_ftvs arg
468 expr_ftvs (Lam (ValBinder b) body) = expr_ftvs body
469 expr_ftvs (Lam (TyBinder b) body) = expr_ftvs body `without` b
471 expr_ftvs (Case scrut alts)
472 = expr_ftvs scrut `combine` alts_ftvs
476 AlgAlts alg_alts deflt -> unionManyTyVarSets (deflt_ftvs : alt_ftvs)
478 alt_ftvs = map do_alg_alt alg_alts
479 deflt_ftvs = do_deflt deflt
481 PrimAlts prim_alts deflt -> unionManyTyVarSets (deflt_ftvs : alt_ftvs)
483 alt_ftvs = map do_prim_alt prim_alts
484 deflt_ftvs = do_deflt deflt
486 do_alg_alt :: (Id, [Id], CoreExpr) -> TyVarSet
487 do_alg_alt (con, args, rhs) = expr_ftvs rhs
489 do_prim_alt (lit, rhs) = expr_ftvs rhs
491 do_deflt NoDefault = noFreeTyVars
492 do_deflt (BindDefault b rhs) = expr_ftvs rhs
494 expr_ftvs (Let (NonRec b r) body)
495 = bind_ftvs (b,r) `combine` expr_ftvs body
497 expr_ftvs (Let (Rec pairs) body)
498 = foldr (combine . bind_ftvs) noFreeTyVars pairs `combine`
501 --------------------------------------
502 bind_ftvs (b,e) = tyVarsOfType (idType b) `combine` expr_ftvs e
504 --------------------------------------
505 arg_ftvs (TyArg ty) = tyVarsOfType ty
506 arg_ftvs other_arg = noFreeTyVars
508 --------------------------------------
509 args_ftvs args = foldr (combine . arg_ftvs) noFreeTyVars args