2 % (c) The GRASP/AQUA Project, Glasgow University, 1993-1996
4 \section[CoreLift]{Lifts unboxed bindings and any references to them}
17 #include "HsVersions.h"
20 import CoreUtils ( coreExprType )
21 import Id ( idType, mkSysLocal,
22 nullIdEnv, growIdEnvList, lookupIdEnv,
24 IdEnv, GenId{-instances-}, Id
26 import Name ( isLocallyDefined, getSrcLoc, getOccString )
27 import TyCon ( isBoxedTyCon, TyCon{-instance-} )
28 import Type ( splitAlgTyConApp_maybe )
29 import TysPrim ( statePrimTyCon )
30 import TysWiredIn ( liftDataCon, mkLiftTy )
31 import Unique ( Unique )
32 import UniqSupply ( getUnique, getUniques, splitUniqSupply, UniqSupply )
33 import Util ( zipEqual, zipWithEqual, assertPanic, panic )
39 %************************************************************************
41 \subsection{``lift'' for various constructs}
43 %************************************************************************
45 @liftCoreBindings@ is the top-level interface function.
48 liftCoreBindings :: UniqSupply -- unique supply
49 -> [CoreBinding] -- unlifted bindings
50 -> [CoreBinding] -- lifted bindings
52 liftCoreBindings us binds
53 = initL (lift_top_binds binds) us
55 lift_top_binds [] = returnL []
58 = liftBindAndScope True b (
59 lift_top_binds bs `thenL` \ bs ->
60 returnL (ItsABinds bs)
61 ) `thenL` \ (b, ItsABinds bs) ->
65 -----------------------
66 liftBindAndScope :: Bool -- top level ?
67 -> CoreBinding -- As yet unprocessed
68 -> LiftM BindsOrExpr -- Do the scope of the bindings
69 -> LiftM (CoreBinding, -- Processed
72 liftBindAndScope top_lev bind scopeM
73 = liftBinders top_lev bind (
74 liftCoreBind bind `thenL` \ bind ->
75 scopeM `thenL` \ bindsorexpr ->
76 returnL (bind, bindsorexpr)
79 -----------------------
80 liftCoreArg :: CoreArg -> LiftM (CoreArg, CoreExpr -> CoreExpr)
82 liftCoreArg arg@(TyArg _) = returnL (arg, id)
83 liftCoreArg arg@(LitArg _) = returnL (arg, id)
84 liftCoreArg arg@(VarArg v)
85 = isLiftedId v `thenL` \ lifted ->
87 Nothing -> returnL (arg, id)
89 Just (lifted, unlifted) ->
90 returnL (VarArg unlifted, bindUnlift lifted unlifted)
93 -----------------------
94 liftCoreBind :: CoreBinding -> LiftM CoreBinding
96 liftCoreBind (NonRec b rhs)
97 = liftOneBind (b,rhs) `thenL` \ (b,rhs) ->
98 returnL (NonRec b rhs)
100 liftCoreBind (Rec pairs)
101 = mapL liftOneBind pairs `thenL` \ pairs ->
104 -----------------------
105 liftOneBind (binder,rhs)
106 = liftCoreExpr rhs `thenL` \ rhs ->
107 isLiftedId binder `thenL` \ lifted ->
109 Just (lifted, unlifted) ->
110 returnL (lifted, liftExpr unlifted rhs)
112 returnL (binder, rhs)
114 -----------------------
115 liftCoreExpr :: CoreExpr -> LiftM CoreExpr
117 liftCoreExpr expr@(Var var)
118 = isLiftedId var `thenL` \ lifted ->
120 Nothing -> returnL expr
121 Just (lifted, unlifted) ->
122 returnL (bindUnlift lifted unlifted (Var unlifted))
124 liftCoreExpr expr@(Lit lit) = returnL expr
126 liftCoreExpr (SCC label expr)
127 = liftCoreExpr expr `thenL` \ expr ->
128 returnL (SCC label expr)
130 liftCoreExpr (Coerce coerce ty expr)
131 = liftCoreExpr expr `thenL` \ expr ->
132 returnL (Coerce coerce ty expr) -- ToDo:right?:Coerce
134 liftCoreExpr (Let (NonRec binder rhs) body) -- special case: no lifting
135 = liftCoreExpr rhs `thenL` \ rhs ->
136 liftCoreExpr body `thenL` \ body ->
137 returnL (mkCoLetUnboxedToCase (NonRec binder rhs) body)
139 liftCoreExpr (Let bind body) -- general case
140 = liftBindAndScope False bind (
141 liftCoreExpr body `thenL` \ body ->
142 returnL (ItsAnExpr body)
143 ) `thenL` \ (bind, ItsAnExpr body) ->
144 returnL (Let bind body)
146 liftCoreExpr (Con con args)
147 = mapAndUnzipL liftCoreArg args `thenL` \ (args, unlifts) ->
148 returnL (applyBindUnlifts unlifts (Con con args))
150 liftCoreExpr (Prim op args)
151 = mapAndUnzipL liftCoreArg args `thenL` \ (args, unlifts) ->
152 returnL (applyBindUnlifts unlifts (Prim op args))
154 liftCoreExpr (App fun arg)
157 lift_app (App fun arg) args
158 = lift_app fun (arg:args)
159 lift_app other_fun args
160 = liftCoreExpr other_fun `thenL` \ other_fun ->
161 mapAndUnzipL liftCoreArg args `thenL` \ (args, unlifts) ->
162 returnL (applyBindUnlifts unlifts (mkGenApp other_fun args))
164 liftCoreExpr (Lam binder expr)
165 = liftCoreExpr expr `thenL` \ expr ->
166 returnL (Lam binder expr)
168 liftCoreExpr (Case scrut alts)
169 = liftCoreExpr scrut `thenL` \ scrut ->
170 liftCoreAlts alts `thenL` \ alts ->
171 returnL (Case scrut alts)
174 liftCoreAlts :: CoreCaseAlts -> LiftM CoreCaseAlts
176 liftCoreAlts (AlgAlts alg_alts deflt)
177 = mapL liftAlgAlt alg_alts `thenL` \ alg_alts ->
178 liftDeflt deflt `thenL` \ deflt ->
179 returnL (AlgAlts alg_alts deflt)
181 liftCoreAlts (PrimAlts prim_alts deflt)
182 = mapL liftPrimAlt prim_alts `thenL` \ prim_alts ->
183 liftDeflt deflt `thenL` \ deflt ->
184 returnL (PrimAlts prim_alts deflt)
187 liftAlgAlt (con,args,rhs)
188 = liftCoreExpr rhs `thenL` \ rhs ->
189 returnL (con,args,rhs)
192 liftPrimAlt (lit,rhs)
193 = liftCoreExpr rhs `thenL` \ rhs ->
199 liftDeflt (BindDefault binder rhs)
200 = liftCoreExpr rhs `thenL` \ rhs ->
201 returnL (BindDefault binder rhs)
204 %************************************************************************
206 \subsection{Misc functions}
208 %************************************************************************
212 = IdEnv (Id, Id) -- lifted Ids are mapped to:
213 -- * lifted Id with the same Unique
214 -- (top-level bindings must keep their unique
215 -- * unlifted version with a new Unique
216 -> UniqSupply -- unique supply
220 = ItsABinds [CoreBinding]
223 initL m us = m nullIdEnv us
225 returnL :: a -> LiftM a
226 returnL r idenv us = r
228 thenL :: LiftM a -> (a -> LiftM b) -> LiftM b
230 = case (splitUniqSupply s0) of { (s1, s2) ->
231 case (m idenv s1) of { r ->
235 mapL :: (a -> LiftM b) -> [a] -> LiftM [b]
236 mapL f [] = returnL []
239 mapL f xs `thenL` \ rs ->
242 mapAndUnzipL :: (a -> LiftM (b1, b2)) -> [a] -> LiftM ([b1],[b2])
243 mapAndUnzipL f [] = returnL ([],[])
244 mapAndUnzipL f (x:xs)
245 = f x `thenL` \ (r1, r2) ->
246 mapAndUnzipL f xs `thenL` \ (rs1,rs2) ->
247 returnL ((r1:rs1),(r2:rs2))
249 -- liftBinders is only called for top-level or recusive case
250 liftBinders :: Bool -> CoreBinding -> LiftM thing -> LiftM thing
252 liftBinders False (NonRec _ _) liftM idenv s0
253 = panic "CoreLift:liftBinders" -- should be caught by special case above
255 liftBinders top_lev bind liftM idenv s0
256 = liftM (growIdEnvList idenv lift_map) s2
258 (s1, s2) = splitUniqSupply s0
259 lift_ids = [ id | id <- bindersOf bind, isUnboxedButNotState (idType id) ]
260 lift_uniqs = getUniques (length lift_ids) s1
261 lift_map = zipEqual "liftBinders" lift_ids (zipWithEqual "liftBinders" mkLiftedId lift_ids lift_uniqs)
263 -- ToDo: Give warning for recursive bindings involving unboxed values ???
265 isLiftedId :: Id -> LiftM (Maybe (Id, Id))
266 isLiftedId id idenv us
267 | isLocallyDefined id
268 = lookupIdEnv idenv id
269 | otherwise -- ensure all imported ids are lifted
270 = if isUnboxedButNotState (idType id)
271 then Just (mkLiftedId id (getUnique us))
274 mkLiftedId :: Id -> Unique -> (Id,Id)
276 = ASSERT (isUnboxedButNotState unlifted_ty)
277 (lifted_id, unlifted_id)
279 id_name = _PK_ (getOccString id) -- yuk!
280 lifted_id = mkIdWithNewType id lifted_ty
281 unlifted_id = mkSysLocal id_name u unlifted_ty (getSrcLoc id)
283 unlifted_ty = idType id
284 lifted_ty = mkLiftTy unlifted_ty
286 bindUnlift :: Id -> Id -> CoreExpr -> CoreExpr
287 bindUnlift vlift vunlift expr
288 = ASSERT (isUnboxedButNotState unlift_ty)
289 ASSERT (lift_ty == mkLiftTy unlift_ty)
291 (AlgAlts [(liftDataCon, [vunlift], expr)] NoDefault)
293 lift_ty = idType vlift
294 unlift_ty = idType vunlift
296 liftExpr :: Id -> CoreExpr -> CoreExpr
298 = ASSERT (isUnboxedButNotState unlift_ty)
299 ASSERT (rhs_ty == unlift_ty)
300 Case rhs (PrimAlts []
301 (BindDefault vunlift (mkCon liftDataCon [unlift_ty] [VarArg vunlift])))
303 rhs_ty = coreExprType rhs
304 unlift_ty = idType vunlift
307 applyBindUnlifts :: [CoreExpr -> CoreExpr] -> CoreExpr -> CoreExpr
308 applyBindUnlifts [] expr = expr
309 applyBindUnlifts (f:fs) expr = f (applyBindUnlifts fs expr)
311 isUnboxedButNotState ty =
312 case (splitAlgTyConApp_maybe ty) of
314 Just (tycon, _, _) ->
315 not (isBoxedTyCon tycon) && not (tycon == statePrimTyCon)