[project @ 1999-11-01 17:09:54 by simonpj]
[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.36 1999/11/01 17:10:07 simonpj 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 )
55 import CmdLineOpts      ( opt_SccProfilingOn )
56 import Outputable
57
58 import Name             ( nameOccName )
59 import OccName          ( occNameFS )
60
61 getWrapperArgTypeCategories = panic "CgClosure.getWrapperArgTypeCategories (ToDo)"
62 \end{code}
63
64 %********************************************************
65 %*                                                      *
66 \subsection[closures-no-free-vars]{Top-level closures}
67 %*                                                      *
68 %********************************************************
69
70 For closures bound at top level, allocate in static space.
71 They should have no free variables.
72
73 \begin{code}
74 cgTopRhsClosure :: Id
75                 -> CostCentreStack      -- Optional cost centre annotation
76                 -> StgBinderInfo
77                 -> [Id]         -- Args
78                 -> StgExpr
79                 -> LambdaFormInfo
80                 -> FCode (Id, CgIdInfo)
81
82 cgTopRhsClosure id ccs binder_info args body lf_info
83   =     -- LAY OUT THE OBJECT
84     let
85         closure_info = layOutStaticNoFVClosure name lf_info
86     in
87
88         -- BUILD THE OBJECT (IF NECESSARY)
89     ({- if staticClosureRequired name binder_info lf_info
90      then -}
91         (if opt_SccProfilingOn 
92           then
93              absC (CStaticClosure
94                 closure_label   -- Labelled with the name on lhs of defn
95                 closure_info
96                 (mkCCostCentreStack ccs)
97                 [])             -- No fields
98           else
99              absC (CStaticClosure
100                 closure_label   -- Labelled with the name on lhs of defn
101                 closure_info
102                 (panic "absent cc")
103                 [])             -- No fields
104         )
105
106      {- else
107         nopC -}
108                                                         `thenC`
109
110         -- GENERATE THE INFO TABLE (IF NECESSARY)
111     forkClosureBody (closureCodeBody binder_info closure_info
112                                          ccs args body)
113
114     ) `thenC`
115
116     returnFC (id, cg_id_info)
117   where
118     name          = idName id
119     closure_label = mkClosureLabel name
120     cg_id_info    = stableAmodeIdInfo id (CLbl closure_label PtrRep) lf_info
121 \end{code}
122
123 %********************************************************
124 %*                                                      *
125 \subsection[non-top-level-closures]{Non top-level closures}
126 %*                                                      *
127 %********************************************************
128
129 For closures with free vars, allocate in heap.
130
131 \begin{code}
132 cgStdRhsClosure
133         :: Id
134         -> CostCentreStack      -- Optional cost centre annotation
135         -> StgBinderInfo
136         -> [Id]                 -- Free vars
137         -> [Id]                 -- Args
138         -> StgExpr
139         -> LambdaFormInfo
140         -> [StgArg]             -- payload
141         -> FCode (Id, CgIdInfo)
142
143 cgStdRhsClosure binder cc binder_info fvs args body lf_info payload
144                 -- AHA!  A STANDARD-FORM THUNK
145   = (
146         -- LAY OUT THE OBJECT
147     getArgAmodes payload                        `thenFC` \ amodes ->
148     let
149         (closure_info, amodes_w_offsets)
150           = layOutDynClosure (idName binder) getAmodeRep amodes lf_info
151
152         (use_cc, blame_cc) = chooseDynCostCentres cc args fvs body
153     in
154         -- BUILD THE OBJECT
155     allocDynClosure closure_info use_cc blame_cc amodes_w_offsets
156     )
157                 `thenFC` \ heap_offset ->
158
159         -- RETURN
160     returnFC (binder, heapIdInfo binder heap_offset lf_info)
161
162   where
163     is_std_thunk           = isStandardFormThunk 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                 -> [Id]                 -- Free vars
173                 -> [Id]                 -- Args
174                 -> StgExpr
175                 -> LambdaFormInfo
176                 -> FCode (Id, CgIdInfo)
177
178 cgRhsClosure binder cc binder_info fvs args body lf_info
179   = (
180         -- LAY OUT THE OBJECT
181         --
182         -- If the binder is itself a free variable, then don't store
183         -- it in the closure.  Instead, just bind it to Node on entry.
184         -- NB we can be sure that Node will point to it, because we
185         -- havn't told mkClosureLFInfo about this; so if the binder
186         -- *was* a free var of its RHS, mkClosureLFInfo thinks it *is*
187         -- stored in the closure itself, so it will make sure that
188         -- Node points to it...
189     let
190         is_elem        = isIn "cgRhsClosure"
191
192         binder_is_a_fv = binder `is_elem` fvs
193         reduced_fvs    = if binder_is_a_fv
194                          then fvs `minusList` [binder]
195                          else fvs
196     in
197     mapFCs getCAddrModeAndInfo reduced_fvs      `thenFC` \ amodes_and_info ->
198     let
199         fvs_w_amodes_and_info         = reduced_fvs `zip` amodes_and_info
200
201         closure_info :: ClosureInfo
202         bind_details :: [((Id, (CAddrMode, LambdaFormInfo)), VirtualHeapOffset)]
203
204         (closure_info, bind_details)
205           = layOutDynClosure (idName binder) get_kind fvs_w_amodes_and_info lf_info
206
207         bind_fv ((id, (_, lf_info)), offset) = bindNewToNode id offset lf_info
208
209         amodes_w_offsets = [(amode,offset) | ((_, (amode,_)), offset) <- bind_details]
210
211         get_kind (id, amode_and_info) = idPrimRep id
212     in
213         -- BUILD ITS INFO TABLE AND CODE
214     forkClosureBody (
215                 -- Bind the fvs
216             mapCs bind_fv bind_details `thenC`
217
218                 -- Bind the binder itself, if it is a free var
219             (if binder_is_a_fv then
220                 bindNewToReg binder node lf_info
221             else
222                 nopC)                                   `thenC`
223
224                 -- Compile the body
225             closureCodeBody binder_info closure_info cc args body
226     )   `thenC`
227
228         -- BUILD THE OBJECT
229     let
230         (use_cc, blame_cc) = chooseDynCostCentres cc args fvs body
231     in
232     allocDynClosure closure_info use_cc blame_cc amodes_w_offsets
233     )           `thenFC` \ heap_offset ->
234
235         -- RETURN
236     returnFC (binder, heapIdInfo binder heap_offset lf_info)
237 \end{code}
238
239 %************************************************************************
240 %*                                                                      *
241 \subsection[code-for-closures]{The code for closures}
242 %*                                                                      *
243 %************************************************************************
244
245 \begin{code}
246 closureCodeBody :: StgBinderInfo
247                 -> ClosureInfo     -- Lots of information about this closure
248                 -> CostCentreStack -- Optional cost centre attached to closure
249                 -> [Id]
250                 -> StgExpr
251                 -> Code
252 \end{code}
253
254 There are two main cases for the code for closures.  If there are {\em
255 no arguments}, then the closure is a thunk, and not in normal form.
256 So it should set up an update frame (if it is shared).  Also, it has
257 no argument satisfaction check, so fast and slow entry-point labels
258 are the same.
259
260 \begin{code}
261 closureCodeBody binder_info closure_info cc [] body
262   = -- thunks cannot have a primitive type!
263     getAbsC body_code   `thenFC` \ body_absC ->
264     moduleName          `thenFC` \ mod_name ->
265
266     absC (CClosureInfoAndCode closure_info body_absC Nothing
267                               (cl_descr mod_name))
268   where
269     cl_descr mod_name = closureDescription mod_name (closureName closure_info)
270
271     body_label   = entryLabelFromCI closure_info
272     is_box  = case body of { StgApp fun [] -> True; _ -> False }
273
274     body_code   = profCtrC SLIT("TICK_ENT_THK") []              `thenC`
275                   thunkWrapper closure_info body_label (
276                         -- We only enter cc after setting up update so that cc
277                         -- of enclosing scope will be recorded in update frame
278                         -- CAF/DICT functions will be subsumed by this enclosing cc
279                     enterCostCentreCode closure_info cc IsThunk is_box `thenC`
280                     cgExpr body)
281 \end{code}
282
283 If there is {\em at least one argument}, then this closure is in
284 normal form, so there is no need to set up an update frame.  On the
285 other hand, we do have to check that there are enough args, and
286 perform an update if not!
287
288 The Macros for GrAnSim are produced at the beginning of the
289 argSatisfactionCheck (by calling fetchAndReschedule).  There info if
290 Node points to closure is available. -- HWL
291
292 \begin{code}
293 closureCodeBody binder_info closure_info cc all_args body
294   = getEntryConvention name lf_info
295                        (map idPrimRep all_args)         `thenFC` \ entry_conv ->
296
297     -- get the current virtual Sp (it might not be zero, eg. if we're
298     -- compiling a let-no-escape).
299     getVirtSp `thenFC` \vSp ->
300
301     let
302         -- Figure out what is needed and what isn't
303
304         -- SDM: need everything for now in case the heap/stack check refers
305         -- to it. (ToDo)
306         slow_code_needed   = True 
307                    --slowFunEntryCodeRequired name binder_info entry_conv
308         info_table_needed  = True
309                    --funInfoTableRequired name binder_info lf_info
310
311         -- Arg mapping for standard (slow) entry point; all args on stack,
312         -- with tagging.
313         (sp_all_args, arg_offsets, arg_tags)
314            = mkTaggedVirtStkOffsets vSp idPrimRep all_args
315
316         -- Arg mapping for the fast entry point; as many args as poss in
317         -- registers; the rest on the stack
318         --      arg_regs are the registers used for arg passing
319         --      stk_args are the args which are passed on the stack
320         --
321         -- Args passed on the stack are tagged, but the tags may not
322         -- actually be present (just gaps) if the function is called 
323         -- by jumping directly to the fast entry point.
324         --
325         arg_regs = case entry_conv of
326                 DirectEntry lbl arity regs -> regs
327                 other                       -> panic "closureCodeBody:arg_regs"
328
329         num_arg_regs = length arg_regs
330         
331         (reg_args, stk_args) = splitAt num_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") []            `thenC`
345
346             -- Bind args, and record expected position of stk ptrs
347             mapCs bindNewToStack arg_offsets                `thenC`
348             setRealAndVirtualSp sp_all_args                 `thenC`
349
350             argSatisfactionCheck closure_info               `thenC`
351
352             -- OK, so there are enough args.  Now we need to stuff as
353             -- many of them in registers as the fast-entry code
354             -- expects. Note that the zipWith will give up when it hits
355             -- the end of arg_regs.
356
357             mapFCs getCAddrMode all_args            `thenFC` \ stk_amodes ->
358             absC (mkAbstractCs (zipWith assign_to_reg arg_regs stk_amodes)) 
359                                                             `thenC`
360
361             -- Now adjust real stack pointers (no need to adjust Hp,
362             -- but call this function for convenience).
363             adjustSpAndHp sp_stk_args                   `thenC`
364
365             absC (CFallThrough (CLbl fast_label CodePtrRep))
366
367         assign_to_reg reg_id amode = CAssign (CReg reg_id) amode
368
369         -- HWL
370         -- Old version (reschedule combined with heap check);
371         -- see argSatisfactionCheck for new version
372         -- fast_entry_code = forceHeapCheck [] True fast_entry_code'
373
374         fast_entry_code
375           = moduleName          `thenFC` \ mod_name ->
376             profCtrC SLIT("TICK_CTR") [ 
377                 CLbl ticky_ctr_label DataPtrRep,
378                 mkCString (_PK_ (ppr_for_ticky_name mod_name name)),
379                 mkIntCLit stg_arity,    -- total # of args
380                 mkIntCLit sp_stk_args,  -- # passed on stk
381                 mkCString (_PK_ (map (showTypeCategory . idType) all_args))
382             ] `thenC`
383
384             profCtrC SLIT("TICK_ENT_FUN_DIRECT") [
385                     CLbl ticky_ctr_label DataPtrRep
386             ] `thenC`
387
388 -- Nuked for now; see comment at end of file
389 --                  CString (_PK_ (show_wrapper_name wrapper_maybe)),
390 --                  CString (_PK_ (show_wrapper_arg_kinds wrapper_maybe))
391
392
393                 -- Bind args to regs/stack as appropriate, and
394                 -- record expected position of sps.
395             bindArgsToRegs reg_args arg_regs                `thenC`
396             mapCs bindNewToStack stk_offsets                `thenC`
397             setRealAndVirtualSp sp_stk_args                 `thenC`
398
399                 -- free up the stack slots containing tags
400             freeStackSlots (map fst stk_tags)               `thenC`
401
402                 -- Enter the closures cc, if required
403             enterCostCentreCode closure_info cc IsFunction False `thenC`
404
405                 -- Do the business
406             funWrapper closure_info arg_regs stk_tags info_label (cgExpr body)
407     in
408
409     setTickyCtrLabel ticky_ctr_label (
410
411         -- Make a labelled code-block for the slow and fast entry code
412       forkAbsC (if slow_code_needed then slow_entry_code else absC AbsCNop)
413                                 `thenFC` \ slow_abs_c ->
414       forkAbsC fast_entry_code  `thenFC` \ fast_abs_c ->
415       moduleName                        `thenFC` \ mod_name ->
416
417         -- Now either construct the info table, or put the fast code in alone
418         -- (We never have slow code without an info table)
419         -- XXX probably need the info table and slow entry code in case of
420         -- a heap check failure.
421       absC (
422        if info_table_needed then
423           CClosureInfoAndCode closure_info slow_abs_c (Just fast_abs_c)
424                         (cl_descr mod_name)
425        else
426         CCodeBlock fast_label fast_abs_c
427        )
428     )
429   where
430     ticky_ctr_label = mkRednCountsLabel name
431
432     stg_arity = length all_args
433     lf_info = closureLFInfo closure_info
434
435     cl_descr mod_name = closureDescription mod_name name
436
437         -- Manufacture labels
438     name       = closureName closure_info
439     fast_label = mkFastEntryLabel name stg_arity
440     info_label = mkInfoTableLabel name
441
442
443 -- When printing the name of a thing in a ticky file, we want to
444 -- give the module name even for *local* things.   We print
445 -- just "x (M)" rather that "M.x" to distinguish them from the global kind.
446 ppr_for_ticky_name mod_name name
447   | isLocalName name = showSDocDebug (ppr name <+> (parens (ppr mod_name)))
448   | otherwise        = showSDocDebug (ppr name)
449 \end{code}
450
451 For lexically scoped profiling we have to load the cost centre from
452 the closure entered, if the costs are not supposed to be inherited.
453 This is done immediately on entering the fast entry point.
454
455 Load current cost centre from closure, if not inherited.
456 Node is guaranteed to point to it, if profiling and not inherited.
457
458 \begin{code}
459 data IsThunk = IsThunk | IsFunction -- Bool-like, local
460 -- #ifdef DEBUG
461         deriving Eq
462 -- #endif
463
464 enterCostCentreCode 
465    :: ClosureInfo -> CostCentreStack
466    -> IsThunk
467    -> Bool      -- is_box: this closure is a special box introduced by SCCfinal
468    -> Code
469
470 enterCostCentreCode closure_info ccs is_thunk is_box
471   = if not opt_SccProfilingOn then
472         nopC
473     else
474         ASSERT(not (noCCSAttached ccs))
475
476         if isSubsumedCCS ccs then
477             ASSERT(isToplevClosure closure_info)
478             ASSERT(is_thunk == IsFunction)
479             costCentresC SLIT("ENTER_CCS_FSUB") []
480  
481         else if isCurrentCCS ccs then 
482             if re_entrant && not is_box
483                 then costCentresC SLIT("ENTER_CCS_FCL") [CReg node]
484                 else costCentresC SLIT("ENTER_CCS_TCL") [CReg node]
485
486         else if isCafCCS ccs then
487             ASSERT(isToplevClosure closure_info)
488             ASSERT(is_thunk == IsThunk)
489                 -- might be a PAP, in which case we want to subsume costs
490             if re_entrant
491                 then costCentresC SLIT("ENTER_CCS_FSUB") []
492                 else costCentresC SLIT("ENTER_CCS_CAF") c_ccs
493
494         else panic "enterCostCentreCode"
495
496    where
497         c_ccs = [mkCCostCentreStack ccs]
498         re_entrant = closureReEntrant closure_info
499 \end{code}
500
501 %************************************************************************
502 %*                                                                      *
503 \subsubsection[pre-closure-code-stuff]{Pre-closure-code code}
504 %*                                                                      *
505 %************************************************************************
506
507 The argument-satisfaction check code is placed after binding
508 the arguments to their stack locations. Hence, the virtual stack
509 pointer is pointing after all the args, and virtual offset 1 means
510 the base of frame and hence most distant arg.  Hence
511 virtual offset 0 is just beyond the most distant argument; the
512 relative offset of this word tells how many words of arguments
513 are expected.
514
515 \begin{code}
516 argSatisfactionCheck :: ClosureInfo -> Code
517
518 argSatisfactionCheck closure_info
519
520   = nodeMustPointToIt (closureLFInfo closure_info)   `thenFC` \ node_points ->
521
522     let
523        emit_gran_macros = opt_GranMacros
524     in
525
526     -- HWL  ngo' ngoq:
527     -- absC (CMacroStmt GRAN_FETCH [])                  `thenC`
528     -- forceHeapCheck [] node_points (absC AbsCNop)                     `thenC`
529     (if emit_gran_macros 
530       then if node_points 
531              then fetchAndReschedule  [] node_points 
532              else yield [] node_points
533       else absC AbsCNop)                       `thenC`
534
535         getSpRelOffset 0        `thenFC` \ (SpRel sp) ->
536         let
537             off = I# sp
538             rel_arg = mkIntCLit off
539         in
540         ASSERT(off /= 0)
541         if node_points then
542             absC (CMacroStmt ARGS_CHK [rel_arg]) -- node already points
543         else
544             absC (CMacroStmt ARGS_CHK_LOAD_NODE [rel_arg, set_Node_to_this])
545   where
546     -- We must tell the arg-satis macro whether Node is pointing to
547     -- the closure or not.  If it isn't so pointing, then we give to
548     -- the macro the (static) address of the closure.
549
550     set_Node_to_this = CLbl (closureLabelFromCI closure_info) PtrRep
551 \end{code}
552
553 %************************************************************************
554 %*                                                                      *
555 \subsubsection[closure-code-wrappers]{Wrappers around closure code}
556 %*                                                                      *
557 %************************************************************************
558
559 \begin{code}
560 thunkWrapper:: ClosureInfo -> CLabel -> Code -> Code
561 thunkWrapper closure_info lbl thunk_code
562   =     -- Stack and heap overflow checks
563     nodeMustPointToIt (closureLFInfo closure_info) `thenFC` \ node_points ->
564
565     let
566        emit_gran_macros = opt_GranMacros
567     in
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 emit_gran_macros 
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     let
598        emit_gran_macros = opt_GranMacros
599     in
600     -- HWL   chu' ngoq:
601     (if emit_gran_macros
602       then yield  arg_regs node_points
603       else absC AbsCNop)                                 `thenC`
604
605         -- heap and/or stack checks
606     fastEntryChecks arg_regs stk_tags info_label node_points (
607
608         -- Finally, do the business
609     fun_body
610     )
611 \end{code}
612
613
614 %************************************************************************
615 %*                                                                      *
616 \subsubsubsection[update-and-BHs]{Update and black-hole wrappers}
617 %*                                                                      *
618 %************************************************************************
619
620
621 \begin{code}
622 blackHoleIt :: ClosureInfo -> Bool -> Code      -- Only called for closures with no args
623
624 blackHoleIt closure_info node_points
625   = if blackHoleOnEntry closure_info && node_points
626     then
627         absC (if closureSingleEntry(closure_info) then
628                 CMacroStmt UPD_BH_SINGLE_ENTRY [CReg node]
629               else
630                 CMacroStmt UPD_BH_UPDATABLE [CReg node])
631     else
632         nopC
633 \end{code}
634
635 \begin{code}
636 setupUpdate :: ClosureInfo -> Code -> Code      -- Only called for closures with no args
637         -- Nota Bene: this function does not change Node (even if it's a CAF),
638         -- so that the cost centre in the original closure can still be
639         -- extracted by a subsequent ENTER_CC_TCL
640
641 -- I've tidied up the code for this function, but it should still do the same as
642 -- it did before (modulo ticky stuff).  KSW 1999-04.
643 setupUpdate closure_info code
644  = if closureReEntrant closure_info
645    then
646      code
647    else
648      case (closureUpdReqd closure_info, isStaticClosure closure_info) of
649        (False,False) -> profCtrC SLIT("TICK_UPDF_OMITTED") [] `thenC`
650                         code
651        (False,True ) -> (if opt_DoTickyProfiling
652                          then
653                          -- blackhole the SE CAF
654                            link_caf seCafBlackHoleClosureInfo `thenFC` \ _ -> nopC
655                          else
656                            nopC)                                                       `thenC`
657                         profCtrC SLIT("TICK_UPD_CAF_BH_SINGLE_ENTRY") [mkCString cl_name] `thenC`
658                         profCtrC SLIT("TICK_UPDF_OMITTED") []                           `thenC`
659                         code
660        (True ,False) -> pushUpdateFrame (CReg node) code
661        (True ,True ) -> -- blackhole the (updatable) CAF:
662                         link_caf cafBlackHoleClosureInfo           `thenFC` \ update_closure ->
663                         profCtrC SLIT("TICK_UPD_CAF_BH_UPDATABLE") [mkCString cl_name]    `thenC`
664                         pushUpdateFrame update_closure code
665  where
666    cl_name :: FAST_STRING
667    cl_name  = (occNameFS . nameOccName . closureName) closure_info
668
669    link_caf :: (ClosureInfo -> ClosureInfo)  -- function yielding BH closure_info
670             -> FCode CAddrMode               -- Returns amode for closure to be updated
671    link_caf bhCI
672      = -- To update a CAF we must allocate a black hole, link the CAF onto the
673        -- CAF list, then update the CAF to point to the fresh black hole.
674        -- This function returns the address of the black hole, so it can be
675        -- updated with the new value when available.
676
677              -- Alloc black hole specifying CC_HDR(Node) as the cost centre
678              --   Hack Warning: Using a CLitLit to get CAddrMode !
679        let
680            use_cc   = CLitLit SLIT("CCS_HDR(R1.p)") PtrRep
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}
742
743
744
745 ========================================================================
746 OLD CODE THAT EMITTED INFORMATON FOR QUANTITATIVE ANALYSIS
747
748 It's pretty wierd, so I've nuked it for now.  SLPJ Nov 96
749
750 \begin{pseudocode}
751 getWrapperArgTypeCategories
752         :: Type                         -- wrapper's type
753         -> StrictnessInfo bdee          -- strictness info about its args
754         -> Maybe String
755
756 getWrapperArgTypeCategories _ NoStrictnessInfo      = Nothing
757 getWrapperArgTypeCategories _ BottomGuaranteed
758   = trace "getWrapperArgTypeCategories:BottomGuaranteed!" Nothing  -- wrong
759 getWrapperArgTypeCategories _ (StrictnessInfo [] _) = Nothing
760
761 getWrapperArgTypeCategories ty (StrictnessInfo arg_info _)
762   = Just (mkWrapperArgTypeCategories ty arg_info)
763
764 mkWrapperArgTypeCategories
765         :: Type         -- wrapper's type
766         -> [Demand]     -- info about its arguments
767         -> String       -- a string saying lots about the args
768
769 mkWrapperArgTypeCategories wrapper_ty wrap_info
770   = case (splitFunTy_maybe wrapper_ty) of { Just (arg_tys,_) ->
771     map do_one (wrap_info `zip` (map showTypeCategory arg_tys)) }
772   where
773     -- ToDo: this needs FIXING UP (it was a hack anyway...)
774     do_one (WwPrim, _) = 'P'
775     do_one (WwEnum, _) = 'E'
776     do_one (WwStrict, arg_ty_char) = arg_ty_char
777     do_one (WwUnpack _ _ _, arg_ty_char)
778       = if arg_ty_char `elem` "CIJFDTS"
779         then toLower arg_ty_char
780         else if arg_ty_char == '+' then 't'
781         else trace ("mkWrapp..:funny char:"++[arg_ty_char]) '-'
782     do_one (other_wrap_info, _) = '-'
783 \end{pseudocode}
784