2 % (c) The GRASP/AQUA Project, Glasgow University, 1992-1995
4 %********************************************************
6 \section[CgExpr]{Converting @StgExpr@s}
8 %********************************************************
11 #include "HsVersions.h"
13 module CgExpr ( cgExpr, getPrimOpArgAmodes ) where
16 IMPORT_DELOOPER(CgLoop2) -- here for paranoia-checking
18 import Constants ( mAX_SPEC_SELECTEE_SIZE )
23 import AbsCUtils ( mkAbsCStmts, mkAbstractCs )
24 import CgBindery ( getArgAmodes, getCAddrModeAndInfo, CgIdInfo )
25 import CgCase ( cgCase, saveVolatileVarsAndRegs )
26 import CgClosure ( cgRhsClosure )
27 import CgCon ( buildDynCon, cgReturnDataCon )
28 import CgHeapery ( allocHeap )
29 import CgLetNoEscape ( cgLetNoEscapeClosure )
30 import CgRetConv ( dataReturnConvAlg, ctrlReturnConvAlg,
31 DataReturnConvention(..), CtrlReturnConvention(..),
32 assignPrimOpResultRegs, makePrimOpArgsRobust
34 import CgTailCall ( cgTailCall, performReturn,
35 mkDynamicAlgReturnCode, mkPrimReturnCode
37 import CLabel ( mkPhantomInfoTableLabel, mkInfoTableVecTblLabel )
38 import ClosureInfo ( mkClosureLFInfo, mkSelectorLFInfo, mkVapLFInfo, lfArity_maybe,
40 import CostCentre ( sccAbleCostCentre, isDictCC, isSccCountCostCentre )
41 import HeapOffs ( SYN_IE(VirtualSpBOffset), intOffsetIntoGoods )
42 import Id ( dataConTyCon, idPrimRep, getIdArity,
43 mkIdSet, unionIdSets, GenId{-instance Outputable-}
45 import IdInfo ( ArityInfo(..) )
46 import Name ( isLocallyDefined )
47 import PprStyle ( PprStyle(..) )
48 import PrimOp ( primOpCanTriggerGC, primOpHeapReq, HeapRequirement(..),
49 getPrimOpResultInfo, PrimOp(..), PrimOpResultInfo(..)
51 import PrimRep ( getPrimRepSize, PrimRep(..) )
52 import TyCon ( tyConDataCons, maybeTyConSingleCon )
53 import Maybes ( assocMaybe, maybeToBool )
54 import Util ( panic, isIn, pprPanic, assertPanic )
57 This module provides the support code for @StgToAbstractC@ to deal
58 with STG {\em expressions}. See also @CgClosure@, which deals
59 with closures, and @CgCon@, which deals with constructors.
62 cgExpr :: StgExpr -- input
66 %********************************************************
70 %********************************************************
72 ``Applications'' mean {\em tail calls}, a service provided by module
73 @CgTailCall@. This includes literals, which show up as
74 @(STGApp (StgLitArg 42) [])@.
77 cgExpr (StgApp fun args live_vars) = cgTailCall fun args live_vars
80 %********************************************************
82 %* STG ConApps (for inline versions) *
84 %********************************************************
87 cgExpr (StgCon con args live_vars)
88 = getArgAmodes args `thenFC` \ amodes ->
89 cgReturnDataCon con amodes (all zero_size args) live_vars
91 zero_size atom = getPrimRepSize (getArgPrimRep atom) == 0
94 %********************************************************
96 %* STG PrimApps (unboxed primitive ops) *
98 %********************************************************
100 Here is where we insert real live machine instructions.
103 cgExpr x@(StgPrim op args live_vars)
104 = ASSERT(op /= SeqOp) -- can't handle SeqOp
105 getPrimOpArgAmodes op args `thenFC` \ arg_amodes ->
107 result_regs = assignPrimOpResultRegs op
108 result_amodes = map CReg result_regs
109 may_gc = primOpCanTriggerGC op
110 dyn_tag = head result_amodes
111 -- The tag from a primitive op returning an algebraic data type
112 -- is returned in the first result_reg_amode
115 -- Use registers for args, and assign args to the regs
116 -- (Can-trigger-gc primops guarantee to have their args in regs)
118 (arg_robust_amodes, liveness_mask, arg_assts)
119 = makePrimOpArgsRobust op arg_amodes
121 liveness_arg = mkIntCLit liveness_mask
125 COpStmt result_amodes op
126 (pin_liveness op liveness_arg arg_robust_amodes)
131 -- Use args from their current amodes.
133 liveness_mask = panic "cgExpr: liveness of non-GC-ing primop touched\n"
136 COpStmt result_amodes op arg_amodes liveness_mask [{-no vol_regs-}],
139 ) `thenFC` \ (do_before_stack_cleanup,
140 do_just_before_jump) ->
142 case (getPrimOpResultInfo op) of
145 performReturn do_before_stack_cleanup
146 (\ sequel -> robustifySequel may_gc sequel
147 `thenFC` \ (ret_asst, sequel') ->
148 absC (ret_asst `mkAbsCStmts` do_just_before_jump)
150 mkPrimReturnCode sequel')
154 profCtrC SLIT("RET_NEW_IN_REGS") [num_of_fields] `thenC`
156 performReturn do_before_stack_cleanup
157 (\ sequel -> robustifySequel may_gc sequel
158 `thenFC` \ (ret_asst, sequel') ->
159 absC (mkAbstractCs [ret_asst,
162 -- Must load info ptr here, not in do_just_before_stack_cleanup,
163 -- because the info-ptr reg clashes with argument registers
166 mkDynamicAlgReturnCode tycon dyn_tag sequel')
170 -- Here, the destination _can_ be an update frame, so we need to make sure that
171 -- infoptr (R2) is loaded with the constructor's info ptr.
173 info_ptr_assign = CAssign (CReg infoptr) info_lbl
176 = case (ctrlReturnConvAlg tycon) of
177 VectoredReturn _ -> vec_lbl
178 UnvectoredReturn _ -> dir_lbl
180 vec_lbl = CTableEntry (CLbl (mkInfoTableVecTblLabel tycon) DataPtrRep)
183 data_con = head (tyConDataCons tycon)
185 (dir_lbl, num_of_fields)
186 = case (dataReturnConvAlg data_con) of
188 -> (CLbl (mkPhantomInfoTableLabel data_con) DataPtrRep,
189 mkIntCLit (length rs)) -- for ticky-ticky only
192 -> pprPanic "CgExpr: can't return prim in heap:" (ppr PprDebug data_con)
193 -- Never used, and no point in generating
196 -- for all PrimOps except ccalls, we pin the liveness info
197 -- on as the first "argument"
198 -- ToDo: un-duplicate?
200 pin_liveness (CCallOp _ _ _ _ _) _ args = args
201 pin_liveness other_op liveness_arg args
204 -- We only need to worry about the sequel when we may GC and the
205 -- sequel is OnStack. If that's the case, arrange to pull the
206 -- sequel out into RetReg before performing the primOp.
208 robustifySequel True sequel@(OnStack _) =
209 sequelToAmode sequel `thenFC` \ amode ->
210 returnFC (CAssign (CReg RetReg) amode, InRetReg)
211 robustifySequel _ sequel = returnFC (AbsCNop, sequel)
214 %********************************************************
216 %* Case expressions *
218 %********************************************************
219 Case-expression conversion is complicated enough to have its own
223 cgExpr (StgCase expr live_vars save_vars uniq alts)
224 = cgCase expr live_vars save_vars uniq alts
228 %********************************************************
232 %********************************************************
233 \subsection[let-and-letrec-codegen]{Converting @StgLet@ and @StgLetrec@}
236 cgExpr (StgLet (StgNonRec name rhs) expr)
237 = cgRhs name rhs `thenFC` \ (name, info) ->
238 addBindC name info `thenC`
241 cgExpr (StgLet (StgRec pairs) expr)
242 = fixC (\ new_bindings -> addBindsC new_bindings `thenC`
243 listFCs [ cgRhs b e | (b,e) <- pairs ]
244 ) `thenFC` \ new_bindings ->
246 addBindsC new_bindings `thenC`
251 cgExpr (StgLetNoEscape live_in_whole_let live_in_rhss bindings body)
252 = -- Figure out what volatile variables to save
253 nukeDeadBindings live_in_whole_let `thenC`
254 saveVolatileVarsAndRegs live_in_rhss
255 `thenFC` \ (save_assts, rhs_eob_info, maybe_cc_slot) ->
257 -- ToDo: cost centre???
259 -- Save those variables right now!
260 absC save_assts `thenC`
262 -- Produce code for the rhss
263 -- and add suitable bindings to the environment
264 cgLetNoEscapeBindings live_in_rhss rhs_eob_info maybe_cc_slot bindings `thenC`
267 setEndOfBlockInfo rhs_eob_info (cgExpr body)
271 %********************************************************
275 %********************************************************
276 \subsection[scc-codegen]{Converting StgSCC}
278 SCC expressions are treated specially. They set the current cost
281 cgExpr (StgSCC ty cc expr)
282 = ASSERT(sccAbleCostCentre cc)
284 (if isDictCC cc then SLIT("SET_DICT_CCC") else SLIT("SET_CCC"))
285 [mkCCostCentre cc, mkIntCLit (if isSccCountCostCentre cc then 1 else 0)]
290 ToDo: counting of dict sccs ...
292 %********************************************************
294 %* Non-top-level bindings *
296 %********************************************************
297 \subsection[non-top-level-bindings]{Converting non-top-level bindings}
299 We rely on the support code in @CgCon@ (to do constructors) and
300 in @CgClosure@ (to do closures).
303 cgRhs :: Id -> StgRhs -> FCode (Id, CgIdInfo)
304 -- the Id is passed along so a binding can be set up
306 cgRhs name (StgRhsCon maybe_cc con args)
307 = getArgAmodes args `thenFC` \ amodes ->
308 buildDynCon name maybe_cc con amodes (all zero_size args)
310 returnFC (name, idinfo)
312 zero_size atom = getPrimRepSize (getArgPrimRep atom) == 0
314 cgRhs name (StgRhsClosure cc bi fvs upd_flag args body)
315 = mkRhsLFInfo fvs upd_flag args body `thenFC` \ lf_info ->
316 cgRhsClosure name cc bi fvs args body lf_info
319 mkRhsLFInfo looks for two special forms of the right-hand side:
323 If neither happens, it just calls mkClosureLFInfo. You might think
324 that mkClosureLFInfo should do all this, but
325 (a) it seems wrong for the latter to look at the structure
327 (b) mkRhsLFInfo has to be in the monad since it looks up in
328 the environment, and it's very tiresome for mkClosureLFInfo to
329 be. Apart from anything else it would make a loop between
330 CgBindery and ClosureInfo.
334 We look at the body of the closure to see if it's a selector---turgid,
335 but nothing deep. We are looking for a closure of {\em exactly} the
338 ... = [the_fv] \ u [] ->
340 con a_1 ... a_n -> a_i
344 mkRhsLFInfo [the_fv] -- Just one free var
345 Updatable -- Updatable thunk
347 (StgCase (StgApp (StgVarArg scrutinee) [{-no args-}] _)
348 _ _ _ -- ignore live vars and uniq...
350 [(con, params, use_mask,
351 (StgApp (StgVarArg selectee) [{-no args-}] _))]
353 | the_fv == scrutinee -- Scrutinee is the only free variable
354 && maybeToBool maybe_offset -- Selectee is a component of the tuple
355 && maybeToBool offset_into_int_maybe
356 && offset_into_int <= mAX_SPEC_SELECTEE_SIZE -- Offset is small enough
357 = -- ASSERT(is_single_constructor) -- Should be true, but causes error for SpecTyCon
358 returnFC (mkSelectorLFInfo scrutinee con offset_into_int)
360 (_, params_w_offsets) = layOutDynCon con idPrimRep params
361 maybe_offset = assocMaybe params_w_offsets selectee
362 Just the_offset = maybe_offset
363 offset_into_int_maybe = intOffsetIntoGoods the_offset
364 Just offset_into_int = offset_into_int_maybe
365 is_single_constructor = maybeToBool (maybeTyConSingleCon tycon)
366 tycon = dataConTyCon con
372 Same kind of thing, looking for vector-apply thunks, of the form:
374 x = [...] \ .. [] -> f a1 .. an
376 where f has arity n. We rely on the arity info inside the Id being correct.
381 [] -- No args; a thunk
382 (StgApp (StgVarArg fun_id) args _)
383 | isLocallyDefined fun_id -- Must be defined in this module
384 = -- Get the arity of the fun_id. We could find out from the
385 -- looking in the Id, but it's more certain just to look in the code
386 -- generator's environment.
388 ----------------------------------------------
389 -- Sadly, looking in the environment, as suggested above,
390 -- causes a black hole (because cgRhsClosure depends on the LFInfo
391 -- returned here to determine its control flow.
392 -- So I wimped out and went back to looking at the arity inside the Id.
393 -- That means beefing up Core2Stg to propagate it. Sigh.
394 -- getCAddrModeAndInfo fun_id `thenFC` \ (_, fun_lf_info) ->
395 -- let arity_maybe = lfArity_maybe fun_lf_info
396 ----------------------------------------------
399 arity_maybe = case getIdArity fun_id of
400 ArityExactly n -> Just n
403 returnFC (case arity_maybe of
405 | arity > 0 && -- It'd better be a function!
406 arity == length args -- Saturated application
407 -> -- Ha! A VAP thunk
408 mkVapLFInfo fvs upd_flag fun_id args store_fun_in_vap
410 other -> mkClosureLFInfo False{-not top level-} fvs upd_flag []
414 -- If the function is a free variable then it must be stored
415 -- in the thunk too; if it isn't a free variable it must be
416 -- because it's constant, so it doesn't need to be stored in the thunk
417 store_fun_in_vap = fun_id `is_elem` fvs
418 is_elem = isIn "mkClosureLFInfo"
424 mkRhsLFInfo fvs upd_flag args body
425 = returnFC (mkClosureLFInfo False{-not top level-} fvs upd_flag args)
429 %********************************************************
431 %* Let-no-escape bindings
433 %********************************************************
435 cgLetNoEscapeBindings live_in_rhss rhs_eob_info maybe_cc_slot (StgNonRec binder rhs)
436 = cgLetNoEscapeRhs live_in_rhss rhs_eob_info maybe_cc_slot binder rhs
437 `thenFC` \ (binder, info) ->
440 cgLetNoEscapeBindings live_in_rhss rhs_eob_info maybe_cc_slot (StgRec pairs)
441 = fixC (\ new_bindings ->
442 addBindsC new_bindings `thenC`
443 listFCs [ cgLetNoEscapeRhs full_live_in_rhss rhs_eob_info
444 maybe_cc_slot b e | (b,e) <- pairs ]
445 ) `thenFC` \ new_bindings ->
447 addBindsC new_bindings
449 -- We add the binders to the live-in-rhss set so that we don't
450 -- delete the bindings for the binder from the environment!
451 full_live_in_rhss = live_in_rhss `unionIdSets` (mkIdSet [b | (b,r) <- pairs])
454 :: StgLiveVars -- Live in rhss
456 -> Maybe VirtualSpBOffset
459 -> FCode (Id, CgIdInfo)
461 cgLetNoEscapeRhs full_live_in_rhss rhs_eob_info maybe_cc_slot binder
462 (StgRhsClosure cc bi _ upd_flag args body)
463 = -- We could check the update flag, but currently we don't switch it off
464 -- for let-no-escaped things, so we omit the check too!
466 -- Updatable -> panic "cgLetNoEscapeRhs" -- Nothing to update!
467 -- other -> cgLetNoEscapeClosure binder cc bi live_in_whole_let live_in_rhss args body
468 cgLetNoEscapeClosure binder cc bi full_live_in_rhss rhs_eob_info maybe_cc_slot args body
470 -- For a constructor RHS we want to generate a single chunk of code which
471 -- can be jumped to from many places, which will return the constructor.
472 -- It's easy; just behave as if it was an StgRhsClosure with a ConApp inside!
473 cgLetNoEscapeRhs full_live_in_rhss rhs_eob_info maybe_cc_slot binder
474 (StgRhsCon cc con args)
475 = cgLetNoEscapeClosure binder cc stgArgOcc{-safe-} full_live_in_rhss rhs_eob_info maybe_cc_slot
476 [] --No args; the binder is data structure, not a function
477 (StgCon con args full_live_in_rhss)
480 Some PrimOps require a {\em fixed} amount of heap allocation. Rather
481 than tidy away ready for GC and do a full heap check, we simply
482 allocate a completely uninitialised block in-line, just like any other
483 thunk/constructor allocation, and pass it to the PrimOp as its first
484 argument. Remember! The PrimOp is entirely responsible for
485 initialising the object. In particular, the PrimOp had better not
486 trigger GC before it has filled it in, and even then it had better
487 make sure that the GC can find the object somehow.
489 Main current use: allocating SynchVars.
492 getPrimOpArgAmodes op args
493 = getArgAmodes args `thenFC` \ arg_amodes ->
495 case primOpHeapReq op of
496 FixedHeapRequired size -> allocHeap size `thenFC` \ amode ->
497 returnFC (amode : arg_amodes)
499 _ -> returnFC arg_amodes