1 -----------------------------------------------------------------------------
3 -- Stg to C-- code generation: bindings
5 -- (c) The University of Glasgow 2004-2006
7 -----------------------------------------------------------------------------
15 #include "HsVersions.h"
30 import CoreSyn ( AltCon(..) )
50 ------------------------------------------------------------------------
52 ------------------------------------------------------------------------
54 -- For closures bound at top level, allocate in static space.
55 -- They should have no free variables.
58 -> CostCentreStack -- Optional cost centre annotation
64 -> FCode (Id, CgIdInfo)
66 cgTopRhsClosure id ccs binder_info upd_flag srt args body = do
67 { -- LAY OUT THE OBJECT
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 []
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 }
85 ; returnFC (id, cg_id_info) }
87 ------------------------------------------------------------------------
88 -- Non-top-level bindings
89 ------------------------------------------------------------------------
91 cgBind :: StgBinding -> FCode ()
92 cgBind (StgNonRec name rhs)
93 = do { (name, info) <- cgRhs name rhs
94 ; addBindC name info }
97 = do { new_binds <- fixC (\ new_binds ->
98 do { addBindsC new_binds
99 ; listFCs [ cgRhs b e | (b,e) <- pairs ] })
100 ; addBindsC new_binds }
103 cgRhs :: Id -> StgRhs -> FCode (Id, CgIdInfo)
104 -- The Id is passed along so a binding can be set up
106 cgRhs name (StgRhsCon maybe_cc con args)
107 = do { idinfo <- buildDynCon name maybe_cc con args
108 ; return (name, idinfo) }
110 cgRhs name (StgRhsClosure cc bi fvs upd_flag srt args body)
111 = mkRhsClosure name cc bi fvs upd_flag srt args body
113 ------------------------------------------------------------------------
114 -- Non-constructor right hand sides
115 ------------------------------------------------------------------------
117 mkRhsClosure :: Id -> CostCentreStack -> StgBinderInfo
122 -> FCode (Id, CgIdInfo)
124 {- mkRhsClosure looks for two special forms of the right-hand side:
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
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
138 ... = [the_fv] \ u [] ->
140 con a_1 ... a_n -> a_i
144 A more generic AP thunk of the form
146 x = [ x_1...x_n ] \.. [] -> x_1 ... x_n
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
154 We only generate an Ap thunk if all the free variables are pointers,
155 for semi-obvious reasons.
159 ---------- Note [Selectors] ------------------
160 mkRhsClosure bndr cc bi
161 [the_fv] -- Just one free var
162 upd_flag -- Updatable thunk
165 body@(StgCase (StgApp scrutinee [{-no args-}])
166 _ _ _ _ -- ignore uniq, etc.
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
180 -- srt is discarded; it must be empty
181 cgStdThunk bndr cc bi body lf_info [StgVarArg the_fv]
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
191 ---------- Note [Ap thunks] ------------------
192 mkRhsClosure bndr cc bi
196 [] -- No args; a thunk
197 body@(StgApp fun_id args)
199 | args `lengthIs` (arity-1)
200 && all isFollowableArg (map idCgRep fvs)
201 && isUpdatable upd_flag
202 && arity <= mAX_SPEC_AP_SIZE
205 = cgStdThunk bndr cc bi body lf_info payload
207 lf_info = mkApLFInfo bndr upd_flag arity
208 -- the payload has to be in the correct order, hence we can't
210 payload = StgVarArg fun_id : args
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...
224 is_elem = isIn "cgRhsClosure"
225 bndr_is_a_fv = bndr `is_elem` fvs
226 reduced_fvs | bndr_is_a_fv = fvs `minusList` [bndr]
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
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
251 -- Bind the free variables
252 ; mapCs (bind_fv node) fv_details
254 -- And compile the body
255 ; closureCodeBody bi closure_info cc c_srt node args body }
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)
264 ; return (bndr, regIdInfo bndr lf_info tmp) }
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)
270 bind_fv node (id, off)
271 = do { reg <- rebindToReg id
272 ; emit $ mkTaggedObjectLoad reg node off tag }
274 -------------------------
277 -> CostCentreStack -- Optional cost centre annotation
278 -> StgBinderInfo -- XXX: not used??
281 -> [StgArg] -- payload
282 -> FCode (Id, CgIdInfo)
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)
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
297 ; (use_cc, blame_cc) <- chooseDynCostCentres cc [{- no args-}] body
300 ; tmp <- allocDynClosure closure_info use_cc blame_cc payload_w_offsets
303 ; returnFC (bndr, regIdInfo bndr lf_info tmp) }
305 mkClosureLFInfo :: Id -- The binder
306 -> TopLevelFlag -- True of top level
308 -> UpdateFlag -- Update flag
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) }
317 ------------------------------------------------------------------------
318 -- The code for closures}
319 ------------------------------------------------------------------------
321 closureCodeBody :: StgBinderInfo -- XXX: unused?
322 -> ClosureInfo -- Lots of information about this closure
323 -> CostCentreStack -- Optional cost centre attached to closure
325 -> LocalReg -- The closure itself; first argument
326 -- The Id is in scope already, bound to this reg
331 {- There are two main cases for the code for closures.
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!
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.
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 -}
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 }
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
358 -- -- XXX: no slow-entry code for now
359 -- -- Emit the slow-entry code
360 -- { reg_save_code <- mkSlowEntryCode cl_info reg_args
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
372 ; entryHeapCheck node arg_regs srt $
375 ; emitClosureCodeAndInfoTable cl_info (node:arg_regs) blks
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
386 -- The slow entry point is used in two places:
388 -- (a) unknown calls: eg. stg_PAP_entry
389 -- (b) returning from a heap-check failure
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
403 name = closureName cl_info
404 slow_lbl = mkSlowEntryLabel name
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
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))
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)
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))
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)) []
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)
435 ; tickyEnterThunk cl_info
436 ; ldvEnterClosure cl_info -- NB: Node always points when profiling
437 ; granThunk node_points
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)
447 ; setupUpdate cl_info node
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
458 ------------------------------------------------------------------------
459 -- Update and black-hole wrappers
460 ------------------------------------------------------------------------
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)
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)))
475 bh_lbl | is_single_entry = mkRtsDataLabel (sLit "stg_SE_BLACKHOLE_info")
476 | otherwise = mkRtsDataLabel (sLit "stg_BLACKHOLE_info")
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]
484 -- Profiling needs slop filling (to support LDV profiling), so
485 -- currently eager blackholing doesn't work with profiling.
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
492 eager_blackholing = False
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
502 | not (isStaticClosure closure_info)
503 = if closureUpdReqd closure_info
504 then do { tickyPushUpdateFrame; pushUpdateFrame node }
505 else tickyUpdateFrameOmitted
507 | otherwise -- A static closure
508 = do { tickyUpdateBhCaf closure_info
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
517 pushUpdateFrame :: LocalReg -> FCode ()
518 pushUpdateFrame cl_reg
519 = emit (mkAddToContext (mkLblExpr mkUpdInfoLabel)
520 [CmmReg (CmmLocal cl_reg)])
522 -----------------------------------------------------------------------------
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.
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.
532 -- Why do we make a black hole in the heap when we enter a CAF?
534 -- - for a generational garbage collector, which needs a fast
535 -- test for whether an updatee is in an old generation or not
537 -- - for the parallel system, which can implement updates more
538 -- easily if the updatee is always in the heap. (allegedly).
540 -- When debugging, we maintain a separate CAF list so we can tell when
541 -- a CAF has been garbage collected.
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.)
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.
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)
568 ; hp_rel <- allocDynClosure bh_cl_info use_cc blame_cc []
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.
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)
584 bh_cl_info :: ClosureInfo
585 bh_cl_info | is_upd = cafBlackHoleClosureInfo cl_info
586 | otherwise = seCafBlackHoleClosureInfo cl_info
588 ind_static_info :: CmmExpr
589 ind_static_info = mkLblExpr mkIndStaticInfoLabel
591 off_indirectee :: WordOff
592 off_indirectee = fixedHdrSize + oFFSET_StgInd_indirectee*wORD_SIZE
595 ------------------------------------------------------------------------
597 ------------------------------------------------------------------------
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.
603 closureDescription :: Module -- Module
604 -> Name -- Id of closure binding
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) <>
614 -- showSDocDump, because we want to see the unique on the Name.