ghc-9.6.2: The GHC API
Safe HaskellSafe-Inferred



Non-global free variable analysis on STG terms. This pass annotates non-top-level closure bindings with captured variables. Global variables are not captured. For example, in a top-level binding like (pseudo-STG)

f = [x,y] . let g = [p] . reverse (x ++ p) in g y

In g, reverse and (++) are global variables so they're not considered free. p is an argument, so x is the only actual free variable here. The annotated version is thus:

f = [x,y] . let g = [x] [p] . reverse (x ++ p) in g y

Note that non-top-level recursive bindings are also considered free within the group:

map = {} r [f xs0] let { Rec { go = {f, go} r [xs1] case xs1 of { [] -> [] []; : x xs2 -> let { xs' = {go, xs2} u [] go xs2; } in let { x' = {f, x} u [] f x; } in : [x' xs']; }; end Rec } } in go xs0;

Here go is free in its RHS.

Top-level closure bindings never capture variables as all of their free variables are global.



depSortWithAnnotStgPgm :: Module -> [StgTopBinding] -> [CgStgTopBinding] Source #

Dependency sort a STG program, and annotate it with free variables The returned bindings: * Are in dependency order * Each StgRhsClosure is correctly annotated (in its extension field) with the free variables needed in the closure * Each StgCase is correctly annotated (in its extension field) with the variables that must be saved across the case

annBindingFreeVars :: Module -> StgBinding -> CgStgBinding Source #

Dependency analysis on STG terms.

Dependencies of a binding are just free variables in the binding. This includes imported ids and ids in the current module. For recursive groups we just return one set of free variables which is just the union of dependencies of all bindings in the group.

Implementation: pass bound variables (NestedIds) to recursive calls, get free variables (TopFVs) back. We ignore imported TopFVs as they do not change the ordering but it improves performance (see nameIsExternalFrom call in vars_fvs).