2 % (c) The University of Glasgow 2006
3 % (c) The Univserity of Glasgow 1992-2004
6 Data structures which describe closures, and
7 operations over those data structures
9 Nothing monadic in here
11 Much of the rationale for these things is in the ``details'' part of
16 -- The above warning supression flag is a temporary kludge.
17 -- While working on this module you are encouraged to remove it and fix
18 -- any warnings in the module. See
19 -- http://hackage.haskell.org/trac/ghc/wiki/Commentary/CodingStyle#Warnings
23 ClosureInfo(..), LambdaFormInfo(..), -- would be abstract but
24 StandardFormInfo(..), -- mkCmmInfo looks inside
27 ArgDescr(..), Liveness(..),
30 mkLFThunk, mkLFReEntrant, mkConLFInfo, mkSelectorLFInfo,
31 mkApLFInfo, mkLFImported, mkLFArgument, mkLFLetNoEscape,
33 mkClosureInfo, mkConInfo, maybeIsLFCon,
35 closureSize, closureNonHdrSize,
36 closureGoodStuffSize, closurePtrsSize,
39 closureName, infoTableLabelFromCI,
40 closureLabelFromCI, closureSRT,
41 closureLFInfo, isLFThunk,closureSMRep, closureUpdReqd,
42 closureNeedsUpdSpace, closureIsThunk,
43 closureSingleEntry, closureReEntrant, isConstrClosure_maybe,
44 closureFunInfo, isStandardFormThunk, isKnownFun,
45 funTag, funTagLFInfo, tagForArity,
47 enterIdLabel, enterLocalIdLabel, enterReturnPtLabel,
50 CallMethod(..), getCallMethod,
54 staticClosureRequired,
58 closureValDescr, closureTypeDescr, -- profiling
61 cafBlackHoleClosureInfo, seCafBlackHoleClosureInfo,
63 staticClosureNeedsLink,
66 #include "../includes/MachDeps.h"
67 #include "HsVersions.h"
93 %************************************************************************
95 \subsection[ClosureInfo-datatypes]{Data types for closure information}
97 %************************************************************************
99 Information about a closure, from the code generator's point of view.
101 A ClosureInfo decribes the info pointer of a closure. It has
103 a) to construct the info table itself
104 b) to allocate a closure containing that info pointer (i.e.
105 it knows the info table label)
107 We make a ClosureInfo for
108 - each let binding (both top level and not)
109 - each data constructor (for its shared static and
115 closureName :: !Name, -- The thing bound to this closure
116 closureLFInfo :: !LambdaFormInfo, -- NOTE: not an LFCon (see below)
117 closureSMRep :: !SMRep, -- representation used by storage mgr
118 closureSRT :: !C_SRT, -- What SRT applies to this closure
119 closureType :: !Type, -- Type of closure (ToDo: remove)
120 closureDescr :: !String -- closure description (for profiling)
123 -- Constructor closures don't have a unique info table label (they use
124 -- the constructor's info table), and they don't have an SRT.
126 closureCon :: !DataCon,
127 closureSMRep :: !SMRep
130 -- C_SRT is what StgSyn.SRT gets translated to...
131 -- we add a label for the table, and expect only the 'offset/length' form
134 | C_SRT !CLabel !WordOff !StgHalfWord {-bitmap or escape-}
137 needsSRT :: C_SRT -> Bool
138 needsSRT NoC_SRT = False
139 needsSRT (C_SRT _ _ _) = True
141 instance Outputable C_SRT where
142 ppr (NoC_SRT) = ptext (sLit "_no_srt_")
143 ppr (C_SRT label off bitmap) = parens (ppr label <> comma <> ppr off <> comma <> text (show bitmap))
146 %************************************************************************
148 \subsubsection[LambdaFormInfo-datatype]{@LambdaFormInfo@: source-derivable info}
150 %************************************************************************
152 Information about an identifier, from the code generator's point of
153 view. Every identifier is bound to a LambdaFormInfo in the
154 environment, which gives the code generator enough info to be able to
155 tail call or return that identifier.
157 Note that a closure is usually bound to an identifier, so a
158 ClosureInfo contains a LambdaFormInfo.
162 = LFReEntrant -- Reentrant closure (a function)
163 TopLevelFlag -- True if top level
164 !Int -- Arity. Invariant: always > 0
165 !Bool -- True <=> no fvs
166 ArgDescr -- Argument descriptor (should reall be in ClosureInfo)
168 | LFCon -- A saturated constructor application
169 DataCon -- The constructor
171 | LFThunk -- Thunk (zero arity)
173 !Bool -- True <=> no free vars
174 !Bool -- True <=> updatable (i.e., *not* single-entry)
176 !Bool -- True <=> *might* be a function type
178 | LFUnknown -- Used for function arguments and imported things.
179 -- We know nothing about this closure. Treat like
180 -- updatable "LFThunk"...
181 -- Imported things which we do know something about use
182 -- one of the other LF constructors (eg LFReEntrant for
184 !Bool -- True <=> *might* be a function type
186 | LFLetNoEscape -- See LetNoEscape module for precise description of
190 | LFBlackHole -- Used for the closures allocated to hold the result
191 -- of a CAF. We want the target of the update frame to
192 -- be in the heap, so we make a black hole to hold it.
193 CLabel -- Flavour (info label, eg CAF_BLACKHOLE_info).
196 -------------------------
197 -- An ArgDsecr describes the argument pattern of a function
200 = ArgSpec -- Fits one of the standard patterns
201 !StgHalfWord -- RTS type identifier ARG_P, ARG_N, ...
203 | ArgGen -- General case
204 Liveness -- Details about the arguments
207 -------------------------
208 -- We represent liveness bitmaps as a Bitmap (whose internal
209 -- representation really is a bitmap). These are pinned onto case return
210 -- vectors to indicate the state of the stack for the garbage collector.
212 -- In the compiled program, liveness bitmaps that fit inside a single
213 -- word (StgWord) are stored as a single word, while larger bitmaps are
214 -- stored as a pointer to an array of words.
217 = SmallLiveness -- Liveness info that fits in one word
218 StgWord -- Here's the bitmap
220 | BigLiveness -- Liveness info witha a multi-word bitmap
221 CLabel -- Label for the bitmap
224 -------------------------
225 -- StandardFormInfo tells whether this thunk has one of
226 -- a small number of standard forms
228 data StandardFormInfo
230 -- Not of of the standard forms
233 -- A SelectorThunk is of form
235 -- con a1,..,an -> ak
236 -- and the constructor is from a single-constr type.
237 WordOff -- 0-origin offset of ak within the "goods" of
238 -- constructor (Recall that the a1,...,an may be laid
239 -- out in the heap in a non-obvious order.)
242 -- An ApThunk is of form
244 -- The code for the thunk just pushes x2..xn on the stack and enters x1.
245 -- There are a few of these (for 1 <= n <= MAX_SPEC_AP_SIZE) pre-compiled
246 -- in the RTS to save space.
250 %************************************************************************
252 \subsection[ClosureInfo-construction]{Functions which build LFInfos}
254 %************************************************************************
257 mkLFReEntrant :: TopLevelFlag -- True of top level
260 -> ArgDescr -- Argument descriptor
263 mkLFReEntrant top fvs args arg_descr
264 = LFReEntrant top (length args) (null fvs) arg_descr
266 mkLFThunk thunk_ty top fvs upd_flag
267 = ASSERT( not (isUpdatable upd_flag) || not (isUnLiftedType thunk_ty) )
268 LFThunk top (null fvs)
269 (isUpdatable upd_flag)
271 (might_be_a_function thunk_ty)
273 might_be_a_function :: Type -> Bool
274 -- Return False only if we are *sure* it's a data type
275 -- Look through newtypes etc as much as poss
276 might_be_a_function ty
277 = case splitTyConApp_maybe (repType ty) of
278 Just (tc, _) -> not (isDataTyCon tc)
282 @mkConLFInfo@ is similar, for constructors.
285 mkConLFInfo :: DataCon -> LambdaFormInfo
286 mkConLFInfo con = LFCon con
288 maybeIsLFCon :: LambdaFormInfo -> Maybe DataCon
289 maybeIsLFCon (LFCon con) = Just con
290 maybeIsLFCon _ = Nothing
292 mkSelectorLFInfo id offset updatable
293 = LFThunk NotTopLevel False updatable (SelectorThunk offset)
294 (might_be_a_function (idType id))
296 mkApLFInfo id upd_flag arity
297 = LFThunk NotTopLevel (arity == 0) (isUpdatable upd_flag) (ApThunk arity)
298 (might_be_a_function (idType id))
301 Miscellaneous LF-infos.
304 mkLFArgument id = LFUnknown (might_be_a_function (idType id))
306 mkLFLetNoEscape = LFLetNoEscape
308 mkLFImported :: Id -> LambdaFormInfo
311 n | n > 0 -> LFReEntrant TopLevel n True (panic "arg_descr") -- n > 0
312 other -> mkLFArgument id -- Not sure of exact arity
316 isLFThunk :: LambdaFormInfo -> Bool
317 isLFThunk (LFThunk _ _ _ _ _) = True
318 isLFThunk (LFBlackHole _) = True
319 -- return True for a blackhole: this function is used to determine
320 -- whether to use the thunk header in SMP mode, and a blackhole
325 %************************************************************************
327 Building ClosureInfos
329 %************************************************************************
332 mkClosureInfo :: Bool -- Is static
335 -> Int -> Int -- Total and pointer words
337 -> String -- String descriptor
339 mkClosureInfo is_static id lf_info tot_wds ptr_wds srt_info descr
340 = ClosureInfo { closureName = name,
341 closureLFInfo = lf_info,
342 closureSMRep = sm_rep,
343 closureSRT = srt_info,
344 closureType = idType id,
345 closureDescr = descr }
348 sm_rep = chooseSMRep is_static lf_info tot_wds ptr_wds
350 mkConInfo :: Bool -- Is static
352 -> Int -> Int -- Total and pointer words
354 mkConInfo is_static data_con tot_wds ptr_wds
355 = ConInfo { closureSMRep = sm_rep,
356 closureCon = data_con }
358 sm_rep = chooseSMRep is_static (mkConLFInfo data_con) tot_wds ptr_wds
361 %************************************************************************
363 \subsection[ClosureInfo-sizes]{Functions about closure {\em sizes}}
365 %************************************************************************
368 closureSize :: ClosureInfo -> WordOff
369 closureSize cl_info = hdr_size + closureNonHdrSize cl_info
370 where hdr_size | closureIsThunk cl_info = thunkHdrSize
371 | otherwise = fixedHdrSize
372 -- All thunks use thunkHdrSize, even if they are non-updatable.
373 -- this is because we don't have separate closure types for
374 -- updatable vs. non-updatable thunks, so the GC can't tell the
375 -- difference. If we ever have significant numbers of non-
376 -- updatable thunks, it might be worth fixing this.
378 closureNonHdrSize :: ClosureInfo -> WordOff
379 closureNonHdrSize cl_info
380 = tot_wds + computeSlopSize tot_wds cl_info
382 tot_wds = closureGoodStuffSize cl_info
384 closureGoodStuffSize :: ClosureInfo -> WordOff
385 closureGoodStuffSize cl_info
386 = let (ptrs, nonptrs) = sizes_from_SMRep (closureSMRep cl_info)
389 closurePtrsSize :: ClosureInfo -> WordOff
390 closurePtrsSize cl_info
391 = let (ptrs, _) = sizes_from_SMRep (closureSMRep cl_info)
395 sizes_from_SMRep :: SMRep -> (WordOff,WordOff)
396 sizes_from_SMRep (GenericRep _ ptrs nonptrs _) = (ptrs, nonptrs)
397 sizes_from_SMRep BlackHoleRep = (0, 0)
400 Computing slop size. WARNING: this looks dodgy --- it has deep
401 knowledge of what the storage manager does with the various
404 Slop Requirements: every thunk gets an extra padding word in the
405 header, which takes the the updated value.
408 slopSize cl_info = computeSlopSize payload_size cl_info
409 where payload_size = closureGoodStuffSize cl_info
411 computeSlopSize :: WordOff -> ClosureInfo -> WordOff
412 computeSlopSize payload_size cl_info
413 = max 0 (minPayloadSize smrep updatable - payload_size)
415 smrep = closureSMRep cl_info
416 updatable = closureNeedsUpdSpace cl_info
418 -- we leave space for an update if either (a) the closure is updatable
419 -- or (b) it is a static thunk. This is because a static thunk needs
420 -- a static link field in a predictable place (after the slop), regardless
421 -- of whether it is updatable or not.
422 closureNeedsUpdSpace (ClosureInfo { closureLFInfo =
423 LFThunk TopLevel _ _ _ _ }) = True
424 closureNeedsUpdSpace cl_info = closureUpdReqd cl_info
426 minPayloadSize :: SMRep -> Bool -> WordOff
427 minPayloadSize smrep updatable
429 BlackHoleRep -> min_upd_size
430 GenericRep _ _ _ _ | updatable -> min_upd_size
431 GenericRep True _ _ _ -> 0 -- static
432 GenericRep False _ _ _ -> mIN_PAYLOAD_SIZE
436 ASSERT(mIN_PAYLOAD_SIZE <= sIZEOF_StgSMPThunkHeader)
437 0 -- check that we already have enough
438 -- room for mIN_SIZE_NonUpdHeapObject,
439 -- due to the extra header word in SMP
442 %************************************************************************
444 \subsection[SMreps]{Choosing SM reps}
446 %************************************************************************
450 :: Bool -- True <=> static closure
452 -> WordOff -> WordOff -- Tot wds, ptr wds
455 chooseSMRep is_static lf_info tot_wds ptr_wds
457 nonptr_wds = tot_wds - ptr_wds
458 closure_type = getClosureType is_static ptr_wds lf_info
460 GenericRep is_static ptr_wds nonptr_wds closure_type
462 -- We *do* get non-updatable top-level thunks sometimes. eg. f = g
463 -- gets compiled to a jump to g (if g has non-zero arity), instead of
464 -- messing around with update frames and PAPs. We set the closure type
465 -- to FUN_STATIC in this case.
467 getClosureType :: Bool -> WordOff -> LambdaFormInfo -> ClosureType
468 getClosureType is_static ptr_wds lf_info
470 LFCon con | is_static && ptr_wds == 0 -> ConstrNoCaf
471 | otherwise -> Constr
472 LFReEntrant _ _ _ _ -> Fun
473 LFThunk _ _ _ (SelectorThunk _) _ -> ThunkSelector
474 LFThunk _ _ _ _ _ -> Thunk
475 _ -> panic "getClosureType"
478 %************************************************************************
480 \subsection[ClosureInfo-4-questions]{Four major questions about @ClosureInfo@}
482 %************************************************************************
484 Be sure to see the stg-details notes about these...
487 nodeMustPointToIt :: LambdaFormInfo -> Bool
488 nodeMustPointToIt (LFReEntrant top _ no_fvs _)
489 = not no_fvs || -- Certainly if it has fvs we need to point to it
491 -- If it is not top level we will point to it
492 -- We can have a \r closure with no_fvs which
493 -- is not top level as special case cgRhsClosure
494 -- has been dissabled in favour of let floating
496 -- For lex_profiling we also access the cost centre for a
497 -- non-inherited function i.e. not top level
498 -- the not top case above ensures this is ok.
500 nodeMustPointToIt (LFCon _) = True
502 -- Strictly speaking, the above two don't need Node to point
503 -- to it if the arity = 0. But this is a *really* unlikely
504 -- situation. If we know it's nil (say) and we are entering
505 -- it. Eg: let x = [] in x then we will certainly have inlined
506 -- x, since nil is a simple atom. So we gain little by not
507 -- having Node point to known zero-arity things. On the other
508 -- hand, we do lose something; Patrick's code for figuring out
509 -- when something has been updated but not entered relies on
510 -- having Node point to the result of an update. SLPJ
513 nodeMustPointToIt (LFThunk _ no_fvs updatable NonStandardThunk _)
514 = updatable || not no_fvs || opt_SccProfilingOn
515 -- For the non-updatable (single-entry case):
517 -- True if has fvs (in which case we need access to them, and we
518 -- should black-hole it)
519 -- or profiling (in which case we need to recover the cost centre
522 nodeMustPointToIt (LFThunk _ no_fvs updatable some_standard_form_thunk _)
523 = True -- Node must point to any standard-form thunk
525 nodeMustPointToIt (LFUnknown _) = True
526 nodeMustPointToIt (LFBlackHole _) = True -- BH entry may require Node to point
527 nodeMustPointToIt (LFLetNoEscape _) = False
530 The entry conventions depend on the type of closure being entered,
531 whether or not it has free variables, and whether we're running
532 sequentially or in parallel.
534 \begin{tabular}{lllll}
535 Closure Characteristics & Parallel & Node Req'd & Argument Passing & Enter Via \\
536 Unknown & no & yes & stack & node \\
537 Known fun ($\ge$ 1 arg), no fvs & no & no & registers & fast entry (enough args) \\
538 \ & \ & \ & \ & slow entry (otherwise) \\
539 Known fun ($\ge$ 1 arg), fvs & no & yes & registers & fast entry (enough args) \\
540 0 arg, no fvs @\r,\s@ & no & no & n/a & direct entry \\
541 0 arg, no fvs @\u@ & no & yes & n/a & node \\
542 0 arg, fvs @\r,\s@ & no & yes & n/a & direct entry \\
543 0 arg, fvs @\u@ & no & yes & n/a & node \\
545 Unknown & yes & yes & stack & node \\
546 Known fun ($\ge$ 1 arg), no fvs & yes & no & registers & fast entry (enough args) \\
547 \ & \ & \ & \ & slow entry (otherwise) \\
548 Known fun ($\ge$ 1 arg), fvs & yes & yes & registers & node \\
549 0 arg, no fvs @\r,\s@ & yes & no & n/a & direct entry \\
550 0 arg, no fvs @\u@ & yes & yes & n/a & node \\
551 0 arg, fvs @\r,\s@ & yes & yes & n/a & node \\
552 0 arg, fvs @\u@ & yes & yes & n/a & node\\
555 When black-holing, single-entry closures could also be entered via node
556 (rather than directly) to catch double-entry.
560 = EnterIt -- no args, not a function
562 | JumpToIt CLabel -- no args, not a function, but we
563 -- know what its entry code is
565 | ReturnIt -- it's a function, but we have
566 -- zero args to apply to it, so just
569 | ReturnCon DataCon -- It's a data constructor, just return it
571 | SlowCall -- Unknown fun, or known fun with
574 | DirectEntry -- Jump directly, with args in regs
575 CLabel -- The code label
578 getCallMethod :: Name -- Function being applied
579 -> LambdaFormInfo -- Its info
580 -> Int -- Number of available arguments
583 getCallMethod name lf_info n_args
584 | nodeMustPointToIt lf_info && opt_Parallel
585 = -- If we're parallel, then we must always enter via node.
586 -- The reason is that the closure may have been
587 -- fetched since we allocated it.
590 getCallMethod name (LFReEntrant _ arity _ _) n_args
591 | n_args == 0 = ASSERT( arity /= 0 )
592 ReturnIt -- No args at all
593 | n_args < arity = SlowCall -- Not enough args
594 | otherwise = DirectEntry (enterIdLabel name) arity
596 getCallMethod name (LFCon con) n_args
597 = ASSERT( n_args == 0 )
600 getCallMethod name (LFThunk _ _ updatable std_form_info is_fun) n_args
601 | is_fun -- it *might* be a function, so we must "call" it (which is
603 = SlowCall -- We cannot just enter it [in eval/apply, the entry code
604 -- is the fast-entry code]
606 -- Since is_fun is False, we are *definitely* looking at a data value
607 | updatable || opt_DoTickyProfiling -- to catch double entry
609 I decided to remove this, because in SMP mode it doesn't matter
610 if we enter the same thunk multiple times, so the optimisation
611 of jumping directly to the entry code is still valid. --SDM
614 -- We used to have ASSERT( n_args == 0 ), but actually it is
615 -- possible for the optimiser to generate
616 -- let bot :: Int = error Int "urk"
617 -- in (bot `cast` unsafeCoerce Int (Int -> Int)) 3
618 -- This happens as a result of the case-of-error transformation
619 -- So the right thing to do is just to enter the thing
621 | otherwise -- Jump direct to code for single-entry thunks
622 = ASSERT( n_args == 0 )
623 JumpToIt (thunkEntryLabel name std_form_info updatable)
625 getCallMethod name (LFUnknown True) n_args
626 = SlowCall -- might be a function
628 getCallMethod name (LFUnknown False) n_args
629 = ASSERT2 ( n_args == 0, ppr name <+> ppr n_args )
630 EnterIt -- Not a function
632 getCallMethod name (LFBlackHole _) n_args
633 = SlowCall -- Presumably the black hole has by now
634 -- been updated, but we don't know with
635 -- what, so we slow call it
637 getCallMethod name (LFLetNoEscape 0) n_args
638 = JumpToIt (enterReturnPtLabel (nameUnique name))
640 getCallMethod name (LFLetNoEscape arity) n_args
641 | n_args == arity = DirectEntry (enterReturnPtLabel (nameUnique name)) arity
642 | otherwise = pprPanic "let-no-escape: " (ppr name <+> ppr arity)
644 blackHoleOnEntry :: ClosureInfo -> Bool
645 -- Static closures are never themselves black-holed.
646 -- Updatable ones will be overwritten with a CAFList cell, which points to a
648 -- Single-entry ones have no fvs to plug, and we trust they don't form part
651 blackHoleOnEntry ConInfo{} = False
652 blackHoleOnEntry (ClosureInfo { closureLFInfo = lf_info, closureSMRep = rep })
654 = False -- Never black-hole a static closure
658 LFReEntrant _ _ _ _ -> False
659 LFLetNoEscape _ -> False
660 LFThunk _ no_fvs updatable _ _
662 then not opt_OmitBlackHoling
663 else opt_DoTickyProfiling || not no_fvs
664 -- the former to catch double entry,
665 -- and the latter to plug space-leaks. KSW/SDM 1999-04.
667 other -> panic "blackHoleOnEntry" -- Should never happen
669 isStandardFormThunk :: LambdaFormInfo -> Bool
670 isStandardFormThunk (LFThunk _ _ _ (SelectorThunk _) _) = True
671 isStandardFormThunk (LFThunk _ _ _ (ApThunk _) _) = True
672 isStandardFormThunk other_lf_info = False
674 isKnownFun :: LambdaFormInfo -> Bool
675 isKnownFun (LFReEntrant _ _ _ _) = True
676 isKnownFun (LFLetNoEscape _) = True
680 -----------------------------------------------------------------------------
684 staticClosureNeedsLink :: ClosureInfo -> Bool
685 -- A static closure needs a link field to aid the GC when traversing
686 -- the static closure graph. But it only needs such a field if either
688 -- b) it's a constructor with one or more pointer fields
689 -- In case (b), the constructor's fields themselves play the role
691 staticClosureNeedsLink (ClosureInfo { closureSRT = srt })
693 staticClosureNeedsLink (ConInfo { closureSMRep = sm_rep, closureCon = con })
694 = not (isNullaryRepDataCon con) && not_nocaf_constr
698 GenericRep _ _ _ ConstrNoCaf -> False
702 Avoiding generating entries and info tables
703 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
704 At present, for every function we generate all of the following,
705 just in case. But they aren't always all needed, as noted below:
707 [NB1: all of this applies only to *functions*. Thunks always
708 have closure, info table, and entry code.]
710 [NB2: All are needed if the function is *exported*, just to play safe.]
713 * Fast-entry code ALWAYS NEEDED
716 Needed iff (a) we have any un-saturated calls to the function
717 OR (b) the function is passed as an arg
718 OR (c) we're in the parallel world and the function has free vars
719 [Reason: in parallel world, we always enter functions
720 with free vars via the closure.]
722 * The function closure
723 Needed iff (a) we have any un-saturated calls to the function
724 OR (b) the function is passed as an arg
725 OR (c) if the function has free vars (ie not top level)
727 Why case (a) here? Because if the arg-satis check fails,
728 UpdatePAP stuffs a pointer to the function closure in the PAP.
729 [Could be changed; UpdatePAP could stuff in a code ptr instead,
730 but doesn't seem worth it.]
732 [NB: these conditions imply that we might need the closure
733 without the slow-entry code. Here's how.
735 f x y = let g w = ...x..y..w...
739 Here we need a closure for g which contains x and y,
740 but since the calls are all saturated we just jump to the
741 fast entry point for g, with R1 pointing to the closure for g.]
744 * Standard info table
745 Needed iff (a) we have any un-saturated calls to the function
746 OR (b) the function is passed as an arg
747 OR (c) the function has free vars (ie not top level)
749 NB. In the sequential world, (c) is only required so that the function closure has
750 an info table to point to, to keep the storage manager happy.
751 If (c) alone is true we could fake up an info table by choosing
752 one of a standard family of info tables, whose entry code just
755 [NB In the parallel world (c) is needed regardless because
756 we enter functions with free vars via the closure.]
758 If (c) is retained, then we'll sometimes generate an info table
759 (for storage mgr purposes) without slow-entry code. Then we need
760 to use an error label in the info table to substitute for the absent
764 staticClosureRequired
769 staticClosureRequired binder bndr_info
770 (LFReEntrant top_level _ _ _) -- It's a function
771 = ASSERT( isTopLevel top_level )
772 -- Assumption: it's a top-level, no-free-var binding
773 not (satCallsOnly bndr_info)
775 staticClosureRequired binder other_binder_info other_lf_info = True
778 %************************************************************************
780 \subsection[ClosureInfo-misc-funs]{Misc functions about @ClosureInfo@, etc.}
782 %************************************************************************
786 isStaticClosure :: ClosureInfo -> Bool
787 isStaticClosure cl_info = isStaticRep (closureSMRep cl_info)
789 closureUpdReqd :: ClosureInfo -> Bool
790 closureUpdReqd ClosureInfo{ closureLFInfo = lf_info } = lfUpdatable lf_info
791 closureUpdReqd ConInfo{} = False
793 lfUpdatable :: LambdaFormInfo -> Bool
794 lfUpdatable (LFThunk _ _ upd _ _) = upd
795 lfUpdatable (LFBlackHole _) = True
796 -- Black-hole closures are allocated to receive the results of an
797 -- alg case with a named default... so they need to be updated.
798 lfUpdatable _ = False
800 closureIsThunk :: ClosureInfo -> Bool
801 closureIsThunk ClosureInfo{ closureLFInfo = lf_info } = isLFThunk lf_info
802 closureIsThunk ConInfo{} = False
804 closureSingleEntry :: ClosureInfo -> Bool
805 closureSingleEntry (ClosureInfo { closureLFInfo = LFThunk _ _ upd _ _}) = not upd
806 closureSingleEntry other_closure = False
808 closureReEntrant :: ClosureInfo -> Bool
809 closureReEntrant (ClosureInfo { closureLFInfo = LFReEntrant _ _ _ _ }) = True
810 closureReEntrant other_closure = False
812 isConstrClosure_maybe :: ClosureInfo -> Maybe DataCon
813 isConstrClosure_maybe (ConInfo { closureCon = data_con }) = Just data_con
814 isConstrClosure_maybe _ = Nothing
816 closureFunInfo :: ClosureInfo -> Maybe (Int, ArgDescr)
817 closureFunInfo (ClosureInfo { closureLFInfo = lf_info }) = lfFunInfo lf_info
818 closureFunInfo _ = Nothing
820 lfFunInfo :: LambdaFormInfo -> Maybe (Int, ArgDescr)
821 lfFunInfo (LFReEntrant _ arity _ arg_desc) = Just (arity, arg_desc)
822 lfFunInfo _ = Nothing
824 funTag :: ClosureInfo -> Int
825 funTag (ClosureInfo { closureLFInfo = lf_info }) = funTagLFInfo lf_info
828 -- maybe this should do constructor tags too?
829 funTagLFInfo :: LambdaFormInfo -> Int
831 -- A function is tagged with its arity
832 | Just (arity,_) <- lfFunInfo lf,
833 Just tag <- tagForArity arity
836 -- other closures (and unknown ones) are not tagged
840 tagForArity :: Int -> Maybe Int
841 tagForArity i | i <= mAX_PTR_TAG = Just i
842 | otherwise = Nothing
846 isToplevClosure :: ClosureInfo -> Bool
847 isToplevClosure (ClosureInfo { closureLFInfo = lf_info })
849 LFReEntrant TopLevel _ _ _ -> True
850 LFThunk TopLevel _ _ _ _ -> True
852 isToplevClosure _ = False
858 infoTableLabelFromCI :: ClosureInfo -> CLabel
859 infoTableLabelFromCI (ClosureInfo { closureName = name,
860 closureLFInfo = lf_info,
861 closureSMRep = rep })
863 LFBlackHole info -> info
865 LFThunk _ _ upd_flag (SelectorThunk offset) _ ->
866 mkSelectorInfoLabel upd_flag offset
868 LFThunk _ _ upd_flag (ApThunk arity) _ ->
869 mkApInfoTableLabel upd_flag arity
871 LFThunk{} -> mkLocalInfoTableLabel name
873 LFReEntrant _ _ _ _ -> mkLocalInfoTableLabel name
875 other -> panic "infoTableLabelFromCI"
877 infoTableLabelFromCI (ConInfo { closureCon = con,
878 closureSMRep = rep })
879 | isStaticRep rep = mkStaticInfoTableLabel name
880 | otherwise = mkConInfoTableLabel name
882 name = dataConName con
884 -- ClosureInfo for a closure (as opposed to a constructor) is always local
885 closureLabelFromCI (ClosureInfo { closureName = nm }) = mkLocalClosureLabel nm
886 closureLabelFromCI _ = panic "closureLabelFromCI"
888 -- thunkEntryLabel is a local help function, not exported. It's used from both
889 -- entryLabelFromCI and getCallMethod.
891 thunkEntryLabel thunk_id (ApThunk arity) is_updatable
892 = enterApLabel is_updatable arity
893 thunkEntryLabel thunk_id (SelectorThunk offset) upd_flag
894 = enterSelectorLabel upd_flag offset
895 thunkEntryLabel thunk_id _ is_updatable
896 = enterIdLabel thunk_id
898 enterApLabel is_updatable arity
899 | tablesNextToCode = mkApInfoTableLabel is_updatable arity
900 | otherwise = mkApEntryLabel is_updatable arity
902 enterSelectorLabel upd_flag offset
903 | tablesNextToCode = mkSelectorInfoLabel upd_flag offset
904 | otherwise = mkSelectorEntryLabel upd_flag offset
907 | tablesNextToCode = mkInfoTableLabel id
908 | otherwise = mkEntryLabel id
911 | tablesNextToCode = mkLocalInfoTableLabel id
912 | otherwise = mkLocalEntryLabel id
914 enterReturnPtLabel name
915 | tablesNextToCode = mkReturnInfoLabel name
916 | otherwise = mkReturnPtLabel name
920 We need a black-hole closure info to pass to @allocDynClosure@ when we
921 want to allocate the black hole on entry to a CAF. These are the only
922 ways to build an LFBlackHole, maintaining the invariant that it really
923 is a black hole and not something else.
926 cafBlackHoleClosureInfo (ClosureInfo { closureName = nm,
928 = ClosureInfo { closureName = nm,
929 closureLFInfo = LFBlackHole mkCAFBlackHoleInfoTableLabel,
930 closureSMRep = BlackHoleRep,
931 closureSRT = NoC_SRT,
934 cafBlackHoleClosureInfo _ = panic "cafBlackHoleClosureInfo"
936 seCafBlackHoleClosureInfo (ClosureInfo { closureName = nm,
938 = ClosureInfo { closureName = nm,
939 closureLFInfo = LFBlackHole mkSECAFBlackHoleInfoTableLabel,
940 closureSMRep = BlackHoleRep,
941 closureSRT = NoC_SRT,
944 seCafBlackHoleClosureInfo _ = panic "seCafBlackHoleClosureInfo"
947 %************************************************************************
949 \subsection[ClosureInfo-Profiling-funs]{Misc functions about for profiling info.}
951 %************************************************************************
953 Profiling requires two pieces of information to be determined for
954 each closure's info table --- description and type.
956 The description is stored directly in the @CClosureInfoTable@ when the
959 The type is determined from the type information stored with the @Id@
960 in the closure info using @closureTypeDescr@.
963 closureValDescr, closureTypeDescr :: ClosureInfo -> String
964 closureValDescr (ClosureInfo {closureDescr = descr})
966 closureValDescr (ConInfo {closureCon = con})
967 = occNameString (getOccName con)
969 closureTypeDescr (ClosureInfo { closureType = ty })
970 = getTyDescription ty
971 closureTypeDescr (ConInfo { closureCon = data_con })
972 = occNameString (getOccName (dataConTyCon data_con))
974 getTyDescription :: Type -> String
976 = case (tcSplitSigmaTy ty) of { (_, _, tau_ty) ->
979 AppTy fun _ -> getTyDescription fun
980 FunTy _ res -> '-' : '>' : fun_result res
981 TyConApp tycon _ -> getOccString tycon
982 PredTy sty -> getPredTyDescription sty
983 ForAllTy _ ty -> getTyDescription ty
986 fun_result (FunTy _ res) = '>' : fun_result res
987 fun_result other = getTyDescription other
989 getPredTyDescription (ClassP cl tys) = getOccString cl
990 getPredTyDescription (IParam ip ty) = getOccString (ipNameName ip)