2e100a9223594202213799952bdf6fb645c76d52
[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,
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 noV :: VM a
210 noV = VM $ \_ _ _ -> return No
211
212 traceNoV :: String -> SDoc -> VM a
213 traceNoV s d = pprTrace s d noV
214
215 tryV :: VM a -> VM (Maybe a)
216 tryV (VM p) = VM $ \bi genv lenv ->
217   do
218     r <- p bi genv lenv
219     case r of
220       Yes genv' lenv' x -> return (Yes genv' lenv' (Just x))
221       No                -> return (Yes genv  lenv  Nothing)
222
223 maybeV :: VM (Maybe a) -> VM a
224 maybeV p = maybe noV return =<< p
225
226 traceMaybeV :: String -> SDoc -> VM (Maybe a) -> VM a
227 traceMaybeV s d p = maybe (traceNoV s d) return =<< p
228
229 orElseV :: VM a -> VM a -> VM a
230 orElseV p q = maybe q return =<< tryV p
231
232 fixV :: (a -> VM a) -> VM a
233 fixV f = VM (\bi genv lenv -> fixDs $ \r -> runVM (f (unYes r)) bi genv lenv )
234   where
235     -- NOTE: It is essential that we are lazy in r above so do not replace
236     --       calls to this function by an explicit case.
237     unYes (Yes _ _ x) = x
238     unYes No          = panic "VectMonad.fixV: no result"
239
240 localV :: VM a -> VM a
241 localV p = do
242              env <- readLEnv id
243              x <- p
244              setLEnv env
245              return x
246
247 closedV :: VM a -> VM a
248 closedV p = do
249               env <- readLEnv id
250               setLEnv (emptyLocalEnv { local_bind_name = local_bind_name env })
251               x <- p
252               setLEnv env
253               return x
254
255 liftDs :: DsM a -> VM a
256 liftDs p = VM $ \_ genv lenv -> do { x <- p; return (Yes genv lenv x) }
257
258 liftBuiltinDs :: (Builtins -> DsM a) -> VM a
259 liftBuiltinDs p = VM $ \bi genv lenv -> do { x <- p bi; return (Yes genv lenv x)}
260
261 builtin :: (Builtins -> a) -> VM a
262 builtin f = VM $ \bi genv lenv -> return (Yes genv lenv (f bi))
263
264 builtins :: (a -> Builtins -> b) -> VM (a -> b)
265 builtins f = VM $ \bi genv lenv -> return (Yes genv lenv (`f` bi))
266
267 readGEnv :: (GlobalEnv -> a) -> VM a
268 readGEnv f = VM $ \_ genv lenv -> return (Yes genv lenv (f genv))
269
270 setGEnv :: GlobalEnv -> VM ()
271 setGEnv genv = VM $ \_ _ lenv -> return (Yes genv lenv ())
272
273 updGEnv :: (GlobalEnv -> GlobalEnv) -> VM ()
274 updGEnv f = VM $ \_ genv lenv -> return (Yes (f genv) lenv ())
275
276 readLEnv :: (LocalEnv -> a) -> VM a
277 readLEnv f = VM $ \_ genv lenv -> return (Yes genv lenv (f lenv))
278
279 setLEnv :: LocalEnv -> VM ()
280 setLEnv lenv = VM $ \_ genv _ -> return (Yes genv lenv ())
281
282 updLEnv :: (LocalEnv -> LocalEnv) -> VM ()
283 updLEnv f = VM $ \_ genv lenv -> return (Yes genv (f lenv) ())
284
285 {-
286 getInstEnv :: VM (InstEnv, InstEnv)
287 getInstEnv = readGEnv global_inst_env
288 -}
289
290 getFamInstEnv :: VM FamInstEnvs
291 getFamInstEnv = readGEnv global_fam_inst_env
292
293 getBindName :: VM FastString
294 getBindName = readLEnv local_bind_name
295
296 inBind :: Id -> VM a -> VM a
297 inBind id p
298   = do updLEnv $ \env -> env { local_bind_name = occNameFS (getOccName id) }
299        p
300
301 cloneName :: (OccName -> OccName) -> Name -> VM Name
302 cloneName mk_occ name = liftM make (liftDs newUnique)
303   where
304     occ_name = mk_occ (nameOccName name)
305
306     make u | isExternalName name = mkExternalName u (nameModule name)
307                                                     occ_name
308                                                     (nameSrcSpan name)
309            | otherwise           = mkSystemName u occ_name
310
311 cloneId :: (OccName -> OccName) -> Id -> Type -> VM Id
312 cloneId mk_occ id ty
313   = do
314       name <- cloneName mk_occ (getName id)
315       let id' | isExportedId id = Id.mkExportedLocalId name ty
316               | otherwise       = Id.mkLocalId         name ty
317       return id'
318
319 cloneVar :: Var -> VM Var
320 cloneVar var = liftM (setIdUnique var) (liftDs newUnique)
321
322 newExportedVar :: OccName -> Type -> VM Var
323 newExportedVar occ_name ty 
324   = do
325       mod <- liftDs getModuleDs
326       u   <- liftDs newUnique
327
328       let name = mkExternalName u mod occ_name noSrcSpan
329       
330       return $ Id.mkExportedLocalId name ty
331
332 newLocalVar :: FastString -> Type -> VM Var
333 newLocalVar fs ty
334   = do
335       u <- liftDs newUnique
336       return $ mkSysLocal fs u ty
337
338 newDummyVar :: Type -> VM Var
339 newDummyVar = newLocalVar (fsLit "vv")
340
341 newTyVar :: FastString -> Kind -> VM Var
342 newTyVar fs k
343   = do
344       u <- liftDs newUnique
345       return $ mkTyVar (mkSysTvName u fs) k
346
347 defGlobalVar :: Var -> Var -> VM ()
348 defGlobalVar v v' = updGEnv $ \env ->
349   env { global_vars = extendVarEnv (global_vars env) v v'
350       , global_exported_vars = upd (global_exported_vars env)
351       }
352   where
353     upd env | isExportedId v = extendVarEnv env v (v, v')
354             | otherwise      = env
355
356 lookupVar :: Var -> VM (Scope Var (Var, Var))
357 lookupVar v
358   = do
359       r <- readLEnv $ \env -> lookupVarEnv (local_vars env) v
360       case r of
361         Just e  -> return (Local e)
362         Nothing -> liftM Global
363                  $  traceMaybeV "lookupVar" (ppr v)
364                                 (readGEnv $ \env -> lookupVarEnv (global_vars env) v)
365
366 lookupTyCon :: TyCon -> VM (Maybe TyCon)
367 lookupTyCon tc
368   | isUnLiftedTyCon tc || isTupleTyCon tc = return (Just tc)
369
370   | otherwise = readGEnv $ \env -> lookupNameEnv (global_tycons env) (tyConName tc)
371
372 defTyCon :: TyCon -> TyCon -> VM ()
373 defTyCon tc tc' = updGEnv $ \env ->
374   env { global_tycons = extendNameEnv (global_tycons env) (tyConName tc) tc' }
375
376 lookupDataCon :: DataCon -> VM (Maybe DataCon)
377 lookupDataCon dc
378   | isTupleTyCon (dataConTyCon dc) = return (Just dc)
379   | otherwise = readGEnv $ \env -> lookupNameEnv (global_datacons env) (dataConName dc)
380
381 defDataCon :: DataCon -> DataCon -> VM ()
382 defDataCon dc dc' = updGEnv $ \env ->
383   env { global_datacons = extendNameEnv (global_datacons env) (dataConName dc) dc' }
384
385 lookupPrimPArray :: TyCon -> VM (Maybe TyCon)
386 lookupPrimPArray = liftBuiltinDs . primPArray
387
388 lookupPrimMethod :: TyCon -> String -> VM (Maybe Var)
389 lookupPrimMethod tycon = liftBuiltinDs . primMethod tycon
390
391 lookupTyConPA :: TyCon -> VM (Maybe Var)
392 lookupTyConPA tc = readGEnv $ \env -> lookupNameEnv (global_pa_funs env) (tyConName tc)
393
394 defTyConPA :: TyCon -> Var -> VM ()
395 defTyConPA tc pa = updGEnv $ \env ->
396   env { global_pa_funs = extendNameEnv (global_pa_funs env) (tyConName tc) pa }
397
398 defTyConPAs :: [(TyCon, Var)] -> VM ()
399 defTyConPAs ps = updGEnv $ \env ->
400   env { global_pa_funs = extendNameEnvList (global_pa_funs env)
401                                            [(tyConName tc, pa) | (tc, pa) <- ps] }
402
403 lookupTyVarPA :: Var -> VM (Maybe CoreExpr)
404 lookupTyVarPA tv = readLEnv $ \env -> lookupVarEnv (local_tyvar_pa env) tv
405
406 lookupTyConPR :: TyCon -> VM (Maybe Var)
407 lookupTyConPR tc = readGEnv $ \env -> lookupNameEnv (global_pr_funs env) (tyConName tc)
408
409 lookupBoxedTyCon :: TyCon -> VM (Maybe TyCon)
410 lookupBoxedTyCon tc = readGEnv $ \env -> lookupNameEnv (global_boxed_tycons env)
411                                                        (tyConName tc)
412
413 defLocalTyVar :: TyVar -> VM ()
414 defLocalTyVar tv = updLEnv $ \env ->
415   env { local_tyvars   = tv : local_tyvars env
416       , local_tyvar_pa = local_tyvar_pa env `delVarEnv` tv
417       }
418
419 defLocalTyVarWithPA :: TyVar -> CoreExpr -> VM ()
420 defLocalTyVarWithPA tv pa = updLEnv $ \env ->
421   env { local_tyvars   = tv : local_tyvars env
422       , local_tyvar_pa = extendVarEnv (local_tyvar_pa env) tv pa
423       }
424
425 localTyVars :: VM [TyVar]
426 localTyVars = readLEnv (reverse . local_tyvars)
427
428 -- Look up the dfun of a class instance.
429 --
430 -- The match must be unique - ie, match exactly one instance - but the 
431 -- type arguments used for matching may be more specific than those of 
432 -- the class instance declaration.  The found class instances must not have
433 -- any type variables in the instance context that do not appear in the
434 -- instances head (i.e., no flexi vars); for details for what this means,
435 -- see the docs at InstEnv.lookupInstEnv.
436 --
437 {-
438 lookupInst :: Class -> [Type] -> VM (DFunId, [Type])
439 lookupInst cls tys
440   = do { instEnv <- getInstEnv
441        ; case lookupInstEnv instEnv cls tys of
442            ([(inst, inst_tys)], _) 
443              | noFlexiVar -> return (instanceDFunId inst, inst_tys')
444              | otherwise  -> pprPanic "VectMonad.lookupInst: flexi var: " 
445                                       (ppr $ mkTyConApp (classTyCon cls) tys)
446              where
447                inst_tys'  = [ty | Right ty <- inst_tys]
448                noFlexiVar = all isRight inst_tys
449            _other         -> traceNoV "lookupInst" (ppr cls <+> ppr tys)
450        }
451   where
452     isRight (Left  _) = False
453     isRight (Right _) = True
454 -}
455
456 -- Look up the representation tycon of a family instance.
457 --
458 -- The match must be unique - ie, match exactly one instance - but the 
459 -- type arguments used for matching may be more specific than those of 
460 -- the family instance declaration.
461 --
462 -- Return the instance tycon and its type instance.  For example, if we have
463 --
464 --  lookupFamInst 'T' '[Int]' yields (':R42T', 'Int')
465 --
466 -- then we have a coercion (ie, type instance of family instance coercion)
467 --
468 --  :Co:R42T Int :: T [Int] ~ :R42T Int
469 --
470 -- which implies that :R42T was declared as 'data instance T [a]'.
471 --
472 lookupFamInst :: TyCon -> [Type] -> VM (TyCon, [Type])
473 lookupFamInst tycon tys
474   = ASSERT( isOpenTyCon tycon )
475     do { instEnv <- getFamInstEnv
476        ; case lookupFamInstEnv instEnv tycon tys of
477            [(fam_inst, rep_tys)] -> return (famInstTyCon fam_inst, rep_tys)
478            _other                -> 
479              pprPanic "VectMonad.lookupFamInst: not found: " 
480                       (ppr $ mkTyConApp tycon tys)
481        }
482
483 initV :: PackageId -> HscEnv -> ModGuts -> VectInfo -> VM a -> IO (Maybe (VectInfo, a))
484 initV pkg hsc_env guts info p
485   = do
486          -- XXX: ignores error messages and warnings, check that this is
487          -- indeed ok (the use of "Just r" suggests so)
488       (_,Just r) <- initDs hsc_env (mg_module guts)
489                                (mg_rdr_env guts)
490                                (mg_types guts)
491                                go
492       return r
493   where
494
495     go =
496       do
497         builtins       <- initBuiltins pkg
498         builtin_vars   <- initBuiltinVars builtins
499         builtin_tycons <- initBuiltinTyCons builtins
500         let builtin_datacons = initBuiltinDataCons builtins
501         builtin_pas    <- initBuiltinPAs builtins
502         builtin_prs    <- initBuiltinPRs builtins
503         builtin_boxed  <- initBuiltinBoxedTyCons builtins
504
505         eps <- liftIO $ hscEPS hsc_env
506         let famInstEnvs = (eps_fam_inst_env eps, mg_fam_inst_env guts)
507             instEnvs    = (eps_inst_env     eps, mg_inst_env     guts)
508
509         let genv = extendImportedVarsEnv builtin_vars
510                  . extendTyConsEnv builtin_tycons
511                  . extendDataConsEnv builtin_datacons
512                  . extendPAFunsEnv builtin_pas
513                  . setPRFunsEnv    builtin_prs
514                  . setBoxedTyConsEnv builtin_boxed
515                  $ initGlobalEnv info instEnvs famInstEnvs
516
517         r <- runVM p builtins genv emptyLocalEnv
518         case r of
519           Yes genv _ x -> return $ Just (new_info genv, x)
520           No           -> return Nothing
521
522     new_info genv = updVectInfo genv (mg_types guts) info
523