2 -- The above warning supression flag is a temporary kludge.
3 -- While working on this module you are encouraged to remove it and fix
4 -- any warnings in the module. See
5 -- http://hackage.haskell.org/trac/ghc/wiki/Commentary/CodingStyle#Warnings
12 noV, tryV, maybeV, traceMaybeV, orElseV, fixV, localV, closedV, initV,
14 cloneName, cloneId, cloneVar,
15 newExportedVar, newLocalVar, newDummyVar, newTyVar,
17 Builtins(..), sumTyCon, prodTyCon, combinePAVar,
22 readGEnv, setGEnv, updGEnv,
25 readLEnv, setLEnv, updLEnv,
29 lookupVar, defGlobalVar,
30 lookupTyCon, defTyCon,
31 lookupDataCon, defDataCon,
32 lookupTyConPA, defTyConPA, defTyConPAs,
35 lookupPrimMethod, lookupPrimPArray,
36 lookupTyVarPA, defLocalTyVar, defLocalTyVarWithPA, localTyVars,
38 {-lookupInst,-} lookupFamInst
41 #include "HsVersions.h"
57 import TysPrim ( intPrimTy )
60 import IOEnv ( ioToIOEnv )
71 import SrcLoc ( noSrcSpan )
73 import Control.Monad ( liftM, zipWithM )
75 data Scope a b = Global a | Local b
77 -- ----------------------------------------------------------------------------
78 -- Vectorisation monad
80 data GlobalEnv = GlobalEnv {
81 -- Mapping from global variables to their vectorised versions.
83 global_vars :: VarEnv Var
85 -- Exported variables which have a vectorised version
87 , global_exported_vars :: VarEnv (Var, Var)
89 -- Mapping from TyCons to their vectorised versions.
90 -- TyCons which do not have to be vectorised are mapped to
93 , global_tycons :: NameEnv TyCon
95 -- Mapping from DataCons to their vectorised versions
97 , global_datacons :: NameEnv DataCon
99 -- Mapping from TyCons to their PA dfuns
101 , global_pa_funs :: NameEnv Var
103 -- Mapping from TyCons to their PR dfuns
104 , global_pr_funs :: NameEnv Var
106 -- Mapping from unboxed TyCons to their boxed versions
107 , global_boxed_tycons :: NameEnv TyCon
109 -- External package inst-env & home-package inst-env for class
112 , global_inst_env :: (InstEnv, InstEnv)
114 -- External package inst-env & home-package inst-env for family
117 , global_fam_inst_env :: FamInstEnvs
120 , global_bindings :: [(Var, CoreExpr)]
123 data LocalEnv = LocalEnv {
124 -- Mapping from local variables to their vectorised and
127 local_vars :: VarEnv (Var, Var)
129 -- In-scope type variables
131 , local_tyvars :: [TyVar]
133 -- Mapping from tyvars to their PA dictionaries
134 , local_tyvar_pa :: VarEnv CoreExpr
136 -- Local binding name
137 , local_bind_name :: FastString
140 initGlobalEnv :: VectInfo -> (InstEnv, InstEnv) -> FamInstEnvs -> GlobalEnv
141 initGlobalEnv info instEnvs famInstEnvs
143 global_vars = mapVarEnv snd $ vectInfoVar info
144 , global_exported_vars = emptyVarEnv
145 , global_tycons = mapNameEnv snd $ vectInfoTyCon info
146 , global_datacons = mapNameEnv snd $ vectInfoDataCon info
147 , global_pa_funs = mapNameEnv snd $ vectInfoPADFun info
148 , global_pr_funs = emptyNameEnv
149 , global_boxed_tycons = emptyNameEnv
150 , global_inst_env = instEnvs
151 , global_fam_inst_env = famInstEnvs
152 , global_bindings = []
155 setFamInstEnv :: FamInstEnv -> GlobalEnv -> GlobalEnv
156 setFamInstEnv l_fam_inst genv
157 = genv { global_fam_inst_env = (g_fam_inst, l_fam_inst) }
159 (g_fam_inst, _) = global_fam_inst_env genv
161 extendTyConsEnv :: [(Name, TyCon)] -> GlobalEnv -> GlobalEnv
162 extendTyConsEnv ps genv
163 = genv { global_tycons = extendNameEnvList (global_tycons genv) ps }
165 extendDataConsEnv :: [(Name, DataCon)] -> GlobalEnv -> GlobalEnv
166 extendDataConsEnv ps genv
167 = genv { global_datacons = extendNameEnvList (global_datacons genv) ps }
169 extendPAFunsEnv :: [(Name, Var)] -> GlobalEnv -> GlobalEnv
170 extendPAFunsEnv ps genv
171 = genv { global_pa_funs = extendNameEnvList (global_pa_funs genv) ps }
173 setPRFunsEnv :: [(Name, Var)] -> GlobalEnv -> GlobalEnv
175 = genv { global_pr_funs = mkNameEnv ps }
177 setBoxedTyConsEnv :: [(Name, TyCon)] -> GlobalEnv -> GlobalEnv
178 setBoxedTyConsEnv ps genv
179 = genv { global_boxed_tycons = mkNameEnv ps }
181 emptyLocalEnv = LocalEnv {
182 local_vars = emptyVarEnv
184 , local_tyvar_pa = emptyVarEnv
185 , local_bind_name = FSLIT("fn")
189 updVectInfo :: GlobalEnv -> TypeEnv -> VectInfo -> VectInfo
190 updVectInfo env tyenv info
192 vectInfoVar = global_exported_vars env
193 , vectInfoTyCon = mk_env typeEnvTyCons global_tycons
194 , vectInfoDataCon = mk_env typeEnvDataCons global_datacons
195 , vectInfoPADFun = mk_env typeEnvTyCons global_pa_funs
198 mk_env from_tyenv from_env = mkNameEnv [(name, (from,to))
199 | from <- from_tyenv tyenv
200 , let name = getName from
201 , Just to <- [lookupNameEnv (from_env env) name]]
203 data VResult a = Yes GlobalEnv LocalEnv a | No
205 newtype VM a = VM { runVM :: Builtins -> GlobalEnv -> LocalEnv -> DsM (VResult a) }
207 instance Monad VM where
208 return x = VM $ \bi genv lenv -> return (Yes genv lenv x)
209 VM p >>= f = VM $ \bi genv lenv -> do
212 Yes genv' lenv' x -> runVM (f x) bi genv' lenv'
216 noV = VM $ \_ _ _ -> return No
218 traceNoV :: String -> SDoc -> VM a
219 traceNoV s d = pprTrace s d noV
221 tryV :: VM a -> VM (Maybe a)
222 tryV (VM p) = VM $ \bi genv lenv ->
226 Yes genv' lenv' x -> return (Yes genv' lenv' (Just x))
227 No -> return (Yes genv lenv Nothing)
229 maybeV :: VM (Maybe a) -> VM a
230 maybeV p = maybe noV return =<< p
232 traceMaybeV :: String -> SDoc -> VM (Maybe a) -> VM a
233 traceMaybeV s d p = maybe (traceNoV s d) return =<< p
235 orElseV :: VM a -> VM a -> VM a
236 orElseV p q = maybe q return =<< tryV p
238 fixV :: (a -> VM a) -> VM a
239 fixV f = VM (\bi genv lenv -> fixDs $ \r -> runVM (f (unYes r)) bi genv lenv )
241 unYes (Yes _ _ x) = x
243 localV :: VM a -> VM a
250 closedV :: VM a -> VM a
253 setLEnv (emptyLocalEnv { local_bind_name = local_bind_name env })
258 liftDs :: DsM a -> VM a
259 liftDs p = VM $ \bi genv lenv -> do { x <- p; return (Yes genv lenv x) }
261 builtin :: (Builtins -> a) -> VM a
262 builtin f = VM $ \bi genv lenv -> return (Yes genv lenv (f bi))
264 builtins :: (a -> Builtins -> b) -> VM (a -> b)
265 builtins f = VM $ \bi genv lenv -> return (Yes genv lenv (`f` bi))
267 readGEnv :: (GlobalEnv -> a) -> VM a
268 readGEnv f = VM $ \bi genv lenv -> return (Yes genv lenv (f genv))
270 setGEnv :: GlobalEnv -> VM ()
271 setGEnv genv = VM $ \_ _ lenv -> return (Yes genv lenv ())
273 updGEnv :: (GlobalEnv -> GlobalEnv) -> VM ()
274 updGEnv f = VM $ \_ genv lenv -> return (Yes (f genv) lenv ())
276 readLEnv :: (LocalEnv -> a) -> VM a
277 readLEnv f = VM $ \bi genv lenv -> return (Yes genv lenv (f lenv))
279 setLEnv :: LocalEnv -> VM ()
280 setLEnv lenv = VM $ \_ genv _ -> return (Yes genv lenv ())
282 updLEnv :: (LocalEnv -> LocalEnv) -> VM ()
283 updLEnv f = VM $ \_ genv lenv -> return (Yes genv (f lenv) ())
285 getInstEnv :: VM (InstEnv, InstEnv)
286 getInstEnv = readGEnv global_inst_env
288 getFamInstEnv :: VM FamInstEnvs
289 getFamInstEnv = readGEnv global_fam_inst_env
291 getBindName :: VM FastString
292 getBindName = readLEnv local_bind_name
294 inBind :: Id -> VM a -> VM a
296 = do updLEnv $ \env -> env { local_bind_name = occNameFS (getOccName id) }
299 cloneName :: (OccName -> OccName) -> Name -> VM Name
300 cloneName mk_occ name = liftM make (liftDs newUnique)
302 occ_name = mk_occ (nameOccName name)
304 make u | isExternalName name = mkExternalName u (nameModule name)
307 | otherwise = mkSystemName u occ_name
309 cloneId :: (OccName -> OccName) -> Id -> Type -> VM Id
312 name <- cloneName mk_occ (getName id)
313 let id' | isExportedId id = Id.mkExportedLocalId name ty
314 | otherwise = Id.mkLocalId name ty
317 cloneVar :: Var -> VM Var
318 cloneVar var = liftM (setIdUnique var) (liftDs newUnique)
320 newExportedVar :: OccName -> Type -> VM Var
321 newExportedVar occ_name ty
323 mod <- liftDs getModuleDs
324 u <- liftDs newUnique
326 let name = mkExternalName u mod occ_name noSrcSpan
328 return $ Id.mkExportedLocalId name ty
330 newLocalVar :: FastString -> Type -> VM Var
333 u <- liftDs newUnique
334 return $ mkSysLocal fs u ty
336 newDummyVar :: Type -> VM Var
337 newDummyVar = newLocalVar FSLIT("ds")
339 newTyVar :: FastString -> Kind -> VM Var
342 u <- liftDs newUnique
343 return $ mkTyVar (mkSysTvName u fs) k
345 defGlobalVar :: Var -> Var -> VM ()
346 defGlobalVar v v' = updGEnv $ \env ->
347 env { global_vars = extendVarEnv (global_vars env) v v'
348 , global_exported_vars = upd (global_exported_vars env)
351 upd env | isExportedId v = extendVarEnv env v (v, v')
354 lookupVar :: Var -> VM (Scope Var (Var, Var))
357 r <- readLEnv $ \env -> lookupVarEnv (local_vars env) v
359 Just e -> return (Local e)
360 Nothing -> liftM Global
361 $ traceMaybeV "lookupVar" (ppr v)
362 (readGEnv $ \env -> lookupVarEnv (global_vars env) v)
364 lookupTyCon :: TyCon -> VM (Maybe TyCon)
366 | isUnLiftedTyCon tc || isTupleTyCon tc = return (Just tc)
368 | otherwise = readGEnv $ \env -> lookupNameEnv (global_tycons env) (tyConName tc)
370 defTyCon :: TyCon -> TyCon -> VM ()
371 defTyCon tc tc' = updGEnv $ \env ->
372 env { global_tycons = extendNameEnv (global_tycons env) (tyConName tc) tc' }
374 lookupDataCon :: DataCon -> VM (Maybe DataCon)
375 lookupDataCon dc = readGEnv $ \env -> lookupNameEnv (global_datacons env) (dataConName dc)
377 defDataCon :: DataCon -> DataCon -> VM ()
378 defDataCon dc dc' = updGEnv $ \env ->
379 env { global_datacons = extendNameEnv (global_datacons env) (dataConName dc) dc' }
381 lookupPrimPArray :: TyCon -> VM (Maybe TyCon)
382 lookupPrimPArray = liftDs . primPArray
384 lookupPrimMethod :: TyCon -> String -> VM (Maybe Var)
385 lookupPrimMethod tycon = liftDs . primMethod tycon
387 lookupTyConPA :: TyCon -> VM (Maybe Var)
388 lookupTyConPA tc = readGEnv $ \env -> lookupNameEnv (global_pa_funs env) (tyConName tc)
390 defTyConPA :: TyCon -> Var -> VM ()
391 defTyConPA tc pa = updGEnv $ \env ->
392 env { global_pa_funs = extendNameEnv (global_pa_funs env) (tyConName tc) pa }
394 defTyConPAs :: [(TyCon, Var)] -> VM ()
395 defTyConPAs ps = updGEnv $ \env ->
396 env { global_pa_funs = extendNameEnvList (global_pa_funs env)
397 [(tyConName tc, pa) | (tc, pa) <- ps] }
399 lookupTyVarPA :: Var -> VM (Maybe CoreExpr)
400 lookupTyVarPA tv = readLEnv $ \env -> lookupVarEnv (local_tyvar_pa env) tv
402 lookupTyConPR :: TyCon -> VM (Maybe Var)
403 lookupTyConPR tc = readGEnv $ \env -> lookupNameEnv (global_pr_funs env) (tyConName tc)
405 lookupBoxedTyCon :: TyCon -> VM (Maybe TyCon)
406 lookupBoxedTyCon tc = readGEnv $ \env -> lookupNameEnv (global_boxed_tycons env)
409 defLocalTyVar :: TyVar -> VM ()
410 defLocalTyVar tv = updLEnv $ \env ->
411 env { local_tyvars = tv : local_tyvars env
412 , local_tyvar_pa = local_tyvar_pa env `delVarEnv` tv
415 defLocalTyVarWithPA :: TyVar -> CoreExpr -> VM ()
416 defLocalTyVarWithPA tv pa = updLEnv $ \env ->
417 env { local_tyvars = tv : local_tyvars env
418 , local_tyvar_pa = extendVarEnv (local_tyvar_pa env) tv pa
421 localTyVars :: VM [TyVar]
422 localTyVars = readLEnv (reverse . local_tyvars)
424 -- Look up the dfun of a class instance.
426 -- The match must be unique - ie, match exactly one instance - but the
427 -- type arguments used for matching may be more specific than those of
428 -- the class instance declaration. The found class instances must not have
429 -- any type variables in the instance context that do not appear in the
430 -- instances head (i.e., no flexi vars); for details for what this means,
431 -- see the docs at InstEnv.lookupInstEnv.
434 lookupInst :: Class -> [Type] -> VM (DFunId, [Type])
436 = do { instEnv <- getInstEnv
437 ; case lookupInstEnv instEnv cls tys of
438 ([(inst, inst_tys)], _)
439 | noFlexiVar -> return (instanceDFunId inst, inst_tys')
440 | otherwise -> pprPanic "VectMonad.lookupInst: flexi var: "
441 (ppr $ mkTyConApp (classTyCon cls) tys)
443 inst_tys' = [ty | Right ty <- inst_tys]
444 noFlexiVar = all isRight inst_tys
445 _other -> traceNoV "lookupInst" (ppr cls <+> ppr tys)
448 isRight (Left _) = False
449 isRight (Right _) = True
452 -- Look up the representation tycon of a family instance.
454 -- The match must be unique - ie, match exactly one instance - but the
455 -- type arguments used for matching may be more specific than those of
456 -- the family instance declaration.
458 -- Return the instance tycon and its type instance. For example, if we have
460 -- lookupFamInst 'T' '[Int]' yields (':R42T', 'Int')
462 -- then we have a coercion (ie, type instance of family instance coercion)
464 -- :Co:R42T Int :: T [Int] ~ :R42T Int
466 -- which implies that :R42T was declared as 'data instance T [a]'.
468 lookupFamInst :: TyCon -> [Type] -> VM (TyCon, [Type])
469 lookupFamInst tycon tys
470 = ASSERT( isOpenTyCon tycon )
471 do { instEnv <- getFamInstEnv
472 ; case lookupFamInstEnv instEnv tycon tys of
473 [(fam_inst, rep_tys)] -> return (famInstTyCon fam_inst, rep_tys)
475 pprPanic "VectMonad.lookupFamInst: not found: "
476 (ppr $ mkTyConApp tycon tys)
479 initV :: HscEnv -> ModGuts -> VectInfo -> VM a -> IO (Maybe (VectInfo, a))
480 initV hsc_env guts info p
482 Just r <- initDs hsc_env (mg_module guts)
491 builtins <- initBuiltins
492 let builtin_tycons = initBuiltinTyCons builtins
493 builtin_datacons = initBuiltinDataCons builtins
494 builtin_pas <- initBuiltinPAs builtins
495 builtin_prs <- initBuiltinPRs builtins
496 builtin_boxed <- initBuiltinBoxedTyCons builtins
498 eps <- ioToIOEnv $ hscEPS hsc_env
499 let famInstEnvs = (eps_fam_inst_env eps, mg_fam_inst_env guts)
500 instEnvs = (eps_inst_env eps, mg_inst_env guts)
502 let genv = extendTyConsEnv builtin_tycons
503 . extendDataConsEnv builtin_datacons
504 . extendPAFunsEnv builtin_pas
505 . setPRFunsEnv builtin_prs
506 . setBoxedTyConsEnv builtin_boxed
507 $ initGlobalEnv info instEnvs famInstEnvs
509 r <- runVM p builtins genv emptyLocalEnv
511 Yes genv _ x -> return $ Just (new_info genv, x)
514 new_info genv = updVectInfo genv (mg_types guts) info