Jaro Reinders pushed to branch wip/reduce-type-in-stg at Glasgow Haskell Compiler / GHC

Commits:

10 changed files:

Changes:

  • compiler/GHC/CoreToStg.hs
    ... ... @@ -566,7 +566,7 @@ mkStgApp f how_bound core_args stg_args res_ty
    566 566
     
    
    567 567
           -- A regular foreign call.
    
    568 568
           FCallId call     -> assert exactly_saturated $
    
    569
    -                          StgOpApp (StgFCallOp call (idType f)) stg_args res_kind
    
    569
    +                          StgOpApp (StgFCallOp call (collectStgFArgTypes (idType f))) stg_args res_kind
    
    570 570
     
    
    571 571
           TickBoxOpId {}   -> pprPanic "coreToStg TickBox" $ ppr (f,stg_args)
    
    572 572
     
    
    ... ... @@ -722,7 +722,7 @@ coreToMkStgRhs bndr expr = do
    722 722
         let mk_rhs = MkStgRhs
    
    723 723
               { rhs_args = args'
    
    724 724
               , rhs_expr = body'
    
    725
    -          , rhs_type = exprType body
    
    725
    +          , rhs_kind = MkStgKind (typeKind (exprType body))
    
    726 726
               , rhs_is_join = isJoinId bndr
    
    727 727
               }
    
    728 728
         pure mk_rhs
    

  • compiler/GHC/Stg/BcPrep.hs
    ... ... @@ -50,7 +50,7 @@ bcPrepRHS con@StgRhsCon{} = pure con
    50 50
     bcPrepExpr :: StgExpr -> BcPrepM StgExpr
    
    51 51
     -- explicitly match all constructors so we get a warning if we miss any
    
    52 52
     bcPrepExpr (StgTick bp@(Breakpoint tick_ty _ _) rhs)
    
    53
    -  | isLiftedTypeKind (typeKind tick_ty) = do
    
    53
    +  | isLiftedTypeKind tick_kind = do
    
    54 54
           id <- newId tick_ty
    
    55 55
           rhs' <- bcPrepExpr rhs
    
    56 56
           let expr' = StgTick bp rhs'
    
    ... ... @@ -59,7 +59,7 @@ bcPrepExpr (StgTick bp@(Breakpoint tick_ty _ _) rhs)
    59 59
                                                 ReEntrant
    
    60 60
                                                 []
    
    61 61
                                                 expr'
    
    62
    -                                            tick_ty
    
    62
    +                                            (MkStgKind tick_kind)
    
    63 63
                                  )
    
    64 64
               letExp = StgLet noExtFieldSilent bnd (StgApp id [])
    
    65 65
           pure letExp
    
    ... ... @@ -72,9 +72,10 @@ bcPrepExpr (StgTick bp@(Breakpoint tick_ty _ _) rhs)
    72 72
                                                 ReEntrant
    
    73 73
                                                 [voidArgId]
    
    74 74
                                                 expr'
    
    75
    -                                            tick_ty
    
    75
    +                                            (MkStgKind tick_kind)
    
    76 76
                                  )
    
    77 77
           pure $ StgLet noExtFieldSilent bnd (StgApp id [StgVarArg realWorldPrimId])
    
    78
    +  where tick_kind = typeKind tick_ty
    
    78 79
     bcPrepExpr (StgTick tick rhs) =
    
    79 80
       StgTick tick <$> bcPrepExpr rhs
    
    80 81
     bcPrepExpr (StgLet xlet bnds expr) =
    

  • compiler/GHC/Stg/Make.hs
    ... ... @@ -11,7 +11,6 @@ import GHC.Prelude
    11 11
     import GHC.Unit.Module
    
    12 12
     
    
    13 13
     import GHC.Core.DataCon
    
    14
    -import GHC.Core.Type (Type)
    
    15 14
     
    
    16 15
     import GHC.Stg.Syntax
    
    17 16
     import GHC.Stg.Utils (stripStgTicksTop)
    
    ... ... @@ -27,7 +26,7 @@ import GHC.Types.Tickish
    27 26
     data MkStgRhs = MkStgRhs
    
    28 27
       { rhs_args :: [Id]     -- ^ Empty for thunks
    
    29 28
       , rhs_expr :: StgExpr  -- ^ RHS expression
    
    30
    -  , rhs_type :: Type     -- ^ RHS type (only used in the JS backend: layering violation)
    
    29
    +  , rhs_kind :: StgKind  -- ^ RHS kind (only used in the JS backend: layering violation)
    
    31 30
       , rhs_is_join :: !Bool -- ^ Is it a RHS for a join-point?
    
    32 31
       }
    
    33 32
     
    
    ... ... @@ -37,7 +36,7 @@ data MkStgRhs = MkStgRhs
    37 36
     mkTopStgRhs :: (Module -> DataCon -> [StgArg] -> Bool)
    
    38 37
                 -> Bool -> Module -> CollectedCCs
    
    39 38
                 -> Id -> MkStgRhs -> (StgRhs, CollectedCCs)
    
    40
    -mkTopStgRhs allow_toplevel_con_app opt_AutoSccsOnIndividualCafs this_mod ccs bndr mk_rhs@(MkStgRhs bndrs rhs typ _)
    
    39
    +mkTopStgRhs allow_toplevel_con_app opt_AutoSccsOnIndividualCafs this_mod ccs bndr mk_rhs@(MkStgRhs bndrs rhs kind _)
    
    41 40
       -- try to make a StgRhsCon first
    
    42 41
       | Just rhs_con <- mkTopStgRhsCon_maybe (allow_toplevel_con_app this_mod) mk_rhs
    
    43 42
       = ( rhs_con, ccs )
    
    ... ... @@ -47,20 +46,20 @@ mkTopStgRhs allow_toplevel_con_app opt_AutoSccsOnIndividualCafs this_mod ccs bnd
    47 46
         ( StgRhsClosure noExtFieldSilent
    
    48 47
                         dontCareCCS
    
    49 48
                         ReEntrant
    
    50
    -                    bndrs rhs typ
    
    49
    +                    bndrs rhs kind
    
    51 50
         , ccs )
    
    52 51
     
    
    53 52
       -- Otherwise it's a CAF, see Note [Cost-centre initialization plan].
    
    54 53
       | opt_AutoSccsOnIndividualCafs
    
    55 54
       = ( StgRhsClosure noExtFieldSilent
    
    56 55
                         caf_ccs
    
    57
    -                    upd_flag [] rhs typ
    
    56
    +                    upd_flag [] rhs kind
    
    58 57
         , collectCC caf_cc caf_ccs ccs )
    
    59 58
     
    
    60 59
       | otherwise
    
    61 60
       = ( StgRhsClosure noExtFieldSilent
    
    62 61
                         all_cafs_ccs
    
    63
    -                    upd_flag [] rhs typ
    
    62
    +                    upd_flag [] rhs kind
    
    64 63
         , ccs )
    
    65 64
     
    
    66 65
       where
    
    ... ... @@ -82,7 +81,7 @@ mkTopStgRhs allow_toplevel_con_app opt_AutoSccsOnIndividualCafs this_mod ccs bnd
    82 81
     -- Generate a non-top-level RHS. Cost-centre is always currentCCS,
    
    83 82
     -- see Note [Cost-centre initialization plan].
    
    84 83
     mkStgRhs :: Id -> MkStgRhs -> StgRhs
    
    85
    -mkStgRhs bndr mk_rhs@(MkStgRhs bndrs rhs typ is_join)
    
    84
    +mkStgRhs bndr mk_rhs@(MkStgRhs bndrs rhs kind is_join)
    
    86 85
       -- try to make a StgRhsCon first
    
    87 86
       | Just rhs_con <- mkStgRhsCon_maybe mk_rhs
    
    88 87
       = rhs_con
    
    ... ... @@ -90,7 +89,7 @@ mkStgRhs bndr mk_rhs@(MkStgRhs bndrs rhs typ is_join)
    90 89
       | otherwise
    
    91 90
       = StgRhsClosure noExtFieldSilent
    
    92 91
                       currentCCS
    
    93
    -                  upd_flag bndrs rhs typ
    
    92
    +                  upd_flag bndrs rhs kind
    
    94 93
       where
    
    95 94
         upd_flag | is_join                             = JumpedTo
    
    96 95
                  | not (null bndrs)                    = ReEntrant
    
    ... ... @@ -151,22 +150,22 @@ isPAP env _ = False
    151 150
     
    
    152 151
     -- | Try to make a non top-level StgRhsCon if appropriate
    
    153 152
     mkStgRhsCon_maybe :: MkStgRhs -> Maybe StgRhs
    
    154
    -mkStgRhsCon_maybe (MkStgRhs bndrs rhs typ is_join)
    
    153
    +mkStgRhsCon_maybe (MkStgRhs bndrs rhs kind is_join)
    
    155 154
       | [] <- bndrs
    
    156 155
       , not is_join
    
    157 156
       , (ticks, StgConApp con mn args _) <- stripStgTicksTop (not . tickishIsCode) rhs
    
    158
    -  = Just (StgRhsCon currentCCS con mn ticks args typ)
    
    157
    +  = Just (StgRhsCon currentCCS con mn ticks args kind)
    
    159 158
     
    
    160 159
       | otherwise = Nothing
    
    161 160
     
    
    162 161
     
    
    163 162
     -- | Try to make a top-level StgRhsCon if appropriate
    
    164 163
     mkTopStgRhsCon_maybe :: (DataCon -> [StgArg] -> Bool) -> MkStgRhs -> Maybe StgRhs
    
    165
    -mkTopStgRhsCon_maybe allow_static_con_app (MkStgRhs bndrs rhs typ is_join)
    
    164
    +mkTopStgRhsCon_maybe allow_static_con_app (MkStgRhs bndrs rhs kind is_join)
    
    166 165
       | [] <- bndrs
    
    167 166
       , not is_join -- shouldn't happen at top-level
    
    168 167
       , (ticks, StgConApp con mn args _) <- stripStgTicksTop (not . tickishIsCode) rhs
    
    169 168
       , allow_static_con_app con args
    
    170
    -  = Just (StgRhsCon dontCareCCS con mn ticks args typ)
    
    169
    +  = Just (StgRhsCon dontCareCCS con mn ticks args kind)
    
    171 170
     
    
    172 171
       | otherwise = Nothing

  • compiler/GHC/Stg/Syntax.hs
    ... ... @@ -16,6 +16,9 @@ generation.
    16 16
     module GHC.Stg.Syntax (
    
    17 17
             StgKind(..),
    
    18 18
     
    
    19
    +        StgFArgType(..),
    
    20
    +        collectStgFArgTypes,
    
    21
    +
    
    19 22
             StgArg(..),
    
    20 23
     
    
    21 24
             GenStgTopBinding(..), GenStgBinding(..), GenStgExpr(..), GenStgRhs(..),
    
    ... ... @@ -77,7 +80,7 @@ import GHC.Types.CostCentre ( CostCentreStack )
    77 80
     import GHC.Core     ( AltCon )
    
    78 81
     import GHC.Core.DataCon
    
    79 82
     import GHC.Core.TyCon    ( PrimRep(..), PrimOrVoidRep(..), TyCon )
    
    80
    -import GHC.Core.Type     ( Type )
    
    83
    +import GHC.Core.Type     ( Type, tyConAppTyCon )
    
    81 84
     import GHC.Core.Ppr( {- instances -} )
    
    82 85
     
    
    83 86
     import GHC.Types.ForeignCall ( ForeignCall )
    
    ... ... @@ -85,7 +88,7 @@ import GHC.Types.Id
    85 88
     import GHC.Types.Tickish     ( StgTickish )
    
    86 89
     import GHC.Types.Var.Set
    
    87 90
     import GHC.Types.Literal     ( Literal, literalType )
    
    88
    -import GHC.Types.RepType ( typePrimRep, typePrimRep1, typePrimRepU, typePrimRep_maybe )
    
    91
    +import GHC.Types.RepType ( typePrimRep, typePrimRep1, typePrimRepU, typePrimRep_maybe, unwrapType )
    
    89 92
     
    
    90 93
     import GHC.Utils.Outputable
    
    91 94
     import GHC.Utils.Panic.Plain
    
    ... ... @@ -96,6 +99,14 @@ import Data.ByteString ( ByteString )
    96 99
     import Data.Data   ( Data )
    
    97 100
     import Data.List   ( intersperse )
    
    98 101
     import GHC.Tc.Utils.TcType (Kind)
    
    102
    +import GHC.Core.TyCo.Rep (Type(..))
    
    103
    +import GHC.Builtin.Types.Prim
    
    104
    +    ( arrayPrimTyCon,
    
    105
    +      byteArrayPrimTyCon,
    
    106
    +      mutableArrayPrimTyCon,
    
    107
    +      mutableByteArrayPrimTyCon,
    
    108
    +      smallArrayPrimTyCon,
    
    109
    +      smallMutableArrayPrimTyCon )
    
    99 110
     
    
    100 111
     newtype StgKind = MkStgKind { getStgKind :: Kind }
    
    101 112
     
    
    ... ... @@ -414,7 +425,7 @@ data GenStgRhs pass
    414 425
             [BinderP pass]     -- ^ arguments; if empty, then not a function;
    
    415 426
                                --   as above, order is important.
    
    416 427
             (GenStgExpr pass)  -- ^ body
    
    417
    -        Type               -- ^ result type
    
    428
    +        StgKind            -- ^ result kind
    
    418 429
     
    
    419 430
     {-
    
    420 431
     An example may be in order.  Consider:
    
    ... ... @@ -444,7 +455,7 @@ important):
    444 455
             ConstructorNumber
    
    445 456
             [StgTickish]
    
    446 457
             [StgArg]        -- Saturated Args. See Note [Constructor applications in STG]
    
    447
    -        Type            -- Type, for rewriting to an StgRhsClosure
    
    458
    +        StgKind         -- Kind, for rewriting to an StgRhsClosure
    
    448 459
     
    
    449 460
     -- | Like 'GHC.Hs.Extension.NoExtField', but with an 'Outputable' instance that
    
    450 461
     -- returns 'empty'.
    
    ... ... @@ -701,6 +712,51 @@ isUpdatable SingleEntry = False
    701 712
     isUpdatable Updatable   = True
    
    702 713
     isUpdatable JumpedTo    = False
    
    703 714
     
    
    715
    +-- The minimum amount of information needed to determine
    
    716
    +-- the offset to apply to an argument to a foreign call.
    
    717
    +-- See Note [Unlifted boxed arguments to foreign calls]
    
    718
    +data StgFArgType
    
    719
    +  = StgPlainType
    
    720
    +  | StgArrayType
    
    721
    +  | StgSmallArrayType
    
    722
    +  | StgByteArrayType
    
    723
    +
    
    724
    +-- From a function, extract information needed to determine
    
    725
    +-- the offset of each argument when used as a C FFI argument.
    
    726
    +-- See Note [Unlifted boxed arguments to foreign calls]
    
    727
    +collectStgFArgTypes :: Type -> [StgFArgType]
    
    728
    +collectStgFArgTypes = go []
    
    729
    +  where
    
    730
    +    -- Skip foralls
    
    731
    +    go bs (ForAllTy _ res) = go bs res
    
    732
    +    go bs (AppTy{}) = reverse bs
    
    733
    +    go bs (TyConApp{}) = reverse bs
    
    734
    +    go bs (LitTy{}) = reverse bs
    
    735
    +    go bs (TyVarTy{}) = reverse bs
    
    736
    +    go  _ (CastTy{}) = panic "myCollectTypeArgs: CastTy"
    
    737
    +    go  _ (CoercionTy{}) = panic "myCollectTypeArgs: CoercionTy"
    
    738
    +    go bs (FunTy {ft_arg = arg, ft_res=res}) =
    
    739
    +      go (typeToStgFArgType arg:bs) res
    
    740
    +
    
    741
    +-- Choose the offset based on the type. For anything other
    
    742
    +-- than an unlifted boxed type, there is no offset.
    
    743
    +-- See Note [Unlifted boxed arguments to foreign calls]
    
    744
    +typeToStgFArgType :: Type -> StgFArgType
    
    745
    +typeToStgFArgType typ
    
    746
    +  | tycon == arrayPrimTyCon = StgArrayType
    
    747
    +  | tycon == mutableArrayPrimTyCon = StgArrayType
    
    748
    +  | tycon == smallArrayPrimTyCon = StgSmallArrayType
    
    749
    +  | tycon == smallMutableArrayPrimTyCon = StgSmallArrayType
    
    750
    +  | tycon == byteArrayPrimTyCon = StgByteArrayType
    
    751
    +  | tycon == mutableByteArrayPrimTyCon = StgByteArrayType
    
    752
    +  | otherwise = StgPlainType
    
    753
    +  where
    
    754
    +  -- Should be a tycon app, since this is a foreign call. We look
    
    755
    +  -- through newtypes so the offset does not change if a user replaces
    
    756
    +  -- a type in a foreign function signature with a representationally
    
    757
    +  -- equivalent newtype.
    
    758
    +  tycon = tyConAppTyCon (unwrapType typ)
    
    759
    +
    
    704 760
     {-
    
    705 761
     ************************************************************************
    
    706 762
     *                                                                      *
    
    ... ... @@ -717,11 +773,12 @@ data StgOp
    717 773
     
    
    718 774
       | StgPrimCallOp PrimCall
    
    719 775
     
    
    720
    -  | StgFCallOp ForeignCall Type
    
    721
    -        -- The Type, which is obtained from the foreign import declaration
    
    722
    -        -- itself, is needed by the stg-to-cmm pass to determine the offset to
    
    723
    -        -- apply to unlifted boxed arguments in GHC.StgToCmm.Foreign. See Note
    
    724
    -        -- [Unlifted boxed arguments to foreign calls]
    
    776
    +  | StgFCallOp ForeignCall [StgFArgType]
    
    777
    +        -- The foreign argument types, which are obtained from the foreign
    
    778
    +        -- import declaration itself, areneeded by the stg-to-cmm pass to
    
    779
    +        -- determine the offset to apply to unlifted boxed arguments in
    
    780
    +        -- GHC.StgToCmm.Foreign.
    
    781
    +        -- See Note [Unlifted boxed arguments to foreign calls]
    
    725 782
     
    
    726 783
       | StgTagToEnumOp TyCon
    
    727 784
     
    
    ... ... @@ -915,6 +972,8 @@ pprStgOp :: StgOp -> SDoc
    915 972
     pprStgOp (StgPrimOp  op)   = ppr op
    
    916 973
     pprStgOp (StgPrimCallOp op)= ppr op
    
    917 974
     pprStgOp (StgFCallOp op _) = ppr op
    
    975
    +-- TODO: how do we want to pretty print this?
    
    976
    +pprStgOp (StgTagToEnumOp tyc) = text "TagToEnumOp" <+> ppr tyc
    
    918 977
     
    
    919 978
     instance Outputable StgOp where
    
    920 979
       ppr = pprStgOp
    

  • compiler/GHC/Stg/Unarise.hs
    ... ... @@ -494,7 +494,7 @@ unariseBinding rho top_level (StgRec xrhss)
    494 494
       = StgRec <$> mapM (\(x, rhs) -> (x,) <$> unariseRhs rho top_level rhs) xrhss
    
    495 495
     
    
    496 496
     unariseRhs :: UnariseEnv -> Bool -> StgRhs -> UniqSM StgRhs
    
    497
    -unariseRhs rho top_level (StgRhsClosure ext ccs update_flag args expr typ)
    
    497
    +unariseRhs rho top_level (StgRhsClosure ext ccs update_flag args expr kind)
    
    498 498
       = do (rho', args1) <- unariseFunArgBinders rho args
    
    499 499
            expr' <- unariseExpr rho' expr
    
    500 500
            -- Unarisation can lead to a StgRhsClosure becoming a StgRhsCon.
    
    ... ... @@ -515,7 +515,7 @@ unariseRhs rho top_level (StgRhsClosure ext ccs update_flag args expr typ)
    515 515
            let mk_rhs = MkStgRhs
    
    516 516
                 { rhs_args = args1
    
    517 517
                 , rhs_expr = expr'
    
    518
    -            , rhs_type = typ
    
    518
    +            , rhs_kind = kind
    
    519 519
                 , rhs_is_join = update_flag == JumpedTo
    
    520 520
                 }
    
    521 521
            if | top_level
    
    ... ... @@ -527,7 +527,7 @@ unariseRhs rho top_level (StgRhsClosure ext ccs update_flag args expr typ)
    527 527
               -> pure rhs_con
    
    528 528
     
    
    529 529
               | otherwise
    
    530
    -          -> pure (StgRhsClosure ext ccs update_flag args1 expr' typ)
    
    530
    +          -> pure (StgRhsClosure ext ccs update_flag args1 expr' kind)
    
    531 531
     
    
    532 532
     unariseRhs rho _top (StgRhsCon ccs con mu ts args typ)
    
    533 533
       = assert (not (isUnboxedTupleDataCon con || isUnboxedSumDataCon con))
    

  • compiler/GHC/StgToByteCode.hs
    ... ... @@ -47,7 +47,6 @@ import GHC.Utils.Misc
    47 47
     import GHC.Utils.Logger
    
    48 48
     import GHC.Types.Var.Set
    
    49 49
     import GHC.Builtin.Types.Prim
    
    50
    -import GHC.Core.TyCo.Ppr ( pprType )
    
    51 50
     import GHC.Utils.Error
    
    52 51
     import GHC.Builtin.Uniques
    
    53 52
     import GHC.Data.FastString
    
    ... ... @@ -2171,7 +2170,7 @@ mkDummyLiteral platform pr
    2171 2170
     
    
    2172 2171
     maybe_is_tagToEnum_call :: CgStgExpr -> Maybe (StgArg, [Name])
    
    2173 2172
     -- Detect and extract relevant info for the tagToEnum kludge.
    
    2174
    -maybe_is_tagToEnum_call (StgOpApp (StgTagToEnumOp tyc) args t)
    
    2173
    +maybe_is_tagToEnum_call (StgOpApp (StgTagToEnumOp tyc) args _)
    
    2175 2174
       | [v] <- args
    
    2176 2175
       = Just (v, extract_constr_Names tyc)
    
    2177 2176
       | otherwise
    

  • compiler/GHC/StgToCmm/Expr.hs
    ... ... @@ -688,6 +688,7 @@ isSimpleOp (StgPrimOp op) stg_args = do
    688 688
         -- See Note [Inlining out-of-line primops and heap checks]
    
    689 689
         return $! shouldInlinePrimOp cfg op arg_exprs
    
    690 690
     isSimpleOp (StgPrimCallOp _) _                           = return False
    
    691
    +isSimpleOp (StgTagToEnumOp _) _ = return True
    
    691 692
     
    
    692 693
     -----------------
    
    693 694
     chooseReturnBndrs :: Id -> AltType -> [CgStgAlt] -> [NonVoid Id]
    

  • compiler/GHC/StgToCmm/Foreign.hs
    ... ... @@ -42,7 +42,6 @@ import GHC.Cmm.Reg ( GlobalArgRegs(..) )
    42 42
     import GHC.Cmm.Utils
    
    43 43
     import GHC.Cmm.Graph
    
    44 44
     import GHC.Cmm.CallConv
    
    45
    -import GHC.Core.Type
    
    46 45
     import GHC.Types.RepType
    
    47 46
     import GHC.Cmm.CLabel
    
    48 47
     import GHC.Runtime.Heap.Layout
    
    ... ... @@ -53,8 +52,6 @@ import GHC.Types.Basic
    53 52
     import GHC.Types.Unique.DSM
    
    54 53
     import GHC.Unit.Types
    
    55 54
     
    
    56
    -import GHC.Core.TyCo.Rep
    
    57
    -import GHC.Builtin.Types.Prim
    
    58 55
     import GHC.Utils.Misc (zipEqual)
    
    59 56
     
    
    60 57
     import Control.Monad
    
    ... ... @@ -67,13 +64,13 @@ import Control.Monad
    67 64
     -- Precondition: the length of the arguments list is the same as the
    
    68 65
     -- arity of the foreign function.
    
    69 66
     cgForeignCall :: ForeignCall            -- the op
    
    70
    -              -> Type                   -- type of foreign function
    
    67
    +              -> [StgFArgType]
    
    71 68
                   -> [StgArg]               -- x,y    arguments
    
    72 69
                   -> StgKind                -- result kind
    
    73 70
                   -> FCode ReturnKind
    
    74 71
     
    
    75
    -cgForeignCall (CCall (CCallSpec target cconv safety)) typ stg_args res_kind
    
    76
    -  = do  { cmm_args <- getFCallArgs stg_args typ
    
    72
    +cgForeignCall (CCall (CCallSpec target cconv safety)) arg_tys stg_args res_kind
    
    73
    +  = do  { cmm_args <- getFCallArgs stg_args arg_tys
    
    77 74
             -- ; traceM $ show cmm_args
    
    78 75
             ; (res_regs, res_hints) <- newUnboxedTupleRegs (getStgKind res_kind)
    
    79 76
             ; let ((call_args, arg_hints), cmm_target)
    
    ... ... @@ -711,15 +708,15 @@ closureField profile off = off + fixedHdrSize profile
    711 708
     
    
    712 709
     getFCallArgs ::
    
    713 710
          [StgArg]
    
    714
    -  -> Type -- the type of the foreign function
    
    711
    +  -> [StgFArgType]
    
    715 712
       -> FCode [(CmmExpr, ForeignHint)]
    
    716 713
     -- (a) Drop void args
    
    717 714
     -- (b) Add foreign-call shim code
    
    718 715
     -- It's (b) that makes this differ from getNonVoidArgAmodes
    
    719 716
     -- Precondition: args and typs have the same length
    
    720 717
     -- See Note [Unlifted boxed arguments to foreign calls]
    
    721
    -getFCallArgs args typ
    
    722
    -  = do  { mb_cmms <- mapM get (zipEqual args (collectStgFArgTypes typ))
    
    718
    +getFCallArgs args arg_tys
    
    719
    +  = do  { mb_cmms <- mapM get (zipEqual args arg_tys)
    
    723 720
             ; return (catMaybes mb_cmms) }
    
    724 721
       where
    
    725 722
         get (arg,typ)
    
    ... ... @@ -734,15 +731,6 @@ getFCallArgs args typ
    734 731
             arg_reps = typePrimRep arg_ty
    
    735 732
             hint     = typeForeignHint arg_ty
    
    736 733
     
    
    737
    --- The minimum amount of information needed to determine
    
    738
    --- the offset to apply to an argument to a foreign call.
    
    739
    --- See Note [Unlifted boxed arguments to foreign calls]
    
    740
    -data StgFArgType
    
    741
    -  = StgPlainType
    
    742
    -  | StgArrayType
    
    743
    -  | StgSmallArrayType
    
    744
    -  | StgByteArrayType
    
    745
    -
    
    746 734
     -- See Note [Unlifted boxed arguments to foreign calls]
    
    747 735
     add_shim :: Profile -> StgFArgType -> CmmExpr -> CmmExpr
    
    748 736
     add_shim profile ty expr = case ty of
    
    ... ... @@ -752,39 +740,3 @@ add_shim profile ty expr = case ty of
    752 740
       StgByteArrayType  -> cmmOffsetB platform expr (arrWordsHdrSize profile)
    
    753 741
       where
    
    754 742
         platform = profilePlatform profile
    755
    -
    
    756
    --- From a function, extract information needed to determine
    
    757
    --- the offset of each argument when used as a C FFI argument.
    
    758
    --- See Note [Unlifted boxed arguments to foreign calls]
    
    759
    -collectStgFArgTypes :: Type -> [StgFArgType]
    
    760
    -collectStgFArgTypes = go []
    
    761
    -  where
    
    762
    -    -- Skip foralls
    
    763
    -    go bs (ForAllTy _ res) = go bs res
    
    764
    -    go bs (AppTy{}) = reverse bs
    
    765
    -    go bs (TyConApp{}) = reverse bs
    
    766
    -    go bs (LitTy{}) = reverse bs
    
    767
    -    go bs (TyVarTy{}) = reverse bs
    
    768
    -    go  _ (CastTy{}) = panic "myCollectTypeArgs: CastTy"
    
    769
    -    go  _ (CoercionTy{}) = panic "myCollectTypeArgs: CoercionTy"
    
    770
    -    go bs (FunTy {ft_arg = arg, ft_res=res}) =
    
    771
    -      go (typeToStgFArgType arg:bs) res
    
    772
    -
    
    773
    --- Choose the offset based on the type. For anything other
    
    774
    --- than an unlifted boxed type, there is no offset.
    
    775
    --- See Note [Unlifted boxed arguments to foreign calls]
    
    776
    -typeToStgFArgType :: Type -> StgFArgType
    
    777
    -typeToStgFArgType typ
    
    778
    -  | tycon == arrayPrimTyCon = StgArrayType
    
    779
    -  | tycon == mutableArrayPrimTyCon = StgArrayType
    
    780
    -  | tycon == smallArrayPrimTyCon = StgSmallArrayType
    
    781
    -  | tycon == smallMutableArrayPrimTyCon = StgSmallArrayType
    
    782
    -  | tycon == byteArrayPrimTyCon = StgByteArrayType
    
    783
    -  | tycon == mutableByteArrayPrimTyCon = StgByteArrayType
    
    784
    -  | otherwise = StgPlainType
    
    785
    -  where
    
    786
    -  -- Should be a tycon app, since this is a foreign call. We look
    
    787
    -  -- through newtypes so the offset does not change if a user replaces
    
    788
    -  -- a type in a foreign function signature with a representationally
    
    789
    -  -- equivalent newtype.
    
    790
    -  tycon = tyConAppTyCon (unwrapType typ)

  • compiler/GHC/StgToCmm/Prim.hs
    ... ... @@ -36,6 +36,7 @@ import GHC.Stg.Syntax
    36 36
     import GHC.Cmm
    
    37 37
     import GHC.Unit         ( rtsUnit )
    
    38 38
     import GHC.Core.Type    ( typeKind )
    
    39
    +import GHC.Core.TyCon ( isEnumerationTyCon )
    
    39 40
     import GHC.Cmm.CLabel
    
    40 41
     import GHC.Cmm.Info     ( closureInfoPtr )
    
    41 42
     import GHC.Cmm.Utils
    
    ... ... @@ -85,6 +86,22 @@ cgOpApp (StgPrimCallOp primcall) args _res_ty
    85 86
             ; let fun = CmmLit (CmmLabel (mkPrimCallLabel primcall))
    
    86 87
             ; emitCall (NativeNodeCall, NativeReturn) fun cmm_args }
    
    87 88
     
    
    89
    +-- tagToEnum# is special: we need to pull the constructor
    
    90
    +-- out of the table, and perform an appropriate return.
    
    91
    +cgOpApp (StgTagToEnumOp tyc) args _ = do
    
    92
    +  amodes <- getNonVoidArgAmodes args
    
    93
    +  case amodes of
    
    94
    +    [amode] -> do
    
    95
    +      -- If you're reading this code in the attempt to figure
    
    96
    +      -- out why the compiler panic'ed here, it is probably because
    
    97
    +      -- you used tagToEnum# in a non-monomorphic setting, e.g.,
    
    98
    +      --         intToTg :: Enum a => Int -> a ; intToTg (I# x#) = tagToEnum# x#
    
    99
    +      -- That won't work.
    
    100
    +      massert (isEnumerationTyCon tyc)
    
    101
    +      platform <- getPlatform
    
    102
    +      emitReturn [tagToClosure platform tyc amode]
    
    103
    +    _ -> pprPanic "cgOpApp: tagToEnum# should be applied to exactly one argument" (ppr args)
    
    104
    +
    
    88 105
     cmmPrimOpApp :: StgToCmmConfig -> PrimOp -> [CmmExpr] -> Maybe StgKind -> FCode ReturnKind
    
    89 106
     cmmPrimOpApp cfg primop cmm_args mres_ty =
    
    90 107
       case emitPrimOp cfg primop cmm_args of
    
    ... ... @@ -1670,7 +1687,7 @@ emitPrimOp cfg primop =
    1670 1687
     
    
    1671 1688
       -- tagToEnum# is removed in CoreToStg and rewritten to a special StgTagToEnumOp
    
    1672 1689
       -- See Note [?]
    
    1673
    -  TagToEnumOp -> panic "emitPrimOp: TagToEnumOp should have been gone by now" 
    
    1690
    +  TagToEnumOp -> panic "emitPrimOp: TagToEnumOp should have been gone by now"
    
    1674 1691
     
    
    1675 1692
     -- Out of line primops.
    
    1676 1693
     -- TODO compiler need not know about these
    

  • compiler/GHC/StgToJS/Expr.hs
    ... ... @@ -307,9 +307,9 @@ genBody :: HasDebugCallStack
    307 307
              -> StgReg
    
    308 308
              -> [Id]
    
    309 309
              -> CgStgExpr
    
    310
    -         -> Type
    
    310
    +         -> StgKind
    
    311 311
              -> G JStgStat
    
    312
    -genBody ctx startReg args e typ = do
    
    312
    +genBody ctx startReg args e kind = do
    
    313 313
       -- load arguments into local variables
    
    314 314
       la <- do
    
    315 315
         args' <- concatMapM genIdArgI args
    
    ... ... @@ -320,7 +320,7 @@ genBody ctx startReg args e typ = do
    320 320
     
    
    321 321
       -- compute PrimReps and their number of slots required to return the result of
    
    322 322
       -- i applied to args.
    
    323
    -  let res_vars = resultSize typ
    
    323
    +  let res_vars = resultSize kind
    
    324 324
     
    
    325 325
       -- compute typed expressions for each slot and assign registers
    
    326 326
       let go_var regs = \case
    
    ... ... @@ -338,6 +338,12 @@ genBody ctx startReg args e typ = do
    338 338
     
    
    339 339
       return $ la <> lav <> e <> returnStack
    
    340 340
     
    
    341
    +-- TODO: move to a proper place
    
    342
    +stgKindPrimRep :: StgKind -> [PrimRep]
    
    343
    +stgKindPrimRep (MkStgKind kind) = case kindPrimRep_maybe kind of
    
    344
    +  Just rs -> rs
    
    345
    +  r -> pprPanic "stgKindPrimRep" (ppr r)
    
    346
    +
    
    341 347
     -- | Find the result type after applying the function to the arguments
    
    342 348
     --
    
    343 349
     -- It's trickier than it looks because:
    
    ... ... @@ -361,12 +367,12 @@ genBody ctx startReg args e typ = do
    361 367
     -- In case of failure to determine the type, we default to LiftedRep as it's
    
    362 368
     -- probably what it is.
    
    363 369
     --
    
    364
    -resultSize :: HasDebugCallStack => Type -> [(PrimRep, Int)]
    
    365
    -resultSize ty = result
    
    370
    +resultSize :: HasDebugCallStack => StgKind -> [(PrimRep, Int)]
    
    371
    +resultSize kind = result
    
    366 372
       where
    
    367 373
         result       = result_reps `zip` result_slots
    
    368 374
         result_slots = fmap (slotCount . primRepSize) result_reps
    
    369
    -    result_reps  = typePrimRep ty
    
    375
    +    result_reps  = stgKindPrimRep kind
    
    370 376
     
    
    371 377
     -- | Ensure that the set of identifiers has valid 'RuntimeRep's. This function
    
    372 378
     -- returns a no-op when 'csRuntimeAssert' in 'StgToJSConfig' is False.
    
    ... ... @@ -1121,6 +1127,8 @@ genPrimOp ctx op args = do
    1121 1127
     
    
    1122 1128
     genTagToEnumOp :: ExprCtx -> TyCon -> StgArg -> State.StateT GenState IO (JStgStat, ExprResult)
    
    1123 1129
     genTagToEnumOp ctx tyc arg = do
    
    1124
    -  [tag] <- genArg arg
    
    1125
    -  let [v] = concatMap typex_expr $ ctxTarget ctx
    
    1126
    -  pure (v |= if tyc == boolTyCon then IfExpr tag true_ false_ else app hdTagToEnum [tag], ExprInline)
    \ No newline at end of file
    1130
    +  tags <- genArg arg
    
    1131
    +  case (tags, concatMap typex_expr $ ctxTarget ctx) of
    
    1132
    +    ([tag], [v]) ->
    
    1133
    +      pure (v |= if tyc == boolTyCon then IfExpr tag true_ false_ else app hdTagToEnum [tag], ExprInline)
    
    1134
    +    _ -> pprPanic "genTagToEnumOp: should be applied to exactly one argument and have one result" (ppr ctx <+> ppr tyc <+> ppr arg)
    \ No newline at end of file