2 % (c) The GRASP/AQUA Project, Glasgow University, 1993-1996
4 \section[CoreLift]{Lifts unboxed bindings and any references to them}
7 #include "HsVersions.h"
23 import CoreUtils ( coreExprType )
24 import Id ( idType, mkSysLocal,
25 nullIdEnv, growIdEnvList, lookupIdEnv, IdEnv(..),
28 import PrelInfo ( liftDataCon, mkLiftTy, statePrimTyCon )
29 import TyCon ( isBoxedTyCon, TyCon{-instance-} )
30 import Type ( maybeAppDataTyCon, eqTy )
31 import UniqSupply ( getUnique, getUniques, splitUniqSupply, UniqSupply )
32 import Util ( zipEqual, zipWithEqual, assertPanic, panic )
36 updateIdType = panic "CoreLift.updateIdType"
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@(UsageArg _) = returnL (arg, id)
84 liftCoreArg arg@(LitArg _) = returnL (arg, id)
85 liftCoreArg arg@(VarArg v)
86 = isLiftedId v `thenL` \ lifted ->
88 Nothing -> returnL (arg, id)
90 Just (lifted, unlifted) ->
91 returnL (VarArg unlifted, bindUnlift lifted unlifted)
94 -----------------------
95 liftCoreBind :: CoreBinding -> LiftM CoreBinding
97 liftCoreBind (NonRec b rhs)
98 = liftOneBind (b,rhs) `thenL` \ (b,rhs) ->
99 returnL (NonRec b rhs)
101 liftCoreBind (Rec pairs)
102 = mapL liftOneBind pairs `thenL` \ pairs ->
105 -----------------------
106 liftOneBind (binder,rhs)
107 = liftCoreExpr rhs `thenL` \ rhs ->
108 isLiftedId binder `thenL` \ lifted ->
110 Just (lifted, unlifted) ->
111 returnL (lifted, liftExpr unlifted rhs)
113 returnL (binder, rhs)
115 -----------------------
116 liftCoreExpr :: CoreExpr -> LiftM CoreExpr
118 liftCoreExpr expr@(Var var)
119 = isLiftedId var `thenL` \ lifted ->
121 Nothing -> returnL expr
122 Just (lifted, unlifted) ->
123 returnL (bindUnlift lifted unlifted (Var unlifted))
125 liftCoreExpr expr@(Lit lit) = returnL expr
127 liftCoreExpr (SCC label expr)
128 = liftCoreExpr expr `thenL` \ expr ->
129 returnL (SCC label expr)
131 liftCoreExpr (Let (NonRec binder rhs) body) -- special case: no lifting
132 = liftCoreExpr rhs `thenL` \ rhs ->
133 liftCoreExpr body `thenL` \ body ->
134 returnL (mkCoLetUnboxedToCase (NonRec binder rhs) body)
136 liftCoreExpr (Let bind body) -- general case
137 = liftBindAndScope False bind (
138 liftCoreExpr body `thenL` \ body ->
139 returnL (ItsAnExpr body)
140 ) `thenL` \ (bind, ItsAnExpr body) ->
141 returnL (Let bind body)
143 liftCoreExpr (Con con args)
144 = mapAndUnzipL liftCoreArg args `thenL` \ (args, unlifts) ->
145 returnL (applyBindUnlifts unlifts (Con con args))
147 liftCoreExpr (Prim op args)
148 = mapAndUnzipL liftCoreArg args `thenL` \ (args, unlifts) ->
149 returnL (applyBindUnlifts unlifts (Prim op args))
151 liftCoreExpr (App fun arg)
154 lift_app (App fun arg) args
155 = lift_app fun (arg:args)
156 lift_app other_fun args
157 = liftCoreExpr other_fun `thenL` \ other_fun ->
158 mapAndUnzipL liftCoreArg args `thenL` \ (args, unlifts) ->
159 returnL (applyBindUnlifts unlifts (mkGenApp other_fun args))
161 liftCoreExpr (Lam binder expr)
162 = liftCoreExpr expr `thenL` \ expr ->
163 returnL (Lam binder expr)
165 liftCoreExpr (Case scrut alts)
166 = liftCoreExpr scrut `thenL` \ scrut ->
167 liftCoreAlts alts `thenL` \ alts ->
168 returnL (Case scrut alts)
171 liftCoreAlts :: CoreCaseAlts -> LiftM CoreCaseAlts
173 liftCoreAlts (AlgAlts alg_alts deflt)
174 = mapL liftAlgAlt alg_alts `thenL` \ alg_alts ->
175 liftDeflt deflt `thenL` \ deflt ->
176 returnL (AlgAlts alg_alts deflt)
178 liftCoreAlts (PrimAlts prim_alts deflt)
179 = mapL liftPrimAlt prim_alts `thenL` \ prim_alts ->
180 liftDeflt deflt `thenL` \ deflt ->
181 returnL (PrimAlts prim_alts deflt)
184 liftAlgAlt (con,args,rhs)
185 = liftCoreExpr rhs `thenL` \ rhs ->
186 returnL (con,args,rhs)
189 liftPrimAlt (lit,rhs)
190 = liftCoreExpr rhs `thenL` \ rhs ->
196 liftDeflt (BindDefault binder rhs)
197 = liftCoreExpr rhs `thenL` \ rhs ->
198 returnL (BindDefault binder rhs)
201 %************************************************************************
203 \subsection{Misc functions}
205 %************************************************************************
209 = IdEnv (Id, Id) -- lifted Ids are mapped to:
210 -- * lifted Id with the same Unique
211 -- (top-level bindings must keep their
212 -- unique (see TopLevId in Id.lhs))
213 -- * unlifted version with a new Unique
214 -> UniqSupply -- unique supply
218 = ItsABinds [CoreBinding]
221 initL m us = m nullIdEnv us
223 returnL :: a -> LiftM a
224 returnL r idenv us = r
226 thenL :: LiftM a -> (a -> LiftM b) -> LiftM b
228 = case (splitUniqSupply s0) of { (s1, s2) ->
229 case (m idenv s1) of { r ->
233 mapL :: (a -> LiftM b) -> [a] -> LiftM [b]
234 mapL f [] = returnL []
237 mapL f xs `thenL` \ rs ->
240 mapAndUnzipL :: (a -> LiftM (b1, b2)) -> [a] -> LiftM ([b1],[b2])
241 mapAndUnzipL f [] = returnL ([],[])
242 mapAndUnzipL f (x:xs)
243 = f x `thenL` \ (r1, r2) ->
244 mapAndUnzipL f xs `thenL` \ (rs1,rs2) ->
245 returnL ((r1:rs1),(r2:rs2))
247 -- liftBinders is only called for top-level or recusive case
248 liftBinders :: Bool -> CoreBinding -> LiftM thing -> LiftM thing
250 liftBinders False (NonRec _ _) liftM idenv s0
251 = panic "CoreLift:liftBinders" -- should be caught by special case above
253 liftBinders top_lev bind liftM idenv s0
254 = liftM (growIdEnvList idenv lift_map) s2
256 (s1, s2) = splitUniqSupply s0
257 lift_ids = [ id | id <- bindersOf bind, isUnboxedButNotState (idType id) ]
258 lift_uniqs = getUniques (length lift_ids) s1
259 lift_map = zipEqual lift_ids (zipWithEqual mkLiftedId lift_ids lift_uniqs)
261 -- ToDo: Give warning for recursive bindings involving unboxed values ???
263 isLiftedId :: Id -> LiftM (Maybe (Id, Id))
264 isLiftedId id idenv us
265 | isLocallyDefined id
266 = lookupIdEnv idenv id
267 | otherwise -- ensure all imported ids are lifted
268 = if isUnboxedButNotState (idType id)
269 then Just (mkLiftedId id (getUnique us))
272 mkLiftedId :: Id -> Unique -> (Id,Id)
274 = ASSERT (isUnboxedButNotState unlifted_ty)
275 (lifted_id, unlifted_id)
277 id_name = getOccurrenceName id
278 lifted_id = updateIdType id lifted_ty
279 unlifted_id = mkSysLocal id_name u unlifted_ty (getSrcLoc id)
281 unlifted_ty = idType id
282 lifted_ty = mkLiftTy unlifted_ty
284 bindUnlift :: Id -> Id -> CoreExpr -> CoreExpr
285 bindUnlift vlift vunlift expr
286 = ASSERT (isUnboxedButNotState unlift_ty)
287 ASSERT (lift_ty `eqTy` mkLiftTy unlift_ty)
289 (AlgAlts [(liftDataCon, [vunlift], expr)] NoDefault)
291 lift_ty = idType vlift
292 unlift_ty = idType vunlift
294 liftExpr :: Id -> CoreExpr -> CoreExpr
296 = ASSERT (isUnboxedButNotState unlift_ty)
297 ASSERT (rhs_ty `eqTy` unlift_ty)
298 Case rhs (PrimAlts []
299 (BindDefault vunlift (mkCon liftDataCon [] [unlift_ty] [VarArg vunlift])))
301 rhs_ty = coreExprType rhs
302 unlift_ty = idType vunlift
305 applyBindUnlifts :: [CoreExpr -> CoreExpr] -> CoreExpr -> CoreExpr
306 applyBindUnlifts [] expr = expr
307 applyBindUnlifts (f:fs) expr = f (applyBindUnlifts fs expr)
309 isUnboxedButNotState ty
310 = case (maybeAppDataTyCon ty) of
312 Just (tycon, _, _) ->
313 not (isBoxedTyCon tycon) && not (tycon == statePrimTyCon)