Merging in the new codegen branch
[ghc-hetmet.git] / compiler / codeGen / StgCmmBind.hs
1 -----------------------------------------------------------------------------
2 --
3 -- Stg to C-- code generation: bindings
4 --
5 -- (c) The University of Glasgow 2004-2006
6 --
7 -----------------------------------------------------------------------------
8
9 module StgCmmBind ( 
10         cgTopRhsClosure, 
11         cgBind,
12         emitBlackHoleCode
13   ) where
14
15 #include "HsVersions.h"
16
17 import StgCmmMonad
18 import StgCmmExpr
19 import StgCmmEnv
20 import StgCmmCon
21 import StgCmmHeap
22 import StgCmmProf
23 import StgCmmTicky
24 import StgCmmGran
25 import StgCmmLayout
26 import StgCmmUtils
27 import StgCmmClosure
28
29 import MkZipCfgCmm
30 import CoreSyn          ( AltCon(..) )
31 import SMRep
32 import Cmm
33 import CmmUtils
34 import CLabel
35 import StgSyn
36 import CostCentre       
37 import Id
38 import Name
39 import Module
40 import ListSetOps
41 import Util
42 import BasicTypes
43 import Constants
44 import Outputable
45 import FastString
46 import Maybes
47
48 import Data.List
49
50 ------------------------------------------------------------------------
51 --              Top-level bindings
52 ------------------------------------------------------------------------
53
54 -- For closures bound at top level, allocate in static space.
55 -- They should have no free variables.
56
57 cgTopRhsClosure :: Id
58                 -> CostCentreStack      -- Optional cost centre annotation
59                 -> StgBinderInfo
60                 -> UpdateFlag
61                 -> SRT
62                 -> [Id]         -- Args
63                 -> StgExpr
64                 -> FCode (Id, CgIdInfo)
65
66 cgTopRhsClosure id ccs binder_info upd_flag srt args body = do
67   {     -- LAY OUT THE OBJECT
68     let name = idName id
69   ; lf_info  <- mkClosureLFInfo id TopLevel [] upd_flag args
70   ; srt_info <- getSRTInfo srt
71   ; mod_name <- getModuleName
72   ; let descr         = closureDescription mod_name name
73         closure_info  = mkClosureInfo True id lf_info 0 0 srt_info descr
74         closure_label = mkLocalClosureLabel name (idCafInfo id)
75         cg_id_info    = litIdInfo id lf_info (CmmLabel closure_label)
76         closure_rep   = mkStaticClosureFields closure_info ccs True []
77
78          -- BUILD THE OBJECT, AND GENERATE INFO TABLE (IF NECESSARY)
79   ; emitDataLits closure_label closure_rep
80   ; forkClosureBody $ do
81         { node <- bindToReg id lf_info
82         ; closureCodeBody binder_info closure_info
83                           ccs srt_info node args body }
84
85   ; returnFC (id, cg_id_info) }
86
87 ------------------------------------------------------------------------
88 --              Non-top-level bindings
89 ------------------------------------------------------------------------
90
91 cgBind :: StgBinding -> FCode ()
92 cgBind (StgNonRec name rhs)
93   = do  { (name, info) <- cgRhs name rhs
94         ; addBindC name info }
95
96 cgBind (StgRec pairs)
97   = do  { new_binds <- fixC (\ new_binds -> 
98                 do { addBindsC new_binds
99                    ; listFCs [ cgRhs b e | (b,e) <- pairs ] })
100         ; addBindsC new_binds }
101
102 --------------------
103 cgRhs :: Id -> StgRhs -> FCode (Id, CgIdInfo)
104    -- The Id is passed along so a binding can be set up
105
106 cgRhs name (StgRhsCon maybe_cc con args)
107   = do  { idinfo <- buildDynCon name maybe_cc con args
108         ; return (name, idinfo) }
109
110 cgRhs name (StgRhsClosure cc bi fvs upd_flag srt args body)
111   = mkRhsClosure name cc bi fvs upd_flag srt args body
112
113 ------------------------------------------------------------------------
114 --              Non-constructor right hand sides
115 ------------------------------------------------------------------------
116
117 mkRhsClosure :: Id -> CostCentreStack -> StgBinderInfo
118              -> [Id]                    -- Free vars
119              -> UpdateFlag -> SRT
120              -> [Id]                    -- Args
121              -> StgExpr
122              -> FCode (Id, CgIdInfo) 
123
124 {- mkRhsClosure looks for two special forms of the right-hand side:
125         a) selector thunks
126         b) AP thunks
127
128 If neither happens, it just calls mkClosureLFInfo.  You might think
129 that mkClosureLFInfo should do all this, but it seems wrong for the
130 latter to look at the structure of an expression
131
132 Note [Selectors]
133 ~~~~~~~~~~~~~~~~
134 We look at the body of the closure to see if it's a selector---turgid,
135 but nothing deep.  We are looking for a closure of {\em exactly} the
136 form:
137
138 ...  = [the_fv] \ u [] ->
139          case the_fv of
140            con a_1 ... a_n -> a_i
141
142 Note [Ap thunks]
143 ~~~~~~~~~~~~~~~~
144 A more generic AP thunk of the form
145
146         x = [ x_1...x_n ] \.. [] -> x_1 ... x_n
147
148 A set of these is compiled statically into the RTS, so we just use
149 those.  We could extend the idea to thunks where some of the x_i are
150 global ids (and hence not free variables), but this would entail
151 generating a larger thunk.  It might be an option for non-optimising
152 compilation, though.
153
154 We only generate an Ap thunk if all the free variables are pointers,
155 for semi-obvious reasons.
156
157 -}
158
159 ---------- Note [Selectors] ------------------
160 mkRhsClosure    bndr cc bi
161                 [the_fv]                -- Just one free var
162                 upd_flag                -- Updatable thunk
163                 _srt
164                 []                      -- A thunk
165                 body@(StgCase (StgApp scrutinee [{-no args-}])
166                       _ _ _ _   -- ignore uniq, etc.
167                       (AlgAlt _)
168                       [(DataAlt con, params, _use_mask,
169                             (StgApp selectee [{-no args-}]))])
170   |  the_fv == scrutinee                -- Scrutinee is the only free variable
171   && maybeToBool maybe_offset           -- Selectee is a component of the tuple
172   && offset_into_int <= mAX_SPEC_SELECTEE_SIZE  -- Offset is small enough
173   = -- NOT TRUE: ASSERT(is_single_constructor)
174     -- The simplifier may have statically determined that the single alternative
175     -- is the only possible case and eliminated the others, even if there are
176     -- other constructors in the datatype.  It's still ok to make a selector
177     -- thunk in this case, because we *know* which constructor the scrutinee
178     -- will evaluate to.
179     --
180     -- srt is discarded; it must be empty
181     cgStdThunk bndr cc bi body lf_info [StgVarArg the_fv]
182   where
183     lf_info               = mkSelectorLFInfo bndr offset_into_int
184                                  (isUpdatable upd_flag)
185     (_, params_w_offsets) = layOutDynConstr con (addIdReps params)
186                         -- Just want the layout
187     maybe_offset          = assocMaybe params_w_offsets selectee
188     Just the_offset       = maybe_offset
189     offset_into_int       = the_offset - fixedHdrSize
190
191 ---------- Note [Ap thunks] ------------------
192 mkRhsClosure    bndr cc bi
193                 fvs
194                 upd_flag
195                 _srt
196                 []                      -- No args; a thunk
197                 body@(StgApp fun_id args)
198
199   | args `lengthIs` (arity-1)
200         && all isFollowableArg (map idCgRep fvs) 
201         && isUpdatable upd_flag
202         && arity <= mAX_SPEC_AP_SIZE 
203
204                    -- Ha! an Ap thunk
205   = cgStdThunk bndr cc bi body lf_info payload
206   where
207         lf_info = mkApLFInfo bndr upd_flag arity
208         -- the payload has to be in the correct order, hence we can't
209         -- just use the fvs.
210         payload = StgVarArg fun_id : args
211         arity   = length fvs
212
213 ---------- Default case ------------------
214 mkRhsClosure bndr cc bi fvs upd_flag srt args body
215   = do  {       -- LAY OUT THE OBJECT
216         -- If the binder is itself a free variable, then don't store
217         -- it in the closure.  Instead, just bind it to Node on entry.
218         -- NB we can be sure that Node will point to it, because we
219         -- havn't told mkClosureLFInfo about this; so if the binder
220         -- _was_ a free var of its RHS, mkClosureLFInfo thinks it *is*
221         -- stored in the closure itself, so it will make sure that
222         -- Node points to it...
223         ; let
224                 is_elem      = isIn "cgRhsClosure"
225                 bndr_is_a_fv = bndr `is_elem` fvs
226                 reduced_fvs | bndr_is_a_fv = fvs `minusList` [bndr]
227                             | otherwise    = fvs
228
229                 
230         -- MAKE CLOSURE INFO FOR THIS CLOSURE
231         ; lf_info <- mkClosureLFInfo bndr NotTopLevel fvs upd_flag args
232         ; mod_name <- getModuleName
233         ; c_srt <- getSRTInfo srt
234         ; let   name  = idName bndr
235                 descr = closureDescription mod_name name
236                 fv_details :: [(Id, VirtualHpOffset)]
237                 (tot_wds, ptr_wds, fv_details) 
238                    = mkVirtHeapOffsets (isLFThunk lf_info) 
239                                        (addIdReps reduced_fvs)
240                 closure_info = mkClosureInfo False      -- Not static
241                                              bndr lf_info tot_wds ptr_wds
242                                              c_srt descr
243
244         -- BUILD ITS INFO TABLE AND CODE
245         ; forkClosureBody $ do
246                 {   -- Bind the binder itself
247                     -- It does no harm to have it in the envt even if
248                     -- it's not a free variable; and we need a reg for it
249                   node <- bindToReg bndr lf_info
250
251                     -- Bind the free variables
252                 ; mapCs (bind_fv node) fv_details
253         
254                     -- And compile the body
255                 ; closureCodeBody bi closure_info cc c_srt node args body }
256
257         -- BUILD THE OBJECT
258         ; (use_cc, blame_cc) <- chooseDynCostCentres cc args body
259         ; emit (mkComment $ mkFastString "calling allocDynClosure")
260         ; tmp <- allocDynClosure closure_info use_cc blame_cc 
261                                  (mapFst StgVarArg fv_details)
262         
263         -- RETURN
264         ; return (bndr, regIdInfo bndr lf_info tmp) }
265   where
266       -- A function closure pointer may be tagged, so we
267       -- must take it into account when accessing the free variables.
268      tag = tagForArity (length args)
269
270      bind_fv node (id, off) 
271         = do { reg <- rebindToReg id
272              ; emit $ mkTaggedObjectLoad reg node off tag }
273
274 -------------------------
275 cgStdThunk
276         :: Id
277         -> CostCentreStack      -- Optional cost centre annotation
278         -> StgBinderInfo        -- XXX: not used??
279         -> StgExpr
280         -> LambdaFormInfo
281         -> [StgArg]                     -- payload
282         -> FCode (Id, CgIdInfo)
283
284 cgStdThunk bndr cc _bndr_info body lf_info payload
285   = do  -- AHA!  A STANDARD-FORM THUNK
286   {     -- LAY OUT THE OBJECT
287     mod_name <- getModuleName
288   ; let (tot_wds, ptr_wds, payload_w_offsets) 
289             = mkVirtHeapOffsets (isLFThunk lf_info) (addArgReps payload)
290
291         descr = closureDescription mod_name (idName bndr)
292         closure_info = mkClosureInfo False      -- Not static
293                                      bndr lf_info tot_wds ptr_wds 
294                                      NoC_SRT    -- No SRT for a std-form closure
295                                      descr
296
297   ; (use_cc, blame_cc) <- chooseDynCostCentres cc [{- no args-}] body
298
299         -- BUILD THE OBJECT
300   ; tmp <- allocDynClosure closure_info use_cc blame_cc payload_w_offsets
301
302         -- RETURN
303   ; returnFC (bndr, regIdInfo bndr lf_info tmp) }
304
305 mkClosureLFInfo :: Id           -- The binder
306                 -> TopLevelFlag -- True of top level
307                 -> [Id]         -- Free vars
308                 -> UpdateFlag   -- Update flag
309                 -> [Id]         -- Args
310                 -> FCode LambdaFormInfo
311 mkClosureLFInfo bndr top fvs upd_flag args
312   | null args = return (mkLFThunk (idType bndr) top fvs upd_flag)
313   | otherwise = do { arg_descr <- mkArgDescr (idName bndr) args
314                    ; return (mkLFReEntrant top fvs args arg_descr) }
315
316
317 ------------------------------------------------------------------------
318 --              The code for closures}
319 ------------------------------------------------------------------------
320
321 closureCodeBody :: StgBinderInfo   -- XXX: unused?
322                 -> ClosureInfo     -- Lots of information about this closure
323                 -> CostCentreStack -- Optional cost centre attached to closure
324                 -> C_SRT
325                 -> LocalReg        -- The closure itself; first argument
326                                    -- The Id is in scope already, bound to this reg
327                 -> [Id]
328                 -> StgExpr
329                 -> FCode ()
330
331 {- There are two main cases for the code for closures.  
332
333 * If there are *no arguments*, then the closure is a thunk, and not in
334   normal form. So it should set up an update frame (if it is
335   shared). NB: Thunks cannot have a primitive type!
336
337 * If there is *at least one* argument, then this closure is in
338   normal form, so there is no need to set up an update frame.
339
340   The Macros for GrAnSim are produced at the beginning of the
341   argSatisfactionCheck (by calling fetchAndReschedule).  
342   There info if Node points to closure is available. -- HWL -}
343
344 closureCodeBody _binder_info cl_info cc srt node args body 
345   | null args   -- No args i.e. thunk
346   = do  { code <- getCode $ thunkCode cl_info cc srt node body
347         ; emitClosureCodeAndInfoTable cl_info [node] code }
348
349 closureCodeBody _binder_info cl_info cc srt node args body 
350   = ASSERT( length args > 0 )
351     do  {       -- Allocate the global ticky counter,
352                 -- and establish the ticky-counter 
353                 -- label for this block
354           let ticky_ctr_lbl = mkRednCountsLabel (closureName cl_info) $ clHasCafRefs cl_info
355         ; emitTickyCounter cl_info args
356         ; setTickyCtrLabel ticky_ctr_lbl $ do
357
358 --      -- XXX: no slow-entry code for now
359 --      -- Emit the slow-entry code
360 --      { reg_save_code <- mkSlowEntryCode cl_info reg_args
361
362         -- Emit the main entry code
363         ; let node_points = nodeMustPointToIt (closureLFInfo cl_info)
364         ; arg_regs <- bindArgsToRegs args
365         ; blks <- forkProc $ getCode $ do
366                 { enterCostCentre cl_info cc body
367                 ; tickyEnterFun cl_info
368                 ; whenC node_points (ldvEnterClosure cl_info)
369                 ; granYield arg_regs node_points
370
371                         -- Main payload
372                 ; entryHeapCheck node arg_regs srt $
373                   cgExpr body }
374
375         ; emitClosureCodeAndInfoTable cl_info (node:arg_regs) blks
376   }
377
378 {-
379 -----------------------------------------
380 -- The "slow entry" code for a function.  This entry point takes its
381 -- arguments on the stack.  It loads the arguments into registers
382 -- according to the calling convention, and jumps to the function's
383 -- normal entry point.  The function's closure is assumed to be in
384 -- R1/node.
385 -- 
386 -- The slow entry point is used in two places:
387 -- 
388 -- (a) unknown calls: eg. stg_PAP_entry 
389 --  (b) returning from a heap-check failure
390
391 mkSlowEntryCode :: ClosureInfo -> [(Id,GlobalReg)] -> FCode CmmStmts
392 -- If this function doesn't have a specialised ArgDescr, we need
393 -- to generate the function's arg bitmap, slow-entry code, and
394 -- register-save code for the heap-check failure
395 -- Here, we emit the slow-entry code, and 
396 -- return the register-save assignments
397 mkSlowEntryCode cl_info reg_args
398   | Just (_, ArgGen _) <- closureFunInfo cl_info
399   = do  { emitSimpleProc slow_lbl (emitStmts load_stmts)
400         ; return save_stmts }
401   | otherwise = return noStmts
402   where
403      name = closureName cl_info
404      slow_lbl = mkSlowEntryLabel name
405
406      load_stmts = mkStmts load_assts `plusStmts` mkStmts [stk_adj_pop, jump_to_entry]
407      save_stmts = oneStmt stk_adj_push `plusStmts`  mkStmts save_assts
408
409      reps_w_regs :: [(CgRep,GlobalReg)]
410      reps_w_regs = [(idCgRep id, reg) | (id,reg) <- reverse reg_args]
411      (final_stk_offset, stk_offsets)
412         = mapAccumL (\off (rep,_) -> (off + cgRepSizeW rep, off))
413                     0 reps_w_regs
414
415      load_assts = zipWithEqual "mk_load" mk_load reps_w_regs stk_offsets
416      mk_load (rep,reg) offset = CmmAssign (CmmGlobal reg) 
417                                           (CmmLoad (cmmRegOffW spReg offset)
418                                                    (argMachRep rep))
419
420      save_assts = zipWithEqual "mk_save" mk_save reps_w_regs stk_offsets
421      mk_save (rep,reg) offset = ASSERT( argMachRep rep == globalRegType reg )
422                                 CmmStore (cmmRegOffW spReg offset) 
423                                          (CmmReg (CmmGlobal reg))
424
425      stk_adj_pop   = CmmAssign spReg (cmmRegOffW spReg final_stk_offset)
426      stk_adj_push  = CmmAssign spReg (cmmRegOffW spReg (- final_stk_offset))
427      jump_to_entry = CmmJump (mkLblExpr (enterLocalIdLabel name)) []
428 -}
429
430 -----------------------------------------
431 thunkCode :: ClosureInfo -> CostCentreStack -> C_SRT -> LocalReg -> StgExpr -> FCode ()
432 thunkCode cl_info cc srt node body 
433   = do  { let node_points = nodeMustPointToIt (closureLFInfo cl_info)
434
435         ; tickyEnterThunk cl_info
436         ; ldvEnterClosure cl_info  -- NB: Node always points when profiling
437         ; granThunk node_points
438
439         -- Heap overflow check
440         ; entryHeapCheck node [] srt $ do
441         {       -- Overwrite with black hole if necessary
442                 -- but *after* the heap-overflow check
443           whenC (blackHoleOnEntry cl_info && node_points)
444                 (blackHoleIt cl_info)
445
446                 -- Push update frame
447         ; setupUpdate cl_info node
448
449                 -- We only enter cc after setting up update so
450                 -- that cc of enclosing scope will be recorded
451                 -- in update frame CAF/DICT functions will be
452                 -- subsumed by this enclosing cc
453         ; enterCostCentre cl_info cc body
454
455         ; cgExpr body } }
456
457
458 ------------------------------------------------------------------------
459 --              Update and black-hole wrappers
460 ------------------------------------------------------------------------
461
462 blackHoleIt :: ClosureInfo -> FCode ()
463 -- Only called for closures with no args
464 -- Node points to the closure
465 blackHoleIt closure_info = emitBlackHoleCode (closureSingleEntry closure_info)
466
467 emitBlackHoleCode :: Bool -> FCode ()
468 emitBlackHoleCode is_single_entry 
469   | eager_blackholing = do 
470         tickyBlackHole (not is_single_entry)
471         emit (mkStore (CmmReg nodeReg) (CmmLit (CmmLabel bh_lbl)))
472   | otherwise = 
473         nopC
474   where
475     bh_lbl | is_single_entry = mkRtsDataLabel (sLit "stg_SE_BLACKHOLE_info")
476            | otherwise       = mkRtsDataLabel (sLit "stg_BLACKHOLE_info")
477
478         -- If we wanted to do eager blackholing with slop filling,
479         -- we'd need to do it at the *end* of a basic block, otherwise
480         -- we overwrite the free variables in the thunk that we still
481         -- need.  We have a patch for this from Andy Cheadle, but not
482         -- incorporated yet. --SDM [6/2004]
483         --
484         -- Profiling needs slop filling (to support LDV profiling), so
485         -- currently eager blackholing doesn't work with profiling.
486         --
487         -- Previously, eager blackholing was enabled when ticky-ticky
488         -- was on. But it didn't work, and it wasn't strictly necessary 
489         -- to bring back minimal ticky-ticky, so now EAGER_BLACKHOLING 
490         -- is unconditionally disabled. -- krc 1/2007
491
492     eager_blackholing = False 
493
494 setupUpdate :: ClosureInfo -> LocalReg -> FCode ()
495         -- Nota Bene: this function does not change Node (even if it's a CAF),
496         -- so that the cost centre in the original closure can still be
497         -- extracted by a subsequent enterCostCentre
498 setupUpdate closure_info node
499   | closureReEntrant closure_info
500   = return ()
501
502   | not (isStaticClosure closure_info)
503   = if closureUpdReqd closure_info
504     then do { tickyPushUpdateFrame; pushUpdateFrame node }
505     else tickyUpdateFrameOmitted
506  
507   | otherwise   -- A static closure
508   = do  { tickyUpdateBhCaf closure_info
509
510         ; if closureUpdReqd closure_info
511           then do       -- Blackhole the (updatable) CAF:
512                 { upd_closure <- link_caf closure_info True
513                 ; pushUpdateFrame upd_closure }
514           else tickyUpdateFrameOmitted
515     }
516
517 pushUpdateFrame :: LocalReg -> FCode ()
518 pushUpdateFrame cl_reg
519   = emit (mkAddToContext (mkLblExpr mkUpdInfoLabel) 
520                          [CmmReg (CmmLocal cl_reg)])
521
522 -----------------------------------------------------------------------------
523 -- Entering a CAF
524 --
525 -- When a CAF is first entered, it creates a black hole in the heap,
526 -- and updates itself with an indirection to this new black hole.
527 --
528 -- We update the CAF with an indirection to a newly-allocated black
529 -- hole in the heap.  We also set the blocking queue on the newly
530 -- allocated black hole to be empty.
531 --
532 -- Why do we make a black hole in the heap when we enter a CAF?
533 --    
534 --     - for a  generational garbage collector, which needs a fast
535 --       test for whether an updatee is in an old generation or not
536 --
537 --     - for the parallel system, which can implement updates more
538 --       easily if the updatee is always in the heap. (allegedly).
539 --
540 -- When debugging, we maintain a separate CAF list so we can tell when
541 -- a CAF has been garbage collected.
542
543 -- newCAF must be called before the itbl ptr is overwritten, since
544 -- newCAF records the old itbl ptr in order to do CAF reverting
545 -- (which Hugs needs to do in order that combined mode works right.)
546 --
547
548 -- ToDo [Feb 04]  This entire link_caf nonsense could all be moved
549 -- into the "newCAF" RTS procedure, which we call anyway, including
550 -- the allocation of the black-hole indirection closure.
551 -- That way, code size would fall, the CAF-handling code would 
552 -- be closer together, and the compiler wouldn't need to know
553 -- about off_indirectee etc.
554
555 link_caf :: ClosureInfo
556          -> Bool                -- True <=> updatable, False <=> single-entry
557          -> FCode LocalReg      -- Returns amode for closure to be updated
558 -- To update a CAF we must allocate a black hole, link the CAF onto the
559 -- CAF list, then update the CAF to point to the fresh black hole.
560 -- This function returns the address of the black hole, so it can be
561 -- updated with the new value when available.  The reason for all of this
562 -- is that we only want to update dynamic heap objects, not static ones,
563 -- so that generational GC is easier.
564 link_caf cl_info is_upd = do
565   {     -- Alloc black hole specifying CC_HDR(Node) as the cost centre
566   ; let use_cc   = costCentreFrom (CmmReg nodeReg)
567         blame_cc = use_cc
568   ; hp_rel <- allocDynClosure bh_cl_info use_cc blame_cc []
569
570         -- Call the RTS function newCAF to add the CAF to the CafList
571         -- so that the garbage collector can find them
572         -- This must be done *before* the info table pointer is overwritten, 
573         -- because the old info table ptr is needed for reversion
574   ; emitRtsCallWithVols (sLit "newCAF") [(CmmReg nodeReg,AddrHint)] [node] False
575         -- node is live, so save it.
576
577         -- Overwrite the closure with a (static) indirection 
578         -- to the newly-allocated black hole
579   ; emit (mkStore (cmmRegOffW nodeReg off_indirectee) (CmmReg (CmmLocal hp_rel)) <*>
580           mkStore (CmmReg nodeReg) ind_static_info)
581
582   ; return hp_rel }
583   where
584     bh_cl_info :: ClosureInfo
585     bh_cl_info | is_upd    = cafBlackHoleClosureInfo   cl_info
586                | otherwise = seCafBlackHoleClosureInfo cl_info
587
588     ind_static_info :: CmmExpr
589     ind_static_info = mkLblExpr mkIndStaticInfoLabel
590
591     off_indirectee :: WordOff
592     off_indirectee = fixedHdrSize + oFFSET_StgInd_indirectee*wORD_SIZE
593
594
595 ------------------------------------------------------------------------
596 --              Profiling 
597 ------------------------------------------------------------------------
598
599 -- For "global" data constructors the description is simply occurrence
600 -- name of the data constructor itself.  Otherwise it is determined by
601 -- @closureDescription@ from the let binding information.
602
603 closureDescription :: Module            -- Module
604                    -> Name              -- Id of closure binding
605                    -> String
606         -- Not called for StgRhsCon which have global info tables built in
607         -- CgConTbls.lhs with a description generated from the data constructor
608 closureDescription mod_name name
609   = showSDocDump (char '<' <>
610                     (if isExternalName name
611                       then ppr name -- ppr will include the module name prefix
612                       else pprModule mod_name <> char '.' <> ppr name) <>
613                     char '>')
614    -- showSDocDump, because we want to see the unique on the Name.
615