module CLasH.Utils.GhcTools where
import qualified Monad
import qualified System.IO.Unsafe
import qualified Language.Haskell.TH as TH
import qualified Maybe
import qualified Annotations
import qualified CoreSyn
import qualified CoreUtils
import qualified DynFlags
import qualified HscTypes
import qualified GHC
import qualified Name
import qualified Serialized
import qualified Var
import qualified Outputable
import qualified Class
import CLasH.Utils.Pretty
import CLasH.Translator.TranslatorTypes
import CLasH.Translator.Annotations
import CLasH.Utils
listBindings :: FilePath -> [FilePath] -> IO ()
listBindings libdir filenames = do
(cores,_,_) <- loadModules libdir filenames Nothing
let binds = concatMap (CoreSyn.flattenBinds . HscTypes.cm_binds) cores
mapM listBinding binds
putStr "\n=========================\n"
let classes = concatMap (HscTypes.typeEnvClasses . HscTypes.cm_types) cores
mapM listClass classes
return ()
listBinding :: (CoreSyn.CoreBndr, CoreSyn.CoreExpr) -> IO ()
listBinding (b, e) = do
putStr "\nBinder: "
putStr $ show b ++ "[" ++ show (Var.varUnique b) ++ "]"
putStr "\nType of Binder: \n"
putStr $ Outputable.showSDoc $ Outputable.ppr $ Var.varType b
putStr "\n\nExpression: \n"
putStr $ prettyShow e
putStr "\n\n"
putStr $ Outputable.showSDoc $ Outputable.ppr e
putStr "\n\nType of Expression: \n"
putStr $ Outputable.showSDoc $ Outputable.ppr $ CoreUtils.exprType e
putStr "\n\n"
listClass :: Class.Class -> IO ()
listClass c = do
putStr "\nClass: "
putStr $ show (Class.className c)
putStr "\nSelectors: "
putStr $ show (Class.classSelIds c)
putStr "\n"
listBind :: FilePath -> [FilePath] -> String -> IO ()
listBind libdir filenames name = do
(cores,_,_) <- loadModules libdir filenames Nothing
bindings <- concatM $ mapM (findBinder (hasVarName name)) cores
mapM_ listBinding bindings
return ()
setDynFlag :: DynFlags.DynFlag -> GHC.Ghc ()
setDynFlag dflag = do
dflags <- GHC.getSessionDynFlags
let dflags' = DynFlags.dopt_set dflags dflag
GHC.setSessionDynFlags dflags'
return ()
unsafeRunGhc :: FilePath -> GHC.Ghc a -> a
unsafeRunGhc libDir m =
System.IO.Unsafe.unsafePerformIO $
GHC.runGhc (Just libDir) $ do
dflags <- GHC.getSessionDynFlags
GHC.setSessionDynFlags dflags
m
loadModules ::
FilePath
-> [String]
-> Maybe Finder
-> IO ( [HscTypes.CoreModule]
, HscTypes.HscEnv
, [EntitySpec]
)
loadModules libdir filenames finder =
GHC.defaultErrorHandler DynFlags.defaultDynFlags $
GHC.runGhc (Just libdir) $ do
dflags <- GHC.getSessionDynFlags
GHC.setSessionDynFlags dflags
cores <- mapM GHC.compileToCoreModule filenames
env <- GHC.getSession
specs <- case finder of
Nothing -> return []
Just f -> concatM $ mapM f cores
return (cores, env, specs)
findBinds ::
Monad m =>
(Var.Var -> m Bool)
-> HscTypes.CoreModule
-> m (Maybe [CoreSyn.CoreBndr])
findBinds criteria core = do
binders <- findBinder criteria core
case binders of
[] -> return Nothing
bndrs -> return $ Just $ map fst bndrs
findBind ::
Monad m =>
(Var.Var -> m Bool)
-> HscTypes.CoreModule
-> m (Maybe CoreSyn.CoreBndr)
findBind criteria core = do
binders <- findBinds criteria core
case binders of
Nothing -> return Nothing
(Just bndrs) -> return $ Just $ head bndrs
findExprs ::
Monad m =>
(Var.Var -> m Bool)
-> HscTypes.CoreModule
-> m (Maybe [CoreSyn.CoreExpr])
findExprs criteria core = do
binders <- findBinder criteria core
case binders of
[] -> return Nothing
bndrs -> return $ Just (map snd bndrs)
findExpr ::
Monad m =>
(Var.Var -> m Bool)
-> HscTypes.CoreModule
-> m (Maybe CoreSyn.CoreExpr)
findExpr criteria core = do
exprs <- findExprs criteria core
case exprs of
Nothing -> return Nothing
(Just exprs) -> return $ Just $ head exprs
findAnns ::
Monad m =>
(Var.Var -> m [CLasHAnn])
-> HscTypes.CoreModule
-> m [CLasHAnn]
findAnns criteria core = do
let binds = CoreSyn.flattenBinds $ HscTypes.cm_binds core
anns <- Monad.mapM (criteria . fst) binds
case anns of
[] -> return []
xs -> return $ concat xs
findBinder ::
Monad m =>
(Var.Var -> m Bool)
-> HscTypes.CoreModule
-> m [(CoreSyn.CoreBndr, CoreSyn.CoreExpr)]
findBinder criteria core = do
let binds = CoreSyn.flattenBinds $ HscTypes.cm_binds core
Monad.filterM (criteria . fst) binds
isCLasHAnnotation ::
GHC.GhcMonad m =>
(CLasHAnn -> Bool)
-> Var.Var
-> m [CLasHAnn]
isCLasHAnnotation clashAnn var = do
let deserializer = Serialized.deserializeWithData
let target = Annotations.NamedTarget (Var.varName var)
(anns :: [CLasHAnn]) <- GHC.findGlobalAnns deserializer target
let annEnts = filter clashAnn anns
return annEnts
hasCLasHAnnotation ::
GHC.GhcMonad m =>
(CLasHAnn -> Bool)
-> Var.Var
-> m Bool
hasCLasHAnnotation clashAnn var = do
anns <- isCLasHAnnotation clashAnn var
case anns of
[] -> return False
xs -> return True
hasVarName ::
Monad m =>
String
-> Var.Var
-> m Bool
hasVarName lookfor bind = return $ lookfor == Name.occNameString (Name.nameOccName $ Name.getName bind)
findInitStates ::
(Var.Var -> GHC.Ghc Bool) ->
(Var.Var -> GHC.Ghc [CLasHAnn]) ->
HscTypes.CoreModule ->
GHC.Ghc (Maybe [(CoreSyn.CoreBndr, CoreSyn.CoreBndr)])
findInitStates statec annsc mod = do
states <- findBinds statec mod
anns <- findAnns annsc mod
let funs = Maybe.catMaybes (map extractInits anns)
exprs' <- mapM (\x -> findBind (hasVarName (TH.nameBase x)) mod) funs
let exprs = Maybe.catMaybes exprs'
let inits = zipMWith (\a b -> (a,b)) states exprs
return inits
where
extractInits :: CLasHAnn -> Maybe TH.Name
extractInits (InitState x) = Just x
extractInits _ = Nothing
zipMWith :: (a -> b -> c) -> (Maybe [a]) -> [b] -> (Maybe [c])
zipMWith _ Nothing _ = Nothing
zipMWith f (Just as) bs = Just $ zipWith f as bs
findSpec ::
(Var.Var -> GHC.Ghc Bool) -> (Var.Var -> GHC.Ghc Bool) -> (Var.Var -> GHC.Ghc [CLasHAnn]) -> (Var.Var -> GHC.Ghc Bool)
-> Finder
findSpec topc statec annsc testc mod = do
top <- findBind topc mod
state <- findExprs statec mod
anns <- findAnns annsc mod
test <- findExpr testc mod
inits <- findInitStates statec annsc mod
return [(top, inits, test)]