2 % (c) The University of Glasgow 2006
3 % (c) The GRASP/AQUA Project, Glasgow University, 1992-1998
5 \section[CgMonad]{The code generation monad}
7 See the beginning of the top-level @CodeGen@ module, to see how this
8 monadic stuff fits into the Big Picture.
15 initC, thenC, thenFC, listCs, listFCs, mapCs, mapFCs,
16 returnFC, fixC, checkedAbsC,
17 stmtC, stmtsC, labelC, emitStmts, nopC, whenC, newLabelC,
18 newUnique, newUniqSupply,
20 CgStmts, emitCgStmts, forkCgStmts, cgStmtsToBlocks,
21 getCgStmts', getCgStmts,
22 noCgStmts, oneCgStmt, consCgStmt,
25 emitData, emitProc, emitSimpleProc,
28 forkClosureBody, forkStatics, forkAlts, forkEval,
29 forkEvalHelp, forkProc, codeOnly,
30 SemiTaggingStuff, ConTagZ,
33 setEndOfBlockInfo, getEndOfBlockInfo,
36 setSRTLabel, getSRTLabel,
37 setTickyCtrLabel, getTickyCtrLabel,
39 StackUsage(..), HeapUsage(..),
40 VirtualSpOffset, VirtualHpOffset,
41 initStkUsage, initHpUsage,
42 getHpUsage, setHpUsage,
47 Sequel(..), -- ToDo: unabstract?
49 -- ideally we wouldn't export these, but some other modules access internal state
50 getState, setState, getInfoDown, getDynFlags, getThisPackage,
52 -- more localised access to monad state
53 getStkUsage, setStkUsage,
54 getBinds, setBinds, getStaticBinds,
56 -- out of general friendliness, we also export ...
57 CgInfoDownwards(..), CgState(..) -- non-abstract
60 #include "HsVersions.h"
62 import {-# SOURCE #-} CgBindery ( CgBindings, nukeVolatileBinds )
84 infixr 9 `thenC` -- Right-associative!
88 %************************************************************************
90 \subsection[CgMonad-environment]{Stuff for manipulating environments}
92 %************************************************************************
94 This monadery has some information that it only passes {\em
95 downwards}, as well as some ``state'' which is modified as we go
99 data CgInfoDownwards -- information only passed *downwards* by the monad
101 cgd_dflags :: DynFlags,
102 cgd_mod :: Module, -- Module being compiled
103 cgd_statics :: CgBindings, -- [Id -> info] : static environment
104 cgd_srt_lbl :: CLabel, -- label of the current SRT
105 cgd_srt :: SRT, -- the current SRT
106 cgd_ticky :: CLabel, -- current destination for ticky counts
107 cgd_eob :: EndOfBlockInfo -- Info for stuff to do at end of basic block:
110 initCgInfoDown :: DynFlags -> Module -> CgInfoDownwards
111 initCgInfoDown dflags mod
112 = MkCgInfoDown { cgd_dflags = dflags,
114 cgd_statics = emptyVarEnv,
115 cgd_srt_lbl = error "initC: srt_lbl",
116 cgd_srt = error "initC: srt",
117 cgd_ticky = mkTopTickyCtrLabel,
118 cgd_eob = initEobInfo }
122 cgs_stmts :: OrdList CgStmt, -- Current proc
123 cgs_tops :: OrdList CmmTop,
124 -- Other procedures and data blocks in this compilation unit
125 -- Both the latter two are ordered only so that we can
126 -- reduce forward references, when it's easy to do so
128 cgs_binds :: CgBindings, -- [Id -> info] : *local* bindings environment
129 -- Bindings for top-level things are given in
130 -- the info-down part
132 cgs_stk_usg :: StackUsage,
133 cgs_hp_usg :: HeapUsage,
135 cgs_uniqs :: UniqSupply }
137 initCgState :: UniqSupply -> CgState
139 = MkCgState { cgs_stmts = nilOL, cgs_tops = nilOL,
140 cgs_binds = emptyVarEnv,
141 cgs_stk_usg = initStkUsage,
142 cgs_hp_usg = initHpUsage,
146 @EndOfBlockInfo@ tells what to do at the end of this block of code or,
147 if the expression is a @case@, what to do at the end of each
153 VirtualSpOffset -- Args Sp: trim the stack to this point at a
154 -- return; push arguments starting just
155 -- above this point on a tail call.
157 -- This is therefore the stk ptr as seen
158 -- by a case alternative.
161 initEobInfo = EndOfBlockInfo 0 OnStack
164 Any addressing modes inside @Sequel@ must be ``robust,'' in the sense
165 that it must survive stack pointer adjustments at the end of the
170 = OnStack -- Continuation is on the stack
171 | UpdateCode -- Continuation is update
174 CLabel -- Jump to this; if the continuation is for a vectored
175 -- case this might be the label of a return vector
177 Id -- The case binder, only used to see if it's dead
179 type SemiTaggingStuff
180 = Maybe -- Maybe[1] we don't have any semi-tagging stuff...
181 ([(ConTagZ, CmmLit)], -- Alternatives
182 CmmLit) -- Default (will be a can't happen RTS label if can't happen)
184 type ConTagZ = Int -- A *zero-indexed* contructor tag
186 -- The case branch is executed only from a successful semitagging
187 -- venture, when a case has looked at a variable, found that it's
188 -- evaluated, and wants to load up the contents and go to the join
192 %************************************************************************
196 %************************************************************************
198 The CgStmts type is what the code generator outputs: it is a tree of
199 statements, including in-line labels. The job of flattenCgStmts is to
200 turn this into a list of basic blocks, each of which ends in a jump
201 statement (either a local branch or a non-local jump).
204 type CgStmts = OrdList CgStmt
209 | CgFork BlockId CgStmts
211 flattenCgStmts :: BlockId -> CgStmts -> [CmmBasicBlock]
212 flattenCgStmts id stmts =
213 case flatten (fromOL stmts) of
214 ([],blocks) -> blocks
215 (block,blocks) -> BasicBlock id block : blocks
219 -- A label at the end of a function or fork: this label must not be reachable,
220 -- but it might be referred to from another BB that also isn't reachable.
221 -- Eliminating these has to be done with a dead-code analysis. For now,
222 -- we just make it into a well-formed block by adding a recursive jump.
224 = ( [CmmBranch id], [BasicBlock id [CmmBranch id]] )
226 -- A jump/branch: throw away all the code up to the next label, because
227 -- it is unreachable. Be careful to keep forks that we find on the way.
228 flatten (CgStmt stmt : stmts)
230 = case dropWhile isOrdinaryStmt stmts of
232 [CgLabel id] -> ( [stmt], [BasicBlock id [CmmBranch id]])
233 (CgLabel id : stmts) -> ( [stmt], BasicBlock id block : blocks )
234 where (block,blocks) = flatten stmts
235 (CgFork fork_id stmts : ss) ->
236 flatten (CgFork fork_id stmts : CgStmt stmt : ss)
240 CgStmt stmt -> (stmt:block,blocks)
241 CgLabel id -> ([CmmBranch id],BasicBlock id block:blocks)
242 CgFork fork_id stmts ->
243 (block, BasicBlock fork_id fork_block : fork_blocks ++ blocks)
244 where (fork_block, fork_blocks) = flatten (fromOL stmts)
245 where (block,blocks) = flatten ss
247 isJump (CmmJump _ _) = True
248 isJump (CmmBranch _) = True
249 isJump (CmmSwitch _ _) = True
250 isJump (CmmReturn _) = True
253 isOrdinaryStmt (CgStmt _) = True
254 isOrdinaryStmt _ = False
257 %************************************************************************
259 Stack and heap models
261 %************************************************************************
264 type VirtualHpOffset = WordOff -- Both are in
265 type VirtualSpOffset = WordOff -- units of words
269 virtSp :: VirtualSpOffset,
270 -- Virtual offset of topmost allocated slot
272 frameSp :: VirtualSpOffset,
273 -- Virtual offset of the return address of the enclosing frame.
274 -- This RA describes the liveness/pointedness of
275 -- all the stack from frameSp downwards
276 -- INVARIANT: less than or equal to virtSp
278 freeStk :: [VirtualSpOffset],
279 -- List of free slots, in *increasing* order
280 -- INVARIANT: all <= virtSp
281 -- All slots <= virtSp are taken except these ones
283 realSp :: VirtualSpOffset,
284 -- Virtual offset of real stack pointer register
286 hwSp :: VirtualSpOffset
287 } -- Highest value ever taken by virtSp
289 -- INVARIANT: The environment contains no Stable references to
290 -- stack slots below (lower offset) frameSp
291 -- It can contain volatile references to this area though.
295 virtHp :: VirtualHpOffset, -- Virtual offset of highest-allocated word
296 realHp :: VirtualHpOffset -- realHp: Virtual offset of real heap ptr
300 The heap high water mark is the larger of virtHp and hwHp. The latter is
301 only records the high water marks of forked-off branches, so to find the
302 heap high water mark you have to take the max of virtHp and hwHp. Remember,
303 virtHp never retreats!
305 Note Jan 04: ok, so why do we only look at the virtual Hp??
308 heapHWM :: HeapUsage -> VirtualHpOffset
315 initStkUsage :: StackUsage
316 initStkUsage = StackUsage {
324 initHpUsage :: HeapUsage
325 initHpUsage = HeapUsage {
331 @stateIncUsage@$~e_1~e_2$ incorporates in $e_1$ the stack and heap high water
332 marks found in $e_2$.
335 stateIncUsage :: CgState -> CgState -> CgState
336 stateIncUsage s1 s2@(MkCgState { cgs_stk_usg = stk_usg, cgs_hp_usg = hp_usg })
337 = s1 { cgs_hp_usg = cgs_hp_usg s1 `maxHpHw` virtHp hp_usg,
338 cgs_stk_usg = cgs_stk_usg s1 `maxStkHw` hwSp stk_usg }
339 `addCodeBlocksFrom` s2
341 stateIncUsageEval :: CgState -> CgState -> CgState
342 stateIncUsageEval s1 s2
343 = s1 { cgs_stk_usg = cgs_stk_usg s1 `maxStkHw` hwSp (cgs_stk_usg s2) }
344 `addCodeBlocksFrom` s2
345 -- We don't max the heap high-watermark because stateIncUsageEval is
346 -- used only in forkEval, which in turn is only used for blocks of code
347 -- which do their own heap-check.
349 addCodeBlocksFrom :: CgState -> CgState -> CgState
350 -- Add code blocks from the latter to the former
351 -- (The cgs_stmts will often be empty, but not always; see codeOnly)
352 s1 `addCodeBlocksFrom` s2
353 = s1 { cgs_stmts = cgs_stmts s1 `appOL` cgs_stmts s2,
354 cgs_tops = cgs_tops s1 `appOL` cgs_tops s2 }
356 maxHpHw :: HeapUsage -> VirtualHpOffset -> HeapUsage
357 hp_usg `maxHpHw` hw = hp_usg { virtHp = virtHp hp_usg `max` hw }
359 maxStkHw :: StackUsage -> VirtualSpOffset -> StackUsage
360 stk_usg `maxStkHw` hw = stk_usg { hwSp = hwSp stk_usg `max` hw }
363 %************************************************************************
367 %************************************************************************
370 newtype FCode a = FCode (CgInfoDownwards -> CgState -> (a, CgState))
373 instance Monad FCode where
378 {-# INLINE thenFC #-}
379 {-# INLINE returnFC #-}
381 The Abstract~C is not in the environment so as to improve strictness.
384 initC :: DynFlags -> Module -> FCode a -> IO a
386 initC dflags mod (FCode code)
387 = do { uniqs <- mkSplitUniqSupply 'c'
388 ; case code (initCgInfoDown dflags mod) (initCgState uniqs) of
389 (res, _) -> return res
392 returnFC :: a -> FCode a
393 returnFC val = FCode (\info_down state -> (val, state))
397 thenC :: Code -> FCode a -> FCode a
398 thenC (FCode m) (FCode k) =
399 FCode (\info_down state -> let (_,new_state) = m info_down state in
400 k info_down new_state)
402 listCs :: [Code] -> Code
403 listCs [] = return ()
408 mapCs :: (a -> Code) -> [a] -> Code
413 thenFC :: FCode a -> (a -> FCode c) -> FCode c
414 thenFC (FCode m) k = FCode (
417 (m_result, new_state) = m info_down state
418 (FCode kcode) = k m_result
420 kcode info_down new_state
423 listFCs :: [FCode a] -> FCode [a]
426 mapFCs :: (a -> FCode b) -> [a] -> FCode [b]
430 And the knot-tying combinator:
432 fixC :: (a -> FCode a) -> FCode a
437 result@(v,_) = fc info_down state
444 %************************************************************************
446 Operators for getting and setting the state and "info_down".
449 %************************************************************************
452 getState :: FCode CgState
453 getState = FCode $ \info_down state -> (state,state)
455 setState :: CgState -> FCode ()
456 setState state = FCode $ \info_down _ -> ((),state)
458 getStkUsage :: FCode StackUsage
461 return $ cgs_stk_usg state
463 setStkUsage :: StackUsage -> Code
464 setStkUsage new_stk_usg = do
466 setState $ state {cgs_stk_usg = new_stk_usg}
468 getHpUsage :: FCode HeapUsage
471 return $ cgs_hp_usg state
473 setHpUsage :: HeapUsage -> Code
474 setHpUsage new_hp_usg = do
476 setState $ state {cgs_hp_usg = new_hp_usg}
478 getBinds :: FCode CgBindings
481 return $ cgs_binds state
483 setBinds :: CgBindings -> FCode ()
484 setBinds new_binds = do
486 setState $ state {cgs_binds = new_binds}
488 getStaticBinds :: FCode CgBindings
491 return (cgd_statics info)
493 withState :: FCode a -> CgState -> FCode (a,CgState)
494 withState (FCode fcode) newstate = FCode $ \info_down state ->
495 let (retval, state2) = fcode info_down newstate in ((retval,state2), state)
497 newUniqSupply :: FCode UniqSupply
500 let (us1, us2) = splitUniqSupply (cgs_uniqs state)
501 setState $ state { cgs_uniqs = us1 }
504 newUnique :: FCode Unique
507 return (uniqFromSupply us)
510 getInfoDown :: FCode CgInfoDownwards
511 getInfoDown = FCode $ \info_down state -> (info_down,state)
513 getDynFlags :: FCode DynFlags
514 getDynFlags = liftM cgd_dflags getInfoDown
516 getThisPackage :: FCode PackageId
517 getThisPackage = liftM thisPackage getDynFlags
519 withInfoDown :: FCode a -> CgInfoDownwards -> FCode a
520 withInfoDown (FCode fcode) info_down = FCode $ \_ state -> fcode info_down state
522 doFCode :: FCode a -> CgInfoDownwards -> CgState -> (a,CgState)
523 doFCode (FCode fcode) info_down state = fcode info_down state
527 %************************************************************************
531 %************************************************************************
533 @forkClosureBody@ takes a code, $c$, and compiles it in a completely
534 fresh environment, except that:
535 - compilation info and statics are passed in unchanged.
536 The current environment is passed on completely unaltered, except that
537 abstract C from the fork is incorporated.
539 @forkProc@ takes a code and compiles it in the current environment,
540 returning the basic blocks thus constructed. The current environment
541 is passed on completely unchanged. It is pretty similar to
542 @getBlocks@, except that the latter does affect the environment.
544 @forkStatics@ $fc$ compiles $fc$ in an environment whose statics come
545 from the current bindings, but which is otherwise freshly initialised.
546 The Abstract~C returned is attached to the current state, but the
547 bindings and usage information is otherwise unchanged.
550 forkClosureBody :: Code -> Code
551 forkClosureBody body_code
552 = do { info <- getInfoDown
553 ; us <- newUniqSupply
555 ; let body_info_down = info { cgd_eob = initEobInfo }
556 ((),fork_state) = doFCode body_code body_info_down
558 ; ASSERT( isNilOL (cgs_stmts fork_state) )
559 setState $ state `addCodeBlocksFrom` fork_state }
561 forkStatics :: FCode a -> FCode a
562 forkStatics body_code
563 = do { info <- getInfoDown
564 ; us <- newUniqSupply
566 ; let rhs_info_down = info { cgd_statics = cgs_binds state,
567 cgd_eob = initEobInfo }
568 (result, fork_state_out) = doFCode body_code rhs_info_down
570 ; ASSERT( isNilOL (cgs_stmts fork_state_out) )
571 setState (state `addCodeBlocksFrom` fork_state_out)
574 forkProc :: Code -> FCode CgStmts
576 = do { info_down <- getInfoDown
577 ; us <- newUniqSupply
579 ; let fork_state_in = (initCgState us)
580 { cgs_binds = cgs_binds state,
581 cgs_stk_usg = cgs_stk_usg state,
582 cgs_hp_usg = cgs_hp_usg state }
583 -- ToDo: is the hp usage necesary?
584 (code_blks, fork_state_out) = doFCode (getCgStmts body_code)
585 info_down fork_state_in
586 ; setState $ state `stateIncUsageEval` fork_state_out
589 codeOnly :: Code -> Code
590 -- Emit any code from the inner thing into the outer thing
591 -- Do not affect anything else in the outer state
592 -- Used in almost-circular code to prevent false loop dependencies
594 = do { info_down <- getInfoDown
595 ; us <- newUniqSupply
597 ; let fork_state_in = (initCgState us) { cgs_binds = cgs_binds state,
598 cgs_stk_usg = cgs_stk_usg state,
599 cgs_hp_usg = cgs_hp_usg state }
600 ((), fork_state_out) = doFCode body_code info_down fork_state_in
601 ; setState $ state `addCodeBlocksFrom` fork_state_out }
604 @forkAlts@ $bs~d$ takes fcodes $bs$ for the branches of a @case@, and
605 an fcode for the default case $d$, and compiles each in the current
606 environment. The current environment is passed on unmodified, except
608 - the worst stack high-water mark is incorporated
609 - the virtual Hp is moved on to the worst virtual Hp for the branches
612 forkAlts :: [FCode a] -> FCode [a]
614 forkAlts branch_fcodes
615 = do { info_down <- getInfoDown
616 ; us <- newUniqSupply
618 ; let compile us branch
619 = (us2, doFCode branch info_down branch_state)
621 (us1,us2) = splitUniqSupply us
622 branch_state = (initCgState us1) {
623 cgs_binds = cgs_binds state,
624 cgs_stk_usg = cgs_stk_usg state,
625 cgs_hp_usg = cgs_hp_usg state }
627 (_us, results) = mapAccumL compile us branch_fcodes
628 (branch_results, branch_out_states) = unzip results
629 ; setState $ foldl stateIncUsage state branch_out_states
630 -- NB foldl. state is the *left* argument to stateIncUsage
631 ; return branch_results }
634 @forkEval@ takes two blocks of code.
636 - The first meddles with the environment to set it up as expected by
637 the alternatives of a @case@ which does an eval (or gc-possible primop).
638 - The second block is the code for the alternatives.
639 (plus info for semi-tagging purposes)
641 @forkEval@ picks up the virtual stack pointer and returns a suitable
642 @EndOfBlockInfo@ for the caller to use, together with whatever value
643 is returned by the second block.
645 It uses @initEnvForAlternatives@ to initialise the environment, and
646 @stateIncUsageAlt@ to incorporate usage; the latter ignores the heap
650 forkEval :: EndOfBlockInfo -- For the body
651 -> Code -- Code to set environment
652 -> FCode Sequel -- Semi-tagging info to store
653 -> FCode EndOfBlockInfo -- The new end of block info
655 forkEval body_eob_info env_code body_code
656 = do { (v, sequel) <- forkEvalHelp body_eob_info env_code body_code
657 ; returnFC (EndOfBlockInfo v sequel) }
659 forkEvalHelp :: EndOfBlockInfo -- For the body
660 -> Code -- Code to set environment
661 -> FCode a -- The code to do after the eval
662 -> FCode (VirtualSpOffset, -- Sp
663 a) -- Result of the FCode
664 -- A disturbingly complicated function
665 forkEvalHelp body_eob_info env_code body_code
666 = do { info_down <- getInfoDown
667 ; us <- newUniqSupply
669 ; let { info_down_for_body = info_down {cgd_eob = body_eob_info}
670 ; (_, env_state) = doFCode env_code info_down_for_body
671 (state {cgs_uniqs = us})
672 ; state_for_body = (initCgState (cgs_uniqs env_state))
673 { cgs_binds = binds_for_body,
674 cgs_stk_usg = stk_usg_for_body }
675 ; binds_for_body = nukeVolatileBinds (cgs_binds env_state)
676 ; stk_usg_from_env = cgs_stk_usg env_state
677 ; virtSp_from_env = virtSp stk_usg_from_env
678 ; stk_usg_for_body = stk_usg_from_env {realSp = virtSp_from_env,
679 hwSp = virtSp_from_env}
680 ; (value_returned, state_at_end_return)
681 = doFCode body_code info_down_for_body state_for_body
683 ; ASSERT( isNilOL (cgs_stmts state_at_end_return) )
684 -- The code coming back should consist only of nested declarations,
685 -- notably of the return vector!
686 setState $ state `stateIncUsageEval` state_at_end_return
687 ; return (virtSp_from_env, value_returned) }
690 -- ----------------------------------------------------------------------------
691 -- Combinators for emitting code
696 whenC :: Bool -> Code -> Code
697 whenC True code = code
698 whenC False code = nopC
700 stmtC :: CmmStmt -> Code
701 stmtC stmt = emitCgStmt (CgStmt stmt)
703 labelC :: BlockId -> Code
704 labelC id = emitCgStmt (CgLabel id)
706 newLabelC :: FCode BlockId
707 newLabelC = do { id <- newUnique; return (BlockId id) }
709 checkedAbsC :: CmmStmt -> Code
710 -- Emit code, eliminating no-ops
711 checkedAbsC stmt = emitStmts (if isNopStmt stmt then nilOL
714 stmtsC :: [CmmStmt] -> Code
715 stmtsC stmts = emitStmts (toOL stmts)
717 -- Emit code; no no-op checking
718 emitStmts :: CmmStmts -> Code
719 emitStmts stmts = emitCgStmts (fmap CgStmt stmts)
721 -- forkLabelledCode is for emitting a chunk of code with a label, outside
722 -- of the current instruction stream.
723 forkLabelledCode :: Code -> FCode BlockId
724 forkLabelledCode code = getCgStmts code >>= forkCgStmts
726 emitCgStmt :: CgStmt -> Code
728 = do { state <- getState
729 ; setState $ state { cgs_stmts = cgs_stmts state `snocOL` stmt }
732 emitData :: Section -> [CmmStatic] -> Code
734 = do { state <- getState
735 ; setState $ state { cgs_tops = cgs_tops state `snocOL` data_block } }
737 data_block = CmmData sect lits
739 emitProc :: CmmInfo -> CLabel -> CmmFormals -> [CmmBasicBlock] -> Code
740 emitProc info lbl args blocks
741 = do { let proc_block = CmmProc info lbl args blocks
743 ; setState $ state { cgs_tops = cgs_tops state `snocOL` proc_block } }
745 emitSimpleProc :: CLabel -> Code -> Code
746 -- Emit a procedure whose body is the specified code; no info table
747 emitSimpleProc lbl code
748 = do { stmts <- getCgStmts code
749 ; blks <- cgStmtsToBlocks stmts
750 ; emitProc (CmmInfo Nothing Nothing CmmNonInfoTable) lbl [] blks }
752 getCmm :: Code -> FCode Cmm
753 -- Get all the CmmTops (there should be no stmts)
755 = do { state1 <- getState
756 ; ((), state2) <- withState code (state1 { cgs_tops = nilOL })
757 ; setState $ state2 { cgs_tops = cgs_tops state1 }
758 ; return (Cmm (fromOL (cgs_tops state2))) }
760 -- ----------------------------------------------------------------------------
763 -- These functions deal in terms of CgStmts, which is an abstract type
764 -- representing the code in the current proc.
767 -- emit CgStmts into the current instruction stream
768 emitCgStmts :: CgStmts -> Code
770 = do { state <- getState
771 ; setState $ state { cgs_stmts = cgs_stmts state `appOL` stmts } }
773 -- emit CgStmts outside the current instruction stream, and return a label
774 forkCgStmts :: CgStmts -> FCode BlockId
776 = do { id <- newLabelC
777 ; emitCgStmt (CgFork id stmts)
781 -- turn CgStmts into [CmmBasicBlock], for making a new proc.
782 cgStmtsToBlocks :: CgStmts -> FCode [CmmBasicBlock]
783 cgStmtsToBlocks stmts
784 = do { id <- newLabelC
785 ; return (flattenCgStmts id stmts)
788 -- collect the code emitted by an FCode computation
789 getCgStmts' :: FCode a -> FCode (a, CgStmts)
791 = do { state1 <- getState
792 ; (a, state2) <- withState fcode (state1 { cgs_stmts = nilOL })
793 ; setState $ state2 { cgs_stmts = cgs_stmts state1 }
794 ; return (a, cgs_stmts state2) }
796 getCgStmts :: FCode a -> FCode CgStmts
797 getCgStmts fcode = do { (_,stmts) <- getCgStmts' fcode; return stmts }
799 -- Simple ways to construct CgStmts:
803 oneCgStmt :: CmmStmt -> CgStmts
804 oneCgStmt stmt = unitOL (CgStmt stmt)
806 consCgStmt :: CmmStmt -> CgStmts -> CgStmts
807 consCgStmt stmt stmts = CgStmt stmt `consOL` stmts
809 -- ----------------------------------------------------------------------------
810 -- Get the current module name
812 getModuleName :: FCode Module
813 getModuleName = do { info <- getInfoDown; return (cgd_mod info) }
815 -- ----------------------------------------------------------------------------
816 -- Get/set the end-of-block info
818 setEndOfBlockInfo :: EndOfBlockInfo -> Code -> Code
819 setEndOfBlockInfo eob_info code = do
821 withInfoDown code (info {cgd_eob = eob_info})
823 getEndOfBlockInfo :: FCode EndOfBlockInfo
824 getEndOfBlockInfo = do
826 return (cgd_eob info)
828 -- ----------------------------------------------------------------------------
829 -- Get/set the current SRT label
831 -- There is just one SRT for each top level binding; all the nested
832 -- bindings use sub-sections of this SRT. The label is passed down to
833 -- the nested bindings via the monad.
835 getSRTLabel :: FCode CLabel -- Used only by cgPanic
836 getSRTLabel = do info <- getInfoDown
837 return (cgd_srt_lbl info)
839 setSRTLabel :: CLabel -> FCode a -> FCode a
840 setSRTLabel srt_lbl code
841 = do info <- getInfoDown
842 withInfoDown code (info { cgd_srt_lbl = srt_lbl})
845 getSRT = do info <- getInfoDown
846 return (cgd_srt info)
848 setSRT :: SRT -> FCode a -> FCode a
850 = do info <- getInfoDown
851 withInfoDown code (info { cgd_srt = srt})
853 -- ----------------------------------------------------------------------------
854 -- Get/set the current ticky counter label
856 getTickyCtrLabel :: FCode CLabel
857 getTickyCtrLabel = do
859 return (cgd_ticky info)
861 setTickyCtrLabel :: CLabel -> Code -> Code
862 setTickyCtrLabel ticky code = do
864 withInfoDown code (info {cgd_ticky = ticky})