2 % (c) The University of Glasgow 2006
3 % (c) The GRASP/AQUA Project, Glasgow University, 1992-1998
7 module CgExpr ( cgExpr ) where
9 #include "HsVersions.h"
47 This module provides the support code for @StgToAbstractC@ to deal
48 with STG {\em expressions}. See also @CgClosure@, which deals
49 with closures, and @CgCon@, which deals with constructors.
52 cgExpr :: StgExpr -- input
56 %********************************************************
60 %********************************************************
62 ``Applications'' mean {\em tail calls}, a service provided by module
63 @CgTailCall@. This includes literals, which show up as
64 @(STGApp (StgLitArg 42) [])@.
67 cgExpr (StgApp fun args) = cgTailCall fun args
70 %********************************************************
72 %* STG ConApps (for inline versions) *
74 %********************************************************
77 cgExpr (StgConApp con args)
78 = do { amodes <- getArgAmodes args
79 ; cgReturnDataCon con amodes }
82 Literals are similar to constructors; they return by putting
83 themselves in an appropriate register and returning to the address on
88 = do { cmm_lit <- cgLit lit
89 ; performPrimReturn rep (CmmLit cmm_lit) }
91 rep = (typeCgRep) (literalType lit)
95 %********************************************************
97 %* PrimOps and foreign calls.
99 %********************************************************
101 NOTE about "safe" foreign calls: a safe foreign call is never compiled
102 inline in a case expression. When we see
104 case (ccall ...) of { ... }
106 We generate a proper return address for the alternatives and push the
107 stack frame before doing the call, so that in the event that the call
108 re-enters the RTS the stack is in a sane state.
111 cgExpr (StgOpApp (StgFCallOp fcall _) stg_args res_ty) = do
113 First, copy the args into temporaries. We're going to push
114 a return address right before doing the call, so the args
115 must be out of the way.
117 reps_n_amodes <- getArgAmodes stg_args
119 -- Get the *non-void* args, and jiggle them with shimForeignCall
120 arg_exprs = [ shimForeignCallArg stg_arg expr
121 | (stg_arg, (rep,expr)) <- stg_args `zip` reps_n_amodes,
125 arg_tmps <- mapM assignTemp arg_exprs
127 arg_hints = zip arg_tmps (map (typeHint.stgArgType) stg_args)
130 Now, allocate some result regs.
132 (res_reps,res_regs,res_hints) <- newUnboxedTupleRegs res_ty
133 ccallReturnUnboxedTuple (zip res_reps (map CmmReg res_regs)) $
134 emitForeignCall (zip res_regs res_hints) fcall
135 arg_hints emptyVarSet{-no live vars-}
137 -- tagToEnum# is special: we need to pull the constructor out of the table,
138 -- and perform an appropriate return.
140 cgExpr (StgOpApp (StgPrimOp TagToEnumOp) [arg] res_ty)
141 = ASSERT(isEnumerationTyCon tycon)
142 do { (_,amode) <- getArgAmode arg
143 ; amode' <- assignTemp amode -- We're going to use it twice,
144 -- so save in a temp if non-trivial
145 ; this_pkg <- getThisPackage
146 ; stmtC (CmmAssign nodeReg (tagToClosure this_pkg tycon amode'))
147 ; performReturn (emitAlgReturnCode tycon amode') }
149 -- If you're reading this code in the attempt to figure
150 -- out why the compiler panic'ed here, it is probably because
151 -- you used tagToEnum# in a non-monomorphic setting, e.g.,
152 -- intToTg :: Enum a => Int -> a ; intToTg (I# x#) = tagToEnum# x#
154 tycon = tyConAppTyCon res_ty
157 cgExpr x@(StgOpApp op@(StgPrimOp primop) args res_ty)
158 | primOpOutOfLine primop
159 = tailCallPrimOp primop args
161 | ReturnsPrim VoidRep <- result_info
162 = do cgPrimOp [] primop args emptyVarSet
163 performReturn emitDirectReturnInstr
165 | ReturnsPrim rep <- result_info
166 = do cgPrimOp [dataReturnConvPrim (primRepToCgRep rep)]
167 primop args emptyVarSet
168 performReturn emitDirectReturnInstr
170 | ReturnsAlg tycon <- result_info, isUnboxedTupleTyCon tycon
171 = do (reps, regs, _hints) <- newUnboxedTupleRegs res_ty
172 cgPrimOp regs primop args emptyVarSet{-no live vars-}
173 returnUnboxedTuple (zip reps (map CmmReg regs))
175 | ReturnsAlg tycon <- result_info, isEnumerationTyCon tycon
176 -- c.f. cgExpr (...TagToEnumOp...)
177 = do tag_reg <- newTemp wordRep
178 this_pkg <- getThisPackage
179 cgPrimOp [tag_reg] primop args emptyVarSet
180 stmtC (CmmAssign nodeReg (tagToClosure this_pkg tycon (CmmReg tag_reg)))
181 performReturn (emitAlgReturnCode tycon (CmmReg tag_reg))
183 result_info = getPrimOpResultInfo primop
186 %********************************************************
188 %* Case expressions *
190 %********************************************************
191 Case-expression conversion is complicated enough to have its own
195 cgExpr (StgCase expr live_vars save_vars bndr srt alt_type alts)
196 = cgCase expr live_vars save_vars bndr srt alt_type alts
200 %********************************************************
204 %********************************************************
205 \subsection[let-and-letrec-codegen]{Converting @StgLet@ and @StgLetrec@}
208 cgExpr (StgLet (StgNonRec name rhs) expr)
209 = cgRhs name rhs `thenFC` \ (name, info) ->
210 addBindC name info `thenC`
213 cgExpr (StgLet (StgRec pairs) expr)
214 = fixC (\ new_bindings -> addBindsC new_bindings `thenC`
215 listFCs [ cgRhs b e | (b,e) <- pairs ]
216 ) `thenFC` \ new_bindings ->
218 addBindsC new_bindings `thenC`
223 cgExpr (StgLetNoEscape live_in_whole_let live_in_rhss bindings body)
224 = do { -- Figure out what volatile variables to save
225 ; nukeDeadBindings live_in_whole_let
226 ; (save_assts, rhs_eob_info, maybe_cc_slot)
227 <- saveVolatileVarsAndRegs live_in_rhss
229 -- Save those variables right now!
230 ; emitStmts save_assts
232 -- Produce code for the rhss
233 -- and add suitable bindings to the environment
234 ; cgLetNoEscapeBindings live_in_rhss rhs_eob_info
235 maybe_cc_slot bindings
238 ; setEndOfBlockInfo rhs_eob_info (cgExpr body) }
242 %********************************************************
246 %********************************************************
248 SCC expressions are treated specially. They set the current cost
252 cgExpr (StgSCC cc expr) = do emitSetCCC cc; cgExpr expr
255 %********************************************************
259 %********************************************************
262 cgExpr (StgTick m n expr) = do cgTickBox m n; cgExpr expr
265 %********************************************************
267 %* Non-top-level bindings *
269 %********************************************************
270 \subsection[non-top-level-bindings]{Converting non-top-level bindings}
272 We rely on the support code in @CgCon@ (to do constructors) and
273 in @CgClosure@ (to do closures).
276 cgRhs :: Id -> StgRhs -> FCode (Id, CgIdInfo)
277 -- the Id is passed along so a binding can be set up
279 cgRhs name (StgRhsCon maybe_cc con args)
280 = do { amodes <- getArgAmodes args
281 ; idinfo <- buildDynCon name maybe_cc con amodes
282 ; returnFC (name, idinfo) }
284 cgRhs name (StgRhsClosure cc bi fvs upd_flag srt args body)
285 = do this_pkg <- getThisPackage
286 mkRhsClosure this_pkg name cc bi srt fvs upd_flag args body
289 mkRhsClosure looks for two special forms of the right-hand side:
293 If neither happens, it just calls mkClosureLFInfo. You might think
294 that mkClosureLFInfo should do all this, but it seems wrong for the
295 latter to look at the structure of an expression
299 We look at the body of the closure to see if it's a selector---turgid,
300 but nothing deep. We are looking for a closure of {\em exactly} the
303 ... = [the_fv] \ u [] ->
305 con a_1 ... a_n -> a_i
309 mkRhsClosure this_pkg bndr cc bi srt
310 [the_fv] -- Just one free var
311 upd_flag -- Updatable thunk
313 body@(StgCase (StgApp scrutinee [{-no args-}])
314 _ _ _ _ -- ignore uniq, etc.
316 [(DataAlt con, params, use_mask,
317 (StgApp selectee [{-no args-}]))])
318 | the_fv == scrutinee -- Scrutinee is the only free variable
319 && maybeToBool maybe_offset -- Selectee is a component of the tuple
320 && offset_into_int <= mAX_SPEC_SELECTEE_SIZE -- Offset is small enough
321 = -- NOT TRUE: ASSERT(is_single_constructor)
322 -- The simplifier may have statically determined that the single alternative
323 -- is the only possible case and eliminated the others, even if there are
324 -- other constructors in the datatype. It's still ok to make a selector
325 -- thunk in this case, because we *know* which constructor the scrutinee
327 cgStdRhsClosure bndr cc bi [the_fv] [] body lf_info [StgVarArg the_fv]
329 lf_info = mkSelectorLFInfo bndr offset_into_int
330 (isUpdatable upd_flag)
331 (_, params_w_offsets) = layOutDynConstr this_pkg con (addIdReps params)
332 -- Just want the layout
333 maybe_offset = assocMaybe params_w_offsets selectee
334 Just the_offset = maybe_offset
335 offset_into_int = the_offset - fixedHdrSize
341 A more generic AP thunk of the form
343 x = [ x_1...x_n ] \.. [] -> x_1 ... x_n
345 A set of these is compiled statically into the RTS, so we just use
346 those. We could extend the idea to thunks where some of the x_i are
347 global ids (and hence not free variables), but this would entail
348 generating a larger thunk. It might be an option for non-optimising
351 We only generate an Ap thunk if all the free variables are pointers,
352 for semi-obvious reasons.
355 mkRhsClosure this_pkg bndr cc bi srt
358 [] -- No args; a thunk
359 body@(StgApp fun_id args)
361 | args `lengthIs` (arity-1)
362 && all isFollowableArg (map idCgRep fvs)
363 && isUpdatable upd_flag
364 && arity <= mAX_SPEC_AP_SIZE
367 = cgStdRhsClosure bndr cc bi fvs [] body lf_info payload
370 lf_info = mkApLFInfo bndr upd_flag arity
371 -- the payload has to be in the correct order, hence we can't
373 payload = StgVarArg fun_id : args
380 mkRhsClosure this_pkg bndr cc bi srt fvs upd_flag args body
381 = cgRhsClosure bndr cc bi srt fvs upd_flag args body
385 %********************************************************
387 %* Let-no-escape bindings
389 %********************************************************
391 cgLetNoEscapeBindings live_in_rhss rhs_eob_info maybe_cc_slot
392 (StgNonRec binder rhs)
393 = do { (binder,info) <- cgLetNoEscapeRhs live_in_rhss rhs_eob_info
395 NonRecursive binder rhs
396 ; addBindC binder info }
398 cgLetNoEscapeBindings live_in_rhss rhs_eob_info maybe_cc_slot (StgRec pairs)
399 = do { new_bindings <- fixC (\ new_bindings -> do
400 { addBindsC new_bindings
401 ; listFCs [ cgLetNoEscapeRhs full_live_in_rhss
402 rhs_eob_info maybe_cc_slot Recursive b e
403 | (b,e) <- pairs ] })
405 ; addBindsC new_bindings }
407 -- We add the binders to the live-in-rhss set so that we don't
408 -- delete the bindings for the binder from the environment!
409 full_live_in_rhss = live_in_rhss `unionVarSet` (mkVarSet [b | (b,r) <- pairs])
412 :: StgLiveVars -- Live in rhss
414 -> Maybe VirtualSpOffset
418 -> FCode (Id, CgIdInfo)
420 cgLetNoEscapeRhs full_live_in_rhss rhs_eob_info maybe_cc_slot rec binder
421 (StgRhsClosure cc bi _ upd_flag srt args body)
422 = -- We could check the update flag, but currently we don't switch it off
423 -- for let-no-escaped things, so we omit the check too!
425 -- Updatable -> panic "cgLetNoEscapeRhs" -- Nothing to update!
426 -- other -> cgLetNoEscapeClosure binder cc bi live_in_whole_let live_in_rhss args body
427 cgLetNoEscapeClosure binder cc bi srt full_live_in_rhss rhs_eob_info
428 maybe_cc_slot rec args body
430 -- For a constructor RHS we want to generate a single chunk of code which
431 -- can be jumped to from many places, which will return the constructor.
432 -- It's easy; just behave as if it was an StgRhsClosure with a ConApp inside!
433 cgLetNoEscapeRhs full_live_in_rhss rhs_eob_info maybe_cc_slot rec binder
434 (StgRhsCon cc con args)
435 = cgLetNoEscapeClosure binder cc noBinderInfo{-safe-} NoSRT
436 full_live_in_rhss rhs_eob_info maybe_cc_slot rec
437 [] --No args; the binder is data structure, not a function
441 Little helper for primitives that return unboxed tuples.
444 newUnboxedTupleRegs :: Type -> FCode ([CgRep], [CmmReg], [MachHint])
445 newUnboxedTupleRegs res_ty =
447 ty_args = tyConAppArgs (repType res_ty)
448 (reps,hints) = unzip [ (rep, typeHint ty) | ty <- ty_args,
449 let rep = typeCgRep ty,
452 regs <- mapM (newTemp . argMachRep) reps
453 return (reps,regs,hints)