2 % (c) The GRASP/AQUA Project, Glasgow University, 1992-1995
4 \section[CgClosure]{Code generation for closures}
6 This module provides the support code for @StgToAbstractC@ to deal
7 with {\em closures} on the RHSs of let(rec)s. See also
8 @CgCon@, which deals with constructors.
11 #include "HsVersions.h"
13 module CgClosure ( cgTopRhsClosure, cgRhsClosure ) where
16 IMPORT_DELOOPER(CgLoop2) ( cgExpr )
22 import AbsCUtils ( mkAbstractCs, getAmodeRep )
23 import CgBindery ( getCAddrMode, getArgAmodes,
24 getCAddrModeAndInfo, bindNewToNode,
25 bindNewToAStack, bindNewToBStack,
26 bindNewToReg, bindArgsToRegs,
27 stableAmodeIdInfo, heapIdInfo, CgIdInfo
29 import CgCompInfo ( spARelToInt, spBRelToInt )
30 import CgUpdate ( pushUpdateFrame )
31 import CgHeapery ( allocDynClosure, heapCheck
32 , heapCheckOnly, fetchAndReschedule, yield -- HWL
34 import CgRetConv ( ctrlReturnConvAlg, dataReturnConvAlg,
35 CtrlReturnConvention(..), DataReturnConvention(..)
37 import CgStackery ( getFinalStackHW, mkVirtStkOffsets,
40 import CgUsages ( getVirtSps, setRealAndVirtualSps,
41 getSpARelOffset, getSpBRelOffset,
44 import CLabel ( mkClosureLabel, mkConUpdCodePtrVecLabel,
45 mkStdUpdCodePtrVecLabel, mkStdUpdVecTblLabel,
46 mkErrorStdEntryLabel, mkRednCountsLabel
48 import ClosureInfo -- lots and lots of stuff
49 import CmdLineOpts ( opt_ForConcurrent, opt_GranMacros )
50 import CostCentre ( useCurrentCostCentre, currentOrSubsumedCosts,
51 noCostCentreAttached, costsAreSubsumed,
52 isCafCC, isDictCC, overheadCostCentre
54 import HeapOffs ( SYN_IE(VirtualHeapOffset) )
55 import Id ( idType, idPrimRep,
56 showId, getIdStrictness, dataConTag,
58 GenId{-instance Outputable-}
60 import ListSetOps ( minusList )
61 import Maybes ( maybeToBool )
62 import PprStyle ( PprStyle(..) )
63 import PprType ( GenType{-instance Outputable-}, TyCon{-ditto-} )
64 import Pretty ( prettyToUn, ppBesides, ppChar, ppPStr )
65 import PrimRep ( isFollowableRep, PrimRep(..) )
66 import TyCon ( isPrimTyCon, tyConDataCons )
67 import Unpretty ( uppShow )
68 import Util ( isIn, panic, pprPanic, assertPanic )
70 myWrapperMaybe = panic "CgClosure.myWrapperMaybe (ToDo)"
71 showTypeCategory = panic "CgClosure.showTypeCategory (ToDo)"
72 getWrapperArgTypeCategories = panic "CgClosure.getWrapperArgTypeCategories (ToDo)"
75 %********************************************************
77 \subsection[closures-no-free-vars]{Top-level closures}
79 %********************************************************
81 For closures bound at top level, allocate in static space.
82 They should have no free variables.
86 -> CostCentre -- Optional cost centre annotation
91 -> FCode (Id, CgIdInfo)
93 cgTopRhsClosure name cc binder_info args body lf_info
94 = -- LAY OUT THE OBJECT
96 closure_info = layOutStaticNoFVClosure name lf_info
99 -- GENERATE THE INFO TABLE (IF NECESSARY)
100 forkClosureBody (closureCodeBody binder_info closure_info
104 -- BUILD VAP INFO TABLES IF NECESSARY
105 -- Don't build Vap info tables etc for
106 -- a function whose result is an unboxed type,
107 -- because we can never have thunks with such a type.
108 (if closureReturnsUnboxedType closure_info then
112 bind_the_fun = addBindC name cg_id_info -- It's global!
114 cgVapInfoTables True {- Top level -} bind_the_fun binder_info name args lf_info
117 -- BUILD THE OBJECT (IF NECESSARY)
118 (if staticClosureRequired name binder_info lf_info
121 cost_centre = mkCCostCentre cc
124 closure_label -- Labelled with the name on lhs of defn
132 returnFC (name, cg_id_info)
134 closure_label = mkClosureLabel name
135 cg_id_info = stableAmodeIdInfo name (CLbl closure_label PtrRep) lf_info
138 %********************************************************
140 \subsection[non-top-level-closures]{Non top-level closures}
142 %********************************************************
144 For closures with free vars, allocate in heap.
146 ===================== OLD PROBABLY OUT OF DATE COMMENTS =============
148 -- Closures which (a) have no fvs and (b) have some args (i.e.
149 -- combinator functions), are allocated statically, just as if they
150 -- were top-level closures. We can't get a space leak that way
151 -- (because they are HNFs) and it saves allocation.
153 -- Lexical Scoping: Problem
154 -- These top level function closures will be inherited, possibly
155 -- to a different cost centre scope set before entering.
157 -- Evaluation Scoping: ok as already in HNF
159 -- Should rely on floating mechanism to achieve this floating to top level.
160 -- As let floating will avoid floating which breaks cost centre attribution
161 -- everything will be OK.
163 -- Disabled: because it breaks lexical-scoped cost centre semantics.
164 -- cgRhsClosure binder cc bi [] upd_flag args@(_:_) body
165 -- = cgTopRhsClosure binder cc bi upd_flag args body
167 ===================== END OF OLD PROBABLY OUT OF DATE COMMENTS =============
171 -> CostCentre -- Optional cost centre annotation
177 -> FCode (Id, CgIdInfo)
179 cgRhsClosure binder cc binder_info fvs args body lf_info
180 | maybeToBool maybe_std_thunk -- AHA! A STANDARD-FORM THUNK
181 -- ToDo: check non-primitiveness (ASSERT)
183 -- LAY OUT THE OBJECT
184 getArgAmodes std_thunk_payload `thenFC` \ amodes ->
186 (closure_info, amodes_w_offsets)
187 = layOutDynClosure binder getAmodeRep amodes lf_info
189 (use_cc, blame_cc) = chooseDynCostCentres cc args fvs body
192 allocDynClosure closure_info use_cc blame_cc amodes_w_offsets
194 `thenFC` \ heap_offset ->
197 returnFC (binder, heapIdInfo binder heap_offset lf_info)
200 maybe_std_thunk = getStandardFormThunkInfo lf_info
201 Just std_thunk_payload = maybe_std_thunk
204 Here's the general case.
206 cgRhsClosure binder cc binder_info fvs args body lf_info
208 -- LAY OUT THE OBJECT
210 -- If the binder is itself a free variable, then don't store
211 -- it in the closure. Instead, just bind it to Node on entry.
212 -- NB we can be sure that Node will point to it, because we
213 -- havn't told mkClosureLFInfo about this; so if the binder
214 -- *was* a free var of its RHS, mkClosureLFInfo thinks it *is*
215 -- stored in the closure itself, so it will make sure that
216 -- Node points to it...
218 is_elem = isIn "cgRhsClosure"
220 binder_is_a_fv = binder `is_elem` fvs
221 reduced_fvs = if binder_is_a_fv
222 then fvs `minusList` [binder]
225 mapFCs getCAddrModeAndInfo reduced_fvs `thenFC` \ amodes_and_info ->
227 fvs_w_amodes_and_info = reduced_fvs `zip` amodes_and_info
229 closure_info :: ClosureInfo
230 bind_details :: [((Id, (CAddrMode, LambdaFormInfo)), VirtualHeapOffset)]
232 (closure_info, bind_details)
233 = layOutDynClosure binder get_kind fvs_w_amodes_and_info lf_info
235 bind_fv ((id, (_, lf_info)), offset) = bindNewToNode id offset lf_info
237 amodes_w_offsets = [(amode,offset) | ((_, (amode,_)), offset) <- bind_details]
239 get_kind (id, amode_and_info) = idPrimRep id
241 -- BUILD ITS INFO TABLE AND CODE
244 mapCs bind_fv bind_details `thenC`
246 -- Bind the binder itself, if it is a free var
247 (if binder_is_a_fv then
248 bindNewToReg binder node lf_info
253 closureCodeBody binder_info closure_info cc args body
256 -- BUILD VAP INFO TABLES IF NECESSARY
257 -- Don't build Vap info tables etc for
258 -- a function whose result is an unboxed type,
259 -- because we can never have thunks with such a type.
260 (if closureReturnsUnboxedType closure_info then
263 cgVapInfoTables False {- Not top level -} nopC binder_info binder args lf_info
268 (use_cc, blame_cc) = chooseDynCostCentres cc args fvs body
270 allocDynClosure closure_info use_cc blame_cc amodes_w_offsets
271 ) `thenFC` \ heap_offset ->
274 returnFC (binder, heapIdInfo binder heap_offset lf_info)
277 @cgVapInfoTables@ generates both Vap info tables, if they are required
278 at all. It calls @cgVapInfoTable@ to generate each Vap info table,
279 along with its entry code.
282 -- Don't generate Vap info tables for thunks; only for functions
283 cgVapInfoTables top_level perhaps_bind_the_fun binder_info fun [{- no args; a thunk! -}] lf_info
286 cgVapInfoTables top_level perhaps_bind_the_fun binder_info fun args lf_info
287 = -- BUILD THE STANDARD VAP-ENTRY STUFF IF NECESSARY
288 (if stdVapRequired binder_info then
289 cgVapInfoTable perhaps_bind_the_fun Updatable fun args fun_in_payload lf_info
294 -- BUILD THE NO-UPDATE VAP-ENTRY STUFF IF NECESSARY
295 (if noUpdVapRequired binder_info then
296 cgVapInfoTable perhaps_bind_the_fun SingleEntry fun args fun_in_payload lf_info
302 fun_in_payload = not top_level
304 cgVapInfoTable perhaps_bind_the_fun upd_flag fun args fun_in_payload fun_lf_info
306 -- The vap_entry_rhs is a manufactured STG expression which
307 -- looks like the RHS of any binding which is going to use the vap-entry
308 -- point of the function. Each of these bindings will look like:
310 -- x = [a,b,c] \upd [] -> f a b c
312 -- If f is not top-level, then f is one of the free variables too,
313 -- hence "payload_ids" isn't the same as "arg_ids".
315 vap_entry_rhs = StgApp (StgVarArg fun) (map StgVarArg args) emptyIdSet
318 arg_ids_w_info = [(name,mkLFArgument) | name <- args]
319 payload_ids_w_info | fun_in_payload = (fun,fun_lf_info) : arg_ids_w_info
320 | otherwise = arg_ids_w_info
322 payload_ids | fun_in_payload = fun : args -- Sigh; needed for mkClosureLFInfo
325 vap_lf_info = mkClosureLFInfo False {-not top level-} payload_ids
326 upd_flag [] vap_entry_rhs
327 -- It's not top level, even if we're currently compiling a top-level
328 -- function, because any VAP *use* of this function will be for a
330 -- let x = f p q -- x isn't top level!
333 get_kind (id, info) = idPrimRep id
335 payload_bind_details :: [((Id, LambdaFormInfo), VirtualHeapOffset)]
336 (closure_info, payload_bind_details) = layOutDynClosure
338 get_kind payload_ids_w_info
340 -- The dodgy thing is that we use the "fun" as the
341 -- Id to give to layOutDynClosure. This Id gets embedded in
342 -- the closure_info it returns. But of course, the function doesn't
343 -- have the right type to match the Vap closure. Never mind,
344 -- a hack in closureType spots the special case. Otherwise that
345 -- Id is just used for label construction, which is OK.
347 bind_fv ((id,lf_info), offset) = bindNewToNode id offset lf_info
350 -- BUILD ITS INFO TABLE AND CODE
353 -- Bind the fvs; if the fun is not in the payload, then bind_the_fun tells
354 -- how to bind it. If it is in payload it'll be bound by payload_bind_details.
355 perhaps_bind_the_fun `thenC`
356 mapCs bind_fv payload_bind_details `thenC`
358 -- Generate the info table and code
359 closureCodeBody NoStgBinderInfo
362 [] -- No args; it's a thunk
366 %************************************************************************
368 \subsection[code-for-closures]{The code for closures}
370 %************************************************************************
373 closureCodeBody :: StgBinderInfo
374 -> ClosureInfo -- Lots of information about this closure
375 -> CostCentre -- Optional cost centre attached to closure
381 There are two main cases for the code for closures. If there are {\em
382 no arguments}, then the closure is a thunk, and not in normal form.
383 So it should set up an update frame (if it is shared). Also, it has
384 no argument satisfaction check, so fast and slow entry-point labels
388 closureCodeBody binder_info closure_info cc [] body
389 = -- thunks cannot have a primitive type!
393 = case (closureType closure_info) of
394 Nothing -> (False, panic "debug")
395 Just (tc,_,_) -> (True, tc)
397 if has_tycon && isPrimTyCon tycon then
398 pprPanic "closureCodeBody:thunk:prim type!" (ppr PprDebug tycon)
401 getAbsC body_code `thenFC` \ body_absC ->
402 moduleName `thenFC` \ mod_name ->
404 absC (CClosureInfoAndCode closure_info body_absC Nothing
405 stdUpd (cl_descr mod_name)
406 (dataConLiveness closure_info))
408 cl_descr mod_name = closureDescription mod_name (closureId closure_info) [] body
410 body_addr = CLbl (entryLabelFromCI closure_info) CodePtrRep
411 body_code = profCtrC SLIT("ENT_THK") [] `thenC`
412 enterCostCentreCode closure_info cc IsThunk `thenC`
413 thunkWrapper closure_info (cgExpr body)
415 stdUpd = CLbl mkErrorStdEntryLabel CodePtrRep
418 If there is {\em at least one argument}, then this closure is in
419 normal form, so there is no need to set up an update frame. On the
420 other hand, we do have to check that there are enough args, and
421 perform an update if not!
423 The Macros for GrAnSim are produced at the beginning of the
424 argSatisfactionCheck (by calling fetchAndReschedule). There info if
425 Node points to closure is available. -- HWL
428 closureCodeBody binder_info closure_info cc all_args body
429 = getEntryConvention id lf_info
430 (map idPrimRep all_args) `thenFC` \ entry_conv ->
432 is_concurrent = opt_ForConcurrent
434 stg_arity = length all_args
436 -- Arg mapping for standard (slow) entry point; all args on stack
437 (spA_all_args, spB_all_args, all_bxd_w_offsets, all_ubxd_w_offsets)
439 0 0 -- Initial virtual SpA, SpB
443 -- Arg mapping for the fast entry point; as many args as poss in
444 -- registers; the rest on the stack
445 -- arg_regs are the registers used for arg passing
446 -- stk_args are the args which are passed on the stack
448 arg_regs = case entry_conv of
449 DirectEntry lbl arity regs -> regs
450 ViaNode | is_concurrent -> []
451 other -> panic "closureCodeBody:arg_regs"
453 num_arg_regs = length arg_regs
455 (reg_args, stk_args) = splitAt num_arg_regs all_args
457 (spA_stk_args, spB_stk_args, stk_bxd_w_offsets, stk_ubxd_w_offsets)
459 0 0 -- Initial virtual SpA, SpB
463 -- HWL; Note: empty list of live regs in slow entry code
464 -- Old version (reschedule combined with heap check);
465 -- see argSatisfactionCheck for new version
466 --slow_entry_code = forceHeapCheck [node] True slow_entry_code'
467 -- where node = VanillaReg PtrRep 1
468 --slow_entry_code = forceHeapCheck [] True slow_entry_code'
471 = profCtrC SLIT("ENT_FUN_STD") [] `thenC`
473 -- Bind args, and record expected position of stk ptrs
474 mapCs bindNewToAStack all_bxd_w_offsets `thenC`
475 mapCs bindNewToBStack all_ubxd_w_offsets `thenC`
476 setRealAndVirtualSps spA_all_args spB_all_args `thenC`
478 argSatisfactionCheck closure_info all_args `thenC`
480 -- OK, so there are enough args. Now we need to stuff as
481 -- many of them in registers as the fast-entry code
482 -- expects Note that the zipWith will give up when it hits
483 -- the end of arg_regs.
485 mapFCs getCAddrMode all_args `thenFC` \ stk_amodes ->
486 absC (mkAbstractCs (zipWith assign_to_reg arg_regs stk_amodes)) `thenC`
488 -- Now adjust real stack pointers
489 adjustRealSps spA_stk_args spB_stk_args `thenC`
491 absC (CFallThrough (CLbl fast_label CodePtrRep))
493 assign_to_reg reg_id amode = CAssign (CReg reg_id) amode
496 -- Old version (reschedule combined with heap check);
497 -- see argSatisfactionCheck for new version
498 -- fast_entry_code = forceHeapCheck [] True fast_entry_code'
501 = profCtrC SLIT("ENT_FUN_DIRECT") [
502 CLbl (mkRednCountsLabel id) PtrRep,
503 CString (_PK_ (showId PprDebug id)),
504 mkIntCLit stg_arity, -- total # of args
505 mkIntCLit spA_stk_args, -- # passed on A stk
506 mkIntCLit spB_stk_args, -- B stk (rest in regs)
507 CString (_PK_ (map (showTypeCategory . idType) all_args)),
508 CString (_PK_ (show_wrapper_name wrapper_maybe)),
509 CString (_PK_ (show_wrapper_arg_kinds wrapper_maybe))
512 -- Bind args to regs/stack as appropriate, and
513 -- record expected position of sps
514 bindArgsToRegs reg_args arg_regs `thenC`
515 mapCs bindNewToAStack stk_bxd_w_offsets `thenC`
516 mapCs bindNewToBStack stk_ubxd_w_offsets `thenC`
517 setRealAndVirtualSps spA_stk_args spB_stk_args `thenC`
519 -- Enter the closures cc, if required
520 enterCostCentreCode closure_info cc IsFunction `thenC`
523 funWrapper closure_info arg_regs (cgExpr body)
525 -- Make a labelled code-block for the slow and fast entry code
526 forkAbsC (if slow_code_needed then slow_entry_code else absC AbsCNop)
527 `thenFC` \ slow_abs_c ->
528 forkAbsC fast_entry_code `thenFC` \ fast_abs_c ->
529 moduleName `thenFC` \ mod_name ->
531 -- Now either construct the info table, or put the fast code in alone
532 -- (We never have slow code without an info table)
534 if info_table_needed then
535 CClosureInfoAndCode closure_info slow_abs_c (Just fast_abs_c)
536 stdUpd (cl_descr mod_name)
537 (dataConLiveness closure_info)
539 CCodeBlock fast_label fast_abs_c
542 lf_info = closureLFInfo closure_info
544 cl_descr mod_name = closureDescription mod_name id all_args body
546 -- Figure out what is needed and what isn't
547 slow_code_needed = slowFunEntryCodeRequired id binder_info
548 info_table_needed = funInfoTableRequired id binder_info lf_info
550 -- Manufacture labels
551 id = closureId closure_info
553 fast_label = fastLabelFromCI closure_info
555 stdUpd = CLbl mkErrorStdEntryLabel CodePtrRep
557 wrapper_maybe = get_ultimate_wrapper Nothing id
559 get_ultimate_wrapper deflt x -- walk all the way up a "wrapper chain"
560 = case (myWrapperMaybe x) of
562 Just xx -> get_ultimate_wrapper (Just xx) xx
564 show_wrapper_name Nothing = ""
565 show_wrapper_name (Just xx) = showId PprDebug xx
567 show_wrapper_arg_kinds Nothing = ""
568 show_wrapper_arg_kinds (Just xx)
569 = case (getWrapperArgTypeCategories (idType xx) (getIdStrictness xx)) of
574 For lexically scoped profiling we have to load the cost centre from
575 the closure entered, if the costs are not supposed to be inherited.
576 This is done immediately on entering the fast entry point.
578 Load current cost centre from closure, if not inherited.
579 Node is guaranteed to point to it, if profiling and not inherited.
582 data IsThunk = IsThunk | IsFunction -- Bool-like, local
587 enterCostCentreCode :: ClosureInfo -> CostCentre -> IsThunk -> Code
589 enterCostCentreCode closure_info cc is_thunk
590 = costCentresFlag `thenFC` \ profiling_on ->
591 if not profiling_on then
594 ASSERT(not (noCostCentreAttached cc))
596 if costsAreSubsumed cc then
597 ASSERT(isToplevClosure closure_info)
598 ASSERT(is_thunk == IsFunction)
599 costCentresC SLIT("ENTER_CC_FSUB") []
601 else if currentOrSubsumedCosts cc then
602 -- i.e. current; subsumed dealt with above
603 -- get CCC out of the closure, where we put it when we alloc'd
605 IsThunk -> costCentresC SLIT("ENTER_CC_TCL") [CReg node]
606 IsFunction -> costCentresC SLIT("ENTER_CC_FCL") [CReg node]
608 else if isCafCC cc && isToplevClosure closure_info then
609 ASSERT(is_thunk == IsThunk)
610 costCentresC SLIT("ENTER_CC_CAF") [mkCCostCentre cc]
612 else -- we've got a "real" cost centre right here in our hands...
614 IsThunk -> costCentresC SLIT("ENTER_CC_T") [mkCCostCentre cc]
615 IsFunction -> if isCafCC cc || isDictCC cc
616 then costCentresC SLIT("ENTER_CC_FCAF") [mkCCostCentre cc]
617 else costCentresC SLIT("ENTER_CC_FLOAD") [mkCCostCentre cc]
620 %************************************************************************
622 \subsubsection[pre-closure-code-stuff]{Pre-closure-code code}
624 %************************************************************************
626 The argument-satisfaction check code is placed after binding
627 the arguments to their stack locations. Hence, the virtual stack
628 pointer is pointing after all the args, and virtual offset 1 means
629 the base of frame and hence most distant arg. Hence
630 virtual offset 0 is just beyond the most distant argument; the
631 relative offset of this word tells how many words of arguments
635 argSatisfactionCheck :: ClosureInfo -> [Id] -> Code
637 argSatisfactionCheck closure_info [] = nopC
639 argSatisfactionCheck closure_info args
640 = -- safest way to determine which stack last arg will be on:
641 -- look up CAddrMode that last arg is bound to;
643 -- check isFollowableRep.
645 nodeMustPointToIt (closureLFInfo closure_info) `thenFC` \ node_points ->
648 emit_gran_macros = opt_GranMacros
652 -- absC (CMacroStmt GRAN_FETCH []) `thenC`
653 -- forceHeapCheck [] node_points (absC AbsCNop) `thenC`
656 then fetchAndReschedule [] node_points
657 else yield [] node_points
658 else absC AbsCNop) `thenC`
660 getCAddrMode (last args) `thenFC` \ last_amode ->
662 if (isFollowableRep (getAmodeRep last_amode)) then
663 getSpARelOffset 0 `thenFC` \ (SpARel spA off) ->
665 a_rel_int = spARelToInt spA off
666 a_rel_arg = mkIntCLit a_rel_int
668 ASSERT(a_rel_int /= 0)
670 absC (CMacroStmt ARGS_CHK_A [a_rel_arg])
672 absC (CMacroStmt ARGS_CHK_A_LOAD_NODE [a_rel_arg, set_Node_to_this])
674 getSpBRelOffset 0 `thenFC` \ (SpBRel spB off) ->
676 b_rel_int = spBRelToInt spB off
677 b_rel_arg = mkIntCLit b_rel_int
679 ASSERT(b_rel_int /= 0)
681 absC (CMacroStmt ARGS_CHK_B [b_rel_arg])
683 absC (CMacroStmt ARGS_CHK_B_LOAD_NODE [b_rel_arg, set_Node_to_this])
685 -- We must tell the arg-satis macro whether Node is pointing to
686 -- the closure or not. If it isn't so pointing, then we give to
687 -- the macro the (static) address of the closure.
689 set_Node_to_this = CLbl (closureLabelFromCI closure_info) PtrRep
692 %************************************************************************
694 \subsubsection[closure-code-wrappers]{Wrappers around closure code}
696 %************************************************************************
699 thunkWrapper:: ClosureInfo -> Code -> Code
700 thunkWrapper closure_info thunk_code
701 = -- Stack and heap overflow checks
702 nodeMustPointToIt (closureLFInfo closure_info) `thenFC` \ node_points ->
705 emit_gran_macros = opt_GranMacros
707 -- HWL: insert macros for GrAnSim; 2 versions depending on liveness of node
708 -- (we prefer fetchAndReschedule-style context switches to yield ones)
711 then fetchAndReschedule [] node_points
712 else yield [] node_points
713 else absC AbsCNop) `thenC`
715 stackCheck closure_info [] node_points ( -- stackCheck *encloses* the rest
717 -- Must be after stackCheck: if stchk fails new stack
718 -- space has to be allocated from the heap
720 heapCheck [] node_points (
721 -- heapCheck *encloses* the rest
722 -- The "[]" says there are no live argument registers
724 -- Overwrite with black hole if necessary
725 blackHoleIt closure_info `thenC`
727 -- Push update frame if necessary
728 setupUpdate closure_info ( -- setupUpdate *encloses* the rest
732 funWrapper :: ClosureInfo -- Closure whose code body this is
733 -> [MagicId] -- List of argument registers (if any)
734 -> Code -- Body of function being compiled
736 funWrapper closure_info arg_regs fun_body
737 = -- Stack overflow check
738 nodeMustPointToIt (closureLFInfo closure_info) `thenFC` \ node_points ->
740 emit_gran_macros = opt_GranMacros
744 then yield arg_regs node_points
745 else absC AbsCNop) `thenC`
747 stackCheck closure_info arg_regs node_points ( -- stackCheck *encloses* the rest
749 -- Heap overflow check
750 heapCheck arg_regs node_points (
751 -- heapCheck *encloses* the rest
753 -- Finally, do the business
758 %************************************************************************
760 \subsubsubsection[overflow-checks]{Stack and heap overflow wrappers}
762 %************************************************************************
764 Assumption: virtual and real stack pointers are currently exactly aligned.
767 stackCheck :: ClosureInfo
768 -> [MagicId] -- Live registers
769 -> Bool -- Node required to point after check?
773 stackCheck closure_info regs node_reqd code
774 = getFinalStackHW (\ aHw -> \ bHw -> -- Both virtual stack offsets
776 getVirtSps `thenFC` \ (vSpA, vSpB) ->
778 let a_headroom_reqd = aHw - vSpA -- Virtual offsets are positive integers
779 b_headroom_reqd = bHw - vSpB
782 absC (if (a_headroom_reqd == 0 && b_headroom_reqd == 0) then
785 CMacroStmt STK_CHK [mkIntCLit liveness_mask,
786 mkIntCLit a_headroom_reqd,
787 mkIntCLit b_headroom_reqd,
790 mkIntCLit (if returns_prim_type then 1 else 0),
791 mkIntCLit (if node_reqd then 1 else 0)]
793 -- The test is *inside* the absC, to avoid black holes!
798 all_regs = if node_reqd then node:regs else regs
799 liveness_mask = mkLiveRegsMask all_regs
801 returns_prim_type = closureReturnsUnboxedType closure_info
804 %************************************************************************
806 \subsubsubsection[update-and-BHs]{Update and black-hole wrappers}
808 %************************************************************************
812 blackHoleIt :: ClosureInfo -> Code -- Only called for thunks
813 blackHoleIt closure_info
814 = noBlackHolingFlag `thenFC` \ no_black_holing ->
816 if (blackHoleOnEntry no_black_holing closure_info)
818 absC (if closureSingleEntry(closure_info) then
819 CMacroStmt UPD_BH_SINGLE_ENTRY [CReg node]
821 CMacroStmt UPD_BH_UPDATABLE [CReg node])
822 -- Node always points to it; see stg-details
828 setupUpdate :: ClosureInfo -> Code -> Code -- Only called for thunks
829 -- Nota Bene: this function does not change Node (even if it's a CAF),
830 -- so that the cost centre in the original closure can still be
831 -- extracted by a subsequent ENTER_CC_TCL
833 setupUpdate closure_info code
834 = if (closureUpdReqd closure_info) then
835 link_caf_if_needed `thenFC` \ update_closure ->
836 pushUpdateFrame update_closure vector code
838 profCtrC SLIT("UPDF_OMITTED") [] `thenC`
841 link_caf_if_needed :: FCode CAddrMode -- Returns amode for closure to be updated
843 = if not (isStaticClosure closure_info) then
847 -- First we must allocate a black hole, and link the
848 -- CAF onto the CAF list
850 -- Alloc black hole specifying CC_HDR(Node) as the cost centre
851 -- Hack Warning: Using a CLitLit to get CAddrMode !
853 use_cc = CLitLit SLIT("CC_HDR(R1.p)") PtrRep
856 allocDynClosure (blackHoleClosureInfo closure_info) use_cc blame_cc []
857 `thenFC` \ heap_offset ->
858 getHpRelOffset heap_offset `thenFC` \ hp_rel ->
859 let amode = CAddr hp_rel
861 absC (CMacroStmt UPD_CAF [CReg node, amode])
866 = case (closureType closure_info) of
867 Nothing -> CReg StdUpdRetVecReg
868 Just (spec_tycon, _, spec_datacons) ->
869 case (ctrlReturnConvAlg spec_tycon) of
870 UnvectoredReturn 1 ->
872 spec_data_con = head spec_datacons
873 only_tag = dataConTag spec_data_con
875 direct = case (dataReturnConvAlg spec_data_con) of
876 ReturnInRegs _ -> mkConUpdCodePtrVecLabel spec_tycon only_tag
877 ReturnInHeap -> mkStdUpdCodePtrVecLabel spec_tycon only_tag
879 vectored = mkStdUpdVecTblLabel spec_tycon
881 CUnVecLbl direct vectored
883 UnvectoredReturn _ -> CReg StdUpdRetVecReg
884 VectoredReturn _ -> CLbl (mkStdUpdVecTblLabel spec_tycon) DataPtrRep
887 %************************************************************************
889 \subsection[CgClosure-Description]{Profiling Closure Description.}
891 %************************************************************************
893 For "global" data constructors the description is simply occurrence
894 name of the data constructor itself (see \ref{CgConTbls-info-tables}).
896 Otherwise it is determind by @closureDescription@ from the let
900 closureDescription :: FAST_STRING -- Module
901 -> Id -- Id of closure binding
906 -- Not called for StgRhsCon which have global info tables built in
907 -- CgConTbls.lhs with a description generated from the data constructor
909 closureDescription mod_name name args body
910 = uppShow 0 (prettyToUn (
911 ppBesides [ppChar '<',
919 chooseDynCostCentres cc args fvs body
921 use_cc -- cost-centre we record in the object
922 = if currentOrSubsumedCosts cc
923 then CReg CurCostCentre
924 else mkCCostCentre cc
926 blame_cc -- cost-centre on whom we blame the allocation
927 = case (args, fvs, body) of
928 ([], [just1], StgApp (StgVarArg fun) [{-no args-}] _)
930 -> mkCCostCentre overheadCostCentre
933 -- if it's an utterly trivial RHS, then it must be
934 -- one introduced by boxHigherOrderArgs for profiling,
935 -- so we charge it to "OVERHEAD".