module GHC.StgToCmm ( codeGen ) where
#include "HsVersions.h"
import GhcPrelude as Prelude
import GHC.StgToCmm.Prof (initCostCentres, ldvEnter)
import GHC.StgToCmm.Monad
import GHC.StgToCmm.Env
import GHC.StgToCmm.Bind
import GHC.StgToCmm.DataCon
import GHC.StgToCmm.Layout
import GHC.StgToCmm.Utils
import GHC.StgToCmm.Closure
import GHC.StgToCmm.Hpc
import GHC.StgToCmm.Ticky
import Cmm
import CmmUtils
import CLabel
import StgSyn
import DynFlags
import ErrUtils
import HscTypes
import CostCentre
import Id
import IdInfo
import RepType
import DataCon
import TyCon
import Module
import Outputable
import Stream
import BasicTypes
import VarSet ( isEmptyDVarSet )
import OrdList
import MkGraph
import Data.IORef
import Control.Monad (when,void)
import Util
codeGen :: DynFlags
-> Module
-> [TyCon]
-> CollectedCCs
-> [CgStgTopBinding]
-> HpcInfo
-> Stream IO CmmGroup ()
codeGen dflags this_mod data_tycons
cost_centre_info stg_binds hpc_info
= do {
; cgref <- liftIO $ newIORef =<< initC
; let cg :: FCode () -> Stream IO CmmGroup ()
cg fcode = do
cmm <- liftIO . withTimingSilent dflags (text "STG -> Cmm") (`seq` ()) $ do
st <- readIORef cgref
let (a,st') = runC dflags this_mod st (getCmm fcode)
writeIORef cgref $! st'{ cgs_tops = nilOL,
cgs_stmts = mkNop }
return a
yield cmm
; cg (mkModuleInit cost_centre_info this_mod hpc_info)
; mapM_ (cg . cgTopBinding dflags) stg_binds
; let do_tycon tycon = do
when (isEnumerationTyCon tycon) $ cg (cgEnumerationTyCon tycon)
mapM_ (cg . cgDataCon) (tyConDataCons tycon)
; mapM_ do_tycon data_tycons
}
cgTopBinding :: DynFlags -> CgStgTopBinding -> FCode ()
cgTopBinding dflags (StgTopLifted (StgNonRec id rhs))
= do { let (info, fcode) = cgTopRhs dflags NonRecursive id rhs
; fcode
; addBindC info
}
cgTopBinding dflags (StgTopLifted (StgRec pairs))
= do { let (bndrs, rhss) = unzip pairs
; let pairs' = zip bndrs rhss
r = unzipWith (cgTopRhs dflags Recursive) pairs'
(infos, fcodes) = unzip r
; addBindsC infos
; sequence_ fcodes
}
cgTopBinding dflags (StgTopStringLit id str)
= do { let label = mkBytesLabel (idName id)
; let (lit, decl) = mkByteStringCLit label str
; emitDecl decl
; addBindC (litIdInfo dflags id mkLFStringLit lit)
}
cgTopRhs :: DynFlags -> RecFlag -> Id -> CgStgRhs -> (CgIdInfo, FCode ())
cgTopRhs dflags _rec bndr (StgRhsCon _cc con args)
= cgTopRhsCon dflags bndr con (assertNonVoidStgArgs args)
cgTopRhs dflags rec bndr (StgRhsClosure fvs cc upd_flag args body)
= ASSERT(isEmptyDVarSet fvs)
cgTopRhsClosure dflags rec bndr cc upd_flag args body
mkModuleInit
:: CollectedCCs
-> Module
-> HpcInfo
-> FCode ()
mkModuleInit cost_centre_info this_mod hpc_info
= do { initHpc this_mod hpc_info
; initCostCentres cost_centre_info
}
cgEnumerationTyCon :: TyCon -> FCode ()
cgEnumerationTyCon tycon
= do dflags <- getDynFlags
emitRODataLits (mkLocalClosureTableLabel (tyConName tycon) NoCafRefs)
[ CmmLabelOff (mkLocalClosureLabel (dataConName con) NoCafRefs)
(tagForCon dflags con)
| con <- tyConDataCons tycon]
cgDataCon :: DataCon -> FCode ()
cgDataCon data_con
= do { dflags <- getDynFlags
; let
(tot_wds,
ptr_wds)
= mkVirtConstrSizes dflags arg_reps
nonptr_wds = tot_wds ptr_wds
dyn_info_tbl =
mkDataConInfoTable dflags data_con False ptr_wds nonptr_wds
arg_reps :: [NonVoid PrimRep]
arg_reps = [ NonVoid rep_ty
| ty <- dataConRepArgTys data_con
, rep_ty <- typePrimRep ty
, not (isVoidRep rep_ty) ]
; emitClosureAndInfoTable dyn_info_tbl NativeDirectCall [] $
do { tickyEnterDynCon
; ldvEnter (CmmReg nodeReg)
; tickyReturnOldCon (length arg_reps)
; void $ emitReturn [cmmOffsetB dflags (CmmReg nodeReg) (tagForCon dflags data_con)]
}
}