[Git][ghc/ghc][wip/T19520] Remove VoidRep from PrimRep, introduce PrimOrVoidRep
Krzysztof Gogolewski (@monoidal)
gitlab at gitlab.haskell.org
Fri Jan 5 14:23:05 UTC 2024
Krzysztof Gogolewski pushed to branch wip/T19520 at Glasgow Haskell Compiler / GHC
Commits:
fcb0a1de by Krzysztof Gogolewski at 2024-01-05T15:22:42+01:00
Remove VoidRep from PrimRep, introduce PrimOrVoidRep
This introduces
data PrimOrVoidRep = VoidRep | NVRep PrimRep
changes typePrimRep1 to return PrimOrVoidRep, and adds a new function
typePrimRepU to be used when the argument is definitely non-void.
Details in Note [VoidRep] in GHC.Types.RepType.
Fixes #19520
- - - - -
25 changed files:
- compiler/GHC/Builtin/PrimOps.hs
- compiler/GHC/ByteCode/InfoTable.hs
- compiler/GHC/Cmm/Utils.hs
- compiler/GHC/Core/TyCon.hs
- compiler/GHC/HsToCore/Foreign/Utils.hs
- compiler/GHC/Stg/Lift/Analysis.hs
- compiler/GHC/Stg/Lint.hs
- compiler/GHC/Stg/Syntax.hs
- compiler/GHC/Stg/Unarise.hs
- compiler/GHC/StgToByteCode.hs
- compiler/GHC/StgToCmm.hs
- compiler/GHC/StgToCmm/ArgRep.hs
- compiler/GHC/StgToCmm/Bind.hs
- compiler/GHC/StgToCmm/Closure.hs
- compiler/GHC/StgToCmm/Env.hs
- compiler/GHC/StgToCmm/Expr.hs
- compiler/GHC/StgToCmm/Layout.hs
- compiler/GHC/StgToCmm/Lit.hs
- compiler/GHC/StgToCmm/Prim.hs
- compiler/GHC/StgToCmm/Ticky.hs
- compiler/GHC/StgToJS/Arg.hs
- compiler/GHC/StgToJS/Expr.hs
- compiler/GHC/StgToJS/Utils.hs
- compiler/GHC/Types/Id/Make.hs
- compiler/GHC/Types/RepType.hs
Changes:
=====================================
compiler/GHC/Builtin/PrimOps.hs
=====================================
@@ -44,7 +44,7 @@ import GHC.Types.Demand
import GHC.Types.Id
import GHC.Types.Id.Info
import GHC.Types.Name
-import GHC.Types.RepType ( tyConPrimRep1 )
+import GHC.Types.RepType ( tyConPrimRep )
import GHC.Types.Basic
import GHC.Types.Fixity ( Fixity(..), FixityDirection(..) )
import GHC.Types.SrcLoc ( wiredInSrcSpan )
@@ -857,7 +857,8 @@ primOpSig op
GenPrimOp _occ tyvars arg_tys res_ty -> (tyvars, arg_tys, res_ty )
data PrimOpResultInfo
- = ReturnsPrim PrimRep
+ = ReturnsVoid
+ | ReturnsPrim PrimRep
| ReturnsTuple
-- Some PrimOps need not return a manifest primitive or algebraic value
@@ -867,8 +868,11 @@ data PrimOpResultInfo
getPrimOpResultInfo :: PrimOp -> PrimOpResultInfo
getPrimOpResultInfo op
= case (primOpInfo op) of
- Compare _ _ -> ReturnsPrim (tyConPrimRep1 intPrimTyCon)
- GenPrimOp _ _ _ ty | isPrimTyCon tc -> ReturnsPrim (tyConPrimRep1 tc)
+ Compare _ _ -> ReturnsPrim IntRep
+ GenPrimOp _ _ _ ty | isPrimTyCon tc -> case tyConPrimRep tc of
+ [] -> ReturnsVoid
+ [rep] -> ReturnsPrim rep
+ _ -> pprPanic "getPrimOpResultInfo" (ppr op)
| isUnboxedTupleTyCon tc -> ReturnsTuple
| otherwise -> pprPanic "getPrimOpResultInfo" (ppr op)
where
=====================================
compiler/GHC/ByteCode/InfoTable.hs
=====================================
@@ -25,7 +25,7 @@ import GHC.Core.TyCon ( TyCon, tyConFamilySize, isDataTyCon, tyConDataCons
import GHC.Core.Multiplicity ( scaledThing )
import GHC.StgToCmm.Layout ( mkVirtConstrSizes )
-import GHC.StgToCmm.Closure ( tagForCon, NonVoid (..) )
+import GHC.StgToCmm.Closure ( tagForCon )
import GHC.Utils.Misc
import GHC.Utils.Panic
@@ -61,7 +61,7 @@ make_constr_itbls interp profile cons =
where
mk_itbl :: DataCon -> Int -> IO (Name,ItblPtr)
mk_itbl dcon conNo = do
- let rep_args = [ NonVoid prim_rep
+ let rep_args = [ prim_rep
| arg <- dataConRepArgTys dcon
, prim_rep <- typePrimRep (scaledThing arg) ]
=====================================
compiler/GHC/Cmm/Utils.hs
=====================================
@@ -70,7 +70,7 @@ module GHC.Cmm.Utils(
import GHC.Prelude
import GHC.Core.TyCon ( PrimRep(..), PrimElemRep(..) )
-import GHC.Types.RepType ( UnaryType, SlotTy (..), typePrimRep1 )
+import GHC.Types.RepType ( NvUnaryType, SlotTy (..), typePrimRepU )
import GHC.Platform
import GHC.Runtime.Heap.Layout
@@ -97,7 +97,6 @@ import GHC.Cmm.Dataflow.Collections
primRepCmmType :: Platform -> PrimRep -> CmmType
primRepCmmType platform = \case
- VoidRep -> panic "primRepCmmType:VoidRep"
BoxedRep _ -> gcWord platform
IntRep -> bWord platform
WordRep -> bWord platform
@@ -136,11 +135,10 @@ primElemRepCmmType Word64ElemRep = b64
primElemRepCmmType FloatElemRep = f32
primElemRepCmmType DoubleElemRep = f64
-typeCmmType :: Platform -> UnaryType -> CmmType
-typeCmmType platform ty = primRepCmmType platform (typePrimRep1 ty)
+typeCmmType :: Platform -> NvUnaryType -> CmmType
+typeCmmType platform ty = primRepCmmType platform (typePrimRepU ty)
primRepForeignHint :: PrimRep -> ForeignHint
-primRepForeignHint VoidRep = panic "primRepForeignHint:VoidRep"
primRepForeignHint (BoxedRep _) = AddrHint
primRepForeignHint IntRep = SignedHint
primRepForeignHint Int8Rep = SignedHint
@@ -157,8 +155,8 @@ primRepForeignHint FloatRep = NoHint
primRepForeignHint DoubleRep = NoHint
primRepForeignHint (VecRep {}) = NoHint
-typeForeignHint :: UnaryType -> ForeignHint
-typeForeignHint = primRepForeignHint . typePrimRep1
+typeForeignHint :: NvUnaryType -> ForeignHint
+typeForeignHint = primRepForeignHint . typePrimRepU
---------------------------------------------------
--
=====================================
compiler/GHC/Core/TyCon.hs
=====================================
@@ -126,8 +126,9 @@ module GHC.Core.TyCon(
-- * Primitive representations of Types
PrimRep(..), PrimElemRep(..), Levity(..),
+ PrimOrVoidRep(..),
primElemRepToPrimRep,
- isVoidRep, isGcPtrRep,
+ isGcPtrRep,
primRepSizeB, primRepSizeW64_B,
primElemRepSizeB, primElemRepSizeW64_B,
primRepIsFloat,
@@ -1532,17 +1533,18 @@ See Note [RuntimeRep and PrimRep] in GHC.Types.RepType.
-}
--- | A 'PrimRep' is an abstraction of a type. It contains information that
--- the code generator needs in order to pass arguments, return results,
+-- | A 'PrimRep' is an abstraction of a /non-void/ type.
+-- (Use 'PrimRepOrVoidRep' if you want void types too.)
+-- It contains information that the code generator needs
+-- in order to pass arguments, return results,
-- and store values of this type. See also Note [RuntimeRep and PrimRep] in
-- "GHC.Types.RepType" and Note [VoidRep] in "GHC.Types.RepType".
data PrimRep
- = VoidRep
-- Unpacking of sum types is only supported since 9.6.1
#if MIN_VERSION_GLASGOW_HASKELL(9,6,0,0)
- | BoxedRep {-# UNPACK #-} !(Maybe Levity) -- ^ Boxed, heap value
+ = BoxedRep {-# UNPACK #-} !(Maybe Levity) -- ^ Boxed, heap value
#else
- | BoxedRep !(Maybe Levity) -- ^ Boxed, heap value
+ = BoxedRep !(Maybe Levity) -- ^ Boxed, heap value
#endif
| Int8Rep -- ^ Signed, 8-bit value
| Int16Rep -- ^ Signed, 16-bit value
@@ -1560,6 +1562,9 @@ data PrimRep
| VecRep Int PrimElemRep -- ^ A vector
deriving( Data.Data, Eq, Ord, Show )
+data PrimOrVoidRep = VoidRep | NVRep PrimRep
+ -- See Note [VoidRep] in GHC.Types.RepType
+
data PrimElemRep
= Int8ElemRep
| Int16ElemRep
@@ -1580,58 +1585,52 @@ instance Outputable PrimElemRep where
ppr r = text (show r)
instance Binary PrimRep where
- put_ bh VoidRep = putByte bh 0
put_ bh (BoxedRep ml) = case ml of
-- cheaper storage of the levity than using
-- the Binary (Maybe Levity) instance
- Nothing -> putByte bh 1
- Just Lifted -> putByte bh 2
- Just Unlifted -> putByte bh 3
- put_ bh Int8Rep = putByte bh 4
- put_ bh Int16Rep = putByte bh 5
- put_ bh Int32Rep = putByte bh 6
- put_ bh Int64Rep = putByte bh 7
- put_ bh IntRep = putByte bh 8
- put_ bh Word8Rep = putByte bh 9
- put_ bh Word16Rep = putByte bh 10
- put_ bh Word32Rep = putByte bh 11
- put_ bh Word64Rep = putByte bh 12
- put_ bh WordRep = putByte bh 13
- put_ bh AddrRep = putByte bh 14
- put_ bh FloatRep = putByte bh 15
- put_ bh DoubleRep = putByte bh 16
- put_ bh (VecRep n per) = putByte bh 17 *> put_ bh n *> put_ bh per
+ Nothing -> putByte bh 0
+ Just Lifted -> putByte bh 1
+ Just Unlifted -> putByte bh 2
+ put_ bh Int8Rep = putByte bh 3
+ put_ bh Int16Rep = putByte bh 4
+ put_ bh Int32Rep = putByte bh 5
+ put_ bh Int64Rep = putByte bh 6
+ put_ bh IntRep = putByte bh 7
+ put_ bh Word8Rep = putByte bh 8
+ put_ bh Word16Rep = putByte bh 9
+ put_ bh Word32Rep = putByte bh 10
+ put_ bh Word64Rep = putByte bh 11
+ put_ bh WordRep = putByte bh 12
+ put_ bh AddrRep = putByte bh 13
+ put_ bh FloatRep = putByte bh 14
+ put_ bh DoubleRep = putByte bh 15
+ put_ bh (VecRep n per) = putByte bh 16 *> put_ bh n *> put_ bh per
get bh = do
h <- getByte bh
case h of
- 0 -> pure VoidRep
- 1 -> pure $ BoxedRep Nothing
- 2 -> pure $ BoxedRep (Just Lifted)
- 3 -> pure $ BoxedRep (Just Unlifted)
- 4 -> pure Int8Rep
- 5 -> pure Int16Rep
- 6 -> pure Int32Rep
- 7 -> pure Int64Rep
- 8 -> pure IntRep
- 9 -> pure Word8Rep
- 10 -> pure Word16Rep
- 11 -> pure Word32Rep
- 12 -> pure Word64Rep
- 13 -> pure WordRep
- 14 -> pure AddrRep
- 15 -> pure FloatRep
- 16 -> pure DoubleRep
- 17 -> VecRep <$> get bh <*> get bh
+ 0 -> pure $ BoxedRep Nothing
+ 1 -> pure $ BoxedRep (Just Lifted)
+ 2 -> pure $ BoxedRep (Just Unlifted)
+ 3 -> pure Int8Rep
+ 4 -> pure Int16Rep
+ 5 -> pure Int32Rep
+ 6 -> pure Int64Rep
+ 7 -> pure IntRep
+ 8 -> pure Word8Rep
+ 9 -> pure Word16Rep
+ 10 -> pure Word32Rep
+ 11 -> pure Word64Rep
+ 12 -> pure WordRep
+ 13 -> pure AddrRep
+ 14 -> pure FloatRep
+ 15 -> pure DoubleRep
+ 16 -> VecRep <$> get bh <*> get bh
_ -> pprPanic "Binary:PrimRep" (int (fromIntegral h))
instance Binary PrimElemRep where
put_ bh per = putByte bh (fromIntegral (fromEnum per))
get bh = toEnum . fromIntegral <$> getByte bh
-isVoidRep :: PrimRep -> Bool
-isVoidRep VoidRep = True
-isVoidRep _other = False
-
isGcPtrRep :: PrimRep -> Bool
isGcPtrRep (BoxedRep _) = True
isGcPtrRep _ = False
@@ -1676,7 +1675,6 @@ primRepSizeB platform = \case
DoubleRep -> dOUBLE_SIZE
AddrRep -> platformWordSizeInBytes platform
BoxedRep _ -> platformWordSizeInBytes platform
- VoidRep -> 0
(VecRep len rep) -> len * primElemRepSizeB platform rep
-- | Like primRepSizeB but assumes pointers/words are 8 words wide.
@@ -1699,7 +1697,6 @@ primRepSizeW64_B = \case
DoubleRep -> dOUBLE_SIZE
AddrRep -> 8
BoxedRep{} -> 8
- VoidRep -> 0
(VecRep len rep) -> len * primElemRepSizeW64_B rep
primElemRepSizeB :: Platform -> PrimElemRep -> Int
=====================================
compiler/GHC/HsToCore/Foreign/Utils.hs
=====================================
@@ -57,7 +57,7 @@ primTyDescChar :: Platform -> Type -> Char
primTyDescChar !platform ty
| ty `eqType` unitTy = 'v'
| otherwise
- = case typePrimRep1 (getPrimTyOf ty) of
+ = case typePrimRepU (getPrimTyOf ty) of
IntRep -> signed_word
WordRep -> unsigned_word
Int8Rep -> 'B'
=====================================
compiler/GHC/Stg/Lift/Analysis.hs
=====================================
@@ -418,7 +418,7 @@ closureSize profile ids = words + pc_STD_HDR_SIZE (platformConstants (profilePla
-- | The number of words a single 'Id' adds to a closure's size.
-- Note that this can't handle unboxed tuples (which may still be present in
-- let-no-escapes, even after Unarise), in which case
--- @'GHC.StgToCmm.Closure.idPrimRep'@ will crash.
+-- @'GHC.StgToCmm.ArgRep.idArgRep'@ will crash.
idClosureFootprint:: Platform -> Id -> WordOff
idClosureFootprint platform
= StgToCmm.ArgRep.argRepSizeW platform
=====================================
compiler/GHC/Stg/Lint.hs
=====================================
@@ -382,8 +382,6 @@ lintStgAppReps fun args = do
= match_args actual_reps_left expected_reps_left
-- Check for void rep (empty list)
- -- Note typePrimRep_maybe will never return a result containing VoidRep.
- -- We should refactor to make this obvious from the types.
| isVoidRep actual_rep && isVoidRep expected_rep
= match_args actual_reps_left expected_reps_left
=====================================
compiler/GHC/Stg/Syntax.hs
=====================================
@@ -58,6 +58,7 @@ module GHC.Stg.Syntax (
stgArgType,
stgArgRep,
stgArgRep1,
+ stgArgRepU,
stgArgRep_maybe,
stgCaseBndrInScope,
@@ -80,7 +81,7 @@ import GHC.Types.CostCentre ( CostCentreStack )
import GHC.Core ( AltCon )
import GHC.Core.DataCon
-import GHC.Core.TyCon ( PrimRep(..), TyCon )
+import GHC.Core.TyCon ( PrimRep(..), PrimOrVoidRep(..), TyCon )
import GHC.Core.Type ( Type )
import GHC.Core.Ppr( {- instances -} )
@@ -90,7 +91,7 @@ import GHC.Types.Name ( isDynLinkName )
import GHC.Types.Tickish ( StgTickish )
import GHC.Types.Var.Set
import GHC.Types.Literal ( Literal, literalType )
-import GHC.Types.RepType ( typePrimRep1, typePrimRep, typePrimRep_maybe )
+import GHC.Types.RepType ( typePrimRep, typePrimRep1, typePrimRepU, typePrimRep_maybe )
import GHC.Unit.Module ( Module )
import GHC.Utils.Outputable
@@ -177,10 +178,10 @@ isDllConApp platform ext_dyn_refs this_mod con args
-- $WT1 = T1 Int (Coercion (Refl Int))
--
-- The coercion argument here gets VoidRep
-isAddrRep :: PrimRep -> Bool
-isAddrRep AddrRep = True
-isAddrRep (BoxedRep _) = True -- FIXME: not true for JavaScript
-isAddrRep _ = False
+isAddrRep :: PrimOrVoidRep -> Bool
+isAddrRep (NVRep AddrRep) = True
+isAddrRep (NVRep (BoxedRep _)) = True -- FIXME: not true for JavaScript
+isAddrRep _ = False
-- | Type of an @StgArg@
--
@@ -199,11 +200,17 @@ stgArgRep ty = typePrimRep (stgArgType ty)
stgArgRep_maybe :: StgArg -> Maybe [PrimRep]
stgArgRep_maybe ty = typePrimRep_maybe (stgArgType ty)
--- | Assumes that the argument has one PrimRep, which holds after unarisation.
+-- | Assumes that the argument has at most one PrimRep, which holds after unarisation.
-- See Note [Post-unarisation invariants] in GHC.Stg.Unarise.
-stgArgRep1 :: StgArg -> PrimRep
+-- See Note [VoidRep] in GHC.Types.RepType.
+stgArgRep1 :: StgArg -> PrimOrVoidRep
stgArgRep1 ty = typePrimRep1 (stgArgType ty)
+-- | Assumes that the argument has exactly one PrimRep.
+-- See Note [VoidRep] in GHC.Types.RepType.
+stgArgRepU :: StgArg -> PrimRep
+stgArgRepU ty = typePrimRepU (stgArgType ty)
+
-- | Given an alt type and whether the program is unarised, return whether the
-- case binder is in scope.
--
=====================================
compiler/GHC/Stg/Unarise.hs
=====================================
@@ -373,6 +373,7 @@ STG programs after unarisation have these invariants:
2. No unboxed tuple binders. Tuples only appear in return position.
3. Binders and literals always have zero (for void arguments) or one PrimRep.
+ (i.e. typePrimRep1 won't crash; see Note [VoidRep] in GHC.Types.RepType.)
4. DataCon applications (StgRhsCon and StgConApp) don't have void arguments.
This means that it's safe to wrap `StgArg`s of DataCon applications with
@@ -607,13 +608,12 @@ unariseUbxSumOrTupleArgs rho us dc args ty_args
-- See also Note [Rubbish literals] in GHC.Types.Literal.
unariseLiteral_maybe :: Literal -> Maybe [OutStgArg]
unariseLiteral_maybe (LitRubbish torc rep)
- | [prep] <- preps
- , assert (not (isVoidRep prep)) True
- = Nothing -- Single, non-void PrimRep. Nothing to do!
+ | [_] <- preps
+ = Nothing -- Single PrimRep. Nothing to do!
- | otherwise -- Multiple reps, possibly with VoidRep. Eliminate via elimCase
+ | otherwise -- Multiple reps, or zero. Eliminate via elimCase
= Just [ StgLitArg (LitRubbish torc (primRepToRuntimeRep prep))
- | prep <- preps, assert (not (isVoidRep prep)) True ]
+ | prep <- preps ]
where
preps = runtimeRepPrimRep (text "unariseLiteral_maybe") rep
@@ -814,7 +814,7 @@ mapSumIdBinders alt_bndr args rhs rho0
mkCastInput :: (Id,PrimRep,UniqSupply) -> ([(PrimOp,Type,Unique)],Id,Id)
mkCastInput (id,rep,bndr_us) =
- let (ops,types) = unzip $ getCasts (typePrimRep1 $ idType id) rep
+ let (ops,types) = unzip $ getCasts (typePrimRepU $ idType id) rep
cst_opts = zip3 ops types $ uniqsFromSupply bndr_us
out_id = case cst_opts of
[] -> id
@@ -860,7 +860,7 @@ mkCastVar uq ty = mkSysLocal (fsLit "cst_sum") uq ManyTy ty
mkCast :: StgArg -> PrimOp -> OutId -> Type -> StgExpr -> StgExpr
mkCast arg_in cast_op out_id out_ty in_rhs =
- let r2 = typePrimRep1 out_ty
+ let r2 = typePrimRepU out_ty
scrut = StgOpApp (StgPrimOp cast_op) [arg_in] out_ty
alt = GenStgAlt { alt_con = DEFAULT, alt_bndrs = [], alt_rhs = in_rhs}
alt_ty = PrimAlt r2
@@ -922,8 +922,8 @@ mkUbxSum dc ty_args args0 us
castArg :: UniqSupply -> SlotTy -> StgArg -> Maybe (StgArg,UniqSupply,StgExpr -> StgExpr)
castArg us slot_ty arg
-- Cast the argument to the type of the slot if required
- | slotPrimRep slot_ty /= stgArgRep1 arg
- , (ops,types) <- unzip $ getCasts (stgArgRep1 arg) $ slotPrimRep slot_ty
+ | slotPrimRep slot_ty /= stgArgRepU arg
+ , (ops,types) <- unzip $ getCasts (stgArgRepU arg) $ slotPrimRep slot_ty
, not . null $ ops
= let (us1,us2) = splitUniqSupply us
cast_uqs = uniqsFromSupply us1
=====================================
compiler/GHC/StgToByteCode.hs
=====================================
@@ -57,7 +57,7 @@ import GHC.Builtin.Uniques
import GHC.Data.FastString
import GHC.Utils.Panic
import GHC.Utils.Exception (evaluate)
-import GHC.StgToCmm.Closure ( NonVoid(..), fromNonVoid, idPrimRep,
+import GHC.StgToCmm.Closure ( NonVoid(..), fromNonVoid, idPrimRepU,
addIdReps, addArgReps,
nonVoidIds, nonVoidStgArgs )
import GHC.StgToCmm.Layout
@@ -529,7 +529,7 @@ returnUnboxedTuple
returnUnboxedTuple d s p es = do
profile <- getProfile
let platform = profilePlatform profile
- arg_ty e = primRepCmmType platform (stgArgRep1 e)
+ arg_ty e = primRepCmmType platform (stgArgRepU e)
(call_info, tuple_components) = layoutNativeCall profile
NativeTupleReturn
d
@@ -540,12 +540,14 @@ returnUnboxedTuple d s p es = do
massert (off == dd + szb)
go (dd + szb) (push:pushes) cs
pushes <- go d [] tuple_components
- let non_void VoidRep = False
- non_void _ = True
+ let rep_to_maybe :: PrimOrVoidRep -> Maybe PrimRep
+ rep_to_maybe VoidRep = Nothing
+ rep_to_maybe (NVRep rep) = Just rep
+
ret <- returnUnliftedReps d
s
(wordsToBytes platform $ nativeCallSize call_info)
- (filter non_void $ map stgArgRep1 es)
+ (mapMaybe (rep_to_maybe . stgArgRep1) es)
return (mconcat pushes `appOL` ret)
-- Compile code to apply the given expression to the remaining args
@@ -928,7 +930,7 @@ doCase d s p scrut bndr alts
rhs_code <- schemeE d_alts s p_alts rhs
return (my_discr alt, rhs_code)
| isUnboxedTupleType bndr_ty || isUnboxedSumType bndr_ty =
- let bndr_ty = primRepCmmType platform . idPrimRep
+ let bndr_ty = primRepCmmType platform . idPrimRepU
tuple_start = d_bndr
(call_info, args_offsets) =
layoutNativeCall profile
@@ -944,7 +946,7 @@ doCase d s p scrut bndr alts
wordsToBytes platform (nativeCallSize call_info) +
offset)
| (arg, offset) <- args_offsets
- , not (isVoidRep $ idPrimRep arg)]
+ , not (isZeroBitTy $ idType arg)]
p_alts
in do
rhs_code <- schemeE stack_bot s p' rhs
@@ -1378,10 +1380,10 @@ generatePrimCall d s p target _mb_unit _result_ty args
layoutNativeCall profile
NativePrimCall
0
- (primRepCmmType platform . stgArgRep1)
+ (primRepCmmType platform . stgArgRepU)
nv_args
- prim_args_offsets = mapFst stgArgRep1 args_offsets
+ prim_args_offsets = mapFst stgArgRepU args_offsets
shifted_args_offsets = mapSnd (+ d) args_offsets
push_target = PUSH_UBX (LitLabel target Nothing IsFunction) 1
@@ -1457,7 +1459,7 @@ generateCCall d0 s p (CCallSpec target cconv safety) result_ty args
-- ArgRep of what was actually pushed.
pargs
- :: ByteOff -> [StgArg] -> BcM [(BCInstrList, PrimRep)]
+ :: ByteOff -> [StgArg] -> BcM [(BCInstrList, PrimOrVoidRep)]
pargs _ [] = return []
pargs d (aa@(StgVarArg a):az)
| Just t <- tyConAppTyCon_maybe (idType a)
@@ -1470,7 +1472,7 @@ generateCCall d0 s p (CCallSpec target cconv safety) result_ty args
-- The ptr points at the header. Advance it over the
-- header and then pretend this is an Addr#.
let code = push_fo `snocOL` SWIZZLE 0 (fromIntegral hdr_sz)
- return ((code, AddrRep) : rest)
+ return ((code, NVRep AddrRep) : rest)
pargs d (aa:az) = do (code_a, sz_a) <- pushAtom d p aa
rest <- pargs (d + sz_a) az
return ((code_a, stgArgRep1 aa) : rest)
@@ -1483,8 +1485,7 @@ generateCCall d0 s p (CCallSpec target cconv safety) result_ty args
push_args = concatOL pushs_arg
!d_after_args = d0 + wordsToBytes platform a_reps_sizeW
a_reps_pushed_RAW
- | x:xs <- a_reps_pushed_r_to_l
- , isVoidRep x
+ | VoidRep:xs <- a_reps_pushed_r_to_l
= reverse xs
| otherwise
= panic "GHC.StgToByteCode.generateCCall: missing or invalid World token?"
@@ -1494,10 +1495,7 @@ generateCCall d0 s p (CCallSpec target cconv safety) result_ty args
-- d_after_args is the stack depth once the args are on.
-- Get the result rep.
- (returns_void, r_rep)
- = case maybe_getCCallReturnRep result_ty of
- Nothing -> (True, VoidRep)
- Just rr -> (False, rr)
+ r_rep = maybe_getCCallReturnRep result_ty
{-
Because the Haskell stack grows down, the a_reps refer to
lowest to highest addresses in that order. The args for the call
@@ -1570,10 +1568,9 @@ generateCCall d0 s p (CCallSpec target cconv safety) result_ty args
-- this is a V (tag).
r_sizeW = repSizeWords platform r_rep
d_after_r = d_after_Addr + wordsToBytes platform r_sizeW
- push_r =
- if returns_void
- then nilOL
- else unitOL (PUSH_UBX (mkDummyLiteral platform r_rep) (r_sizeW))
+ push_r = case r_rep of
+ VoidRep -> nilOL
+ NVRep r -> unitOL (PUSH_UBX (mkDummyLiteral platform r) r_sizeW)
-- generate the marshalling code we're going to call
@@ -1611,17 +1608,17 @@ generateCCall d0 s p (CCallSpec target cconv safety) result_ty args
-- slide and return
d_after_r_min_s = bytesToWords platform (d_after_r - s)
wrapup = mkSlideW r_sizeW (d_after_r_min_s - r_sizeW)
- `snocOL` RETURN (toArgRep platform r_rep)
+ `snocOL` RETURN (toArgRepOrV platform r_rep)
--trace (show (arg1_offW, args_offW , (map argRepSizeW a_reps) )) $
return (
push_args `appOL`
push_Addr `appOL` push_r `appOL` do_call `appOL` wrapup
)
-primRepToFFIType :: Platform -> PrimRep -> FFIType
-primRepToFFIType platform r
+primRepToFFIType :: Platform -> PrimOrVoidRep -> FFIType
+primRepToFFIType _ VoidRep = FFIVoid
+primRepToFFIType platform (NVRep r)
= case r of
- VoidRep -> FFIVoid
IntRep -> signed_word
WordRep -> unsigned_word
Int8Rep -> FFISInt8
@@ -1668,7 +1665,7 @@ mkDummyLiteral platform pr
-- GHC.Prim.Char# -> GHC.Prim.State# GHC.Prim.RealWorld
-- -> (# GHC.Prim.State# GHC.Prim.RealWorld, GHC.Prim.Int# #)
--
--- to Just IntRep
+-- to NVRep IntRep
-- and check that an unboxed pair is returned wherein the first arg is V'd.
--
-- Alternatively, for call-targets returning nothing, convert
@@ -1676,16 +1673,16 @@ mkDummyLiteral platform pr
-- GHC.Prim.Char# -> GHC.Prim.State# GHC.Prim.RealWorld
-- -> (# GHC.Prim.State# GHC.Prim.RealWorld #)
--
--- to Nothing
+-- to VoidRep
-maybe_getCCallReturnRep :: Type -> Maybe PrimRep
+maybe_getCCallReturnRep :: Type -> PrimOrVoidRep
maybe_getCCallReturnRep fn_ty
= let
(_a_tys, r_ty) = splitFunTys (dropForAlls fn_ty)
in
case typePrimRep r_ty of
- [] -> Nothing
- [rep] -> Just rep
+ [] -> VoidRep
+ [rep] -> NVRep rep
-- if it was, it would be impossible to create a
-- valid return value placeholder on the stack
@@ -2131,10 +2128,10 @@ idSizeCon platform var
wordsToBytes platform .
WordOff . sum . map (argRepSizeW platform . toArgRep platform) .
typePrimRep . idType $ var
- | otherwise = ByteOff (primRepSizeB platform (idPrimRep var))
+ | otherwise = ByteOff (primRepSizeB platform (idPrimRepU var))
-repSizeWords :: Platform -> PrimRep -> WordOff
-repSizeWords platform rep = WordOff $ argRepSizeW platform (toArgRep platform rep)
+repSizeWords :: Platform -> PrimOrVoidRep -> WordOff
+repSizeWords platform rep = WordOff $ argRepSizeW platform (toArgRepOrV platform rep)
isFollowableArg :: ArgRep -> Bool
isFollowableArg P = True
@@ -2171,7 +2168,7 @@ mkSlideW !n !ws
atomRep :: Platform -> StgArg -> ArgRep
-atomRep platform e = toArgRep platform (stgArgRep1 e)
+atomRep platform e = toArgRepOrV platform (stgArgRep1 e)
-- | Let szsw be the sizes in bytes of some items pushed onto the stack, which
-- has initial depth @original_depth at . Return the values which the stack
=====================================
compiler/GHC/StgToCmm.hs
=====================================
@@ -253,8 +253,8 @@ cgDataCon mn data_con
-- We're generating info tables, so we don't know and care about
-- what the actual arguments are. Using () here as the place holder.
- arg_reps :: [NonVoid PrimRep]
- arg_reps = [ NonVoid rep_ty
+ arg_reps :: [PrimRep]
+ arg_reps = [ rep_ty
| ty <- dataConRepArgTys data_con
, rep_ty <- typePrimRep (scaledThing ty)
]
=====================================
compiler/GHC/StgToCmm/ArgRep.hs
=====================================
@@ -9,7 +9,7 @@
{-# LANGUAGE LambdaCase #-}
module GHC.StgToCmm.ArgRep (
- ArgRep(..), toArgRep, argRepSizeW,
+ ArgRep(..), toArgRep, toArgRepOrV, argRepSizeW,
argRepString, isNonV, idArgRep,
@@ -20,10 +20,10 @@ module GHC.StgToCmm.ArgRep (
import GHC.Prelude
import GHC.Platform
-import GHC.StgToCmm.Closure ( idPrimRep )
+import GHC.StgToCmm.Closure ( idPrimRep1 )
import GHC.Runtime.Heap.Layout ( WordOff )
import GHC.Types.Id ( Id )
-import GHC.Core.TyCon ( PrimRep(..), primElemRepSizeB )
+import GHC.Core.TyCon ( PrimRep(..), PrimOrVoidRep(..), primElemRepSizeB )
import GHC.Types.Basic ( RepArity )
import GHC.Settings.Constants ( wORD64_SIZE, dOUBLE_SIZE )
@@ -68,7 +68,6 @@ argRepString V64 = "V64"
toArgRep :: Platform -> PrimRep -> ArgRep
toArgRep platform rep = case rep of
- VoidRep -> V
BoxedRep _ -> P
IntRep -> N
WordRep -> N
@@ -93,6 +92,10 @@ toArgRep platform rep = case rep of
64 -> V64
_ -> error "toArgRep: bad vector primrep"
+toArgRepOrV :: Platform -> PrimOrVoidRep -> ArgRep
+toArgRepOrV _ VoidRep = V
+toArgRepOrV platform (NVRep rep) = toArgRep platform rep
+
isNonV :: ArgRep -> Bool
isNonV V = False
isNonV _ = True
@@ -112,7 +115,7 @@ argRepSizeW platform = \case
ws = platformWordSizeInBytes platform
idArgRep :: Platform -> Id -> ArgRep
-idArgRep platform = toArgRep platform . idPrimRep
+idArgRep platform = toArgRepOrV platform . idPrimRep1
-- This list of argument patterns should be kept in sync with at least
-- the following:
=====================================
compiler/GHC/StgToCmm/Bind.hs
=====================================
@@ -382,7 +382,7 @@ mkRhsClosure profile use_std_ap check_tags bndr _cc
-- args are all distinct local variables
-- The "-1" is for fun_id
-- Missed opportunity: (f x x) is not detected
- , all (isGcPtrRep . idPrimRep . fromNonVoid) fvs
+ , all (isGcPtrRep . idPrimRepU . fromNonVoid) fvs
, isUpdatable upd_flag
, n_fvs <= pc_MAX_SPEC_AP_SIZE (profileConstants profile)
, not (profileIsProfiling profile)
=====================================
compiler/GHC/StgToCmm/Closure.hs
=====================================
@@ -18,7 +18,7 @@
module GHC.StgToCmm.Closure (
DynTag, tagForCon, isSmallFamily,
- idPrimRep, isVoidRep, isGcPtrRep, addIdReps, addArgReps,
+ idPrimRep1, idPrimRepU, isGcPtrRep, addIdReps, addArgReps,
NonVoid(..), fromNonVoid, nonVoidIds, nonVoidStgArgs,
assertNonVoidIds, assertNonVoidStgArgs,
@@ -176,24 +176,27 @@ assertNonVoidStgArgs args = assert (not (any (null . stgArgRep) args)) $
-- Why are these here?
--- | Assumes that there is precisely one 'PrimRep' of the type. This assumption
+-- | Assumes that there is at most one 'PrimRep' of the type. This assumption
-- holds after unarise.
-- See Note [Post-unarisation invariants] in GHC.Stg.Unarise.
-idPrimRep :: Id -> PrimRep
-idPrimRep id = typePrimRep1 (idType id)
- -- See also Note [VoidRep] in GHC.Types.RepType
+-- See Note [VoidRep] in GHC.Types.RepType.
+idPrimRep1 :: Id -> PrimOrVoidRep
+idPrimRep1 id = typePrimRep1 (idType id)
+
+idPrimRepU :: Id -> PrimRep
+idPrimRepU id = typePrimRepU (idType id)
-- | Assumes that Ids have one PrimRep, which holds after unarisation.
-- See Note [Post-unarisation invariants] in GHC.Stg.Unarise.
addIdReps :: [NonVoid Id] -> [NonVoid (PrimRep, Id)]
addIdReps = map (\id -> let id' = fromNonVoid id
- in NonVoid (idPrimRep id', id'))
+ in NonVoid (idPrimRepU id', id'))
-- | Assumes that arguments have one PrimRep, which holds after unarisation.
-- See Note [Post-unarisation invariants] in GHC.Stg.Unarise.
addArgReps :: [NonVoid StgArg] -> [NonVoid (PrimRep, StgArg)]
addArgReps = map (\arg -> let arg' = fromNonVoid arg
- in NonVoid (stgArgRep1 arg', arg'))
+ in NonVoid (stgArgRepU arg', arg'))
------------------------------------------------------
-- Building LambdaFormInfo
=====================================
compiler/GHC/StgToCmm/Env.hs
=====================================
@@ -205,4 +205,4 @@ idToReg :: Platform -> NonVoid Id -> LocalReg
-- about accidental collision
idToReg platform (NonVoid id)
= LocalReg (idUnique id)
- (primRepCmmType platform (idPrimRep id))
+ (primRepCmmType platform (idPrimRepU id))
=====================================
compiler/GHC/StgToCmm/Expr.hs
=====================================
@@ -488,7 +488,7 @@ accurate update would complexify the implementation and doesn't seem worth it.
-}
cgCase (StgApp v []) _ (PrimAlt _) alts
- | isVoidRep (idPrimRep v) -- See Note [Scrutinising VoidRep]
+ | isZeroBitTy (idType v) -- See Note [Scrutinising VoidRep]
, [GenStgAlt{alt_con=DEFAULT, alt_bndrs=_, alt_rhs=rhs}] <- alts
= cgExpr rhs
@@ -522,9 +522,9 @@ cgCase (StgApp v []) bndr alt_type@(PrimAlt _) alts
; _ <- bindArgToReg (NonVoid bndr)
; cgAlts (NoGcInAlts,AssignedDirectly) (NonVoid bndr) alt_type alts }
where
- reps_compatible platform = primRepCompatible platform (idPrimRep v) (idPrimRep bndr)
+ reps_compatible platform = primRepCompatible platform (idPrimRepU v) (idPrimRepU bndr)
- pp_bndr id = ppr id <+> dcolon <+> ppr (idType id) <+> parens (ppr (idPrimRep id))
+ pp_bndr id = ppr id <+> dcolon <+> ppr (idType id) <+> parens (ppr (idPrimRepU id))
{- Note [Dodgy unsafeCoerce 2, #3132]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
=====================================
compiler/GHC/StgToCmm/Layout.hs
=====================================
@@ -26,7 +26,7 @@ module GHC.StgToCmm.Layout (
mkVirtConstrSizes,
getHpRelOffset,
- ArgRep(..), toArgRep, idArgRep, argRepSizeW, -- re-exported from GHC.StgToCmm.ArgRep
+ ArgRep(..), toArgRep, toArgRepOrV, idArgRep, argRepSizeW, -- re-exported from GHC.StgToCmm.ArgRep
getArgAmode, getNonVoidArgAmodes
) where
@@ -50,7 +50,7 @@ import GHC.Cmm.Info
import GHC.Cmm.CLabel
import GHC.Stg.Syntax
import GHC.Types.Id
-import GHC.Core.TyCon ( PrimRep(..), primRepSizeB )
+import GHC.Core.TyCon ( PrimRep(..), PrimOrVoidRep(..), primRepSizeB )
import GHC.Types.Basic ( RepArity )
import GHC.Platform
import GHC.Platform.Profile
@@ -330,8 +330,8 @@ getArgRepsAmodes args = do
where getArgRepAmode platform arg
= case stgArgRep1 arg of
VoidRep -> return (V, Nothing)
- rep -> do expr <- getArgAmode (NonVoid arg)
- return (toArgRep platform rep, Just expr)
+ NVRep rep -> do expr <- getArgAmode (NonVoid arg)
+ return (toArgRep platform rep, Just expr)
nonVArgs :: [(ArgRep, Maybe CmmExpr)] -> [CmmExpr]
nonVArgs [] = []
@@ -438,7 +438,6 @@ mkVirtHeapOffsetsWithPadding
-- than the unboxed things
mkVirtHeapOffsetsWithPadding profile header things =
- assert (not (any (isVoidRep . fst . fromNonVoid) things))
( tot_wds
, bytesToWordsRoundUp platform bytes_of_ptrs
, concat (ptrs_w_offsets ++ non_ptrs_w_offsets) ++ final_pad
@@ -520,13 +519,13 @@ mkVirtConstrOffsets profile = mkVirtHeapOffsets profile StdHeader
-- | Just like mkVirtConstrOffsets, but used when we don't have the actual
-- arguments. Useful when e.g. generating info tables; we just need to know
-- sizes of pointer and non-pointer fields.
-mkVirtConstrSizes :: Profile -> [NonVoid PrimRep] -> (WordOff, WordOff)
+mkVirtConstrSizes :: Profile -> [PrimRep] -> (WordOff, WordOff)
mkVirtConstrSizes profile field_reps
= (tot_wds, ptr_wds)
where
(tot_wds, ptr_wds, _) =
mkVirtConstrOffsets profile
- (map (\nv_rep -> NonVoid (fromNonVoid nv_rep, ())) field_reps)
+ (map (\nv_rep -> NonVoid (nv_rep, ())) field_reps)
-------------------------------------------------------------------------
--
=====================================
compiler/GHC/StgToCmm/Lit.hs
=====================================
@@ -52,7 +52,6 @@ cgLit (LitString s) =
-- not unpackFS; we want the UTF-8 byte stream.
cgLit (LitRubbish _ rep) =
case expectOnly "cgLit" prim_reps of -- Note [Post-unarisation invariants]
- VoidRep -> panic "cgLit:VoidRep" -- ditto
BoxedRep _ -> idInfoToAmode <$> getCgIdInfo unitDataConId
AddrRep -> cgLit LitNullAddr
VecRep n elem -> do
=====================================
compiler/GHC/StgToCmm/Prim.hs
=====================================
@@ -1720,7 +1720,7 @@ emitPrimOp cfg primop =
-> PrimopCmmEmit
opIntoRegs f = PrimopCmmEmit_Internal $ \res_ty -> do
regs <- case result_info of
- ReturnsPrim VoidRep -> pure []
+ ReturnsVoid -> pure []
ReturnsPrim rep
-> do reg <- newTemp (primRepCmmType platform rep)
pure [reg]
=====================================
compiler/GHC/StgToCmm/Ticky.hs
=====================================
@@ -118,7 +118,7 @@ import GHC.Prelude
import GHC.Platform
import GHC.Platform.Profile
-import GHC.StgToCmm.ArgRep ( slowCallPattern , toArgRep , argRepString )
+import GHC.StgToCmm.ArgRep ( slowCallPattern, toArgRepOrV, argRepString )
import GHC.StgToCmm.Closure
import GHC.StgToCmm.Config
import {-# SOURCE #-} GHC.StgToCmm.Foreign ( emitPrimCall )
@@ -615,7 +615,7 @@ tickySlowCall lf_info args = do
tickySlowCallPat :: [StgArg] -> FCode ()
tickySlowCallPat args = ifTicky $ do
platform <- profilePlatform <$> getProfile
- let argReps = map (toArgRep platform . stgArgRep1) args
+ let argReps = map (toArgRepOrV platform . stgArgRep1) args
(_, n_matched) = slowCallPattern argReps
if n_matched > 0 && args `lengthIs` n_matched
then bumpTickyLbl $ mkRtsSlowFastTickyCtrLabel $ concatMap (map Data.Char.toLower . argRepString) argReps
=====================================
compiler/GHC/StgToJS/Arg.hs
=====================================
@@ -120,7 +120,7 @@ genStaticArg a = case a of
Nothing -> reg
Just expr -> unfloated expr
where
- r = primRepToJSRep $ stgArgRep1 a
+ r = primOrVoidRepToJSRep $ stgArgRep1 a
reg
| isVoid r =
return []
@@ -162,7 +162,7 @@ genArg a = case a of
where
-- if our argument is a joinid, it can be an unboxed tuple
r :: HasDebugCallStack => JSRep
- r = primRepToJSRep $ stgArgRep1 a
+ r = primOrVoidRepToJSRep $ stgArgRep1 a
unfloated :: HasDebugCallStack => CgStgExpr -> G [JStgExpr]
unfloated = \case
=====================================
compiler/GHC/StgToJS/Expr.hs
=====================================
@@ -351,7 +351,7 @@ genBody ctx startReg args e typ = do
--
-- Se we're left to use the applied arguments to peel the type (unwrapped) one
-- arg at a time. But passed args are args after unarisation so we need to
--- unarise every argument type that we peel (using typePrimRepArgs) to get the
+-- unarise every argument type that we peel (using typePrimRep) to get the
-- number of passed args consumed by each type arg.
--
-- In case of failure to determine the type, we default to LiftedRep as it's
=====================================
compiler/GHC/StgToJS/Utils.hs
=====================================
@@ -20,6 +20,7 @@ module GHC.StgToJS.Utils
, typeJSRep
, unaryTypeJSRep
, primRepToJSRep
+ , primOrVoidRepToJSRep
, stackSlotType
, primRepSize
, mkArityTag
@@ -196,10 +197,9 @@ typeJSRep t = map primRepToJSRep (typePrimRep t)
-- only use if you know it's not an unboxed tuple
unaryTypeJSRep :: HasDebugCallStack => UnaryType -> JSRep
-unaryTypeJSRep ut = primRepToJSRep (typePrimRep1 ut)
+unaryTypeJSRep ut = primOrVoidRepToJSRep (typePrimRep1 ut)
primRepToJSRep :: HasDebugCallStack => PrimRep -> JSRep
-primRepToJSRep VoidRep = VoidV
primRepToJSRep (BoxedRep _) = PtrV
primRepToJSRep IntRep = IntV
primRepToJSRep Int8Rep = IntV
@@ -216,6 +216,10 @@ primRepToJSRep FloatRep = DoubleV
primRepToJSRep DoubleRep = DoubleV
primRepToJSRep (VecRep{}) = error "primRepToJSRep: vector types are unsupported"
+primOrVoidRepToJSRep :: HasDebugCallStack => PrimOrVoidRep -> JSRep
+primOrVoidRepToJSRep VoidRep = VoidV
+primOrVoidRepToJSRep (NVRep rep) = primRepToJSRep rep
+
dataConType :: DataCon -> Type
dataConType dc = idType (dataConWrapId dc)
=====================================
compiler/GHC/Types/Id/Make.hs
=====================================
@@ -1525,7 +1525,6 @@ shouldUnpackArgTy bang_opts prag fam_envs arg_ty
-- and tells us if they can fit into 8 bytes. See Note [Unpack one-wide fields]
is_small_rep =
let -- Neccesary to look through unboxed tuples.
- -- Note typePrimRep never returns VoidRep
prim_reps = concatMap (typePrimRep . scaledThing . fst) $ rep_tys
-- And then get the actual size of the unpacked constructor.
rep_size = sum $ map primRepSizeW64_B prim_reps
=====================================
compiler/GHC/Types/RepType.hs
=====================================
@@ -11,11 +11,11 @@ module GHC.Types.RepType
isZeroBitTy,
-- * Type representation for the code generator
- typePrimRep, typePrimRep1,
- runtimeRepPrimRep, typePrimRepArgs,
+ typePrimRep, typePrimRep1, typePrimRepU,
+ runtimeRepPrimRep,
PrimRep(..), primRepToRuntimeRep, primRepToType,
countFunRepArgs, countConRepArgs, dataConRuntimeRepStrictness,
- tyConPrimRep, tyConPrimRep1,
+ tyConPrimRep,
runtimeRepPrimRep_maybe, kindPrimRep_maybe, typePrimRep_maybe,
-- * Unboxed sum representation type
@@ -38,7 +38,7 @@ import GHC.Core.TyCo.Rep
import GHC.Core.Type
import {-# SOURCE #-} GHC.Builtin.Types ( anyTypeOfKind
, vecRepDataConTyCon
- , liftedRepTy, unliftedRepTy, zeroBitRepTy
+ , liftedRepTy, unliftedRepTy
, intRepDataConTy
, int8RepDataConTy, int16RepDataConTy, int32RepDataConTy, int64RepDataConTy
, wordRepDataConTy
@@ -80,15 +80,6 @@ isNvUnaryRep :: [PrimRep] -> Bool
isNvUnaryRep [_] = True
isNvUnaryRep _ = False
--- INVARIANT: the result list is never empty.
-typePrimRepArgs :: HasDebugCallStack => Type -> NonEmpty PrimRep
-typePrimRepArgs ty
- = case reps of
- [] -> VoidRep :| []
- (x:xs) -> x :| xs
- where
- reps = typePrimRep ty
-
-- | Gets rid of the stuff that prevents us from understanding the
-- runtime representation of a type. Including:
-- 1. Casts
@@ -129,7 +120,10 @@ countFunRepArgs 0 _
= 0
countFunRepArgs n ty
| FunTy _ _ arg res <- unwrapType ty
- = length (typePrimRepArgs arg) + countFunRepArgs (n - 1) res
+ = (length (typePrimRep arg) `max` 1)
+ + countFunRepArgs (n - 1) res
+ -- If typePrimRep returns [] that means a void arg,
+ -- and we count 1 for that
| otherwise
= pprPanic "countFunRepArgs: arity greater than type can handle" (ppr (n, ty, typePrimRep ty))
@@ -308,7 +302,6 @@ repSlotTy reps = case reps of
_ -> pprPanic "repSlotTy" (ppr reps)
primRepSlot :: PrimRep -> SlotTy
-primRepSlot VoidRep = pprPanic "primRepSlot" (text "No slot for VoidRep")
primRepSlot (BoxedRep mlev) = case mlev of
Nothing -> panic "primRepSlot: levity polymorphic BoxedRep"
Just Lifted -> PtrLiftedSlot
@@ -391,8 +384,7 @@ needed and how many bits are required. The data type GHC.Core.TyCon.PrimRep
enumerates all the possibilities.
data PrimRep
- = VoidRep -- See Note [VoidRep]
- | LiftedRep -- ^ Lifted pointer
+ = LiftedRep -- ^ Lifted pointer
| UnliftedRep -- ^ Unlifted pointer
| Int8Rep -- ^ Signed, 8-bit value
| Int16Rep -- ^ Signed, 16-bit value
@@ -441,18 +433,37 @@ See also Note [Getting from RuntimeRep to PrimRep] and Note [VoidRep].
Note [VoidRep]
~~~~~~~~~~~~~~
-PrimRep contains a constructor VoidRep, while RuntimeRep does
-not. Yet representations are often characterised by a list of PrimReps,
-where a void would be denoted as []. (See also Note [RuntimeRep and PrimRep].)
+PrimRep is used to denote one primitive representation.
+Because of unboxed tuples and sums, the representation of a value
+in general is a list of PrimReps. (See also Note [RuntimeRep and PrimRep].)
+
+For example:
+ typePrimRep Int# = [IntRep]
+ typePrimRep Int = [LiftedRep]
+ typePrimRep (# Int#, Int# #) = [IntRep,IntRep]
+ typePrimRep (# #) = []
+ typePrimRep (State# s) = []
+
+After the unariser, all identifiers have at most one PrimRep
+(that is, the [PrimRep] for each identifier is empty or a singleton list).
+More precisely: typePrimRep1 will succeed (not crash) on every binder
+and argument type.
+(See Note [Post-unarisation invariants] in GHC.Stg.Unarise.)
-However, after the unariser, all identifiers have exactly one PrimRep, but
-void arguments still exist. Thus, PrimRep includes VoidRep to describe these
-binders. Perhaps post-unariser representations (which need VoidRep) should be
-a different type than pre-unariser representations (which use a list and do
-not need VoidRep), but we have what we have.
+Thus, we have
-RuntimeRep instead uses TupleRep '[] to denote a void argument. When
-converting a TupleRep '[] into a list of PrimReps, we get an empty list.
+1. typePrimRep :: Type -> [PrimRep]
+ which returns the list
+
+2. typePrimRepU :: Type -> PrimRep
+ which asserts that the type has exactly one PrimRep and returns it
+
+3. typePrimRep1 :: Type -> PrimOrVoidRep
+ data PrimOrVoidRep = VoidRep | NVRep PrimRep
+ which asserts that the type either has exactly one PrimRep or is void.
+
+Likewise, we have idPrimRepU and idPrimRep1, stgArgRepU and stgArgRep1,
+which have analogous preconditions.
Note [Getting from RuntimeRep to PrimRep]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -546,17 +557,22 @@ typePrimRep ty = kindPrimRep (text "typePrimRep" <+>
typePrimRep_maybe :: Type -> Maybe [PrimRep]
typePrimRep_maybe ty = kindPrimRep_maybe (typeKind ty)
--- | Like 'typePrimRep', but assumes that there is precisely one 'PrimRep' output;
+-- | Like 'typePrimRep', but assumes that there is at most one 'PrimRep' output;
-- an empty list of PrimReps becomes a VoidRep.
-- This assumption holds after unarise, see Note [Post-unarisation invariants].
-- Before unarise it may or may not hold.
-- See also Note [RuntimeRep and PrimRep] and Note [VoidRep]
-typePrimRep1 :: HasDebugCallStack => UnaryType -> PrimRep
+typePrimRep1 :: HasDebugCallStack => UnaryType -> PrimOrVoidRep
typePrimRep1 ty = case typePrimRep ty of
[] -> VoidRep
- [rep] -> rep
+ [rep] -> NVRep rep
_ -> pprPanic "typePrimRep1" (ppr ty $$ ppr (typePrimRep ty))
+typePrimRepU :: HasDebugCallStack => NvUnaryType -> PrimRep
+typePrimRepU ty = case typePrimRep ty of
+ [rep] -> rep
+ _ -> pprPanic "typePrimRepU" (ppr ty $$ ppr (typePrimRep ty))
+
-- | Find the runtime representation of a 'TyCon'. Defined here to
-- avoid module loops. Returns a list of the register shapes necessary.
-- See also Note [Getting from RuntimeRep to PrimRep]
@@ -567,15 +583,6 @@ tyConPrimRep tc
where
res_kind = tyConResKind tc
--- | Like 'tyConPrimRep', but assumed that there is precisely zero or
--- one 'PrimRep' output
--- See also Note [Getting from RuntimeRep to PrimRep] and Note [VoidRep]
-tyConPrimRep1 :: HasDebugCallStack => TyCon -> PrimRep
-tyConPrimRep1 tc = case tyConPrimRep tc of
- [] -> VoidRep
- [rep] -> rep
- _ -> pprPanic "tyConPrimRep1" (ppr tc $$ ppr (tyConPrimRep tc))
-
-- | Take a kind (of shape @TYPE rr@) and produce the 'PrimRep's
-- of values of types of this kind.
-- See also Note [Getting from RuntimeRep to PrimRep]
@@ -603,8 +610,6 @@ kindPrimRep_maybe ki
-- | Take a type of kind RuntimeRep and extract the list of 'PrimRep' that
-- it encodes. See also Note [Getting from RuntimeRep to PrimRep].
-- The @[PrimRep]@ is the final runtime representation /after/ unarisation.
---
--- The result does not contain any VoidRep.
runtimeRepPrimRep :: HasDebugCallStack => SDoc -> RuntimeRepType -> [PrimRep]
runtimeRepPrimRep doc rr_ty
| Just rr_ty' <- coreView rr_ty
@@ -617,8 +622,7 @@ runtimeRepPrimRep doc rr_ty
-- | Take a type of kind RuntimeRep and extract the list of 'PrimRep' that
-- it encodes. See also Note [Getting from RuntimeRep to PrimRep].
--- The @[PrimRep]@ is the final runtime representation /after/ unarisation
--- and does not contain VoidRep.
+-- The @[PrimRep]@ is the final runtime representation /after/ unarisation.
--
-- Returns @Nothing@ if rep can't be determined. Eg. levity polymorphic types.
runtimeRepPrimRep_maybe :: Type -> Maybe [PrimRep]
@@ -634,7 +638,6 @@ runtimeRepPrimRep_maybe rr_ty
-- | Convert a 'PrimRep' to a 'Type' of kind RuntimeRep
primRepToRuntimeRep :: PrimRep -> RuntimeRepType
primRepToRuntimeRep rep = case rep of
- VoidRep -> zeroBitRepTy
BoxedRep mlev -> case mlev of
Nothing -> panic "primRepToRuntimeRep: levity polymorphic BoxedRep"
Just Lifted -> liftedRepTy
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/fcb0a1de395021aa6609cd108a2ddd21ccdd7ba2
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/fcb0a1de395021aa6609cd108a2ddd21ccdd7ba2
You're receiving this email because of your account on gitlab.haskell.org.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/ghc-commits/attachments/20240105/b254b83c/attachment-0001.html>
More information about the ghc-commits
mailing list