1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
|
%
% (c) The GRASP/AQUA Project, Glasgow University, 1992-1996
%
%************************************************************************
%* *
\section[CoreToStg]{Converting core syntax to STG syntax}
%* *
%************************************************************************
Convert a @CoreSyntax@ program to a @StgSyntax@ program.
\begin{code}
#include "HsVersions.h"
module CoreToStg ( topCoreBindsToStg ) where
IMP_Ubiq(){-uitous-}
IMPORT_1_3(Ratio(numerator,denominator))
import CoreSyn -- input
import StgSyn -- output
import Bag ( emptyBag, unitBag, unionBags, unionManyBags, bagToList )
import CoreUtils ( coreExprType )
import CostCentre ( noCostCentre )
import Id ( mkSysLocal, idType, isBottomingId,
externallyVisibleId,
nullIdEnv, addOneToIdEnv, lookupIdEnv,
SYN_IE(IdEnv), GenId{-instance NamedThing-}
)
import Literal ( mkMachInt, Literal(..) )
import PrelVals ( unpackCStringId, unpackCString2Id,
integerZeroId, integerPlusOneId,
integerPlusTwoId, integerMinusOneId
)
import PrimOp ( PrimOp(..) )
import SpecUtils ( mkSpecialisedCon )
import SrcLoc ( mkUnknownSrcLoc )
import TyCon ( TyCon{-instance Uniquable-} )
import Type ( maybeAppDataTyCon, getAppDataTyConExpandingDicts )
import TysWiredIn ( stringTy )
import Unique ( integerTyConKey, ratioTyConKey, Unique{-instance Eq-} )
import UniqSupply -- all of it, really
import Util ( panic, assertPanic, pprTrace{-ToDo:rm-} )
import Pretty--ToDo:rm
import PprStyle--ToDo:rm
import PprType --ToDo:rm
import Outputable--ToDo:rm
import PprEnv--ToDo:rm
isLeakFreeType x y = False -- safe option; ToDo
\end{code}
*************** OVERVIEW *********************
The business of this pass is to convert Core to Stg. On the way:
* We discard type lambdas and applications. In so doing we discard
"trivial" bindings such as
x = y t1 t2
where t1, t2 are types
* We make the representation of NoRep literals explicit, and
float their bindings to the top level
* We do *not* pin on the correct free/live var info; that's done later.
Instead we use bOGUS_LVS and _FVS as a placeholder.
* We convert case x of {...; x' -> ...x'...}
to
case x of {...; _ -> ...x... }
See notes in SimplCase.lhs, near simplDefault for the reasoning here.
%************************************************************************
%* *
\subsection[coreToStg-programs]{Converting a core program and core bindings}
%* *
%************************************************************************
Because we're going to come across ``boring'' bindings like
\tr{let x = /\ tyvars -> y in ...}, we want to keep a small
environment, so we can just replace all occurrences of \tr{x}
with \tr{y}.
\begin{code}
type StgEnv = IdEnv StgArg
\end{code}
No free/live variable information is pinned on in this pass; it's added
later. For this pass
we use @bOGUS_LVs@ and @bOGUS_FVs@ as placeholders.
\begin{code}
bOGUS_LVs :: StgLiveVars
bOGUS_LVs = panic "bOGUS_LVs" -- emptyUniqSet (used when pprTracing)
bOGUS_FVs :: [Id]
bOGUS_FVs = panic "bOGUS_FVs" -- [] (ditto)
\end{code}
\begin{code}
topCoreBindsToStg :: UniqSupply -- name supply
-> [CoreBinding] -- input
-> [StgBinding] -- output
topCoreBindsToStg us core_binds
= case (initUs us (binds_to_stg nullIdEnv core_binds)) of
(_, stuff) -> stuff
where
binds_to_stg :: StgEnv -> [CoreBinding] -> UniqSM [StgBinding]
binds_to_stg env [] = returnUs []
binds_to_stg env (b:bs)
= do_top_bind env b `thenUs` \ (new_b, new_env, float_binds) ->
binds_to_stg new_env bs `thenUs` \ new_bs ->
returnUs (bagToList float_binds ++ -- Literals
new_b ++
new_bs)
do_top_bind env bind@(Rec pairs)
= coreBindToStg env bind
do_top_bind env bind@(NonRec var rhs)
= coreBindToStg env bind `thenUs` \ (stg_binds, new_env, float_binds) ->
{- TESTING:
let
ppr_blah xs = ppInterleave ppComma (map pp_x xs)
pp_x (u,x) = ppBesides [pprUnique u, ppStr ": ", ppr PprDebug x]
in
pprTrace "do_top_bind:" (ppAbove (ppr PprDebug stg_binds) (ppr_blah (ufmToList new_env))) $
-}
case stg_binds of
[StgNonRec var (StgRhsClosure cc bi fvs u [] rhs_body)] ->
-- Mega-special case; there's still a binding there
-- no fvs (of course), *no args*, "let" rhs
let
(extra_float_binds, rhs_body') = seek_liftable [] rhs_body
in
returnUs (extra_float_binds ++
[StgNonRec var (StgRhsClosure cc bi fvs u [] rhs_body')],
new_env,
float_binds)
other -> returnUs (stg_binds, new_env, float_binds)
--------------------
-- HACK: look for very simple, obviously-liftable bindings
-- that can come up to the top level; those that couldn't
-- 'cause they were big-lambda constrained in the Core world.
seek_liftable :: [StgBinding] -- accumulator...
-> StgExpr -- look for top-lev liftables
-> ([StgBinding], StgExpr) -- result
seek_liftable acc expr@(StgLet inner_bind body)
| is_liftable inner_bind
= seek_liftable (inner_bind : acc) body
seek_liftable acc other_expr = (reverse acc, other_expr) -- Finished
--------------------
is_liftable (StgNonRec binder (StgRhsClosure _ _ _ _ args body))
= not (null args) -- it's manifestly a function...
|| isLeakFreeType [] (idType binder)
|| is_whnf body
-- ToDo: use a decent manifestlyWHNF function for STG?
where
is_whnf (StgCon _ _ _) = True
is_whnf (StgApp (StgVarArg v) _ _) = isBottomingId v
is_whnf other = False
is_liftable (StgRec [(_, StgRhsClosure _ _ _ _ args body)])
= not (null args) -- it's manifestly a (recursive) function...
is_liftable anything_else = False
\end{code}
%************************************************************************
%* *
\subsection[coreToStg-binds]{Converting bindings}
%* *
%************************************************************************
\begin{code}
coreBindToStg :: StgEnv
-> CoreBinding
-> UniqSM ([StgBinding], -- Empty or singleton
StgEnv, -- New envt
Bag StgBinding) -- Floats
coreBindToStg env (NonRec binder rhs)
= coreRhsToStg env rhs `thenUs` \ (stg_rhs, rhs_binds) ->
let
-- Binds to return if RHS is trivial
triv_binds = if externallyVisibleId binder then
-- pprTrace "coreBindToStg:keeping:" (ppCat [ppr PprDebug binder, ppr PprDebug (externallyVisibleId binder)]) $
[StgNonRec binder stg_rhs] -- Retain it
else
-- pprTrace "coreBindToStg:tossing:" (ppCat [ppr PprDebug binder, ppr PprDebug (externallyVisibleId binder)]) $
[] -- Discard it
in
case stg_rhs of
StgRhsClosure cc bi fvs upd [] (StgApp atom [] lvs) ->
-- Trivial RHS, so augment envt, and ditch the binding
returnUs (triv_binds, new_env, rhs_binds)
where
new_env = addOneToIdEnv env binder atom
StgRhsCon cc con_id [] ->
-- Trivial RHS, so augment envt, and ditch the binding
returnUs (triv_binds, new_env, rhs_binds)
where
new_env = addOneToIdEnv env binder (StgVarArg con_id)
other -> -- Non-trivial RHS, so don't augment envt
returnUs ([StgNonRec binder stg_rhs], env, rhs_binds)
coreBindToStg env (Rec pairs)
= -- NB: *** WE DO NOT CHECK FOR TRIV_BINDS in REC BIND ****
-- (possibly ToDo)
let
(binders, rhss) = unzip pairs
in
mapAndUnzipUs (coreRhsToStg env) rhss `thenUs` \ (stg_rhss, rhs_binds) ->
returnUs ([StgRec (binders `zip` stg_rhss)], env, unionManyBags rhs_binds)
\end{code}
%************************************************************************
%* *
\subsection[coreToStg-rhss]{Converting right hand sides}
%* *
%************************************************************************
\begin{code}
coreRhsToStg :: StgEnv -> CoreExpr -> UniqSM (StgRhs, Bag StgBinding)
coreRhsToStg env core_rhs
= coreExprToStg env core_rhs `thenUs` \ (stg_expr, stg_binds) ->
let stg_rhs = case stg_expr of
StgLet (StgNonRec var1 rhs) (StgApp (StgVarArg var2) [] _)
| var1 == var2 -> rhs
-- This curious stuff is to unravel what a lambda turns into
-- We have to do it this way, rather than spot a lambda in the
-- incoming rhs
StgCon con args _ -> StgRhsCon noCostCentre con args
other -> StgRhsClosure noCostCentre -- No cost centre (ToDo?)
stgArgOcc -- safe
bOGUS_FVs
Updatable -- Be pessimistic
[]
stg_expr
in
returnUs (stg_rhs, stg_binds)
\end{code}
%************************************************************************
%* *
\subsection[coreToStg-lits]{Converting literals}
%* *
%************************************************************************
Literals: the NoRep kind need to be de-no-rep'd.
We always replace them with a simple variable, and float a suitable
binding out to the top level.
If an Integer is small enough (Haskell implementations must support
Ints in the range $[-2^29+1, 2^29-1]$), wrap it up in @int2Integer@;
otherwise, wrap with @litString2Integer@.
\begin{code}
tARGET_MIN_INT, tARGET_MAX_INT :: Integer
tARGET_MIN_INT = -536870912
tARGET_MAX_INT = 536870912
litToStgArg :: Literal -> UniqSM (StgArg, Bag StgBinding)
litToStgArg (NoRepStr s)
= newStgVar stringTy `thenUs` \ var ->
let
rhs = StgRhsClosure noCostCentre -- No cost centre (ToDo?)
stgArgOcc -- safe
bOGUS_FVs
Updatable -- WAS: ReEntrant (see note below)
[] -- No arguments
val
-- We used not to update strings, so that they wouldn't clog up the heap,
-- but instead be unpacked each time. But on some programs that costs a lot
-- [eg hpg], so now we update them.
val = if (any is_NUL (_UNPK_ s)) then -- must cater for NULs in literal string
StgApp (StgVarArg unpackCString2Id)
[StgLitArg (MachStr s),
StgLitArg (mkMachInt (toInteger (_LENGTH_ s)))]
bOGUS_LVs
else
StgApp (StgVarArg unpackCStringId)
[StgLitArg (MachStr s)]
bOGUS_LVs
in
returnUs (StgVarArg var, unitBag (StgNonRec var rhs))
where
is_NUL c = c == '\0'
litToStgArg (NoRepInteger i integer_ty)
-- extremely convenient to look out for a few very common
-- Integer literals!
| i == 0 = returnUs (StgVarArg integerZeroId, emptyBag)
| i == 1 = returnUs (StgVarArg integerPlusOneId, emptyBag)
| i == 2 = returnUs (StgVarArg integerPlusTwoId, emptyBag)
| i == (-1) = returnUs (StgVarArg integerMinusOneId, emptyBag)
| otherwise
= newStgVar integer_ty `thenUs` \ var ->
let
rhs = StgRhsClosure noCostCentre -- No cost centre (ToDo?)
stgArgOcc -- safe
bOGUS_FVs
Updatable -- Update an integer
[] -- No arguments
val
val
| i > tARGET_MIN_INT && i < tARGET_MAX_INT
= -- Start from an Int
StgPrim Int2IntegerOp [StgLitArg (mkMachInt i)] bOGUS_LVs
| otherwise
= -- Start from a string
StgPrim Addr2IntegerOp [StgLitArg (MachStr (_PK_ (show i)))] bOGUS_LVs
in
returnUs (StgVarArg var, unitBag (StgNonRec var rhs))
litToStgArg (NoRepRational r rational_ty)
= --ASSERT(is_rational_ty)
(if is_rational_ty then \x->x else pprTrace "litToStgArg:not rational?" (pprType PprDebug rational_ty)) $
litToStgArg (NoRepInteger (numerator r) integer_ty) `thenUs` \ (num_atom, binds1) ->
litToStgArg (NoRepInteger (denominator r) integer_ty) `thenUs` \ (denom_atom, binds2) ->
newStgVar rational_ty `thenUs` \ var ->
let
rhs = StgRhsCon noCostCentre -- No cost centre (ToDo?)
ratio_data_con -- Constructor
[num_atom, denom_atom]
in
returnUs (StgVarArg var, binds1 `unionBags`
binds2 `unionBags`
unitBag (StgNonRec var rhs))
where
(is_rational_ty, ratio_data_con, integer_ty)
= case (maybeAppDataTyCon rational_ty) of
Just (tycon, [i_ty], [con])
-> ASSERT(is_integer_ty i_ty)
(uniqueOf tycon == ratioTyConKey, con, i_ty)
_ -> (False, panic "ratio_data_con", panic "integer_ty")
is_integer_ty ty
= case (maybeAppDataTyCon ty) of
Just (tycon, [], _) -> uniqueOf tycon == integerTyConKey
_ -> False
litToStgArg other_lit = returnUs (StgLitArg other_lit, emptyBag)
\end{code}
%************************************************************************
%* *
\subsection[coreToStg-atoms{Converting atoms}
%* *
%************************************************************************
\begin{code}
coreArgsToStg :: StgEnv -> [CoreArg] -> UniqSM ([Type], [StgArg], Bag StgBinding)
coreArgsToStg env [] = returnUs ([], [], emptyBag)
coreArgsToStg env (a:as)
= coreArgsToStg env as `thenUs` \ (tys, args, binds) ->
do_arg a tys args binds
where
do_arg a trest vrest binds
= case a of
TyArg t -> returnUs (t:trest, vrest, binds)
UsageArg u -> returnUs (trest, vrest, binds)
VarArg v -> returnUs (trest, stgLookup env v : vrest, binds)
LitArg i -> litToStgArg i `thenUs` \ (v, bs) ->
returnUs (trest, v:vrest, bs `unionBags` binds)
\end{code}
There's not anything interesting we can ASSERT about \tr{var} if it
isn't in the StgEnv. (WDP 94/06)
\begin{code}
stgLookup :: StgEnv -> Id -> StgArg
stgLookup env var = case (lookupIdEnv env var) of
Nothing -> StgVarArg var
Just atom -> atom
\end{code}
%************************************************************************
%* *
\subsection[coreToStg-exprs]{Converting core expressions}
%* *
%************************************************************************
\begin{code}
coreExprToStg :: StgEnv
-> CoreExpr
-> UniqSM (StgExpr, -- Result
Bag StgBinding) -- Float these to top level
\end{code}
\begin{code}
coreExprToStg env (Lit lit)
= litToStgArg lit `thenUs` \ (atom, binds) ->
returnUs (StgApp atom [] bOGUS_LVs, binds)
coreExprToStg env (Var var)
= returnUs (StgApp (stgLookup env var) [] bOGUS_LVs, emptyBag)
coreExprToStg env (Con con args)
= coreArgsToStg env args `thenUs` \ (types, stg_atoms, stg_binds) ->
let
spec_con = mkSpecialisedCon con types
in
returnUs (StgCon spec_con stg_atoms bOGUS_LVs, stg_binds)
coreExprToStg env (Prim op args)
= coreArgsToStg env args `thenUs` \ (_, stg_atoms, stg_binds) ->
returnUs (StgPrim op stg_atoms bOGUS_LVs, stg_binds)
\end{code}
%************************************************************************
%* *
\subsubsection[coreToStg-lambdas]{Lambda abstractions}
%* *
%************************************************************************
\begin{code}
coreExprToStg env expr@(Lam _ _)
= let
(_,_, binders, body) = collectBinders expr
in
coreExprToStg env body `thenUs` \ stuff@(stg_body, binds) ->
if null binders then -- it was all type/usage binders; tossed
returnUs stuff
else
newStgVar (coreExprType expr) `thenUs` \ var ->
returnUs
(StgLet (StgNonRec var (StgRhsClosure noCostCentre
stgArgOcc
bOGUS_FVs
ReEntrant -- binders is non-empty
binders
stg_body))
(StgApp (StgVarArg var) [] bOGUS_LVs),
binds)
\end{code}
%************************************************************************
%* *
\subsubsection[coreToStg-applications]{Applications}
%* *
%************************************************************************
\begin{code}
coreExprToStg env expr@(App _ _)
= let
(fun,args) = collect_args expr []
in
-- Deal with the arguments
coreArgsToStg env args `thenUs` \ (_, stg_args, arg_binds) ->
-- Now deal with the function
case (fun, args) of
(Var fun_id, _) -> -- A function Id, so do an StgApp; it's ok if
-- there are no arguments.
returnUs (StgApp (stgLookup env fun_id) stg_args bOGUS_LVs, arg_binds)
(non_var_fun, []) -> -- No value args, so recurse into the function
coreExprToStg env non_var_fun
other -> -- A non-variable applied to things; better let-bind it.
newStgVar (coreExprType fun) `thenUs` \ fun_id ->
coreExprToStg env fun `thenUs` \ (stg_fun, fun_binds) ->
let
fun_rhs = StgRhsClosure noCostCentre -- No cost centre (ToDo?)
stgArgOcc
bOGUS_FVs
SingleEntry -- Only entered once
[]
stg_fun
in
returnUs (StgLet (StgNonRec fun_id fun_rhs)
(StgApp (StgVarArg fun_id) stg_args bOGUS_LVs),
arg_binds `unionBags` fun_binds)
where
-- Collect arguments, discarding type/usage applications
collect_args (App e (TyArg _)) args = collect_args e args
collect_args (App e (UsageArg _)) args = collect_args e args
collect_args (App fun arg) args = collect_args fun (arg:args)
collect_args fun args = (fun, args)
\end{code}
%************************************************************************
%* *
\subsubsection[coreToStg-cases]{Case expressions}
%* *
%************************************************************************
At this point, we *mangle* cases involving fork# and par# in the
discriminant. The original templates for these primops (see
@PrelVals.lhs@) constructed case expressions with boolean results
solely to fool the strictness analyzer, the simplifier, and anyone
else who might want to fool with the evaluation order. Now, we
believe that once the translation to STG code is performed, our
evaluation order is safe. Therefore, we convert expressions of the
form:
case par# e of
True -> rhs
False -> parError#
to
case par# e of
_ -> rhs
\begin{code}
coreExprToStg env (Case discrim@(Prim op _) alts)
| funnyParallelOp op
= getUnique `thenUs` \ uniq ->
coreExprToStg env discrim `thenUs` \ (stg_discrim, discrim_binds) ->
alts_to_stg alts `thenUs` \ (stg_alts, alts_binds) ->
returnUs (
StgCase stg_discrim
bOGUS_LVs
bOGUS_LVs
uniq
stg_alts,
discrim_binds `unionBags` alts_binds
)
where
funnyParallelOp SeqOp = True
funnyParallelOp ParOp = True
funnyParallelOp ForkOp = True
funnyParallelOp _ = False
discrim_ty = coreExprType discrim
alts_to_stg (PrimAlts _ (BindDefault binder rhs))
= coreExprToStg env rhs `thenUs` \ (stg_rhs, rhs_binds) ->
let
stg_deflt = StgBindDefault binder False stg_rhs
in
returnUs (StgPrimAlts discrim_ty [] stg_deflt, rhs_binds)
-- OK, back to real life...
coreExprToStg env (Case discrim alts)
= coreExprToStg env discrim `thenUs` \ (stg_discrim, discrim_binds) ->
alts_to_stg discrim alts `thenUs` \ (stg_alts, alts_binds) ->
getUnique `thenUs` \ uniq ->
returnUs (
StgCase stg_discrim
bOGUS_LVs
bOGUS_LVs
uniq
stg_alts,
discrim_binds `unionBags` alts_binds
)
where
discrim_ty = coreExprType discrim
(_, discrim_ty_args, _) = getAppDataTyConExpandingDicts discrim_ty
alts_to_stg discrim (AlgAlts alts deflt)
= default_to_stg discrim deflt `thenUs` \ (stg_deflt, deflt_binds) ->
mapAndUnzipUs boxed_alt_to_stg alts `thenUs` \ (stg_alts, alts_binds) ->
returnUs (StgAlgAlts discrim_ty stg_alts stg_deflt,
deflt_binds `unionBags` unionManyBags alts_binds)
where
boxed_alt_to_stg (con, bs, rhs)
= coreExprToStg env rhs `thenUs` \ (stg_rhs, rhs_binds) ->
returnUs ((spec_con, bs, [ True | b <- bs ]{-bogus use mask-}, stg_rhs),
rhs_binds)
where
spec_con = mkSpecialisedCon con discrim_ty_args
alts_to_stg discrim (PrimAlts alts deflt)
= default_to_stg discrim deflt `thenUs` \ (stg_deflt,deflt_binds) ->
mapAndUnzipUs unboxed_alt_to_stg alts `thenUs` \ (stg_alts, alts_binds) ->
returnUs (StgPrimAlts discrim_ty stg_alts stg_deflt,
deflt_binds `unionBags` unionManyBags alts_binds)
where
unboxed_alt_to_stg (lit, rhs)
= coreExprToStg env rhs `thenUs` \ (stg_rhs, rhs_binds) ->
returnUs ((lit, stg_rhs), rhs_binds)
default_to_stg discrim NoDefault
= returnUs (StgNoDefault, emptyBag)
default_to_stg discrim (BindDefault binder rhs)
= coreExprToStg new_env rhs `thenUs` \ (stg_rhs, rhs_binds) ->
returnUs (StgBindDefault binder True{-used? no it is lying-} stg_rhs,
rhs_binds)
where
--
-- We convert case x of {...; x' -> ...x'...}
-- to
-- case x of {...; _ -> ...x... }
--
-- See notes in SimplCase.lhs, near simplDefault for the reasoning.
-- It's quite easily done: simply extend the environment to bind the
-- default binder to the scrutinee.
--
new_env = case discrim of
Var v -> addOneToIdEnv env binder (stgLookup env v)
other -> env
\end{code}
%************************************************************************
%* *
\subsubsection[coreToStg-let(rec)]{Let and letrec expressions}
%* *
%************************************************************************
\begin{code}
coreExprToStg env (Let bind body)
= coreBindToStg env bind `thenUs` \ (stg_binds, new_env, float_binds1) ->
coreExprToStg new_env body `thenUs` \ (stg_body, float_binds2) ->
returnUs (mkStgLets stg_binds stg_body, float_binds1 `unionBags` float_binds2)
\end{code}
%************************************************************************
%* *
\subsubsection[coreToStg-scc]{SCC expressions}
%* *
%************************************************************************
Covert core @scc@ expression directly to STG @scc@ expression.
\begin{code}
coreExprToStg env (SCC cc expr)
= coreExprToStg env expr `thenUs` \ (stg_expr, binds) ->
returnUs (StgSCC (coreExprType expr) cc stg_expr, binds)
\end{code}
\begin{code}
coreExprToStg env (Coerce c ty expr) = coreExprToStg env expr
\end{code}
%************************************************************************
%* *
\subsection[coreToStg-misc]{Miscellaneous helping functions}
%* *
%************************************************************************
Utilities.
Invent a fresh @Id@:
\begin{code}
newStgVar :: Type -> UniqSM Id
newStgVar ty
= getUnique `thenUs` \ uniq ->
returnUs (mkSysLocal SLIT("stg") uniq ty mkUnknownSrcLoc)
\end{code}
\begin{code}
mkStgLets :: [StgBinding]
-> StgExpr -- body of let
-> StgExpr
mkStgLets binds body = foldr StgLet body binds
\end{code}
|