1 {-# LANGUAGE PatternGuards, TypeSynonymInstances #-}
2 -- | This module provides a number of functions to find out things about Core
3 -- programs. This module does not provide the actual plumbing to work with
4 -- Core and Haskell (it uses HsTools for this), but only the functions that
5 -- know about various libraries and know which functions to call.
6 module CLasH.Utils.Core.CoreTools where
10 import System.IO.Unsafe
15 import qualified TcType
16 import qualified HsExpr
17 import qualified HsTypes
18 import qualified HsBinds
19 import qualified HscTypes
20 import qualified RdrName
22 import qualified OccName
25 import qualified TyCon
26 import qualified DataCon
27 import qualified TysWiredIn
29 import qualified DynFlags
30 import qualified SrcLoc
31 import qualified CoreSyn
33 import qualified IdInfo
34 import qualified VarSet
35 import qualified Unique
36 import qualified CoreUtils
37 import qualified CoreFVs
38 import qualified Literal
39 import qualified MkCore
40 import qualified VarEnv
41 import qualified Literal
44 import CLasH.Translator.TranslatorTypes
45 import CLasH.Utils.GhcTools
46 import CLasH.Utils.HsTools
47 import CLasH.Utils.Pretty
49 import qualified CLasH.Utils.Core.BinderTools as BinderTools
51 -- | A single binding, used as a shortcut to simplify type signatures.
52 type Binding = (CoreSyn.CoreBndr, CoreSyn.CoreExpr)
54 -- | Evaluate a core Type representing type level int from the tfp
55 -- library to a real int.
56 eval_tfp_int :: HscTypes.HscEnv -> Type.Type -> Int
58 unsafeRunGhc libdir $ do
60 -- Automatically import modules for any fully qualified identifiers
61 setDynFlag DynFlags.Opt_ImplicitImportQualified
63 let from_int_t_name = mkRdrName "Types.Data.Num.Ops" "fromIntegerT"
64 let from_int_t = SrcLoc.noLoc $ HsExpr.HsVar from_int_t_name
65 let undef = hsTypedUndef $ coreToHsType ty
66 let app = SrcLoc.noLoc $ HsExpr.HsApp (from_int_t) (undef)
67 let int_ty = SrcLoc.noLoc $ HsTypes.HsTyVar TysWiredIn.intTyCon_RDR
68 let expr = HsExpr.ExprWithTySig app int_ty
72 libdir = DynFlags.topDir dynflags
73 dynflags = HscTypes.hsc_dflags env
75 normalise_tfp_int :: HscTypes.HscEnv -> Type.Type -> Type.Type
76 normalise_tfp_int env ty =
78 nty <- normaliseType env ty
81 -- | Get the width of a SizedWord type
82 -- sized_word_len :: HscTypes.HscEnv -> Type.Type -> Int
83 -- sized_word_len env ty = eval_tfp_int env (sized_word_len_ty ty)
85 sized_word_len_ty :: Type.Type -> Type.Type
86 sized_word_len_ty ty = len
88 args = case Type.splitTyConApp_maybe ty of
89 Just (tycon, args) -> args
90 Nothing -> error $ "\nCoreTools.sized_word_len_ty: Not a sized word type: " ++ (pprString ty)
93 -- | Get the width of a SizedInt type
94 -- sized_int_len :: HscTypes.HscEnv -> Type.Type -> Int
95 -- sized_int_len env ty = eval_tfp_int env (sized_int_len_ty ty)
97 sized_int_len_ty :: Type.Type -> Type.Type
98 sized_int_len_ty ty = len
100 args = case Type.splitTyConApp_maybe ty of
101 Just (tycon, args) -> args
102 Nothing -> error $ "\nCoreTools.sized_int_len_ty: Not a sized int type: " ++ (pprString ty)
105 -- | Get the upperbound of a RangedWord type
106 -- ranged_word_bound :: HscTypes.HscEnv -> Type.Type -> Int
107 -- ranged_word_bound env ty = eval_tfp_int env (ranged_word_bound_ty ty)
109 ranged_word_bound_ty :: Type.Type -> Type.Type
110 ranged_word_bound_ty ty = len
112 args = case Type.splitTyConApp_maybe ty of
113 Just (tycon, args) -> args
114 Nothing -> error $ "\nCoreTools.ranged_word_bound_ty: Not a sized word type: " ++ (pprString ty)
117 -- | Evaluate a core Type representing type level int from the TypeLevel
118 -- library to a real int.
119 -- eval_type_level_int :: Type.Type -> Int
120 -- eval_type_level_int ty =
122 -- -- Automatically import modules for any fully qualified identifiers
123 -- setDynFlag DynFlags.Opt_ImplicitImportQualified
125 -- let to_int_name = mkRdrName "Data.TypeLevel.Num.Sets" "toInt"
126 -- let to_int = SrcLoc.noLoc $ HsExpr.HsVar to_int_name
127 -- let undef = hsTypedUndef $ coreToHsType ty
128 -- let app = HsExpr.HsApp (to_int) (undef)
130 -- core <- toCore [] app
133 -- | Get the length of a FSVec type
134 -- tfvec_len :: HscTypes.HscEnv -> Type.Type -> Int
135 -- tfvec_len env ty = eval_tfp_int env (tfvec_len_ty ty)
137 tfvec_len_ty :: Type.Type -> Type.Type
138 tfvec_len_ty ty = len
140 args = case Type.splitTyConApp_maybe ty of
141 Just (tycon, args) -> args
142 Nothing -> error $ "\nCoreTools.tfvec_len_ty: Not a vector type: " ++ (pprString ty)
145 -- | Get the element type of a TFVec type
146 tfvec_elem :: Type.Type -> Type.Type
147 tfvec_elem ty = el_ty
149 args = case Type.splitTyConApp_maybe ty of
150 Just (tycon, args) -> args
151 Nothing -> error $ "\nCoreTools.tfvec_len: Not a vector type: " ++ (pprString ty)
154 -- Is the given core expression a lambda abstraction?
155 is_lam :: CoreSyn.CoreExpr -> Bool
156 is_lam (CoreSyn.Lam _ _) = True
159 -- Is the given core expression of a function type?
160 is_fun :: CoreSyn.CoreExpr -> Bool
161 -- Treat Type arguments differently, because exprType is not defined for them.
162 is_fun (CoreSyn.Type _) = False
163 is_fun expr = (Type.isFunTy . CoreUtils.exprType) expr
165 -- Is the given core expression polymorphic (i.e., does it accept type
167 is_poly :: CoreSyn.CoreExpr -> Bool
168 -- Treat Type arguments differently, because exprType is not defined for them.
169 is_poly (CoreSyn.Type _) = False
170 is_poly expr = (Maybe.isJust . Type.splitForAllTy_maybe . CoreUtils.exprType) expr
172 -- Is the given core expression a variable reference?
173 is_var :: CoreSyn.CoreExpr -> Bool
174 is_var (CoreSyn.Var _) = True
177 is_lit :: CoreSyn.CoreExpr -> Bool
178 is_lit (CoreSyn.Lit _) = True
181 -- Can the given core expression be applied to something? This is true for
182 -- applying to a value as well as a type.
183 is_applicable :: CoreSyn.CoreExpr -> Bool
184 is_applicable expr = is_fun expr || is_poly expr
186 -- Is the given core expression a variable or an application?
187 is_simple :: CoreSyn.CoreExpr -> Bool
188 is_simple (CoreSyn.App _ _) = True
189 is_simple (CoreSyn.Var _) = True
190 is_simple (CoreSyn.Cast expr _) = is_simple expr
193 -- Does the given CoreExpr have any free type vars?
194 has_free_tyvars :: CoreSyn.CoreExpr -> Bool
195 has_free_tyvars = not . VarSet.isEmptyVarSet . (CoreFVs.exprSomeFreeVars Var.isTyVar)
197 -- Does the given type have any free type vars?
198 ty_has_free_tyvars :: Type.Type -> Bool
199 ty_has_free_tyvars = not . VarSet.isEmptyVarSet . Type.tyVarsOfType
201 -- Does the given CoreExpr have any free local vars?
202 has_free_vars :: CoreSyn.CoreExpr -> Bool
203 has_free_vars = not . VarSet.isEmptyVarSet . CoreFVs.exprFreeVars
205 -- Does the given expression use any of the given binders?
206 expr_uses_binders :: [CoreSyn.CoreBndr] -> CoreSyn.CoreExpr -> Bool
207 expr_uses_binders bndrs = not . VarSet.isEmptyVarSet . (CoreFVs.exprSomeFreeVars (`elem` bndrs))
209 -- Turns a Var CoreExpr into the Id inside it. Will of course only work for
210 -- simple Var CoreExprs, not complexer ones.
211 exprToVar :: CoreSyn.CoreExpr -> Var.Id
212 exprToVar (CoreSyn.Var id) = id
213 exprToVar expr = error $ "\nCoreTools.exprToVar: Not a var: " ++ show expr
215 -- Turns a Lit CoreExpr into the Literal inside it.
216 exprToLit :: CoreSyn.CoreExpr -> Literal.Literal
217 exprToLit (CoreSyn.Lit lit) = lit
218 exprToLit expr = error $ "\nCoreTools.exprToLit: Not a lit: " ++ show expr
220 -- Removes all the type and dictionary arguments from the given argument list,
221 -- leaving only the normal value arguments. The type given is the type of the
222 -- expression applied to this argument list.
223 get_val_args :: Type.Type -> [CoreSyn.CoreExpr] -> [CoreSyn.CoreExpr]
224 get_val_args ty args = drop n args
226 (tyvars, predtypes, _) = TcType.tcSplitSigmaTy ty
227 -- The first (length tyvars) arguments should be types, the next
228 -- (length predtypes) arguments should be dictionaries. We drop this many
229 -- arguments, to get at the value arguments.
230 n = length tyvars + length predtypes
232 getLiterals :: HscTypes.HscEnv -> CoreSyn.CoreExpr -> [CoreSyn.CoreExpr]
233 getLiterals _ app@(CoreSyn.App _ _) = literals
235 (CoreSyn.Var f, args) = CoreSyn.collectArgs app
236 literals = filter (is_lit) args
238 getLiterals _ lit@(CoreSyn.Lit _) = [lit]
240 getLiterals hscenv letrec@(CoreSyn.Let (CoreSyn.NonRec letBind (letExpr)) letRes) = [lit]
242 ty = Var.varType letBind
243 litInt = eval_tfp_int hscenv ty
244 lit = CoreSyn.Lit (Literal.mkMachInt (toInteger litInt))
246 getLiterals _ expr = error $ "\nCoreTools.getLiterals: Not a known Lit: " ++ pprString expr
248 reduceCoreListToHsList ::
249 [HscTypes.CoreModule] -- ^ The modules where parts of the list are hidden
250 -> CoreSyn.CoreExpr -- ^ The refence to atleast one of the nodes
251 -> TranslatorSession [CoreSyn.CoreExpr]
252 reduceCoreListToHsList cores app@(CoreSyn.App _ _) = do {
253 ; let { (fun, args) = CoreSyn.collectArgs app
258 ; let topelem = args!!1
260 (varz@(CoreSyn.Var id)) -> do {
261 ; binds <- mapM (findExpr (isVarName id)) cores
262 ; otherelems <- reduceCoreListToHsList cores (head (Maybe.catMaybes binds))
263 ; return (topelem:otherelems)
265 (appz@(CoreSyn.App _ _)) -> do {
266 ; otherelems <- reduceCoreListToHsList cores appz
267 ; return (topelem:otherelems)
269 otherwise -> return [topelem]
271 otherwise -> return []
274 isVarName :: Monad m => Var.Var -> Var.Var -> m Bool
275 isVarName lookfor bind = return $ (Var.varName lookfor) == (Var.varName bind)
277 reduceCoreListToHsList _ _ = return []
279 -- Is the given var the State data constructor?
280 isStateCon :: Var.Var -> Bool
282 -- See if it is a DataConWrapId (not DataConWorkId, since State is a
284 case Id.idDetails var of
285 IdInfo.DataConWrapId dc ->
286 -- See if the datacon is the State datacon from the State type.
287 let tycon = DataCon.dataConTyCon dc
288 tyname = Name.getOccString tycon
289 dcname = Name.getOccString dc
290 in case (tyname, dcname) of
291 ("State", "State") -> True
295 -- | Is the given type a State type?
296 isStateType :: Type.Type -> Bool
297 -- Resolve any type synonyms remaining
298 isStateType ty | Just ty' <- Type.tcView ty = isStateType ty'
299 isStateType ty = Maybe.isJust $ do
300 -- Split the type. Don't use normal splitAppTy, since that looks through
301 -- newtypes, and we want to see the State newtype.
302 (typef, _) <- Type.repSplitAppTy_maybe ty
303 -- See if the applied type is a type constructor
304 (tycon, _) <- Type.splitTyConApp_maybe typef
305 if TyCon.isNewTyCon tycon && Name.getOccString tycon == "State"
311 -- | Does the given TypedThing have a State type?
312 hasStateType :: (TypedThing t) => t -> Bool
313 hasStateType expr = case getType expr of
315 Just ty -> isStateType ty
318 -- | Flattens nested lets into a single list of bindings. The expression
319 -- passed does not have to be a let expression, if it isn't an empty list of
320 -- bindings is returned.
322 CoreSyn.CoreExpr -- ^ The expression to flatten.
323 -> ([Binding], CoreSyn.CoreExpr) -- ^ The bindings and resulting expression.
324 flattenLets (CoreSyn.Let binds expr) =
325 (bindings ++ bindings', expr')
327 -- Recursively flatten the contained expression
328 (bindings', expr') =flattenLets expr
329 -- Flatten our own bindings to remove the Rec / NonRec constructors
330 bindings = CoreSyn.flattenBinds [binds]
331 flattenLets expr = ([], expr)
333 -- | Create bunch of nested non-recursive let expressions from the given
334 -- bindings. The first binding is bound at the highest level (and thus
335 -- available in all other bindings).
336 mkNonRecLets :: [Binding] -> CoreSyn.CoreExpr -> CoreSyn.CoreExpr
337 mkNonRecLets bindings expr = MkCore.mkCoreLets binds expr
339 binds = map (uncurry CoreSyn.NonRec) bindings
341 -- | A class of things that (optionally) have a core Type. The type is
342 -- optional, since Type expressions don't have a type themselves.
343 class TypedThing t where
344 getType :: t -> Maybe Type.Type
346 instance TypedThing CoreSyn.CoreExpr where
347 getType (CoreSyn.Type _) = Nothing
348 getType expr = Just $ CoreUtils.exprType expr
350 instance TypedThing CoreSyn.CoreBndr where
351 getType = return . Id.idType
353 instance TypedThing Type.Type where
354 getType = return . id
356 -- | Generate new uniques for all binders in the given expression.
357 -- Does not support making type variables unique, though this could be
358 -- supported if required (by passing a CoreSubst.Subst instead of VarEnv to
359 -- genUniques' below).
360 genUniques :: CoreSyn.CoreExpr -> TranslatorSession CoreSyn.CoreExpr
361 genUniques = genUniques' VarEnv.emptyVarEnv
363 -- | A helper function to generate uniques, that takes a VarEnv containing the
364 -- substitutions already performed.
365 genUniques' :: VarEnv.VarEnv CoreSyn.CoreBndr -> CoreSyn.CoreExpr -> TranslatorSession CoreSyn.CoreExpr
366 genUniques' subst (CoreSyn.Var f) = do
367 -- Replace the binder with its new value, if applicable.
368 let f' = VarEnv.lookupWithDefaultVarEnv subst f f
369 return (CoreSyn.Var f')
370 -- Leave literals untouched
371 genUniques' subst (CoreSyn.Lit l) = return $ CoreSyn.Lit l
372 genUniques' subst (CoreSyn.App f arg) = do
373 -- Only work on subexpressions
374 f' <- genUniques' subst f
375 arg' <- genUniques' subst arg
376 return (CoreSyn.App f' arg')
377 -- Don't change type abstractions
378 genUniques' subst expr@(CoreSyn.Lam bndr res) | CoreSyn.isTyVar bndr = return expr
379 genUniques' subst (CoreSyn.Lam bndr res) = do
380 -- Generate a new unique for the bound variable
381 (subst', bndr') <- genUnique subst bndr
382 res' <- genUniques' subst' res
383 return (CoreSyn.Lam bndr' res')
384 genUniques' subst (CoreSyn.Let (CoreSyn.NonRec bndr bound) res) = do
385 -- Make the binders unique
386 (subst', bndr') <- genUnique subst bndr
387 bound' <- genUniques' subst' bound
388 res' <- genUniques' subst' res
389 return $ CoreSyn.Let (CoreSyn.NonRec bndr' bound') res'
390 genUniques' subst (CoreSyn.Let (CoreSyn.Rec binds) res) = do
391 -- Make each of the binders unique
392 (subst', bndrs') <- mapAccumLM genUnique subst (map fst binds)
393 bounds' <- mapM (genUniques' subst') (map snd binds)
394 res' <- genUniques' subst' res
395 let binds' = zip bndrs' bounds'
396 return $ CoreSyn.Let (CoreSyn.Rec binds') res'
397 genUniques' subst (CoreSyn.Case scrut bndr ty alts) = do
398 -- Process the scrutinee with the original substitution, since non of the
399 -- binders bound in the Case statement is in scope in the scrutinee.
400 scrut' <- genUniques' subst scrut
401 -- Generate a new binder for the scrutinee
402 (subst', bndr') <- genUnique subst bndr
403 -- Process each of the alts
404 alts' <- mapM (doalt subst') alts
405 return $ CoreSyn.Case scrut' bndr' ty alts'
407 doalt subst (con, bndrs, expr) = do
408 (subst', bndrs') <- mapAccumLM genUnique subst bndrs
409 expr' <- genUniques' subst' expr
410 -- Note that we don't return subst', since bndrs are only in scope in
412 return (con, bndrs', expr')
413 genUniques' subst (CoreSyn.Cast expr coercion) = do
414 expr' <- genUniques' subst expr
415 -- Just process the casted expression
416 return $ CoreSyn.Cast expr' coercion
417 genUniques' subst (CoreSyn.Note note expr) = do
418 expr' <- genUniques' subst expr
419 -- Just process the annotated expression
420 return $ CoreSyn.Note note expr'
421 -- Leave types untouched
422 genUniques' subst expr@(CoreSyn.Type _) = return expr
424 -- Generate a new unique for the given binder, and extend the given
425 -- substitution to reflect this.
426 genUnique :: VarEnv.VarEnv CoreSyn.CoreBndr -> CoreSyn.CoreBndr -> TranslatorSession (VarEnv.VarEnv CoreSyn.CoreBndr, CoreSyn.CoreBndr)
427 genUnique subst bndr = do
428 bndr' <- BinderTools.cloneVar bndr
429 -- Replace all occurences of the old binder with a reference to the new
431 let subst' = VarEnv.extendVarEnv subst bndr bndr'
432 return (subst', bndr')