{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE TypeFamilies #-}
module GHC.Stg.Pipeline
( StgPipelineOpts (..)
, StgToDo (..)
, stg2stg
, StgCgInfos
) where
import GHC.Prelude
import GHC.Driver.Flags
import GHC.Stg.Syntax
import GHC.Stg.Lint ( lintStgTopBindings )
import GHC.Stg.Stats ( showStgStats )
import GHC.Stg.FVs ( depSortWithAnnotStgPgm )
import GHC.Stg.Unarise ( unarise )
import GHC.Stg.BcPrep ( bcPrep )
import GHC.Stg.CSE ( stgCse )
import GHC.Stg.Lift ( StgLiftConfig, stgLiftLams )
import GHC.Unit.Module ( Module )
import GHC.Core.DataCon (DataCon)
import GHC.Utils.Error
import GHC.Types.Var
import GHC.Types.Var.Set
import GHC.Types.Unique.Supply
import GHC.Utils.Outputable
import GHC.Utils.Logger
import Control.Monad
import Control.Monad.IO.Class
import Control.Monad.Trans.Reader
import GHC.Settings (Platform)
import GHC.Stg.EnforceEpt (enforceEpt)
import GHC.Stg.EnforceEpt.TagSig ( StgCgInfos )
data StgPipelineOpts = StgPipelineOpts
{ StgPipelineOpts -> [StgToDo]
stgPipeline_phases :: ![StgToDo]
, StgPipelineOpts -> Maybe DiagOpts
stgPipeline_lint :: !(Maybe DiagOpts)
, StgPipelineOpts -> StgPprOpts
stgPipeline_pprOpts :: !StgPprOpts
, StgPipelineOpts -> Platform
stgPlatform :: !Platform
, StgPipelineOpts -> Bool
stgPipeline_forBytecode :: !Bool
, StgPipelineOpts -> Module -> DataCon -> [StgArg] -> Bool
stgPipeline_allowTopLevelConApp :: Module -> DataCon -> [StgArg] -> Bool
}
newtype StgM a = StgM { forall a. StgM a -> ReaderT Char IO a
_unStgM :: ReaderT Char IO a }
deriving ((forall a b. (a -> b) -> StgM a -> StgM b)
-> (forall a b. a -> StgM b -> StgM a) -> Functor StgM
forall a b. a -> StgM b -> StgM a
forall a b. (a -> b) -> StgM a -> StgM b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
$cfmap :: forall a b. (a -> b) -> StgM a -> StgM b
fmap :: forall a b. (a -> b) -> StgM a -> StgM b
$c<$ :: forall a b. a -> StgM b -> StgM a
<$ :: forall a b. a -> StgM b -> StgM a
Functor, Functor StgM
Functor StgM =>
(forall a. a -> StgM a)
-> (forall a b. StgM (a -> b) -> StgM a -> StgM b)
-> (forall a b c. (a -> b -> c) -> StgM a -> StgM b -> StgM c)
-> (forall a b. StgM a -> StgM b -> StgM b)
-> (forall a b. StgM a -> StgM b -> StgM a)
-> Applicative StgM
forall a. a -> StgM a
forall a b. StgM a -> StgM b -> StgM a
forall a b. StgM a -> StgM b -> StgM b
forall a b. StgM (a -> b) -> StgM a -> StgM b
forall a b c. (a -> b -> c) -> StgM a -> StgM b -> StgM c
forall (f :: * -> *).
Functor f =>
(forall a. a -> f a)
-> (forall a b. f (a -> b) -> f a -> f b)
-> (forall a b c. (a -> b -> c) -> f a -> f b -> f c)
-> (forall a b. f a -> f b -> f b)
-> (forall a b. f a -> f b -> f a)
-> Applicative f
$cpure :: forall a. a -> StgM a
pure :: forall a. a -> StgM a
$c<*> :: forall a b. StgM (a -> b) -> StgM a -> StgM b
<*> :: forall a b. StgM (a -> b) -> StgM a -> StgM b
$cliftA2 :: forall a b c. (a -> b -> c) -> StgM a -> StgM b -> StgM c
liftA2 :: forall a b c. (a -> b -> c) -> StgM a -> StgM b -> StgM c
$c*> :: forall a b. StgM a -> StgM b -> StgM b
*> :: forall a b. StgM a -> StgM b -> StgM b
$c<* :: forall a b. StgM a -> StgM b -> StgM a
<* :: forall a b. StgM a -> StgM b -> StgM a
Applicative, Applicative StgM
Applicative StgM =>
(forall a b. StgM a -> (a -> StgM b) -> StgM b)
-> (forall a b. StgM a -> StgM b -> StgM b)
-> (forall a. a -> StgM a)
-> Monad StgM
forall a. a -> StgM a
forall a b. StgM a -> StgM b -> StgM b
forall a b. StgM a -> (a -> StgM b) -> StgM b
forall (m :: * -> *).
Applicative m =>
(forall a b. m a -> (a -> m b) -> m b)
-> (forall a b. m a -> m b -> m b)
-> (forall a. a -> m a)
-> Monad m
$c>>= :: forall a b. StgM a -> (a -> StgM b) -> StgM b
>>= :: forall a b. StgM a -> (a -> StgM b) -> StgM b
$c>> :: forall a b. StgM a -> StgM b -> StgM b
>> :: forall a b. StgM a -> StgM b -> StgM b
$creturn :: forall a. a -> StgM a
return :: forall a. a -> StgM a
Monad, Monad StgM
Monad StgM => (forall a. IO a -> StgM a) -> MonadIO StgM
forall a. IO a -> StgM a
forall (m :: * -> *).
Monad m =>
(forall a. IO a -> m a) -> MonadIO m
$cliftIO :: forall a. IO a -> StgM a
liftIO :: forall a. IO a -> StgM a
MonadIO)
instance MonadUnique StgM where
getUniqueSupplyM :: StgM UniqSupply
getUniqueSupplyM = ReaderT Char IO UniqSupply -> StgM UniqSupply
forall a. ReaderT Char IO a -> StgM a
StgM (ReaderT Char IO UniqSupply -> StgM UniqSupply)
-> ReaderT Char IO UniqSupply -> StgM UniqSupply
forall a b. (a -> b) -> a -> b
$ do { tag <- ReaderT Char IO Char
forall (m :: * -> *) r. Monad m => ReaderT r m r
ask
; liftIO $! mkSplitUniqSupply tag}
getUniqueM :: StgM Unique
getUniqueM = ReaderT Char IO Unique -> StgM Unique
forall a. ReaderT Char IO a -> StgM a
StgM (ReaderT Char IO Unique -> StgM Unique)
-> ReaderT Char IO Unique -> StgM Unique
forall a b. (a -> b) -> a -> b
$ do { tag <- ReaderT Char IO Char
forall (m :: * -> *) r. Monad m => ReaderT r m r
ask
; liftIO $! uniqFromTag tag}
runStgM :: Char -> StgM a -> IO a
runStgM :: forall a. Char -> StgM a -> IO a
runStgM Char
mask (StgM ReaderT Char IO a
m) = ReaderT Char IO a -> Char -> IO a
forall r (m :: * -> *) a. ReaderT r m a -> r -> m a
runReaderT ReaderT Char IO a
m Char
mask
stg2stg :: Logger
-> [Var]
-> StgPipelineOpts
-> Module
-> [StgTopBinding]
-> IO ([(CgStgTopBinding,IdSet)], StgCgInfos)
stg2stg :: Logger
-> [Id]
-> StgPipelineOpts
-> Module
-> [StgTopBinding]
-> IO ([(CgStgTopBinding, IdSet)], StgCgInfos)
stg2stg Logger
logger [Id]
extra_vars StgPipelineOpts
opts Module
this_mod [StgTopBinding]
binds
= do { DumpFlag -> String -> [StgTopBinding] -> IO ()
dump_when DumpFlag
Opt_D_dump_stg_from_core String
"Initial STG:" [StgTopBinding]
binds
; Bool -> String -> [StgTopBinding] -> IO ()
forall (a :: StgPass).
(BinderP a ~ Id, OutputablePass a) =>
Bool -> String -> [GenStgTopBinding a] -> IO ()
stg_linter Bool
False String
"StgFromCore" [StgTopBinding]
binds
; Logger -> String -> IO ()
showPass Logger
logger String
"Stg2Stg"
; binds' <- Char -> StgM [StgTopBinding] -> IO [StgTopBinding]
forall a. Char -> StgM a -> IO a
runStgM Char
'g' (StgM [StgTopBinding] -> IO [StgTopBinding])
-> StgM [StgTopBinding] -> IO [StgTopBinding]
forall a b. (a -> b) -> a -> b
$
([StgTopBinding] -> StgToDo -> StgM [StgTopBinding])
-> [StgTopBinding] -> [StgToDo] -> StgM [StgTopBinding]
forall (t :: * -> *) (m :: * -> *) b a.
(Foldable t, Monad m) =>
(b -> a -> m b) -> b -> t a -> m b
foldM (Module -> [StgTopBinding] -> StgToDo -> StgM [StgTopBinding]
do_stg_pass Module
this_mod) [StgTopBinding]
binds (StgPipelineOpts -> [StgToDo]
stgPipeline_phases StgPipelineOpts
opts)
; let (binds_sorted_with_fvs, imp_fvs) = unzip (depSortWithAnnotStgPgm this_mod binds')
; (cg_binds, cg_infos) <- enforceEpt (stgPipeline_pprOpts opts) (stgPipeline_forBytecode opts) logger this_mod binds_sorted_with_fvs
; stg_linter False "StgCodeGen" cg_binds
; pure (zip cg_binds imp_fvs, cg_infos)
}
where
stg_linter :: (BinderP a ~ Id, OutputablePass a) => Bool -> String -> [GenStgTopBinding a] -> IO ()
stg_linter :: forall (a :: StgPass).
(BinderP a ~ Id, OutputablePass a) =>
Bool -> String -> [GenStgTopBinding a] -> IO ()
stg_linter Bool
unarised
| Just DiagOpts
diag_opts <- StgPipelineOpts -> Maybe DiagOpts
stgPipeline_lint StgPipelineOpts
opts
= Platform
-> Logger
-> DiagOpts
-> StgPprOpts
-> [Id]
-> Module
-> Bool
-> String
-> [GenStgTopBinding a]
-> IO ()
forall (a :: StgPass).
(OutputablePass a, BinderP a ~ Id) =>
Platform
-> Logger
-> DiagOpts
-> StgPprOpts
-> [Id]
-> Module
-> Bool
-> String
-> [GenStgTopBinding a]
-> IO ()
lintStgTopBindings
(StgPipelineOpts -> Platform
stgPlatform StgPipelineOpts
opts) Logger
logger
DiagOpts
diag_opts StgPprOpts
ppr_opts
[Id]
extra_vars Module
this_mod Bool
unarised
| Bool
otherwise
= \ String
_whodunit [GenStgTopBinding a]
_binds -> () -> IO ()
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
do_stg_pass :: Module -> [StgTopBinding] -> StgToDo -> StgM [StgTopBinding]
do_stg_pass :: Module -> [StgTopBinding] -> StgToDo -> StgM [StgTopBinding]
do_stg_pass Module
this_mod [StgTopBinding]
binds StgToDo
to_do
= case StgToDo
to_do of
StgToDo
StgDoNothing ->
[StgTopBinding] -> StgM [StgTopBinding]
forall a. a -> StgM a
forall (m :: * -> *) a. Monad m => a -> m a
return [StgTopBinding]
binds
StgToDo
StgStats ->
Logger
-> String -> SDoc -> StgM [StgTopBinding] -> StgM [StgTopBinding]
forall a. Logger -> String -> SDoc -> a -> a
logTraceMsg Logger
logger String
"STG stats" (String -> SDoc
forall doc. IsLine doc => String -> doc
text ([StgTopBinding] -> String
showStgStats [StgTopBinding]
binds)) ([StgTopBinding] -> StgM [StgTopBinding]
forall a. a -> StgM a
forall (m :: * -> *) a. Monad m => a -> m a
return [StgTopBinding]
binds)
StgToDo
StgCSE -> do
let binds' :: [StgTopBinding]
binds' = {-# SCC "StgCse" #-} [StgTopBinding] -> [StgTopBinding]
stgCse [StgTopBinding]
binds
String -> [StgTopBinding] -> StgM [StgTopBinding]
end_pass String
"StgCse" [StgTopBinding]
binds'
StgLiftLams StgLiftConfig
cfg -> do
us <- StgM UniqSupply
forall (m :: * -> *). MonadUnique m => m UniqSupply
getUniqueSupplyM
let binds' = {-# SCC "StgLiftLams" #-} Module
-> StgLiftConfig
-> UniqSupply
-> [StgTopBinding]
-> [StgTopBinding]
stgLiftLams Module
this_mod StgLiftConfig
cfg UniqSupply
us [StgTopBinding]
binds
end_pass "StgLiftLams" binds'
StgToDo
StgBcPrep -> do
us <- StgM UniqSupply
forall (m :: * -> *). MonadUnique m => m UniqSupply
getUniqueSupplyM
let binds' = {-# SCC "StgBcPrep" #-} UniqSupply -> [StgTopBinding] -> [StgTopBinding]
bcPrep UniqSupply
us [StgTopBinding]
binds
end_pass "StgBcPrep" binds'
StgToDo
StgUnarise -> do
us <- StgM UniqSupply
forall (m :: * -> *). MonadUnique m => m UniqSupply
getUniqueSupplyM
liftIO (stg_linter False "Pre-unarise" binds)
let binds' = {-# SCC "StgUnarise" #-} UniqSupply
-> (DataCon -> [StgArg] -> Bool)
-> [StgTopBinding]
-> [StgTopBinding]
unarise UniqSupply
us (StgPipelineOpts -> Module -> DataCon -> [StgArg] -> Bool
stgPipeline_allowTopLevelConApp StgPipelineOpts
opts Module
this_mod) [StgTopBinding]
binds
liftIO (dump_when Opt_D_dump_stg_unarised "Unarised STG:" binds')
liftIO (stg_linter True "Unarise" binds')
return binds'
ppr_opts :: StgPprOpts
ppr_opts = StgPipelineOpts -> StgPprOpts
stgPipeline_pprOpts StgPipelineOpts
opts
dump_when :: DumpFlag -> String -> [StgTopBinding] -> IO ()
dump_when DumpFlag
flag String
header [StgTopBinding]
binds
= Logger -> DumpFlag -> String -> DumpFormat -> SDoc -> IO ()
putDumpFileMaybe Logger
logger DumpFlag
flag String
header DumpFormat
FormatSTG (StgPprOpts -> [StgTopBinding] -> SDoc
forall (pass :: StgPass).
OutputablePass pass =>
StgPprOpts -> [GenStgTopBinding pass] -> SDoc
pprStgTopBindings StgPprOpts
ppr_opts [StgTopBinding]
binds)
end_pass :: String -> [StgTopBinding] -> StgM [StgTopBinding]
end_pass String
what [StgTopBinding]
binds2
= IO [StgTopBinding] -> StgM [StgTopBinding]
forall a. IO a -> StgM a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO [StgTopBinding] -> StgM [StgTopBinding])
-> IO [StgTopBinding] -> StgM [StgTopBinding]
forall a b. (a -> b) -> a -> b
$ do
Logger -> DumpFlag -> String -> DumpFormat -> SDoc -> IO ()
putDumpFileMaybe Logger
logger DumpFlag
Opt_D_verbose_stg2stg String
what
DumpFormat
FormatSTG ([SDoc] -> SDoc
forall doc. IsDoc doc => [doc] -> doc
vcat ((StgTopBinding -> SDoc) -> [StgTopBinding] -> [SDoc]
forall a b. (a -> b) -> [a] -> [b]
map (StgPprOpts -> StgTopBinding -> SDoc
forall (pass :: StgPass).
OutputablePass pass =>
StgPprOpts -> GenStgTopBinding pass -> SDoc
pprStgTopBinding StgPprOpts
ppr_opts) [StgTopBinding]
binds2))
Bool -> String -> [StgTopBinding] -> IO ()
forall (a :: StgPass).
(BinderP a ~ Id, OutputablePass a) =>
Bool -> String -> [GenStgTopBinding a] -> IO ()
stg_linter Bool
False String
what [StgTopBinding]
binds2
[StgTopBinding] -> IO [StgTopBinding]
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return [StgTopBinding]
binds2
data StgToDo
= StgCSE
| StgLiftLams StgLiftConfig
| StgStats
| StgUnarise
| StgBcPrep
| StgDoNothing
deriving (Int -> StgToDo -> ShowS
[StgToDo] -> ShowS
StgToDo -> String
(Int -> StgToDo -> ShowS)
-> (StgToDo -> String) -> ([StgToDo] -> ShowS) -> Show StgToDo
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> StgToDo -> ShowS
showsPrec :: Int -> StgToDo -> ShowS
$cshow :: StgToDo -> String
show :: StgToDo -> String
$cshowList :: [StgToDo] -> ShowS
showList :: [StgToDo] -> ShowS
Show, ReadPrec [StgToDo]
ReadPrec StgToDo
Int -> ReadS StgToDo
ReadS [StgToDo]
(Int -> ReadS StgToDo)
-> ReadS [StgToDo]
-> ReadPrec StgToDo
-> ReadPrec [StgToDo]
-> Read StgToDo
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
$creadsPrec :: Int -> ReadS StgToDo
readsPrec :: Int -> ReadS StgToDo
$creadList :: ReadS [StgToDo]
readList :: ReadS [StgToDo]
$creadPrec :: ReadPrec StgToDo
readPrec :: ReadPrec StgToDo
$creadListPrec :: ReadPrec [StgToDo]
readListPrec :: ReadPrec [StgToDo]
Read, StgToDo -> StgToDo -> Bool
(StgToDo -> StgToDo -> Bool)
-> (StgToDo -> StgToDo -> Bool) -> Eq StgToDo
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: StgToDo -> StgToDo -> Bool
== :: StgToDo -> StgToDo -> Bool
$c/= :: StgToDo -> StgToDo -> Bool
/= :: StgToDo -> StgToDo -> Bool
Eq, Eq StgToDo
Eq StgToDo =>
(StgToDo -> StgToDo -> Ordering)
-> (StgToDo -> StgToDo -> Bool)
-> (StgToDo -> StgToDo -> Bool)
-> (StgToDo -> StgToDo -> Bool)
-> (StgToDo -> StgToDo -> Bool)
-> (StgToDo -> StgToDo -> StgToDo)
-> (StgToDo -> StgToDo -> StgToDo)
-> Ord StgToDo
StgToDo -> StgToDo -> Bool
StgToDo -> StgToDo -> Ordering
StgToDo -> StgToDo -> StgToDo
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: StgToDo -> StgToDo -> Ordering
compare :: StgToDo -> StgToDo -> Ordering
$c< :: StgToDo -> StgToDo -> Bool
< :: StgToDo -> StgToDo -> Bool
$c<= :: StgToDo -> StgToDo -> Bool
<= :: StgToDo -> StgToDo -> Bool
$c> :: StgToDo -> StgToDo -> Bool
> :: StgToDo -> StgToDo -> Bool
$c>= :: StgToDo -> StgToDo -> Bool
>= :: StgToDo -> StgToDo -> Bool
$cmax :: StgToDo -> StgToDo -> StgToDo
max :: StgToDo -> StgToDo -> StgToDo
$cmin :: StgToDo -> StgToDo -> StgToDo
min :: StgToDo -> StgToDo -> StgToDo
Ord)