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 Bag ( emptyBag, unitBag, unionBags, unionManyBags, bagToList )
21 import CoreUtils ( coreExprType )
22 import CostCentre ( noCostCentre )
23 import Id ( mkSysLocal, idType, isBottomingId,
24 externallyVisibleId, mkIdWithNewUniq,
26 nullIdEnv, addOneToIdEnv, lookupIdEnv, growIdEnvList,
27 IdEnv, GenId{-instance NamedThing-}, Id
29 import Literal ( mkMachInt, Literal(..) )
30 import PrelVals ( unpackCStringId, unpackCString2Id,
31 integerZeroId, integerPlusOneId,
32 integerPlusTwoId, integerMinusOneId
34 import PrimOp ( PrimOp(..) )
35 import SrcLoc ( noSrcLoc )
36 import TyCon ( TyCon{-instance Uniquable-} )
37 import Type ( splitAlgTyConApp, Type )
38 import TysWiredIn ( stringTy )
39 import Unique ( integerTyConKey, ratioTyConKey, Unique{-instance Eq-} )
40 import UniqSupply -- all of it, really
41 import Util ( zipLazy )
43 import Ratio ( numerator, denominator )
45 isLeakFreeType x y = False -- safe option; ToDo
49 *************** OVERVIEW *********************
52 The business of this pass is to convert Core to Stg. On the way:
54 * We discard type lambdas and applications. In so doing we discard
55 "trivial" bindings such as
57 where t1, t2 are types
59 * We don't pin on correct arities any more, because they can be mucked up
60 by the lambda lifter. In particular, the lambda lifter can take a local
61 letrec-bound variable and make it a lambda argument, which shouldn't have
62 an arity. So SetStgVarInfo sets arities now.
64 * We do *not* pin on the correct free/live var info; that's done later.
65 Instead we use bOGUS_LVS and _FVS as a placeholder.
67 [Quite a bit of stuff that used to be here has moved
68 to tidyCorePgm (SimplCore.lhs) SLPJ Nov 96]
71 %************************************************************************
73 \subsection[coreToStg-programs]{Converting a core program and core bindings}
75 %************************************************************************
77 Because we're going to come across ``boring'' bindings like
78 \tr{let x = /\ tyvars -> y in ...}, we want to keep a small
79 environment, so we can just replace all occurrences of \tr{x}
82 March 98: We also use this environment to give all locally bound
83 Names new unique ids, since the code generator assumes that binders
84 are unique across a module. (Simplifier doesn't maintain this
85 invariant any longer.)
88 type StgEnv = IdEnv StgArg
91 No free/live variable information is pinned on in this pass; it's added
93 we use @bOGUS_LVs@ and @bOGUS_FVs@ as placeholders.
96 bOGUS_LVs :: StgLiveVars
97 bOGUS_LVs = panic "bOGUS_LVs" -- emptyUniqSet (used when pprTracing)
100 bOGUS_FVs = panic "bOGUS_FVs" -- [] (ditto)
104 topCoreBindsToStg :: UniqSupply -- name supply
105 -> [CoreBinding] -- input
106 -> [StgBinding] -- output
108 topCoreBindsToStg us core_binds
109 = initUs us (coreBindsToStg nullIdEnv core_binds)
111 coreBindsToStg :: StgEnv -> [CoreBinding] -> UniqSM [StgBinding]
113 coreBindsToStg env [] = returnUs []
114 coreBindsToStg env (b:bs)
115 = coreBindToStg env b `thenUs` \ (new_b, new_env) ->
116 coreBindsToStg new_env bs `thenUs` \ new_bs ->
117 returnUs (new_b ++ new_bs)
120 %************************************************************************
122 \subsection[coreToStg-binds]{Converting bindings}
124 %************************************************************************
127 coreBindToStg :: StgEnv
129 -> UniqSM ([StgBinding], -- Empty or singleton
132 coreBindToStg env (NonRec binder rhs)
133 = coreRhsToStg env rhs `thenUs` \ stg_rhs ->
135 -- Binds to return if RHS is trivial
136 triv_binds | externallyVisibleId binder = [StgNonRec binder stg_rhs] -- Retain it
137 | otherwise = [] -- Discard it
140 StgRhsClosure cc bi fvs upd [] (StgApp atom [] lvs) ->
141 -- Trivial RHS, so augment envt, and ditch the binding
142 returnUs (triv_binds, new_env)
144 new_env = addOneToIdEnv env binder atom
146 StgRhsCon cc con_id [] ->
147 -- Trivial RHS, so augment envt, and ditch the binding
148 returnUs (triv_binds, new_env)
150 new_env = addOneToIdEnv env binder (StgConArg con_id)
152 other -> -- Non-trivial RHS
153 mkUniqueBinder env binder `thenUs` \ (new_env, new_binder) ->
154 returnUs ([StgNonRec new_binder stg_rhs], new_env)
156 mkUniqueBinder env binder
157 | externallyVisibleId binder = returnUs (env, binder)
159 -- local binder, give it a new unique Id.
160 newUniqueLocalId binder `thenUs` \ binder' ->
162 new_env = addOneToIdEnv env binder (StgVarArg binder')
164 returnUs (new_env, binder')
167 coreBindToStg env (Rec pairs)
168 = -- NB: *** WE DO NOT CHECK FOR TRIV_BINDS in REC BIND ****
171 (binders, rhss) = unzip pairs
173 newLocalIds env True{-maybe externally visible-} binders `thenUs` \ (binders', env') ->
174 mapUs (coreRhsToStg env') rhss `thenUs` \ stg_rhss ->
175 returnUs ([StgRec (binders' `zip` stg_rhss)], env')
179 %************************************************************************
181 \subsection[coreToStg-rhss]{Converting right hand sides}
183 %************************************************************************
186 coreRhsToStg :: StgEnv -> CoreExpr -> UniqSM StgRhs
188 coreRhsToStg env core_rhs
189 = coreExprToStg env core_rhs `thenUs` \ stg_expr ->
191 let stg_rhs = case stg_expr of
192 StgLet (StgNonRec var1 rhs) (StgApp (StgVarArg var2) [] _)
193 | var1 == var2 -> rhs
194 -- This curious stuff is to unravel what a lambda turns into
195 -- We have to do it this way, rather than spot a lambda in the
196 -- incoming rhs. Why? Because trivial bindings might conceal
197 -- what the rhs is actually like.
199 StgCon con args _ -> StgRhsCon noCostCentre con args
201 other -> StgRhsClosure noCostCentre -- No cost centre (ToDo?)
204 Updatable -- Be pessimistic
212 %************************************************************************
214 \subsection[coreToStg-atoms{Converting atoms}
216 %************************************************************************
219 coreArgsToStg :: StgEnv -> [CoreArg] -> ([Type], [StgArg])
221 coreArgsToStg env [] = ([], [])
222 coreArgsToStg env (a:as)
224 TyArg t -> (t:trest, vrest)
225 VarArg v -> (trest, stgLookup env v : vrest)
226 LitArg l -> (trest, StgLitArg l : vrest)
228 (trest,vrest) = coreArgsToStg env as
232 %************************************************************************
234 \subsection[coreToStg-exprs]{Converting core expressions}
236 %************************************************************************
239 coreExprToStg :: StgEnv -> CoreExpr -> UniqSM StgExpr
241 coreExprToStg env (Lit lit)
242 = returnUs (StgApp (StgLitArg lit) [] bOGUS_LVs)
244 coreExprToStg env (Var var)
245 = returnUs (mk_app (stgLookup env var) [])
247 coreExprToStg env (Con con args)
249 (types, stg_atoms) = coreArgsToStg env args
251 returnUs (StgCon con stg_atoms bOGUS_LVs)
253 coreExprToStg env (Prim op args)
255 (types, stg_atoms) = coreArgsToStg env args
257 returnUs (StgPrim op stg_atoms bOGUS_LVs)
260 %************************************************************************
262 \subsubsection[coreToStg-lambdas]{Lambda abstractions}
264 %************************************************************************
267 coreExprToStg env expr@(Lam _ _)
269 (_, binders, body) = collectBinders expr
271 newLocalIds env False{-all local-} binders `thenUs` \ (binders', env') ->
272 coreExprToStg env' body `thenUs` \ stg_body ->
274 if null binders then -- it was all type/usage binders; tossed
277 newStgVar (coreExprType expr) `thenUs` \ var ->
279 (StgLet (StgNonRec var
280 (StgRhsClosure noCostCentre
283 ReEntrant -- binders is non-empty
286 (StgApp (StgVarArg var) [] bOGUS_LVs))
289 %************************************************************************
291 \subsubsection[coreToStg-applications]{Applications}
293 %************************************************************************
296 coreExprToStg env expr@(App _ _)
298 (fun,args) = collect_args expr []
299 (_, stg_args) = coreArgsToStg env args
301 -- Now deal with the function
303 (Var fun_id, _) -> -- A function Id, so do an StgApp; it's ok if
304 -- there are no arguments.
305 returnUs (mk_app (stgLookup env fun_id) stg_args)
307 (non_var_fun, []) -> -- No value args, so recurse into the function
308 coreExprToStg env non_var_fun
310 other -> -- A non-variable applied to things; better let-bind it.
311 newStgVar (coreExprType fun) `thenUs` \ fun_id ->
312 coreExprToStg env fun `thenUs` \ (stg_fun) ->
314 fun_rhs = StgRhsClosure noCostCentre -- No cost centre (ToDo?)
317 SingleEntry -- Only entered once
321 returnUs (StgLet (StgNonRec fun_id fun_rhs)
322 (StgApp (StgVarArg fun_id) stg_args bOGUS_LVs))
324 -- Collect arguments, discarding type/usage applications
325 collect_args (App e (TyArg _)) args = collect_args e args
326 collect_args (App fun arg) args = collect_args fun (arg:args)
327 collect_args (Coerce _ _ expr) args = collect_args expr args
328 collect_args fun args = (fun, args)
331 %************************************************************************
333 \subsubsection[coreToStg-cases]{Case expressions}
335 %************************************************************************
338 coreExprToStg env (Case discrim alts)
339 = coreExprToStg env discrim `thenUs` \ stg_discrim ->
340 alts_to_stg discrim alts `thenUs` \ stg_alts ->
341 getUnique `thenUs` \ uniq ->
350 discrim_ty = coreExprType discrim
351 (_, discrim_ty_args, _) = splitAlgTyConApp discrim_ty
353 alts_to_stg discrim (AlgAlts alts deflt)
354 = default_to_stg discrim deflt `thenUs` \ stg_deflt ->
355 mapUs boxed_alt_to_stg alts `thenUs` \ stg_alts ->
356 returnUs (StgAlgAlts discrim_ty stg_alts stg_deflt)
358 boxed_alt_to_stg (con, bs, rhs)
359 = coreExprToStg env rhs `thenUs` \ stg_rhs ->
360 returnUs (con, bs, [ True | b <- bs ]{-bogus use mask-}, stg_rhs)
362 alts_to_stg discrim (PrimAlts alts deflt)
363 = default_to_stg discrim deflt `thenUs` \ stg_deflt ->
364 mapUs unboxed_alt_to_stg alts `thenUs` \ stg_alts ->
365 returnUs (StgPrimAlts discrim_ty stg_alts stg_deflt)
367 unboxed_alt_to_stg (lit, rhs)
368 = coreExprToStg env rhs `thenUs` \ stg_rhs ->
369 returnUs (lit, stg_rhs)
371 default_to_stg discrim NoDefault
372 = returnUs StgNoDefault
374 default_to_stg discrim (BindDefault binder rhs)
375 = coreExprToStg env rhs `thenUs` \ stg_rhs ->
376 returnUs (StgBindDefault binder True{-used? no it is lying-} stg_rhs)
379 %************************************************************************
381 \subsubsection[coreToStg-let(rec)]{Let and letrec expressions}
383 %************************************************************************
386 coreExprToStg env (Let bind body)
387 = coreBindToStg env bind `thenUs` \ (stg_binds, new_env) ->
388 coreExprToStg new_env body `thenUs` \ stg_body ->
389 returnUs (mkStgLets stg_binds stg_body)
393 %************************************************************************
395 \subsubsection[coreToStg-scc]{SCC expressions}
397 %************************************************************************
399 Covert core @scc@ expression directly to STG @scc@ expression.
401 coreExprToStg env (SCC cc expr)
402 = coreExprToStg env expr `thenUs` \ stg_expr ->
403 returnUs (StgSCC (coreExprType expr) cc stg_expr)
407 coreExprToStg env (Coerce c ty expr) = coreExprToStg env expr
411 %************************************************************************
413 \subsection[coreToStg-misc]{Miscellaneous helping functions}
415 %************************************************************************
417 There's not anything interesting we can ASSERT about \tr{var} if it
418 isn't in the StgEnv. (WDP 94/06)
421 stgLookup :: StgEnv -> Id -> StgArg
422 stgLookup env var = case (lookupIdEnv env var) of
423 Nothing -> StgVarArg var
429 newStgVar :: Type -> UniqSM Id
431 = getUnique `thenUs` \ uniq ->
432 returnUs (mkSysLocal SLIT("stg") uniq ty noSrcLoc)
436 newUniqueLocalId :: Id -> UniqSM Id
438 getUnique `thenUs` \ uniq ->
439 returnUs (mkIdWithNewUniq i uniq)
441 newLocalIds :: StgEnv -> Bool -> [Id] -> UniqSM ([Id], StgEnv)
442 newLocalIds env maybe_visible [] = returnUs ([], env)
443 newLocalIds env maybe_visible (i:is)
444 | maybe_visible && externallyVisibleId i =
445 newLocalIds env maybe_visible is `thenUs` \ (is', env') ->
446 returnUs (i:is', env')
448 newUniqueLocalId i `thenUs` \ i' ->
450 new_env = addOneToIdEnv env i (StgVarArg i')
452 newLocalIds new_env maybe_visible is `thenUs` \ (is', env') ->
453 returnUs (i':is', env')
458 mkStgLets :: [StgBinding]
459 -> StgExpr -- body of let
462 mkStgLets binds body = foldr StgLet body binds
464 -- mk_app spots an StgCon in a function position,
465 -- and turns it into an StgCon. See notes with
466 -- getArgAmode in CgBindery.
467 mk_app (StgConArg con) args = StgCon con args bOGUS_LVs
468 mk_app other_fun args = StgApp other_fun args bOGUS_LVs