2 % (c) The GRASP/AQUA Project, Glasgow University, 1992-1998
4 % $Id: CgMonad.lhs,v 1.20 1999/05/18 15:03:49 simonpj Exp $
6 \section[CgMonad]{The code generation monad}
8 See the beginning of the top-level @CodeGen@ module, to see how this
9 monadic stuff fits into the Big Picture.
16 initC, thenC, thenFC, listCs, listFCs, mapCs, mapFCs,
17 returnFC, fixC, absC, nopC, getAbsC,
19 forkClosureBody, forkStatics, forkAlts, forkEval,
20 forkEvalHelp, forkAbsC,
23 addBindC, addBindsC, modifyBindC, lookupBindC,
26 setEndOfBlockInfo, getEndOfBlockInfo,
28 setSRTLabel, getSRTLabel,
30 StackUsage, HeapUsage,
34 costCentresC, moduleName,
36 Sequel(..), -- ToDo: unabstract?
39 -- out of general friendliness, we also export ...
40 CgInfoDownwards(..), CgState(..), -- non-abstract
44 #include "HsVersions.h"
46 import {-# SOURCE #-} CgBindery ( CgIdInfo(..), CgBindings, maybeStkLoc, nukeVolatileBinds )
47 import {-# SOURCE #-} CgUsages ( getSpRelOffset )
50 import AbsCUtils ( mkAbsCStmts )
51 import CmdLineOpts ( opt_SccProfilingOn, opt_DoTickyProfiling )
52 import CLabel ( CLabel, mkUpdInfoLabel, pprCLabel )
53 import Module ( Module )
54 import DataCon ( ConTag )
57 import PrimRep ( PrimRep(..) )
58 import StgSyn ( StgLiveVars )
61 infixr 9 `thenC` -- Right-associative!
65 %************************************************************************
67 \subsection[CgMonad-environment]{Stuff for manipulating environments}
69 %************************************************************************
71 This monadery has some information that it only passes {\em
72 downwards}, as well as some ``state'' which is modified as we go
76 data CgInfoDownwards -- information only passed *downwards* by the monad
78 CompilationInfo -- COMPLETELY STATIC info about this compilation
79 -- (e.g., what flags were passed to the compiler)
81 CgBindings -- [Id -> info] : static environment
83 CLabel -- label of the current SRT
85 EndOfBlockInfo -- Info for stuff to do at end of basic block:
90 Module -- the module name
94 AbstractC -- code accumulated so far
95 CgBindings -- [Id -> info] : *local* bindings environment
96 -- Bindings for top-level things are given in the info-down part
100 @EndOfBlockInfo@ tells what to do at the end of this block of code or,
101 if the expression is a @case@, what to do at the end of each
107 VirtualSpOffset -- Args Sp: trim the stack to this point at a
108 -- return; push arguments starting just
109 -- above this point on a tail call.
111 -- This is therefore the stk ptr as seen
112 -- by a case alternative.
115 initEobInfo = EndOfBlockInfo 0 (OnStack 0)
118 Any addressing modes inside @Sequel@ must be ``robust,'' in the sense
119 that it must survive stack pointer adjustments at the end of the
125 VirtualSpOffset -- Continuation is on the stack, at the
126 -- specified location
131 CAddrMode -- Jump to this; if the continuation is for a vectored
132 -- case this might be the label of a return
133 -- vector Guaranteed to be a non-volatile
134 -- addressing mode (I think)
137 | SeqFrame -- like CaseAlts but push a seq frame too.
141 type SemiTaggingStuff
142 = Maybe -- Maybe[1] we don't have any semi-tagging stuff...
143 ([(ConTag, JoinDetails)], -- Alternatives
144 Maybe (Maybe Id, JoinDetails) -- Default (but Maybe[2] we don't have one)
145 -- Maybe[3] the default is a
146 -- bind-default (Just b); that is,
147 -- it expects a ptr to the thing
148 -- in Node, bound to b
152 = (AbstractC, CLabel) -- Code to load regs from heap object + profiling macros,
153 -- and join point label
155 -- The abstract C is executed only from a successful semitagging
156 -- venture, when a case has looked at a variable, found that it's
157 -- evaluated, and wants to load up the contents and go to the join
161 -- The OnStack case of sequelToAmode delivers an Amode which is only
162 -- valid just before the final control transfer, because it assumes
163 -- that Sp is pointing to the top word of the return address. This
164 -- seems unclean but there you go.
166 -- sequelToAmode returns an amode which refers to an info table. The info
167 -- table will always be of the RET(_VEC)?_(BIG|SMALL) kind. We're careful
168 -- not to handle real code pointers, just in case we're compiling for
169 -- an unregisterised/untailcallish architecture, where info pointers and
170 -- code pointers aren't the same.
172 sequelToAmode :: Sequel -> FCode CAddrMode
174 sequelToAmode (OnStack virt_sp_offset)
175 = getSpRelOffset virt_sp_offset `thenFC` \ sp_rel ->
176 returnFC (CVal sp_rel RetRep)
178 sequelToAmode UpdateCode = returnFC (CLbl mkUpdInfoLabel RetRep)
179 sequelToAmode (CaseAlts amode _) = returnFC amode
180 sequelToAmode (SeqFrame _ _) = cgPanic (text "sequelToAmode: SeqFrame")
182 type CgStksAndHeapUsage -- stacks and heap usage information
183 = (StackUsage, HeapUsage)
186 (Int, -- virtSp: Virtual offset of topmost allocated slot
187 [Int], -- free: List of free slots, in increasing order
188 Int, -- realSp: Virtual offset of real stack pointer
189 Int) -- hwSp: Highest value ever taken by virtSp
192 (HeapOffset, -- virtHp: Virtual offset of highest-allocated word
193 HeapOffset) -- realHp: Virtual offset of real heap ptr
196 NB: absolutely every one of the above Ints is really
197 a VirtualOffset of some description (the code generator
198 works entirely in terms of VirtualOffsets).
203 initialStateC = MkCgState AbsCNop emptyVarEnv initUsage
205 initUsage :: CgStksAndHeapUsage
206 initUsage = ((0,[],0,0), (initVirtHp, initRealHp))
207 initVirtHp = panic "Uninitialised virtual Hp"
208 initRealHp = panic "Uninitialised real Hp"
211 "envInitForAlternatives" initialises the environment for a case alternative,
212 assuming that the alternative is entered after an evaluation.
215 - zapping any volatile bindings, which aren't valid.
217 - zapping the heap usage. It should be restored by a heap check.
219 - setting the virtual AND real stack pointer fields to the given
220 virtual stack offsets. this doesn't represent any {\em code}; it is a
221 prediction of where the real stack pointer will be when we come back
222 from the case analysis.
224 - BUT LEAVING the rest of the stack-usage info because it is all
225 valid. In particular, we leave the tail stack pointers unchanged,
226 becuase the alternative has to de-allocate the original @case@
227 expression's stack. \end{itemize}
229 @stateIncUsage@$~e_1~e_2$ incorporates in $e_1$ the stack and heap high water
230 marks found in $e_2$.
233 stateIncUsage :: CgState -> CgState -> CgState
235 stateIncUsage (MkCgState abs_c bs ((v,f,r,h1),(vH1,rH1)))
236 (MkCgState _ _ ((_,_,_,h2),(vH2, _)))
239 ((v,f,r,h1 `max` h2),
240 (vH1 `max` vH2, rH1))
243 %************************************************************************
245 \subsection[CgMonad-basics]{Basic code-generation monad magic}
247 %************************************************************************
250 type FCode a = CgInfoDownwards -> CgState -> (a, CgState)
251 type Code = CgInfoDownwards -> CgState -> CgState
254 {-# INLINE thenFC #-}
255 {-# INLINE returnFC #-}
257 The Abstract~C is not in the environment so as to improve strictness.
260 initC :: CompilationInfo -> Code -> AbstractC
263 = case (code (MkCgInfoDown
265 (error "initC: statics")
269 MkCgState abc _ _ -> abc
271 returnFC :: a -> FCode a
273 returnFC val info_down state = (val, state)
278 -> (CgInfoDownwards -> CgState -> a)
279 -> CgInfoDownwards -> CgState -> a
281 -- thenC has both of the following types:
282 -- thenC :: Code -> Code -> Code
283 -- thenC :: Code -> FCode a -> FCode a
285 thenC m k info_down state
286 = k info_down new_state
288 new_state = m info_down state
290 listCs :: [Code] -> Code
292 listCs [] info_down state = state
293 listCs (c:cs) info_down state = stateN
295 state1 = c info_down state
296 stateN = listCs cs info_down state1
298 mapCs :: (a -> Code) -> [a] -> Code
300 mapCs f [] info_down state = state
301 mapCs f (c:cs) info_down state = stateN
303 state1 = (f c) info_down state
304 stateN = mapCs f cs info_down state1
309 -> (a -> CgInfoDownwards -> CgState -> c)
310 -> CgInfoDownwards -> CgState -> c
312 -- thenFC :: FCode a -> (a -> FCode b) -> FCode b
313 -- thenFC :: FCode a -> (a -> Code) -> Code
315 thenFC m k info_down state
316 = k m_result info_down new_state
318 (m_result, new_state) = m info_down state
320 listFCs :: [FCode a] -> FCode [a]
322 listFCs [] info_down state = ([], state)
323 listFCs (fc:fcs) info_down state = (thing : things, stateN)
325 (thing, state1) = fc info_down state
326 (things, stateN) = listFCs fcs info_down state1
328 mapFCs :: (a -> FCode b) -> [a] -> FCode [b]
330 mapFCs f [] info_down state = ([], state)
331 mapFCs f (fc:fcs) info_down state = (thing : things, stateN)
333 (thing, state1) = (f fc) info_down state
334 (things, stateN) = mapFCs f fcs info_down state1
337 And the knot-tying combinator:
339 fixC :: (a -> FCode a) -> FCode a
340 fixC fcode info_down state = result
342 result@(v, _) = fcode v info_down state
346 @forkClosureBody@ takes a code, $c$, and compiles it in a completely
347 fresh environment, except that:
348 - compilation info and statics are passed in unchanged.
349 The current environment is passed on completely unaltered, except that
350 abstract C from the fork is incorporated.
352 @forkAbsC@ takes a code and compiles it in the current environment,
353 returning the abstract C thus constructed. The current environment
354 is passed on completely unchanged. It is pretty similar to @getAbsC@,
355 except that the latter does affect the environment. ToDo: combine?
357 @forkStatics@ $fc$ compiles $fc$ in an environment whose statics come
358 from the current bindings, but which is otherwise freshly initialised.
359 The Abstract~C returned is attached to the current state, but the
360 bindings and usage information is otherwise unchanged.
363 forkClosureBody :: Code -> Code
366 (MkCgInfoDown cg_info statics srt _)
367 (MkCgState absC_in binds un_usage)
368 = MkCgState (AbsCStmts absC_in absC_fork) binds un_usage
370 fork_state = code body_info_down initialStateC
371 MkCgState absC_fork _ _ = fork_state
372 body_info_down = MkCgInfoDown cg_info statics srt initEobInfo
374 forkStatics :: FCode a -> FCode a
376 forkStatics fcode (MkCgInfoDown cg_info _ srt _)
377 (MkCgState absC_in statics un_usage)
378 = (result, MkCgState (AbsCStmts absC_in absC_fork) statics un_usage)
380 (result, state) = fcode rhs_info_down initialStateC
381 MkCgState absC_fork _ _ = state -- Don't merge these this line with the one
382 -- above or it becomes too strict!
383 rhs_info_down = MkCgInfoDown cg_info statics srt initEobInfo
385 forkAbsC :: Code -> FCode AbstractC
386 forkAbsC code info_down (MkCgState absC1 bs usage)
389 MkCgState absC2 _ ((_, _, _,h2), _) =
390 code info_down (MkCgState AbsCNop bs usage)
391 ((v, f, r, h1), heap_usage) = usage
393 new_usage = ((v, f, r, h1 `max` h2), heap_usage)
394 new_state = MkCgState absC1 bs new_usage
397 @forkAlts@ $bs~d$ takes fcodes $bs$ for the branches of a @case@, and
398 an fcode for the default case $d$, and compiles each in the current
399 environment. The current environment is passed on unmodified, except
401 - the worst stack high-water mark is incorporated
402 - the virtual Hp is moved on to the worst virtual Hp for the branches
405 forkAlts :: [FCode a] -> FCode b -> FCode ([a],b)
407 forkAlts branch_fcodes deflt_fcode info_down in_state
408 = ((branch_results , deflt_result), out_state)
410 compile fc = fc info_down in_state
412 (branch_results, branch_out_states) = unzip (map compile branch_fcodes)
414 (deflt_result, deflt_out_state) = deflt_fcode info_down in_state
416 out_state = foldl stateIncUsage in_state (deflt_out_state:branch_out_states)
417 -- NB foldl. in_state is the *left* argument to stateIncUsage
420 @forkEval@ takes two blocks of code.
422 - The first meddles with the environment to set it up as expected by
423 the alternatives of a @case@ which does an eval (or gc-possible primop).
424 - The second block is the code for the alternatives.
425 (plus info for semi-tagging purposes)
427 @forkEval@ picks up the virtual stack pointer and returns a suitable
428 @EndOfBlockInfo@ for the caller to use, together with whatever value
429 is returned by the second block.
431 It uses @initEnvForAlternatives@ to initialise the environment, and
432 @stateIncUsageAlt@ to incorporate usage; the latter ignores the heap
436 forkEval :: EndOfBlockInfo -- For the body
437 -> Code -- Code to set environment
438 -> FCode Sequel -- Semi-tagging info to store
439 -> FCode EndOfBlockInfo -- The new end of block info
441 forkEval body_eob_info env_code body_code
442 = forkEvalHelp body_eob_info env_code body_code `thenFC` \ (v, sequel) ->
443 returnFC (EndOfBlockInfo v sequel)
445 forkEvalHelp :: EndOfBlockInfo -- For the body
446 -> Code -- Code to set environment
447 -> FCode a -- The code to do after the eval
449 a) -- Result of the FCode
451 forkEvalHelp body_eob_info env_code body_code
452 info_down@(MkCgInfoDown cg_info statics srt _) state
453 = ((v,value_returned), state `stateIncUsageEval` state_at_end_return)
455 info_down_for_body = MkCgInfoDown cg_info statics srt body_eob_info
457 (MkCgState _ binds ((v,f,_,_), _)) = env_code info_down_for_body state
458 -- These v and f things are now set up as the body code expects them
460 (value_returned, state_at_end_return)
461 = body_code info_down_for_body state_for_body
463 state_for_body = MkCgState AbsCNop
464 (nukeVolatileBinds binds)
466 (initVirtHp, initRealHp))
469 stateIncUsageEval :: CgState -> CgState -> CgState
470 stateIncUsageEval (MkCgState absC1 bs ((v,f,r,h1),heap_usage))
471 (MkCgState absC2 _ ((_,_,_,h2), _))
472 = MkCgState (absC1 `AbsCStmts` absC2)
473 -- The AbsC coming back should consist only of nested declarations,
474 -- notably of the return vector!
476 ((v,f,r,h1 `max` h2), heap_usage)
477 -- We don't max the heap high-watermark because stateIncUsageEval is
478 -- used only in forkEval, which in turn is only used for blocks of code
479 -- which do their own heap-check.
482 %************************************************************************
484 \subsection[CgMonad-spitting-AbstractC]{Spitting out @AbstractC@}
486 %************************************************************************
488 @nopC@ is the no-op for the @Code@ monad; it adds no Abstract~C to the
489 environment; @absC@ glues @ab_C@ onto the Abstract~C collected so far.
492 nopC info_down state = state
494 absC :: AbstractC -> Code
495 absC more_absC info_down state@(MkCgState absC binds usage)
496 = MkCgState (mkAbsCStmts absC more_absC) binds usage
499 These two are just like @absC@, except they examine the compilation
500 info (whether SCC profiling or profiling-ctrs going) and possibly emit
504 costCentresC :: FAST_STRING -> [CAddrMode] -> Code
506 costCentresC macro args _ state@(MkCgState absC binds usage)
507 = if opt_SccProfilingOn
508 then MkCgState (mkAbsCStmts absC (CCallProfCCMacro macro args)) binds usage
511 profCtrC :: FAST_STRING -> [CAddrMode] -> Code
513 profCtrC macro args _ state@(MkCgState absC binds usage)
514 = if not opt_DoTickyProfiling
516 else MkCgState (mkAbsCStmts absC (CCallProfCtrMacro macro args)) binds usage
518 {- Try to avoid adding too many special compilation strategies here.
519 It's better to modify the header files as necessary for particular
520 targets, so that we can get away with as few variants of .hc files
525 @getAbsC@ compiles the code in the current environment, and returns
526 the abstract C thus constructed (leaving the abstract C being carried
527 around in the state untouched). @getAbsC@ does not generate any
528 in-line Abstract~C itself, but the environment it returns is that
529 obtained from the compilation.
532 getAbsC :: Code -> FCode AbstractC
534 getAbsC code info_down (MkCgState absC binds usage)
535 = (absC2, MkCgState absC binds2 usage2)
537 (MkCgState absC2 binds2 usage2)
538 = code info_down (MkCgState AbsCNop binds usage)
543 moduleName :: FCode Module
544 moduleName (MkCgInfoDown (MkCompInfo mod_name) _ _ _) state
550 setEndOfBlockInfo :: EndOfBlockInfo -> Code -> Code
551 setEndOfBlockInfo eob_info code (MkCgInfoDown c_info statics srt _) state
552 = code (MkCgInfoDown c_info statics srt eob_info) state
554 getEndOfBlockInfo :: FCode EndOfBlockInfo
555 getEndOfBlockInfo (MkCgInfoDown c_info statics _ eob_info) state
560 getSRTLabel :: FCode CLabel
561 getSRTLabel (MkCgInfoDown _ _ srt _) state
564 setSRTLabel :: CLabel -> Code -> Code
565 setSRTLabel srt code (MkCgInfoDown c_info statics _ eob_info) state
566 = code (MkCgInfoDown c_info statics srt eob_info) state
569 %************************************************************************
571 \subsection[CgMonad-bindery]{Monad things for fiddling with @CgBindings@}
573 %************************************************************************
575 There are three basic routines, for adding (@addBindC@), modifying
576 (@modifyBindC@) and looking up (@lookupBindC@) bindings.
578 A @Id@ is bound to a @(VolatileLoc, StableLoc)@ triple.
579 The name should not already be bound. (nice ASSERT, eh?)
582 addBindC :: Id -> CgIdInfo -> Code
583 addBindC name stuff_to_bind info_down (MkCgState absC binds usage)
584 = MkCgState absC (extendVarEnv binds name stuff_to_bind) usage
586 addBindsC :: [(Id, CgIdInfo)] -> Code
587 addBindsC new_bindings info_down (MkCgState absC binds usage)
588 = MkCgState absC new_binds usage
590 new_binds = foldl (\ binds (name,info) -> extendVarEnv binds name info)
594 modifyBindC :: Id -> (CgIdInfo -> CgIdInfo) -> Code
595 modifyBindC name mangle_fn info_down (MkCgState absC binds usage)
596 = MkCgState absC (modifyVarEnv mangle_fn binds name) usage
598 lookupBindC :: Id -> FCode CgIdInfo
599 lookupBindC name info_down@(MkCgInfoDown _ static_binds srt _)
600 state@(MkCgState absC local_binds usage)
603 val = case (lookupVarEnv local_binds name) of
604 Nothing -> try_static
608 case (lookupVarEnv static_binds name) of
611 -> cgPanic (text "lookupBindC: no info for" <+> ppr name) info_down state
613 cgPanic :: SDoc -> CgInfoDownwards -> CgState -> a
614 cgPanic doc info_down@(MkCgInfoDown _ static_binds srt _)
615 state@(MkCgState absC local_binds usage)
618 ptext SLIT("static binds for:"),
619 vcat [ ppr i | (MkCgIdInfo i _ _ _) <- rngVarEnv static_binds ],
620 ptext SLIT("local binds for:"),
621 vcat [ ppr i | (MkCgIdInfo i _ _ _) <- rngVarEnv local_binds ],
622 ptext SLIT("SRT label") <+> pprCLabel srt