Tidy up the treatment of dead binders
[ghc-hetmet.git] / compiler / vectorise / VectMonad.hs
1 module VectMonad (
2   Scope(..),
3   VM,
4
5   noV, traceNoV, tryV, maybeV, traceMaybeV, orElseV, fixV, localV, closedV,
6   initV, cantVectorise, maybeCantVectorise, maybeCantVectoriseM,
7   liftDs,
8   cloneName, cloneId, cloneVar,
9   newExportedVar, newLocalVar, newDummyVar, newTyVar,
10   
11   Builtins(..), sumTyCon, prodTyCon,
12   combinePAVar,
13   builtin, builtins,
14
15   GlobalEnv(..),
16   setFamInstEnv,
17   readGEnv, setGEnv, updGEnv,
18
19   LocalEnv(..),
20   readLEnv, setLEnv, updLEnv,
21
22   getBindName, inBind,
23
24   lookupVar, defGlobalVar,
25   lookupTyCon, defTyCon,
26   lookupDataCon, defDataCon,
27   lookupTyConPA, defTyConPA, defTyConPAs,
28   lookupTyConPR,
29   lookupBoxedTyCon,
30   lookupPrimMethod, lookupPrimPArray,
31   lookupTyVarPA, defLocalTyVar, defLocalTyVarWithPA, localTyVars,
32
33   {-lookupInst,-} lookupFamInst
34 ) where
35
36 #include "HsVersions.h"
37
38 import VectBuiltIn
39
40 import HscTypes hiding  ( MonadThings(..) )
41 import Module           ( PackageId )
42 import CoreSyn
43 import TyCon
44 import DataCon
45 import Type
46 import Var
47 import VarEnv
48 import Id
49 import Name
50 import NameEnv
51 import IOEnv         ( liftIO )
52
53 import DsMonad
54
55 import InstEnv
56 import FamInstEnv
57
58 import Outputable
59 import FastString
60 import SrcLoc        ( noSrcSpan )
61
62 import Control.Monad
63
64 data Scope a b = Global a | Local b
65
66 -- ----------------------------------------------------------------------------
67 -- Vectorisation monad
68
69 data GlobalEnv = GlobalEnv {
70                   -- Mapping from global variables to their vectorised versions.
71                   -- 
72                   global_vars :: VarEnv Var
73
74                   -- Exported variables which have a vectorised version
75                   --
76                 , global_exported_vars :: VarEnv (Var, Var)
77
78                   -- Mapping from TyCons to their vectorised versions.
79                   -- TyCons which do not have to be vectorised are mapped to
80                   -- themselves.
81                   --
82                 , global_tycons :: NameEnv TyCon
83
84                   -- Mapping from DataCons to their vectorised versions
85                   --
86                 , global_datacons :: NameEnv DataCon
87
88                   -- Mapping from TyCons to their PA dfuns
89                   --
90                 , global_pa_funs :: NameEnv Var
91
92                   -- Mapping from TyCons to their PR dfuns
93                 , global_pr_funs :: NameEnv Var
94
95                   -- Mapping from unboxed TyCons to their boxed versions
96                 , global_boxed_tycons :: NameEnv TyCon
97
98                 -- External package inst-env & home-package inst-env for class
99                 -- instances
100                 --
101                 , global_inst_env :: (InstEnv, InstEnv)
102
103                 -- External package inst-env & home-package inst-env for family
104                 -- instances
105                 --
106                 , global_fam_inst_env :: FamInstEnvs
107
108                 -- Hoisted bindings
109                 , global_bindings :: [(Var, CoreExpr)]
110                 }
111
112 data LocalEnv = LocalEnv {
113                  -- Mapping from local variables to their vectorised and
114                  -- lifted versions
115                  --
116                  local_vars :: VarEnv (Var, Var)
117
118                  -- In-scope type variables
119                  --
120                , local_tyvars :: [TyVar]
121
122                  -- Mapping from tyvars to their PA dictionaries
123                , local_tyvar_pa :: VarEnv CoreExpr
124
125                  -- Local binding name
126                , local_bind_name :: FastString
127                }
128
129 initGlobalEnv :: VectInfo -> (InstEnv, InstEnv) -> FamInstEnvs -> GlobalEnv
130 initGlobalEnv info instEnvs famInstEnvs
131   = GlobalEnv {
132       global_vars          = mapVarEnv snd $ vectInfoVar info
133     , global_exported_vars = emptyVarEnv
134     , global_tycons        = mapNameEnv snd $ vectInfoTyCon info
135     , global_datacons      = mapNameEnv snd $ vectInfoDataCon info
136     , global_pa_funs       = mapNameEnv snd $ vectInfoPADFun info
137     , global_pr_funs       = emptyNameEnv
138     , global_boxed_tycons  = emptyNameEnv
139     , global_inst_env      = instEnvs
140     , global_fam_inst_env  = famInstEnvs
141     , global_bindings      = []
142     }
143
144 extendImportedVarsEnv :: [(Var, Var)] -> GlobalEnv -> GlobalEnv
145 extendImportedVarsEnv ps genv
146   = genv { global_vars = extendVarEnvList (global_vars genv) ps }
147
148 setFamInstEnv :: FamInstEnv -> GlobalEnv -> GlobalEnv
149 setFamInstEnv l_fam_inst genv
150   = genv { global_fam_inst_env = (g_fam_inst, l_fam_inst) }
151   where
152     (g_fam_inst, _) = global_fam_inst_env genv
153
154 extendTyConsEnv :: [(Name, TyCon)] -> GlobalEnv -> GlobalEnv
155 extendTyConsEnv ps genv
156   = genv { global_tycons = extendNameEnvList (global_tycons genv) ps }
157
158 extendDataConsEnv :: [(Name, DataCon)] -> GlobalEnv -> GlobalEnv
159 extendDataConsEnv ps genv
160   = genv { global_datacons = extendNameEnvList (global_datacons genv) ps }
161
162 extendPAFunsEnv :: [(Name, Var)] -> GlobalEnv -> GlobalEnv
163 extendPAFunsEnv ps genv
164   = genv { global_pa_funs = extendNameEnvList (global_pa_funs genv) ps }
165
166 setPRFunsEnv :: [(Name, Var)] -> GlobalEnv -> GlobalEnv
167 setPRFunsEnv ps genv
168   = genv { global_pr_funs = mkNameEnv ps }
169
170 setBoxedTyConsEnv :: [(Name, TyCon)] -> GlobalEnv -> GlobalEnv
171 setBoxedTyConsEnv ps genv
172   = genv { global_boxed_tycons = mkNameEnv ps }
173
174 emptyLocalEnv :: LocalEnv
175 emptyLocalEnv = LocalEnv {
176                    local_vars     = emptyVarEnv
177                  , local_tyvars   = []
178                  , local_tyvar_pa = emptyVarEnv
179                  , local_bind_name  = fsLit "fn"
180                  }
181
182 -- FIXME
183 updVectInfo :: GlobalEnv -> TypeEnv -> VectInfo -> VectInfo
184 updVectInfo env tyenv info
185   = info {
186       vectInfoVar     = global_exported_vars env
187     , vectInfoTyCon   = mk_env typeEnvTyCons global_tycons
188     , vectInfoDataCon = mk_env typeEnvDataCons global_datacons
189     , vectInfoPADFun  = mk_env typeEnvTyCons global_pa_funs
190     }
191   where
192     mk_env from_tyenv from_env = mkNameEnv [(name, (from,to))
193                                    | from <- from_tyenv tyenv
194                                    , let name = getName from
195                                    , Just to <- [lookupNameEnv (from_env env) name]]
196
197 data VResult a = Yes GlobalEnv LocalEnv a | No
198
199 newtype VM a = VM { runVM :: Builtins -> GlobalEnv -> LocalEnv -> DsM (VResult a) }
200
201 instance Monad VM where
202   return x   = VM $ \_  genv lenv -> return (Yes genv lenv x)
203   VM p >>= f = VM $ \bi genv lenv -> do
204                                       r <- p bi genv lenv
205                                       case r of
206                                         Yes genv' lenv' x -> runVM (f x) bi genv' lenv'
207                                         No                -> return No
208
209
210 cantVectorise :: String -> SDoc -> a
211 cantVectorise s d = pgmError
212                   . showSDocDump
213                   $ vcat [text "*** Vectorisation error ***",
214                           nest 4 $ sep [text s, nest 4 d]]
215
216 maybeCantVectorise :: String -> SDoc -> Maybe a -> a
217 maybeCantVectorise s d Nothing  = cantVectorise s d
218 maybeCantVectorise _ _ (Just x) = x
219
220 maybeCantVectoriseM :: Monad m => String -> SDoc -> m (Maybe a) -> m a
221 maybeCantVectoriseM s d p
222   = do
223       r <- p
224       case r of
225         Just x  -> return x
226         Nothing -> cantVectorise s d
227
228 noV :: VM a
229 noV = VM $ \_ _ _ -> return No
230
231 traceNoV :: String -> SDoc -> VM a
232 traceNoV s d = pprTrace s d noV
233
234 tryV :: VM a -> VM (Maybe a)
235 tryV (VM p) = VM $ \bi genv lenv ->
236   do
237     r <- p bi genv lenv
238     case r of
239       Yes genv' lenv' x -> return (Yes genv' lenv' (Just x))
240       No                -> return (Yes genv  lenv  Nothing)
241
242 maybeV :: VM (Maybe a) -> VM a
243 maybeV p = maybe noV return =<< p
244
245 traceMaybeV :: String -> SDoc -> VM (Maybe a) -> VM a
246 traceMaybeV s d p = maybe (traceNoV s d) return =<< p
247
248 orElseV :: VM a -> VM a -> VM a
249 orElseV p q = maybe q return =<< tryV p
250
251 fixV :: (a -> VM a) -> VM a
252 fixV f = VM (\bi genv lenv -> fixDs $ \r -> runVM (f (unYes r)) bi genv lenv )
253   where
254     -- NOTE: It is essential that we are lazy in r above so do not replace
255     --       calls to this function by an explicit case.
256     unYes (Yes _ _ x) = x
257     unYes No          = panic "VectMonad.fixV: no result"
258
259 localV :: VM a -> VM a
260 localV p = do
261              env <- readLEnv id
262              x <- p
263              setLEnv env
264              return x
265
266 closedV :: VM a -> VM a
267 closedV p = do
268               env <- readLEnv id
269               setLEnv (emptyLocalEnv { local_bind_name = local_bind_name env })
270               x <- p
271               setLEnv env
272               return x
273
274 liftDs :: DsM a -> VM a
275 liftDs p = VM $ \_ genv lenv -> do { x <- p; return (Yes genv lenv x) }
276
277 liftBuiltinDs :: (Builtins -> DsM a) -> VM a
278 liftBuiltinDs p = VM $ \bi genv lenv -> do { x <- p bi; return (Yes genv lenv x)}
279
280 builtin :: (Builtins -> a) -> VM a
281 builtin f = VM $ \bi genv lenv -> return (Yes genv lenv (f bi))
282
283 builtins :: (a -> Builtins -> b) -> VM (a -> b)
284 builtins f = VM $ \bi genv lenv -> return (Yes genv lenv (`f` bi))
285
286 readGEnv :: (GlobalEnv -> a) -> VM a
287 readGEnv f = VM $ \_ genv lenv -> return (Yes genv lenv (f genv))
288
289 setGEnv :: GlobalEnv -> VM ()
290 setGEnv genv = VM $ \_ _ lenv -> return (Yes genv lenv ())
291
292 updGEnv :: (GlobalEnv -> GlobalEnv) -> VM ()
293 updGEnv f = VM $ \_ genv lenv -> return (Yes (f genv) lenv ())
294
295 readLEnv :: (LocalEnv -> a) -> VM a
296 readLEnv f = VM $ \_ genv lenv -> return (Yes genv lenv (f lenv))
297
298 setLEnv :: LocalEnv -> VM ()
299 setLEnv lenv = VM $ \_ genv _ -> return (Yes genv lenv ())
300
301 updLEnv :: (LocalEnv -> LocalEnv) -> VM ()
302 updLEnv f = VM $ \_ genv lenv -> return (Yes genv (f lenv) ())
303
304 {-
305 getInstEnv :: VM (InstEnv, InstEnv)
306 getInstEnv = readGEnv global_inst_env
307 -}
308
309 getFamInstEnv :: VM FamInstEnvs
310 getFamInstEnv = readGEnv global_fam_inst_env
311
312 getBindName :: VM FastString
313 getBindName = readLEnv local_bind_name
314
315 inBind :: Id -> VM a -> VM a
316 inBind id p
317   = do updLEnv $ \env -> env { local_bind_name = occNameFS (getOccName id) }
318        p
319
320 cloneName :: (OccName -> OccName) -> Name -> VM Name
321 cloneName mk_occ name = liftM make (liftDs newUnique)
322   where
323     occ_name = mk_occ (nameOccName name)
324
325     make u | isExternalName name = mkExternalName u (nameModule name)
326                                                     occ_name
327                                                     (nameSrcSpan name)
328            | otherwise           = mkSystemName u occ_name
329
330 cloneId :: (OccName -> OccName) -> Id -> Type -> VM Id
331 cloneId mk_occ id ty
332   = do
333       name <- cloneName mk_occ (getName id)
334       let id' | isExportedId id = Id.mkExportedLocalId name ty
335               | otherwise       = Id.mkLocalId         name ty
336       return id'
337
338 cloneVar :: Var -> VM Var
339 cloneVar var = liftM (setIdUnique var) (liftDs newUnique)
340
341 newExportedVar :: OccName -> Type -> VM Var
342 newExportedVar occ_name ty 
343   = do
344       mod <- liftDs getModuleDs
345       u   <- liftDs newUnique
346
347       let name = mkExternalName u mod occ_name noSrcSpan
348       
349       return $ Id.mkExportedLocalId name ty
350
351 newLocalVar :: FastString -> Type -> VM Var
352 newLocalVar fs ty
353   = do
354       u <- liftDs newUnique
355       return $ mkSysLocal fs u ty
356
357 newDummyVar :: Type -> VM Var
358 newDummyVar = newLocalVar (fsLit "vv")
359
360 newTyVar :: FastString -> Kind -> VM Var
361 newTyVar fs k
362   = do
363       u <- liftDs newUnique
364       return $ mkTyVar (mkSysTvName u fs) k
365
366 defGlobalVar :: Var -> Var -> VM ()
367 defGlobalVar v v' = updGEnv $ \env ->
368   env { global_vars = extendVarEnv (global_vars env) v v'
369       , global_exported_vars = upd (global_exported_vars env)
370       }
371   where
372     upd env | isExportedId v = extendVarEnv env v (v, v')
373             | otherwise      = env
374
375 lookupVar :: Var -> VM (Scope Var (Var, Var))
376 lookupVar v
377   = do
378       r <- readLEnv $ \env -> lookupVarEnv (local_vars env) v
379       case r of
380         Just e  -> return (Local e)
381         Nothing -> liftM Global
382                 . maybeCantVectoriseM "Variable not vectorised:" (ppr v)
383                 . readGEnv $ \env -> lookupVarEnv (global_vars env) v
384
385 lookupTyCon :: TyCon -> VM (Maybe TyCon)
386 lookupTyCon tc
387   | isUnLiftedTyCon tc || isTupleTyCon tc = return (Just tc)
388
389   | otherwise = readGEnv $ \env -> lookupNameEnv (global_tycons env) (tyConName tc)
390
391 defTyCon :: TyCon -> TyCon -> VM ()
392 defTyCon tc tc' = updGEnv $ \env ->
393   env { global_tycons = extendNameEnv (global_tycons env) (tyConName tc) tc' }
394
395 lookupDataCon :: DataCon -> VM (Maybe DataCon)
396 lookupDataCon dc
397   | isTupleTyCon (dataConTyCon dc) = return (Just dc)
398   | otherwise = readGEnv $ \env -> lookupNameEnv (global_datacons env) (dataConName dc)
399
400 defDataCon :: DataCon -> DataCon -> VM ()
401 defDataCon dc dc' = updGEnv $ \env ->
402   env { global_datacons = extendNameEnv (global_datacons env) (dataConName dc) dc' }
403
404 lookupPrimPArray :: TyCon -> VM (Maybe TyCon)
405 lookupPrimPArray = liftBuiltinDs . primPArray
406
407 lookupPrimMethod :: TyCon -> String -> VM (Maybe Var)
408 lookupPrimMethod tycon = liftBuiltinDs . primMethod tycon
409
410 lookupTyConPA :: TyCon -> VM (Maybe Var)
411 lookupTyConPA tc = readGEnv $ \env -> lookupNameEnv (global_pa_funs env) (tyConName tc)
412
413 defTyConPA :: TyCon -> Var -> VM ()
414 defTyConPA tc pa = updGEnv $ \env ->
415   env { global_pa_funs = extendNameEnv (global_pa_funs env) (tyConName tc) pa }
416
417 defTyConPAs :: [(TyCon, Var)] -> VM ()
418 defTyConPAs ps = updGEnv $ \env ->
419   env { global_pa_funs = extendNameEnvList (global_pa_funs env)
420                                            [(tyConName tc, pa) | (tc, pa) <- ps] }
421
422 lookupTyVarPA :: Var -> VM (Maybe CoreExpr)
423 lookupTyVarPA tv = readLEnv $ \env -> lookupVarEnv (local_tyvar_pa env) tv
424
425 lookupTyConPR :: TyCon -> VM (Maybe Var)
426 lookupTyConPR tc = readGEnv $ \env -> lookupNameEnv (global_pr_funs env) (tyConName tc)
427
428 lookupBoxedTyCon :: TyCon -> VM (Maybe TyCon)
429 lookupBoxedTyCon tc = readGEnv $ \env -> lookupNameEnv (global_boxed_tycons env)
430                                                        (tyConName tc)
431
432 defLocalTyVar :: TyVar -> VM ()
433 defLocalTyVar tv = updLEnv $ \env ->
434   env { local_tyvars   = tv : local_tyvars env
435       , local_tyvar_pa = local_tyvar_pa env `delVarEnv` tv
436       }
437
438 defLocalTyVarWithPA :: TyVar -> CoreExpr -> VM ()
439 defLocalTyVarWithPA tv pa = updLEnv $ \env ->
440   env { local_tyvars   = tv : local_tyvars env
441       , local_tyvar_pa = extendVarEnv (local_tyvar_pa env) tv pa
442       }
443
444 localTyVars :: VM [TyVar]
445 localTyVars = readLEnv (reverse . local_tyvars)
446
447 -- Look up the dfun of a class instance.
448 --
449 -- The match must be unique - ie, match exactly one instance - but the 
450 -- type arguments used for matching may be more specific than those of 
451 -- the class instance declaration.  The found class instances must not have
452 -- any type variables in the instance context that do not appear in the
453 -- instances head (i.e., no flexi vars); for details for what this means,
454 -- see the docs at InstEnv.lookupInstEnv.
455 --
456 {-
457 lookupInst :: Class -> [Type] -> VM (DFunId, [Type])
458 lookupInst cls tys
459   = do { instEnv <- getInstEnv
460        ; case lookupInstEnv instEnv cls tys of
461            ([(inst, inst_tys)], _) 
462              | noFlexiVar -> return (instanceDFunId inst, inst_tys')
463              | otherwise  -> pprPanic "VectMonad.lookupInst: flexi var: " 
464                                       (ppr $ mkTyConApp (classTyCon cls) tys)
465              where
466                inst_tys'  = [ty | Right ty <- inst_tys]
467                noFlexiVar = all isRight inst_tys
468            _other         -> traceNoV "lookupInst" (ppr cls <+> ppr tys)
469        }
470   where
471     isRight (Left  _) = False
472     isRight (Right _) = True
473 -}
474
475 -- Look up the representation tycon of a family instance.
476 --
477 -- The match must be unique - ie, match exactly one instance - but the 
478 -- type arguments used for matching may be more specific than those of 
479 -- the family instance declaration.
480 --
481 -- Return the instance tycon and its type instance.  For example, if we have
482 --
483 --  lookupFamInst 'T' '[Int]' yields (':R42T', 'Int')
484 --
485 -- then we have a coercion (ie, type instance of family instance coercion)
486 --
487 --  :Co:R42T Int :: T [Int] ~ :R42T Int
488 --
489 -- which implies that :R42T was declared as 'data instance T [a]'.
490 --
491 lookupFamInst :: TyCon -> [Type] -> VM (TyCon, [Type])
492 lookupFamInst tycon tys
493   = ASSERT( isOpenTyCon tycon )
494     do { instEnv <- getFamInstEnv
495        ; case lookupFamInstEnv instEnv tycon tys of
496            [(fam_inst, rep_tys)] -> return (famInstTyCon fam_inst, rep_tys)
497            _other                -> 
498              pprPanic "VectMonad.lookupFamInst: not found: " 
499                       (ppr $ mkTyConApp tycon tys)
500        }
501
502 initV :: PackageId -> HscEnv -> ModGuts -> VectInfo -> VM a -> IO (Maybe (VectInfo, a))
503 initV pkg hsc_env guts info p
504   = do
505          -- XXX: ignores error messages and warnings, check that this is
506          -- indeed ok (the use of "Just r" suggests so)
507       (_,Just r) <- initDs hsc_env (mg_module guts)
508                                (mg_rdr_env guts)
509                                (mg_types guts)
510                                go
511       return r
512   where
513
514     go =
515       do
516         builtins       <- initBuiltins pkg
517         builtin_vars   <- initBuiltinVars builtins
518         builtin_tycons <- initBuiltinTyCons builtins
519         let builtin_datacons = initBuiltinDataCons builtins
520         builtin_pas    <- initBuiltinPAs builtins
521         builtin_prs    <- initBuiltinPRs builtins
522         builtin_boxed  <- initBuiltinBoxedTyCons builtins
523
524         eps <- liftIO $ hscEPS hsc_env
525         let famInstEnvs = (eps_fam_inst_env eps, mg_fam_inst_env guts)
526             instEnvs    = (eps_inst_env     eps, mg_inst_env     guts)
527
528         let genv = extendImportedVarsEnv builtin_vars
529                  . extendTyConsEnv builtin_tycons
530                  . extendDataConsEnv builtin_datacons
531                  . extendPAFunsEnv builtin_pas
532                  . setPRFunsEnv    builtin_prs
533                  . setBoxedTyConsEnv builtin_boxed
534                  $ initGlobalEnv info instEnvs famInstEnvs
535
536         r <- runVM p builtins genv emptyLocalEnv
537         case r of
538           Yes genv _ x -> return $ Just (new_info genv, x)
539           No           -> return Nothing
540
541     new_info genv = updVectInfo genv (mg_types guts) info
542