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, uarrTy, intPrimArrayTy,
23 readGEnv, setGEnv, updGEnv,
26 readLEnv, setLEnv, updLEnv,
30 lookupVar, defGlobalVar,
31 lookupTyCon, defTyCon,
32 lookupDataCon, defDataCon,
33 lookupTyConPA, defTyConPA, defTyConPAs,
36 lookupPrimMethod, lookupPrimPArray,
37 lookupTyVarPA, defLocalTyVar, defLocalTyVarWithPA, localTyVars,
39 {-lookupInst,-} lookupFamInst
42 #include "HsVersions.h"
58 import TysPrim ( intPrimTy )
61 import IOEnv ( ioToIOEnv )
72 import SrcLoc ( noSrcSpan )
74 import Control.Monad ( liftM, zipWithM )
76 data Scope a b = Global a | Local b
78 -- ----------------------------------------------------------------------------
79 -- Vectorisation monad
81 data GlobalEnv = GlobalEnv {
82 -- Mapping from global variables to their vectorised versions.
84 global_vars :: VarEnv Var
86 -- Exported variables which have a vectorised version
88 , global_exported_vars :: VarEnv (Var, Var)
90 -- Mapping from TyCons to their vectorised versions.
91 -- TyCons which do not have to be vectorised are mapped to
94 , global_tycons :: NameEnv TyCon
96 -- Mapping from DataCons to their vectorised versions
98 , global_datacons :: NameEnv DataCon
100 -- Mapping from TyCons to their PA dfuns
102 , global_pa_funs :: NameEnv Var
104 -- Mapping from TyCons to their PR dfuns
105 , global_pr_funs :: NameEnv Var
107 -- Mapping from unboxed TyCons to their boxed versions
108 , global_boxed_tycons :: NameEnv TyCon
110 -- External package inst-env & home-package inst-env for class
113 , global_inst_env :: (InstEnv, InstEnv)
115 -- External package inst-env & home-package inst-env for family
118 , global_fam_inst_env :: FamInstEnvs
121 , global_bindings :: [(Var, CoreExpr)]
124 data LocalEnv = LocalEnv {
125 -- Mapping from local variables to their vectorised and
128 local_vars :: VarEnv (Var, Var)
130 -- In-scope type variables
132 , local_tyvars :: [TyVar]
134 -- Mapping from tyvars to their PA dictionaries
135 , local_tyvar_pa :: VarEnv CoreExpr
137 -- Local binding name
138 , local_bind_name :: FastString
141 initGlobalEnv :: VectInfo -> (InstEnv, InstEnv) -> FamInstEnvs -> GlobalEnv
142 initGlobalEnv info instEnvs famInstEnvs
144 global_vars = mapVarEnv snd $ vectInfoVar info
145 , global_exported_vars = emptyVarEnv
146 , global_tycons = mapNameEnv snd $ vectInfoTyCon info
147 , global_datacons = mapNameEnv snd $ vectInfoDataCon info
148 , global_pa_funs = mapNameEnv snd $ vectInfoPADFun info
149 , global_pr_funs = emptyNameEnv
150 , global_boxed_tycons = emptyNameEnv
151 , global_inst_env = instEnvs
152 , global_fam_inst_env = famInstEnvs
153 , global_bindings = []
156 extendImportedVarsEnv :: [(Var, Var)] -> GlobalEnv -> GlobalEnv
157 extendImportedVarsEnv ps genv
158 = genv { global_vars = extendVarEnvList (global_vars genv) ps }
160 setFamInstEnv :: FamInstEnv -> GlobalEnv -> GlobalEnv
161 setFamInstEnv l_fam_inst genv
162 = genv { global_fam_inst_env = (g_fam_inst, l_fam_inst) }
164 (g_fam_inst, _) = global_fam_inst_env genv
166 extendTyConsEnv :: [(Name, TyCon)] -> GlobalEnv -> GlobalEnv
167 extendTyConsEnv ps genv
168 = genv { global_tycons = extendNameEnvList (global_tycons genv) ps }
170 extendDataConsEnv :: [(Name, DataCon)] -> GlobalEnv -> GlobalEnv
171 extendDataConsEnv ps genv
172 = genv { global_datacons = extendNameEnvList (global_datacons genv) ps }
174 extendPAFunsEnv :: [(Name, Var)] -> GlobalEnv -> GlobalEnv
175 extendPAFunsEnv ps genv
176 = genv { global_pa_funs = extendNameEnvList (global_pa_funs genv) ps }
178 setPRFunsEnv :: [(Name, Var)] -> GlobalEnv -> GlobalEnv
180 = genv { global_pr_funs = mkNameEnv ps }
182 setBoxedTyConsEnv :: [(Name, TyCon)] -> GlobalEnv -> GlobalEnv
183 setBoxedTyConsEnv ps genv
184 = genv { global_boxed_tycons = mkNameEnv ps }
186 emptyLocalEnv = LocalEnv {
187 local_vars = emptyVarEnv
189 , local_tyvar_pa = emptyVarEnv
190 , local_bind_name = FSLIT("fn")
194 updVectInfo :: GlobalEnv -> TypeEnv -> VectInfo -> VectInfo
195 updVectInfo env tyenv info
197 vectInfoVar = global_exported_vars env
198 , vectInfoTyCon = mk_env typeEnvTyCons global_tycons
199 , vectInfoDataCon = mk_env typeEnvDataCons global_datacons
200 , vectInfoPADFun = mk_env typeEnvTyCons global_pa_funs
203 mk_env from_tyenv from_env = mkNameEnv [(name, (from,to))
204 | from <- from_tyenv tyenv
205 , let name = getName from
206 , Just to <- [lookupNameEnv (from_env env) name]]
208 data VResult a = Yes GlobalEnv LocalEnv a | No
210 newtype VM a = VM { runVM :: Builtins -> GlobalEnv -> LocalEnv -> DsM (VResult a) }
212 instance Monad VM where
213 return x = VM $ \bi genv lenv -> return (Yes genv lenv x)
214 VM p >>= f = VM $ \bi genv lenv -> do
217 Yes genv' lenv' x -> runVM (f x) bi genv' lenv'
221 noV = VM $ \_ _ _ -> return No
223 traceNoV :: String -> SDoc -> VM a
224 traceNoV s d = pprTrace s d noV
226 tryV :: VM a -> VM (Maybe a)
227 tryV (VM p) = VM $ \bi genv lenv ->
231 Yes genv' lenv' x -> return (Yes genv' lenv' (Just x))
232 No -> return (Yes genv lenv Nothing)
234 maybeV :: VM (Maybe a) -> VM a
235 maybeV p = maybe noV return =<< p
237 traceMaybeV :: String -> SDoc -> VM (Maybe a) -> VM a
238 traceMaybeV s d p = maybe (traceNoV s d) return =<< p
240 orElseV :: VM a -> VM a -> VM a
241 orElseV p q = maybe q return =<< tryV p
243 fixV :: (a -> VM a) -> VM a
244 fixV f = VM (\bi genv lenv -> fixDs $ \r -> runVM (f (unYes r)) bi genv lenv )
246 unYes (Yes _ _ x) = x
248 localV :: VM a -> VM a
255 closedV :: VM a -> VM a
258 setLEnv (emptyLocalEnv { local_bind_name = local_bind_name env })
263 liftDs :: DsM a -> VM a
264 liftDs p = VM $ \bi genv lenv -> do { x <- p; return (Yes genv lenv x) }
266 builtin :: (Builtins -> a) -> VM a
267 builtin f = VM $ \bi genv lenv -> return (Yes genv lenv (f bi))
269 builtins :: (a -> Builtins -> b) -> VM (a -> b)
270 builtins f = VM $ \bi genv lenv -> return (Yes genv lenv (`f` bi))
272 readGEnv :: (GlobalEnv -> a) -> VM a
273 readGEnv f = VM $ \bi genv lenv -> return (Yes genv lenv (f genv))
275 setGEnv :: GlobalEnv -> VM ()
276 setGEnv genv = VM $ \_ _ lenv -> return (Yes genv lenv ())
278 updGEnv :: (GlobalEnv -> GlobalEnv) -> VM ()
279 updGEnv f = VM $ \_ genv lenv -> return (Yes (f genv) lenv ())
281 readLEnv :: (LocalEnv -> a) -> VM a
282 readLEnv f = VM $ \bi genv lenv -> return (Yes genv lenv (f lenv))
284 setLEnv :: LocalEnv -> VM ()
285 setLEnv lenv = VM $ \_ genv _ -> return (Yes genv lenv ())
287 updLEnv :: (LocalEnv -> LocalEnv) -> VM ()
288 updLEnv f = VM $ \_ genv lenv -> return (Yes genv (f lenv) ())
290 getInstEnv :: VM (InstEnv, InstEnv)
291 getInstEnv = readGEnv global_inst_env
293 getFamInstEnv :: VM FamInstEnvs
294 getFamInstEnv = readGEnv global_fam_inst_env
296 getBindName :: VM FastString
297 getBindName = readLEnv local_bind_name
299 inBind :: Id -> VM a -> VM a
301 = do updLEnv $ \env -> env { local_bind_name = occNameFS (getOccName id) }
304 cloneName :: (OccName -> OccName) -> Name -> VM Name
305 cloneName mk_occ name = liftM make (liftDs newUnique)
307 occ_name = mk_occ (nameOccName name)
309 make u | isExternalName name = mkExternalName u (nameModule name)
312 | otherwise = mkSystemName u occ_name
314 cloneId :: (OccName -> OccName) -> Id -> Type -> VM Id
317 name <- cloneName mk_occ (getName id)
318 let id' | isExportedId id = Id.mkExportedLocalId name ty
319 | otherwise = Id.mkLocalId name ty
322 cloneVar :: Var -> VM Var
323 cloneVar var = liftM (setIdUnique var) (liftDs newUnique)
325 newExportedVar :: OccName -> Type -> VM Var
326 newExportedVar occ_name ty
328 mod <- liftDs getModuleDs
329 u <- liftDs newUnique
331 let name = mkExternalName u mod occ_name noSrcSpan
333 return $ Id.mkExportedLocalId name ty
335 newLocalVar :: FastString -> Type -> VM Var
338 u <- liftDs newUnique
339 return $ mkSysLocal fs u ty
341 newDummyVar :: Type -> VM Var
342 newDummyVar = newLocalVar FSLIT("ds")
344 newTyVar :: FastString -> Kind -> VM Var
347 u <- liftDs newUnique
348 return $ mkTyVar (mkSysTvName u fs) k
350 defGlobalVar :: Var -> Var -> VM ()
351 defGlobalVar v v' = updGEnv $ \env ->
352 env { global_vars = extendVarEnv (global_vars env) v v'
353 , global_exported_vars = upd (global_exported_vars env)
356 upd env | isExportedId v = extendVarEnv env v (v, v')
359 lookupVar :: Var -> VM (Scope Var (Var, Var))
362 r <- readLEnv $ \env -> lookupVarEnv (local_vars env) v
364 Just e -> return (Local e)
365 Nothing -> liftM Global
366 $ traceMaybeV "lookupVar" (ppr v)
367 (readGEnv $ \env -> lookupVarEnv (global_vars env) v)
369 lookupTyCon :: TyCon -> VM (Maybe TyCon)
371 | isUnLiftedTyCon tc || isTupleTyCon tc = return (Just tc)
373 | otherwise = readGEnv $ \env -> lookupNameEnv (global_tycons env) (tyConName tc)
375 defTyCon :: TyCon -> TyCon -> VM ()
376 defTyCon tc tc' = updGEnv $ \env ->
377 env { global_tycons = extendNameEnv (global_tycons env) (tyConName tc) tc' }
379 lookupDataCon :: DataCon -> VM (Maybe DataCon)
381 | isTupleTyCon (dataConTyCon dc) = return (Just dc)
382 | otherwise = readGEnv $ \env -> lookupNameEnv (global_datacons env) (dataConName dc)
384 defDataCon :: DataCon -> DataCon -> VM ()
385 defDataCon dc dc' = updGEnv $ \env ->
386 env { global_datacons = extendNameEnv (global_datacons env) (dataConName dc) dc' }
388 lookupPrimPArray :: TyCon -> VM (Maybe TyCon)
389 lookupPrimPArray = liftDs . primPArray
391 lookupPrimMethod :: TyCon -> String -> VM (Maybe Var)
392 lookupPrimMethod tycon = liftDs . primMethod tycon
394 lookupTyConPA :: TyCon -> VM (Maybe Var)
395 lookupTyConPA tc = readGEnv $ \env -> lookupNameEnv (global_pa_funs env) (tyConName tc)
397 defTyConPA :: TyCon -> Var -> VM ()
398 defTyConPA tc pa = updGEnv $ \env ->
399 env { global_pa_funs = extendNameEnv (global_pa_funs env) (tyConName tc) pa }
401 defTyConPAs :: [(TyCon, Var)] -> VM ()
402 defTyConPAs ps = updGEnv $ \env ->
403 env { global_pa_funs = extendNameEnvList (global_pa_funs env)
404 [(tyConName tc, pa) | (tc, pa) <- ps] }
406 lookupTyVarPA :: Var -> VM (Maybe CoreExpr)
407 lookupTyVarPA tv = readLEnv $ \env -> lookupVarEnv (local_tyvar_pa env) tv
409 lookupTyConPR :: TyCon -> VM (Maybe Var)
410 lookupTyConPR tc = readGEnv $ \env -> lookupNameEnv (global_pr_funs env) (tyConName tc)
412 lookupBoxedTyCon :: TyCon -> VM (Maybe TyCon)
413 lookupBoxedTyCon tc = readGEnv $ \env -> lookupNameEnv (global_boxed_tycons env)
416 defLocalTyVar :: TyVar -> VM ()
417 defLocalTyVar tv = updLEnv $ \env ->
418 env { local_tyvars = tv : local_tyvars env
419 , local_tyvar_pa = local_tyvar_pa env `delVarEnv` tv
422 defLocalTyVarWithPA :: TyVar -> CoreExpr -> VM ()
423 defLocalTyVarWithPA tv pa = updLEnv $ \env ->
424 env { local_tyvars = tv : local_tyvars env
425 , local_tyvar_pa = extendVarEnv (local_tyvar_pa env) tv pa
428 localTyVars :: VM [TyVar]
429 localTyVars = readLEnv (reverse . local_tyvars)
431 -- Look up the dfun of a class instance.
433 -- The match must be unique - ie, match exactly one instance - but the
434 -- type arguments used for matching may be more specific than those of
435 -- the class instance declaration. The found class instances must not have
436 -- any type variables in the instance context that do not appear in the
437 -- instances head (i.e., no flexi vars); for details for what this means,
438 -- see the docs at InstEnv.lookupInstEnv.
441 lookupInst :: Class -> [Type] -> VM (DFunId, [Type])
443 = do { instEnv <- getInstEnv
444 ; case lookupInstEnv instEnv cls tys of
445 ([(inst, inst_tys)], _)
446 | noFlexiVar -> return (instanceDFunId inst, inst_tys')
447 | otherwise -> pprPanic "VectMonad.lookupInst: flexi var: "
448 (ppr $ mkTyConApp (classTyCon cls) tys)
450 inst_tys' = [ty | Right ty <- inst_tys]
451 noFlexiVar = all isRight inst_tys
452 _other -> traceNoV "lookupInst" (ppr cls <+> ppr tys)
455 isRight (Left _) = False
456 isRight (Right _) = True
459 -- Look up the representation tycon of a family instance.
461 -- The match must be unique - ie, match exactly one instance - but the
462 -- type arguments used for matching may be more specific than those of
463 -- the family instance declaration.
465 -- Return the instance tycon and its type instance. For example, if we have
467 -- lookupFamInst 'T' '[Int]' yields (':R42T', 'Int')
469 -- then we have a coercion (ie, type instance of family instance coercion)
471 -- :Co:R42T Int :: T [Int] ~ :R42T Int
473 -- which implies that :R42T was declared as 'data instance T [a]'.
475 lookupFamInst :: TyCon -> [Type] -> VM (TyCon, [Type])
476 lookupFamInst tycon tys
477 = ASSERT( isOpenTyCon tycon )
478 do { instEnv <- getFamInstEnv
479 ; case lookupFamInstEnv instEnv tycon tys of
480 [(fam_inst, rep_tys)] -> return (famInstTyCon fam_inst, rep_tys)
482 pprPanic "VectMonad.lookupFamInst: not found: "
483 (ppr $ mkTyConApp tycon tys)
486 initV :: HscEnv -> ModGuts -> VectInfo -> VM a -> IO (Maybe (VectInfo, a))
487 initV hsc_env guts info p
489 Just r <- initDs hsc_env (mg_module guts)
498 builtins <- initBuiltins
499 builtin_vars <- initBuiltinVars builtins
500 builtin_tycons <- initBuiltinTyCons builtins
501 let builtin_datacons = initBuiltinDataCons builtins
502 builtin_pas <- initBuiltinPAs builtins
503 builtin_prs <- initBuiltinPRs builtins
504 builtin_boxed <- initBuiltinBoxedTyCons builtins
506 eps <- ioToIOEnv $ hscEPS hsc_env
507 let famInstEnvs = (eps_fam_inst_env eps, mg_fam_inst_env guts)
508 instEnvs = (eps_inst_env eps, mg_inst_env guts)
510 let genv = extendImportedVarsEnv builtin_vars
511 . extendTyConsEnv builtin_tycons
512 . extendDataConsEnv builtin_datacons
513 . extendPAFunsEnv builtin_pas
514 . setPRFunsEnv builtin_prs
515 . setBoxedTyConsEnv builtin_boxed
516 $ initGlobalEnv info instEnvs famInstEnvs
518 r <- runVM p builtins genv emptyLocalEnv
520 Yes genv _ x -> return $ Just (new_info genv, x)
523 new_info genv = updVectInfo genv (mg_types guts) info