2 % (c) The GRASP/AQUA Project, Glasgow University, 1992-1996
4 %************************************************************************
6 \section[CoreToStg]{Converting core syntax to STG syntax}
8 %************************************************************************
10 Convert a @CoreSyntax@ program to a @StgSyntax@ program.
13 module CoreToStg ( topCoreBindsToStg ) where
15 #include "HsVersions.h"
17 import CoreSyn -- input
18 import StgSyn -- output
20 import CoreUtils ( coreExprType )
21 import CostCentre ( noCostCentre )
22 import MkId ( mkSysLocal )
23 import Id ( externallyVisibleId, mkIdWithNewUniq,
24 nullIdEnv, addOneToIdEnv, lookupIdEnv,
27 import SrcLoc ( noSrcLoc )
28 import Type ( splitAlgTyConApp, Type )
29 import UniqSupply ( UniqSupply, UniqSM,
30 returnUs, thenUs, initUs,
33 import Outputable ( panic )
35 isLeakFreeType x y = False -- safe option; ToDo
39 *************** OVERVIEW *********************
42 The business of this pass is to convert Core to Stg. On the way:
44 * We discard type lambdas and applications. In so doing we discard
45 "trivial" bindings such as
47 where t1, t2 are types
49 * We don't pin on correct arities any more, because they can be mucked up
50 by the lambda lifter. In particular, the lambda lifter can take a local
51 letrec-bound variable and make it a lambda argument, which shouldn't have
52 an arity. So SetStgVarInfo sets arities now.
54 * We do *not* pin on the correct free/live var info; that's done later.
55 Instead we use bOGUS_LVS and _FVS as a placeholder.
57 [Quite a bit of stuff that used to be here has moved
58 to tidyCorePgm (SimplCore.lhs) SLPJ Nov 96]
61 %************************************************************************
63 \subsection[coreToStg-programs]{Converting a core program and core bindings}
65 %************************************************************************
67 Because we're going to come across ``boring'' bindings like
68 \tr{let x = /\ tyvars -> y in ...}, we want to keep a small
69 environment, so we can just replace all occurrences of \tr{x}
72 March 98: We also use this environment to give all locally bound
73 Names new unique ids, since the code generator assumes that binders
74 are unique across a module. (Simplifier doesn't maintain this
75 invariant any longer.)
78 type StgEnv = IdEnv StgArg
81 No free/live variable information is pinned on in this pass; it's added
83 we use @bOGUS_LVs@ and @bOGUS_FVs@ as placeholders.
86 bOGUS_LVs :: StgLiveVars
87 bOGUS_LVs = panic "bOGUS_LVs" -- emptyUniqSet (used when pprTracing)
90 bOGUS_FVs = panic "bOGUS_FVs" -- [] (ditto)
94 topCoreBindsToStg :: UniqSupply -- name supply
95 -> [CoreBinding] -- input
96 -> [StgBinding] -- output
98 topCoreBindsToStg us core_binds
99 = initUs us (coreBindsToStg nullIdEnv core_binds)
101 coreBindsToStg :: StgEnv -> [CoreBinding] -> UniqSM [StgBinding]
103 coreBindsToStg env [] = returnUs []
104 coreBindsToStg env (b:bs)
105 = coreBindToStg env b `thenUs` \ (new_b, new_env) ->
106 coreBindsToStg new_env bs `thenUs` \ new_bs ->
107 returnUs (new_b ++ new_bs)
110 %************************************************************************
112 \subsection[coreToStg-binds]{Converting bindings}
114 %************************************************************************
117 coreBindToStg :: StgEnv
119 -> UniqSM ([StgBinding], -- Empty or singleton
122 coreBindToStg env (NonRec binder rhs)
123 = coreRhsToStg env rhs `thenUs` \ stg_rhs ->
125 -- Binds to return if RHS is trivial
126 triv_binds | externallyVisibleId binder = [StgNonRec binder stg_rhs] -- Retain it
127 | otherwise = [] -- Discard it
130 StgRhsClosure cc bi fvs upd [] (StgApp atom [] lvs) ->
131 -- Trivial RHS, so augment envt, and ditch the binding
132 returnUs (triv_binds, new_env)
134 new_env = addOneToIdEnv env binder atom
136 StgRhsCon cc con_id [] ->
137 -- Trivial RHS, so augment envt, and ditch the binding
138 returnUs (triv_binds, new_env)
140 new_env = addOneToIdEnv env binder (StgConArg con_id)
142 other -> -- Non-trivial RHS
143 mkUniqueBinder env binder `thenUs` \ (new_env, new_binder) ->
144 returnUs ([StgNonRec new_binder stg_rhs], new_env)
146 mkUniqueBinder env binder
147 | externallyVisibleId binder = returnUs (env, binder)
149 -- local binder, give it a new unique Id.
150 newUniqueLocalId binder `thenUs` \ binder' ->
152 new_env = addOneToIdEnv env binder (StgVarArg binder')
154 returnUs (new_env, binder')
157 coreBindToStg env (Rec pairs)
158 = -- NB: *** WE DO NOT CHECK FOR TRIV_BINDS in REC BIND ****
161 (binders, rhss) = unzip pairs
163 newLocalIds env True{-maybe externally visible-} binders `thenUs` \ (binders', env') ->
164 mapUs (coreRhsToStg env') rhss `thenUs` \ stg_rhss ->
165 returnUs ([StgRec (binders' `zip` stg_rhss)], env')
169 %************************************************************************
171 \subsection[coreToStg-rhss]{Converting right hand sides}
173 %************************************************************************
176 coreRhsToStg :: StgEnv -> CoreExpr -> UniqSM StgRhs
178 coreRhsToStg env core_rhs
179 = coreExprToStg env core_rhs `thenUs` \ stg_expr ->
181 let stg_rhs = case stg_expr of
182 StgLet (StgNonRec var1 rhs) (StgApp (StgVarArg var2) [] _)
183 | var1 == var2 -> rhs
184 -- This curious stuff is to unravel what a lambda turns into
185 -- We have to do it this way, rather than spot a lambda in the
186 -- incoming rhs. Why? Because trivial bindings might conceal
187 -- what the rhs is actually like.
189 StgCon con args _ -> StgRhsCon noCostCentre con args
191 other -> StgRhsClosure noCostCentre -- No cost centre (ToDo?)
194 Updatable -- Be pessimistic
202 %************************************************************************
204 \subsection[coreToStg-atoms{Converting atoms}
206 %************************************************************************
209 coreArgsToStg :: StgEnv -> [CoreArg] -> ([Type], [StgArg])
211 coreArgsToStg env [] = ([], [])
212 coreArgsToStg env (a:as)
214 TyArg t -> (t:trest, vrest)
215 VarArg v -> (trest, stgLookup env v : vrest)
216 LitArg l -> (trest, StgLitArg l : vrest)
218 (trest,vrest) = coreArgsToStg env as
222 %************************************************************************
224 \subsection[coreToStg-exprs]{Converting core expressions}
226 %************************************************************************
229 coreExprToStg :: StgEnv -> CoreExpr -> UniqSM StgExpr
231 coreExprToStg env (Lit lit)
232 = returnUs (StgApp (StgLitArg lit) [] bOGUS_LVs)
234 coreExprToStg env (Var var)
235 = returnUs (mk_app (stgLookup env var) [])
237 coreExprToStg env (Con con args)
239 (types, stg_atoms) = coreArgsToStg env args
241 returnUs (StgCon con stg_atoms bOGUS_LVs)
243 coreExprToStg env (Prim op args)
245 (types, stg_atoms) = coreArgsToStg env args
247 returnUs (StgPrim op stg_atoms bOGUS_LVs)
250 %************************************************************************
252 \subsubsection[coreToStg-lambdas]{Lambda abstractions}
254 %************************************************************************
257 coreExprToStg env expr@(Lam _ _)
259 (_, binders, body) = collectBinders expr
261 newLocalIds env False{-all local-} binders `thenUs` \ (binders', env') ->
262 coreExprToStg env' body `thenUs` \ stg_body ->
264 if null binders then -- it was all type/usage binders; tossed
267 newStgVar (coreExprType expr) `thenUs` \ var ->
269 (StgLet (StgNonRec var
270 (StgRhsClosure noCostCentre
273 ReEntrant -- binders is non-empty
276 (StgApp (StgVarArg var) [] bOGUS_LVs))
279 %************************************************************************
281 \subsubsection[coreToStg-applications]{Applications}
283 %************************************************************************
286 coreExprToStg env expr@(App _ _)
288 (fun,args) = collect_args expr []
289 (_, stg_args) = coreArgsToStg env args
291 -- Now deal with the function
293 (Var fun_id, _) -> -- A function Id, so do an StgApp; it's ok if
294 -- there are no arguments.
295 returnUs (mk_app (stgLookup env fun_id) stg_args)
297 (non_var_fun, []) -> -- No value args, so recurse into the function
298 coreExprToStg env non_var_fun
300 other -> -- A non-variable applied to things; better let-bind it.
301 newStgVar (coreExprType fun) `thenUs` \ fun_id ->
302 coreExprToStg env fun `thenUs` \ (stg_fun) ->
304 fun_rhs = StgRhsClosure noCostCentre -- No cost centre (ToDo?)
307 SingleEntry -- Only entered once
311 returnUs (StgLet (StgNonRec fun_id fun_rhs)
312 (StgApp (StgVarArg fun_id) stg_args bOGUS_LVs))
314 -- Collect arguments, discarding type/usage applications
315 collect_args (App e (TyArg _)) args = collect_args e args
316 collect_args (App fun arg) args = collect_args fun (arg:args)
317 collect_args (Note (Coerce _ _) expr) args = collect_args expr args
318 collect_args (Note InlineCall expr) args = collect_args expr args
319 collect_args fun args = (fun, args)
322 %************************************************************************
324 \subsubsection[coreToStg-cases]{Case expressions}
326 %************************************************************************
329 ******* TO DO TO DO: fix what follows
333 case (op x1 ... xn) of
336 where the type of the case scrutinee is a multi-constuctor algebraic type.
337 Then we simply compile code for
345 case (op x1 ... xn) of
349 where the type of the case scrutinee is a multi-constuctor algebraic type.
350 we just bomb out at the moment. It never happens in practice.
352 **** END OF TO DO TO DO
355 coreExprToStg env (Case scrut@(Prim op args) (AlgAlts alts (BindDefault binder rhs)))
356 = if not (null alts) then
357 panic "cgCase: case on PrimOp with default *and* alts\n"
358 -- For now, die if alts are non-empty
360 coreExprToStg env (Let (NonRec binder scrut) rhs)
362 coreExprToStg env (Case discrim alts)
363 = coreExprToStg env discrim `thenUs` \ stg_discrim ->
364 alts_to_stg discrim alts `thenUs` \ stg_alts ->
365 getUnique `thenUs` \ uniq ->
374 discrim_ty = coreExprType discrim
375 (_, discrim_ty_args, _) = splitAlgTyConApp discrim_ty
377 alts_to_stg discrim (AlgAlts alts deflt)
378 = default_to_stg discrim deflt `thenUs` \ stg_deflt ->
379 mapUs boxed_alt_to_stg alts `thenUs` \ stg_alts ->
380 returnUs (StgAlgAlts discrim_ty stg_alts stg_deflt)
382 boxed_alt_to_stg (con, bs, rhs)
383 = coreExprToStg env rhs `thenUs` \ stg_rhs ->
384 returnUs (con, bs, [ True | b <- bs ]{-bogus use mask-}, stg_rhs)
386 alts_to_stg discrim (PrimAlts alts deflt)
387 = default_to_stg discrim deflt `thenUs` \ stg_deflt ->
388 mapUs unboxed_alt_to_stg alts `thenUs` \ stg_alts ->
389 returnUs (StgPrimAlts discrim_ty stg_alts stg_deflt)
391 unboxed_alt_to_stg (lit, rhs)
392 = coreExprToStg env rhs `thenUs` \ stg_rhs ->
393 returnUs (lit, stg_rhs)
395 default_to_stg discrim NoDefault
396 = returnUs StgNoDefault
398 default_to_stg discrim (BindDefault binder rhs)
399 = coreExprToStg env rhs `thenUs` \ stg_rhs ->
400 returnUs (StgBindDefault binder True{-used? no it is lying-} stg_rhs)
403 %************************************************************************
405 \subsubsection[coreToStg-let(rec)]{Let and letrec expressions}
407 %************************************************************************
410 coreExprToStg env (Let bind body)
411 = coreBindToStg env bind `thenUs` \ (stg_binds, new_env) ->
412 coreExprToStg new_env body `thenUs` \ stg_body ->
413 returnUs (mkStgLets stg_binds stg_body)
417 %************************************************************************
419 \subsubsection[coreToStg-scc]{SCC expressions}
421 %************************************************************************
423 Covert core @scc@ expression directly to STG @scc@ expression.
425 coreExprToStg env (Note (SCC cc) expr)
426 = coreExprToStg env expr `thenUs` \ stg_expr ->
427 returnUs (StgSCC (coreExprType expr) cc stg_expr)
431 coreExprToStg env (Note other_note expr) = coreExprToStg env expr
435 %************************************************************************
437 \subsection[coreToStg-misc]{Miscellaneous helping functions}
439 %************************************************************************
441 There's not anything interesting we can ASSERT about \tr{var} if it
442 isn't in the StgEnv. (WDP 94/06)
445 stgLookup :: StgEnv -> Id -> StgArg
446 stgLookup env var = case (lookupIdEnv env var) of
447 Nothing -> StgVarArg var
453 newStgVar :: Type -> UniqSM Id
455 = getUnique `thenUs` \ uniq ->
456 returnUs (mkSysLocal SLIT("stg") uniq ty noSrcLoc)
460 newUniqueLocalId :: Id -> UniqSM Id
462 getUnique `thenUs` \ uniq ->
463 returnUs (mkIdWithNewUniq i uniq)
465 newLocalIds :: StgEnv -> Bool -> [Id] -> UniqSM ([Id], StgEnv)
466 newLocalIds env maybe_visible [] = returnUs ([], env)
467 newLocalIds env maybe_visible (i:is)
468 | maybe_visible && externallyVisibleId i =
469 newLocalIds env maybe_visible is `thenUs` \ (is', env') ->
470 returnUs (i:is', env')
472 newUniqueLocalId i `thenUs` \ i' ->
474 new_env = addOneToIdEnv env i (StgVarArg i')
476 newLocalIds new_env maybe_visible is `thenUs` \ (is', env') ->
477 returnUs (i':is', env')
482 mkStgLets :: [StgBinding]
483 -> StgExpr -- body of let
486 mkStgLets binds body = foldr StgLet body binds
488 -- mk_app spots an StgCon in a function position,
489 -- and turns it into an StgCon. See notes with
490 -- getArgAmode in CgBindery.
491 mk_app (StgConArg con) args = StgCon con args bOGUS_LVs
492 mk_app other_fun args = StgApp other_fun args bOGUS_LVs