module VectMonad (
+ Scope(..),
VM,
- noV, tryV, maybeV, orElseV, localV, initV,
- newLocalVar, newTyVar,
+ noV, tryV, maybeV, orElseV, fixV, localV, closedV, initV,
+ cloneName, newExportedVar, newLocalVar, newDummyVar, newTyVar,
- Builtins(..),
+ Builtins(..), paDictTyCon, paDictDataCon,
builtin,
GlobalEnv(..),
+ setInstEnvs,
readGEnv, setGEnv, updGEnv,
LocalEnv(..),
readLEnv, setLEnv, updLEnv,
- lookupTyCon, extendTyVarPA
+ lookupVar, defGlobalVar,
+ lookupTyCon, defTyCon,
+ lookupDataCon, defDataCon,
+ lookupTyVarPA, defLocalTyVar, defLocalTyVarWithPA, localTyVars,
+
+ lookupInst, lookupFamInst
) where
#include "HsVersions.h"
import HscTypes
import CoreSyn
+import Class
import TyCon
+import DataCon
import Type
import Var
import VarEnv
import Id
+import OccName
import Name
import NameEnv
import DsMonad
import PrelNames
+import InstEnv
+import FamInstEnv
+
+import Panic
+import Outputable
import FastString
+import SrcLoc ( noSrcSpan )
+
+import Control.Monad ( liftM )
+
+data Scope a b = Global a | Local b
-- ----------------------------------------------------------------------------
-- Vectorisation monad
data Builtins = Builtins {
parrayTyCon :: TyCon
- , paTyCon :: TyCon
+ , paClass :: Class
, closureTyCon :: TyCon
, mkClosureVar :: Var
, applyClosureVar :: Var
, mkClosurePVar :: Var
, applyClosurePVar :: Var
- , closurePAVar :: Var
, lengthPAVar :: Var
, replicatePAVar :: Var
+ , emptyPAVar :: Var
}
+paDictTyCon :: Builtins -> TyCon
+paDictTyCon = classTyCon . paClass
+
+paDictDataCon :: Builtins -> DataCon
+paDictDataCon = classDataCon . paClass
+
initBuiltins :: DsM Builtins
initBuiltins
= do
parrayTyCon <- dsLookupTyCon parrayTyConName
- paTyCon <- dsLookupTyCon paTyConName
+ paClass <- dsLookupClass paClassName
closureTyCon <- dsLookupTyCon closureTyConName
mkClosureVar <- dsLookupGlobalId mkClosureName
applyClosureVar <- dsLookupGlobalId applyClosureName
mkClosurePVar <- dsLookupGlobalId mkClosurePName
applyClosurePVar <- dsLookupGlobalId applyClosurePName
- closurePAVar <- dsLookupGlobalId closurePAName
lengthPAVar <- dsLookupGlobalId lengthPAName
replicatePAVar <- dsLookupGlobalId replicatePAName
+ emptyPAVar <- dsLookupGlobalId emptyPAName
return $ Builtins {
parrayTyCon = parrayTyCon
- , paTyCon = paTyCon
+ , paClass = paClass
, closureTyCon = closureTyCon
, mkClosureVar = mkClosureVar
, applyClosureVar = applyClosureVar
, mkClosurePVar = mkClosurePVar
, applyClosurePVar = applyClosurePVar
- , closurePAVar = closurePAVar
, lengthPAVar = lengthPAVar
, replicatePAVar = replicatePAVar
+ , emptyPAVar = emptyPAVar
}
data GlobalEnv = GlobalEnv {
--
, global_tycons :: NameEnv TyCon
- -- Mapping from TyCons to their PA dictionaries
+ -- Mapping from DataCons to their vectorised versions
--
- , global_tycon_pa :: NameEnv CoreExpr
+ , global_datacons :: NameEnv DataCon
+
+ -- External package inst-env & home-package inst-env for class
+ -- instances
+ --
+ , global_inst_env :: (InstEnv, InstEnv)
+
+ -- External package inst-env & home-package inst-env for family
+ -- instances
+ --
+ , global_fam_inst_env :: FamInstEnvs
+
+ -- Hoisted bindings
+ , global_bindings :: [(Var, CoreExpr)]
}
data LocalEnv = LocalEnv {
--
local_vars :: VarEnv (CoreExpr, CoreExpr)
+ -- In-scope type variables
+ --
+ , local_tyvars :: [TyVar]
+
-- Mapping from tyvars to their PA dictionaries
, local_tyvar_pa :: VarEnv CoreExpr
}
-initGlobalEnv :: VectInfo -> GlobalEnv
-initGlobalEnv info
+initGlobalEnv :: VectInfo -> (InstEnv, InstEnv) -> FamInstEnvs -> Builtins -> GlobalEnv
+initGlobalEnv info instEnvs famInstEnvs bi
= GlobalEnv {
- global_vars = mapVarEnv (Var . snd) $ vectInfoCCVar info
+ global_vars = mapVarEnv (Var . snd) $ vectInfoVar info
, global_exported_vars = emptyVarEnv
- , global_tycons = mapNameEnv snd $ vectInfoCCTyCon info
- , global_tycon_pa = emptyNameEnv
+ , global_tycons = extendNameEnv (mapNameEnv snd (vectInfoTyCon info))
+ (tyConName funTyCon) (closureTyCon bi)
+
+ , global_datacons = mapNameEnv snd $ vectInfoDataCon info
+ , global_inst_env = instEnvs
+ , global_fam_inst_env = famInstEnvs
+ , global_bindings = []
}
+setInstEnvs :: InstEnv -> FamInstEnv -> GlobalEnv -> GlobalEnv
+setInstEnvs l_inst l_fam_inst genv
+ | (g_inst, _) <- global_inst_env genv
+ , (g_fam_inst, _) <- global_fam_inst_env genv
+ = genv { global_inst_env = (g_inst, l_inst)
+ , global_fam_inst_env = (g_fam_inst, l_fam_inst) }
+
emptyLocalEnv = LocalEnv {
local_vars = emptyVarEnv
+ , local_tyvars = []
, local_tyvar_pa = emptyVarEnv
}
updVectInfo :: GlobalEnv -> TypeEnv -> VectInfo -> VectInfo
updVectInfo env tyenv info
= info {
- vectInfoCCVar = global_exported_vars env
- , vectInfoCCTyCon = tc_env
+ vectInfoVar = global_exported_vars env
+ , vectInfoTyCon = mk_env typeEnvTyCons global_tycons
+ , vectInfoDataCon = mk_env typeEnvDataCons global_datacons
}
where
- tc_env = mkNameEnv [(tc_name, (tc,tc'))
- | tc <- typeEnvTyCons tyenv
- , let tc_name = tyConName tc
- , Just tc' <- [lookupNameEnv (global_tycons env) tc_name]]
+ mk_env from_tyenv from_env = mkNameEnv [(name, (from,to))
+ | from <- from_tyenv tyenv
+ , let name = getName from
+ , Just to <- [lookupNameEnv (from_env env) name]]
data VResult a = Yes GlobalEnv LocalEnv a | No
orElseV :: VM a -> VM a -> VM a
orElseV p q = maybe q return =<< tryV p
+fixV :: (a -> VM a) -> VM a
+fixV f = VM (\bi genv lenv -> fixDs $ \r -> runVM (f (unYes r)) bi genv lenv )
+ where
+ unYes (Yes _ _ x) = x
+
localV :: VM a -> VM a
localV p = do
env <- readLEnv id
setLEnv env
return x
+closedV :: VM a -> VM a
+closedV p = do
+ env <- readLEnv id
+ setLEnv emptyLocalEnv
+ x <- p
+ setLEnv env
+ return x
+
liftDs :: DsM a -> VM a
liftDs p = VM $ \bi genv lenv -> do { x <- p; return (Yes genv lenv x) }
updLEnv :: (LocalEnv -> LocalEnv) -> VM ()
updLEnv f = VM $ \_ genv lenv -> return (Yes genv (f lenv) ())
+getInstEnv :: VM (InstEnv, InstEnv)
+getInstEnv = readGEnv global_inst_env
+
+getFamInstEnv :: VM FamInstEnvs
+getFamInstEnv = readGEnv global_fam_inst_env
+
+cloneName :: (OccName -> OccName) -> Name -> VM Name
+cloneName mk_occ name = liftM make (liftDs newUnique)
+ where
+ occ_name = mk_occ (nameOccName name)
+
+ make u | isExternalName name = mkExternalName u (nameModule name)
+ occ_name
+ (nameSrcSpan name)
+ | otherwise = mkSystemName u occ_name
+
+newExportedVar :: OccName -> Type -> VM Var
+newExportedVar occ_name ty
+ = do
+ mod <- liftDs getModuleDs
+ u <- liftDs newUnique
+
+ let name = mkExternalName u mod occ_name noSrcSpan
+
+ return $ Id.mkExportedLocalId name ty
+
newLocalVar :: FastString -> Type -> VM Var
newLocalVar fs ty
= do
u <- liftDs newUnique
return $ mkSysLocal fs u ty
+newDummyVar :: Type -> VM Var
+newDummyVar = newLocalVar FSLIT("ds")
+
newTyVar :: FastString -> Kind -> VM Var
newTyVar fs k
= do
u <- liftDs newUnique
return $ mkTyVar (mkSysTvName u fs) k
-lookupTyCon :: TyCon -> VM (Maybe TyCon)
-lookupTyCon tc = readGEnv $ \env -> lookupNameEnv (global_tycons env) (tyConName tc)
+defGlobalVar :: Var -> Var -> VM ()
+defGlobalVar v v' = updGEnv $ \env ->
+ env { global_vars = extendVarEnv (global_vars env) v (Var v')
+ , global_exported_vars = upd (global_exported_vars env)
+ }
+ where
+ upd env | isExportedId v = extendVarEnv env v (v, v')
+ | otherwise = env
+
+lookupVar :: Var -> VM (Scope CoreExpr (CoreExpr, CoreExpr))
+lookupVar v
+ = do
+ r <- readLEnv $ \env -> lookupVarEnv (local_vars env) v
+ case r of
+ Just e -> return (Local e)
+ Nothing -> liftM Global
+ $ maybeV (readGEnv $ \env -> lookupVarEnv (global_vars env) v)
-extendTyVarPA :: Var -> CoreExpr -> VM ()
-extendTyVarPA tv pa = updLEnv $ \env -> env { local_tyvar_pa = extendVarEnv (local_tyvar_pa env) tv pa }
+lookupTyCon :: TyCon -> VM (Maybe TyCon)
+lookupTyCon tc
+ | isUnLiftedTyCon tc || isTupleTyCon tc = return (Just tc)
+
+ | otherwise = readGEnv $ \env -> lookupNameEnv (global_tycons env) (tyConName tc)
+
+defTyCon :: TyCon -> TyCon -> VM ()
+defTyCon tc tc' = updGEnv $ \env ->
+ env { global_tycons = extendNameEnv (global_tycons env) (tyConName tc) tc' }
+
+lookupDataCon :: DataCon -> VM (Maybe DataCon)
+lookupDataCon dc = readGEnv $ \env -> lookupNameEnv (global_datacons env) (dataConName dc)
+
+defDataCon :: DataCon -> DataCon -> VM ()
+defDataCon dc dc' = updGEnv $ \env ->
+ env { global_datacons = extendNameEnv (global_datacons env) (dataConName dc) dc' }
+
+lookupTyVarPA :: Var -> VM (Maybe CoreExpr)
+lookupTyVarPA tv = readLEnv $ \env -> lookupVarEnv (local_tyvar_pa env) tv
+
+defLocalTyVar :: TyVar -> VM ()
+defLocalTyVar tv = updLEnv $ \env ->
+ env { local_tyvars = tv : local_tyvars env
+ , local_tyvar_pa = local_tyvar_pa env `delVarEnv` tv
+ }
+
+defLocalTyVarWithPA :: TyVar -> CoreExpr -> VM ()
+defLocalTyVarWithPA tv pa = updLEnv $ \env ->
+ env { local_tyvars = tv : local_tyvars env
+ , local_tyvar_pa = extendVarEnv (local_tyvar_pa env) tv pa
+ }
+
+localTyVars :: VM [TyVar]
+localTyVars = readLEnv (reverse . local_tyvars)
+
+-- Look up the dfun of a class instance.
+--
+-- The match must be unique - ie, match exactly one instance - but the
+-- type arguments used for matching may be more specific than those of
+-- the class instance declaration. The found class instances must not have
+-- any type variables in the instance context that do not appear in the
+-- instances head (i.e., no flexi vars); for details for what this means,
+-- see the docs at InstEnv.lookupInstEnv.
+--
+lookupInst :: Class -> [Type] -> VM (DFunId, [Type])
+lookupInst cls tys
+ = do { instEnv <- getInstEnv
+ ; case lookupInstEnv instEnv cls tys of
+ ([(inst, inst_tys)], _)
+ | noFlexiVar -> return (instanceDFunId inst, inst_tys')
+ | otherwise -> pprPanic "VectMonad.lookupInst: flexi var: "
+ (ppr $ mkTyConApp (classTyCon cls) tys)
+ where
+ inst_tys' = [ty | Right ty <- inst_tys]
+ noFlexiVar = all isRight inst_tys
+ _other -> noV
+ }
+ where
+ isRight (Left _) = False
+ isRight (Right _) = True
+
+-- Look up the representation tycon of a family instance.
+--
+-- The match must be unique - ie, match exactly one instance - but the
+-- type arguments used for matching may be more specific than those of
+-- the family instance declaration.
+--
+-- Return the instance tycon and its type instance. For example, if we have
+--
+-- lookupFamInst 'T' '[Int]' yields (':R42T', 'Int')
+--
+-- then we have a coercion (ie, type instance of family instance coercion)
+--
+-- :Co:R42T Int :: T [Int] ~ :R42T Int
+--
+-- which implies that :R42T was declared as 'data instance T [a]'.
+--
+lookupFamInst :: TyCon -> [Type] -> VM (TyCon, [Type])
+lookupFamInst tycon tys
+ = ASSERT( isOpenTyCon tycon )
+ do { instEnv <- getFamInstEnv
+ ; case lookupFamInstEnv instEnv tycon tys of
+ [(fam_inst, rep_tys)] -> return (famInstTyCon fam_inst, rep_tys)
+ _other ->
+ pprPanic "VectMonad.lookupFamInst: not found: "
+ (ppr $ mkTyConApp tycon tys)
+ }
initV :: HscEnv -> ModGuts -> VectInfo -> VM a -> IO (Maybe (VectInfo, a))
initV hsc_env guts info p
= do
+ eps <- hscEPS hsc_env
+ let famInstEnvs = (eps_fam_inst_env eps, mg_fam_inst_env guts)
+ let instEnvs = (eps_inst_env eps, mg_inst_env guts)
+
Just r <- initDs hsc_env (mg_module guts)
(mg_rdr_env guts)
(mg_types guts)
- go
+ (go instEnvs famInstEnvs)
return r
where
- go = do
- builtins <- initBuiltins
- r <- runVM p builtins (initGlobalEnv info) emptyLocalEnv
- case r of
- Yes genv _ x -> return $ Just (new_info genv, x)
- No -> return Nothing
+
+ go instEnvs famInstEnvs =
+ do
+ builtins <- initBuiltins
+ r <- runVM p builtins (initGlobalEnv info instEnvs famInstEnvs builtins)
+ emptyLocalEnv
+ case r of
+ Yes genv _ x -> return $ Just (new_info genv, x)
+ No -> return Nothing
new_info genv = updVectInfo genv (mg_types guts) info