{-# LANGUAGE CPP #-}
module GHC.Core.Opt.WorkWrap.Utils
   ( mkWwBodies, mkWWstr, mkWorkerArgs
   , DataConPatContext(..), UnboxingDecision(..), splitArgType_maybe, wantToUnbox
   , findTypeShape
   , isWorkerSmallEnough
   )
where
#include "HsVersions.h"
import GHC.Prelude
import GHC.Core
import GHC.Core.Utils   ( exprType, mkCast, mkDefaultCase, mkSingleAltCase
                        , dataConRepFSInstPat )
import GHC.Types.Id
import GHC.Types.Id.Info ( JoinArity )
import GHC.Core.DataCon
import GHC.Types.Demand
import GHC.Types.Cpr
import GHC.Core.Make    ( mkAbsentErrorApp, mkCoreUbxTup
                        , mkCoreApp, mkCoreLet )
import GHC.Types.Id.Make ( voidArgId, voidPrimId )
import GHC.Builtin.Types      ( tupleDataCon, unboxedUnitTy )
import GHC.Types.Literal ( absentLiteralOf, rubbishLit )
import GHC.Types.Var.Env ( mkInScopeSet )
import GHC.Types.Var.Set ( VarSet )
import GHC.Core.Type
import GHC.Core.Multiplicity
import GHC.Core.Predicate ( isClassPred )
import GHC.Types.RepType  ( isVoidTy, typePrimRep )
import GHC.Core.Coercion
import GHC.Core.FamInstEnv
import GHC.Types.Basic       ( Boxity(..) )
import GHC.Core.TyCon
import GHC.Core.TyCon.RecWalk
import GHC.Types.Unique.Supply
import GHC.Types.Unique
import GHC.Types.Name ( getOccFS )
import GHC.Data.Maybe
import GHC.Utils.Misc
import GHC.Utils.Outputable
import GHC.Utils.Panic
import GHC.Driver.Session
import GHC.Driver.Ppr
import GHC.Data.FastString
import GHC.Data.List.SetOps
type WwResult
  = ([Demand],              
     JoinArity,             
     Id -> CoreExpr,        
     CoreExpr -> CoreExpr)  
mkWwBodies :: DynFlags
           -> FamInstEnvs
           -> VarSet         
                             
           -> Id             
           -> [Demand]       
           -> Cpr            
           -> UniqSM (Maybe WwResult)
mkWwBodies :: DynFlags
-> FamInstEnvs
-> VarSet
-> Id
-> [Demand]
-> Cpr
-> UniqSM (Maybe WwResult)
mkWwBodies DynFlags
dflags FamInstEnvs
fam_envs VarSet
rhs_fvs Id
fun_id [Demand]
demands Cpr
cpr_info
  = do  { let empty_subst :: TCvSubst
empty_subst = InScopeSet -> TCvSubst
mkEmptyTCvSubst (VarSet -> InScopeSet
mkInScopeSet VarSet
rhs_fvs)
                
        ; ([Id]
wrap_args, CoreExpr -> CoreExpr
wrap_fn_args, CoreExpr -> CoreExpr
work_fn_args, Kind
res_ty)
             <- TCvSubst
-> Kind
-> [Demand]
-> UniqSM ([Id], CoreExpr -> CoreExpr, CoreExpr -> CoreExpr, Kind)
mkWWargs TCvSubst
empty_subst Kind
fun_ty [Demand]
demands
        ; (Bool
useful1, [Id]
work_args, CoreExpr -> CoreExpr
wrap_fn_str, CoreExpr -> CoreExpr
work_fn_str)
             <- DynFlags
-> FamInstEnvs
-> Bool
-> [Id]
-> UniqSM (Bool, [Id], CoreExpr -> CoreExpr, CoreExpr -> CoreExpr)
mkWWstr DynFlags
dflags FamInstEnvs
fam_envs Bool
has_inlineable_prag [Id]
wrap_args
        
        ; (Bool
useful2, CoreExpr -> CoreExpr
wrap_fn_cpr, CoreExpr -> CoreExpr
work_fn_cpr, Kind
cpr_res_ty)
              <- Bool
-> FamInstEnvs
-> Kind
-> Cpr
-> UniqSM (Bool, CoreExpr -> CoreExpr, CoreExpr -> CoreExpr, Kind)
mkWWcpr (GeneralFlag -> DynFlags -> Bool
gopt GeneralFlag
Opt_CprAnal DynFlags
dflags) FamInstEnvs
fam_envs Kind
res_ty Cpr
cpr_info
        ; let ([Id]
work_lam_args, [Id]
work_call_args) = DynFlags -> [Id] -> Kind -> ([Id], [Id])
mkWorkerArgs DynFlags
dflags [Id]
work_args Kind
cpr_res_ty
              worker_args_dmds :: [Demand]
worker_args_dmds = [Id -> Demand
idDemandInfo Id
v | Id
v <- [Id]
work_call_args, Id -> Bool
isId Id
v]
              wrapper_body :: Id -> CoreExpr
wrapper_body = CoreExpr -> CoreExpr
wrap_fn_args (CoreExpr -> CoreExpr) -> (Id -> CoreExpr) -> Id -> CoreExpr
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CoreExpr -> CoreExpr
wrap_fn_cpr (CoreExpr -> CoreExpr) -> (Id -> CoreExpr) -> Id -> CoreExpr
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CoreExpr -> CoreExpr
wrap_fn_str (CoreExpr -> CoreExpr) -> (Id -> CoreExpr) -> Id -> CoreExpr
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Id] -> CoreExpr -> CoreExpr
applyToVars [Id]
work_call_args (CoreExpr -> CoreExpr) -> (Id -> CoreExpr) -> Id -> CoreExpr
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Id -> CoreExpr
forall b. Id -> Expr b
Var
              worker_body :: CoreExpr -> CoreExpr
worker_body = [Id] -> CoreExpr -> CoreExpr
forall b. [b] -> Expr b -> Expr b
mkLams [Id]
work_lam_args(CoreExpr -> CoreExpr)
-> (CoreExpr -> CoreExpr) -> CoreExpr -> CoreExpr
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CoreExpr -> CoreExpr
work_fn_str (CoreExpr -> CoreExpr)
-> (CoreExpr -> CoreExpr) -> CoreExpr -> CoreExpr
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CoreExpr -> CoreExpr
work_fn_cpr (CoreExpr -> CoreExpr)
-> (CoreExpr -> CoreExpr) -> CoreExpr -> CoreExpr
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CoreExpr -> CoreExpr
work_fn_args
        ; if DynFlags -> Int -> [Id] -> Bool
isWorkerSmallEnough DynFlags
dflags ([Demand] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Demand]
demands) [Id]
work_args
             Bool -> Bool -> Bool
&& Bool -> Bool
not ([Id] -> Bool
too_many_args_for_join_point [Id]
wrap_args)
             Bool -> Bool -> Bool
&& ((Bool
useful1 Bool -> Bool -> Bool
&& Bool -> Bool
not Bool
only_one_void_argument) Bool -> Bool -> Bool
|| Bool
useful2)
          then Maybe WwResult -> UniqSM (Maybe WwResult)
forall (m :: * -> *) a. Monad m => a -> m a
return (WwResult -> Maybe WwResult
forall a. a -> Maybe a
Just ([Demand]
worker_args_dmds, [Id] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Id]
work_call_args,
                       Id -> CoreExpr
wrapper_body, CoreExpr -> CoreExpr
worker_body))
          else Maybe WwResult -> UniqSM (Maybe WwResult)
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe WwResult
forall a. Maybe a
Nothing
        }
        
        
        
        
        
        
        
  where
    fun_ty :: Kind
fun_ty        = Id -> Kind
idType Id
fun_id
    mb_join_arity :: Maybe Int
mb_join_arity = Id -> Maybe Int
isJoinId_maybe Id
fun_id
    has_inlineable_prag :: Bool
has_inlineable_prag = Unfolding -> Bool
isStableUnfolding (Id -> Unfolding
realIdUnfolding Id
fun_id)
                          
    
    only_one_void_argument :: Bool
