2 % (c) The GRASP/AQUA Project, Glasgow University, 1992-1996
4 %********************************************************
6 \section[CgCase]{Converting @StgCase@ expressions}
8 %********************************************************
11 module CgCase ( cgCase, saveVolatileVarsAndRegs ) where
13 #include "HsVersions.h"
15 import {-# SOURCE #-} CgExpr
21 import AbsCUtils ( mkAbstractCs, mkAbsCStmts, mkAlgAltsCSwitch,
22 magicIdPrimRep, getAmodeRep
24 import CgBindery ( getVolatileRegs, getArgAmode, getArgAmodes,
25 bindNewToReg, bindNewToTemp,
27 rebindToAStack, rebindToBStack,
28 getCAddrModeAndInfo, getCAddrModeIfVolatile,
31 import CgCon ( buildDynCon, bindConArgs )
32 import CgHeapery ( heapCheck, yield )
33 import CgRetConv ( dataReturnConvAlg, dataReturnConvPrim,
35 DataReturnConvention(..), CtrlReturnConvention(..),
36 assignPrimOpResultRegs,
39 import CgStackery ( allocAStack, allocBStack, allocAStackTop, allocBStackTop )
40 import CgTailCall ( tailCallBusiness, performReturn )
41 import CgUsages ( getSpARelOffset, getSpBRelOffset, freeBStkSlot )
42 import CLabel ( mkVecTblLabel, mkReturnPtLabel, mkDefaultLabel,
45 import ClosureInfo ( mkConLFInfo, mkLFArgument, layOutDynCon )
46 import CmdLineOpts ( opt_SccProfilingOn, opt_GranMacros )
47 import CostCentre ( useCurrentCostCentre, CostCentre )
48 import HeapOffs ( VirtualSpBOffset, VirtualHeapOffset )
49 import Id ( idPrimRep, dataConTag, fIRST_TAG, ConTag,
51 idSetToList, GenId{-instance Uniquable,Eq-}, Id
53 import Literal ( Literal )
54 import Maybes ( catMaybes )
55 import PrimOp ( primOpCanTriggerGC, PrimOp(..),
56 primOpStackRequired, StackRequirement(..)
58 import PrimRep ( getPrimRepSize, isFollowableRep, retPrimRepSize,
61 import TyCon ( isEnumerationTyCon )
62 import Type ( typePrimRep,
63 splitAlgTyConApp, splitAlgTyConApp_maybe,
66 import Unique ( Unique, Uniquable(..) )
67 import Util ( sortLt, isIn, isn'tIn, zipEqual )
73 = GCMayHappen -- The scrutinee may involve GC, so everything must be
74 -- tidy before the code for the scrutinee.
76 | NoGC -- The scrutinee is a primitive value, or a call to a
77 -- primitive op which does no GC. Hence the case can
78 -- be done inline, without tidying up first.
81 It is quite interesting to decide whether to put a heap-check
82 at the start of each alternative. Of course we certainly have
83 to do so if the case forces an evaluation, or if there is a primitive
84 op which can trigger GC.
86 A more interesting situation is this:
93 default -> !C!; ...C...
96 where \tr{!x!} indicates a possible heap-check point. The heap checks
97 in the alternatives {\em can} be omitted, in which case the topmost
98 heapcheck will take their worst case into account.
100 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
116 May do more allocation than reqd. This sometimes bites us
117 badly. For example, nfib (ha!) allocates about 30\% more space if the
118 worst-casing is done, because many many calls to nfib are leaf calls
119 which don't need to allocate anything.
121 This never hurts us if there is only one alternative.
125 *** NOT YET DONE *** The difficulty is that \tr{!B!}, \tr{!C!} need
126 to take account of what is live, and that includes all live volatile
127 variables, even if they also have stable analogues. Furthermore, the
128 stack pointers must be lined up properly so that GC sees tidy stacks.
129 If these things are done, then the heap checks can be done at \tr{!B!} and
130 \tr{!C!} without a full save-volatile-vars sequence.
141 Several special cases for primitive operations.
145 cgCase (StgPrim op args _) live_in_whole_case live_in_alts uniq alts
146 | not (primOpCanTriggerGC op)
148 -- Get amodes for the arguments and results
149 getPrimOpArgAmodes op args `thenFC` \ arg_amodes ->
151 result_amodes = getPrimAppResultAmodes uniq alts
152 liveness_mask = panic "cgCase: liveness of non-GC-ing primop touched\n"
154 -- Perform the operation
155 getVolatileRegs live_in_alts `thenFC` \ vol_regs ->
157 -- seq cannot happen here => no additional B Stack alloc
159 absC (COpStmt result_amodes op
160 arg_amodes -- note: no liveness arg
161 liveness_mask vol_regs) `thenC`
163 -- Scrutinise the result
164 cgInlineAlts NoGC uniq alts
166 | otherwise -- *Can* trigger GC
167 = getPrimOpArgAmodes op args `thenFC` \ arg_amodes ->
169 -- Get amodes for the arguments and results, and assign to regs
170 -- (Can-trigger-gc primops guarantee to have their (nonRobust)
173 op_result_regs = assignPrimOpResultRegs op
175 op_result_amodes = map CReg op_result_regs
177 (op_arg_amodes, liveness_mask, arg_assts)
178 = makePrimOpArgsRobust op arg_amodes
180 liveness_arg = mkIntCLit liveness_mask
182 -- Tidy up in case GC happens...
184 -- Nota Bene the use of live_in_whole_case in nukeDeadBindings.
185 -- Reason: the arg_assts computed above may refer to some stack slots
186 -- which are not live in the alts. So we mustn't use those slots
187 -- to save volatile vars in!
188 nukeDeadBindings live_in_whole_case `thenC`
189 saveVolatileVars live_in_alts `thenFC` \ volatile_var_save_assts ->
191 -- Allocate stack words for the prim-op itself,
192 -- these are guaranteed to be ON TOP OF the stack.
193 -- Currently this is used *only* by the seq# primitive op.
195 (a_req,b_req) = case (primOpStackRequired op) of
196 NoStackRequired -> (0, 0)
197 FixedStackRequired a b -> (a, b)
198 VariableStackRequired -> (0, 0) -- i.e. don't care
200 allocAStackTop a_req `thenFC` \ a_slot ->
201 allocBStackTop b_req `thenFC` \ b_slot ->
203 getEndOfBlockInfo `thenFC` \ eob_info@(EndOfBlockInfo args_spa args_spb sequel) ->
204 -- a_req and b_req allocate stack space that is taken care of by the
205 -- macros generated for the primops; thus, we there is no need to adjust
206 -- this part of the stacks later on (=> +a_req in EndOfBlockInfo)
207 -- currently all this is only used for SeqOp
208 forkEval (if True {- a_req==0 && b_req==0 -}
210 else (EndOfBlockInfo (args_spa+a_req)
211 (args_spb+b_req) sequel)) nopC
213 getAbsC (cgInlineAlts GCMayHappen uniq alts) `thenFC` \ abs_c ->
214 absC (CRetUnVector vtbl_label (CLabelledCode return_label abs_c))
216 returnFC (CaseAlts (CUnVecLbl return_label vtbl_label)
217 Nothing{-no semi-tagging-}))
218 `thenFC` \ new_eob_info ->
220 -- Record the continuation info
221 setEndOfBlockInfo new_eob_info (
223 -- Now "return" to the inline alternatives; this will get
224 -- compiled to a fall-through.
226 simultaneous_assts = arg_assts `mkAbsCStmts` volatile_var_save_assts
228 -- do_op_and_continue will be passed an amode for the continuation
229 do_op_and_continue sequel
230 = absC (COpStmt op_result_amodes
232 (pin_liveness op liveness_arg op_arg_amodes)
237 sequelToAmode sequel `thenFC` \ dest_amode ->
238 absC (CReturn dest_amode DirectReturn)
240 -- Note: we CJump even for algebraic data types,
241 -- because cgInlineAlts always generates code, never a
244 performReturn simultaneous_assts do_op_and_continue live_in_alts
247 -- for all PrimOps except ccalls, we pin the liveness info
248 -- on as the first "argument"
249 -- ToDo: un-duplicate?
251 pin_liveness (CCallOp _ _ _ _ _ _) _ args = args
252 pin_liveness other_op liveness_arg args
255 vtbl_label = mkVecTblLabel uniq
256 return_label = mkReturnPtLabel uniq
260 Another special case: scrutinising a primitive-typed variable. No
261 evaluation required. We don't save volatile variables, nor do we do a
262 heap-check in the alternatives. Instead, the heap usage of the
263 alternatives is worst-cased and passed upstream. This can result in
264 allocating more heap than strictly necessary, but it will sometimes
265 eliminate a heap check altogether.
268 cgCase (StgApp v [] _) live_in_whole_case live_in_alts uniq (StgPrimAlts ty alts deflt)
269 = getArgAmode v `thenFC` \ amode ->
270 cgPrimAltsGivenScrutinee NoGC amode alts deflt
273 Special case: scrutinising a non-primitive variable.
274 This can be done a little better than the general case, because
275 we can reuse/trim the stack slot holding the variable (if it is in one).
278 cgCase (StgApp (StgVarArg fun) args _ {-lvs must be same as live_in_alts-})
279 live_in_whole_case live_in_alts uniq alts@(StgAlgAlts _ _ _)
281 getCAddrModeAndInfo fun `thenFC` \ (fun_amode, lf_info) ->
282 getArgAmodes args `thenFC` \ arg_amodes ->
284 -- Squish the environment
285 nukeDeadBindings live_in_alts `thenC`
286 saveVolatileVarsAndRegs live_in_alts
287 `thenFC` \ (save_assts, alts_eob_info, maybe_cc_slot) ->
289 forkEval alts_eob_info
290 nopC (cgEvalAlts maybe_cc_slot uniq alts) `thenFC` \ scrut_eob_info ->
291 setEndOfBlockInfo scrut_eob_info (
292 tailCallBusiness fun fun_amode lf_info arg_amodes live_in_alts save_assts
297 Finally, here is the general case.
300 cgCase expr live_in_whole_case live_in_alts uniq alts
301 = -- Figure out what volatile variables to save
302 nukeDeadBindings live_in_whole_case `thenC`
303 saveVolatileVarsAndRegs live_in_alts
304 `thenFC` \ (save_assts, alts_eob_info, maybe_cc_slot) ->
306 -- Save those variables right now!
307 absC save_assts `thenC`
309 forkEval alts_eob_info
310 (nukeDeadBindings live_in_alts)
311 (cgEvalAlts maybe_cc_slot uniq alts) `thenFC` \ scrut_eob_info ->
313 setEndOfBlockInfo scrut_eob_info (cgExpr expr)
316 %************************************************************************
318 \subsection[CgCase-primops]{Primitive applications}
320 %************************************************************************
322 Get result amodes for a primitive operation, in the case wher GC can't happen.
323 The amodes are returned in canonical order, ready for the prim-op!
325 Alg case: temporaries named as in the alternatives,
326 plus (CTemp u) for the tag (if needed)
329 This is all disgusting, because these amodes must be consistent with those
330 invented by CgAlgAlts.
333 getPrimAppResultAmodes
340 -- If there's an StgBindDefault which does use the bound
341 -- variable, then we can only handle it if the type involved is
342 -- an enumeration type. That's important in the case
348 -- The only reason for the restriction to *enumeration* types is our
349 -- inability to invent suitable temporaries to hold the results;
350 -- Elaborating the CTemp addr mode to have a second uniq field
351 -- (which would simply count from 1) would solve the problem.
352 -- Anyway, cgInlineAlts is now capable of handling all cases;
353 -- it's only this function which is being wimpish.
355 getPrimAppResultAmodes uniq (StgAlgAlts ty alts (StgBindDefault _ True {- used -} _))
356 | isEnumerationTyCon spec_tycon = [tag_amode]
357 | otherwise = panic "getPrimAppResultAmodes: non-enumeration algebraic alternatives with default"
359 -- A temporary variable to hold the tag; this is unaffected by GC because
360 -- the heap-checks in the branches occur after the switch
361 tag_amode = CTemp uniq IntRep
362 (spec_tycon, _, _) = splitAlgTyConApp ty
364 getPrimAppResultAmodes uniq (StgAlgAlts ty alts other_default)
365 -- Default is either StgNoDefault or StgBindDefault with unused binder
367 [_] -> arg_amodes -- No need for a tag
368 other -> tag_amode : arg_amodes
370 -- A temporary variable to hold the tag; this is unaffected by GC because
371 -- the heap-checks in the branches occur after the switch
372 tag_amode = CTemp uniq IntRep
374 -- Sort alternatives into canonical order; there must be a complete
375 -- set because there's no default case.
376 sorted_alts = sortLt lt alts
377 (con1,_,_,_) `lt` (con2,_,_,_) = dataConTag con1 < dataConTag con2
379 arg_amodes :: [CAddrMode]
381 -- Turn them into amodes
382 arg_amodes = concat (map mk_amodes sorted_alts)
383 mk_amodes (con, args, use_mask, rhs)
384 = [ CTemp (uniqueOf arg) (idPrimRep arg) | arg <- args ]
387 The situation is simpler for primitive
388 results, because there is only one!
391 getPrimAppResultAmodes uniq (StgPrimAlts ty _ _)
392 = [CTemp uniq (typePrimRep ty)]
396 %************************************************************************
398 \subsection[CgCase-alts]{Alternatives}
400 %************************************************************************
402 @cgEvalAlts@ returns an addressing mode for a continuation for the
403 alternatives of a @case@, used in a context when there
404 is some evaluation to be done.
407 cgEvalAlts :: Maybe VirtualSpBOffset -- Offset of cost-centre to be restored, if any
410 -> FCode Sequel -- Any addr modes inside are guaranteed to be a label
411 -- so that we can duplicate it without risk of
414 cgEvalAlts cc_slot uniq (StgAlgAlts ty alts deflt)
415 = -- Generate the instruction to restore cost centre, if any
416 restoreCurrentCostCentre cc_slot `thenFC` \ cc_restore ->
418 -- Generate sequel info for use downstream
419 -- At the moment, we only do it if the type is vector-returnable.
420 -- Reason: if not, then it costs extra to label the
421 -- alternatives, because we'd get return code like:
423 -- switch TagReg { 0 : JMP(alt_1); 1 : JMP(alt_2) ..etc }
425 -- which is worse than having the alt code in the switch statement
428 (spec_tycon, _, _) = splitAlgTyConApp ty
431 = case ctrlReturnConvAlg spec_tycon of
432 VectoredReturn _ -> True
436 = if not use_labelled_alts then
437 Nothing -- no semi-tagging info
439 cgSemiTaggedAlts uniq alts deflt -- Just <something>
441 cgAlgAlts GCMayHappen uniq cc_restore use_labelled_alts ty alts deflt True
442 `thenFC` \ (tagged_alt_absCs, deflt_absC) ->
444 mkReturnVector uniq ty tagged_alt_absCs deflt_absC `thenFC` \ return_vec ->
446 returnFC (CaseAlts return_vec semi_tagged_stuff)
448 cgEvalAlts cc_slot uniq (StgPrimAlts ty alts deflt)
449 = -- Generate the instruction to restore cost centre, if any
450 restoreCurrentCostCentre cc_slot `thenFC` \ cc_restore ->
452 -- Generate the switch
453 getAbsC (cgPrimAlts GCMayHappen uniq ty alts deflt) `thenFC` \ abs_c ->
455 -- Generate the labelled block, starting with restore-cost-centre
456 absC (CRetUnVector vtbl_label
457 (CLabelledCode return_label (cc_restore `mkAbsCStmts` abs_c)))
459 -- Return an amode for the block
460 returnFC (CaseAlts (CUnVecLbl return_label vtbl_label) Nothing{-no semi-tagging-})
462 vtbl_label = mkVecTblLabel uniq
463 return_label = mkReturnPtLabel uniq
468 cgInlineAlts :: GCFlag -> Unique
473 HWL comment on {\em GrAnSim\/} (adding GRAN_YIELDs for context switch): If
474 we do an inlining of the case no separate functions for returning are
475 created, so we don't have to generate a GRAN_YIELD in that case. This info
476 must be propagated to cgAlgAltRhs (where the GRAN_YIELD macro might be
477 emitted). Hence, the new Bool arg to cgAlgAltRhs.
479 First case: algebraic case, exactly one alternative, no default.
480 In this case the primitive op will not have set a temporary to the
481 tag, so we shouldn't generate a switch statment. Instead we just
485 cgInlineAlts gc_flag uniq (StgAlgAlts ty [alt@(con,args,use_mask,rhs)] StgNoDefault)
486 = cgAlgAltRhs gc_flag con args use_mask rhs False{-no yield macro if alt gets inlined-}
489 Second case: algebraic case, several alternatives.
490 Tag is held in a temporary.
493 cgInlineAlts gc_flag uniq (StgAlgAlts ty alts deflt)
494 = cgAlgAlts gc_flag uniq AbsCNop{-restore_cc-} False{-no semi-tagging-}
496 False{-don't emit yield-} `thenFC` \ (tagged_alts, deflt_c) ->
499 absC (mkAlgAltsCSwitch tag_amode tagged_alts deflt_c)
501 -- A temporary variable to hold the tag; this is unaffected by GC because
502 -- the heap-checks in the branches occur after the switch
503 tag_amode = CTemp uniq IntRep
506 Third (real) case: primitive result type.
509 cgInlineAlts gc_flag uniq (StgPrimAlts ty alts deflt)
510 = cgPrimAlts gc_flag uniq ty alts deflt
514 %************************************************************************
516 \subsection[CgCase-alg-alts]{Algebraic alternatives}
518 %************************************************************************
520 In @cgAlgAlts@, none of the binders in the alternatives are
521 assumed to be yet bound.
523 HWL comment on {\em GrAnSim\/} (adding GRAN_YIELDs for context switch): The
524 last arg of cgAlgAlts indicates if we want a context switch at the
525 beginning of each alternative. Normally we want that. The only exception
526 are inlined alternatives.
531 -> AbstractC -- Restore-cost-centre instruction
532 -> Bool -- True <=> branches must be labelled
533 -> Type -- From the case statement
534 -> [(Id, [Id], [Bool], StgExpr)] -- The alternatives
535 -> StgCaseDefault -- The default
536 -> Bool -- Context switch at alts?
537 -> FCode ([(ConTag, AbstractC)], -- The branches
538 AbstractC -- The default case
542 The case with a default which has a binder is different. We need to
543 pick all the constructors which aren't handled explicitly by an
544 alternative, and which return their results in registers, allocate
545 them explicitly in the heap, and jump to a join point for the default
548 OLD: All of this only works if a heap-check is required anyway, because
549 otherwise it isn't safe to allocate.
551 NEW (July 94): now false! It should work regardless of gc_flag,
552 because of the extra_branches argument now added to forkAlts.
554 We put a heap-check at the join point, for the benefit of constructors
555 which don't need to do allocation. This means that ones which do need
556 to allocate may end up doing two heap-checks; but that's just too bad.
557 (We'd need two join labels otherwise. ToDo.)
559 It's all pretty turgid anyway.
562 cgAlgAlts gc_flag uniq restore_cc semi_tagging
563 ty alts deflt@(StgBindDefault binder True{-used-} _)
564 emit_yield{-should a yield macro be emitted?-}
566 extra_branches :: [FCode (ConTag, AbstractC)]
567 extra_branches = catMaybes (map mk_extra_branch default_cons)
569 must_label_default = semi_tagging || not (null extra_branches)
571 forkAlts (map (cgAlgAlt gc_flag uniq restore_cc semi_tagging emit_yield) alts)
573 (cgAlgDefault gc_flag uniq restore_cc must_label_default deflt emit_yield)
576 default_join_lbl = mkDefaultLabel uniq
577 jump_instruction = CJump (CLbl default_join_lbl CodePtrRep)
579 (spec_tycon, _, spec_cons) = splitAlgTyConApp ty
581 alt_cons = [ con | (con,_,_,_) <- alts ]
583 default_cons = [ spec_con | spec_con <- spec_cons, -- In this type
584 spec_con `not_elem` alt_cons ] -- Not handled explicitly
586 not_elem = isn'tIn "cgAlgAlts"
588 -- (mk_extra_branch con) returns the a maybe for the extra branch for con.
589 -- The "maybe" is because con may return in heap, in which case there is
590 -- nothing to do. Otherwise, we have a special case for a nullary constructor,
591 -- but in the general case we do an allocation and heap-check.
593 mk_extra_branch :: DataCon -> (Maybe (FCode (ConTag, AbstractC)))
596 = ASSERT(isDataCon con)
597 case dataReturnConvAlg con of
598 ReturnInHeap -> Nothing
599 ReturnInRegs rs -> Just (getAbsC (alloc_code rs) `thenFC` \ abs_c ->
600 returnFC (tag, abs_c)
603 lf_info = mkConLFInfo con
606 -- alloc_code generates code to allocate constructor con, whose args are
607 -- in the arguments to alloc_code, assigning the result to Node.
608 alloc_code :: [MagicId] -> Code
611 = possibleHeapCheck gc_flag regs False (
612 buildDynCon binder useCurrentCostCentre con
613 (map CReg regs) (all zero_size regs)
615 idInfoToAmode PtrRep idinfo `thenFC` \ amode ->
617 absC (CAssign (CReg node) amode) `thenC`
618 absC jump_instruction
621 zero_size reg = getPrimRepSize (magicIdPrimRep reg) == 0
624 Now comes the general case
627 cgAlgAlts gc_flag uniq restore_cc must_label_branches ty alts deflt
628 {- The deflt is either StgNoDefault or a BindDefault which doesn't use the binder -}
629 emit_yield{-should a yield macro be emitted?-}
631 = forkAlts (map (cgAlgAlt gc_flag uniq restore_cc must_label_branches emit_yield) alts)
632 [{- No "extra branches" -}]
633 (cgAlgDefault gc_flag uniq restore_cc must_label_branches deflt emit_yield)
637 cgAlgDefault :: GCFlag
638 -> Unique -> AbstractC -> Bool -- turgid state...
639 -> StgCaseDefault -- input
641 -> FCode AbstractC -- output
643 cgAlgDefault gc_flag uniq restore_cc must_label_branch
647 cgAlgDefault gc_flag uniq restore_cc must_label_branch
648 (StgBindDefault _ False{-binder not used-} rhs)
649 emit_yield{-should a yield macro be emitted?-}
651 = getAbsC (absC restore_cc `thenC`
653 emit_gran_macros = opt_GranMacros
655 (if emit_gran_macros && emit_yield
657 else absC AbsCNop) `thenC`
658 -- liveness same as in possibleHeapCheck below
659 possibleHeapCheck gc_flag [] False (cgExpr rhs)) `thenFC` \ abs_c ->
661 final_abs_c | must_label_branch = CJump (CLabelledCode lbl abs_c)
666 lbl = mkDefaultLabel uniq
669 cgAlgDefault gc_flag uniq restore_cc must_label_branch
670 (StgBindDefault binder True{-binder used-} rhs)
671 emit_yield{-should a yield macro be emitted?-}
673 = -- We have arranged that Node points to the thing, even
674 -- even if we return in registers
675 bindNewToReg binder node mkLFArgument `thenC`
676 getAbsC (absC restore_cc `thenC`
678 emit_gran_macros = opt_GranMacros
680 (if emit_gran_macros && emit_yield
681 then yield [node] False
682 else absC AbsCNop) `thenC`
683 -- liveness same as in possibleHeapCheck below
684 possibleHeapCheck gc_flag [node] False (cgExpr rhs)
685 -- Node is live, but doesn't need to point at the thing itself;
686 -- it's ok for Node to point to an indirection or FETCH_ME
687 -- Hence no need to re-enter Node.
688 ) `thenFC` \ abs_c ->
691 final_abs_c | must_label_branch = CJump (CLabelledCode lbl abs_c)
696 lbl = mkDefaultLabel uniq
698 -- HWL comment on GrAnSim: GRAN_YIELDs needed; emitted in cgAlgAltRhs
701 -> Unique -> AbstractC -> Bool -- turgid state
702 -> Bool -- Context switch at alts?
703 -> (Id, [Id], [Bool], StgExpr)
704 -> FCode (ConTag, AbstractC)
706 cgAlgAlt gc_flag uniq restore_cc must_label_branch
707 emit_yield{-should a yield macro be emitted?-}
708 (con, args, use_mask, rhs)
709 = getAbsC (absC restore_cc `thenC`
710 cgAlgAltRhs gc_flag con args use_mask rhs
712 ) `thenFC` \ abs_c ->
714 final_abs_c | must_label_branch = CJump (CLabelledCode lbl abs_c)
717 returnFC (tag, final_abs_c)
720 lbl = mkAltLabel uniq tag
722 cgAlgAltRhs :: GCFlag
727 -> Bool -- context switch?
729 cgAlgAltRhs gc_flag con args use_mask rhs emit_yield
731 (live_regs, node_reqd)
732 = case (dataReturnConvAlg con) of
733 ReturnInHeap -> ([], True)
734 ReturnInRegs regs -> ([reg | (reg,True) <- zipEqual "cgAlgAltRhs" regs use_mask], False)
735 -- Pick the live registers using the use_mask
736 -- Doing so is IMPORTANT, because with semi-tagging
737 -- enabled only the live registers will have valid
741 emit_gran_macros = opt_GranMacros
743 (if emit_gran_macros && emit_yield
744 then yield live_regs node_reqd
745 else absC AbsCNop) `thenC`
746 -- liveness same as in possibleHeapCheck below
747 possibleHeapCheck gc_flag live_regs node_reqd (
749 NoGC -> mapFCs bindNewToTemp args `thenFC` \ _ ->
751 GCMayHappen -> bindConArgs con args
757 %************************************************************************
759 \subsection[CgCase-semi-tagged-alts]{The code to deal with sem-tagging}
761 %************************************************************************
763 Turgid-but-non-monadic code to conjure up the required info from
764 algebraic case alternatives for semi-tagging.
767 cgSemiTaggedAlts :: Unique
768 -> [(Id, [Id], [Bool], StgExpr)]
769 -> GenStgCaseDefault Id Id
772 cgSemiTaggedAlts uniq alts deflt
773 = Just (map st_alt alts, st_deflt deflt)
775 st_deflt StgNoDefault = Nothing
777 st_deflt (StgBindDefault binder binder_used _)
778 = Just (if binder_used then Just binder else Nothing,
779 (CCallProfCtrMacro SLIT("RET_SEMI_BY_DEFAULT") [], -- ToDo: monadise?
783 st_alt (con, args, use_mask, _)
784 = case (dataReturnConvAlg con) of
787 -- Ha! Nothing to do; Node already points to the thing
789 (CCallProfCtrMacro SLIT("RET_SEMI_IN_HEAP") -- ToDo: monadise?
790 [mkIntCLit (length args)], -- how big the thing in the heap is
795 -- We have to load the live registers from the constructor
796 -- pointed to by Node.
798 (_, regs_w_offsets) = layOutDynCon con magicIdPrimRep regs
800 used_regs = selectByMask use_mask regs
802 used_regs_w_offsets = [ ro | ro@(reg,offset) <- regs_w_offsets,
803 reg `is_elem` used_regs]
805 is_elem = isIn "cgSemiTaggedAlts"
809 CCallProfCtrMacro SLIT("RET_SEMI_IN_REGS") -- ToDo: macroise?
810 [mkIntCLit (length regs_w_offsets),
811 mkIntCLit (length used_regs_w_offsets)],
812 CSimultaneous (mkAbstractCs (map move_to_reg used_regs_w_offsets))],
815 con_tag = dataConTag con
816 join_label = mkAltLabel uniq con_tag
818 move_to_reg :: (MagicId, VirtualHeapOffset {-from Node-}) -> AbstractC
819 move_to_reg (reg, offset)
820 = CAssign (CReg reg) (CVal (NodeRel offset) (magicIdPrimRep reg))
823 %************************************************************************
825 \subsection[CgCase-prim-alts]{Primitive alternatives}
827 %************************************************************************
829 @cgPrimAlts@ generates a suitable @CSwitch@ for dealing with the
830 alternatives of a primitive @case@, given an addressing mode for the
831 thing to scrutinise. It also keeps track of the maximum stack depth
832 encountered down any branch.
834 As usual, no binders in the alternatives are yet bound.
840 -> [(Literal, StgExpr)] -- Alternatives
841 -> StgCaseDefault -- Default
844 cgPrimAlts gc_flag uniq ty alts deflt
845 = cgPrimAltsGivenScrutinee gc_flag scrutinee alts deflt
847 -- A temporary variable, or standard register, to hold the result
848 scrutinee = case gc_flag of
849 NoGC -> CTemp uniq kind
850 GCMayHappen -> CReg (dataReturnConvPrim kind)
852 kind = typePrimRep ty
855 cgPrimAltsGivenScrutinee gc_flag scrutinee alts deflt
856 = forkAlts (map (cgPrimAlt gc_flag) alts)
857 [{- No "extra branches" -}]
858 (cgPrimDefault gc_flag scrutinee deflt) `thenFC` \ (alt_absCs, deflt_absC) ->
859 absC (CSwitch scrutinee alt_absCs deflt_absC)
860 -- CSwitch does sensible things with one or zero alternatives
864 -> (Literal, StgExpr) -- The alternative
865 -> FCode (Literal, AbstractC) -- Its compiled form
867 cgPrimAlt gc_flag (lit, rhs)
868 = getAbsC rhs_code `thenFC` \ absC ->
871 rhs_code = possibleHeapCheck gc_flag [] False (cgExpr rhs )
873 cgPrimDefault :: GCFlag
874 -> CAddrMode -- Scrutinee
878 cgPrimDefault gc_flag scrutinee StgNoDefault
879 = panic "cgPrimDefault: No default in prim case"
881 cgPrimDefault gc_flag scrutinee (StgBindDefault _ False{-binder not used-} rhs)
882 = getAbsC (possibleHeapCheck gc_flag [] False (cgExpr rhs ))
884 cgPrimDefault gc_flag scrutinee (StgBindDefault binder True{-used-} rhs)
885 = getAbsC (possibleHeapCheck gc_flag regs False rhs_code)
887 regs = if isFollowableRep (getAmodeRep scrutinee) then
890 rhs_code = bindNewPrimToAmode binder scrutinee `thenC`
895 %************************************************************************
897 \subsection[CgCase-tidy]{Code for tidying up prior to an eval}
899 %************************************************************************
902 saveVolatileVarsAndRegs
903 :: StgLiveVars -- Vars which should be made safe
904 -> FCode (AbstractC, -- Assignments to do the saves
905 EndOfBlockInfo, -- New sequel, recording where the return
907 Maybe VirtualSpBOffset) -- Slot for current cost centre
910 saveVolatileVarsAndRegs vars
911 = saveVolatileVars vars `thenFC` \ var_saves ->
912 saveCurrentCostCentre `thenFC` \ (maybe_cc_slot, cc_save) ->
913 saveReturnAddress `thenFC` \ (new_eob_info, ret_save) ->
914 returnFC (mkAbstractCs [var_saves, cc_save, ret_save],
919 saveVolatileVars :: StgLiveVars -- Vars which should be made safe
920 -> FCode AbstractC -- Assignments to to the saves
922 saveVolatileVars vars
923 = save_em (idSetToList vars)
925 save_em [] = returnFC AbsCNop
928 = getCAddrModeIfVolatile var `thenFC` \ v ->
930 Nothing -> save_em vars -- Non-volatile, so carry on
933 Just vol_amode -> -- Aha! It's volatile
934 save_var var vol_amode `thenFC` \ abs_c ->
935 save_em vars `thenFC` \ abs_cs ->
936 returnFC (abs_c `mkAbsCStmts` abs_cs)
938 save_var var vol_amode
939 | isFollowableRep kind
940 = allocAStack `thenFC` \ a_slot ->
941 rebindToAStack var a_slot `thenC`
942 getSpARelOffset a_slot `thenFC` \ spa_rel ->
943 returnFC (CAssign (CVal spa_rel kind) vol_amode)
945 = allocBStack (getPrimRepSize kind) `thenFC` \ b_slot ->
946 rebindToBStack var b_slot `thenC`
947 getSpBRelOffset b_slot `thenFC` \ spb_rel ->
948 returnFC (CAssign (CVal spb_rel kind) vol_amode)
950 kind = getAmodeRep vol_amode
952 saveReturnAddress :: FCode (EndOfBlockInfo, AbstractC)
954 = getEndOfBlockInfo `thenFC` \ eob_info@(EndOfBlockInfo vA vB sequel) ->
956 -- See if it is volatile
958 InRetReg -> -- Yes, it's volatile
959 allocBStack retPrimRepSize `thenFC` \ b_slot ->
960 getSpBRelOffset b_slot `thenFC` \ spb_rel ->
962 returnFC (EndOfBlockInfo vA vB (OnStack b_slot),
963 CAssign (CVal spb_rel RetRep) (CReg RetReg))
965 UpdateCode _ -> -- It's non-volatile all right, but we still need
966 -- to allocate a B-stack slot for it, *solely* to make
967 -- sure that update frames for different values do not
968 -- appear adjacent on the B stack. This makes sure
969 -- that B-stack squeezing works ok.
971 allocBStack retPrimRepSize `thenFC` \ b_slot ->
972 returnFC (eob_info, AbsCNop)
974 other -> -- No, it's non-volatile, so do nothing
975 returnFC (eob_info, AbsCNop)
978 Note about B-stack squeezing. Consider the following:`
980 y = [...] \u [] -> ...
981 x = [y] \u [] -> case y of (a,b) -> a
983 The code for x will push an update frame, and then enter y. The code
984 for y will push another update frame. If the B-stack-squeezer then
985 wakes up, it will see two update frames right on top of each other,
986 and will combine them. This is WRONG, of course, because x's value is
989 The fix implemented above makes sure that we allocate an (unused)
990 B-stack slot before entering y. You can think of this as holding the
991 saved value of RetAddr, which (after pushing x's update frame will be
992 some update code ptr). The compiler is clever enough to load the
993 static update code ptr into RetAddr before entering ~a~, but the slot
994 is still there to separate the update frames.
996 When we save the current cost centre (which is done for lexical
997 scoping), we allocate a free B-stack location, and return (a)~the
998 virtual offset of the location, to pass on to the alternatives, and
999 (b)~the assignment to do the save (just as for @saveVolatileVars@).
1002 saveCurrentCostCentre ::
1003 FCode (Maybe VirtualSpBOffset, -- Where we decide to store it
1004 -- Nothing if not lexical CCs
1005 AbstractC) -- Assignment to save it
1006 -- AbsCNop if not lexical CCs
1008 saveCurrentCostCentre
1010 doing_profiling = opt_SccProfilingOn
1012 if not doing_profiling then
1013 returnFC (Nothing, AbsCNop)
1015 allocBStack (getPrimRepSize CostCentreRep) `thenFC` \ b_slot ->
1016 getSpBRelOffset b_slot `thenFC` \ spb_rel ->
1017 returnFC (Just b_slot,
1018 CAssign (CVal spb_rel CostCentreRep) (CReg CurCostCentre))
1020 restoreCurrentCostCentre :: Maybe VirtualSpBOffset -> FCode AbstractC
1022 restoreCurrentCostCentre Nothing
1024 restoreCurrentCostCentre (Just b_slot)
1025 = getSpBRelOffset b_slot `thenFC` \ spb_rel ->
1026 freeBStkSlot b_slot `thenC`
1027 returnFC (CCallProfCCMacro SLIT("RESTORE_CCC") [CVal spb_rel CostCentreRep])
1028 -- we use the RESTORE_CCC macro, rather than just
1029 -- assigning into CurCostCentre, in case RESTORE_CCC
1030 -- has some sanity-checking in it.
1034 %************************************************************************
1036 \subsection[CgCase-return-vec]{Building a return vector}
1038 %************************************************************************
1040 Build a return vector, and return a suitable label addressing
1044 mkReturnVector :: Unique
1046 -> [(ConTag, AbstractC)] -- Branch codes
1047 -> AbstractC -- Default case
1050 mkReturnVector uniq ty tagged_alt_absCs deflt_absC
1052 (return_vec_amode, vtbl_body) = case (ctrlReturnConvAlg tycon) of {
1054 UnvectoredReturn _ ->
1055 (CUnVecLbl ret_label vtbl_label,
1056 absC (CRetUnVector vtbl_label
1057 (CLabelledCode ret_label
1058 (mkAlgAltsCSwitch (CReg TagReg)
1061 VectoredReturn table_size ->
1062 (CLbl vtbl_label DataPtrRep,
1063 absC (CRetVector vtbl_label
1064 -- must restore cc before each alt, if required
1065 (map mk_vector_entry [fIRST_TAG .. (table_size+fIRST_TAG-1)])
1068 -- Leave nops and comments in for now; they are eliminated
1069 -- lazily as it's printed.
1070 -- (case (nonemptyAbsC deflt_absC) of
1071 -- Nothing -> AbsCNop
1076 returnFC return_vec_amode
1080 (tycon,_,_) = case splitAlgTyConApp_maybe ty of -- *must* be a real "data" type constructor
1082 Nothing -> pprPanic "ERROR: can't generate code for polymorphic case"
1083 (vcat [text "probably a mis-use of `seq' or `par';",
1084 text "the User's Guide has more details.",
1085 text "Offending type:" <+> ppr ty
1088 vtbl_label = mkVecTblLabel uniq
1089 ret_label = mkReturnPtLabel uniq
1091 mk_vector_entry :: ConTag -> Maybe CAddrMode
1093 = case [ absC | (t, absC) <- tagged_alt_absCs, t == tag ] of
1095 [absC] -> Just (CCode absC)
1096 _ -> panic "mkReturnVector: too many"
1099 %************************************************************************
1101 \subsection[CgCase-utils]{Utilities for handling case expressions}
1103 %************************************************************************
1105 @possibleHeapCheck@ tests a flag passed in to decide whether to
1106 do a heap check or not.
1109 possibleHeapCheck :: GCFlag -> [MagicId] -> Bool -> Code -> Code
1111 possibleHeapCheck GCMayHappen regs node_reqd code = heapCheck regs node_reqd code
1112 possibleHeapCheck NoGC _ _ code = code
1115 Select a restricted set of registers based on a usage mask.
1118 selectByMask [] [] = []
1119 selectByMask (True:ms) (x:xs) = x : selectByMask ms xs
1120 selectByMask (False:ms) (x:xs) = selectByMask ms xs