[project @ 2001-01-12 11:04:45 by simonmar]
[ghc-hetmet.git] / ghc / compiler / coreSyn / CoreTidy.lhs
index 9873779..2454748 100644 (file)
@@ -14,7 +14,7 @@ module CoreTidy (
 import CmdLineOpts     ( DynFlags, DynFlag(..), opt_OmitInterfacePragmas )
 import CoreSyn
 import CoreUnfold      ( noUnfolding, mkTopUnfolding, okToUnfoldInHiFile )
-import CoreUtils       ( exprArity, exprIsBottom )
+import CoreUtils       ( exprArity )
 import CoreFVs         ( ruleSomeFreeVars, exprSomeFreeVars )
 import CoreLint                ( showPass, endPass )
 import VarEnv
@@ -22,11 +22,11 @@ import VarSet
 import Var             ( Id, Var )
 import Id              ( idType, idInfo, idName, isExportedId,
                          idCafInfo, mkId, isLocalId, isImplicitId,
-                         idFlavour, modifyIdInfo
+                         idFlavour, modifyIdInfo, idArity
                        ) 
 import IdInfo          {- loads of stuff -}
 import Name            ( getOccName, nameOccName, globaliseName, setNameOcc, 
-                         localiseName, mkLocalName, isGlobalName
+                         localiseName, mkLocalName, isGlobalName, isDllName
                        )
 import OccName         ( TidyOccEnv, initTidyOccEnv, tidyOccName )
 import Type            ( tidyTopType, tidyType, tidyTyVar )
@@ -37,6 +37,8 @@ import HscTypes               ( PersistentCompilerState( pcs_PRS ),
                          NameSupply( nsNames ), OrigNameCache
                        )
 import UniqSupply
+import DataCon         ( dataConName )
+import Literal         ( isLitLitLit )
 import FiniteMap       ( lookupFM, addToFM )
 import Maybes          ( maybeToBool, orElse )
 import ErrUtils                ( showPass )
@@ -94,10 +96,19 @@ binder
     that all Ids are unique, rather than the weaker guarantee of
     no clashes which the simplifier provides.
 
-  - Give the Id its final IdInfo; in ptic, 
+  - Give each dynamic CCall occurrence a fresh unique; this is
+    rather like the cloning step above.
+
+  - Give the Id its UTTERLY FINAL IdInfo; in ptic, 
        * Its flavour becomes ConstantId, reflecting the fact that
          from now on we regard it as a constant, not local, Id
+
        * its unfolding, if it should have one
+       
+       * its arity, computed from the number of visible lambdas
+
+       * its CAF info, computed from what is free in its RHS
+
                
 Finally, substitute these new top-level binders consistently
 throughout, including in unfoldings.  We also tidy binders in
@@ -354,16 +365,15 @@ tidyTopBinder mod ext_ids tidy_env rhs caf_info
 tidyIdInfo us tidy_env is_external unfold_info arity_info caf_info id
   | opt_OmitInterfacePragmas || not is_external
        -- No IdInfo if the Id isn't external, or if we don't have -O
-  = mkIdInfo new_flavour 
+  = mkIdInfo new_flavour caf_info
        `setStrictnessInfo` strictnessInfo core_idinfo
        `setArityInfo`      ArityExactly arity_info
-       `setCafInfo`        caf_info
        -- Keep strictness, arity and CAF info; it's used by the code generator
 
   | otherwise
   =  let (rules', _) = initUs us (tidyRules tidy_env (specInfo core_idinfo))
      in
-     mkIdInfo new_flavour
+     mkIdInfo new_flavour caf_info
        `setCprInfo`        cprInfo core_idinfo
        `setStrictnessInfo` strictnessInfo core_idinfo
        `setInlinePragInfo` inlinePragInfo core_idinfo
@@ -371,7 +381,6 @@ tidyIdInfo us tidy_env is_external unfold_info arity_info caf_info id
        `setWorkerInfo`     tidyWorker tidy_env arity_info (workerInfo core_idinfo)
        `setSpecInfo`       rules'
        `setArityInfo`      ArityExactly arity_info
-       `setCafInfo`        caf_info
                -- this is the final IdInfo, it must agree with the
                -- code finally generated (i.e. NO more transformations
                -- after this!).
@@ -647,15 +656,46 @@ cafRefss p (e:es) = cafRefs p e `fastOr` cafRefss p es
 -- in an SRT or not.
 
 isCAF :: CoreExpr -> Bool
-   -- special case for expressions which are always bottom,
-   -- such as 'error "..."'.  We don't need to record it as
-   -- a CAF, since it can only be entered once.
-isCAF e 
-  | not_function && is_bottom = False
-  | not_function && updatable = True
-  | otherwise                = False
+isCAF e = not (rhsIsNonUpd e)
+  {- ToDo: check type for onceness, i.e. non-updatable thunks? -}
+
+rhsIsNonUpd :: CoreExpr -> Bool        -- True => Value-lambda, constructor, PAP
+rhsIsNonUpd (Lam b e)          = isId b || rhsIsNonUpd e
+rhsIsNonUpd (Note (SCC _) e)   = False
+rhsIsNonUpd (Note _ e)         = rhsIsNonUpd e
+rhsIsNonUpd other_expr
+  = go other_expr 0 []
   where
-    not_function = exprArity e == 0
-    is_bottom    = exprIsBottom e
-    updatable    = True {- ToDo: check type for onceness? -}
+    go (Var f) n_args args = idAppIsNonUpd f n_args args
+       
+    go (App f a) n_args args
+       | isTypeArg a = go f n_args args
+       | otherwise   = go f (n_args + 1) (a:args)
+
+    go (Note (SCC _) f) n_args args = False
+    go (Note _ f) n_args args       = go f n_args args
+
+    go other n_args args = False
+
+idAppIsNonUpd :: Id -> Int -> [CoreExpr] -> Bool
+idAppIsNonUpd id n_val_args args
+  = case idFlavour id of
+       DataConId con | not (isDynConApp con args) -> True
+       other -> n_val_args < idArity id
+
+isDynConApp con args = isDllName (dataConName con) || any isDynArg args
+
+       -- Does this argument refer to something in a different DLL,
+       -- or is a LitLit?  Constructor arguments which are in another
+       -- DLL or are LitLits aren't compiled into static constructors
+       -- (see CoreToStg), so we have to take that into account here.
+isDynArg :: CoreExpr -> Bool
+isDynArg (Var v)    = isDllName (idName v)
+isDynArg (Note _ e) = isDynArg e
+isDynArg (Lit lit)  = isLitLitLit lit
+isDynArg (App e _)  = isDynArg e       -- must be a type app
+isDynArg (Lam _ e)  = isDynArg e       -- must be a type lam
+
+-- We consider partial applications to be non-updatable.  NOTE: this
+-- must match how CoreToStg marks the closure.
 \end{code}