only_one_void_argument
      | [Demand
d] <- [Demand]
demands
      , Just (Kind
_, Kind
arg_ty1, Kind
_) <- Kind -> Maybe (Kind, Kind, Kind)
splitFunTy_maybe Kind
fun_ty
      , Demand -> Bool
isAbsDmd Demand
d Bool -> Bool -> Bool
&& Kind -> Bool
isVoidTy Kind
arg_ty1
      = Bool
True
      | Bool
otherwise
      = Bool
False
    
    too_many_args_for_join_point :: [Id] -> Bool
too_many_args_for_join_point [Id]
wrap_args
      | Just Int
join_arity <- Maybe Int
mb_join_arity
      , [Id]
wrap_args [Id] -> Int -> Bool
forall a. [a] -> Int -> Bool
`lengthExceeds` Int
join_arity
      = WARN(True, text "Unable to worker/wrapper join point with arity " <+>
                     int join_arity <+> text "but" <+>
                     int (length wrap_args) <+> text "args")
        Bool
True
      | Bool
otherwise
      = Bool
False
isWorkerSmallEnough :: DynFlags -> Int -> [Var] -> Bool
isWorkerSmallEnough :: DynFlags -> Int -> [Id] -> Bool
isWorkerSmallEnough DynFlags
dflags Int
old_n_args [Id]
vars
  = (Id -> Bool) -> [Id] -> Int
forall a. (a -> Bool) -> [a] -> Int
count Id -> Bool
isId [Id]
vars Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int -> Int -> Int
forall a. Ord a => a -> a -> a
max Int
old_n_args (DynFlags -> Int
maxWorkerArgs DynFlags
dflags)
    
    
    
    
mkWorkerArgs :: DynFlags -> [Var]
             -> Type    
             -> ([Var], 
                 [Var]) 
mkWorkerArgs :: DynFlags -> [Id] -> Kind -> ([Id], [Id])
mkWorkerArgs DynFlags
dflags [Id]
args Kind
res_ty
    | (Id -> Bool) -> [Id] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any Id -> Bool
isId [Id]
args Bool -> Bool -> Bool
|| Bool -> Bool
not Bool
needsAValueLambda
    = ([Id]
args, [Id]
args)
    | Bool
otherwise
    = ([Id]
args [Id] -> [Id] -> [Id]
forall a. [a] -> [a] -> [a]
++ [Id
voidArgId], [Id]
args [Id] -> [Id] -> [Id]
forall a. [a] -> [a] -> [a]
++ [Id
voidPrimId])
    where
      
      needsAValueLambda :: Bool
needsAValueLambda =
        Bool
lifted
        
        
        
        Bool -> Bool -> Bool
|| Bool -> Bool
not (GeneralFlag -> DynFlags -> Bool
gopt GeneralFlag
Opt_FunToThunk DynFlags
dflags)
           
      
      lifted :: Bool
lifted =
        case HasDebugCallStack => Kind -> Maybe Bool
Kind -> Maybe Bool
isLiftedType_maybe Kind
res_ty of
          Just Bool
lifted -> Bool
lifted
          Maybe Bool
Nothing     -> Bool
True
mkWWargs :: TCvSubst            
                                
         -> Type                
         -> [Demand]     
         -> UniqSM  ([Var],            
                     CoreExpr -> CoreExpr,      
                     CoreExpr -> CoreExpr,      
                     Type)                      
mkWWargs :: TCvSubst
-> Kind
-> [Demand]
-> UniqSM ([Id], CoreExpr -> CoreExpr, CoreExpr -> CoreExpr, Kind)
mkWWargs TCvSubst
subst Kind
fun_ty [Demand]
demands
  | [Demand] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Demand]
demands
  = ([Id], CoreExpr -> CoreExpr, CoreExpr -> CoreExpr, Kind)
