2 % (c) The GRASP/AQUA Project, Glasgow University, 1992-1998
4 % $Id: CgCase.lhs,v 1.26 1999/04/23 13:53:28 simonm Exp $
6 %********************************************************
8 \section[CgCase]{Converting @StgCase@ expressions}
10 %********************************************************
13 module CgCase ( cgCase, saveVolatileVarsAndRegs,
14 restoreCurrentCostCentre, freeCostCentreSlot,
15 splitTyConAppThroughNewTypes ) where
17 #include "HsVersions.h"
19 import {-# SOURCE #-} CgExpr ( cgExpr )
25 import AbsCUtils ( mkAbstractCs, mkAbsCStmts, mkAlgAltsCSwitch,
26 getAmodeRep, nonemptyAbsC
28 import CoreSyn ( isDeadBinder )
29 import CgUpdate ( reserveSeqFrame )
30 import CgBindery ( getVolatileRegs, getArgAmodes, getArgAmode,
31 bindNewToReg, bindNewToTemp,
33 rebindToStack, getCAddrMode,
34 getCAddrModeAndInfo, getCAddrModeIfVolatile,
35 buildContLivenessMask, nukeDeadBindings,
37 import CgCon ( bindConArgs, bindUnboxedTupleComponents )
38 import CgHeapery ( altHeapCheck, yield )
39 import CgRetConv ( dataReturnConvPrim, ctrlReturnConvAlg,
40 CtrlReturnConvention(..)
42 import CgStackery ( allocPrimStack, allocStackTop,
43 deAllocStackTop, freeStackSlots
45 import CgTailCall ( tailCallFun )
46 import CgUsages ( getSpRelOffset, getRealSp )
47 import CLabel ( CLabel, mkVecTblLabel, mkReturnPtLabel,
48 mkDefaultLabel, mkAltLabel, mkReturnInfoLabel,
49 mkErrorStdEntryLabel, mkClosureTblLabel
51 import ClosureInfo ( mkLFArgument )
52 import CmdLineOpts ( opt_SccProfilingOn, opt_GranMacros )
53 import CostCentre ( CostCentre )
54 import Id ( Id, idPrimRep )
55 import DataCon ( DataCon, dataConTag, fIRST_TAG, ConTag,
56 isUnboxedTupleCon, dataConType )
57 import VarSet ( varSetElems )
58 import Const ( Con(..), Literal )
59 import PrimOp ( primOpOutOfLine, PrimOp(..) )
60 import PrimRep ( getPrimRepSize, retPrimRepSize, PrimRep(..)
62 import TyCon ( TyCon, isEnumerationTyCon, isUnboxedTupleTyCon,
63 isNewTyCon, isAlgTyCon, isFunTyCon, isPrimTyCon,
64 tyConDataCons, tyConFamilySize )
65 import Type ( Type, typePrimRep, splitAlgTyConApp,
67 splitFunTys, applyTys )
68 import Unique ( Unique, Uniquable(..) )
69 import Maybes ( maybeToBool )
75 = GCMayHappen -- The scrutinee may involve GC, so everything must be
76 -- tidy before the code for the scrutinee.
78 | NoGC -- The scrutinee is a primitive value, or a call to a
79 -- primitive op which does no GC. Hence the case can
80 -- be done inline, without tidying up first.
83 It is quite interesting to decide whether to put a heap-check
84 at the start of each alternative. Of course we certainly have
85 to do so if the case forces an evaluation, or if there is a primitive
86 op which can trigger GC.
88 A more interesting situation is this:
95 default -> !C!; ...C...
98 where \tr{!x!} indicates a possible heap-check point. The heap checks
99 in the alternatives {\em can} be omitted, in which case the topmost
100 heapcheck will take their worst case into account.
102 In favour of omitting \tr{!B!}, \tr{!C!}:
104 - {\em May} save a heap overflow test,
105 if ...A... allocates anything. The other advantage
106 of this is that we can use relative addressing
107 from a single Hp to get at all the closures so allocated.
109 - No need to save volatile vars etc across the case
113 - May do more allocation than reqd. This sometimes bites us
114 badly. For example, nfib (ha!) allocates about 30\% more space if the
115 worst-casing is done, because many many calls to nfib are leaf calls
116 which don't need to allocate anything.
118 This never hurts us if there is only one alternative.
130 Several special cases for inline primitive operations.
133 cgCase (StgCon (PrimOp TagToEnumOp) [arg] res_ty)
134 live_in_whole_case live_in_alts bndr srt alts
135 | isEnumerationTyCon tycon
136 = getArgAmode arg `thenFC` \amode ->
138 [res] = getPrimAppResultAmodes (getUnique bndr) alts
140 absC (CAssign res (CTableEntry
141 (CLbl (mkClosureTblLabel tycon) PtrRep)
142 amode PtrRep)) `thenC`
144 -- Scrutinise the result
145 cgInlineAlts bndr alts
147 | otherwise = panic "cgCase: tagToEnum# of non-enumerated type"
149 (Just (tycon,_)) = splitTyConApp_maybe res_ty
151 cgCase (StgCon (PrimOp op) args res_ty)
152 live_in_whole_case live_in_alts bndr srt alts
153 | not (primOpOutOfLine op)
155 -- Get amodes for the arguments and results
156 getArgAmodes args `thenFC` \ arg_amodes ->
158 result_amodes = getPrimAppResultAmodes (getUnique bndr) alts
160 -- Perform the operation
161 getVolatileRegs live_in_alts `thenFC` \ vol_regs ->
163 absC (COpStmt result_amodes op
164 arg_amodes -- note: no liveness arg
167 -- Scrutinise the result
168 cgInlineAlts bndr alts
171 TODO: Case-of-case of primop can probably be done inline too (but
172 maybe better to translate it out beforehand). See
173 ghc/lib/misc/PackedString.lhs for examples where this crops up (with
176 Another special case: scrutinising a primitive-typed variable. No
177 evaluation required. We don't save volatile variables, nor do we do a
178 heap-check in the alternatives. Instead, the heap usage of the
179 alternatives is worst-cased and passed upstream. This can result in
180 allocating more heap than strictly necessary, but it will sometimes
181 eliminate a heap check altogether.
184 cgCase (StgApp v []) live_in_whole_case live_in_alts bndr srt
185 (StgPrimAlts ty alts deflt)
188 getCAddrMode v `thenFC` \amode ->
191 Careful! we can't just bind the default binder to the same thing
192 as the scrutinee, since it might be a stack location, and having
193 two bindings pointing at the same stack locn doesn't work (it
194 confuses nukeDeadBindings). Hence, use a new temp.
196 (if (isDeadBinder bndr)
198 else bindNewToTemp bndr `thenFC` \deflt_amode ->
199 absC (CAssign deflt_amode amode)) `thenC`
201 cgPrimAlts NoGC amode alts deflt []
204 Special case: scrutinising a non-primitive variable.
205 This can be done a little better than the general case, because
206 we can reuse/trim the stack slot holding the variable (if it is in one).
209 cgCase (StgApp fun args)
210 live_in_whole_case live_in_alts bndr srt alts@(StgAlgAlts ty _ _)
212 getCAddrModeAndInfo fun `thenFC` \ (fun_amode, lf_info) ->
213 getArgAmodes args `thenFC` \ arg_amodes ->
215 -- Squish the environment
216 nukeDeadBindings live_in_alts `thenC`
217 saveVolatileVarsAndRegs live_in_alts
218 `thenFC` \ (save_assts, alts_eob_info, maybe_cc_slot) ->
220 allocStackTop retPrimRepSize `thenFC` \_ ->
222 forkEval alts_eob_info nopC (
223 deAllocStackTop retPrimRepSize `thenFC` \_ ->
224 cgEvalAlts maybe_cc_slot bndr srt alts)
225 `thenFC` \ scrut_eob_info ->
227 let real_scrut_eob_info =
229 then reserveSeqFrame scrut_eob_info
233 setEndOfBlockInfo real_scrut_eob_info (
234 tailCallFun fun fun_amode lf_info arg_amodes save_assts
238 not_con_ty = case (getScrutineeTyCon ty) of
243 Note about return addresses: we *always* push a return address, even
244 if because of an optimisation we end up jumping direct to the return
245 code (not through the address itself). The alternatives always assume
246 that the return address is on the stack. The return address is
247 required in case the alternative performs a heap check, since it
248 encodes the liveness of the slots in the activation record.
250 On entry to the case alternative, we can re-use the slot containing
251 the return address immediately after the heap check. That's what the
252 deAllocStackTop call is doing above.
254 Finally, here is the general case.
257 cgCase expr live_in_whole_case live_in_alts bndr srt alts
258 = -- Figure out what volatile variables to save
259 nukeDeadBindings live_in_whole_case `thenC`
261 saveVolatileVarsAndRegs live_in_alts
262 `thenFC` \ (save_assts, alts_eob_info, maybe_cc_slot) ->
264 -- Save those variables right now!
265 absC save_assts `thenC`
267 -- generate code for the alts
268 forkEval alts_eob_info
270 nukeDeadBindings live_in_alts `thenC`
271 allocStackTop retPrimRepSize -- space for retn address
274 (deAllocStackTop retPrimRepSize `thenFC` \_ ->
275 cgEvalAlts maybe_cc_slot bndr srt alts) `thenFC` \ scrut_eob_info ->
277 let real_scrut_eob_info =
279 then reserveSeqFrame scrut_eob_info
283 setEndOfBlockInfo real_scrut_eob_info (cgExpr expr)
286 not_con_ty = case (getScrutineeTyCon (alts_ty alts)) of
291 There's a lot of machinery going on behind the scenes to manage the
292 stack pointer here. forkEval takes the virtual Sp and free list from
293 the first argument, and turns that into the *real* Sp for the second
294 argument. It also uses this virtual Sp as the args-Sp in the EOB info
295 returned, so that the scrutinee will trim the real Sp back to the
296 right place before doing whatever it does.
297 --SDM (who just spent an hour figuring this out, and didn't want to
300 Why don't we push the return address just before evaluating the
301 scrutinee? Because the slot reserved for the return address might
302 contain something useful, so we wait until performing a tail call or
303 return before pushing the return address (see
304 CgTailCall.pushReturnAddress).
306 This also means that the environment doesn't need to know about the
307 free stack slot for the return address (for generating bitmaps),
308 because we don't reserve it until just before the eval.
310 TODO!! Problem: however, we have to save the current cost centre
311 stack somewhere, because at the eval point the current CCS might be
312 different. So we pick a free stack slot and save CCCS in it. The
313 problem with this is that this slot isn't recorded as free/unboxed in
314 the environment, so a case expression in the scrutinee will have the
315 wrong bitmap attached. Fortunately we don't ever seem to see
316 case-of-case at the back end. One solution might be to shift the
317 saved CCS to the correct place in the activation record just before
321 (one consequence of the above is that activation records on the stack
322 don't follow the layout of closures when we're profiling. The CCS
323 could be anywhere within the record).
326 alts_ty (StgAlgAlts ty _ _) = ty
327 alts_ty (StgPrimAlts ty _ _) = ty
330 %************************************************************************
332 \subsection[CgCase-primops]{Primitive applications}
334 %************************************************************************
336 Get result amodes for a primitive operation, in the case wher GC can't happen.
337 The amodes are returned in canonical order, ready for the prim-op!
339 Alg case: temporaries named as in the alternatives,
340 plus (CTemp u) for the tag (if needed)
343 This is all disgusting, because these amodes must be consistent with those
344 invented by CgAlgAlts.
347 getPrimAppResultAmodes
353 If there's an StgBindDefault which does use the bound
354 variable, then we can only handle it if the type involved is
355 an enumeration type. That's important in the case
361 The only reason for the restriction to *enumeration* types is our
362 inability to invent suitable temporaries to hold the results;
363 Elaborating the CTemp addr mode to have a second uniq field
364 (which would simply count from 1) would solve the problem.
365 Anyway, cgInlineAlts is now capable of handling all cases;
366 it's only this function which is being wimpish.
369 getPrimAppResultAmodes uniq (StgAlgAlts ty alts
370 (StgBindDefault rhs))
371 | isEnumerationTyCon spec_tycon = [tag_amode]
372 | otherwise = pprPanic "getPrimAppResultAmodes: non-enumeration algebraic alternatives with default" (ppr uniq <+> ppr rhs)
374 -- A temporary variable to hold the tag; this is unaffected by GC because
375 -- the heap-checks in the branches occur after the switch
376 tag_amode = CTemp uniq IntRep
377 (spec_tycon, _, _) = splitAlgTyConApp ty
380 If we don't have a default case, we could be scrutinising an unboxed
381 tuple, or an enumeration type...
384 getPrimAppResultAmodes uniq (StgAlgAlts ty alts other_default)
385 -- Default is either StgNoDefault or StgBindDefault with unused binder
387 | isEnumerationTyCon tycon = [CTemp uniq IntRep]
389 | isUnboxedTupleTyCon tycon =
391 [(con, args, use_mask, rhs)] ->
392 [ CTemp (getUnique arg) (idPrimRep arg) | arg <- args ]
393 _ -> panic "getPrimAppResultAmodes: case of unboxed tuple has multiple branches"
395 | otherwise = panic ("getPrimAppResultAmodes: case of primop has strange type: " ++ showSDoc (ppr ty))
397 where (tycon, _, _) = splitAlgTyConApp ty
400 The situation is simpler for primitive results, because there is only
404 getPrimAppResultAmodes uniq (StgPrimAlts ty _ _)
405 = [CTemp uniq (typePrimRep ty)]
409 %************************************************************************
411 \subsection[CgCase-alts]{Alternatives}
413 %************************************************************************
415 @cgEvalAlts@ returns an addressing mode for a continuation for the
416 alternatives of a @case@, used in a context when there
417 is some evaluation to be done.
420 cgEvalAlts :: Maybe VirtualSpOffset -- Offset of cost-centre to be restored, if any
422 -> SRT -- SRT for the continuation
424 -> FCode Sequel -- Any addr modes inside are guaranteed
425 -- to be a label so that we can duplicate it
426 -- without risk of duplicating code
428 cgEvalAlts cc_slot bndr srt alts
430 let uniq = getUnique bndr in
432 -- get the stack liveness for the info table (after the CC slot has
433 -- been freed - this is important).
434 freeCostCentreSlot cc_slot `thenC`
435 buildContLivenessMask uniq `thenFC` \ liveness_mask ->
439 -- algebraic alts ...
440 (StgAlgAlts ty alts deflt) ->
442 -- bind the default binder (it covers all the alternatives)
443 (if (isDeadBinder bndr)
445 else bindNewToReg bndr node mkLFArgument) `thenC`
447 -- Generate sequel info for use downstream
448 -- At the moment, we only do it if the type is vector-returnable.
449 -- Reason: if not, then it costs extra to label the
450 -- alternatives, because we'd get return code like:
452 -- switch TagReg { 0 : JMP(alt_1); 1 : JMP(alt_2) ..etc }
454 -- which is worse than having the alt code in the switch statement
456 let tycon_info = getScrutineeTyCon ty
457 is_alg = maybeToBool tycon_info
458 Just spec_tycon = tycon_info
461 -- deal with the unboxed tuple case
462 if is_alg && isUnboxedTupleTyCon spec_tycon then
464 [alt] -> let lbl = mkReturnInfoLabel uniq in
465 cgUnboxedTupleAlt lbl cc_slot True alt
467 getSRTLabel `thenFC` \srt_label ->
468 absC (CRetDirect uniq abs_c (srt_label, srt)
469 liveness_mask) `thenC`
470 returnFC (CaseAlts (CLbl lbl RetRep) Nothing)
471 _ -> panic "cgEvalAlts: dodgy case of unboxed tuple type"
473 -- normal algebraic (or polymorphic) case alternatives
475 ret_conv | is_alg = ctrlReturnConvAlg spec_tycon
476 | otherwise = UnvectoredReturn 0
478 use_labelled_alts = case ret_conv of
479 VectoredReturn _ -> True
483 = if use_labelled_alts then
484 cgSemiTaggedAlts bndr alts deflt -- Just <something>
486 Nothing -- no semi-tagging info
489 cgAlgAlts GCMayHappen uniq cc_slot use_labelled_alts (not is_alg)
490 alts deflt True `thenFC` \ (tagged_alt_absCs, deflt_absC) ->
492 mkReturnVector uniq tagged_alt_absCs deflt_absC srt liveness_mask
493 ret_conv `thenFC` \ return_vec ->
495 returnFC (CaseAlts return_vec semi_tagged_stuff)
498 (StgPrimAlts ty alts deflt) ->
500 -- Generate the switch
501 getAbsC (cgPrimEvalAlts bndr ty alts deflt) `thenFC` \ abs_c ->
503 -- Generate the labelled block, starting with restore-cost-centre
504 getSRTLabel `thenFC` \srt_label ->
505 restoreCurrentCostCentre cc_slot `thenFC` \ cc_restore ->
506 absC (CRetDirect uniq (cc_restore `mkAbsCStmts` abs_c)
507 (srt_label,srt) liveness_mask) `thenC`
509 -- Return an amode for the block
510 returnFC (CaseAlts (CLbl (mkReturnPtLabel uniq) RetRep) Nothing)
520 HWL comment on {\em GrAnSim\/} (adding GRAN_YIELDs for context switch): If
521 we do an inlining of the case no separate functions for returning are
522 created, so we don't have to generate a GRAN_YIELD in that case. This info
523 must be propagated to cgAlgAltRhs (where the GRAN_YIELD macro might be
524 emitted). Hence, the new Bool arg to cgAlgAltRhs.
526 First case: primitive op returns an unboxed tuple.
529 cgInlineAlts bndr (StgAlgAlts ty [alt@(con,args,use_mask,rhs)] StgNoDefault)
530 | isUnboxedTupleCon con
531 = -- no heap check, no yield, just get in there and do it.
532 mapFCs bindNewToTemp args `thenFC` \ _ ->
536 = panic "cgInlineAlts: single alternative, not an unboxed tuple"
546 cgInlineAlts bndr (StgAlgAlts ty [] (StgBindDefault rhs))
547 = bindNewToTemp bndr `thenFC` \amode ->
549 (tycon, _, _) = splitAlgTyConApp ty
550 closure_lbl = CTableEntry (CLbl (mkClosureTblLabel tycon) PtrRep) amode PtrRep
552 absC (CAssign amode closure_lbl) `thenC`
556 Second case: algebraic case, several alternatives.
557 Tag is held in a temporary.
560 cgInlineAlts bndr (StgAlgAlts ty alts deflt)
561 = -- bind the default binder (it covers all the alternatives)
563 -- ToDo: BUG! bndr isn't bound in the alternatives
564 -- Shows up when compiling Word.lhs
565 -- case cmp# a b of r {
569 cgAlgAlts NoGC uniq Nothing{-cc_slot-} False{-no semi-tagging-}
570 False{-not poly case-} alts deflt
571 False{-don't emit yield-} `thenFC` \ (tagged_alts, deflt_c) ->
574 absC (mkAlgAltsCSwitch tag_amode tagged_alts deflt_c)
576 -- A temporary variable to hold the tag; this is unaffected by GC because
577 -- the heap-checks in the branches occur after the switch
578 tag_amode = CTemp uniq IntRep
579 uniq = getUnique bndr
582 Third (real) case: primitive result type.
585 cgInlineAlts bndr (StgPrimAlts ty alts deflt)
586 = cgPrimInlineAlts bndr ty alts deflt
590 %************************************************************************
592 \subsection[CgCase-alg-alts]{Algebraic alternatives}
594 %************************************************************************
596 In @cgAlgAlts@, none of the binders in the alternatives are
597 assumed to be yet bound.
599 HWL comment on {\em GrAnSim\/} (adding GRAN_YIELDs for context switch): The
600 last arg of cgAlgAlts indicates if we want a context switch at the
601 beginning of each alternative. Normally we want that. The only exception
602 are inlined alternatives.
607 -> Maybe VirtualSpOffset
608 -> Bool -- True <=> branches must be labelled
609 -> Bool -- True <=> polymorphic case
610 -> [(DataCon, [Id], [Bool], StgExpr)] -- The alternatives
611 -> StgCaseDefault -- The default
612 -> Bool -- Context switch at alts?
613 -> FCode ([(ConTag, AbstractC)], -- The branches
614 AbstractC -- The default case
617 cgAlgAlts gc_flag uniq restore_cc must_label_branches is_fun alts deflt
618 emit_yield{-should a yield macro be emitted?-}
620 = forkAlts (map (cgAlgAlt gc_flag uniq restore_cc must_label_branches emit_yield) alts)
621 (cgAlgDefault gc_flag is_fun uniq restore_cc must_label_branches deflt emit_yield)
625 cgAlgDefault :: GCFlag
626 -> Bool -- could be a function-typed result?
627 -> Unique -> Maybe VirtualSpOffset -> Bool -- turgid state...
628 -> StgCaseDefault -- input
630 -> FCode AbstractC -- output
632 cgAlgDefault gc_flag is_fun uniq cc_slot must_label_branch StgNoDefault _
635 cgAlgDefault gc_flag is_fun uniq cc_slot must_label_branch
637 emit_yield{-should a yield macro be emitted?-}
639 = -- We have arranged that Node points to the thing
640 restoreCurrentCostCentre cc_slot `thenFC` \restore_cc ->
641 getAbsC (absC restore_cc `thenC`
642 (if opt_GranMacros && emit_yield
643 then yield [node] False
644 else absC AbsCNop) `thenC`
645 possibleHeapCheck gc_flag is_fun [node] [] Nothing (cgExpr rhs)
646 -- Node is live, but doesn't need to point at the thing itself;
647 -- it's ok for Node to point to an indirection or FETCH_ME
648 -- Hence no need to re-enter Node.
649 ) `thenFC` \ abs_c ->
652 final_abs_c | must_label_branch = CCodeBlock lbl abs_c
657 lbl = mkDefaultLabel uniq
659 -- HWL comment on GrAnSim: GRAN_YIELDs needed; emitted in cgAlgAltRhs
662 -> Unique -> Maybe VirtualSpOffset -> Bool -- turgid state
663 -> Bool -- Context switch at alts?
664 -> (DataCon, [Id], [Bool], StgExpr)
665 -> FCode (ConTag, AbstractC)
667 cgAlgAlt gc_flag uniq cc_slot must_label_branch
668 emit_yield{-should a yield macro be emitted?-}
669 (con, args, use_mask, rhs)
671 restoreCurrentCostCentre cc_slot `thenFC` \restore_cc ->
672 getAbsC (absC restore_cc `thenC`
673 (if opt_GranMacros && emit_yield
674 then yield [node] True -- XXX live regs wrong
675 else absC AbsCNop) `thenC`
677 NoGC -> mapFCs bindNewToTemp args `thenFC` \_ -> nopC
678 GCMayHappen -> bindConArgs con args
680 possibleHeapCheck gc_flag False [node] [] Nothing (
682 ) `thenFC` \ abs_c ->
684 final_abs_c | must_label_branch = CCodeBlock lbl abs_c
687 returnFC (tag, final_abs_c)
690 lbl = mkAltLabel uniq tag
693 :: CLabel -- label of the alternative
694 -> Maybe VirtualSpOffset -- Restore cost centre
695 -> Bool -- ctxt switch
696 -> (DataCon, [Id], [Bool], StgExpr) -- alternative
699 cgUnboxedTupleAlt lbl cc_slot emit_yield (con,args,use_mask,rhs)
701 bindUnboxedTupleComponents args
702 `thenFC` \ (live_regs,tags,stack_res) ->
704 restoreCurrentCostCentre cc_slot `thenFC` \restore_cc ->
705 absC restore_cc `thenC`
707 (if opt_GranMacros && emit_yield
708 then yield live_regs True -- XXX live regs wrong?
709 else absC AbsCNop) `thenC`
711 -- ToDo: could maybe use Nothing here if stack_res is False
712 -- since the heap-check can just return to the top of the
717 -- free up stack slots containing tags,
718 freeStackSlots (map fst tags) `thenC`
720 -- generate a heap check if necessary
721 possibleHeapCheck GCMayHappen False live_regs tags ret_addr (
723 -- and finally the code for the alternative
728 %************************************************************************
730 \subsection[CgCase-semi-tagged-alts]{The code to deal with sem-tagging}
732 %************************************************************************
734 Turgid-but-non-monadic code to conjure up the required info from
735 algebraic case alternatives for semi-tagging.
738 cgSemiTaggedAlts :: Id
739 -> [(DataCon, [Id], [Bool], StgExpr)]
740 -> GenStgCaseDefault Id Id
743 cgSemiTaggedAlts binder alts deflt
744 = Just (map st_alt alts, st_deflt deflt)
746 uniq = getUnique binder
748 st_deflt StgNoDefault = Nothing
750 st_deflt (StgBindDefault _)
752 (CCallProfCtrMacro SLIT("RET_SEMI_BY_DEFAULT") [], -- ToDo: monadise?
756 st_alt (con, args, use_mask, _)
757 = -- Ha! Nothing to do; Node already points to the thing
759 (CCallProfCtrMacro SLIT("RET_SEMI_IN_HEAP") -- ToDo: monadise?
760 [mkIntCLit (length args)], -- how big the thing in the heap is
764 con_tag = dataConTag con
765 join_label = mkAltLabel uniq con_tag
768 %************************************************************************
770 \subsection[CgCase-prim-alts]{Primitive alternatives}
772 %************************************************************************
774 @cgPrimEvalAlts@ and @cgPrimInlineAlts@ generate suitable @CSwitch@es
775 for dealing with the alternatives of a primitive @case@, given an
776 addressing mode for the thing to scrutinise. It also keeps track of
777 the maximum stack depth encountered down any branch.
779 As usual, no binders in the alternatives are yet bound.
782 cgPrimInlineAlts bndr ty alts deflt
783 = cgPrimAltsWithDefault bndr NoGC (CTemp uniq kind) alts deflt []
785 uniq = getUnique bndr
786 kind = typePrimRep ty
788 cgPrimEvalAlts bndr ty alts deflt
789 = cgPrimAltsWithDefault bndr GCMayHappen (CReg reg) alts deflt [reg]
791 reg = dataReturnConvPrim kind
792 kind = typePrimRep ty
794 cgPrimAltsWithDefault bndr gc_flag scrutinee alts deflt regs
795 = -- first bind the default if necessary
796 (if isDeadBinder bndr
798 else bindNewPrimToAmode bndr scrutinee) `thenC`
799 cgPrimAlts gc_flag scrutinee alts deflt regs
801 cgPrimAlts gc_flag scrutinee alts deflt regs
802 = forkAlts (map (cgPrimAlt gc_flag regs) alts)
803 (cgPrimDefault gc_flag regs deflt)
804 `thenFC` \ (alt_absCs, deflt_absC) ->
806 absC (CSwitch scrutinee alt_absCs deflt_absC)
807 -- CSwitch does sensible things with one or zero alternatives
811 -> [MagicId] -- live registers
812 -> (Literal, StgExpr) -- The alternative
813 -> FCode (Literal, AbstractC) -- Its compiled form
815 cgPrimAlt gc_flag regs (lit, rhs)
816 = getAbsC rhs_code `thenFC` \ absC ->
819 rhs_code = possibleHeapCheck gc_flag False regs [] Nothing (cgExpr rhs)
821 cgPrimDefault :: GCFlag
822 -> [MagicId] -- live registers
826 cgPrimDefault gc_flag regs StgNoDefault
827 = panic "cgPrimDefault: No default in prim case"
829 cgPrimDefault gc_flag regs (StgBindDefault rhs)
830 = getAbsC (possibleHeapCheck gc_flag False regs [] Nothing (cgExpr rhs))
834 %************************************************************************
836 \subsection[CgCase-tidy]{Code for tidying up prior to an eval}
838 %************************************************************************
841 saveVolatileVarsAndRegs
842 :: StgLiveVars -- Vars which should be made safe
843 -> FCode (AbstractC, -- Assignments to do the saves
844 EndOfBlockInfo, -- sequel for the alts
845 Maybe VirtualSpOffset) -- Slot for current cost centre
848 saveVolatileVarsAndRegs vars
849 = saveVolatileVars vars `thenFC` \ var_saves ->
850 saveCurrentCostCentre `thenFC` \ (maybe_cc_slot, cc_save) ->
851 getEndOfBlockInfo `thenFC` \ eob_info ->
852 returnFC (mkAbstractCs [var_saves, cc_save],
857 saveVolatileVars :: StgLiveVars -- Vars which should be made safe
858 -> FCode AbstractC -- Assignments to to the saves
860 saveVolatileVars vars
861 = save_em (varSetElems vars)
863 save_em [] = returnFC AbsCNop
866 = getCAddrModeIfVolatile var `thenFC` \ v ->
868 Nothing -> save_em vars -- Non-volatile, so carry on
871 Just vol_amode -> -- Aha! It's volatile
872 save_var var vol_amode `thenFC` \ abs_c ->
873 save_em vars `thenFC` \ abs_cs ->
874 returnFC (abs_c `mkAbsCStmts` abs_cs)
876 save_var var vol_amode
877 = allocPrimStack (getPrimRepSize kind) `thenFC` \ slot ->
878 rebindToStack var slot `thenC`
879 getSpRelOffset slot `thenFC` \ sp_rel ->
880 returnFC (CAssign (CVal sp_rel kind) vol_amode)
882 kind = getAmodeRep vol_amode
885 ---------------------------------------------------------------------------
887 When we save the current cost centre (which is done for lexical
888 scoping), we allocate a free stack location, and return (a)~the
889 virtual offset of the location, to pass on to the alternatives, and
890 (b)~the assignment to do the save (just as for @saveVolatileVars@).
893 saveCurrentCostCentre ::
894 FCode (Maybe VirtualSpOffset, -- Where we decide to store it
895 AbstractC) -- Assignment to save it
897 saveCurrentCostCentre
898 = if not opt_SccProfilingOn then
899 returnFC (Nothing, AbsCNop)
901 allocPrimStack (getPrimRepSize CostCentreRep) `thenFC` \ slot ->
902 getSpRelOffset slot `thenFC` \ sp_rel ->
904 CAssign (CVal sp_rel CostCentreRep) (CReg CurCostCentre))
906 freeCostCentreSlot :: Maybe VirtualSpOffset -> Code
907 freeCostCentreSlot Nothing = nopC
908 freeCostCentreSlot (Just slot) = freeStackSlots [slot]
910 restoreCurrentCostCentre :: Maybe VirtualSpOffset -> FCode AbstractC
911 restoreCurrentCostCentre Nothing = returnFC AbsCNop
912 restoreCurrentCostCentre (Just slot)
913 = getSpRelOffset slot `thenFC` \ sp_rel ->
914 returnFC (CCallProfCCMacro SLIT("RESTORE_CCCS") [CVal sp_rel CostCentreRep])
915 -- we use the RESTORE_CCCS macro, rather than just
916 -- assigning into CurCostCentre, in case RESTORE_CCC
917 -- has some sanity-checking in it.
920 %************************************************************************
922 \subsection[CgCase-return-vec]{Building a return vector}
924 %************************************************************************
926 Build a return vector, and return a suitable label addressing
930 mkReturnVector :: Unique
931 -> [(ConTag, AbstractC)] -- Branch codes
932 -> AbstractC -- Default case
933 -> SRT -- continuation's SRT
934 -> Liveness -- stack liveness
935 -> CtrlReturnConvention
938 mkReturnVector uniq tagged_alt_absCs deflt_absC srt liveness ret_conv
939 = getSRTLabel `thenFC` \srt_label ->
941 srt_info = (srt_label, srt)
943 (return_vec_amode, vtbl_body) = case ret_conv of {
945 -- might be a polymorphic case...
946 UnvectoredReturn 0 ->
947 ASSERT(null tagged_alt_absCs)
948 (CLbl ret_label RetRep,
949 absC (CRetDirect uniq deflt_absC (srt_label, srt) liveness));
951 UnvectoredReturn n ->
952 -- find the tag explicitly rather than using tag_reg for now.
953 -- on architectures with lots of regs the tag will be loaded
954 -- into tag_reg by the code doing the returning.
956 tag = CMacroExpr WordRep GET_TAG [CVal (nodeRel 0) DataPtrRep]
958 (CLbl ret_label RetRep,
959 absC (CRetDirect uniq
960 (mkAlgAltsCSwitch tag tagged_alt_absCs deflt_absC)
964 VectoredReturn table_size ->
966 (vector_table, alts_absC) =
967 unzip (map mk_vector_entry [fIRST_TAG .. (table_size+fIRST_TAG-1)])
969 ret_vector = CRetVector vtbl_label
971 (srt_label, srt) liveness
973 (CLbl vtbl_label DataPtrRep,
974 -- alts come first, because we don't want to declare all the symbols
975 absC (mkAbstractCs (mkAbstractCs alts_absC : [deflt_absC,ret_vector]))
980 returnFC return_vec_amode
984 vtbl_label = mkVecTblLabel uniq
985 ret_label = mkReturnInfoLabel uniq
988 case nonemptyAbsC deflt_absC of
989 -- the simplifier might have eliminated a case
990 Nothing -> CLbl mkErrorStdEntryLabel CodePtrRep
991 Just absC@(CCodeBlock lbl _) -> CLbl lbl CodePtrRep
993 mk_vector_entry :: ConTag -> (CAddrMode, AbstractC)
995 = case [ absC | (t, absC) <- tagged_alt_absCs, t == tag ] of
996 [] -> (deflt_lbl, AbsCNop)
997 [absC@(CCodeBlock lbl _)] -> (CLbl lbl CodePtrRep,absC)
998 _ -> panic "mkReturnVector: too many"
1001 %************************************************************************
1003 \subsection[CgCase-utils]{Utilities for handling case expressions}
1005 %************************************************************************
1007 @possibleHeapCheck@ tests a flag passed in to decide whether to do a
1008 heap check or not. These heap checks are always in a case
1009 alternative, so we use altHeapCheck.
1014 -> Bool -- True <=> algebraic case
1015 -> [MagicId] -- live registers
1016 -> [(VirtualSpOffset,Int)] -- stack slots to tag
1017 -> Maybe CLabel -- return address
1018 -> Code -- continuation
1021 possibleHeapCheck GCMayHappen is_alg regs tags lbl code
1022 = altHeapCheck is_alg regs tags AbsCNop lbl code
1023 possibleHeapCheck NoGC _ _ tags lbl code
1027 splitTyConAppThroughNewTypes is like splitTyConApp_maybe except
1028 that it looks through newtypes in addition to synonyms. It's
1029 useful in the back end where we're not interested in newtypes
1032 Sometimes, we've thrown away the constructors during pruning in the
1033 renamer. In these cases, we emit a warning and fall back to using a
1034 SEQ_FRAME to evaluate the case scrutinee.
1037 getScrutineeTyCon :: Type -> Maybe TyCon
1038 getScrutineeTyCon ty =
1039 case (splitTyConAppThroughNewTypes ty) of
1042 if isFunTyCon tc then Nothing else -- not interested in funs
1043 if isPrimTyCon tc then Just tc else -- return primitive tycons
1044 -- otherwise (algebraic tycons) check the no. of constructors
1045 case (tyConFamilySize tc) of
1046 0 -> pprTrace "Warning" (hcat [
1047 text "constructors for ",
1049 text " not available.\n\tUse -fno-prune-tydecls to fix."
1053 splitTyConAppThroughNewTypes :: Type -> Maybe (TyCon, [Type])
1054 splitTyConAppThroughNewTypes ty
1055 = case splitTyConApp_maybe ty of
1057 | isNewTyCon tc -> splitTyConAppThroughNewTypes ty
1058 | otherwise -> Just (tc, tys)
1060 ([ty], _) = splitFunTys (applyTys (dataConType (head (tyConDataCons tc))) tys)