[project @ 1999-11-02 15:05:38 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.37 1999/11/02 15:05:43 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 )
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     
273     is_box  = case body of { StgApp fun [] -> True; _ -> False }
274
275     body_code   = profCtrC SLIT("TICK_ENT_THK") []              `thenC`
276                   thunkWrapper closure_info body_label (
277                         -- We only enter cc after setting up update so that cc
278                         -- of enclosing scope will be recorded in update frame
279                         -- CAF/DICT functions will be subsumed by this enclosing cc
280                     enterCostCentreCode closure_info cc IsThunk is_box `thenC`
281                     cgExpr body)
282 \end{code}
283
284 If there is {\em at least one argument}, then this closure is in
285 normal form, so there is no need to set up an update frame.  On the
286 other hand, we do have to check that there are enough args, and
287 perform an update if not!
288
289 The Macros for GrAnSim are produced at the beginning of the
290 argSatisfactionCheck (by calling fetchAndReschedule).  There info if
291 Node points to closure is available. -- HWL
292
293 \begin{code}
294 closureCodeBody binder_info closure_info cc all_args body
295   = getEntryConvention name lf_info
296                        (map idPrimRep all_args)         `thenFC` \ entry_conv ->
297
298     -- get the current virtual Sp (it might not be zero, eg. if we're
299     -- compiling a let-no-escape).
300     getVirtSp `thenFC` \vSp ->
301
302     let
303         -- Figure out what is needed and what isn't
304
305         -- SDM: need everything for now in case the heap/stack check refers
306         -- to it. (ToDo)
307         slow_code_needed   = True 
308                    --slowFunEntryCodeRequired name binder_info entry_conv
309         info_table_needed  = True
310                    --funInfoTableRequired name binder_info lf_info
311
312         -- Arg mapping for standard (slow) entry point; all args on stack,
313         -- with tagging.
314         (sp_all_args, arg_offsets, arg_tags)
315            = mkTaggedVirtStkOffsets vSp idPrimRep all_args
316
317         -- Arg mapping for the fast entry point; as many args as poss in
318         -- registers; the rest on the stack
319         --      arg_regs are the registers used for arg passing
320         --      stk_args are the args which are passed on the stack
321         --
322         -- Args passed on the stack are tagged, but the tags may not
323         -- actually be present (just gaps) if the function is called 
324         -- by jumping directly to the fast entry point.
325         --
326         arg_regs = case entry_conv of
327                 DirectEntry lbl arity regs -> regs
328                 other                       -> panic "closureCodeBody:arg_regs"
329
330         num_arg_regs = length arg_regs
331         
332         (reg_args, stk_args) = splitAt num_arg_regs all_args
333
334         (sp_stk_args, stk_offsets, stk_tags)
335           = mkTaggedVirtStkOffsets vSp idPrimRep stk_args
336
337         -- HWL; Note: empty list of live regs in slow entry code
338         -- Old version (reschedule combined with heap check);
339         -- see argSatisfactionCheck for new version
340         --slow_entry_code = forceHeapCheck [node] True slow_entry_code'
341         --                where node = UnusedReg PtrRep 1
342         --slow_entry_code = forceHeapCheck [] True slow_entry_code'
343
344         slow_entry_code
345           = profCtrC SLIT("TICK_ENT_FUN_STD") []            `thenC`
346
347             -- Bind args, and record expected position of stk ptrs
348             mapCs bindNewToStack arg_offsets                `thenC`
349             setRealAndVirtualSp sp_all_args                 `thenC`
350
351             argSatisfactionCheck closure_info               `thenC`
352
353             -- OK, so there are enough args.  Now we need to stuff as
354             -- many of them in registers as the fast-entry code
355             -- expects. Note that the zipWith will give up when it hits
356             -- the end of arg_regs.
357
358             mapFCs getCAddrMode all_args            `thenFC` \ stk_amodes ->
359             absC (mkAbstractCs (zipWith assign_to_reg arg_regs stk_amodes)) 
360                                                             `thenC`
361
362             -- Now adjust real stack pointers (no need to adjust Hp,
363             -- but call this function for convenience).
364             adjustSpAndHp sp_stk_args                   `thenC`
365
366             absC (CFallThrough (CLbl fast_label CodePtrRep))
367
368         assign_to_reg reg_id amode = CAssign (CReg reg_id) amode
369
370         -- HWL
371         -- Old version (reschedule combined with heap check);
372         -- see argSatisfactionCheck for new version
373         -- fast_entry_code = forceHeapCheck [] True fast_entry_code'
374
375         fast_entry_code
376           = moduleName          `thenFC` \ mod_name ->
377             profCtrC SLIT("TICK_CTR") [ 
378                 CLbl ticky_ctr_label DataPtrRep,
379                 mkCString (_PK_ (ppr_for_ticky_name mod_name name)),
380                 mkIntCLit stg_arity,    -- total # of args
381                 mkIntCLit sp_stk_args,  -- # passed on stk
382                 mkCString (_PK_ (map (showTypeCategory . idType) all_args))
383             ] `thenC`
384
385             profCtrC SLIT("TICK_ENT_FUN_DIRECT") [
386                     CLbl ticky_ctr_label DataPtrRep
387             ] `thenC`
388
389 -- Nuked for now; see comment at end of file
390 --                  CString (_PK_ (show_wrapper_name wrapper_maybe)),
391 --                  CString (_PK_ (show_wrapper_arg_kinds wrapper_maybe))
392
393
394                 -- Bind args to regs/stack as appropriate, and
395                 -- record expected position of sps.
396             bindArgsToRegs reg_args arg_regs                `thenC`
397             mapCs bindNewToStack stk_offsets                `thenC`
398             setRealAndVirtualSp sp_stk_args                 `thenC`
399
400                 -- free up the stack slots containing tags
401             freeStackSlots (map fst stk_tags)               `thenC`
402
403                 -- Enter the closures cc, if required
404             enterCostCentreCode closure_info cc IsFunction False `thenC`
405
406                 -- Do the business
407             funWrapper closure_info arg_regs stk_tags info_label (cgExpr body)
408     in
409
410     setTickyCtrLabel ticky_ctr_label (
411
412         -- Make a labelled code-block for the slow and fast entry code
413       forkAbsC (if slow_code_needed then slow_entry_code else absC AbsCNop)
414                                 `thenFC` \ slow_abs_c ->
415       forkAbsC fast_entry_code  `thenFC` \ fast_abs_c ->
416       moduleName                        `thenFC` \ mod_name ->
417
418         -- Now either construct the info table, or put the fast code in alone
419         -- (We never have slow code without an info table)
420         -- XXX probably need the info table and slow entry code in case of
421         -- a heap check failure.
422       absC (
423        if info_table_needed then
424           CClosureInfoAndCode closure_info slow_abs_c (Just fast_abs_c)
425                         (cl_descr mod_name)
426        else
427         CCodeBlock fast_label fast_abs_c
428        )
429     )
430   where
431     ticky_ctr_label = mkRednCountsLabel name
432
433     stg_arity = length all_args
434     lf_info = closureLFInfo closure_info
435
436     cl_descr mod_name = closureDescription mod_name name
437
438         -- Manufacture labels
439     name       = closureName closure_info
440     fast_label = mkFastEntryLabel name stg_arity
441     info_label = mkInfoTableLabel name
442
443
444 -- When printing the name of a thing in a ticky file, we want to
445 -- give the module name even for *local* things.   We print
446 -- just "x (M)" rather that "M.x" to distinguish them from the global kind.
447 ppr_for_ticky_name mod_name name
448   | isLocalName name = showSDocDebug (ppr name <+> (parens (ppr mod_name)))
449   | otherwise        = showSDocDebug (ppr name)
450 \end{code}
451
452 For lexically scoped profiling we have to load the cost centre from
453 the closure entered, if the costs are not supposed to be inherited.
454 This is done immediately on entering the fast entry point.
455
456 Load current cost centre from closure, if not inherited.
457 Node is guaranteed to point to it, if profiling and not inherited.
458
459 \begin{code}
460 data IsThunk = IsThunk | IsFunction -- Bool-like, local
461 -- #ifdef DEBUG
462         deriving Eq
463 -- #endif
464
465 enterCostCentreCode 
466    :: ClosureInfo -> CostCentreStack
467    -> IsThunk
468    -> Bool      -- is_box: this closure is a special box introduced by SCCfinal
469    -> Code
470
471 enterCostCentreCode closure_info ccs is_thunk is_box
472   = if not opt_SccProfilingOn then
473         nopC
474     else
475         ASSERT(not (noCCSAttached ccs))
476
477         if isSubsumedCCS ccs then
478             ASSERT(isToplevClosure closure_info)
479             ASSERT(is_thunk == IsFunction)
480             costCentresC SLIT("ENTER_CCS_FSUB") []
481  
482         else if isCurrentCCS ccs then 
483             if re_entrant && not is_box
484                 then costCentresC SLIT("ENTER_CCS_FCL") [CReg node]
485                 else costCentresC SLIT("ENTER_CCS_TCL") [CReg node]
486
487         else if isCafCCS ccs then
488             ASSERT(isToplevClosure closure_info)
489             ASSERT(is_thunk == IsThunk)
490                 -- might be a PAP, in which case we want to subsume costs
491             if re_entrant
492                 then costCentresC SLIT("ENTER_CCS_FSUB") []
493                 else costCentresC SLIT("ENTER_CCS_CAF") c_ccs
494
495         else panic "enterCostCentreCode"
496
497    where
498         c_ccs = [mkCCostCentreStack ccs]
499         re_entrant = closureReEntrant closure_info
500 \end{code}
501
502 %************************************************************************
503 %*                                                                      *
504 \subsubsection[pre-closure-code-stuff]{Pre-closure-code code}
505 %*                                                                      *
506 %************************************************************************
507
508 The argument-satisfaction check code is placed after binding
509 the arguments to their stack locations. Hence, the virtual stack
510 pointer is pointing after all the args, and virtual offset 1 means
511 the base of frame and hence most distant arg.  Hence
512 virtual offset 0 is just beyond the most distant argument; the
513 relative offset of this word tells how many words of arguments
514 are expected.
515
516 \begin{code}
517 argSatisfactionCheck :: ClosureInfo -> Code
518
519 argSatisfactionCheck closure_info
520
521   = nodeMustPointToIt (closureLFInfo closure_info)   `thenFC` \ node_points ->
522
523     let
524        emit_gran_macros = opt_GranMacros
525     in
526
527     -- HWL  ngo' ngoq:
528     -- absC (CMacroStmt GRAN_FETCH [])                  `thenC`
529     -- forceHeapCheck [] node_points (absC AbsCNop)                     `thenC`
530     (if emit_gran_macros 
531       then if node_points 
532              then fetchAndReschedule  [] node_points 
533              else yield [] node_points
534       else absC AbsCNop)                       `thenC`
535
536         getSpRelOffset 0        `thenFC` \ (SpRel sp) ->
537         let
538             off = I# sp
539             rel_arg = mkIntCLit off
540         in
541         ASSERT(off /= 0)
542         if node_points then
543             absC (CMacroStmt ARGS_CHK [rel_arg]) -- node already points
544         else
545             absC (CMacroStmt ARGS_CHK_LOAD_NODE [rel_arg, set_Node_to_this])
546   where
547     -- We must tell the arg-satis macro whether Node is pointing to
548     -- the closure or not.  If it isn't so pointing, then we give to
549     -- the macro the (static) address of the closure.
550
551     set_Node_to_this = CLbl (closureLabelFromCI closure_info) PtrRep
552 \end{code}
553
554 %************************************************************************
555 %*                                                                      *
556 \subsubsection[closure-code-wrappers]{Wrappers around closure code}
557 %*                                                                      *
558 %************************************************************************
559
560 \begin{code}
561 thunkWrapper:: ClosureInfo -> CLabel -> Code -> Code
562 thunkWrapper closure_info lbl thunk_code
563   =     -- Stack and heap overflow checks
564     nodeMustPointToIt (closureLFInfo closure_info) `thenFC` \ node_points ->
565
566     let
567        emit_gran_macros = opt_GranMacros
568     in
569         -- HWL: insert macros for GrAnSim; 2 versions depending on liveness of node
570         -- (we prefer fetchAndReschedule-style context switches to yield ones)
571     (if emit_gran_macros 
572       then if node_points 
573              then fetchAndReschedule  [] node_points 
574              else yield [] node_points
575       else absC AbsCNop)                       `thenC`
576
577         -- stack and/or heap checks
578     thunkChecks lbl node_points (
579
580         -- Overwrite with black hole if necessary
581     blackHoleIt closure_info node_points  `thenC`
582
583     setupUpdate closure_info (                  -- setupUpdate *encloses* the rest
584
585         -- Finally, do the business
586     thunk_code
587     ))
588
589 funWrapper :: ClosureInfo       -- Closure whose code body this is
590            -> [MagicId]         -- List of argument registers (if any)
591            -> [(VirtualSpOffset,Int)] -- tagged stack slots
592            -> CLabel            -- info table for heap check ret.
593            -> Code              -- Body of function being compiled
594            -> Code
595 funWrapper closure_info arg_regs stk_tags info_label fun_body
596   =     -- Stack overflow check
597     nodeMustPointToIt (closureLFInfo closure_info)      `thenFC` \ node_points ->
598     let
599        emit_gran_macros = opt_GranMacros
600     in
601     -- HWL   chu' ngoq:
602     (if emit_gran_macros
603       then yield  arg_regs node_points
604       else absC AbsCNop)                                 `thenC`
605
606         -- heap and/or stack checks
607     fastEntryChecks arg_regs stk_tags info_label node_points (
608
609         -- Finally, do the business
610     fun_body
611     )
612 \end{code}
613
614
615 %************************************************************************
616 %*                                                                      *
617 \subsubsubsection[update-and-BHs]{Update and black-hole wrappers}
618 %*                                                                      *
619 %************************************************************************
620
621
622 \begin{code}
623 blackHoleIt :: ClosureInfo -> Bool -> Code      -- Only called for closures with no args
624
625 blackHoleIt closure_info node_points
626   = if blackHoleOnEntry closure_info && node_points
627     then
628         let
629           info_label = infoTableLabelFromCI closure_info
630           args = [ CLbl info_label DataPtrRep ]
631         in
632         absC (if closureSingleEntry(closure_info) then
633                 CMacroStmt UPD_BH_SINGLE_ENTRY args
634               else
635                 CMacroStmt UPD_BH_UPDATABLE args)
636     else
637         nopC
638 \end{code}
639
640 \begin{code}
641 setupUpdate :: ClosureInfo -> Code -> Code      -- Only called for closures with no args
642         -- Nota Bene: this function does not change Node (even if it's a CAF),
643         -- so that the cost centre in the original closure can still be
644         -- extracted by a subsequent ENTER_CC_TCL
645
646 -- I've tidied up the code for this function, but it should still do the same as
647 -- it did before (modulo ticky stuff).  KSW 1999-04.
648 setupUpdate closure_info code
649  = if closureReEntrant closure_info
650    then
651      code
652    else
653      case (closureUpdReqd closure_info, isStaticClosure closure_info) of
654        (False,False) -> profCtrC SLIT("TICK_UPDF_OMITTED") [] `thenC`
655                         code
656        (False,True ) -> (if opt_DoTickyProfiling
657                          then
658                          -- blackhole the SE CAF
659                            link_caf seCafBlackHoleClosureInfo `thenFC` \ _ -> nopC
660                          else
661                            nopC)                                                       `thenC`
662                         profCtrC SLIT("TICK_UPD_CAF_BH_SINGLE_ENTRY") [mkCString cl_name] `thenC`
663                         profCtrC SLIT("TICK_UPDF_OMITTED") []                           `thenC`
664                         code
665        (True ,False) -> pushUpdateFrame (CReg node) code
666        (True ,True ) -> -- blackhole the (updatable) CAF:
667                         link_caf cafBlackHoleClosureInfo           `thenFC` \ update_closure ->
668                         profCtrC SLIT("TICK_UPD_CAF_BH_UPDATABLE") [mkCString cl_name]    `thenC`
669                         pushUpdateFrame update_closure code
670  where
671    cl_name :: FAST_STRING
672    cl_name  = (occNameFS . nameOccName . closureName) closure_info
673
674    link_caf :: (ClosureInfo -> ClosureInfo)  -- function yielding BH closure_info
675             -> FCode CAddrMode               -- Returns amode for closure to be updated
676    link_caf bhCI
677      = -- To update a CAF we must allocate a black hole, link the CAF onto the
678        -- CAF list, then update the CAF to point to the fresh black hole.
679        -- This function returns the address of the black hole, so it can be
680        -- updated with the new value when available.
681
682              -- Alloc black hole specifying CC_HDR(Node) as the cost centre
683              --   Hack Warning: Using a CLitLit to get CAddrMode !
684        let
685            use_cc   = CLitLit SLIT("CCS_HDR(R1.p)") PtrRep
686            blame_cc = use_cc
687        in
688        allocDynClosure (bhCI closure_info) use_cc blame_cc []  `thenFC` \ heap_offset ->
689        getHpRelOffset heap_offset                              `thenFC` \ hp_rel ->
690        let  amode = CAddr hp_rel
691        in
692        absC (CMacroStmt UPD_CAF [CReg node, amode])            `thenC`
693        returnFC amode
694 \end{code}
695
696 %************************************************************************
697 %*                                                                      *
698 \subsection[CgClosure-Description]{Profiling Closure Description.}
699 %*                                                                      *
700 %************************************************************************
701
702 For "global" data constructors the description is simply occurrence
703 name of the data constructor itself (see \ref{CgConTbls-info-tables}).
704
705 Otherwise it is determind by @closureDescription@ from the let
706 binding information.
707
708 \begin{code}
709 closureDescription :: Module            -- Module
710                    -> Name              -- Id of closure binding
711                    -> String
712
713         -- Not called for StgRhsCon which have global info tables built in
714         -- CgConTbls.lhs with a description generated from the data constructor
715
716 closureDescription mod_name name
717   = showSDoc (
718         hcat [char '<',
719                    pprModule mod_name,
720                    char '.',
721                    ppr name,
722                    char '>'])
723 \end{code}
724
725 \begin{code}
726 chooseDynCostCentres ccs args fvs body
727   = let
728         use_cc -- cost-centre we record in the object
729           = if currentOrSubsumedCCS ccs
730             then CReg CurCostCentre
731             else mkCCostCentreStack ccs
732
733         blame_cc -- cost-centre on whom we blame the allocation
734           = case (args, fvs, body) of
735               ([], _, StgApp fun [{-no args-}])
736                 -> mkCCostCentreStack overheadCCS
737               _ -> use_cc
738
739             -- if it's an utterly trivial RHS, then it must be
740             -- one introduced by boxHigherOrderArgs for profiling,
741             -- so we charge it to "OVERHEAD".
742
743             -- This looks like a HACK to me --SDM
744     in
745     (use_cc, blame_cc)
746 \end{code}
747
748
749
750 ========================================================================
751 OLD CODE THAT EMITTED INFORMATON FOR QUANTITATIVE ANALYSIS
752
753 It's pretty wierd, so I've nuked it for now.  SLPJ Nov 96
754
755 \begin{pseudocode}
756 getWrapperArgTypeCategories
757         :: Type                         -- wrapper's type
758         -> StrictnessInfo bdee          -- strictness info about its args
759         -> Maybe String
760
761 getWrapperArgTypeCategories _ NoStrictnessInfo      = Nothing
762 getWrapperArgTypeCategories _ BottomGuaranteed
763   = trace "getWrapperArgTypeCategories:BottomGuaranteed!" Nothing  -- wrong
764 getWrapperArgTypeCategories _ (StrictnessInfo [] _) = Nothing
765
766 getWrapperArgTypeCategories ty (StrictnessInfo arg_info _)
767   = Just (mkWrapperArgTypeCategories ty arg_info)
768
769 mkWrapperArgTypeCategories
770         :: Type         -- wrapper's type
771         -> [Demand]     -- info about its arguments
772         -> String       -- a string saying lots about the args
773
774 mkWrapperArgTypeCategories wrapper_ty wrap_info
775   = case (splitFunTy_maybe wrapper_ty) of { Just (arg_tys,_) ->
776     map do_one (wrap_info `zip` (map showTypeCategory arg_tys)) }
777   where
778     -- ToDo: this needs FIXING UP (it was a hack anyway...)
779     do_one (WwPrim, _) = 'P'
780     do_one (WwEnum, _) = 'E'
781     do_one (WwStrict, arg_ty_char) = arg_ty_char
782     do_one (WwUnpack _ _ _, arg_ty_char)
783       = if arg_ty_char `elem` "CIJFDTS"
784         then toLower arg_ty_char
785         else if arg_ty_char == '+' then 't'
786         else trace ("mkWrapp..:funny char:"++[arg_ty_char]) '-'
787     do_one (other_wrap_info, _) = '-'
788 \end{pseudocode}
789