diff options
author | David Terei <davidterei@gmail.com> | 2011-12-06 11:39:45 -0800 |
---|---|---|
committer | David Terei <davidterei@gmail.com> | 2011-12-06 13:43:24 -0800 |
commit | 590988bd5f143428607527097cdb936902b9f05b (patch) | |
tree | 8d2a4a797a814ab7a5823d383c9f4d4881825016 /compiler/codeGen | |
parent | 92e7d6c92fdd14de424524564376d3522f2a40cc (diff) | |
download | haskell-590988bd5f143428607527097cdb936902b9f05b.tar.gz |
Tabs -> Spaces + Formatting
Diffstat (limited to 'compiler/codeGen')
-rw-r--r-- | compiler/codeGen/CgMonad.lhs | 678 | ||||
-rw-r--r-- | compiler/codeGen/CodeGen.lhs | 160 |
2 files changed, 402 insertions, 436 deletions
diff --git a/compiler/codeGen/CgMonad.lhs b/compiler/codeGen/CgMonad.lhs index 1c9cfa7ec1..996ac35a67 100644 --- a/compiler/codeGen/CgMonad.lhs +++ b/compiler/codeGen/CgMonad.lhs @@ -8,61 +8,55 @@ See the beginning of the top-level @CodeGen@ module, to see how this monadic stuff fits into the Big Picture. \begin{code} -{-# OPTIONS -fno-warn-tabs #-} --- The above warning supression flag is a temporary kludge. --- While working on this module you are encouraged to remove it and --- detab the module (please do the detabbing in a separate patch). See --- http://hackage.haskell.org/trac/ghc/wiki/Commentary/CodingStyle#TabsvsSpaces --- for details {-# LANGUAGE BangPatterns #-} module CgMonad ( - Code, -- type - FCode, -- type + Code, + FCode, - initC, thenC, thenFC, listCs, listFCs, mapCs, mapFCs, - returnFC, fixC, fixC_, checkedAbsC, - stmtC, stmtsC, labelC, emitStmts, nopC, whenC, newLabelC, - newUnique, newUniqSupply, + initC, thenC, thenFC, listCs, listFCs, mapCs, mapFCs, + returnFC, fixC, fixC_, checkedAbsC, + stmtC, stmtsC, labelC, emitStmts, nopC, whenC, newLabelC, + newUnique, newUniqSupply, - CgStmts, emitCgStmts, forkCgStmts, cgStmtsToBlocks, - getCgStmts', getCgStmts, - noCgStmts, oneCgStmt, consCgStmt, + CgStmts, emitCgStmts, forkCgStmts, cgStmtsToBlocks, + getCgStmts', getCgStmts, + noCgStmts, oneCgStmt, consCgStmt, - getCmm, - emitDecl, emitProc, emitSimpleProc, + getCmm, + emitDecl, emitProc, emitSimpleProc, - forkLabelledCode, - forkClosureBody, forkStatics, forkAlts, forkEval, - forkEvalHelp, forkProc, codeOnly, - SemiTaggingStuff, ConTagZ, + forkLabelledCode, + forkClosureBody, forkStatics, forkAlts, forkEval, + forkEvalHelp, forkProc, codeOnly, + SemiTaggingStuff, ConTagZ, - EndOfBlockInfo(..), - setEndOfBlockInfo, getEndOfBlockInfo, + EndOfBlockInfo(..), + setEndOfBlockInfo, getEndOfBlockInfo, - setSRT, getSRT, - setSRTLabel, getSRTLabel, - setTickyCtrLabel, getTickyCtrLabel, + setSRT, getSRT, + setSRTLabel, getSRTLabel, + setTickyCtrLabel, getTickyCtrLabel, - StackUsage(..), HeapUsage(..), - VirtualSpOffset, VirtualHpOffset, - initStkUsage, initHpUsage, - getHpUsage, setHpUsage, - heapHWM, + StackUsage(..), HeapUsage(..), + VirtualSpOffset, VirtualHpOffset, + initStkUsage, initHpUsage, + getHpUsage, setHpUsage, + heapHWM, - getModuleName, + getModuleName, - Sequel(..), -- ToDo: unabstract? + Sequel(..), - -- ideally we wouldn't export these, but some other modules access internal state - getState, setState, getInfoDown, getDynFlags, getThisPackage, + -- ideally we wouldn't export these, but some other modules access internal state + getState, setState, getInfoDown, getDynFlags, getThisPackage, - -- more localised access to monad state - getStkUsage, setStkUsage, - getBinds, setBinds, getStaticBinds, + -- more localised access to monad state + getStkUsage, setStkUsage, + getBinds, setBinds, getStaticBinds, - -- out of general friendliness, we also export ... - CgInfoDownwards(..), CgState(..) -- non-abstract + -- out of general friendliness, we also export ... + CgInfoDownwards(..), CgState(..) ) where #include "HsVersions.h" @@ -88,14 +82,14 @@ import Outputable import Control.Monad import Data.List -infixr 9 `thenC` -- Right-associative! +infixr 9 `thenC` infixr 9 `thenFC` \end{code} %************************************************************************ -%* * +%* * \subsection[CgMonad-environment]{Stuff for manipulating environments} -%* * +%* * %************************************************************************ This monadery has some information that it only passes {\em @@ -103,38 +97,38 @@ downwards}, as well as some ``state'' which is modified as we go along. \begin{code} -data CgInfoDownwards -- information only passed *downwards* by the monad +data CgInfoDownwards -- information only passed *downwards* by the monad = MkCgInfoDown { - cgd_dflags :: DynFlags, - cgd_mod :: Module, -- Module being compiled - cgd_statics :: CgBindings, -- [Id -> info] : static environment - cgd_srt_lbl :: CLabel, -- label of the current SRT - cgd_srt :: SRT, -- the current SRT - cgd_ticky :: CLabel, -- current destination for ticky counts - cgd_eob :: EndOfBlockInfo -- Info for stuff to do at end of basic block: + cgd_dflags :: DynFlags, + cgd_mod :: Module, -- Module being compiled + cgd_statics :: CgBindings, -- [Id -> info] : static environment + cgd_srt_lbl :: CLabel, -- label of the current SRT + cgd_srt :: SRT, -- the current SRT + cgd_ticky :: CLabel, -- current destination for ticky counts + cgd_eob :: EndOfBlockInfo -- Info for stuff to do at end of basic block: } initCgInfoDown :: DynFlags -> Module -> CgInfoDownwards initCgInfoDown dflags mod - = MkCgInfoDown { cgd_dflags = dflags, - cgd_mod = mod, - cgd_statics = emptyVarEnv, - cgd_srt_lbl = error "initC: srt_lbl", - cgd_srt = error "initC: srt", - cgd_ticky = mkTopTickyCtrLabel, - cgd_eob = initEobInfo } + = MkCgInfoDown { cgd_dflags = dflags, + cgd_mod = mod, + cgd_statics = emptyVarEnv, + cgd_srt_lbl = error "initC: srt_lbl", + cgd_srt = error "initC: srt", + cgd_ticky = mkTopTickyCtrLabel, + cgd_eob = initEobInfo } data CgState = MkCgState { - cgs_stmts :: OrdList CgStmt, -- Current proc + cgs_stmts :: OrdList CgStmt, -- Current proc cgs_tops :: OrdList CmmDecl, - -- Other procedures and data blocks in this compilation unit - -- Both the latter two are ordered only so that we can - -- reduce forward references, when it's easy to do so + -- Other procedures and data blocks in this compilation unit + -- Both the latter two are ordered only so that we can + -- reduce forward references, when it's easy to do so - cgs_binds :: CgBindings, -- [Id -> info] : *local* bindings environment - -- Bindings for top-level things are given in - -- the info-down part + cgs_binds :: CgBindings, -- [Id -> info] : *local* bindings environment + -- Bindings for top-level things are given in + -- the info-down part cgs_stk_usg :: StackUsage, cgs_hp_usg :: HeapUsage, @@ -144,10 +138,10 @@ data CgState initCgState :: UniqSupply -> CgState initCgState uniqs = MkCgState { cgs_stmts = nilOL, cgs_tops = nilOL, - cgs_binds = emptyVarEnv, - cgs_stk_usg = initStkUsage, - cgs_hp_usg = initHpUsage, - cgs_uniqs = uniqs } + cgs_binds = emptyVarEnv, + cgs_stk_usg = initStkUsage, + cgs_hp_usg = initHpUsage, + cgs_uniqs = uniqs } \end{code} @EndOfBlockInfo@ tells what to do at the end of this block of code or, @@ -157,13 +151,13 @@ alternative. \begin{code} data EndOfBlockInfo = EndOfBlockInfo - VirtualSpOffset -- Args Sp: trim the stack to this point at a - -- return; push arguments starting just - -- above this point on a tail call. - - -- This is therefore the stk ptr as seen - -- by a case alternative. - Sequel + VirtualSpOffset -- Args Sp: trim the stack to this point at a + -- return; push arguments starting just + -- above this point on a tail call. + + -- This is therefore the stk ptr as seen + -- by a case alternative. + Sequel initEobInfo :: EndOfBlockInfo initEobInfo = EndOfBlockInfo 0 OnStack @@ -175,18 +169,18 @@ block. \begin{code} data Sequel - = OnStack -- Continuation is on the stack + = OnStack -- Continuation is on the stack | CaseAlts - CLabel -- Jump to this; if the continuation is for a vectored - -- case this might be the label of a return vector - SemiTaggingStuff - Id -- The case binder, only used to see if it's dead + CLabel -- Jump to this; if the continuation is for a vectored + -- case this might be the label of a return vector + SemiTaggingStuff + Id -- The case binder, only used to see if it's dead type SemiTaggingStuff - = Maybe -- Maybe[1] we don't have any semi-tagging stuff... - ([(ConTagZ, CmmLit)], -- Alternatives - CmmLit) -- Default (will be a can't happen RTS label if can't happen) + = Maybe -- Maybe we don't have any semi-tagging stuff... + ([(ConTagZ, CmmLit)], -- Alternatives + CmmLit) -- Default (will be a can't happen RTS label if can't happen) -- The case branch is executed only from a successful semitagging -- venture, when a case has looked at a variable, found that it's @@ -195,9 +189,9 @@ type SemiTaggingStuff \end{code} %************************************************************************ -%* * - CgStmt type -%* * +%* * + CgStmt type +%* * %************************************************************************ The CgStmts type is what the code generator outputs: it is a tree of @@ -215,9 +209,9 @@ data CgStmt flattenCgStmts :: BlockId -> CgStmts -> [CmmBasicBlock] flattenCgStmts id stmts = - case flatten (fromOL stmts) of - ([],blocks) -> blocks - (block,blocks) -> BasicBlock id block : blocks + case flatten (fromOL stmts) of + ([],blocks) -> blocks + (block,blocks) -> BasicBlock id block : blocks where flatten [] = ([],[]) @@ -233,75 +227,75 @@ flattenCgStmts id stmts = flatten (CgStmt stmt : stmts) | isJump stmt = case dropWhile isOrdinaryStmt stmts of - [] -> ( [stmt], [] ) - [CgLabel id] -> ( [stmt], [BasicBlock id [CmmBranch id]]) - (CgLabel id : stmts) -> ( [stmt], BasicBlock id block : blocks ) - where (block,blocks) = flatten stmts - (CgFork fork_id stmts : ss) -> - flatten (CgFork fork_id stmts : CgStmt stmt : ss) + [] -> ( [stmt], [] ) + [CgLabel id] -> ( [stmt], [BasicBlock id [CmmBranch id]]) + (CgLabel id : stmts) -> ( [stmt], BasicBlock id block : blocks ) + where (block,blocks) = flatten stmts + (CgFork fork_id stmts : ss) -> + flatten (CgFork fork_id stmts : CgStmt stmt : ss) (CgStmt {} : _) -> panic "CgStmt not seen as ordinary" flatten (s:ss) = - case s of - CgStmt stmt -> (stmt:block,blocks) - CgLabel id -> ([CmmBranch id],BasicBlock id block:blocks) - CgFork fork_id stmts -> - (block, BasicBlock fork_id fork_block : fork_blocks ++ blocks) - where (fork_block, fork_blocks) = flatten (fromOL stmts) + case s of + CgStmt stmt -> (stmt:block,blocks) + CgLabel id -> ([CmmBranch id],BasicBlock id block:blocks) + CgFork fork_id stmts -> + (block, BasicBlock fork_id fork_block : fork_blocks ++ blocks) + where (fork_block, fork_blocks) = flatten (fromOL stmts) where (block,blocks) = flatten ss isJump :: CmmStmt -> Bool -isJump (CmmJump _ _) = True -isJump (CmmBranch _) = True +isJump (CmmJump _ _) = True +isJump (CmmBranch _ ) = True isJump (CmmSwitch _ _) = True -isJump (CmmReturn _) = True -isJump _ = False +isJump (CmmReturn _ ) = True +isJump _ = False isOrdinaryStmt :: CgStmt -> Bool isOrdinaryStmt (CgStmt _) = True -isOrdinaryStmt _ = False +isOrdinaryStmt _ = False \end{code} %************************************************************************ -%* * - Stack and heap models -%* * +%* * + Stack and heap models +%* * %************************************************************************ \begin{code} -type VirtualHpOffset = WordOff -- Both are in -type VirtualSpOffset = WordOff -- units of words +type VirtualHpOffset = WordOff -- Both are in +type VirtualSpOffset = WordOff -- units of words data StackUsage = StackUsage { - virtSp :: VirtualSpOffset, - -- Virtual offset of topmost allocated slot + virtSp :: VirtualSpOffset, + -- Virtual offset of topmost allocated slot - frameSp :: VirtualSpOffset, - -- Virtual offset of the return address of the enclosing frame. - -- This RA describes the liveness/pointedness of - -- all the stack from frameSp downwards - -- INVARIANT: less than or equal to virtSp + frameSp :: VirtualSpOffset, + -- Virtual offset of the return address of the enclosing frame. + -- This RA describes the liveness/pointedness of + -- all the stack from frameSp downwards + -- INVARIANT: less than or equal to virtSp - freeStk :: [VirtualSpOffset], - -- List of free slots, in *increasing* order - -- INVARIANT: all <= virtSp - -- All slots <= virtSp are taken except these ones + freeStk :: [VirtualSpOffset], + -- List of free slots, in *increasing* order + -- INVARIANT: all <= virtSp + -- All slots <= virtSp are taken except these ones - realSp :: VirtualSpOffset, - -- Virtual offset of real stack pointer register + realSp :: VirtualSpOffset, + -- Virtual offset of real stack pointer register - hwSp :: VirtualSpOffset - } -- Highest value ever taken by virtSp + hwSp :: VirtualSpOffset + } -- Highest value ever taken by virtSp -- INVARIANT: The environment contains no Stable references to --- stack slots below (lower offset) frameSp --- It can contain volatile references to this area though. +-- stack slots below (lower offset) frameSp +-- It can contain volatile references to this area though. data HeapUsage = HeapUsage { - virtHp :: VirtualHpOffset, -- Virtual offset of highest-allocated word - realHp :: VirtualHpOffset -- realHp: Virtual offset of real heap ptr + virtHp :: VirtualHpOffset, -- Virtual offset of highest-allocated word + realHp :: VirtualHpOffset -- realHp: Virtual offset of real heap ptr } \end{code} @@ -322,44 +316,41 @@ Initialisation. \begin{code} initStkUsage :: StackUsage initStkUsage = StackUsage { - virtSp = 0, - frameSp = 0, - freeStk = [], - realSp = 0, - hwSp = 0 - } - + virtSp = 0, + frameSp = 0, + freeStk = [], + realSp = 0, + hwSp = 0 + } + initHpUsage :: HeapUsage initHpUsage = HeapUsage { - virtHp = 0, - realHp = 0 - } -\end{code} - -@stateIncUsage@$~e_1~e_2$ incorporates in $e_1$ the stack and heap high water -marks found in $e_2$. + virtHp = 0, + realHp = 0 + } -\begin{code} +-- | @stateIncUsafe@ sets the stack and heap high water marks of $arg1$ to +-- be the max of the high water marks of $arg1$ and $arg2$. stateIncUsage :: CgState -> CgState -> CgState stateIncUsage s1 s2@(MkCgState { cgs_stk_usg = stk_usg, cgs_hp_usg = hp_usg }) = s1 { cgs_hp_usg = cgs_hp_usg s1 `maxHpHw` virtHp hp_usg, - cgs_stk_usg = cgs_stk_usg s1 `maxStkHw` hwSp stk_usg } + cgs_stk_usg = cgs_stk_usg s1 `maxStkHw` hwSp stk_usg } `addCodeBlocksFrom` s2 - + stateIncUsageEval :: CgState -> CgState -> CgState stateIncUsageEval s1 s2 = s1 { cgs_stk_usg = cgs_stk_usg s1 `maxStkHw` hwSp (cgs_stk_usg s2) } `addCodeBlocksFrom` s2 - -- We don't max the heap high-watermark because stateIncUsageEval is - -- used only in forkEval, which in turn is only used for blocks of code - -- which do their own heap-check. + -- We don't max the heap high-watermark because stateIncUsageEval is + -- used only in forkEval, which in turn is only used for blocks of code + -- which do their own heap-check. addCodeBlocksFrom :: CgState -> CgState -> CgState -- Add code blocks from the latter to the former -- (The cgs_stmts will often be empty, but not always; see codeOnly) s1 `addCodeBlocksFrom` s2 = s1 { cgs_stmts = cgs_stmts s1 `appOL` cgs_stmts s2, - cgs_tops = cgs_tops s1 `appOL` cgs_tops s2 } + cgs_tops = cgs_tops s1 `appOL` cgs_tops s2 } maxHpHw :: HeapUsage -> VirtualHpOffset -> HeapUsage hp_usg `maxHpHw` hw = hp_usg { virtHp = virtHp hp_usg `max` hw } @@ -369,9 +360,9 @@ stk_usg `maxStkHw` hw = stk_usg { hwSp = hwSp stk_usg `max` hw } \end{code} %************************************************************************ -%* * - The FCode monad -%* * +%* * + The FCode monad +%* * %************************************************************************ \begin{code} @@ -379,8 +370,8 @@ newtype FCode a = FCode (CgInfoDownwards -> CgState -> (a, CgState)) type Code = FCode () instance Monad FCode where - (>>=) = thenFC - return = returnFC + (>>=) = thenFC + return = returnFC {-# INLINE thenC #-} {-# INLINE thenFC #-} @@ -392,10 +383,10 @@ The Abstract~C is not in the environment so as to improve strictness. initC :: DynFlags -> Module -> FCode a -> IO a initC dflags mod (FCode code) - = do { uniqs <- mkSplitUniqSupply 'c' - ; case code (initCgInfoDown dflags mod) (initCgState uniqs) of - (res, _) -> return res - } + = do { uniqs <- mkSplitUniqSupply 'c' + ; case code (initCgInfoDown dflags mod) (initCgState uniqs) of + (res, _) -> return res + } returnFC :: a -> FCode a returnFC val = FCode (\_ state -> (val, state)) @@ -404,59 +395,51 @@ returnFC val = FCode (\_ state -> (val, state)) \begin{code} thenC :: Code -> FCode a -> FCode a thenC (FCode m) (FCode k) = - FCode (\info_down state -> let (_,new_state) = m info_down state in - k info_down new_state) + FCode (\info_down state -> let (_,new_state) = m info_down state in + k info_down new_state) listCs :: [Code] -> Code listCs [] = return () listCs (fc:fcs) = do - fc - listCs fcs - + fc + listCs fcs + mapCs :: (a -> Code) -> [a] -> Code mapCs = mapM_ -\end{code} -\begin{code} -thenFC :: FCode a -> (a -> FCode c) -> FCode c +thenFC :: FCode a -> (a -> FCode c) -> FCode c thenFC (FCode m) k = FCode ( - \info_down state -> - let + \info_down state -> + let (m_result, new_state) = m info_down state (FCode kcode) = k m_result - in - kcode info_down new_state - ) + in + kcode info_down new_state + ) listFCs :: [FCode a] -> FCode [a] listFCs = sequence mapFCs :: (a -> FCode b) -> [a] -> FCode [b] mapFCs = mapM -\end{code} -And the knot-tying combinator: -\begin{code} +-- | Knot-tying combinator for @FCode@ fixC :: (a -> FCode a) -> FCode a -fixC fcode = FCode ( - \info_down state -> - let - FCode fc = fcode v - result@(v,_) = fc info_down state - -- ^--------^ - in - result - ) +fixC fcode = FCode $ + \info_down state -> + let FCode fc = fcode v + result@(v,_) = fc info_down state + in result +-- | Knot-tying combinator that throws result away fixC_ :: (a -> FCode a) -> FCode () fixC_ fcode = fixC fcode >> return () \end{code} %************************************************************************ -%* * - Operators for getting and setting the state and "info_down". - -%* * +%* * + Operators for getting and setting the state and "info_down". +%* * %************************************************************************ \begin{code} @@ -468,56 +451,55 @@ setState state = FCode $ \_ _ -> ((),state) getStkUsage :: FCode StackUsage getStkUsage = do - state <- getState - return $ cgs_stk_usg state + state <- getState + return $ cgs_stk_usg state setStkUsage :: StackUsage -> Code setStkUsage new_stk_usg = do - state <- getState - setState $ state {cgs_stk_usg = new_stk_usg} + state <- getState + setState $ state {cgs_stk_usg = new_stk_usg} getHpUsage :: FCode HeapUsage getHpUsage = do - state <- getState - return $ cgs_hp_usg state - + state <- getState + return $ cgs_hp_usg state + setHpUsage :: HeapUsage -> Code setHpUsage new_hp_usg = do - state <- getState - setState $ state {cgs_hp_usg = new_hp_usg} + state <- getState + setState $ state {cgs_hp_usg = new_hp_usg} getBinds :: FCode CgBindings getBinds = do - state <- getState - return $ cgs_binds state - + state <- getState + return $ cgs_binds state + setBinds :: CgBindings -> FCode () setBinds new_binds = do - state <- getState - setState $ state {cgs_binds = new_binds} + state <- getState + setState $ state {cgs_binds = new_binds} getStaticBinds :: FCode CgBindings getStaticBinds = do - info <- getInfoDown - return (cgd_statics info) + info <- getInfoDown + return (cgd_statics info) withState :: FCode a -> CgState -> FCode (a,CgState) withState (FCode fcode) newstate = FCode $ \info_down state -> - let (retval, state2) = fcode info_down newstate in ((retval,state2), state) + let (retval, state2) = fcode info_down newstate in ((retval,state2), state) newUniqSupply :: FCode UniqSupply newUniqSupply = do - state <- getState - let (us1, us2) = splitUniqSupply (cgs_uniqs state) - setState $ state { cgs_uniqs = us1 } - return us2 + state <- getState + let (us1, us2) = splitUniqSupply (cgs_uniqs state) + setState $ state { cgs_uniqs = us1 } + return us2 newUnique :: FCode Unique newUnique = do - us <- newUniqSupply - return (uniqFromSupply us) + us <- newUniqSupply + return (uniqFromSupply us) ------------------- getInfoDown :: FCode CgInfoDownwards getInfoDown = FCode $ \info_down state -> (info_down,state) @@ -536,14 +518,14 @@ doFCode (FCode fcode) info_down state = fcode info_down state %************************************************************************ -%* * - Forking -%* * +%* * + Forking +%* * %************************************************************************ @forkClosureBody@ takes a code, $c$, and compiles it in a completely fresh environment, except that: - - compilation info and statics are passed in unchanged. + - compilation info and statics are passed in unchanged. The current environment is passed on completely unaltered, except that abstract C from the fork is incorporated. @@ -560,86 +542,86 @@ bindings and usage information is otherwise unchanged. \begin{code} forkClosureBody :: Code -> Code forkClosureBody body_code - = do { info <- getInfoDown - ; us <- newUniqSupply - ; state <- getState - ; let body_info_down = info { cgd_eob = initEobInfo } - ((),fork_state) = doFCode body_code body_info_down - (initCgState us) - ; ASSERT( isNilOL (cgs_stmts fork_state) ) - setState $ state `addCodeBlocksFrom` fork_state } - + = do { info <- getInfoDown + ; us <- newUniqSupply + ; state <- getState + ; let body_info_down = info { cgd_eob = initEobInfo } + ((),fork_state) = doFCode body_code body_info_down + (initCgState us) + ; ASSERT( isNilOL (cgs_stmts fork_state) ) + setState $ state `addCodeBlocksFrom` fork_state } + forkStatics :: FCode a -> FCode a forkStatics body_code - = do { info <- getInfoDown - ; us <- newUniqSupply - ; state <- getState - ; let rhs_info_down = info { cgd_statics = cgs_binds state, - cgd_eob = initEobInfo } - (result, fork_state_out) = doFCode body_code rhs_info_down - (initCgState us) - ; ASSERT( isNilOL (cgs_stmts fork_state_out) ) - setState (state `addCodeBlocksFrom` fork_state_out) - ; return result } + = do { info <- getInfoDown + ; us <- newUniqSupply + ; state <- getState + ; let rhs_info_down = info { cgd_statics = cgs_binds state, + cgd_eob = initEobInfo } + (result, fork_state_out) = doFCode body_code rhs_info_down + (initCgState us) + ; ASSERT( isNilOL (cgs_stmts fork_state_out) ) + setState (state `addCodeBlocksFrom` fork_state_out) + ; return result } forkProc :: Code -> FCode CgStmts forkProc body_code - = do { info_down <- getInfoDown - ; us <- newUniqSupply - ; state <- getState - ; let fork_state_in = (initCgState us) - { cgs_binds = cgs_binds state, - cgs_stk_usg = cgs_stk_usg state, - cgs_hp_usg = cgs_hp_usg state } - -- ToDo: is the hp usage necesary? - (code_blks, fork_state_out) = doFCode (getCgStmts body_code) - info_down fork_state_in - ; setState $ state `stateIncUsageEval` fork_state_out - ; return code_blks } + = do { info_down <- getInfoDown + ; us <- newUniqSupply + ; state <- getState + ; let fork_state_in = (initCgState us) + { cgs_binds = cgs_binds state, + cgs_stk_usg = cgs_stk_usg state, + cgs_hp_usg = cgs_hp_usg state } + -- ToDo: is the hp usage necesary? + (code_blks, fork_state_out) = doFCode (getCgStmts body_code) + info_down fork_state_in + ; setState $ state `stateIncUsageEval` fork_state_out + ; return code_blks } -codeOnly :: Code -> Code -- Emit any code from the inner thing into the outer thing -- Do not affect anything else in the outer state -- Used in almost-circular code to prevent false loop dependencies +codeOnly :: Code -> Code codeOnly body_code - = do { info_down <- getInfoDown - ; us <- newUniqSupply - ; state <- getState - ; let fork_state_in = (initCgState us) { cgs_binds = cgs_binds state, - cgs_stk_usg = cgs_stk_usg state, - cgs_hp_usg = cgs_hp_usg state } - ((), fork_state_out) = doFCode body_code info_down fork_state_in - ; setState $ state `addCodeBlocksFrom` fork_state_out } + = do { info_down <- getInfoDown + ; us <- newUniqSupply + ; state <- getState + ; let fork_state_in = (initCgState us) { cgs_binds = cgs_binds state, + cgs_stk_usg = cgs_stk_usg state, + cgs_hp_usg = cgs_hp_usg state } + ((), fork_state_out) = doFCode body_code info_down fork_state_in + ; setState $ state `addCodeBlocksFrom` fork_state_out } \end{code} @forkAlts@ $bs~d$ takes fcodes $bs$ for the branches of a @case@, and an fcode for the default case $d$, and compiles each in the current environment. The current environment is passed on unmodified, except that - - the worst stack high-water mark is incorporated - - the virtual Hp is moved on to the worst virtual Hp for the branches + - the worst stack high-water mark is incorporated + - the virtual Hp is moved on to the worst virtual Hp for the branches \begin{code} forkAlts :: [FCode a] -> FCode [a] forkAlts branch_fcodes - = do { info_down <- getInfoDown - ; us <- newUniqSupply - ; state <- getState - ; let compile us branch - = (us2, doFCode branch info_down branch_state) - where - (us1,us2) = splitUniqSupply us - branch_state = (initCgState us1) { - cgs_binds = cgs_binds state, - cgs_stk_usg = cgs_stk_usg state, - cgs_hp_usg = cgs_hp_usg state } - - (_us, results) = mapAccumL compile us branch_fcodes - (branch_results, branch_out_states) = unzip results - ; setState $ foldl stateIncUsage state branch_out_states - -- NB foldl. state is the *left* argument to stateIncUsage - ; return branch_results } + = do { info_down <- getInfoDown + ; us <- newUniqSupply + ; state <- getState + ; let compile us branch + = (us2, doFCode branch info_down branch_state) + where + (us1,us2) = splitUniqSupply us + branch_state = (initCgState us1) { + cgs_binds = cgs_binds state, + cgs_stk_usg = cgs_stk_usg state, + cgs_hp_usg = cgs_hp_usg state } + + (_us, results) = mapAccumL compile us branch_fcodes + (branch_results, branch_out_states) = unzip results + ; setState $ foldl stateIncUsage state branch_out_states + -- NB foldl. state is the *left* argument to stateIncUsage + ; return branch_results } \end{code} @forkEval@ takes two blocks of code. @@ -659,43 +641,43 @@ usage. \begin{code} forkEval :: EndOfBlockInfo -- For the body - -> Code -- Code to set environment - -> FCode Sequel -- Semi-tagging info to store - -> FCode EndOfBlockInfo -- The new end of block info + -> Code -- Code to set environment + -> FCode Sequel -- Semi-tagging info to store + -> FCode EndOfBlockInfo -- The new end of block info forkEval body_eob_info env_code body_code = do { (v, sequel) <- forkEvalHelp body_eob_info env_code body_code - ; returnFC (EndOfBlockInfo v sequel) } + ; returnFC (EndOfBlockInfo v sequel) } forkEvalHelp :: EndOfBlockInfo -- For the body - -> Code -- Code to set environment - -> FCode a -- The code to do after the eval - -> FCode (VirtualSpOffset, -- Sp - a) -- Result of the FCode - -- A disturbingly complicated function + -> Code -- Code to set environment + -> FCode a -- The code to do after the eval + -> FCode (VirtualSpOffset, -- Sp + a) -- Result of the FCode + -- A disturbingly complicated function forkEvalHelp body_eob_info env_code body_code - = do { info_down <- getInfoDown - ; us <- newUniqSupply - ; state <- getState - ; let { info_down_for_body = info_down {cgd_eob = body_eob_info} - ; (_, env_state) = doFCode env_code info_down_for_body - (state {cgs_uniqs = us}) - ; state_for_body = (initCgState (cgs_uniqs env_state)) - { cgs_binds = binds_for_body, - cgs_stk_usg = stk_usg_for_body } - ; binds_for_body = nukeVolatileBinds (cgs_binds env_state) - ; stk_usg_from_env = cgs_stk_usg env_state - ; virtSp_from_env = virtSp stk_usg_from_env - ; stk_usg_for_body = stk_usg_from_env {realSp = virtSp_from_env, - hwSp = virtSp_from_env} - ; (value_returned, state_at_end_return) - = doFCode body_code info_down_for_body state_for_body - } - ; ASSERT( isNilOL (cgs_stmts state_at_end_return) ) - -- The code coming back should consist only of nested declarations, - -- notably of the return vector! - setState $ state `stateIncUsageEval` state_at_end_return - ; return (virtSp_from_env, value_returned) } + = do { info_down <- getInfoDown + ; us <- newUniqSupply + ; state <- getState + ; let { info_down_for_body = info_down {cgd_eob = body_eob_info} + ; (_, env_state) = doFCode env_code info_down_for_body + (state {cgs_uniqs = us}) + ; state_for_body = (initCgState (cgs_uniqs env_state)) + { cgs_binds = binds_for_body, + cgs_stk_usg = stk_usg_for_body } + ; binds_for_body = nukeVolatileBinds (cgs_binds env_state) + ; stk_usg_from_env = cgs_stk_usg env_state + ; virtSp_from_env = virtSp stk_usg_from_env + ; stk_usg_for_body = stk_usg_from_env {realSp = virtSp_from_env, + hwSp = virtSp_from_env} + ; (value_returned, state_at_end_return) + = doFCode body_code info_down_for_body state_for_body + } + ; ASSERT( isNilOL (cgs_stmts state_at_end_return) ) + -- The code coming back should consist only of nested declarations, + -- notably of the return vector! + setState $ state `stateIncUsageEval` state_at_end_return + ; return (virtSp_from_env, value_returned) } -- ---------------------------------------------------------------------------- @@ -720,10 +702,10 @@ newLabelC :: FCode BlockId newLabelC = do { u <- newUnique ; return $ mkBlockId u } -checkedAbsC :: CmmStmt -> Code -- Emit code, eliminating no-ops +checkedAbsC :: CmmStmt -> Code checkedAbsC stmt = emitStmts (if isNopStmt stmt then nilOL - else unitOL stmt) + else unitOL stmt) stmtsC :: [CmmStmt] -> Code stmtsC stmts = emitStmts (toOL stmts) @@ -739,37 +721,37 @@ forkLabelledCode code = getCgStmts code >>= forkCgStmts emitCgStmt :: CgStmt -> Code emitCgStmt stmt - = do { state <- getState - ; setState $ state { cgs_stmts = cgs_stmts state `snocOL` stmt } - } + = do { state <- getState + ; setState $ state { cgs_stmts = cgs_stmts state `snocOL` stmt } + } emitDecl :: CmmDecl -> Code emitDecl decl - = do { state <- getState - ; setState $ state { cgs_tops = cgs_tops state `snocOL` decl } } + = do { state <- getState + ; setState $ state { cgs_tops = cgs_tops state `snocOL` decl } } emitProc :: CmmInfo -> CLabel -> [CmmFormal] -> [CmmBasicBlock] -> Code emitProc info lbl [] blocks = do { let proc_block = CmmProc info lbl (ListGraph blocks) - ; state <- getState - ; setState $ state { cgs_tops = cgs_tops state `snocOL` proc_block } } + ; state <- getState + ; setState $ state { cgs_tops = cgs_tops state `snocOL` proc_block } } emitProc _ _ (_:_) _ = panic "emitProc called with nonempty args" -emitSimpleProc :: CLabel -> Code -> Code -- Emit a procedure whose body is the specified code; no info table +emitSimpleProc :: CLabel -> Code -> Code emitSimpleProc lbl code - = do { stmts <- getCgStmts code - ; blks <- cgStmtsToBlocks stmts - ; emitProc (CmmInfo Nothing Nothing CmmNonInfoTable) lbl [] blks } + = do { stmts <- getCgStmts code + ; blks <- cgStmtsToBlocks stmts + ; emitProc (CmmInfo Nothing Nothing CmmNonInfoTable) lbl [] blks } -getCmm :: Code -> FCode CmmGroup -- Get all the CmmTops (there should be no stmts) -- Return a single Cmm which may be split from other Cmms by -- object splitting (at a later stage) +getCmm :: Code -> FCode CmmGroup getCmm code - = do { state1 <- getState - ; ((), state2) <- withState code (state1 { cgs_tops = nilOL }) - ; setState $ state2 { cgs_tops = cgs_tops state1 } + = do { state1 <- getState + ; ((), state2) <- withState code (state1 { cgs_tops = nilOL }) + ; setState $ state2 { cgs_tops = cgs_tops state1 } ; return (fromOL (cgs_tops state2)) } @@ -783,31 +765,31 @@ getCmm code -- emit CgStmts into the current instruction stream emitCgStmts :: CgStmts -> Code emitCgStmts stmts - = do { state <- getState - ; setState $ state { cgs_stmts = cgs_stmts state `appOL` stmts } } + = do { state <- getState + ; setState $ state { cgs_stmts = cgs_stmts state `appOL` stmts } } -- emit CgStmts outside the current instruction stream, and return a label forkCgStmts :: CgStmts -> FCode BlockId forkCgStmts stmts = do { id <- newLabelC - ; emitCgStmt (CgFork id stmts) - ; return id - } + ; emitCgStmt (CgFork id stmts) + ; return id + } -- turn CgStmts into [CmmBasicBlock], for making a new proc. cgStmtsToBlocks :: CgStmts -> FCode [CmmBasicBlock] cgStmtsToBlocks stmts = do { id <- newLabelC - ; return (flattenCgStmts id stmts) - } + ; return (flattenCgStmts id stmts) + } -- collect the code emitted by an FCode computation getCgStmts' :: FCode a -> FCode (a, CgStmts) getCgStmts' fcode - = do { state1 <- getState - ; (a, state2) <- withState fcode (state1 { cgs_stmts = nilOL }) - ; setState $ state2 { cgs_stmts = cgs_stmts state1 } - ; return (a, cgs_stmts state2) } + = do { state1 <- getState + ; (a, state2) <- withState fcode (state1 { cgs_stmts = nilOL }) + ; setState $ state2 { cgs_stmts = cgs_stmts state1 } + ; return (a, cgs_stmts state2) } getCgStmts :: FCode a -> FCode CgStmts getCgStmts fcode = do { (_,stmts) <- getCgStmts' fcode; return stmts } @@ -832,14 +814,14 @@ getModuleName = do { info <- getInfoDown; return (cgd_mod info) } -- Get/set the end-of-block info setEndOfBlockInfo :: EndOfBlockInfo -> Code -> Code -setEndOfBlockInfo eob_info code = do - info <- getInfoDown - withInfoDown code (info {cgd_eob = eob_info}) +setEndOfBlockInfo eob_info code = do + info <- getInfoDown + withInfoDown code (info {cgd_eob = eob_info}) getEndOfBlockInfo :: FCode EndOfBlockInfo getEndOfBlockInfo = do - info <- getInfoDown - return (cgd_eob info) + info <- getInfoDown + return (cgd_eob info) -- ---------------------------------------------------------------------------- -- Get/set the current SRT label @@ -848,14 +830,14 @@ getEndOfBlockInfo = do -- bindings use sub-sections of this SRT. The label is passed down to -- the nested bindings via the monad. -getSRTLabel :: FCode CLabel -- Used only by cgPanic +getSRTLabel :: FCode CLabel -- Used only by cgPanic getSRTLabel = do info <- getInfoDown - return (cgd_srt_lbl info) + return (cgd_srt_lbl info) setSRTLabel :: CLabel -> FCode a -> FCode a setSRTLabel srt_lbl code = do info <- getInfoDown - withInfoDown code (info { cgd_srt_lbl = srt_lbl}) + withInfoDown code (info { cgd_srt_lbl = srt_lbl}) getSRT :: FCode SRT getSRT = do info <- getInfoDown @@ -871,11 +853,11 @@ setSRT srt code getTickyCtrLabel :: FCode CLabel getTickyCtrLabel = do - info <- getInfoDown - return (cgd_ticky info) + info <- getInfoDown + return (cgd_ticky info) setTickyCtrLabel :: CLabel -> Code -> Code setTickyCtrLabel ticky code = do - info <- getInfoDown - withInfoDown code (info {cgd_ticky = ticky}) + info <- getInfoDown + withInfoDown code (info {cgd_ticky = ticky}) \end{code} diff --git a/compiler/codeGen/CodeGen.lhs b/compiler/codeGen/CodeGen.lhs index 08af9715df..aa561c4f40 100644 --- a/compiler/codeGen/CodeGen.lhs +++ b/compiler/codeGen/CodeGen.lhs @@ -7,25 +7,19 @@ The Code Generator This module says how things get going at the top level. -@codeGen@ is the interface to the outside world. The \tr{cgTop*} +@codeGen@ is the interface to the outside world. The \tr{cgTop*} functions drive the mangling of top-level bindings. \begin{code} -{-# OPTIONS -fno-warn-tabs #-} --- The above warning supression flag is a temporary kludge. --- While working on this module you are encouraged to remove it and --- detab the module (please do the detabbing in a separate patch). See --- http://hackage.haskell.org/trac/ghc/wiki/Commentary/CodingStyle#TabsvsSpaces --- for details module CodeGen ( codeGen ) where #include "HsVersions.h" --- Kludge (??) so that CgExpr is reached via at least one non-SOURCE --- import. Before, that wasn't the case, and CM therefore didn't +-- Required so that CgExpr is reached via at least one non-SOURCE +-- import. Before, that wasn't the case, and CM therefore didn't -- bother to compile it. -import CgExpr ( {-NOTHING!-} ) -- DO NOT DELETE THIS IMPORT +import CgExpr ( {-NOTHING!-} ) -- DO NOT DELETE THIS IMPORT import CgProf import CgMonad import CgBindery @@ -51,39 +45,30 @@ import TyCon import Module import ErrUtils import Panic -\end{code} -\begin{code} codeGen :: DynFlags - -> Module - -> [TyCon] - -> CollectedCCs -- (Local/global) cost-centres needing declaring/registering. - -> [(StgBinding,[(Id,[Id])])] -- Bindings to convert, with SRTs - -> HpcInfo - -> IO [CmmGroup] -- Output - - -- N.B. returning '[Cmm]' and not 'Cmm' here makes it - -- possible for object splitting to split up the - -- pieces later. - -codeGen dflags this_mod data_tycons cost_centre_info stg_binds hpc_info - = do - { showPass dflags "CodeGen" - --- Why? --- ; mapM_ (\x -> seq x (return ())) data_tycons - - ; code_stuff <- initC dflags this_mod $ do - { cmm_binds <- mapM (getCmm . cgTopBinding dflags) stg_binds - ; cmm_tycons <- mapM cgTyCon data_tycons - ; cmm_init <- getCmm (mkModuleInit dflags cost_centre_info - this_mod hpc_info) - ; return (cmm_init : cmm_binds ++ cmm_tycons) - } - -- Put datatype_stuff after code_stuff, because the - -- datatype closure table (for enumeration types) to - -- (say) PrelBase_True_closure, which is defined in - -- code_stuff + -> Module -- Module we are compiling + -> [TyCon] -- Type constructors + -> CollectedCCs -- (Local/global) cost-centres needing declaring/registering. + -> [(StgBinding,[(Id,[Id])])] -- Bindings to convert, with SRTs + -> HpcInfo -- Profiling info + -> IO [CmmGroup] + -- N.B. returning '[Cmm]' and not 'Cmm' here makes it + -- possible for object splitting to split up the + -- pieces later. + +codeGen dflags this_mod data_tycons cost_centre_info stg_binds hpc_info = do + showPass dflags "CodeGen" + code_stuff <- + initC dflags this_mod $ do + cmm_binds <- mapM (getCmm . cgTopBinding dflags) stg_binds + cmm_tycons <- mapM cgTyCon data_tycons + cmm_init <- getCmm (mkModuleInit dflags cost_centre_info this_mod hpc_info) + return (cmm_init : cmm_binds ++ cmm_tycons) + -- Put datatype_stuff after code_stuff, because the + -- datatype closure table (for enumeration types) to + -- (say) PrelBase_True_closure, which is defined in + -- code_stuff -- Note [codegen-split-init] the cmm_init block must -- come FIRST. This is because when -split-objs is on @@ -91,24 +76,23 @@ codeGen dflags this_mod data_tycons cost_centre_info stg_binds hpc_info -- initialisation routines; see Note -- [pipeline-split-init]. - ; dumpIfSet_dyn dflags Opt_D_dump_cmm "Cmm" (pprCmms (targetPlatform dflags) code_stuff) - - ; return code_stuff } + dumpIfSet_dyn dflags Opt_D_dump_cmm "Cmm" (pprCmms (targetPlatform dflags) code_stuff) + return code_stuff mkModuleInit :: DynFlags - -> CollectedCCs -- cost centre info - -> Module + -> CollectedCCs -- cost centre info + -> Module -> HpcInfo - -> Code + -> Code mkModuleInit dflags cost_centre_info this_mod hpc_info - = do { -- Allocate the static boolean that records if this + = do { -- Allocate the static boolean that records if this ; whenC (opt_Hpc) $ hpcTable this_mod hpc_info - ; whenC (opt_SccProfilingOn) $ do - initCostCentres cost_centre_info + ; whenC (opt_SccProfilingOn) $ do + initCostCentres cost_centre_info -- For backwards compatibility: user code may refer to this -- label for calling hs_add_root(). @@ -133,15 +117,15 @@ initCostCentres :: CollectedCCs -> Code initCostCentres (local_CCs, ___extern_CCs, singleton_CCSs) | not opt_SccProfilingOn = nopC | otherwise - = do { mapM_ emitCostCentreDecl local_CCs - ; mapM_ emitCostCentreStackDecl singleton_CCSs + = do { mapM_ emitCostCentreDecl local_CCs + ; mapM_ emitCostCentreStackDecl singleton_CCSs } \end{code} %************************************************************************ -%* * +%* * \subsection[codegen-top-bindings]{Converting top-level STG bindings} -%* * +%* * %************************************************************************ @cgTopBinding@ is only used for top-level bindings, since they need @@ -157,45 +141,45 @@ variable. \begin{code} cgTopBinding :: DynFlags -> (StgBinding,[(Id,[Id])]) -> Code cgTopBinding dflags (StgNonRec id rhs, srts) - = do { id' <- maybeExternaliseId dflags id - ; mapM_ (mkSRT [id']) srts - ; (id,info) <- cgTopRhs id' rhs - ; addBindC id info -- Add the *un-externalised* Id to the envt, - -- so we find it when we look up occurrences - } + = do { id' <- maybeExternaliseId dflags id + ; mapM_ (mkSRT [id']) srts + ; (id,info) <- cgTopRhs id' rhs + ; addBindC id info -- Add the *un-externalised* Id to the envt, + -- so we find it when we look up occurrences + } cgTopBinding dflags (StgRec pairs, srts) - = do { let (bndrs, rhss) = unzip pairs - ; bndrs' <- mapFCs (maybeExternaliseId dflags) bndrs - ; let pairs' = zip bndrs' rhss - ; mapM_ (mkSRT bndrs') srts - ; _new_binds <- fixC (\ new_binds -> do - { addBindsC new_binds - ; mapFCs ( \ (b,e) -> cgTopRhs b e ) pairs' }) - ; nopC } + = do { let (bndrs, rhss) = unzip pairs + ; bndrs' <- mapFCs (maybeExternaliseId dflags) bndrs + ; let pairs' = zip bndrs' rhss + ; mapM_ (mkSRT bndrs') srts + ; _new_binds <- fixC (\ new_binds -> do + { addBindsC new_binds + ; mapFCs ( \ (b,e) -> cgTopRhs b e ) pairs' }) + ; nopC } mkSRT :: [Id] -> (Id,[Id]) -> Code mkSRT _ (_,[]) = nopC mkSRT these (id,ids) - = do { ids <- mapFCs remap ids - ; id <- remap id - ; emitRODataLits "CodeGen.mkSRT" (mkSRTLabel (idName id) (idCafInfo id)) - (map (\id -> CmmLabel $ mkClosureLabel (idName id) (idCafInfo id)) ids) - } + = do { ids <- mapFCs remap ids + ; id <- remap id + ; emitRODataLits "CodeGen.mkSRT" (mkSRTLabel (idName id) (idCafInfo id)) + (map (\id -> CmmLabel $ mkClosureLabel (idName id) (idCafInfo id)) ids) + } where - -- Sigh, better map all the ids against the environment in - -- case they've been externalised (see maybeExternaliseId below). + -- Sigh, better map all the ids against the environment in + -- case they've been externalised (see maybeExternaliseId below). remap id = case filter (==id) these of - (id':_) -> returnFC id' - [] -> do { info <- getCgIdInfo id; return (cgIdInfoId info) } + (id':_) -> returnFC id' + [] -> do { info <- getCgIdInfo id; return (cgIdInfoId info) } -- Urgh! I tried moving the forkStatics call from the rhss of cgTopRhs -- to enclose the listFCs in cgTopBinding, but that tickled the -- statics "error" call in initC. I DON'T UNDERSTAND WHY! cgTopRhs :: Id -> StgRhs -> FCode (Id, CgIdInfo) - -- The Id is passed along for setting up a binding... - -- It's already been externalised if necessary + -- The Id is passed along for setting up a binding... + -- It's already been externalised if necessary cgTopRhs bndr (StgRhsCon _cc con args) = forkStatics (cgTopRhsCon bndr con args) @@ -209,9 +193,9 @@ cgTopRhs bndr (StgRhsClosure cc bi fvs upd_flag srt args body) %************************************************************************ -%* * +%* * \subsection{Stuff to support splitting} -%* * +%* * %************************************************************************ If we're splitting the object, we need to externalise all the top-level names @@ -221,18 +205,18 @@ which refers to this name). \begin{code} maybeExternaliseId :: DynFlags -> Id -> FCode Id maybeExternaliseId dflags id - | dopt Opt_SplitObjs dflags, -- Externalise the name for -split-objs + | dopt Opt_SplitObjs dflags, -- Externalise the name for -split-objs isInternalName name = do { mod <- getModuleName - ; returnFC (setIdName id (externalise mod)) } - | otherwise = returnFC id + ; returnFC (setIdName id (externalise mod)) } + | otherwise = returnFC id where externalise mod = mkExternalName uniq mod new_occ loc name = idName id uniq = nameUnique name new_occ = mkLocalOcc uniq (nameOccName name) loc = nameSrcSpan name - -- We want to conjure up a name that can't clash with any - -- existing name. So we generate - -- Mod_$L243foo - -- where 243 is the unique. + -- We want to conjure up a name that can't clash with any + -- existing name. So we generate + -- Mod_$L243foo + -- where 243 is the unique. \end{code} |