-> UniqSM ([Id], CoreExpr -> CoreExpr, CoreExpr -> CoreExpr, Kind)
forall (m :: * -> *) a. Monad m => a -> m a
return ([], CoreExpr -> CoreExpr
forall a. a -> a
id, CoreExpr -> CoreExpr
forall a. a -> a
id, HasCallStack => TCvSubst -> Kind -> Kind
TCvSubst -> Kind -> Kind
substTy TCvSubst
subst Kind
fun_ty)
  | (Demand
dmd:[Demand]
demands') <- [Demand]
demands
  , Just (Kind
mult, Kind
arg_ty, Kind
fun_ty') <- Kind -> Maybe (Kind, Kind, Kind)
splitFunTy_maybe Kind
fun_ty
  = do  { Unique
uniq <- UniqSM Unique
forall (m :: * -> *). MonadUnique m => m Unique
getUniqueM
        ; let arg_ty' :: Scaled Kind
arg_ty' = HasCallStack => TCvSubst -> Scaled Kind -> Scaled Kind
TCvSubst -> Scaled Kind -> Scaled Kind
substScaledTy TCvSubst
subst (Kind -> Kind -> Scaled Kind
forall a. Kind -> a -> Scaled a
Scaled Kind
mult Kind
arg_ty)
              id :: Id
id = Unique -> Scaled Kind -> Demand -> Id
mk_wrap_arg Unique
uniq Scaled Kind
arg_ty' Demand
dmd
        ; ([Id]
wrap_args, CoreExpr -> CoreExpr
wrap_fn_args, CoreExpr -> CoreExpr
work_fn_args, Kind
res_ty)
              <- TCvSubst
-> Kind
-> [Demand]
-> UniqSM ([Id], CoreExpr -> CoreExpr, CoreExpr -> CoreExpr, Kind)
mkWWargs TCvSubst
subst Kind
fun_ty' [Demand]
demands'
        ; ([Id], CoreExpr -> CoreExpr, CoreExpr -> CoreExpr, Kind)
-> UniqSM ([Id], CoreExpr -> CoreExpr, CoreExpr -> CoreExpr, Kind)
forall (m :: * -> *) a. Monad m => a -> m a
return (Id
id Id -> [Id] -> [Id]
forall a. a -> [a] -> [a]
: [Id]
wrap_args,
                  Id -> CoreExpr -> CoreExpr
forall b. b -> Expr b -> Expr b
Lam Id
id (CoreExpr -> CoreExpr)
-> (CoreExpr -> CoreExpr) -> CoreExpr -> CoreExpr
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CoreExpr -> CoreExpr
wrap_fn_args,
                  (CoreExpr -> CoreExpr) -> CoreExpr -> CoreExpr -> CoreExpr
apply_or_bind_then CoreExpr -> CoreExpr
work_fn_args (Id -> CoreExpr
forall b. Id -> Expr b
varToCoreExpr Id
id),
                  Kind
res_ty) }
  | Just (Id
tv, Kind
fun_ty') <- Kind -> Maybe (Id, Kind)
splitForAllTyCoVar_maybe Kind
fun_ty
  = do  { Unique
uniq <- UniqSM Unique
forall (m :: * -> *). MonadUnique m => m Unique
getUniqueM
        ; let (TCvSubst
subst', Id
tv') = TCvSubst -> Id -> Unique -> (TCvSubst, Id)
cloneTyVarBndr TCvSubst
subst Id
tv Unique
uniq
                
        ; ([Id]
wrap_args, CoreExpr -> CoreExpr
wrap_fn_args, CoreExpr -> CoreExpr
work_fn_args, Kind
res_ty)
             <- TCvSubst
-> Kind
-> [Demand]
-> UniqSM ([Id], CoreExpr -> CoreExpr, CoreExpr -> CoreExpr, Kind)
mkWWargs TCvSubst
subst' Kind
fun_ty' [Demand]
demands
        ; ([Id], CoreExpr -> CoreExpr, CoreExpr -> CoreExpr, Kind)
-> UniqSM ([Id], CoreExpr -> CoreExpr, CoreExpr -> CoreExpr, Kind)
forall (m :: * -> *) a. Monad m => a -> m a
return (Id
tv' Id -> [Id] -> [Id]
forall a. a -> [a] -> [a]
: [Id]
wrap_args,
                  Id -> CoreExpr -> CoreExpr
forall b. b -> Expr b -> Expr b
Lam Id
tv' (CoreExpr -> CoreExpr)
-> (CoreExpr -> CoreExpr) -> CoreExpr -> CoreExpr
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CoreExpr -> CoreExpr
wrap_fn_args,
                  (CoreExpr -> CoreExpr) -> CoreExpr -> CoreExpr -> CoreExpr
apply_or_bind_then CoreExpr -> CoreExpr
work_fn_args (Kind -> CoreExpr
forall b. Kind -> Expr b
mkTyArg (Id -> Kind
mkTyVarTy Id
tv')),
                  Kind
res_ty) }
  | Just (Coercion
co, Kind
rep_ty) <- Kind -> Maybe (Coercion, Kind)
topNormaliseNewType_maybe Kind
fun_ty
        
        
        
        
        
        
        
  = do { ([Id]
wrap_args, CoreExpr -> CoreExpr
wrap_fn_args, CoreExpr -> CoreExpr
work_fn_args, Kind
res_ty)
            <-  TCvSubst
-> Kind
-> [Demand]
-> UniqSM ([Id], CoreExpr -> CoreExpr, CoreExpr -> CoreExpr, Kind)
mkWWargs TCvSubst
subst Kind
rep_ty [Demand]
demands
       ; let co' :: Coercion
co' = HasCallStack => TCvSubst -> Coercion -> Coercion
TCvSubst -> Coercion -> Coercion
substCo TCvSubst
subst Coercion
co
       ; ([Id], CoreExpr -> CoreExpr, CoreExpr -> CoreExpr, Kind)
-> UniqSM ([Id], CoreExpr -> CoreExpr, CoreExpr -> CoreExpr, Kind)
forall (m :: * -> *) a. Monad m => a -> m a
return ([Id]
wrap_args,
                  \CoreExpr
e -> CoreExpr -> Coercion -> CoreExpr
forall b. Expr b -> Coercion -> Expr b
Cast (CoreExpr -> CoreExpr
wrap_fn_args CoreExpr
e) (Coercion -> Coercion
mkSymCo Coercion
co'),
                  \CoreExpr
e -> CoreExpr -> CoreExpr
work_fn_args (CoreExpr -> Coercion -> CoreExpr
forall b. Expr b -> Coercion -> Expr b
Cast CoreExpr
e Coercion
co'),
                  Kind
res_ty) }
  | Bool
otherwise
  = WARN( True, ppr fun_ty )                    
    ([Id], CoreExpr -> CoreExpr, CoreExpr -> CoreExpr, Kind)
-> UniqSM ([Id], CoreExpr -> CoreExpr, CoreExpr -> CoreExpr, Kind)
forall (m :: * -> *) a. Monad m => a -> m a
return ([], CoreExpr -> CoreExpr
forall a. a -> a
id, CoreExpr -> CoreExpr
forall a. a -> a
id, HasCallStack => TCvSubst -> Kind -> Kind
TCvSubst -> Kind -> Kind
substTy TCvSubst
subst Kind
fun_ty)   
  where
    
    apply_or_bind_then :: (CoreExpr -> CoreExpr) -> CoreExpr -> CoreExpr -> CoreExpr
apply_or_bind_then CoreExpr -> CoreExpr
k CoreExpr
arg (Lam Id
bndr CoreExpr
body)
      = CoreBind -> CoreExpr -> CoreExpr
mkCoreLet (Id -> CoreExpr -> CoreBind
forall b. b -> Expr b -> Bind b
NonRec Id
bndr CoreExpr
arg) (CoreExpr -> CoreExpr
k CoreExpr
body)    
    apply_or_bind_then CoreExpr -> CoreExpr
k CoreExpr
arg CoreExpr
fun
      = CoreExpr -> CoreExpr
k (CoreExpr -> CoreExpr) -> CoreExpr -> CoreExpr
forall a b. (a -> b) -> a -> b
$ SDoc -> CoreExpr -> CoreExpr -> CoreExpr
mkCoreApp (String -> SDoc
text String
"mkWWargs") CoreExpr
fun CoreExpr
arg
applyToVars :: [Var] -> CoreExpr -> CoreExpr
applyToVars :: [Id] -> CoreExpr -> CoreExpr
applyToVars [Id]
vars CoreExpr
fn = CoreExpr -> [Id] -> CoreExpr
forall b. Expr b -> [Id] -> Expr b
mkVarApps CoreExpr
fn [Id]
vars
mk_wrap_arg :: Unique -> Scaled Type -> Demand -> Id
mk_wrap_arg :: Unique -> Scaled Kind -> Demand -> Id
mk_wrap_arg Unique
uniq (Scaled Kind
w Kind
ty) Demand
dmd
  = FastString -> Unique -> Kind -> Kind -> Id
mkSysLocalOrCoVar (String -> FastString
fsLit String
"w") Unique
uniq Kind
w Kind
ty
       Id -> Demand -> Id
`setIdDemandInfo` Demand
dmd
data DataConPatContext
  = DataConPatContext
  { DataConPatContext -> DataCon
dcpc_dc      :: !DataCon
  , DataConPatContext -> [Kind]
dcpc_tc_args :: ![Type]
  , DataConPatContext -> Coercion
dcpc_co      :: !Coercion
  }
splitArgType_maybe :: FamInstEnvs -> Type -> Maybe DataConPatContext
splitArgType_maybe :: FamInstEnvs -> Kind -> Maybe DataConPatContext
splitArgType_maybe FamInstEnvs
fam_envs Kind
ty
  | let (Coercion
co, Kind
ty1) = FamInstEnvs -> Kind -> Maybe (Coercion, Kind)
topNormaliseType_maybe FamInstEnvs
fam_envs Kind
ty
                    Maybe (Coercion, Kind) -> (Coercion, Kind) -> (Coercion, Kind)
forall a. Maybe a -> a -> a
`orElse` (Kind -> Coercion
mkRepReflCo Kind
ty, Kind
ty)
  , Just (TyCon
tc, [Kind]
tc_args) <- HasDebugCallStack => Kind -> Maybe (TyCon, [Kind])
Kind -> Maybe (TyCon, [Kind])
splitTyConApp_maybe Kind
ty1
  , Just DataCon
con <- TyCon -> Maybe DataCon
tyConSingleAlgDataCon_maybe TyCon
tc
  = DataConPatContext -> Maybe DataConPatContext
forall a. a -> Maybe a
Just DataConPatContext { dcpc_dc :: DataCon
dcpc_dc      = DataCon
con
                           , dcpc_tc_args :: [Kind]
dcpc_tc_args = [Kind]
tc_args
                           , dcpc_co :: Coercion
dcpc_co      = Coercion
co }
splitArgType_maybe FamInstEnvs
_ Kind
_ = Maybe DataConPatContext
forall a. Maybe a
Nothing
splitResultType_maybe :: FamInstEnvs -> ConTag -> Type -> Maybe DataConPatContext
splitResultType_maybe :: FamInstEnvs -> Int -> Kind -> Maybe DataConPatContext
splitResultType_maybe FamInstEnvs
fam_envs Int
con_tag Kind
ty
  | let (Coercion
co, Kind
ty1) = FamInstEnvs -> Kind -> Maybe (Coercion, Kind)
topNormaliseType_maybe FamInstEnvs
fam_envs Kind
ty
                    Maybe (Coercion, Kind) -> (Coercion, Kind) -> (Coercion, Kind)
forall a. Maybe a -> a -> a
`orElse` (Kind -> Coercion
mkRepReflCo Kind
ty, Kind
ty)
  , Just (TyCon
tc, [Kind]
tc_args) <- HasDebugCallStack => Kind -> Maybe (TyCon, [Kind])
Kind -> Maybe (TyCon, [Kind])
splitTyConApp_maybe Kind
ty1
  , TyCon -> Bool
isDataTyCon TyCon
tc 
  , let cons :: [DataCon]
cons = TyCon -> [DataCon]
tyConDataCons TyCon
tc
  , [DataCon]
cons [DataCon] -> Int -> Bool
forall a. [a] -> Int -> Bool
`lengthAtLeast` Int
con_tag 
                                 
  , let con :: DataCon
con = [DataCon]
cons [DataCon] -> Int -> DataCon
forall a. Outputable a => [a] -> Int -> a
`getNth` (Int
con_tag Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
fIRST_TAG)
  , [Id] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null (DataCon -> [Id]
dataConExTyCoVars DataCon
con) 
                                 
                                 
                                 
  , (Scaled Kind -> Bool) -> [Scaled Kind] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all Scaled Kind -> Bool
forall a. Scaled a -> Bool
isLinear (DataCon -> [Kind] -> [Scaled Kind]
dataConInstArgTys DataCon
con [Kind]
tc_args)
  
  
  
  = DataConPatContext -> Maybe DataConPatContext
forall a. a -> Maybe a
Just DataConPatContext { dcpc_dc :: DataCon
dcpc_dc = DataCon
con
                           , dcpc_tc_args :: [Kind]
dcpc_tc_args = [Kind]
tc_args
                           , dcpc_co :: Coercion
dcpc_co = Coercion
co }
splitResultType_maybe FamInstEnvs
_ Int
_ Kind
_ = Maybe DataConPatContext
forall a. Maybe a
Nothing
isLinear :: Scaled a -> Bool
isLinear :: forall a. Scaled a -> Bool
isLinear (Scaled Kind
w a
_ ) =
  case Kind
w of
    Kind
One -> Bool
True
    Kind
_ -> Bool
False
data UnboxingDecision s
  = StopUnboxing
  
  | Unbox !DataConPatContext [s]
  
  
  
  
  
  
wantToUnbox :: FamInstEnvs -> Bool -> Type -> Demand -> UnboxingDecision Demand
wantToUnbox :: FamInstEnvs -> Bool -> Kind -> Demand -> UnboxingDecision Demand
wantToUnbox FamInstEnvs
fam_envs Bool
has_inlineable_prag Kind
ty Demand
dmd =
  case FamInstEnvs -> Kind -> Maybe DataConPatContext
splitArgType_maybe FamInstEnvs
fam_envs Kind
ty of
    Just dcpc :: DataConPatContext
dcpc@DataConPatContext{ dcpc_dc :: DataConPatContext -> DataCon
dcpc_dc = DataCon
dc }
      | Demand -> Bool
isStrUsedDmd Demand
dmd Bool -> Bool -> Bool
|| HasDebugCallStack => Kind -> Bool
Kind -> Bool
isUnliftedType Kind
ty
      , let arity :: Int
arity = DataCon -> Int
dataConRepArity DataCon
dc
      
      , Just [Demand]
cs <- Demand -> Int -> Maybe [Demand]
split_prod_dmd_arity Demand
dmd Int
arity
      
      , Bool -> Bool
not (Bool
has_inlineable_prag Bool -> Bool -> Bool
&& Kind -> Bool
isClassPred Kind
ty)
      
      , [Demand]
cs [Demand] -> Int -> Bool
forall a. [a] -> Int -> Bool
`lengthIs` Int
arity
      
      , let cs' :: [Demand]
cs' = DataCon -> [Demand] -> [Demand]
addDataConStrictness DataCon
dc [Demand]
cs
      -> DataConPatContext -> [Demand] -> UnboxingDecision Demand
forall s. DataConPatContext -> [s] -> UnboxingDecision s
Unbox DataConPatContext
dcpc [Demand]
cs'
    Maybe DataConPatContext
_ -> UnboxingDecision Demand
forall s. UnboxingDecision s
StopUnboxing
  where
    split_prod_dmd_arity :: Demand -> Int -> Maybe [Demand]
split_prod_dmd_arity Demand
dmd Int
arity
      
      
      | Demand -> Bool
isSeqDmd Demand
dmd        = [Demand] -> Maybe [Demand]
forall a. a -> Maybe a
Just (Int -> Demand -> [Demand]
forall a. Int -> a -> [a]
replicate Int
arity Demand
absDmd)
      | Card
_ :* Prod [Demand]
ds <- Demand
dmd = [Demand] -> Maybe [Demand]
forall a. a -> Maybe a
Just [Demand]
ds
      | Bool
otherwise           = Maybe [Demand]
forall a. Maybe a
Nothing
mkWWstr :: DynFlags
        -> FamInstEnvs
        -> Bool    
                   
        -> [Var]                                
                                                
        -> UniqSM (Bool,                        
                   [Var],                       
                   CoreExpr -> CoreExpr,        
                                                
                                                
                   CoreExpr -> CoreExpr)        
                                                
                                                
mkWWstr :: DynFlags
-> FamInstEnvs
-> Bool
-> [Id]
-> UniqSM (Bool, [Id], CoreExpr -> CoreExpr, CoreExpr -> CoreExpr)
mkWWstr DynFlags
dflags FamInstEnvs
fam_envs Bool
has_inlineable_prag [Id]
args
  = [Id]
-> UniqSM (Bool, [Id], CoreExpr -> CoreExpr, CoreExpr -> CoreExpr)
go [Id]
args
  where
    go_one :: Id
-> UniqSM (Bool, [Id], CoreExpr -> CoreExpr, CoreExpr -> CoreExpr)
go_one Id
arg = DynFlags
-> FamInstEnvs
-> Bool
-> Id
-> UniqSM (Bool, [Id], CoreExpr -> CoreExpr, CoreExpr -> CoreExpr)
mkWWstr_one DynFlags
dflags FamInstEnvs
fam_envs Bool
has_inlineable_prag Id
arg
    go :: [Id]
-> UniqSM (Bool, [Id], CoreExpr -> CoreExpr, CoreExpr -> CoreExpr)
go []           = (Bool, [Id], CoreExpr -> CoreExpr, CoreExpr -> CoreExpr)
-> UniqSM (Bool, [Id], CoreExpr -> CoreExpr, CoreExpr -> CoreExpr)
forall (m :: * -> *) a. Monad m => a -> m a
return (Bool
False, [], CoreExpr -> CoreExpr
nop_fn, CoreExpr -> CoreExpr
nop_fn)
    go (Id
arg : [Id]
args) = do { (Bool
useful1, [Id]
args1, CoreExpr -> CoreExpr
wrap_fn1, CoreExpr -> CoreExpr
work_fn1) <- Id
-> UniqSM (Bool, [Id], CoreExpr -> CoreExpr, CoreExpr -> CoreExpr)
go_one Id
arg
                         ; (Bool
useful2, [Id]
args2, CoreExpr -> CoreExpr
wrap_fn2, CoreExpr -> CoreExpr
work_fn2) <- [Id]
-> UniqSM (Bool, [Id], CoreExpr -> CoreExpr, CoreExpr -> CoreExpr)
go [Id]
args
                         ; (Bool, [Id], CoreExpr -> CoreExpr, CoreExpr -> CoreExpr)
-> UniqSM (Bool, [Id], CoreExpr -> CoreExpr, CoreExpr -> CoreExpr)
forall (m :: * -> *) a. Monad m => a -> m a
return ( Bool
useful1 Bool -> Bool -> Bool
|| Bool
useful2
                                  , [Id]
args1 [Id] -> [Id] -> [Id]
forall a. [a] -> [a] -> [a]
++ [Id]
args2
                                  , CoreExpr -> CoreExpr
wrap_fn1 (CoreExpr -> CoreExpr)
-> (CoreExpr -> CoreExpr) -> CoreExpr -> CoreExpr
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CoreExpr -> CoreExpr
wrap_fn2
                                  , CoreExpr -> CoreExpr
work_fn1 (CoreExpr -> CoreExpr)
-> (CoreExpr -> CoreExpr) -> CoreExpr -> CoreExpr
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CoreExpr -> CoreExpr
work_fn2) }
mkWWstr_one :: DynFlags -> FamInstEnvs
            -> Bool    
                       
            -> Var
            -> UniqSM (Bool, [Var], CoreExpr -> CoreExpr, CoreExpr -> CoreExpr)
mkWWstr_one :: DynFlags
-> FamInstEnvs
-> Bool
-> Id
-> UniqSM (Bool, [Id], CoreExpr -> CoreExpr, CoreExpr -> CoreExpr)
mkWWstr_one DynFlags
dflags FamInstEnvs
fam_envs Bool
has_inlineable_prag Id
arg
  | Id -> Bool
isTyVar Id
arg
  = (Bool, [Id], CoreExpr -> CoreExpr, CoreExpr -> CoreExpr)
-> UniqSM (Bool, [Id], CoreExpr -> CoreExpr, CoreExpr -> CoreExpr)
forall (m :: * -> *) a. Monad m => a -> m a
return (Bool
False, [Id
arg],  CoreExpr -> CoreExpr
nop_fn, CoreExpr -> CoreExpr
nop_fn)
  | Demand -> Bool
isAbsDmd Demand
dmd
  , Just CoreExpr -> CoreExpr
work_fn <- DynFlags
-> FamInstEnvs -> Id -> Demand -> Maybe (CoreExpr -> CoreExpr)
mk_absent_let DynFlags
dflags FamInstEnvs
fam_envs Id
arg Demand
dmd
     
     
     
  = (Bool, [Id], CoreExpr -> CoreExpr, CoreExpr -> CoreExpr)
-> UniqSM (Bool, [Id], CoreExpr -> CoreExpr, CoreExpr -> CoreExpr)
forall (m :: * -> *) a. Monad m => a -> m a
return (Bool
True, [], CoreExpr -> CoreExpr
nop_fn, CoreExpr -> CoreExpr
work_fn)
  | Unbox DataConPatContext
dcpc [Demand]
cs <- FamInstEnvs -> Bool -> Kind -> Demand -> UnboxingDecision Demand
wantToUnbox FamInstEnvs
fam_envs Bool
has_inlineable_prag Kind
arg_ty Demand
dmd
  = DynFlags
-> FamInstEnvs
-> Id
-> [Demand]
-> DataConPatContext
-> UniqSM (Bool, [Id], CoreExpr -> CoreExpr, CoreExpr -> CoreExpr)
unbox_one DynFlags
dflags FamInstEnvs
fam_envs Id
arg [Demand]
cs DataConPatContext
dcpc
  | Bool
otherwise   
  = (Bool, [Id], CoreExpr -> CoreExpr, CoreExpr -> CoreExpr)
-> UniqSM (Bool, [Id], CoreExpr -> CoreExpr, CoreExpr -> CoreExpr)
forall (m :: * -> *) a. Monad m => a -> m a
return (Bool
False, [Id
arg], CoreExpr -> CoreExpr
nop_fn, CoreExpr -> CoreExpr
nop_fn)
  where
    arg_ty :: Kind
arg_ty = Id -> Kind
idType Id
arg
    dmd :: Demand
dmd    = Id -> Demand
idDemandInfo Id
arg
unbox_one :: DynFlags -> FamInstEnvs -> Var
          -> [Demand]
          -> DataConPatContext
          -> UniqSM (Bool, [Var], CoreExpr -> CoreExpr, CoreExpr -> CoreExpr)
unbox_one :: DynFlags
-> FamInstEnvs
-> Id
-> [Demand]
-> DataConPatContext
-> UniqSM (Bool, [Id], CoreExpr -> CoreExpr, CoreExpr -> CoreExpr)
unbox_one DynFlags
dflags FamInstEnvs
fam_envs Id
arg [Demand]
cs
          DataConPatContext { dcpc_dc :: DataConPatContext -> DataCon
dcpc_dc = DataCon
dc, dcpc_tc_args :: DataConPatContext -> [Kind]
dcpc_tc_args = [Kind]
tc_args
                            , dcpc_co :: DataConPatContext -> Coercion
dcpc_co = Coercion
co }
  = do { (Unique
case_bndr_uniq:[Unique]
pat_bndrs_uniqs) <- UniqSM [Unique]
forall (m :: * -> *). MonadUnique m => m [Unique]
getUniquesM
       ; let ex_name_fss :: [FastString]
ex_name_fss     = (Id -> FastString) -> [Id] -> [FastString]
forall a b. (a -> b) -> [a] -> [b]
map Id -> FastString
forall a. NamedThing a => a -> FastString
getOccFS ([Id] -> [FastString]) -> [Id] -> [FastString]
forall a b. (a -> b) -> a -> b
$ DataCon -> [Id]
dataConExTyCoVars DataCon
dc
             ([Id]
ex_tvs', [Id]
arg_ids) =
               [FastString]
-> [Unique] -> Kind -> DataCon -> [Kind] -> ([Id], [Id])
dataConRepFSInstPat ([FastString]
ex_name_fss [FastString] -> [FastString] -> [FastString]
forall a. [a] -> [a] -> [a]
++ FastString -> [FastString]
forall a. a -> [a]
repeat FastString
ww_prefix) [Unique]
pat_bndrs_uniqs (Id -> Kind
idMult Id
arg) DataCon
dc [Kind]
tc_args
             arg_ids' :: [Id]
arg_ids'  = String -> (Id -> Demand -> Id) -> [Id] -> [Demand] -> [Id]
forall a b c. String -> (a -> b -> c) -> [a] -> [b] -> [c]
zipWithEqual String
"unbox_one" Id -> Demand -> Id
setIdDemandInfo [Id]
arg_ids [Demand]
cs
             unbox_fn :: CoreExpr -> CoreExpr
unbox_fn  = CoreExpr
-> Coercion
-> Kind
-> Unique
-> DataCon
-> [Id]
-> CoreExpr
-> CoreExpr
mkUnpackCase (Id -> CoreExpr
forall b. Id -> Expr b
Var Id
arg) Coercion
co (Id -> Kind
idMult Id
arg) Unique
case_bndr_uniq
                                      DataCon
dc ([Id]
ex_tvs' [Id] -> [Id] -> [Id]
forall a. [a] -> [a] -> [a]
++ [Id]
arg_ids')
             arg_no_unf :: Id
arg_no_unf = Id -> Id
zapStableUnfolding Id
arg
                          
                          
             rebox_fn :: CoreExpr -> CoreExpr
rebox_fn   = CoreBind -> CoreExpr -> CoreExpr
forall b. Bind b -> Expr b -> Expr b
Let (Id -> CoreExpr -> CoreBind
forall b. b -> Expr b -> Bind b
NonRec Id
arg_no_unf CoreExpr
con_app)
             con_app :: CoreExpr
con_app    = DataCon -> [Kind] -> [Id] -> CoreExpr
forall b. DataCon -> [Kind] -> [Id] -> Expr b
mkConApp2 DataCon
dc [Kind]
tc_args ([Id]
ex_tvs' [Id] -> [Id] -> [Id]
forall a. [a] -> [a] -> [a]
++ [Id]
arg_ids') CoreExpr -> Coercion -> CoreExpr
`mkCast` Coercion -> Coercion
mkSymCo Coercion
co
       ; (Bool
_, [Id]
worker_args, CoreExpr -> CoreExpr
wrap_fn, CoreExpr -> CoreExpr
work_fn) <- DynFlags
-> FamInstEnvs
-> Bool
-> [Id]
-> UniqSM (Bool, [Id], CoreExpr -> CoreExpr, CoreExpr -> CoreExpr)
mkWWstr DynFlags
dflags FamInstEnvs
fam_envs Bool
False ([Id]
ex_tvs' [Id] -> [Id] -> [Id]
forall a. [a] -> [a] -> [a]
++ [Id]
arg_ids')
       ; (Bool, [Id], CoreExpr -> CoreExpr, CoreExpr -> CoreExpr)
-> UniqSM (Bool, [Id], CoreExpr -> CoreExpr, CoreExpr -> CoreExpr)
forall (m :: * -> *) a. Monad m => a -> m a
return (Bool
True, [Id]
worker_args, CoreExpr -> CoreExpr
unbox_fn (CoreExpr -> CoreExpr)
-> (CoreExpr -> CoreExpr) -> CoreExpr -> CoreExpr
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CoreExpr -> CoreExpr
wrap_fn, CoreExpr -> CoreExpr
work_fn (CoreExpr -> CoreExpr)
-> (CoreExpr -> CoreExpr) -> CoreExpr -> CoreExpr
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CoreExpr -> CoreExpr
rebox_fn) }
                          
nop_fn :: CoreExpr -> CoreExpr
nop_fn :: CoreExpr -> CoreExpr
nop_fn CoreExpr
body = CoreExpr
body
addDataConStrictness :: DataCon -> [Demand] -> [Demand]
addDataConStrictness :: DataCon -> [Demand] -> [Demand]
addDataConStrictness DataCon
con [Demand]
ds
  | Maybe Id
Nothing <- DataCon -> Maybe Id
dataConWrapId_maybe DataCon
con
  
  = [Demand]
ds
addDataConStrictness DataCon
con [Demand]
ds
  = String
-> (Demand -> StrictnessMark -> Demand)
-> [Demand]
-> [StrictnessMark]
-> [Demand]
forall a b c. String -> (a -> b -> c) -> [a] -> [b] -> [c]
zipWithEqual String
"addDataConStrictness" Demand -> StrictnessMark -> Demand
add [Demand]
ds [StrictnessMark]
strs
  where
    strs :: [StrictnessMark]
strs = DataCon -> [StrictnessMark]
dataConRepStrictness DataCon
con
    add :: Demand -> StrictnessMark -> Demand
add Demand
dmd StrictnessMark
str | StrictnessMark -> Bool
isMarkedStrict StrictnessMark
str = Demand -> Demand
strictifyDmd Demand
dmd
                | Bool
otherwise          = Demand
dmd
findTypeShape :: FamInstEnvs -> Type -> TypeShape
findTypeShape :: FamInstEnvs -> Kind -> TypeShape
findTypeShape FamInstEnvs
fam_envs Kind
ty
  = RecTcChecker -> Kind -> TypeShape
go (Int -> RecTcChecker -> RecTcChecker
setRecTcMaxBound Int
2 RecTcChecker
initRecTc) Kind
ty
       
       
       
       
  where
    go :: RecTcChecker -> Kind -> TypeShape
go RecTcChecker
rec_tc Kind
ty
       | Just (Kind
_, Kind
_, Kind
res) <- Kind -> Maybe (Kind, Kind, Kind)
splitFunTy_maybe Kind
ty
       = TypeShape -> TypeShape
TsFun (RecTcChecker -> Kind -> TypeShape
go RecTcChecker
rec_tc Kind
res)
       | Just (TyCon
tc, [Kind]
tc_args)  <- HasDebugCallStack => Kind -> Maybe (TyCon, [Kind])
Kind -> Maybe (TyCon, [Kind])
splitTyConApp_maybe Kind
ty
       = RecTcChecker -> TyCon -> [Kind] -> TypeShape
go_tc RecTcChecker
rec_tc TyCon
tc [Kind]
tc_args
       | Just (Id
_, Kind
ty') <- Kind -> Maybe (Id, Kind)
splitForAllTyCoVar_maybe Kind
ty
       = RecTcChecker -> Kind -> TypeShape
go RecTcChecker
rec_tc Kind
ty'
       | Bool
otherwise
       = TypeShape
TsUnk
    go_tc :: RecTcChecker -> TyCon -> [Kind] -> TypeShape
go_tc RecTcChecker
rec_tc TyCon
tc [Kind]
tc_args
       | Just (Coercion
_, Kind
rhs, MCoercion
_) <- FamInstEnvs -> TyCon -> [Kind] -> Maybe (Coercion, Kind, MCoercion)
topReduceTyFamApp_maybe FamInstEnvs
fam_envs TyCon
tc [Kind]
tc_args
       = RecTcChecker -> Kind -> TypeShape
go RecTcChecker
rec_tc Kind
rhs
       | Just DataCon
con <- TyCon -> Maybe DataCon
tyConSingleAlgDataCon_maybe TyCon
tc
       , Just RecTcChecker
rec_tc <- if TyCon -> Bool
isTupleTyCon TyCon
tc
                        then RecTcChecker -> Maybe RecTcChecker
forall a. a -> Maybe a
Just RecTcChecker
rec_tc
                        else RecTcChecker -> TyCon -> Maybe RecTcChecker
checkRecTc RecTcChecker
rec_tc TyCon
tc
         
         
         
         
         
       = [TypeShape] -> TypeShape
TsProd ((Kind -> TypeShape) -> [Kind] -> [TypeShape]
forall a b. (a -> b) -> [a] -> [b]
map (RecTcChecker -> Kind -> TypeShape
go RecTcChecker
rec_tc) (DataCon -> [Kind] -> [Kind]
dubiousDataConInstArgTys DataCon
con [Kind]
tc_args))
       | Just (Kind
ty', Coercion
_) <- TyCon -> [Kind] -> Maybe (Kind, Coercion)
instNewTyCon_maybe TyCon
tc [Kind]
tc_args
       , Just RecTcChecker
rec_tc <- RecTcChecker -> TyCon -> Maybe RecTcChecker
checkRecTc RecTcChecker
rec_tc TyCon
tc
       = RecTcChecker -> Kind -> TypeShape
go RecTcChecker
rec_tc Kind
ty'
       | Bool
otherwise
       = TypeShape
TsUnk
dubiousDataConInstArgTys :: DataCon -> [Type] -> [Type]
dubiousDataConInstArgTys :: DataCon -> [Kind] -> [Kind]
dubiousDataConInstArgTys DataCon
dc [Kind]
tc_args = [Kind]
arg_tys
  where
    univ_tvs :: [Id]
univ_tvs = DataCon -> [Id]
dataConUnivTyVars DataCon
dc
    ex_tvs :: [Id]
ex_tvs   = DataCon -> [Id]
dataConExTyCoVars DataCon
dc
    subst :: TCvSubst
subst    = TCvSubst -> [Id] -> TCvSubst
extendTCvInScopeList ([Id] -> [Kind] -> TCvSubst
HasDebugCallStack => [Id] -> [Kind] -> TCvSubst
zipTvSubst [Id]
univ_tvs [Kind]
tc_args) [Id]
ex_tvs
    arg_tys :: [Kind]
arg_tys  = (Scaled Kind -> Kind) -> [Scaled Kind] -> [Kind]
forall a b. (a -> b) -> [a] -> [b]
map (HasCallStack => TCvSubst -> Kind -> Kind
TCvSubst -> Kind -> Kind
substTy TCvSubst
subst (Kind -> Kind) -> (Scaled Kind -> Kind) -> Scaled Kind -> Kind
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Scaled Kind -> Kind
forall a. Scaled a -> a
scaledThing) (DataCon -> [Scaled Kind]
dataConRepArgTys DataCon
dc)
mkWWcpr :: Bool
        -> FamInstEnvs
        -> Type                              
        -> Cpr                               
        -> UniqSM (Bool,                     
                   CoreExpr -> CoreExpr,     
                   CoreExpr -> CoreExpr,     
                   Type)                     
mkWWcpr :: Bool
-> FamInstEnvs
-> Kind
-> Cpr
-> UniqSM (Bool, CoreExpr -> CoreExpr, CoreExpr -> CoreExpr, Kind)
mkWWcpr Bool
opt_CprAnal FamInstEnvs
fam_envs Kind
body_ty Cpr
cpr
    
  | Bool -> Bool
not Bool
opt_CprAnal = (Bool, CoreExpr -> CoreExpr, CoreExpr -> CoreExpr, Kind)
-> UniqSM (Bool, CoreExpr -> CoreExpr, CoreExpr -> CoreExpr, Kind)
forall (m :: * -> *) a. Monad m => a -> m a
return (Bool
False, CoreExpr -> CoreExpr
forall a. a -> a
id, CoreExpr -> CoreExpr
forall a. a -> a
id, Kind
body_ty)
    
  | Bool
otherwise
  = case Cpr -> Maybe (Int, [Cpr])
asConCpr Cpr
cpr of
       Maybe (Int, [Cpr])
Nothing      -> (Bool, CoreExpr -> CoreExpr, CoreExpr -> CoreExpr, Kind)
-> UniqSM (Bool, CoreExpr -> CoreExpr, CoreExpr -> CoreExpr, Kind)
forall (m :: * -> *) a. Monad m => a -> m a
return (Bool
False, CoreExpr -> CoreExpr
forall a. a -> a
id, CoreExpr -> CoreExpr
forall a. a -> a
id, Kind
body_ty)  
       Just (Int
con_tag, [Cpr]
_cprs)
         | Just DataConPatContext
dcpc <- FamInstEnvs -> Int -> Kind -> Maybe DataConPatContext
splitResultType_maybe FamInstEnvs
fam_envs Int
con_tag Kind
body_ty
         -> DataConPatContext
-> UniqSM (Bool, CoreExpr -> CoreExpr, CoreExpr -> CoreExpr, Kind)
mkWWcpr_help DataConPatContext
dcpc
         |  Bool
otherwise
         
         -> WARN( True, text "mkWWcpr: non-algebraic or open body type" <+> ppr body_ty )
            (Bool, CoreExpr -> CoreExpr, CoreExpr -> CoreExpr, Kind)
-> UniqSM (Bool, CoreExpr -> CoreExpr, CoreExpr -> CoreExpr, Kind)
forall (m :: * -> *) a. Monad m => a -> m a
return (Bool
False, CoreExpr -> CoreExpr
forall a. a -> a
id, CoreExpr -> CoreExpr
forall a. a -> a
id, Kind
body_ty)
mkWWcpr_help :: DataConPatContext
             -> UniqSM (Bool, CoreExpr -> CoreExpr, CoreExpr -> CoreExpr, Type)
mkWWcpr_help :: DataConPatContext
-> UniqSM (Bool, CoreExpr -> CoreExpr, CoreExpr -> CoreExpr, Kind)
mkWWcpr_help (DataConPatContext { dcpc_dc :: DataConPatContext -> DataCon
dcpc_dc = DataCon
dc, dcpc_tc_args :: DataConPatContext -> [Kind]
dcpc_tc_args = [Kind]
tc_args
                                , dcpc_co :: DataConPatContext -> Coercion
dcpc_co = Coercion
co })
  | [Scaled Kind
arg_ty]   <- DataCon -> [Kind] -> [Scaled Kind]
dataConInstArgTys DataCon
dc [Kind]
tc_args 
  , [StrictnessMark
str_mark] <- DataCon -> [StrictnessMark]
dataConRepStrictness DataCon
dc
  , HasDebugCallStack => Kind -> Bool
Kind -> Bool
isUnliftedType (Scaled Kind -> Kind
forall a. Scaled a -> a
scaledThing Scaled Kind
arg_ty)
  , Scaled Kind -> Bool
forall a. Scaled a -> Bool
isLinear Scaled Kind
arg_ty
        
        
        
        
  = do { (Unique
work_uniq : Unique
arg_uniq : [Unique]
_) <- UniqSM [Unique]
forall (m :: * -> *). MonadUnique m => m [Unique]
getUniquesM
       ; let arg_id :: Id
arg_id    = Unique -> StrictnessMark -> Scaled Kind -> Id
mk_ww_local Unique
arg_uniq StrictnessMark
str_mark Scaled Kind
arg_ty
             con_app :: CoreExpr
con_app   = DataCon -> [Kind] -> [Id] -> CoreExpr
forall b. DataCon -> [Kind] -> [Id] -> Expr b
mkConApp2 DataCon
dc [Kind]
tc_args [Id
arg_id] CoreExpr -> Coercion -> CoreExpr
`mkCast` Coercion -> Coercion
mkSymCo Coercion
co
       ; (Bool, CoreExpr -> CoreExpr, CoreExpr -> CoreExpr, Kind)
-> UniqSM (Bool, CoreExpr -> CoreExpr, CoreExpr -> CoreExpr, Kind)
forall (m :: * -> *) a. Monad m => a -> m a
return ( Bool
True
                , \ CoreExpr
wkr_call -> CoreExpr -> Id -> CoreExpr -> CoreExpr
mkDefaultCase CoreExpr
wkr_call Id
arg_id CoreExpr
con_app
                , \ CoreExpr
body     -> CoreExpr
-> Coercion
-> Kind
-> Unique
-> DataCon
-> [Id]
-> CoreExpr
-> CoreExpr
mkUnpackCase CoreExpr
body Coercion
co Kind
One Unique
work_uniq DataCon
dc [Id
arg_id] (Id -> CoreExpr
forall b. Id -> Expr b
varToCoreExpr Id
arg_id)
                                
                                
                , Scaled Kind -> Kind
forall a. Scaled a -> a
scaledThing Scaled Kind
arg_ty ) }
  | Bool
otherwise   
        
        
        
        
        
        
        
        
        
  = do { (Unique
work_uniq : Unique
wild_uniq : [Unique]
pat_bndrs_uniqs) <- UniqSM [Unique]
forall (m :: * -> *). MonadUnique m => m [Unique]
getUniquesM
       ; let case_mult :: Kind
case_mult       = Kind
One 
             ([Id]
_exs, [Id]
arg_ids) =
               [FastString]
-> [Unique] -> Kind -> DataCon -> [Kind] -> ([Id], [Id])
dataConRepFSInstPat (FastString -> [FastString]
forall a. a -> [a]
repeat FastString
ww_prefix) [Unique]
pat_bndrs_uniqs Kind
case_mult DataCon
dc [Kind]
tc_args
             wrap_wild :: Id
wrap_wild       = Unique -> StrictnessMark -> Scaled Kind -> Id
mk_ww_local Unique
wild_uniq StrictnessMark
MarkedStrict (Kind -> Kind -> Scaled Kind
forall a. Kind -> a -> Scaled a
Scaled Kind
case_mult Kind
ubx_tup_ty)
             ubx_tup_ty :: Kind
ubx_tup_ty      = CoreExpr -> Kind
exprType CoreExpr
ubx_tup_app
             ubx_tup_app :: CoreExpr
ubx_tup_app     = [Kind] -> [CoreExpr] -> CoreExpr
mkCoreUbxTup ((Id -> Kind) -> [Id] -> [Kind]
forall a b. (a -> b) -> [a] -> [b]
map Id -> Kind
idType [Id]
arg_ids) ((Id -> CoreExpr) -> [Id] -> [CoreExpr]
forall a b. (a -> b) -> [a] -> [b]
map Id -> CoreExpr
forall b. Id -> Expr b
varToCoreExpr [Id]
arg_ids)
             con_app :: CoreExpr
con_app         = DataCon -> [Kind] -> [Id] -> CoreExpr
forall b. DataCon -> [Kind] -> [Id] -> Expr b
mkConApp2 DataCon
dc [Kind]
tc_args [Id]
arg_ids CoreExpr -> Coercion -> CoreExpr
`mkCast` Coercion -> Coercion
mkSymCo Coercion
co
             tup_con :: DataCon
tup_con         = Boxity -> Int -> DataCon
tupleDataCon Boxity
Unboxed ([Id] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Id]
arg_ids)
       ; MASSERT( null _exs ) 
       ; (Bool, CoreExpr -> CoreExpr, CoreExpr -> CoreExpr, Kind)
-> UniqSM (Bool, CoreExpr -> CoreExpr, CoreExpr -> CoreExpr, Kind)
forall (m :: * -> *) a. Monad m => a -> m a
return (Bool
True
                , \ CoreExpr
wkr_call -> CoreExpr -> Id -> AltCon -> [Id] -> CoreExpr -> CoreExpr
mkSingleAltCase CoreExpr
wkr_call Id
wrap_wild
                                                (DataCon -> AltCon
DataAlt DataCon
tup_con) [Id]
arg_ids CoreExpr
con_app
                , \ CoreExpr
body     -> CoreExpr
-> Coercion
-> Kind
-> Unique
-> DataCon
-> [Id]
-> CoreExpr
-> CoreExpr
mkUnpackCase CoreExpr
body Coercion
co Kind
case_mult Unique
work_uniq DataCon
dc [Id]
arg_ids CoreExpr
ubx_tup_app
                , Kind
ubx_tup_ty ) }
mkUnpackCase ::  CoreExpr -> Coercion -> Mult -> Unique -> DataCon -> [Id] -> CoreExpr -> CoreExpr
mkUnpackCase :: CoreExpr
-> Coercion
-> Kind
-> Unique
-> DataCon
-> [Id]
-> CoreExpr
-> CoreExpr
mkUnpackCase (Tick CoreTickish
tickish CoreExpr
e) Coercion
co Kind
mult Unique
uniq DataCon
con [Id]
args CoreExpr
body   
  = CoreTickish -> CoreExpr -> CoreExpr
forall b. CoreTickish -> Expr b -> Expr b
Tick CoreTickish
tickish (CoreExpr
-> Coercion
-> Kind
-> Unique
-> DataCon
-> [Id]
-> CoreExpr
-> CoreExpr
mkUnpackCase CoreExpr
e Coercion
co Kind
mult Unique
uniq DataCon
con [Id]
args CoreExpr
body)
mkUnpackCase CoreExpr
scrut Coercion
co Kind
mult Unique
uniq DataCon
boxing_con [Id]
unpk_args CoreExpr
body
  = CoreExpr -> Id -> AltCon -> [Id] -> CoreExpr -> CoreExpr
mkSingleAltCase CoreExpr
casted_scrut Id
bndr
                    (DataCon -> AltCon
DataAlt DataCon
boxing_con) [Id]
unpk_args CoreExpr
body
  where
    casted_scrut :: CoreExpr
casted_scrut = CoreExpr
scrut CoreExpr -> Coercion -> CoreExpr
`mkCast` Coercion
co
    bndr :: Id
bndr = Unique -> StrictnessMark -> Scaled Kind -> Id
mk_ww_local Unique
uniq StrictnessMark
MarkedStrict (Kind -> Kind -> Scaled Kind
forall a. Kind -> a -> Scaled a
Scaled Kind
mult (CoreExpr -> Kind
exprType CoreExpr
casted_scrut))
      
      
mk_absent_let :: DynFlags -> FamInstEnvs -> Id -> Demand -> Maybe (CoreExpr -> CoreExpr)
mk_absent_let :: DynFlags
-> FamInstEnvs -> Id -> Demand -> Maybe (CoreExpr -> CoreExpr)
mk_absent_let DynFlags
dflags FamInstEnvs
fam_envs Id
arg Demand
dmd
  
  
  | Bool -> Bool
not (HasDebugCallStack => Kind -> Bool
Kind -> Bool
isUnliftedType Kind
arg_ty)
  = (CoreExpr -> CoreExpr) -> Maybe (CoreExpr -> CoreExpr)
forall a. a -> Maybe a
Just (CoreBind -> CoreExpr -> CoreExpr
forall b. Bind b -> Expr b -> Expr b
Let (Id -> CoreExpr -> CoreBind
forall b. b -> Expr b -> Bind b
NonRec Id
lifted_arg CoreExpr
lifted_rhs))
  
  
  | [PrimRep
UnliftedRep] <- HasDebugCallStack => Kind -> [PrimRep]
Kind -> [PrimRep]
typePrimRep Kind
arg_ty
  = (CoreExpr -> CoreExpr) -> Maybe (CoreExpr -> CoreExpr)
forall a. a -> Maybe a
Just (CoreBind -> CoreExpr -> CoreExpr
forall b. Bind b -> Expr b -> Expr b
Let (Id -> CoreExpr -> CoreBind
forall b. b -> Expr b -> Bind b
NonRec Id
arg CoreExpr
unlifted_rhs))
  
  
  | Just TyCon
tc <- Kind -> Maybe TyCon
tyConAppTyCon_maybe Kind
nty
  , Just Literal
lit <- TyCon -> Maybe Literal
absentLiteralOf TyCon
tc
  = (CoreExpr -> CoreExpr) -> Maybe (CoreExpr -> CoreExpr)
forall a. a -> Maybe a
Just (CoreBind -> CoreExpr -> CoreExpr
forall b. Bind b -> Expr b -> Expr b
Let (Id -> CoreExpr -> CoreBind
forall b. b -> Expr b -> Bind b
NonRec Id
arg (Literal -> CoreExpr
forall b. Literal -> Expr b
Lit Literal
lit CoreExpr -> Coercion -> CoreExpr
`mkCast` Coercion -> Coercion
mkSymCo Coercion
co)))
  | Kind
nty Kind -> Kind -> Bool
`eqType` Kind
unboxedUnitTy
  = (CoreExpr -> CoreExpr) -> Maybe (CoreExpr -> CoreExpr)
forall a. a -> Maybe a
Just (CoreBind -> CoreExpr -> CoreExpr
forall b. Bind b -> Expr b -> Expr b
Let (Id -> CoreExpr -> CoreBind
forall b. b -> Expr b -> Bind b
NonRec Id
arg (Id -> CoreExpr
forall b. Id -> Expr b
Var Id
voidPrimId CoreExpr -> Coercion -> CoreExpr
`mkCast` Coercion -> Coercion
mkSymCo Coercion
co)))
  | Bool
otherwise
  = WARN( True, text "No absent value for" <+> ppr arg_ty )
    Maybe (CoreExpr -> CoreExpr)
forall a. Maybe a
Nothing 
  where
    lifted_arg :: Id
lifted_arg   = Id
arg Id -> StrictSig -> Id
`setIdStrictness` StrictSig
botSig Id -> CprSig -> Id
`setIdCprInfo` Int -> Cpr -> CprSig
mkCprSig Int
0 Cpr
botCpr
              
              
              
    lifted_rhs :: CoreExpr
lifted_rhs | Demand -> Bool
isStrictDmd Demand
dmd = CoreExpr -> [Kind] -> CoreExpr
forall b. Expr b -> [Kind] -> Expr b
mkTyApps (Literal -> CoreExpr
forall b. Literal -> Expr b
Lit (Bool -> Literal
rubbishLit Bool
True))  [Kind
arg_ty]
               | Bool
otherwise       = Kind -> String -> CoreExpr
mkAbsentErrorApp Kind
arg_ty String
msg
    unlifted_rhs :: CoreExpr
unlifted_rhs = CoreExpr -> [Kind] -> CoreExpr
forall b. Expr b -> [Kind] -> Expr b
mkTyApps (Literal -> CoreExpr
forall b. Literal -> Expr b
Lit (Bool -> Literal
rubbishLit Bool
False)) [Kind
arg_ty]
    arg_ty :: Kind
arg_ty       = Id -> Kind
idType Id
arg
    
    
    
    
    (Coercion
co, Kind
nty)    = FamInstEnvs -> Kind -> Maybe (Coercion, Kind)
topNormaliseType_maybe FamInstEnvs
fam_envs Kind
arg_ty
                   Maybe (Coercion, Kind) -> (Coercion, Kind) -> (Coercion, Kind)
forall a. Maybe a -> a -> a
`orElse` (Kind -> Coercion
mkRepReflCo Kind
arg_ty, Kind
arg_ty)
    msg :: String
msg          = DynFlags -> SDoc -> String
showSDoc (DynFlags -> GeneralFlag -> DynFlags
gopt_set DynFlags
dflags GeneralFlag
Opt_SuppressUniques)
                            ([SDoc] -> SDoc
vcat
                              [ String -> SDoc
text String
"Arg:" SDoc -> SDoc -> SDoc
<+> Id -> SDoc
forall a. Outputable a => a -> SDoc
ppr Id
arg
                              , String -> SDoc
text String
"Type:" SDoc -> SDoc -> SDoc
<+> Kind -> SDoc
forall a. Outputable a => a -> SDoc
ppr Kind
arg_ty
                              , SDoc
file_msg
                              ])
    file_msg :: SDoc
file_msg     = case DynFlags -> Maybe String
outputFile DynFlags
dflags of
                     Maybe String
Nothing -> SDoc
empty
                     Just String
f  -> String -> SDoc
text String
"In output file " SDoc -> SDoc -> SDoc
<+> SDoc -> SDoc
quotes (String -> SDoc
text String
f)
              
              
              
              
              
              
ww_prefix :: FastString
ww_prefix :: FastString
ww_prefix = String -> FastString
fsLit String
"ww"
mk_ww_local :: Unique -> StrictnessMark -> Scaled Type -> Id
mk_ww_local :: Unique -> StrictnessMark -> Scaled Kind -> Id
mk_ww_local Unique
uniq StrictnessMark
str (Scaled Kind
w Kind
ty)
  = StrictnessMark -> Id -> Id
setCaseBndrEvald StrictnessMark
str (Id -> Id) -> Id -> Id
forall a b. (a -> b) -> a -> b
$
    FastString -> Unique -> Kind -> Kind -> Id
mkSysLocalOrCoVar FastString
ww_prefix Unique
uniq Kind
w Kind
ty