diff options
author | Ben Gamari <ben@smart-cactus.org> | 2022-10-13 18:17:13 -0400 |
---|---|---|
committer | Ben Gamari <ben@smart-cactus.org> | 2022-10-19 10:06:10 -0400 |
commit | 6148bd126c4602d011e7dd458288c02db1c16dc6 (patch) | |
tree | 0cebae532fef06af2374485530549273cee14bac /compiler/GHC/Core/TyCon.hs | |
parent | 1ef412dde750d4ffd01a332e555ed4503d4eda85 (diff) | |
download | haskell-wip/T22291.tar.gz |
codeGen: Allow levity-polymorphic primop resultswip/T22291
Consider a program such as:
```haskell
foo :: forall (lev :: Levity) (a :: TYPE (BoxedRep lev)). Addr# -> (# a #)
foo x = addrToAny# x
```
While this program is accepted by the type-checker, the code generator would previously
choke on it due the levity polymorphism of `foo`'s result. Specifically,
`boxedRepDataCon` would fail as it was unable to determine the result's `PrimRep`
while trying to identify its Cmm type:
```
<no location info>: error:
panic! (the 'impossible' happened)
GHC version 9.5.20220906:
boxedRepDataCon
[lev_ayH]
Call stack:
CallStack (from HasCallStack):
callStackDoc, called at compiler/GHC/Utils/Panic.hs:188:37 in ghc:GHC.Utils.Panic
pprPanic, called at compiler/GHC/Builtin/Types.hs:1629:9 in ghc:GHC.Builtin.Types
prim_rep_fun, called at compiler/GHC/Builtin/Types.hs:1618:44 in ghc:GHC.Builtin.Types
fun, called at compiler/GHC/Types/RepType.hs:615:5 in ghc:GHC.Types.RepType
runtimeRepPrimRep, called at compiler/GHC/Builtin/Types.hs:1660:20 in ghc:GHC.Builtin.Types
prim_rep_fun, called at compiler/GHC/Builtin/Types.hs:1655:64 in ghc:GHC.Builtin.Types
fun, called at compiler/GHC/Types/RepType.hs:615:5 in ghc:GHC.Types.RepType
runtimeRepPrimRep, called at compiler/GHC/Types/RepType.hs:585:5 in ghc:GHC.Types.RepType
kindPrimRep, called at compiler/GHC/Types/RepType.hs:537:18 in ghc:GHC.Types.RepType
typePrimRep, called at compiler/GHC/StgToCmm/Utils.hs:305:58 in ghc:GHC.StgToCmm.Utils
newUnboxedTupleRegs, called at compiler/GHC/StgToCmm/Prim.hs:1701:33 in ghc:GHC.StgToCmm.Prim
```
Here we fix this by modifying `PrimRep` to reflect the fact that we may
know that a value is boxed without knowing its particular levity:
```haskell
data PrimRep = BoxedRep Levity | IntRep | ...
```
This allows `kindPrimRep (TYPE (BoxedRep lev))` to return
`BoxedRep _|_`, which is enough information for the code generator to
compile `foo`.
Fixes #22291.
Diffstat (limited to 'compiler/GHC/Core/TyCon.hs')
-rw-r--r-- | compiler/GHC/Core/TyCon.hs | 21 |
1 files changed, 9 insertions, 12 deletions
diff --git a/compiler/GHC/Core/TyCon.hs b/compiler/GHC/Core/TyCon.hs index 5ae1e2bf6b..75eeafcb00 100644 --- a/compiler/GHC/Core/TyCon.hs +++ b/compiler/GHC/Core/TyCon.hs @@ -1629,8 +1629,7 @@ See Note [RuntimeRep and PrimRep] in GHC.Types.RepType. -- "GHC.Types.RepType" and Note [VoidRep] in "GHC.Types.RepType". data PrimRep = VoidRep - | LiftedRep - | UnliftedRep -- ^ Unlifted pointer + | BoxedRep Levity | Int8Rep -- ^ Signed, 8-bit value | Int16Rep -- ^ Signed, 16-bit value | Int32Rep -- ^ Signed, 32-bit value @@ -1668,8 +1667,8 @@ instance Outputable PrimElemRep where instance Binary PrimRep where put_ bh VoidRep = putByte bh 0 - put_ bh LiftedRep = putByte bh 1 - put_ bh UnliftedRep = putByte bh 2 + put_ bh (BoxedRep Lifted) = putByte bh 1 + put_ bh (BoxedRep Unlifted) = putByte bh 2 put_ bh Int8Rep = putByte bh 3 put_ bh Int16Rep = putByte bh 4 put_ bh Int32Rep = putByte bh 5 @@ -1688,8 +1687,8 @@ instance Binary PrimRep where h <- getByte bh case h of 0 -> pure VoidRep - 1 -> pure LiftedRep - 2 -> pure UnliftedRep + 1 -> pure (BoxedRep Lifted) + 2 -> pure (BoxedRep Unlifted) 3 -> pure Int8Rep 4 -> pure Int16Rep 5 -> pure Int32Rep @@ -1715,9 +1714,8 @@ isVoidRep VoidRep = True isVoidRep _other = False isGcPtrRep :: PrimRep -> Bool -isGcPtrRep LiftedRep = True -isGcPtrRep UnliftedRep = True -isGcPtrRep _ = False +isGcPtrRep (BoxedRep _) = True +isGcPtrRep _ = False -- A PrimRep is compatible with another iff one can be coerced to the other. -- See Note [Bad unsafe coercion] in GHC.Core.Lint for when are two types coercible. @@ -1758,10 +1756,9 @@ primRepSizeB platform = \case FloatRep -> fLOAT_SIZE DoubleRep -> dOUBLE_SIZE AddrRep -> platformWordSizeInBytes platform - LiftedRep -> platformWordSizeInBytes platform - UnliftedRep -> platformWordSizeInBytes platform + BoxedRep _ -> platformWordSizeInBytes platform VoidRep -> 0 - (VecRep len rep) -> len * primElemRepSizeB platform rep + VecRep len rep -> len * primElemRepSizeB platform rep primElemRepSizeB :: Platform -> PrimElemRep -> Int primElemRepSizeB platform = primRepSizeB platform . primElemRepToPrimRep |