2 % (c) The GRASP/AQUA Project, Glasgow University, 1992-1998
4 % $Id: CgMonad.lhs,v 1.37 2003/01/07 14:31:20 simonmar 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,
24 setEndOfBlockInfo, getEndOfBlockInfo,
26 setSRTLabel, getSRTLabel, getSRTInfo,
27 setTickyCtrLabel, getTickyCtrLabel,
29 StackUsage, Slot(..), HeapUsage,
31 profCtrC, profCtrAbsC, ldvEnter,
33 costCentresC, moduleName,
35 Sequel(..), -- ToDo: unabstract?
38 -- ideally we wouldn't export these, but some other modules access internal state
39 getState, setState, getInfoDown,
41 -- more localised access to monad state
43 getBinds, setBinds, getStaticBinds,
45 -- out of general friendliness, we also export ...
46 CgInfoDownwards(..), CgState(..), -- non-abstract
50 #include "HsVersions.h"
52 import {-# SOURCE #-} CgBindery ( CgBindings, nukeVolatileBinds )
53 import {-# SOURCE #-} CgUsages ( getSpRelOffset )
57 import StgSyn ( SRT(..) )
58 import AbsCUtils ( mkAbsCStmts )
59 import CmdLineOpts ( opt_SccProfilingOn, opt_DoTickyProfiling )
60 import Module ( Module )
61 import DataCon ( ConTag )
64 import PrimRep ( PrimRep(..) )
68 infixr 9 `thenC` -- Right-associative!
72 %************************************************************************
74 \subsection[CgMonad-environment]{Stuff for manipulating environments}
76 %************************************************************************
78 This monadery has some information that it only passes {\em
79 downwards}, as well as some ``state'' which is modified as we go
83 data CgInfoDownwards -- information only passed *downwards* by the monad
85 CompilationInfo -- COMPLETELY STATIC info about this compilation
86 -- (e.g., what flags were passed to the compiler)
88 CgBindings -- [Id -> info] : static environment
90 CLabel -- label of the current SRT
92 CLabel -- current destination for ticky counts
94 EndOfBlockInfo -- Info for stuff to do at end of basic block:
99 Module -- the module name
103 AbstractC -- code accumulated so far
104 CgBindings -- [Id -> info] : *local* bindings environment
105 -- Bindings for top-level things are given in the info-down part
109 @EndOfBlockInfo@ tells what to do at the end of this block of code or,
110 if the expression is a @case@, what to do at the end of each
116 VirtualSpOffset -- Args Sp: trim the stack to this point at a
117 -- return; push arguments starting just
118 -- above this point on a tail call.
120 -- This is therefore the stk ptr as seen
121 -- by a case alternative.
124 initEobInfo = EndOfBlockInfo 0 (OnStack 0)
127 Any addressing modes inside @Sequel@ must be ``robust,'' in the sense
128 that it must survive stack pointer adjustments at the end of the
134 VirtualSpOffset -- Continuation is on the stack, at the
135 -- specified location
140 CAddrMode -- Jump to this; if the continuation is for a vectored
141 -- case this might be the label of a return
142 -- vector Guaranteed to be a non-volatile
143 -- addressing mode (I think)
146 Bool -- True <=> polymorphic, push a SEQ frame too
149 type SemiTaggingStuff
150 = Maybe -- Maybe[1] we don't have any semi-tagging stuff...
151 ([(ConTag, JoinDetails)], -- Alternatives
152 Maybe (Maybe Id, JoinDetails) -- Default (but Maybe[2] we don't have one)
153 -- Maybe[3] the default is a
154 -- bind-default (Just b); that is,
155 -- it expects a ptr to the thing
156 -- in Node, bound to b
160 = (AbstractC, CLabel) -- Code to load regs from heap object + profiling macros,
161 -- and join point label
163 -- The abstract C is executed only from a successful semitagging
164 -- venture, when a case has looked at a variable, found that it's
165 -- evaluated, and wants to load up the contents and go to the join
169 -- The OnStack case of sequelToAmode delivers an Amode which is only
170 -- valid just before the final control transfer, because it assumes
171 -- that Sp is pointing to the top word of the return address. This
172 -- seems unclean but there you go.
174 -- sequelToAmode returns an amode which refers to an info table. The info
175 -- table will always be of the RET(_VEC)?_(BIG|SMALL) kind. We're careful
176 -- not to handle real code pointers, just in case we're compiling for
177 -- an unregisterised/untailcallish architecture, where info pointers and
178 -- code pointers aren't the same.
180 sequelToAmode :: Sequel -> FCode CAddrMode
182 sequelToAmode (OnStack virt_sp_offset)
183 = getSpRelOffset virt_sp_offset `thenFC` \ sp_rel ->
184 returnFC (CVal sp_rel RetRep)
186 sequelToAmode UpdateCode = returnFC (CLbl mkUpdInfoLabel RetRep)
188 sequelToAmode (CaseAlts amode _ False) = returnFC amode
189 sequelToAmode (CaseAlts amode _ True) = returnFC (CLbl mkSeqInfoLabel RetRep)
191 type CgStksAndHeapUsage -- stacks and heap usage information
192 = (StackUsage, HeapUsage)
194 data Slot = Free | NonPointer
203 (Int, -- virtSp: Virtual offset of topmost allocated slot
204 Int, -- frameSp: End of the current stack frame
205 [(Int,Slot)], -- free: List of free slots, in increasing order
206 Int, -- realSp: Virtual offset of real stack pointer
207 Int) -- hwSp: Highest value ever taken by virtSp
209 -- ToDo (SDM, 7 Jan 2003): I'm not sure that the distinction between
210 -- Free and NonPointer in the free list is needed any more. It used
211 -- to be needed because we constructed bitmaps from the free list, but
212 -- now we construct bitmaps by finding all the live pointer bindings
213 -- instead. Non-pointer stack slots (i.e. saved cost centres) can
214 -- just be removed from the free list instead of being recorded as a
218 (HeapOffset, -- virtHp: Virtual offset of highest-allocated word
219 HeapOffset) -- realHp: Virtual offset of real heap ptr
222 NB: absolutely every one of the above Ints is really
223 a VirtualOffset of some description (the code generator
224 works entirely in terms of VirtualOffsets).
229 initialStateC = MkCgState AbsCNop emptyVarEnv initUsage
231 initUsage :: CgStksAndHeapUsage
232 initUsage = ((0,0,[],0,0), (0,0))
235 @stateIncUsage@$~e_1~e_2$ incorporates in $e_1$ the stack and heap high water
236 marks found in $e_2$.
239 stateIncUsage :: CgState -> CgState -> CgState
241 stateIncUsage (MkCgState abs_c bs ((v,t,f,r,h1),(vH1,rH1)))
242 (MkCgState _ _ ((_,_,_,_,h2),(vH2, _)))
245 ((v,t,f,r,h1 `max` h2),
246 (vH1 `max` vH2, rH1))
249 %************************************************************************
251 \subsection[CgMonad-basics]{Basic code-generation monad magic}
253 %************************************************************************
256 newtype FCode a = FCode (CgInfoDownwards -> CgState -> (a, CgState))
259 instance Monad FCode where
264 {-# INLINE thenFC #-}
265 {-# INLINE returnFC #-}
267 The Abstract~C is not in the environment so as to improve strictness.
270 initC :: CompilationInfo -> Code -> AbstractC
272 initC cg_info (FCode code)
273 = case (code (MkCgInfoDown
275 emptyVarEnv -- (error "initC: statics")
280 ((),MkCgState abc _ _) -> abc
282 returnFC :: a -> FCode a
283 returnFC val = FCode (\info_down state -> (val, state))
287 thenC :: Code -> FCode a -> FCode a
288 thenC (FCode m) (FCode k) =
289 FCode (\info_down state -> let (_,new_state) = m info_down state in
290 k info_down new_state)
292 listCs :: [Code] -> Code
293 listCs [] = return ()
298 mapCs :: (a -> Code) -> [a] -> Code
303 thenFC :: FCode a -> (a -> FCode c) -> FCode c
304 thenFC (FCode m) k = FCode (
307 (m_result, new_state) = m info_down state
308 (FCode kcode) = k m_result
310 kcode info_down new_state
313 listFCs :: [FCode a] -> FCode [a]
316 mapFCs :: (a -> FCode b) -> [a] -> FCode [b]
320 And the knot-tying combinator:
322 fixC :: (a -> FCode a) -> FCode a
327 result@(v,_) = fc info_down state
334 Operators for getting and setting the state and "info_down".
335 To maximise encapsulation, code should try to only get and set the
336 state it actually uses.
339 getState :: FCode CgState
340 getState = FCode $ \info_down state -> (state,state)
342 setState :: CgState -> FCode ()
343 setState state = FCode $ \info_down _ -> ((),state)
345 getUsage :: FCode CgStksAndHeapUsage
347 MkCgState absC binds usage <- getState
350 setUsage :: CgStksAndHeapUsage -> FCode ()
351 setUsage newusage = do
352 MkCgState absC binds usage <- getState
353 setState $ MkCgState absC binds newusage
355 getBinds :: FCode CgBindings
357 MkCgState absC binds usage <- getState
360 setBinds :: CgBindings -> FCode ()
361 setBinds newbinds = do
362 MkCgState absC binds usage <- getState
363 setState $ MkCgState absC newbinds usage
365 getStaticBinds :: FCode CgBindings
367 (MkCgInfoDown _ static_binds _ _ _) <- getInfoDown
370 withState :: FCode a -> CgState -> FCode (a,CgState)
371 withState (FCode fcode) newstate = FCode $ \info_down state ->
372 let (retval, state2) = fcode info_down newstate in ((retval,state2), state)
374 getInfoDown :: FCode CgInfoDownwards
375 getInfoDown = FCode $ \info_down state -> (info_down,state)
377 withInfoDown :: FCode a -> CgInfoDownwards -> FCode a
378 withInfoDown (FCode fcode) info_down = FCode $ \_ state -> fcode info_down state
380 doFCode :: FCode a -> CgInfoDownwards -> CgState -> (a,CgState)
381 doFCode (FCode fcode) info_down state = fcode info_down state
385 @forkClosureBody@ takes a code, $c$, and compiles it in a completely
386 fresh environment, except that:
387 - compilation info and statics are passed in unchanged.
388 The current environment is passed on completely unaltered, except that
389 abstract C from the fork is incorporated.
391 @forkAbsC@ takes a code and compiles it in the current environment,
392 returning the abstract C thus constructed. The current environment
393 is passed on completely unchanged. It is pretty similar to @getAbsC@,
394 except that the latter does affect the environment. ToDo: combine?
396 @forkStatics@ $fc$ compiles $fc$ in an environment whose statics come
397 from the current bindings, but which is otherwise freshly initialised.
398 The Abstract~C returned is attached to the current state, but the
399 bindings and usage information is otherwise unchanged.
402 forkClosureBody :: Code -> Code
404 forkClosureBody (FCode code) = do
405 (MkCgInfoDown cg_info statics srt ticky _) <- getInfoDown
406 (MkCgState absC_in binds un_usage) <- getState
407 let body_info_down = MkCgInfoDown cg_info statics srt ticky initEobInfo
408 let ((),fork_state) = code body_info_down initialStateC
409 let MkCgState absC_fork _ _ = fork_state
410 setState $ MkCgState (AbsCStmts absC_in absC_fork) binds un_usage
412 forkStatics :: FCode a -> FCode a
414 forkStatics (FCode fcode) = FCode (
415 \(MkCgInfoDown cg_info _ srt ticky _)
416 (MkCgState absC_in statics un_usage)
419 (result, state) = fcode rhs_info_down initialStateC
420 MkCgState absC_fork _ _ = state -- Don't merge these this line with the one
421 -- above or it becomes too strict!
422 rhs_info_down = MkCgInfoDown cg_info statics srt ticky initEobInfo
424 (result, MkCgState (AbsCStmts absC_in absC_fork) statics un_usage)
427 forkAbsC :: Code -> FCode AbstractC
428 forkAbsC (FCode code) =
430 info_down <- getInfoDown
431 (MkCgState absC1 bs usage) <- getState
432 let ((),MkCgState absC2 _ ((_, _, _, _,h2), _)) = code info_down (MkCgState AbsCNop bs usage)
433 let ((v, t, f, r, h1), heap_usage) = usage
434 let new_usage = ((v, t, f, r, h1 `max` h2), heap_usage)
435 setState $ MkCgState absC1 bs new_usage
439 @forkAlts@ $bs~d$ takes fcodes $bs$ for the branches of a @case@, and
440 an fcode for the default case $d$, and compiles each in the current
441 environment. The current environment is passed on unmodified, except
443 - the worst stack high-water mark is incorporated
444 - the virtual Hp is moved on to the worst virtual Hp for the branches
447 forkAlts :: [FCode a] -> FCode b -> FCode ([a],b)
449 forkAlts branch_fcodes (FCode deflt_fcode) =
451 info_down <- getInfoDown
453 let compile (FCode fc) = fc info_down in_state
454 let (branch_results, branch_out_states) = unzip (map compile branch_fcodes)
455 let (deflt_result, deflt_out_state) = deflt_fcode info_down in_state
456 setState $ foldl stateIncUsage in_state (deflt_out_state:branch_out_states)
457 -- NB foldl. in_state is the *left* argument to stateIncUsage
458 return (branch_results, deflt_result)
462 @forkEval@ takes two blocks of code.
464 - The first meddles with the environment to set it up as expected by
465 the alternatives of a @case@ which does an eval (or gc-possible primop).
466 - The second block is the code for the alternatives.
467 (plus info for semi-tagging purposes)
469 @forkEval@ picks up the virtual stack pointer and returns a suitable
470 @EndOfBlockInfo@ for the caller to use, together with whatever value
471 is returned by the second block.
473 It uses @initEnvForAlternatives@ to initialise the environment, and
474 @stateIncUsageAlt@ to incorporate usage; the latter ignores the heap
478 forkEval :: EndOfBlockInfo -- For the body
479 -> Code -- Code to set environment
480 -> FCode Sequel -- Semi-tagging info to store
481 -> FCode EndOfBlockInfo -- The new end of block info
483 forkEval body_eob_info env_code body_code
484 = forkEvalHelp body_eob_info env_code body_code `thenFC` \ (v, sequel) ->
485 returnFC (EndOfBlockInfo v sequel)
487 forkEvalHelp :: EndOfBlockInfo -- For the body
488 -> Code -- Code to set environment
489 -> FCode a -- The code to do after the eval
491 a) -- Result of the FCode
493 forkEvalHelp body_eob_info env_code body_code =
495 info_down@(MkCgInfoDown cg_info statics srt ticky _) <- getInfoDown
497 let info_down_for_body = MkCgInfoDown cg_info statics srt ticky body_eob_info
498 let (_,MkCgState _ binds ((v,t,f,_,_),_)) =
499 doFCode env_code info_down_for_body state
500 let state_for_body = MkCgState AbsCNop
501 (nukeVolatileBinds binds)
503 let (value_returned, state_at_end_return) =
504 doFCode body_code info_down_for_body state_for_body
505 setState $ state `stateIncUsageEval` state_at_end_return
506 return (v,value_returned)
508 stateIncUsageEval :: CgState -> CgState -> CgState
509 stateIncUsageEval (MkCgState absC1 bs ((v,t,f,r,h1),heap_usage))
510 (MkCgState absC2 _ ((_,_,_,_,h2), _))
511 = MkCgState (absC1 `mkAbsCStmts` absC2)
512 -- The AbsC coming back should consist only of nested declarations,
513 -- notably of the return vector!
515 ((v,t,f,r,h1 `max` h2), heap_usage)
516 -- We don't max the heap high-watermark because stateIncUsageEval is
517 -- used only in forkEval, which in turn is only used for blocks of code
518 -- which do their own heap-check.
521 %************************************************************************
523 \subsection[CgMonad-spitting-AbstractC]{Spitting out @AbstractC@}
525 %************************************************************************
527 @nopC@ is the no-op for the @Code@ monad; it adds no Abstract~C to the
528 environment; @absC@ glues @ab_C@ onto the Abstract~C collected so far.
533 absC :: AbstractC -> Code
535 state@(MkCgState absC binds usage) <- getState
536 setState $ MkCgState (mkAbsCStmts absC more_absC) binds usage
539 These two are just like @absC@, except they examine the compilation
540 info (whether SCC profiling or profiling-ctrs going) and possibly emit
544 costCentresC :: FastString -> [CAddrMode] -> Code
545 costCentresC macro args
546 | opt_SccProfilingOn = absC (CCallProfCCMacro macro args)
549 profCtrC :: FastString -> [CAddrMode] -> Code
551 | opt_DoTickyProfiling = absC (CCallProfCtrMacro macro args)
554 profCtrAbsC :: FastString -> [CAddrMode] -> AbstractC
555 profCtrAbsC macro args
556 | opt_DoTickyProfiling = CCallProfCtrMacro macro args
557 | otherwise = AbsCNop
560 ldvEnter = costCentresC FSLIT("LDV_ENTER") [CReg node]
562 {- Try to avoid adding too many special compilation strategies here.
563 It's better to modify the header files as necessary for particular
564 targets, so that we can get away with as few variants of .hc files
569 @getAbsC@ compiles the code in the current environment, and returns
570 the abstract C thus constructed (leaving the abstract C being carried
571 around in the state untouched). @getAbsC@ does not generate any
572 in-line Abstract~C itself, but the environment it returns is that
573 obtained from the compilation.
576 getAbsC :: Code -> FCode AbstractC
578 MkCgState absC binds usage <- getState
579 ((),MkCgState absC2 binds2 usage2) <- withState code (MkCgState AbsCNop binds usage)
580 setState $ MkCgState absC binds2 usage2
585 moduleName :: FCode Module
587 (MkCgInfoDown (MkCompInfo mod_name) _ _ _ _) <- getInfoDown
592 setEndOfBlockInfo :: EndOfBlockInfo -> Code -> Code
593 setEndOfBlockInfo eob_info code = do
594 (MkCgInfoDown c_info statics srt ticky _) <- getInfoDown
595 withInfoDown code (MkCgInfoDown c_info statics srt ticky eob_info)
597 getEndOfBlockInfo :: FCode EndOfBlockInfo
598 getEndOfBlockInfo = do
599 (MkCgInfoDown c_info statics _ _ eob_info) <- getInfoDown
603 There is just one SRT for each top level binding; all the nested
604 bindings use sub-sections of this SRT. The label is passed down to
605 the nested bindings via the monad.
608 getSRTInfo :: SRT -> FCode C_SRT
609 getSRTInfo NoSRT = return NoC_SRT
610 getSRTInfo (SRT off len) = do srt_lbl <- getSRTLabel
611 return (C_SRT srt_lbl off len)
613 getSRTLabel :: FCode CLabel -- Used only by cgPanic
614 getSRTLabel = do MkCgInfoDown _ _ srt_lbl _ _ <- getInfoDown
617 setSRTLabel :: CLabel -> Code -> Code
618 setSRTLabel srt_lbl code
619 = do MkCgInfoDown c_info statics _ ticky eob_info <- getInfoDown
620 withInfoDown code (MkCgInfoDown c_info statics srt_lbl ticky eob_info)
624 getTickyCtrLabel :: FCode CLabel
625 getTickyCtrLabel = do
626 (MkCgInfoDown _ _ _ ticky _) <- getInfoDown
629 setTickyCtrLabel :: CLabel -> Code -> Code
630 setTickyCtrLabel ticky code = do
631 (MkCgInfoDown c_info statics srt _ eob_info) <- getInfoDown
632 withInfoDown code (MkCgInfoDown c_info statics srt ticky eob_info)