summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--compiler/codeGen/StgCmmExpr.hs14
-rw-r--r--compiler/ghci/ByteCodeGen.hs5
-rw-r--r--compiler/stgSyn/CoreToStg.hs40
-rw-r--r--compiler/types/TyCon.hs21
4 files changed, 46 insertions, 34 deletions
diff --git a/compiler/codeGen/StgCmmExpr.hs b/compiler/codeGen/StgCmmExpr.hs
index 70a044a7ab..cc7caef438 100644
--- a/compiler/codeGen/StgCmmExpr.hs
+++ b/compiler/codeGen/StgCmmExpr.hs
@@ -41,7 +41,7 @@ import Id
import PrimOp
import TyCon
import Type ( isUnliftedType )
-import RepType ( isVoidTy, countConRepArgs, primRepSlot )
+import RepType ( isVoidTy, countConRepArgs )
import CostCentre ( CostCentreStack, currentCCS )
import Maybes
import Util
@@ -50,7 +50,6 @@ import Outputable
import Control.Monad (unless,void)
import Control.Arrow (first)
-import Data.Function ( on )
------------------------------------------------------------------------
-- cgExpr: the main function
@@ -428,10 +427,9 @@ assignment.
-}
cgCase (StgApp v []) bndr alt_type@(PrimAlt _) alts
| isUnliftedType (idType v) -- Note [Dodgy unsafeCoerce 1]
- || reps_compatible
= -- assignment suffices for unlifted types
do { dflags <- getDynFlags
- ; unless reps_compatible $
+ ; unless (reps_compatible dflags) $
pprPanic "cgCase: reps do not match, perhaps a dodgy unsafeCoerce?"
(pp_bndr v $$ pp_bndr bndr)
; v_info <- getCgIdInfo v
@@ -441,13 +439,7 @@ cgCase (StgApp v []) bndr alt_type@(PrimAlt _) alts
; _ <- bindArgToReg (NonVoid bndr)
; cgAlts (NoGcInAlts,AssignedDirectly) (NonVoid bndr) alt_type alts }
where
- reps_compatible = ((==) `on` (primRepSlot . idPrimRep)) v bndr
- -- Must compare SlotTys, not proper PrimReps, because with unboxed sums,
- -- the types of the binders are generated from slotPrimRep and might not
- -- match. Test case:
- -- swap :: (# Int | Int #) -> (# Int | Int #)
- -- swap (# x | #) = (# | x #)
- -- swap (# | y #) = (# y | #)
+ reps_compatible dflags = primRepCompatible dflags (idPrimRep v) (idPrimRep bndr)
pp_bndr id = ppr id <+> dcolon <+> ppr (idType id) <+> parens (ppr (idPrimRep id))
diff --git a/compiler/ghci/ByteCodeGen.hs b/compiler/ghci/ByteCodeGen.hs
index ac7a5def0c..eb82ecb26b 100644
--- a/compiler/ghci/ByteCodeGen.hs
+++ b/compiler/ghci/ByteCodeGen.hs
@@ -1219,7 +1219,7 @@ generateCCall d0 s p (CCallSpec target cconv safety) fn args_r_to_l
push_args = concatOL pushs_arg
!d_after_args = d0 + wordsToBytes dflags a_reps_sizeW
a_reps_pushed_RAW
- | null a_reps_pushed_r_to_l || head a_reps_pushed_r_to_l /= VoidRep
+ | null a_reps_pushed_r_to_l || not (isVoidRep (head a_reps_pushed_r_to_l))
= panic "ByteCodeGen.generateCCall: missing or invalid World token?"
| otherwise
= reverse (tail a_reps_pushed_r_to_l)
@@ -1904,7 +1904,8 @@ atomPrimRep (AnnLit l) = typePrimRep1 (literalType l)
-- #12128:
-- A case expression can be an atom because empty cases evaluate to bottom.
-- See Note [Empty case alternatives] in coreSyn/CoreSyn.hs
-atomPrimRep (AnnCase _ _ ty _) = ASSERT(typePrimRep ty == [LiftedRep]) LiftedRep
+atomPrimRep (AnnCase _ _ ty _) =
+ ASSERT(case typePrimRep ty of [LiftedRep] -> True; _ -> False) LiftedRep
atomPrimRep (AnnCoercion {}) = VoidRep
atomPrimRep other = pprPanic "atomPrimRep" (ppr (deAnnotate' other))
diff --git a/compiler/stgSyn/CoreToStg.hs b/compiler/stgSyn/CoreToStg.hs
index d548616dde..4982ad68f4 100644
--- a/compiler/stgSyn/CoreToStg.hs
+++ b/compiler/stgSyn/CoreToStg.hs
@@ -263,7 +263,7 @@ coreTopBindToStg dflags this_mod env ccs (NonRec id rhs)
how_bound = LetBound TopLet $! manifestArity rhs
(stg_rhs, ccs') =
- initCts env $
+ initCts dflags env $
coreToTopStgRhs dflags ccs this_mod (id,rhs)
bind = StgTopLifted $ StgNonRec id stg_rhs
@@ -286,7 +286,7 @@ coreTopBindToStg dflags this_mod env ccs (Rec pairs)
-- generate StgTopBindings and CAF cost centres created for CAFs
(ccs', stg_rhss)
- = initCts env' $ do
+ = initCts dflags env' $ do
mapAccumLM (\ccs rhs -> do
(rhs', ccs') <-
coreToTopStgRhs dflags ccs this_mod rhs
@@ -598,16 +598,12 @@ coreToStgArgs (arg : args) = do -- Non-type argument
-- This matters particularly when the function is a primop
-- or foreign call.
-- Wanted: a better solution than this hacky warning
+
+ dflags <- getDynFlags
let
- arg_ty = exprType arg
- stg_arg_ty = stgArgType stg_arg
- bad_args = (isUnliftedType arg_ty && not (isUnliftedType stg_arg_ty))
- || (typePrimRep arg_ty /= typePrimRep stg_arg_ty)
- -- In GHCi we coerce an argument of type BCO# (unlifted) to HValue (lifted),
- -- and pass it to a function expecting an HValue (arg_ty). This is ok because
- -- we can treat an unlifted value as lifted. But the other way round
- -- we complain.
- -- We also want to check if a pointer is cast to a non-ptr etc
+ arg_rep = typePrimRep (exprType arg)
+ stg_arg_rep = typePrimRep (stgArgType stg_arg)
+ bad_args = not (primRepsCompatible dflags arg_rep stg_arg_rep)
WARN( bad_args, text "Dangerous-looking argument. Probable cause: bad unsafeCoerce#" $$ ppr arg )
return (stg_arg : stg_args, ticks ++ aticks)
@@ -816,7 +812,8 @@ isPAP env _ = False
-- *down*.
newtype CtsM a = CtsM
- { unCtsM :: IdEnv HowBound
+ { unCtsM :: DynFlags -- Needed for checking for bad coercions in coreToStgArgs
+ -> IdEnv HowBound
-> a
}
deriving (Functor)
@@ -853,8 +850,8 @@ data LetInfo
-- The std monad functions:
-initCts :: IdEnv HowBound -> CtsM a -> a
-initCts env m = unCtsM m env
+initCts :: DynFlags -> IdEnv HowBound -> CtsM a -> a
+initCts dflags env m = unCtsM m dflags env
@@ -862,11 +859,11 @@ initCts env m = unCtsM m env
{-# INLINE returnCts #-}
returnCts :: a -> CtsM a
-returnCts e = CtsM $ \_ -> e
+returnCts e = CtsM $ \_ _ -> e
thenCts :: CtsM a -> (a -> CtsM b) -> CtsM b
-thenCts m k = CtsM $ \env
- -> unCtsM (k (unCtsM m env)) env
+thenCts m k = CtsM $ \dflags env
+ -> unCtsM (k (unCtsM m dflags env)) dflags env
instance Applicative CtsM where
pure = returnCts
@@ -875,15 +872,18 @@ instance Applicative CtsM where
instance Monad CtsM where
(>>=) = thenCts
+instance HasDynFlags CtsM where
+ getDynFlags = CtsM $ \dflags _ -> dflags
+
-- Functions specific to this monad:
extendVarEnvCts :: [(Id, HowBound)] -> CtsM a -> CtsM a
extendVarEnvCts ids_w_howbound expr
- = CtsM $ \env
- -> unCtsM expr (extendVarEnvList env ids_w_howbound)
+ = CtsM $ \dflags env
+ -> unCtsM expr dflags (extendVarEnvList env ids_w_howbound)
lookupVarCts :: Id -> CtsM HowBound
-lookupVarCts v = CtsM $ \env -> lookupBinding env v
+lookupVarCts v = CtsM $ \_ env -> lookupBinding env v
lookupBinding :: IdEnv HowBound -> Id -> HowBound
lookupBinding env v = case lookupVarEnv env v of
diff --git a/compiler/types/TyCon.hs b/compiler/types/TyCon.hs
index d3977aaecb..45fdb411ab 100644
--- a/compiler/types/TyCon.hs
+++ b/compiler/types/TyCon.hs
@@ -121,6 +121,8 @@ module TyCon(
primRepSizeB,
primElemRepSizeB,
primRepIsFloat,
+ primRepsCompatible,
+ primRepCompatible,
-- * Recursion breaking
RecTcChecker, initRecTc, defaultRecTcMaxBound,
@@ -1422,7 +1424,7 @@ data PrimRep
| FloatRep
| DoubleRep
| VecRep Int PrimElemRep -- ^ A vector
- deriving( Eq, Show )
+ deriving( Show )
data PrimElemRep
= Int8ElemRep
@@ -1452,6 +1454,23 @@ isGcPtrRep LiftedRep = True
isGcPtrRep UnliftedRep = True
isGcPtrRep _ = False
+-- A PrimRep is compatible with another iff one can be coerced to the other.
+-- See Note [bad unsafe coercion] in CoreLint for when are two types coercible.
+primRepCompatible :: DynFlags -> PrimRep -> PrimRep -> Bool
+primRepCompatible dflags rep1 rep2 =
+ (isUnboxed rep1 == isUnboxed rep2) &&
+ (primRepSizeB dflags rep1 == primRepSizeB dflags rep2) &&
+ (primRepIsFloat rep1 == primRepIsFloat rep2)
+ where
+ isUnboxed = not . isGcPtrRep
+
+-- More general version of `primRepCompatible` for types represented by zero or
+-- more than one PrimReps.
+primRepsCompatible :: DynFlags -> [PrimRep] -> [PrimRep] -> Bool
+primRepsCompatible dflags reps1 reps2 =
+ length reps1 == length reps2 &&
+ and (zipWith (primRepCompatible dflags) reps1 reps2)
+
-- | The size of a 'PrimRep' in bytes.
--
-- This applies also when used in a constructor, where we allow packing the