[project @ 2001-11-06 11:02:05 by simonmar]
[ghc-hetmet.git] / ghc / compiler / codeGen / CgClosure.lhs
1 %
2 % (c) The GRASP/AQUA Project, Glasgow University, 1992-1998
3 %
4 % $Id: CgClosure.lhs,v 1.52 2001/11/06 11:02:05 simonmar Exp $
5 %
6 \section[CgClosure]{Code generation for closures}
7
8 This module provides the support code for @StgToAbstractC@ to deal
9 with {\em closures} on the RHSs of let(rec)s.  See also
10 @CgCon@, which deals with constructors.
11
12 \begin{code}
13 module CgClosure ( cgTopRhsClosure, 
14                    cgStdRhsClosure, 
15                    cgRhsClosure, 
16                    closureCodeBody ) where
17
18 #include "HsVersions.h"
19
20 import {-# SOURCE #-} CgExpr ( cgExpr )
21
22 import CgMonad
23 import AbsCSyn
24 import StgSyn
25
26 import AbsCUtils        ( mkAbstractCs, getAmodeRep )
27 import CgBindery        ( getCAddrMode, getArgAmodes,
28                           getCAddrModeAndInfo, bindNewToNode,
29                           bindNewToStack,
30                           bindNewToReg, bindArgsToRegs,
31                           stableAmodeIdInfo, heapIdInfo, CgIdInfo
32                         )
33 import CgUpdate         ( pushUpdateFrame )
34 import CgHeapery        ( allocDynClosure, 
35                           fetchAndReschedule, yield,  -- HWL
36                           fastEntryChecks, thunkChecks
37                         )
38 import CgStackery       ( mkTaggedVirtStkOffsets, freeStackSlots )
39 import CgUsages         ( adjustSpAndHp, setRealAndVirtualSp, getVirtSp,
40                           getSpRelOffset, getHpRelOffset
41                         )
42 import CLabel           ( CLabel, mkClosureLabel, mkFastEntryLabel,
43                           mkRednCountsLabel, mkInfoTableLabel
44                         )
45 import ClosureInfo      -- lots and lots of stuff
46 import CmdLineOpts      ( opt_GranMacros, opt_SccProfilingOn, opt_DoTickyProfiling )
47 import CostCentre       
48 import Id               ( Id, idName, idType, idPrimRep )
49 import Name             ( Name, isLocalName )
50 import Module           ( Module, pprModule )
51 import ListSetOps       ( minusList )
52 import PrimRep          ( PrimRep(..) )
53 import PprType          ( showTypeCategory )
54 import Util             ( isIn, splitAtList )
55 import CmdLineOpts      ( opt_SccProfilingOn )
56 import Outputable
57
58 import Name             ( nameOccName )
59 import OccName          ( occNameFS )
60 import FastTypes        ( iBox )
61 \end{code}
62
63 %********************************************************
64 %*                                                      *
65 \subsection[closures-no-free-vars]{Top-level closures}
66 %*                                                      *
67 %********************************************************
68
69 For closures bound at top level, allocate in static space.
70 They should have no free variables.
71
72 \begin{code}
73 cgTopRhsClosure :: Id
74                 -> CostCentreStack      -- Optional cost centre annotation
75                 -> StgBinderInfo
76                 -> SRT
77                 -> [Id]         -- Args
78                 -> StgExpr
79                 -> LambdaFormInfo
80                 -> FCode (Id, CgIdInfo)
81
82 cgTopRhsClosure id ccs binder_info srt args body lf_info
83   = 
84     -- LAY OUT THE OBJECT
85     getSRTInfo srt              `thenFC` \ srt_info ->
86     let
87         name          = idName id
88         closure_info  = layOutStaticNoFVClosure name lf_info srt_info
89         closure_label = mkClosureLabel name
90         cg_id_info    = stableAmodeIdInfo id (CLbl closure_label PtrRep) lf_info
91     in
92
93         -- BUILD THE OBJECT (IF NECESSARY)
94     ({- if staticClosureRequired name binder_info lf_info
95      then -}
96         (if opt_SccProfilingOn 
97           then
98              absC (CStaticClosure
99                 closure_label   -- Labelled with the name on lhs of defn
100                 closure_info
101                 (mkCCostCentreStack ccs)
102                 [])             -- No fields
103           else
104              absC (CStaticClosure
105                 closure_label   -- Labelled with the name on lhs of defn
106                 closure_info
107                 (panic "absent cc")
108                 [])             -- No fields
109         )
110
111      {- else
112         nopC -}
113                                                         `thenC`
114
115         -- GENERATE THE INFO TABLE (IF NECESSARY)
116     forkClosureBody (closureCodeBody binder_info closure_info
117                                          ccs args body)
118
119     ) `thenC`
120
121     returnFC (id, cg_id_info)
122
123 \end{code}
124
125 %********************************************************
126 %*                                                      *
127 \subsection[non-top-level-closures]{Non top-level closures}
128 %*                                                      *
129 %********************************************************
130
131 For closures with free vars, allocate in heap.
132
133 \begin{code}
134 cgStdRhsClosure
135         :: Id
136         -> CostCentreStack      -- Optional cost centre annotation
137         -> StgBinderInfo
138         -> [Id]                 -- Free vars
139         -> [Id]                 -- Args
140         -> StgExpr
141         -> LambdaFormInfo
142         -> [StgArg]             -- payload
143         -> FCode (Id, CgIdInfo)
144
145 cgStdRhsClosure binder cc binder_info fvs args body lf_info payload
146                 -- AHA!  A STANDARD-FORM THUNK
147   = (
148         -- LAY OUT THE OBJECT
149     getArgAmodes payload                        `thenFC` \ amodes ->
150     let
151         (closure_info, amodes_w_offsets)
152           = layOutDynClosure (idName binder) getAmodeRep amodes lf_info NoC_SRT
153                 -- No SRT for a standard-form closure
154
155         (use_cc, blame_cc) = chooseDynCostCentres cc args fvs body
156     in
157         -- BUILD THE OBJECT
158     allocDynClosure closure_info use_cc blame_cc amodes_w_offsets
159     )
160                 `thenFC` \ heap_offset ->
161
162         -- RETURN
163     returnFC (binder, heapIdInfo binder heap_offset lf_info)
164 \end{code}
165
166 Here's the general case.
167
168 \begin{code}
169 cgRhsClosure    :: Id
170                 -> CostCentreStack      -- Optional cost centre annotation
171                 -> StgBinderInfo
172                 -> SRT
173                 -> [Id]                 -- Free vars
174                 -> [Id]                 -- Args
175                 -> StgExpr
176                 -> LambdaFormInfo
177                 -> FCode (Id, CgIdInfo)
178
179 cgRhsClosure binder cc binder_info srt fvs args body lf_info
180   = (
181         -- LAY OUT THE OBJECT
182         --
183         -- If the binder is itself a free variable, then don't store
184         -- it in the closure.  Instead, just bind it to Node on entry.
185         -- NB we can be sure that Node will point to it, because we
186         -- havn't told mkClosureLFInfo about this; so if the binder
187         -- *was* a free var of its RHS, mkClosureLFInfo thinks it *is*
188         -- stored in the closure itself, so it will make sure that
189         -- Node points to it...
190     let
191         is_elem        = isIn "cgRhsClosure"
192
193         binder_is_a_fv = binder `is_elem` fvs
194         reduced_fvs    = if binder_is_a_fv
195                          then fvs `minusList` [binder]
196                          else fvs
197     in
198     mapFCs getCAddrModeAndInfo reduced_fvs      `thenFC` \ fvs_w_amodes_and_info ->
199     getSRTInfo srt                              `thenFC` \ srt_info ->
200     let
201         closure_info :: ClosureInfo
202         bind_details :: [((Id, CAddrMode, LambdaFormInfo), VirtualHeapOffset)]
203
204         (closure_info, bind_details)
205           = layOutDynClosure (idName binder) get_kind
206                              fvs_w_amodes_and_info lf_info srt_info
207
208         bind_fv ((id, _, lf_info), offset) = bindNewToNode id offset lf_info
209
210         amodes_w_offsets = [(amode,offset) | ((_,amode,_), offset) <- bind_details]
211
212         get_kind (id, _, _) = idPrimRep id
213     in
214         -- BUILD ITS INFO TABLE AND CODE
215     forkClosureBody (
216                 -- Bind the fvs
217             mapCs bind_fv bind_details `thenC`
218
219                 -- Bind the binder itself, if it is a free var
220             (if binder_is_a_fv then
221                 bindNewToReg binder node lf_info
222             else
223                 nopC)                                   `thenC`
224
225                 -- Compile the body
226             closureCodeBody binder_info closure_info cc args body
227     )   `thenC`
228
229         -- BUILD THE OBJECT
230     let
231         (use_cc, blame_cc) = chooseDynCostCentres cc args fvs body
232     in
233     allocDynClosure closure_info use_cc blame_cc amodes_w_offsets
234     )           `thenFC` \ heap_offset ->
235
236         -- RETURN
237     returnFC (binder, heapIdInfo binder heap_offset lf_info)
238 \end{code}
239
240 %************************************************************************
241 %*                                                                      *
242 \subsection[code-for-closures]{The code for closures}
243 %*                                                                      *
244 %************************************************************************
245
246 \begin{code}
247 closureCodeBody :: StgBinderInfo
248                 -> ClosureInfo     -- Lots of information about this closure
249                 -> CostCentreStack -- Optional cost centre attached to closure
250                 -> [Id]
251                 -> StgExpr
252                 -> Code
253 \end{code}
254
255 There are two main cases for the code for closures.  If there are {\em
256 no arguments}, then the closure is a thunk, and not in normal form.
257 So it should set up an update frame (if it is shared).  Also, it has
258 no argument satisfaction check, so fast and slow entry-point labels
259 are the same.
260
261 \begin{code}
262 closureCodeBody binder_info closure_info cc [] body
263   = -- thunks cannot have a primitive type!
264     getAbsC body_code   `thenFC` \ body_absC ->
265     moduleName          `thenFC` \ mod_name ->
266
267     absC (CClosureInfoAndCode closure_info body_absC Nothing
268                               (cl_descr mod_name))
269   where
270     cl_descr mod_name = closureDescription mod_name (closureName closure_info)
271
272     body_label   = entryLabelFromCI closure_info
273     
274     is_box  = case body of { StgApp fun [] -> True; _ -> False }
275
276     body_code   = profCtrC SLIT("TICK_ENT_THK") []              `thenC`
277                   thunkWrapper closure_info body_label (
278                         -- We only enter cc after setting up update so that cc
279                         -- of enclosing scope will be recorded in update frame
280                         -- CAF/DICT functions will be subsumed by this enclosing cc
281                     enterCostCentreCode closure_info cc IsThunk is_box `thenC`
282                     cgExpr body)
283 \end{code}
284
285 If there is {\em at least one argument}, then this closure is in
286 normal form, so there is no need to set up an update frame.  On the
287 other hand, we do have to check that there are enough args, and
288 perform an update if not!
289
290 The Macros for GrAnSim are produced at the beginning of the
291 argSatisfactionCheck (by calling fetchAndReschedule).  There info if
292 Node points to closure is available. -- HWL
293
294 \begin{code}
295 closureCodeBody binder_info closure_info cc all_args body
296   = getEntryConvention name lf_info
297                        (map idPrimRep all_args)         `thenFC` \ entry_conv ->
298
299     -- get the current virtual Sp (it might not be zero, eg. if we're
300     -- compiling a let-no-escape).
301     getVirtSp `thenFC` \vSp ->
302
303     let
304         -- Figure out what is needed and what isn't
305
306         -- SDM: need everything for now in case the heap/stack check refers
307         -- to it. (ToDo)
308         slow_code_needed   = True 
309                    --slowFunEntryCodeRequired name binder_info entry_conv
310         info_table_needed  = True
311                    --funInfoTableRequired name binder_info lf_info
312
313         -- Arg mapping for standard (slow) entry point; all args on stack,
314         -- with tagging.
315         (sp_all_args, arg_offsets, _)
316            = mkTaggedVirtStkOffsets vSp idPrimRep all_args
317
318         -- Arg mapping for the fast entry point; as many args as poss in
319         -- registers; the rest on the stack
320         --      arg_regs are the registers used for arg passing
321         --      stk_args are the args which are passed on the stack
322         --
323         -- Args passed on the stack are tagged, but the tags may not
324         -- actually be present (just gaps) if the function is called 
325         -- by jumping directly to the fast entry point.
326         --
327         arg_regs = case entry_conv of
328                 DirectEntry lbl arity regs -> regs
329                 other                      -> []  -- "(HWL ignored; no args passed in regs)"
330
331         (reg_args, stk_args) = splitAtList arg_regs all_args
332
333         (sp_stk_args, stk_offsets, stk_tags)
334           = mkTaggedVirtStkOffsets vSp idPrimRep stk_args
335
336         -- HWL; Note: empty list of live regs in slow entry code
337         -- Old version (reschedule combined with heap check);
338         -- see argSatisfactionCheck for new version
339         --slow_entry_code = forceHeapCheck [node] True slow_entry_code'
340         --                where node = UnusedReg PtrRep 1
341         --slow_entry_code = forceHeapCheck [] True slow_entry_code'
342
343         slow_entry_code
344           = profCtrC SLIT("TICK_ENT_FUN_STD") [
345                     CLbl ticky_ctr_label DataPtrRep
346             ] `thenC`
347
348             -- Bind args, and record expected position of stk ptrs
349             mapCs bindNewToStack arg_offsets                `thenC`
350             setRealAndVirtualSp sp_all_args                 `thenC`
351
352             argSatisfactionCheck closure_info   arg_regs            `thenC`
353
354             -- OK, so there are enough args.  Now we need to stuff as
355             -- many of them in registers as the fast-entry code
356             -- expects. Note that the zipWith will give up when it hits
357             -- the end of arg_regs.
358
359             mapFCs getCAddrMode all_args            `thenFC` \ stk_amodes ->
360             absC (mkAbstractCs (zipWith assign_to_reg arg_regs stk_amodes)) 
361                                                             `thenC`
362
363             -- Now adjust real stack pointers (no need to adjust Hp,
364             -- but call this function for convenience).
365             adjustSpAndHp sp_stk_args                   `thenC`
366
367             absC (CFallThrough (CLbl fast_label CodePtrRep))
368
369         assign_to_reg reg_id amode = CAssign (CReg reg_id) amode
370
371         -- HWL
372         -- Old version (reschedule combined with heap check);
373         -- see argSatisfactionCheck for new version
374         -- fast_entry_code = forceHeapCheck [] True fast_entry_code'
375
376         fast_entry_code = do
377                 mod_name <- moduleName
378                 profCtrC SLIT("TICK_CTR") [ 
379                         CLbl ticky_ctr_label DataPtrRep,
380                         mkCString (_PK_ (ppr_for_ticky_name mod_name name)),
381                         mkIntCLit stg_arity,    -- total # of args
382                         mkIntCLit sp_stk_args,  -- # passed on stk
383                         mkCString (_PK_ (map (showTypeCategory . idType) all_args))
384                         ] 
385                 let prof = 
386                         profCtrC SLIT("TICK_ENT_FUN_DIRECT") [
387                                 CLbl ticky_ctr_label DataPtrRep
388                         ] 
389
390 -- Nuked for now; see comment at end of file
391 --                  CString (_PK_ (show_wrapper_name wrapper_maybe)),
392 --                  CString (_PK_ (show_wrapper_arg_kinds wrapper_maybe))
393
394
395                 -- Bind args to regs/stack as appropriate, and
396                 -- record expected position of sps.
397                 bindArgsToRegs reg_args arg_regs                    
398                 mapCs bindNewToStack stk_offsets                    
399                 setRealAndVirtualSp sp_stk_args             
400
401                 -- free up the stack slots containing tags
402                 freeStackSlots (map fst stk_tags)
403
404                 -- Enter the closures cc, if required
405                 enterCostCentreCode closure_info cc IsFunction False
406
407                 -- Do the business
408                 funWrapper closure_info arg_regs stk_tags info_label 
409                         (prof >> cgExpr body)
410     in
411
412     setTickyCtrLabel ticky_ctr_label (
413
414         -- Make a labelled code-block for the slow and fast entry code
415       forkAbsC (if slow_code_needed then slow_entry_code else absC AbsCNop)
416                                 `thenFC` \ slow_abs_c ->
417       forkAbsC fast_entry_code  `thenFC` \ fast_abs_c ->
418       moduleName                `thenFC` \ mod_name ->
419
420         -- Now either construct the info table, or put the fast code in alone
421         -- (We never have slow code without an info table)
422         -- XXX probably need the info table and slow entry code in case of
423         -- a heap check failure.
424       absC (
425        if info_table_needed then
426           CClosureInfoAndCode closure_info slow_abs_c (Just fast_abs_c)
427                         (cl_descr mod_name)
428        else
429         CCodeBlock fast_label fast_abs_c
430        )
431     )
432   where
433     ticky_ctr_label = mkRednCountsLabel name
434
435     stg_arity = length all_args
436     lf_info = closureLFInfo closure_info
437
438     cl_descr mod_name = closureDescription mod_name name
439
440         -- Manufacture labels
441     name       = closureName closure_info
442     fast_label = mkFastEntryLabel name stg_arity
443     info_label = mkInfoTableLabel name
444
445
446 -- When printing the name of a thing in a ticky file, we want to
447 -- give the module name even for *local* things.   We print
448 -- just "x (M)" rather that "M.x" to distinguish them from the global kind.
449 ppr_for_ticky_name mod_name name
450   | isLocalName name = showSDocDebug (ppr name <+> (parens (ppr mod_name)))
451   | otherwise        = showSDocDebug (ppr name)
452 \end{code}
453
454 For lexically scoped profiling we have to load the cost centre from
455 the closure entered, if the costs are not supposed to be inherited.
456 This is done immediately on entering the fast entry point.
457
458 Load current cost centre from closure, if not inherited.
459 Node is guaranteed to point to it, if profiling and not inherited.
460
461 \begin{code}
462 data IsThunk = IsThunk | IsFunction -- Bool-like, local
463 -- #ifdef DEBUG
464         deriving Eq
465 -- #endif
466
467 enterCostCentreCode 
468    :: ClosureInfo -> CostCentreStack
469    -> IsThunk
470    -> Bool      -- is_box: this closure is a special box introduced by SCCfinal
471    -> Code
472
473 enterCostCentreCode closure_info ccs is_thunk is_box
474   = if not opt_SccProfilingOn then
475         nopC
476     else
477         ASSERT2(not (noCCSAttached ccs), ppr (closureName closure_info) <+> ppr ccs)
478
479         if isSubsumedCCS ccs then
480             ASSERT(isToplevClosure closure_info)
481             ASSERT(is_thunk == IsFunction)
482             costCentresC SLIT("ENTER_CCS_FSUB") []
483  
484         else if isCurrentCCS ccs then 
485             if re_entrant && not is_box
486                 then costCentresC SLIT("ENTER_CCS_FCL") [CReg node]
487                 else costCentresC SLIT("ENTER_CCS_TCL") [CReg node]
488
489         else if isCafCCS ccs then
490             ASSERT(isToplevClosure closure_info)
491             ASSERT(is_thunk == IsThunk)
492                 -- might be a PAP, in which case we want to subsume costs
493             if re_entrant
494                 then costCentresC SLIT("ENTER_CCS_FSUB") []
495                 else costCentresC SLIT("ENTER_CCS_CAF") c_ccs
496
497         else panic "enterCostCentreCode"
498
499    where
500         c_ccs = [mkCCostCentreStack ccs]
501         re_entrant = closureReEntrant closure_info
502 \end{code}
503
504 %************************************************************************
505 %*                                                                      *
506 \subsubsection[pre-closure-code-stuff]{Pre-closure-code code}
507 %*                                                                      *
508 %************************************************************************
509
510 The argument-satisfaction check code is placed after binding
511 the arguments to their stack locations. Hence, the virtual stack
512 pointer is pointing after all the args, and virtual offset 1 means
513 the base of frame and hence most distant arg.  Hence
514 virtual offset 0 is just beyond the most distant argument; the
515 relative offset of this word tells how many words of arguments
516 are expected.
517
518 \begin{code}
519 argSatisfactionCheck :: ClosureInfo -> [MagicId] {-GRAN-} -> Code
520
521 argSatisfactionCheck closure_info arg_regs
522
523   = nodeMustPointToIt (closureLFInfo closure_info)   `thenFC` \ node_points ->
524
525 --      let
526 --         emit_gran_macros = opt_GranMacros
527 --      in
528
529     -- HWL  ngo' ngoq:
530     -- absC (CMacroStmt GRAN_FETCH [])                  `thenC`
531     -- forceHeapCheck [] node_points (absC AbsCNop)                     `thenC`
532     --(if opt_GranMacros
533     --  then if node_points 
534     --         then fetchAndReschedule  arg_regs node_points 
535     --         else yield arg_regs node_points
536     --  else absC AbsCNop)                       `thenC`
537
538         getSpRelOffset 0        `thenFC` \ (SpRel sp) ->
539         let
540             off     = iBox sp
541             rel_arg = mkIntCLit off
542         in
543         ASSERT(off /= 0)
544         if node_points then
545             absC (CMacroStmt ARGS_CHK [rel_arg]) -- node already points
546         else
547             absC (CMacroStmt ARGS_CHK_LOAD_NODE [rel_arg, set_Node_to_this])
548   where
549     -- We must tell the arg-satis macro whether Node is pointing to
550     -- the closure or not.  If it isn't so pointing, then we give to
551     -- the macro the (static) address of the closure.
552
553     set_Node_to_this = CLbl (closureLabelFromCI closure_info) PtrRep
554 \end{code}
555
556 %************************************************************************
557 %*                                                                      *
558 \subsubsection[closure-code-wrappers]{Wrappers around closure code}
559 %*                                                                      *
560 %************************************************************************
561
562 \begin{code}
563 thunkWrapper:: ClosureInfo -> CLabel -> Code -> Code
564 thunkWrapper closure_info lbl thunk_code
565   =     -- Stack and heap overflow checks
566     nodeMustPointToIt (closureLFInfo closure_info) `thenFC` \ node_points ->
567
568     -- HWL: insert macros for GrAnSim; 2 versions depending on liveness of node
569     -- (we prefer fetchAndReschedule-style context switches to yield ones)
570     (if opt_GranMacros
571        then if node_points 
572               then fetchAndReschedule [] node_points 
573               else yield [] node_points
574        else absC AbsCNop)                       `thenC`
575
576         -- stack and/or heap checks
577     thunkChecks lbl node_points (
578
579         -- Overwrite with black hole if necessary
580     blackHoleIt closure_info node_points  `thenC`
581
582     setupUpdate closure_info (                  -- setupUpdate *encloses* the rest
583
584         -- Finally, do the business
585     thunk_code
586     ))
587
588 funWrapper :: ClosureInfo       -- Closure whose code body this is
589            -> [MagicId]         -- List of argument registers (if any)
590            -> [(VirtualSpOffset,Int)] -- tagged stack slots
591            -> CLabel            -- info table for heap check ret.
592            -> Code              -- Body of function being compiled
593            -> Code
594 funWrapper closure_info arg_regs stk_tags info_label fun_body
595   =     -- Stack overflow check
596     nodeMustPointToIt (closureLFInfo closure_info)      `thenFC` \ node_points ->
597     -- HWL   chu' ngoq:
598     (if opt_GranMacros
599        then yield arg_regs node_points
600        else absC AbsCNop)                                 `thenC`
601
602         -- heap and/or stack checks
603     fastEntryChecks arg_regs stk_tags info_label node_points (
604
605         -- Finally, do the business
606     fun_body
607     )
608 \end{code}
609
610
611 %************************************************************************
612 %*                                                                      *
613 \subsubsubsection[update-and-BHs]{Update and black-hole wrappers}
614 %*                                                                      *
615 %************************************************************************
616
617
618 \begin{code}
619 blackHoleIt :: ClosureInfo -> Bool -> Code      -- Only called for closures with no args
620
621 blackHoleIt closure_info node_points
622   = if blackHoleOnEntry closure_info && node_points
623     then
624         let
625           info_label = infoTableLabelFromCI closure_info
626           args = [ CLbl info_label DataPtrRep ]
627         in
628         absC (if closureSingleEntry(closure_info) then
629                 CMacroStmt UPD_BH_SINGLE_ENTRY args
630               else
631                 CMacroStmt UPD_BH_UPDATABLE args)
632     else
633         nopC
634 \end{code}
635
636 \begin{code}
637 setupUpdate :: ClosureInfo -> Code -> Code      -- Only called for closures with no args
638         -- Nota Bene: this function does not change Node (even if it's a CAF),
639         -- so that the cost centre in the original closure can still be
640         -- extracted by a subsequent ENTER_CC_TCL
641
642 -- I've tidied up the code for this function, but it should still do the same as
643 -- it did before (modulo ticky stuff).  KSW 1999-04.
644 setupUpdate closure_info code
645  = if closureReEntrant closure_info
646    then
647      code
648    else
649      case (closureUpdReqd closure_info, isStaticClosure closure_info) of
650        (False,False) -> profCtrC SLIT("TICK_UPDF_OMITTED") [] `thenC`
651                         code
652        (False,True ) -> (if opt_DoTickyProfiling
653                          then
654                          -- blackhole the SE CAF
655                            link_caf seCafBlackHoleClosureInfo `thenFC` \ _ -> nopC
656                          else
657                            nopC)                                                       `thenC`
658                         profCtrC SLIT("TICK_UPD_CAF_BH_SINGLE_ENTRY") [mkCString cl_name] `thenC`
659                         profCtrC SLIT("TICK_UPDF_OMITTED") []                           `thenC`
660                         code
661        (True ,False) -> pushUpdateFrame (CReg node) code
662        (True ,True ) -> -- blackhole the (updatable) CAF:
663                         link_caf cafBlackHoleClosureInfo           `thenFC` \ update_closure ->
664                         profCtrC SLIT("TICK_UPD_CAF_BH_UPDATABLE") [mkCString cl_name]    `thenC`
665                         pushUpdateFrame update_closure code
666  where
667    cl_name :: FAST_STRING
668    cl_name  = (occNameFS . nameOccName . closureName) closure_info
669
670    link_caf :: (ClosureInfo -> ClosureInfo)  -- function yielding BH closure_info
671             -> FCode CAddrMode               -- Returns amode for closure to be updated
672    link_caf bhCI
673      = -- To update a CAF we must allocate a black hole, link the CAF onto the
674        -- CAF list, then update the CAF to point to the fresh black hole.
675        -- This function returns the address of the black hole, so it can be
676        -- updated with the new value when available.
677
678              -- Alloc black hole specifying CC_HDR(Node) as the cost centre
679        let
680            use_cc   = CMacroExpr PtrRep CCS_HDR [nodeReg]
681            blame_cc = use_cc
682        in
683        allocDynClosure (bhCI closure_info) use_cc blame_cc []  `thenFC` \ heap_offset ->
684        getHpRelOffset heap_offset                              `thenFC` \ hp_rel ->
685        let  amode = CAddr hp_rel
686        in
687        absC (CMacroStmt UPD_CAF [CReg node, amode])            `thenC`
688        returnFC amode
689 \end{code}
690
691 %************************************************************************
692 %*                                                                      *
693 \subsection[CgClosure-Description]{Profiling Closure Description.}
694 %*                                                                      *
695 %************************************************************************
696
697 For "global" data constructors the description is simply occurrence
698 name of the data constructor itself (see \ref{CgConTbls-info-tables}).
699
700 Otherwise it is determind by @closureDescription@ from the let
701 binding information.
702
703 \begin{code}
704 closureDescription :: Module            -- Module
705                    -> Name              -- Id of closure binding
706                    -> String
707
708         -- Not called for StgRhsCon which have global info tables built in
709         -- CgConTbls.lhs with a description generated from the data constructor
710
711 closureDescription mod_name name
712   = showSDoc (
713         hcat [char '<',
714                    pprModule mod_name,
715                    char '.',
716                    ppr name,
717                    char '>'])
718 \end{code}
719
720 \begin{code}
721 chooseDynCostCentres ccs args fvs body
722   = let
723         use_cc -- cost-centre we record in the object
724           = if currentOrSubsumedCCS ccs
725             then CReg CurCostCentre
726             else mkCCostCentreStack ccs
727
728         blame_cc -- cost-centre on whom we blame the allocation
729           = case (args, fvs, body) of
730               ([], _, StgApp fun [{-no args-}])
731                 -> mkCCostCentreStack overheadCCS
732               _ -> use_cc
733
734             -- if it's an utterly trivial RHS, then it must be
735             -- one introduced by boxHigherOrderArgs for profiling,
736             -- so we charge it to "OVERHEAD".
737
738             -- This looks like a HACK to me --SDM
739     in
740     (use_cc, blame_cc)
741 \end{code}