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, toplevelishId,
50 dataConTag, fIRST_TAG, ConTag,
52 idSetToList, GenId{-instance Uniquable,Eq-}, Id
54 import Literal ( Literal )
55 import Maybes ( catMaybes )
56 import PprType ( GenType{-instance Outputable-} )
57 import PrimOp ( primOpCanTriggerGC, PrimOp(..),
58 primOpStackRequired, StackRequirement(..)
60 import PrimRep ( getPrimRepSize, isFollowableRep, retPrimRepSize,
63 import TyCon ( isEnumerationTyCon )
64 import Type ( typePrimRep,
65 splitAlgTyConApp, splitAlgTyConApp_maybe,
68 import Unique ( Unique, Uniquable(..) )
69 import Util ( sortLt, isIn, isn'tIn, zipEqual )
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!}:
106 {\em May} save a heap overflow test,
107 if ...A... allocates anything. The other advantage
108 of this is that we can use relative addressing
109 from a single Hp to get at all the closures so allocated.
111 No need to save volatile vars etc across the case
118 May do more allocation than reqd. This sometimes bites us
119 badly. For example, nfib (ha!) allocates about 30\% more space if the
120 worst-casing is done, because many many calls to nfib are leaf calls
121 which don't need to allocate anything.
123 This never hurts us if there is only one alternative.
127 *** NOT YET DONE *** The difficulty is that \tr{!B!}, \tr{!C!} need
128 to take account of what is live, and that includes all live volatile
129 variables, even if they also have stable analogues. Furthermore, the
130 stack pointers must be lined up properly so that GC sees tidy stacks.
131 If these things are done, then the heap checks can be done at \tr{!B!} and
132 \tr{!C!} without a full save-volatile-vars sequence.
143 Several special cases for primitive operations.
145 ******* TO DO TO DO: fix what follows
149 case (op x1 ... xn) of
152 where the type of the case scrutinee is a multi-constuctor algebraic type.
153 Then we simply compile code for
161 case (op x1 ... xn) of
165 where the type of the case scrutinee is a multi-constuctor algebraic type.
166 we just bomb out at the moment. It never happens in practice.
168 **** END OF TO DO TO DO
171 cgCase scrut@(StgPrim op args _) live_in_whole_case live_in_alts uniq
172 (StgAlgAlts _ alts (StgBindDefault id _ deflt_rhs))
173 = if not (null alts) then
174 panic "cgCase: case on PrimOp with default *and* alts\n"
175 -- For now, die if alts are non-empty
177 cgExpr (StgLet (StgNonRec id scrut_rhs) deflt_rhs)
179 scrut_rhs = StgRhsClosure useCurrentCostCentre stgArgOcc{-safe-} scrut_free_vars
181 scrut_free_vars = [ fv | StgVarArg fv <- args, not (toplevelishId fv) ]
187 cgCase (StgPrim op args _) live_in_whole_case live_in_alts uniq alts
188 | not (primOpCanTriggerGC op)
190 -- Get amodes for the arguments and results
191 getPrimOpArgAmodes op args `thenFC` \ arg_amodes ->
193 result_amodes = getPrimAppResultAmodes uniq alts
194 liveness_mask = panic "cgCase: liveness of non-GC-ing primop touched\n"
196 -- Perform the operation
197 getVolatileRegs live_in_alts `thenFC` \ vol_regs ->
199 -- seq cannot happen here => no additional B Stack alloc
201 absC (COpStmt result_amodes op
202 arg_amodes -- note: no liveness arg
203 liveness_mask vol_regs) `thenC`
205 -- Scrutinise the result
206 cgInlineAlts NoGC uniq alts
208 | otherwise -- *Can* trigger GC
209 = getPrimOpArgAmodes op args `thenFC` \ arg_amodes ->
211 -- Get amodes for the arguments and results, and assign to regs
212 -- (Can-trigger-gc primops guarantee to have their (nonRobust)
215 op_result_regs = assignPrimOpResultRegs op
217 op_result_amodes = map CReg op_result_regs
219 (op_arg_amodes, liveness_mask, arg_assts)
220 = makePrimOpArgsRobust op arg_amodes
222 liveness_arg = mkIntCLit liveness_mask
224 -- Tidy up in case GC happens...
226 -- Nota Bene the use of live_in_whole_case in nukeDeadBindings.
227 -- Reason: the arg_assts computed above may refer to some stack slots
228 -- which are not live in the alts. So we mustn't use those slots
229 -- to save volatile vars in!
230 nukeDeadBindings live_in_whole_case `thenC`
231 saveVolatileVars live_in_alts `thenFC` \ volatile_var_save_assts ->
233 -- Allocate stack words for the prim-op itself,
234 -- these are guaranteed to be ON TOP OF the stack.
235 -- Currently this is used *only* by the seq# primitive op.
237 (a_req,b_req) = case (primOpStackRequired op) of
238 NoStackRequired -> (0, 0)
239 FixedStackRequired a b -> (a, b)
240 VariableStackRequired -> (0, 0) -- i.e. don't care
242 allocAStackTop a_req `thenFC` \ a_slot ->
243 allocBStackTop b_req `thenFC` \ b_slot ->
245 getEndOfBlockInfo `thenFC` \ eob_info@(EndOfBlockInfo args_spa args_spb sequel) ->
246 -- a_req and b_req allocate stack space that is taken care of by the
247 -- macros generated for the primops; thus, we there is no need to adjust
248 -- this part of the stacks later on (=> +a_req in EndOfBlockInfo)
249 -- currently all this is only used for SeqOp
250 forkEval (if True {- a_req==0 && b_req==0 -}
252 else (EndOfBlockInfo (args_spa+a_req)
253 (args_spb+b_req) sequel)) nopC
255 getAbsC (cgInlineAlts GCMayHappen uniq alts) `thenFC` \ abs_c ->
256 absC (CRetUnVector vtbl_label (CLabelledCode return_label abs_c))
258 returnFC (CaseAlts (CUnVecLbl return_label vtbl_label)
259 Nothing{-no semi-tagging-}))
260 `thenFC` \ new_eob_info ->
262 -- Record the continuation info
263 setEndOfBlockInfo new_eob_info (
265 -- Now "return" to the inline alternatives; this will get
266 -- compiled to a fall-through.
268 simultaneous_assts = arg_assts `mkAbsCStmts` volatile_var_save_assts
270 -- do_op_and_continue will be passed an amode for the continuation
271 do_op_and_continue sequel
272 = absC (COpStmt op_result_amodes
274 (pin_liveness op liveness_arg op_arg_amodes)
279 sequelToAmode sequel `thenFC` \ dest_amode ->
280 absC (CReturn dest_amode DirectReturn)
282 -- Note: we CJump even for algebraic data types,
283 -- because cgInlineAlts always generates code, never a
286 performReturn simultaneous_assts do_op_and_continue live_in_alts
289 -- for all PrimOps except ccalls, we pin the liveness info
290 -- on as the first "argument"
291 -- ToDo: un-duplicate?
293 pin_liveness (CCallOp _ _ _ _ _) _ args = args
294 pin_liveness other_op liveness_arg args
297 vtbl_label = mkVecTblLabel uniq
298 return_label = mkReturnPtLabel uniq
302 Another special case: scrutinising a primitive-typed variable. No
303 evaluation required. We don't save volatile variables, nor do we do a
304 heap-check in the alternatives. Instead, the heap usage of the
305 alternatives is worst-cased and passed upstream. This can result in
306 allocating more heap than strictly necessary, but it will sometimes
307 eliminate a heap check altogether.
310 cgCase (StgApp v [] _) live_in_whole_case live_in_alts uniq (StgPrimAlts ty alts deflt)
311 = getArgAmode v `thenFC` \ amode ->
312 cgPrimAltsGivenScrutinee NoGC amode alts deflt
315 Special case: scrutinising a non-primitive variable.
316 This can be done a little better than the general case, because
317 we can reuse/trim the stack slot holding the variable (if it is in one).
320 cgCase (StgApp (StgVarArg fun) args _ {-lvs must be same as live_in_alts-})
321 live_in_whole_case live_in_alts uniq alts@(StgAlgAlts _ _ _)
323 getCAddrModeAndInfo fun `thenFC` \ (fun_amode, lf_info) ->
324 getArgAmodes args `thenFC` \ arg_amodes ->
326 -- Squish the environment
327 nukeDeadBindings live_in_alts `thenC`
328 saveVolatileVarsAndRegs live_in_alts
329 `thenFC` \ (save_assts, alts_eob_info, maybe_cc_slot) ->
331 forkEval alts_eob_info
332 nopC (cgEvalAlts maybe_cc_slot uniq alts) `thenFC` \ scrut_eob_info ->
333 setEndOfBlockInfo scrut_eob_info (
334 tailCallBusiness fun fun_amode lf_info arg_amodes live_in_alts save_assts
339 Finally, here is the general case.
342 cgCase expr live_in_whole_case live_in_alts uniq alts
343 = -- Figure out what volatile variables to save
344 nukeDeadBindings live_in_whole_case `thenC`
345 saveVolatileVarsAndRegs live_in_alts
346 `thenFC` \ (save_assts, alts_eob_info, maybe_cc_slot) ->
348 -- Save those variables right now!
349 absC save_assts `thenC`
351 forkEval alts_eob_info
352 (nukeDeadBindings live_in_alts)
353 (cgEvalAlts maybe_cc_slot uniq alts) `thenFC` \ scrut_eob_info ->
355 setEndOfBlockInfo scrut_eob_info (cgExpr expr)
358 %************************************************************************
360 \subsection[CgCase-primops]{Primitive applications}
362 %************************************************************************
364 Get result amodes for a primitive operation, in the case wher GC can't happen.
365 The amodes are returned in canonical order, ready for the prim-op!
367 Alg case: temporaries named as in the alternatives,
368 plus (CTemp u) for the tag (if needed)
371 This is all disgusting, because these amodes must be consistent with those
372 invented by CgAlgAlts.
375 getPrimAppResultAmodes
382 -- If there's an StgBindDefault which does use the bound
383 -- variable, then we can only handle it if the type involved is
384 -- an enumeration type. That's important in the case
390 -- The only reason for the restriction to *enumeration* types is our
391 -- inability to invent suitable temporaries to hold the results;
392 -- Elaborating the CTemp addr mode to have a second uniq field
393 -- (which would simply count from 1) would solve the problem.
394 -- Anyway, cgInlineAlts is now capable of handling all cases;
395 -- it's only this function which is being wimpish.
397 getPrimAppResultAmodes uniq (StgAlgAlts ty alts (StgBindDefault _ True {- used -} _))
398 | isEnumerationTyCon spec_tycon = [tag_amode]
399 | otherwise = panic "getPrimAppResultAmodes: non-enumeration algebraic alternatives with default"
401 -- A temporary variable to hold the tag; this is unaffected by GC because
402 -- the heap-checks in the branches occur after the switch
403 tag_amode = CTemp uniq IntRep
404 (spec_tycon, _, _) = splitAlgTyConApp ty
406 getPrimAppResultAmodes uniq (StgAlgAlts ty alts other_default)
407 -- Default is either StgNoDefault or StgBindDefault with unused binder
409 [_] -> arg_amodes -- No need for a tag
410 other -> tag_amode : arg_amodes
412 -- A temporary variable to hold the tag; this is unaffected by GC because
413 -- the heap-checks in the branches occur after the switch
414 tag_amode = CTemp uniq IntRep
416 -- Sort alternatives into canonical order; there must be a complete
417 -- set because there's no default case.
418 sorted_alts = sortLt lt alts
419 (con1,_,_,_) `lt` (con2,_,_,_) = dataConTag con1 < dataConTag con2
421 arg_amodes :: [CAddrMode]
423 -- Turn them into amodes
424 arg_amodes = concat (map mk_amodes sorted_alts)
425 mk_amodes (con, args, use_mask, rhs)
426 = [ CTemp (uniqueOf arg) (idPrimRep arg) | arg <- args ]
429 The situation is simpler for primitive
430 results, because there is only one!
433 getPrimAppResultAmodes uniq (StgPrimAlts ty _ _)
434 = [CTemp uniq (typePrimRep ty)]
438 %************************************************************************
440 \subsection[CgCase-alts]{Alternatives}
442 %************************************************************************
444 @cgEvalAlts@ returns an addressing mode for a continuation for the
445 alternatives of a @case@, used in a context when there
446 is some evaluation to be done.
449 cgEvalAlts :: Maybe VirtualSpBOffset -- Offset of cost-centre to be restored, if any
452 -> FCode Sequel -- Any addr modes inside are guaranteed to be a label
453 -- so that we can duplicate it without risk of
456 cgEvalAlts cc_slot uniq (StgAlgAlts ty alts deflt)
457 = -- Generate the instruction to restore cost centre, if any
458 restoreCurrentCostCentre cc_slot `thenFC` \ cc_restore ->
460 -- Generate sequel info for use downstream
461 -- At the moment, we only do it if the type is vector-returnable.
462 -- Reason: if not, then it costs extra to label the
463 -- alternatives, because we'd get return code like:
465 -- switch TagReg { 0 : JMP(alt_1); 1 : JMP(alt_2) ..etc }
467 -- which is worse than having the alt code in the switch statement
470 (spec_tycon, _, _) = splitAlgTyConApp ty
473 = case ctrlReturnConvAlg spec_tycon of
474 VectoredReturn _ -> True
478 = if not use_labelled_alts then
479 Nothing -- no semi-tagging info
481 cgSemiTaggedAlts uniq alts deflt -- Just <something>
483 cgAlgAlts GCMayHappen uniq cc_restore use_labelled_alts ty alts deflt True
484 `thenFC` \ (tagged_alt_absCs, deflt_absC) ->
486 mkReturnVector uniq ty tagged_alt_absCs deflt_absC `thenFC` \ return_vec ->
488 returnFC (CaseAlts return_vec semi_tagged_stuff)
490 cgEvalAlts cc_slot uniq (StgPrimAlts ty alts deflt)
491 = -- Generate the instruction to restore cost centre, if any
492 restoreCurrentCostCentre cc_slot `thenFC` \ cc_restore ->
494 -- Generate the switch
495 getAbsC (cgPrimAlts GCMayHappen uniq ty alts deflt) `thenFC` \ abs_c ->
497 -- Generate the labelled block, starting with restore-cost-centre
498 absC (CRetUnVector vtbl_label
499 (CLabelledCode return_label (cc_restore `mkAbsCStmts` abs_c)))
501 -- Return an amode for the block
502 returnFC (CaseAlts (CUnVecLbl return_label vtbl_label) Nothing{-no semi-tagging-})
504 vtbl_label = mkVecTblLabel uniq
505 return_label = mkReturnPtLabel uniq
510 cgInlineAlts :: GCFlag -> Unique
515 HWL comment on {\em GrAnSim\/} (adding GRAN_YIELDs for context switch): If
516 we do an inlining of the case no separate functions for returning are
517 created, so we don't have to generate a GRAN_YIELD in that case. This info
518 must be propagated to cgAlgAltRhs (where the GRAN_YIELD macro might be
519 emitted). Hence, the new Bool arg to cgAlgAltRhs.
521 First case: algebraic case, exactly one alternative, no default.
522 In this case the primitive op will not have set a temporary to the
523 tag, so we shouldn't generate a switch statment. Instead we just
527 cgInlineAlts gc_flag uniq (StgAlgAlts ty [alt@(con,args,use_mask,rhs)] StgNoDefault)
528 = cgAlgAltRhs gc_flag con args use_mask rhs False{-no yield macro if alt gets inlined-}
531 Second case: algebraic case, several alternatives.
532 Tag is held in a temporary.
535 cgInlineAlts gc_flag uniq (StgAlgAlts ty alts deflt)
536 = cgAlgAlts gc_flag uniq AbsCNop{-restore_cc-} False{-no semi-tagging-}
538 False{-don't emit yield-} `thenFC` \ (tagged_alts, deflt_c) ->
541 absC (mkAlgAltsCSwitch tag_amode tagged_alts deflt_c)
543 -- A temporary variable to hold the tag; this is unaffected by GC because
544 -- the heap-checks in the branches occur after the switch
545 tag_amode = CTemp uniq IntRep
548 Third (real) case: primitive result type.
551 cgInlineAlts gc_flag uniq (StgPrimAlts ty alts deflt)
552 = cgPrimAlts gc_flag uniq ty alts deflt
556 %************************************************************************
558 \subsection[CgCase-alg-alts]{Algebraic alternatives}
560 %************************************************************************
562 In @cgAlgAlts@, none of the binders in the alternatives are
563 assumed to be yet bound.
565 HWL comment on {\em GrAnSim\/} (adding GRAN_YIELDs for context switch): The
566 last arg of cgAlgAlts indicates if we want a context switch at the
567 beginning of each alternative. Normally we want that. The only exception
568 are inlined alternatives.
573 -> AbstractC -- Restore-cost-centre instruction
574 -> Bool -- True <=> branches must be labelled
575 -> Type -- From the case statement
576 -> [(Id, [Id], [Bool], StgExpr)] -- The alternatives
577 -> StgCaseDefault -- The default
578 -> Bool -- Context switch at alts?
579 -> FCode ([(ConTag, AbstractC)], -- The branches
580 AbstractC -- The default case
584 The case with a default which has a binder is different. We need to
585 pick all the constructors which aren't handled explicitly by an
586 alternative, and which return their results in registers, allocate
587 them explicitly in the heap, and jump to a join point for the default
590 OLD: All of this only works if a heap-check is required anyway, because
591 otherwise it isn't safe to allocate.
593 NEW (July 94): now false! It should work regardless of gc_flag,
594 because of the extra_branches argument now added to forkAlts.
596 We put a heap-check at the join point, for the benefit of constructors
597 which don't need to do allocation. This means that ones which do need
598 to allocate may end up doing two heap-checks; but that's just too bad.
599 (We'd need two join labels otherwise. ToDo.)
601 It's all pretty turgid anyway.
604 cgAlgAlts gc_flag uniq restore_cc semi_tagging
605 ty alts deflt@(StgBindDefault binder True{-used-} _)
606 emit_yield{-should a yield macro be emitted?-}
608 extra_branches :: [FCode (ConTag, AbstractC)]
609 extra_branches = catMaybes (map mk_extra_branch default_cons)
611 must_label_default = semi_tagging || not (null extra_branches)
613 forkAlts (map (cgAlgAlt gc_flag uniq restore_cc semi_tagging emit_yield) alts)
615 (cgAlgDefault gc_flag uniq restore_cc must_label_default deflt emit_yield)
618 default_join_lbl = mkDefaultLabel uniq
619 jump_instruction = CJump (CLbl default_join_lbl CodePtrRep)
621 (spec_tycon, _, spec_cons) = splitAlgTyConApp ty
623 alt_cons = [ con | (con,_,_,_) <- alts ]
625 default_cons = [ spec_con | spec_con <- spec_cons, -- In this type
626 spec_con `not_elem` alt_cons ] -- Not handled explicitly
628 not_elem = isn'tIn "cgAlgAlts"
630 -- (mk_extra_branch con) returns the a maybe for the extra branch for con.
631 -- The "maybe" is because con may return in heap, in which case there is
632 -- nothing to do. Otherwise, we have a special case for a nullary constructor,
633 -- but in the general case we do an allocation and heap-check.
635 mk_extra_branch :: DataCon -> (Maybe (FCode (ConTag, AbstractC)))
638 = ASSERT(isDataCon con)
639 case dataReturnConvAlg con of
640 ReturnInHeap -> Nothing
641 ReturnInRegs rs -> Just (getAbsC (alloc_code rs) `thenFC` \ abs_c ->
642 returnFC (tag, abs_c)
645 lf_info = mkConLFInfo con
648 -- alloc_code generates code to allocate constructor con, whose args are
649 -- in the arguments to alloc_code, assigning the result to Node.
650 alloc_code :: [MagicId] -> Code
653 = possibleHeapCheck gc_flag regs False (
654 buildDynCon binder useCurrentCostCentre con
655 (map CReg regs) (all zero_size regs)
657 idInfoToAmode PtrRep idinfo `thenFC` \ amode ->
659 absC (CAssign (CReg node) amode) `thenC`
660 absC jump_instruction
663 zero_size reg = getPrimRepSize (magicIdPrimRep reg) == 0
666 Now comes the general case
669 cgAlgAlts gc_flag uniq restore_cc must_label_branches ty alts deflt
670 {- The deflt is either StgNoDefault or a BindDefault which doesn't use the binder -}
671 emit_yield{-should a yield macro be emitted?-}
673 = forkAlts (map (cgAlgAlt gc_flag uniq restore_cc must_label_branches emit_yield) alts)
674 [{- No "extra branches" -}]
675 (cgAlgDefault gc_flag uniq restore_cc must_label_branches deflt emit_yield)
679 cgAlgDefault :: GCFlag
680 -> Unique -> AbstractC -> Bool -- turgid state...
681 -> StgCaseDefault -- input
683 -> FCode AbstractC -- output
685 cgAlgDefault gc_flag uniq restore_cc must_label_branch
689 cgAlgDefault gc_flag uniq restore_cc must_label_branch
690 (StgBindDefault _ False{-binder not used-} rhs)
691 emit_yield{-should a yield macro be emitted?-}
693 = getAbsC (absC restore_cc `thenC`
695 emit_gran_macros = opt_GranMacros
697 (if emit_gran_macros && emit_yield
699 else absC AbsCNop) `thenC`
700 -- liveness same as in possibleHeapCheck below
701 possibleHeapCheck gc_flag [] False (cgExpr rhs)) `thenFC` \ abs_c ->
703 final_abs_c | must_label_branch = CJump (CLabelledCode lbl abs_c)
708 lbl = mkDefaultLabel uniq
711 cgAlgDefault gc_flag uniq restore_cc must_label_branch
712 (StgBindDefault binder True{-binder used-} rhs)
713 emit_yield{-should a yield macro be emitted?-}
715 = -- We have arranged that Node points to the thing, even
716 -- even if we return in registers
717 bindNewToReg binder node mkLFArgument `thenC`
718 getAbsC (absC restore_cc `thenC`
720 emit_gran_macros = opt_GranMacros
722 (if emit_gran_macros && emit_yield
723 then yield [node] False
724 else absC AbsCNop) `thenC`
725 -- liveness same as in possibleHeapCheck below
726 possibleHeapCheck gc_flag [node] False (cgExpr rhs)
727 -- Node is live, but doesn't need to point at the thing itself;
728 -- it's ok for Node to point to an indirection or FETCH_ME
729 -- Hence no need to re-enter Node.
730 ) `thenFC` \ abs_c ->
733 final_abs_c | must_label_branch = CJump (CLabelledCode lbl abs_c)
738 lbl = mkDefaultLabel uniq
740 -- HWL comment on GrAnSim: GRAN_YIELDs needed; emitted in cgAlgAltRhs
743 -> Unique -> AbstractC -> Bool -- turgid state
744 -> Bool -- Context switch at alts?
745 -> (Id, [Id], [Bool], StgExpr)
746 -> FCode (ConTag, AbstractC)
748 cgAlgAlt gc_flag uniq restore_cc must_label_branch
749 emit_yield{-should a yield macro be emitted?-}
750 (con, args, use_mask, rhs)
751 = getAbsC (absC restore_cc `thenC`
752 cgAlgAltRhs gc_flag con args use_mask rhs
754 ) `thenFC` \ abs_c ->
756 final_abs_c | must_label_branch = CJump (CLabelledCode lbl abs_c)
759 returnFC (tag, final_abs_c)
762 lbl = mkAltLabel uniq tag
764 cgAlgAltRhs :: GCFlag
769 -> Bool -- context switch?
771 cgAlgAltRhs gc_flag con args use_mask rhs emit_yield
773 (live_regs, node_reqd)
774 = case (dataReturnConvAlg con) of
775 ReturnInHeap -> ([], True)
776 ReturnInRegs regs -> ([reg | (reg,True) <- zipEqual "cgAlgAltRhs" regs use_mask], False)
777 -- Pick the live registers using the use_mask
778 -- Doing so is IMPORTANT, because with semi-tagging
779 -- enabled only the live registers will have valid
783 emit_gran_macros = opt_GranMacros
785 (if emit_gran_macros && emit_yield
786 then yield live_regs node_reqd
787 else absC AbsCNop) `thenC`
788 -- liveness same as in possibleHeapCheck below
789 possibleHeapCheck gc_flag live_regs node_reqd (
791 NoGC -> mapFCs bindNewToTemp args `thenFC` \ _ ->
793 GCMayHappen -> bindConArgs con args
799 %************************************************************************
801 \subsection[CgCase-semi-tagged-alts]{The code to deal with sem-tagging}
803 %************************************************************************
805 Turgid-but-non-monadic code to conjure up the required info from
806 algebraic case alternatives for semi-tagging.
809 cgSemiTaggedAlts :: Unique
810 -> [(Id, [Id], [Bool], StgExpr)]
811 -> GenStgCaseDefault Id Id
814 cgSemiTaggedAlts uniq alts deflt
815 = Just (map st_alt alts, st_deflt deflt)
817 st_deflt StgNoDefault = Nothing
819 st_deflt (StgBindDefault binder binder_used _)
820 = Just (if binder_used then Just binder else Nothing,
821 (CCallProfCtrMacro SLIT("RET_SEMI_BY_DEFAULT") [], -- ToDo: monadise?
825 st_alt (con, args, use_mask, _)
826 = case (dataReturnConvAlg con) of
829 -- Ha! Nothing to do; Node already points to the thing
831 (CCallProfCtrMacro SLIT("RET_SEMI_IN_HEAP") -- ToDo: monadise?
832 [mkIntCLit (length args)], -- how big the thing in the heap is
837 -- We have to load the live registers from the constructor
838 -- pointed to by Node.
840 (_, regs_w_offsets) = layOutDynCon con magicIdPrimRep regs
842 used_regs = selectByMask use_mask regs
844 used_regs_w_offsets = [ ro | ro@(reg,offset) <- regs_w_offsets,
845 reg `is_elem` used_regs]
847 is_elem = isIn "cgSemiTaggedAlts"
851 CCallProfCtrMacro SLIT("RET_SEMI_IN_REGS") -- ToDo: macroise?
852 [mkIntCLit (length regs_w_offsets),
853 mkIntCLit (length used_regs_w_offsets)],
854 CSimultaneous (mkAbstractCs (map move_to_reg used_regs_w_offsets))],
857 con_tag = dataConTag con
858 join_label = mkAltLabel uniq con_tag
860 move_to_reg :: (MagicId, VirtualHeapOffset {-from Node-}) -> AbstractC
861 move_to_reg (reg, offset)
862 = CAssign (CReg reg) (CVal (NodeRel offset) (magicIdPrimRep reg))
865 %************************************************************************
867 \subsection[CgCase-prim-alts]{Primitive alternatives}
869 %************************************************************************
871 @cgPrimAlts@ generates a suitable @CSwitch@ for dealing with the
872 alternatives of a primitive @case@, given an addressing mode for the
873 thing to scrutinise. It also keeps track of the maximum stack depth
874 encountered down any branch.
876 As usual, no binders in the alternatives are yet bound.
882 -> [(Literal, StgExpr)] -- Alternatives
883 -> StgCaseDefault -- Default
886 cgPrimAlts gc_flag uniq ty alts deflt
887 = cgPrimAltsGivenScrutinee gc_flag scrutinee alts deflt
889 -- A temporary variable, or standard register, to hold the result
890 scrutinee = case gc_flag of
891 NoGC -> CTemp uniq kind
892 GCMayHappen -> CReg (dataReturnConvPrim kind)
894 kind = typePrimRep ty
897 cgPrimAltsGivenScrutinee gc_flag scrutinee alts deflt
898 = forkAlts (map (cgPrimAlt gc_flag) alts)
899 [{- No "extra branches" -}]
900 (cgPrimDefault gc_flag scrutinee deflt) `thenFC` \ (alt_absCs, deflt_absC) ->
901 absC (CSwitch scrutinee alt_absCs deflt_absC)
902 -- CSwitch does sensible things with one or zero alternatives
906 -> (Literal, StgExpr) -- The alternative
907 -> FCode (Literal, AbstractC) -- Its compiled form
909 cgPrimAlt gc_flag (lit, rhs)
910 = getAbsC rhs_code `thenFC` \ absC ->
913 rhs_code = possibleHeapCheck gc_flag [] False (cgExpr rhs )
915 cgPrimDefault :: GCFlag
916 -> CAddrMode -- Scrutinee
920 cgPrimDefault gc_flag scrutinee StgNoDefault
921 = panic "cgPrimDefault: No default in prim case"
923 cgPrimDefault gc_flag scrutinee (StgBindDefault _ False{-binder not used-} rhs)
924 = getAbsC (possibleHeapCheck gc_flag [] False (cgExpr rhs ))
926 cgPrimDefault gc_flag scrutinee (StgBindDefault binder True{-used-} rhs)
927 = getAbsC (possibleHeapCheck gc_flag regs False rhs_code)
929 regs = if isFollowableRep (getAmodeRep scrutinee) then
932 rhs_code = bindNewPrimToAmode binder scrutinee `thenC`
937 %************************************************************************
939 \subsection[CgCase-tidy]{Code for tidying up prior to an eval}
941 %************************************************************************
944 saveVolatileVarsAndRegs
945 :: StgLiveVars -- Vars which should be made safe
946 -> FCode (AbstractC, -- Assignments to do the saves
947 EndOfBlockInfo, -- New sequel, recording where the return
949 Maybe VirtualSpBOffset) -- Slot for current cost centre
952 saveVolatileVarsAndRegs vars
953 = saveVolatileVars vars `thenFC` \ var_saves ->
954 saveCurrentCostCentre `thenFC` \ (maybe_cc_slot, cc_save) ->
955 saveReturnAddress `thenFC` \ (new_eob_info, ret_save) ->
956 returnFC (mkAbstractCs [var_saves, cc_save, ret_save],
961 saveVolatileVars :: StgLiveVars -- Vars which should be made safe
962 -> FCode AbstractC -- Assignments to to the saves
964 saveVolatileVars vars
965 = save_em (idSetToList vars)
967 save_em [] = returnFC AbsCNop
970 = getCAddrModeIfVolatile var `thenFC` \ v ->
972 Nothing -> save_em vars -- Non-volatile, so carry on
975 Just vol_amode -> -- Aha! It's volatile
976 save_var var vol_amode `thenFC` \ abs_c ->
977 save_em vars `thenFC` \ abs_cs ->
978 returnFC (abs_c `mkAbsCStmts` abs_cs)
980 save_var var vol_amode
981 | isFollowableRep kind
982 = allocAStack `thenFC` \ a_slot ->
983 rebindToAStack var a_slot `thenC`
984 getSpARelOffset a_slot `thenFC` \ spa_rel ->
985 returnFC (CAssign (CVal spa_rel kind) vol_amode)
987 = allocBStack (getPrimRepSize kind) `thenFC` \ b_slot ->
988 rebindToBStack var b_slot `thenC`
989 getSpBRelOffset b_slot `thenFC` \ spb_rel ->
990 returnFC (CAssign (CVal spb_rel kind) vol_amode)
992 kind = getAmodeRep vol_amode
994 saveReturnAddress :: FCode (EndOfBlockInfo, AbstractC)
996 = getEndOfBlockInfo `thenFC` \ eob_info@(EndOfBlockInfo vA vB sequel) ->
998 -- See if it is volatile
1000 InRetReg -> -- Yes, it's volatile
1001 allocBStack retPrimRepSize `thenFC` \ b_slot ->
1002 getSpBRelOffset b_slot `thenFC` \ spb_rel ->
1004 returnFC (EndOfBlockInfo vA vB (OnStack b_slot),
1005 CAssign (CVal spb_rel RetRep) (CReg RetReg))
1007 UpdateCode _ -> -- It's non-volatile all right, but we still need
1008 -- to allocate a B-stack slot for it, *solely* to make
1009 -- sure that update frames for different values do not
1010 -- appear adjacent on the B stack. This makes sure
1011 -- that B-stack squeezing works ok.
1013 allocBStack retPrimRepSize `thenFC` \ b_slot ->
1014 returnFC (eob_info, AbsCNop)
1016 other -> -- No, it's non-volatile, so do nothing
1017 returnFC (eob_info, AbsCNop)
1020 Note about B-stack squeezing. Consider the following:`
1022 y = [...] \u [] -> ...
1023 x = [y] \u [] -> case y of (a,b) -> a
1025 The code for x will push an update frame, and then enter y. The code
1026 for y will push another update frame. If the B-stack-squeezer then
1027 wakes up, it will see two update frames right on top of each other,
1028 and will combine them. This is WRONG, of course, because x's value is
1029 not the same as y's.
1031 The fix implemented above makes sure that we allocate an (unused)
1032 B-stack slot before entering y. You can think of this as holding the
1033 saved value of RetAddr, which (after pushing x's update frame will be
1034 some update code ptr). The compiler is clever enough to load the
1035 static update code ptr into RetAddr before entering ~a~, but the slot
1036 is still there to separate the update frames.
1038 When we save the current cost centre (which is done for lexical
1039 scoping), we allocate a free B-stack location, and return (a)~the
1040 virtual offset of the location, to pass on to the alternatives, and
1041 (b)~the assignment to do the save (just as for @saveVolatileVars@).
1044 saveCurrentCostCentre ::
1045 FCode (Maybe VirtualSpBOffset, -- Where we decide to store it
1046 -- Nothing if not lexical CCs
1047 AbstractC) -- Assignment to save it
1048 -- AbsCNop if not lexical CCs
1050 saveCurrentCostCentre
1052 doing_profiling = opt_SccProfilingOn
1054 if not doing_profiling then
1055 returnFC (Nothing, AbsCNop)
1057 allocBStack (getPrimRepSize CostCentreRep) `thenFC` \ b_slot ->
1058 getSpBRelOffset b_slot `thenFC` \ spb_rel ->
1059 returnFC (Just b_slot,
1060 CAssign (CVal spb_rel CostCentreRep) (CReg CurCostCentre))
1062 restoreCurrentCostCentre :: Maybe VirtualSpBOffset -> FCode AbstractC
1064 restoreCurrentCostCentre Nothing
1066 restoreCurrentCostCentre (Just b_slot)
1067 = getSpBRelOffset b_slot `thenFC` \ spb_rel ->
1068 freeBStkSlot b_slot `thenC`
1069 returnFC (CCallProfCCMacro SLIT("RESTORE_CCC") [CVal spb_rel CostCentreRep])
1070 -- we use the RESTORE_CCC macro, rather than just
1071 -- assigning into CurCostCentre, in case RESTORE_CCC
1072 -- has some sanity-checking in it.
1076 %************************************************************************
1078 \subsection[CgCase-return-vec]{Building a return vector}
1080 %************************************************************************
1082 Build a return vector, and return a suitable label addressing
1086 mkReturnVector :: Unique
1088 -> [(ConTag, AbstractC)] -- Branch codes
1089 -> AbstractC -- Default case
1092 mkReturnVector uniq ty tagged_alt_absCs deflt_absC
1094 (return_vec_amode, vtbl_body) = case (ctrlReturnConvAlg tycon) of {
1096 UnvectoredReturn _ ->
1097 (CUnVecLbl ret_label vtbl_label,
1098 absC (CRetUnVector vtbl_label
1099 (CLabelledCode ret_label
1100 (mkAlgAltsCSwitch (CReg TagReg)
1103 VectoredReturn table_size ->
1104 (CLbl vtbl_label DataPtrRep,
1105 absC (CRetVector vtbl_label
1106 -- must restore cc before each alt, if required
1107 (map mk_vector_entry [fIRST_TAG .. (table_size+fIRST_TAG-1)])
1110 -- Leave nops and comments in for now; they are eliminated
1111 -- lazily as it's printed.
1112 -- (case (nonemptyAbsC deflt_absC) of
1113 -- Nothing -> AbsCNop
1118 returnFC return_vec_amode
1122 (tycon,_,_) = case splitAlgTyConApp_maybe ty of -- *must* be a real "data" type constructor
1124 Nothing -> pprPanic "ERROR: can't generate code for polymorphic case"
1125 (vcat [text "probably a mis-use of `seq' or `par';",
1126 text "the User's Guide has more details.",
1127 text "Offending type:" <+> ppr ty
1130 vtbl_label = mkVecTblLabel uniq
1131 ret_label = mkReturnPtLabel uniq
1133 mk_vector_entry :: ConTag -> Maybe CAddrMode
1135 = case [ absC | (t, absC) <- tagged_alt_absCs, t == tag ] of
1137 [absC] -> Just (CCode absC)
1138 _ -> panic "mkReturnVector: too many"
1141 %************************************************************************
1143 \subsection[CgCase-utils]{Utilities for handling case expressions}
1145 %************************************************************************
1147 @possibleHeapCheck@ tests a flag passed in to decide whether to
1148 do a heap check or not.
1151 possibleHeapCheck :: GCFlag -> [MagicId] -> Bool -> Code -> Code
1153 possibleHeapCheck GCMayHappen regs node_reqd code = heapCheck regs node_reqd code
1154 possibleHeapCheck NoGC _ _ code = code
1157 Select a restricted set of registers based on a usage mask.
1160 selectByMask [] [] = []
1161 selectByMask (True:ms) (x:xs) = x : selectByMask ms xs
1162 selectByMask (False:ms) (x:xs) = selectByMask ms xs