summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSylvain Henry <sylvain@haskus.fr>2021-08-12 17:44:15 +0200
committerMarge Bot <ben+marge-bot@smart-cactus.org>2021-09-11 08:54:29 -0400
commit089de88ef5215de0f2db4c4babc556ac43f8232e (patch)
treec036813b9625dbb45b4577b09ec6ad31c45c1bce
parent74a87aa3046f3eb871e5442579e9a2945ef691d4 (diff)
downloadhaskell-089de88ef5215de0f2db4c4babc556ac43f8232e.tar.gz
Canonicalize bignum literals
Before this patch Integer and Natural literals were desugared into "real" Core in Core prep. Now we desugar them directly into their final ConApp form in HsToCore. We only keep the double representation for BigNat# (literals larger than a machine Word/Int) which are still desugared in Core prep. Using the final form directly allows case-of-known-constructor to fire for bignum literals, fixing #20245. Slight increase (+2.3) in T4801 which is a pathological case with Integer literals. Metric Increase: T4801 T11545
-rw-r--r--compiler/GHC/ByteCode/Asm.hs3
-rw-r--r--compiler/GHC/Core/Make.hs13
-rw-r--r--compiler/GHC/Core/Opt/ConstantFold.hs165
-rw-r--r--compiler/GHC/Core/SimpleOpt.hs31
-rw-r--r--compiler/GHC/Core/Unfold.hs3
-rw-r--r--compiler/GHC/CoreToStg.hs5
-rw-r--r--compiler/GHC/CoreToStg/Prep.hs33
-rw-r--r--compiler/GHC/HsToCore/Match/Literal.hs20
-rw-r--r--compiler/GHC/HsToCore/Pmc/Solver/Types.hs47
-rw-r--r--compiler/GHC/HsToCore/Quote.hs10
-rw-r--r--compiler/GHC/StgToByteCode.hs8
-rw-r--r--compiler/GHC/Tc/Instance/Class.hs4
-rw-r--r--compiler/GHC/Tc/Plugin.hs7
-rw-r--r--compiler/GHC/Types/Literal.hs102
-rw-r--r--testsuite/tests/lib/integer/all.T7
-rw-r--r--testsuite/tests/numeric/should_compile/T14170.stdout6
-rw-r--r--testsuite/tests/numeric/should_compile/T14465.stdout10
-rw-r--r--testsuite/tests/numeric/should_compile/T20245.hs9
-rw-r--r--testsuite/tests/numeric/should_compile/T20245.stderr9
-rw-r--r--testsuite/tests/numeric/should_compile/all.T1
-rw-r--r--testsuite/tests/simplCore/should_compile/T15445.stderr2
-rw-r--r--testsuite/tests/simplCore/should_compile/T8832.stdout-ws-322
-rw-r--r--testsuite/tests/simplCore/should_compile/T8832.stdout-ws-642
-rw-r--r--testsuite/tests/tcplugins/ArgsPlugin.hs15
24 files changed, 266 insertions, 248 deletions
diff --git a/compiler/GHC/ByteCode/Asm.hs b/compiler/GHC/ByteCode/Asm.hs
index da03d2a903..1d7402c9cf 100644
--- a/compiler/GHC/ByteCode/Asm.hs
+++ b/compiler/GHC/ByteCode/Asm.hs
@@ -488,8 +488,7 @@ assembleI platform i = case i of
LitNumWord32 -> int32 (fromIntegral i)
LitNumInt64 -> int64 (fromIntegral i)
LitNumWord64 -> int64 (fromIntegral i)
- LitNumInteger -> panic "GHC.ByteCode.Asm.literal: LitNumInteger"
- LitNumNatural -> panic "GHC.ByteCode.Asm.literal: LitNumNatural"
+ LitNumBigNat -> panic "GHC.ByteCode.Asm.literal: LitNumBigNat"
-- We can lower 'LitRubbish' to an arbitrary constant, but @NULL@ is most
-- likely to elicit a crash (rather than corrupt memory) in case absence
diff --git a/compiler/GHC/Core/Make.hs b/compiler/GHC/Core/Make.hs
index d7a78b5888..b43344a92c 100644
--- a/compiler/GHC/Core/Make.hs
+++ b/compiler/GHC/Core/Make.hs
@@ -304,12 +304,17 @@ mkWordExpr :: Platform -> Integer -> CoreExpr
mkWordExpr platform w = mkCoreConApps wordDataCon [mkWordLit platform w]
-- | Create a 'CoreExpr' which will evaluate to the given @Integer@
-mkIntegerExpr :: Integer -> CoreExpr -- Result :: Integer
-mkIntegerExpr i = Lit (mkLitInteger i)
+mkIntegerExpr :: Platform -> Integer -> CoreExpr -- Result :: Integer
+mkIntegerExpr platform i
+ | platformInIntRange platform i = mkCoreConApps integerISDataCon [mkIntLit platform i]
+ | i < 0 = mkCoreConApps integerINDataCon [Lit (mkLitBigNat (negate i))]
+ | otherwise = mkCoreConApps integerIPDataCon [Lit (mkLitBigNat i)]
-- | Create a 'CoreExpr' which will evaluate to the given @Natural@
-mkNaturalExpr :: Integer -> CoreExpr
-mkNaturalExpr i = Lit (mkLitNatural i)
+mkNaturalExpr :: Platform -> Integer -> CoreExpr
+mkNaturalExpr platform w
+ | platformInWordRange platform w = mkCoreConApps naturalNSDataCon [mkWordLit platform w]
+ | otherwise = mkCoreConApps naturalNBDataCon [Lit (mkLitBigNat w)]
-- | Create a 'CoreExpr' which will evaluate to the given @Float@
mkFloatExpr :: Float -> CoreExpr
diff --git a/compiler/GHC/Core/Opt/ConstantFold.hs b/compiler/GHC/Core/Opt/ConstantFold.hs
index df7e9b0782..35df78e5a7 100644
--- a/compiler/GHC/Core/Opt/ConstantFold.hs
+++ b/compiler/GHC/Core/Opt/ConstantFold.hs
@@ -47,7 +47,7 @@ import GHC.Types.Basic
import GHC.Core
import GHC.Core.Make
import GHC.Core.SimpleOpt ( exprIsConApp_maybe, exprIsLiteral_maybe )
-import GHC.Core.DataCon ( dataConTagZ, dataConTyCon, dataConWrapId, dataConWorkId )
+import GHC.Core.DataCon ( DataCon,dataConTagZ, dataConTyCon, dataConWrapId, dataConWorkId )
import GHC.Core.Utils ( eqExpr, cheapEqExpr, exprIsHNF, exprType
, stripTicksTop, stripTicksTopT, mkTicks )
import GHC.Core.Multiplicity
@@ -1452,30 +1452,52 @@ isLiteral e = do
Nothing -> mzero
Just l -> pure l
+-- | Match Integer and Natural literals
+isBignumLiteral :: CoreExpr -> RuleM Integer
+isBignumLiteral e = isIntegerLiteral e <|> isNaturalLiteral e
+
+-- | Match numeric literals
isNumberLiteral :: CoreExpr -> RuleM Integer
isNumberLiteral e = isLiteral e >>= \case
LitNumber _ x -> pure x
_ -> mzero
+-- | Match the application of a DataCon to a numeric literal.
+--
+-- Can be used to match e.g.:
+-- IS 123#
+-- IP bigNatLiteral
+-- W# 123##
+isLitNumConApp :: CoreExpr -> RuleM (DataCon,Integer)
+isLitNumConApp e = do
+ env <- getInScopeEnv
+ case exprIsConApp_maybe env e of
+ Just (_env,_fb,dc,_tys,[arg]) -> case exprIsLiteral_maybe env arg of
+ Just (LitNumber _ i) -> pure (dc,i)
+ _ -> mzero
+ _ -> mzero
+
isIntegerLiteral :: CoreExpr -> RuleM Integer
-isIntegerLiteral e = isLiteral e >>= \case
- LitNumber LitNumInteger x -> pure x
- _ -> mzero
+isIntegerLiteral e = do
+ (dc,i) <- isLitNumConApp e
+ if | dc == integerISDataCon -> pure i
+ | dc == integerINDataCon -> pure (negate i)
+ | dc == integerIPDataCon -> pure i
+ | otherwise -> mzero
+
+isBigIntegerLiteral :: CoreExpr -> RuleM Integer
+isBigIntegerLiteral e = do
+ (dc,i) <- isLitNumConApp e
+ if | dc == integerINDataCon -> pure (negate i)
+ | dc == integerIPDataCon -> pure i
+ | otherwise -> mzero
isNaturalLiteral :: CoreExpr -> RuleM Integer
-isNaturalLiteral e = isLiteral e >>= \case
- LitNumber LitNumNatural x -> pure x
- _ -> mzero
-
-isWordLiteral :: CoreExpr -> RuleM Integer
-isWordLiteral e = isLiteral e >>= \case
- LitNumber LitNumWord x -> pure x
- _ -> mzero
-
-isIntLiteral :: CoreExpr -> RuleM Integer
-isIntLiteral e = isLiteral e >>= \case
- LitNumber LitNumInt x -> pure x
- _ -> mzero
+isNaturalLiteral e = do
+ (dc,i) <- isLitNumConApp e
+ if | dc == naturalNSDataCon -> pure i
+ | dc == naturalNBDataCon -> pure i
+ | otherwise -> mzero
-- return the n-th argument of this rule, if it is a literal
-- argument indices start from 0
@@ -2003,17 +2025,18 @@ builtinBignumRules =
y <- isNaturalLiteral a1
-- return an unboxed sum: (# (# #) | Natural #)
let ret n v = pure $ mkCoreUbxSum 2 n [unboxedUnitTy,naturalTy] v
+ platform <- getPlatform
if x < y
then ret 1 $ Var voidPrimId
- else ret 2 $ Lit (mkLitNatural (x - y))
+ else ret 2 $ mkNaturalExpr platform (x - y)
-- unary operations
- , bignum_unop "integerNegate" integerNegateName mkLitInteger negate
- , bignum_unop "integerAbs" integerAbsName mkLitInteger abs
- , bignum_unop "integerSignum" integerSignumName mkLitInteger signum
- , bignum_unop "integerComplement" integerComplementName mkLitInteger complement
+ , bignum_unop "integerNegate" integerNegateName mkIntegerExpr negate
+ , bignum_unop "integerAbs" integerAbsName mkIntegerExpr abs
+ , bignum_unop "integerSignum" integerSignumName mkIntegerExpr signum
+ , bignum_unop "integerComplement" integerComplementName mkIntegerExpr complement
- , bignum_unop "naturalSignum" naturalSignumName mkLitNatural signum
+ , bignum_unop "naturalSignum" naturalSignumName mkNaturalExpr signum
, mkRule "naturalNegate" naturalNegateName 1 $ do
[a0] <- getArgs
@@ -2033,30 +2056,30 @@ builtinBignumRules =
--
-- Bits.bit
- , bignum_bit "integerBit" integerBitName mkLitInteger
- , bignum_bit "naturalBit" naturalBitName mkLitNatural
+ , bignum_bit "integerBit" integerBitName mkIntegerExpr
+ , bignum_bit "naturalBit" naturalBitName mkNaturalExpr
-- Bits.testBit
, bignum_testbit "integerTestBit" integerTestBitName
, bignum_testbit "naturalTestBit" naturalTestBitName
-- Bits.shift
- , bignum_shift "integerShiftL" integerShiftLName shiftL mkLitInteger
- , bignum_shift "integerShiftR" integerShiftRName shiftR mkLitInteger
- , bignum_shift "naturalShiftL" naturalShiftLName shiftL mkLitNatural
- , bignum_shift "naturalShiftR" naturalShiftRName shiftR mkLitNatural
+ , bignum_shift "integerShiftL" integerShiftLName shiftL mkIntegerExpr
+ , bignum_shift "integerShiftR" integerShiftRName shiftR mkIntegerExpr
+ , bignum_shift "naturalShiftL" naturalShiftLName shiftL mkNaturalExpr
+ , bignum_shift "naturalShiftR" naturalShiftRName shiftR mkNaturalExpr
-- division
- , divop_one "integerQuot" integerQuotName quot mkLitInteger
- , divop_one "integerRem" integerRemName rem mkLitInteger
- , divop_one "integerDiv" integerDivName div mkLitInteger
- , divop_one "integerMod" integerModName mod mkLitInteger
- , divop_both "integerDivMod" integerDivModName divMod mkLitInteger integerTy
- , divop_both "integerQuotRem" integerQuotRemName quotRem mkLitInteger integerTy
+ , divop_one "integerQuot" integerQuotName quot mkIntegerExpr
+ , divop_one "integerRem" integerRemName rem mkIntegerExpr
+ , divop_one "integerDiv" integerDivName div mkIntegerExpr
+ , divop_one "integerMod" integerModName mod mkIntegerExpr
+ , divop_both "integerDivMod" integerDivModName divMod mkIntegerExpr integerTy
+ , divop_both "integerQuotRem" integerQuotRemName quotRem mkIntegerExpr integerTy
- , divop_one "naturalQuot" naturalQuotName quot mkLitNatural
- , divop_one "naturalRem" naturalRemName rem mkLitNatural
- , divop_both "naturalQuotRem" naturalQuotRemName quotRem mkLitNatural naturalTy
+ , divop_one "naturalQuot" naturalQuotName quot mkNaturalExpr
+ , divop_one "naturalRem" naturalRemName rem mkNaturalExpr
+ , divop_both "naturalQuotRem" naturalQuotRemName quotRem mkNaturalExpr naturalTy
-- conversions from Rational for Float/Double literals
, rational_to "rationalToFloat" rationalToFloatName mkFloatExpr
@@ -2080,7 +2103,9 @@ builtinBignumRules =
integer_to_lit str name convert = mkRule str name 1 $ do
[a0] <- getArgs
platform <- getPlatform
- x <- isIntegerLiteral a0
+ -- we only match on Big Integer literals. Small literals
+ -- are matched by the "Int# -> Integer -> *" rules
+ x <- isBigIntegerLiteral a0
pure (convert platform x)
natural_to_word str name clamp = mkRule str name 1 $ do
@@ -2094,36 +2119,40 @@ builtinBignumRules =
integer_to_natural str name thrw clamp = mkRule str name 1 $ do
[a0] <- getArgs
x <- isIntegerLiteral a0
- if | x >= 0 -> pure $ Lit $ mkLitNatural x
+ platform <- getPlatform
+ if | x >= 0 -> pure $ mkNaturalExpr platform x
| thrw -> mzero
- | clamp -> pure $ Lit $ mkLitNatural 0 -- clamp to 0
- | otherwise -> pure $ Lit $ mkLitNatural (abs x) -- negate/wrap
+ | clamp -> pure $ mkNaturalExpr platform 0 -- clamp to 0
+ | otherwise -> pure $ mkNaturalExpr platform (abs x) -- negate/wrap
lit_to_integer str name = mkRule str name 1 $ do
[a0] <- getArgs
- isLiteral a0 >>= \case
- -- convert any numeric literal into an Integer literal
- LitNumber _ i -> pure (Lit (mkLitInteger i))
- _ -> mzero
+ platform <- getPlatform
+ i <- isNumberLiteral a0 <|> isBignumLiteral a0
+ -- convert any numeric literal into an Integer literal
+ pure (mkIntegerExpr platform i)
integer_binop str name op = mkRule str name 2 $ do
[a0,a1] <- getArgs
x <- isIntegerLiteral a0
y <- isIntegerLiteral a1
- pure (Lit (mkLitInteger (x `op` y)))
+ platform <- getPlatform
+ pure (mkIntegerExpr platform (x `op` y))
natural_binop str name op = mkRule str name 2 $ do
[a0,a1] <- getArgs
x <- isNaturalLiteral a0
y <- isNaturalLiteral a1
- pure (Lit (mkLitNatural (x `op` y)))
+ platform <- getPlatform
+ pure (mkNaturalExpr platform (x `op` y))
natural_sub str name = mkRule str name 2 $ do
[a0,a1] <- getArgs
x <- isNaturalLiteral a0
y <- isNaturalLiteral a1
guard (x >= y)
- pure (Lit (mkLitNatural (x - y)))
+ platform <- getPlatform
+ pure (mkNaturalExpr platform (x - y))
integer_cmp str name op = mkRule str name 2 $ do
platform <- getPlatform
@@ -2145,8 +2174,8 @@ builtinBignumRules =
bignum_compare str name = mkRule str name 2 $ do
[a0,a1] <- getArgs
- x <- isNumberLiteral a0
- y <- isNumberLiteral a1
+ x <- isBignumLiteral a0
+ y <- isBignumLiteral a1
pure $ case x `compare` y of
LT -> ltVal
EQ -> eqVal
@@ -2154,8 +2183,9 @@ builtinBignumRules =
bignum_unop str name mk_lit op = mkRule str name 1 $ do
[a0] <- getArgs
- x <- isNumberLiteral a0
- pure $ Lit (mk_lit (op x))
+ x <- isBignumLiteral a0
+ platform <- getPlatform
+ pure $ mk_lit platform (op x)
bignum_popcount str name mk_lit = mkRule str name 1 $ do
platform <- getPlatform
@@ -2164,7 +2194,7 @@ builtinBignumRules =
-- by the target. So we disable this rule if sizes don't match.
guard (platformWordSizeInBits platform == finiteBitSize (0 :: Word))
[a0] <- getArgs
- x <- isNumberLiteral a0
+ x <- isBignumLiteral a0
pure $ Lit (mk_lit platform (fromIntegral (popCount x)))
bignum_bit str name mk_lit = mkRule str name 1 $ do
@@ -2178,12 +2208,12 @@ builtinBignumRules =
guard (n >= 0 && n <= fromIntegral (platformWordSizeInBits platform))
-- it's safe to convert a target Int value into a host Int value
-- to perform the "bit" operation because n is very small (<= 64).
- pure $ Lit (mk_lit (bit (fromIntegral n)))
+ pure $ mk_lit platform (bit (fromIntegral n))
bignum_testbit str name = mkRule str name 2 $ do
[a0,a1] <- getArgs
platform <- getPlatform
- x <- isNumberLiteral a0
+ x <- isBignumLiteral a0
n <- isNumberLiteral a1
-- ensure that we can store 'n' in a host Int
guard (n >= 0 && n <= fromIntegral (maxBound :: Int))
@@ -2193,34 +2223,37 @@ builtinBignumRules =
bignum_shift str name shift_op mk_lit = mkRule str name 2 $ do
[a0,a1] <- getArgs
- x <- isNumberLiteral a0
- n <- isWordLiteral a1
+ x <- isBignumLiteral a0
+ n <- isNumberLiteral a1
-- See Note [Guarding against silly shifts]
-- Restrict constant-folding of shifts on Integers, somewhat arbitrary.
-- We can get huge shifts in inaccessible code (#15673)
guard (n <= 4)
- pure $ Lit (mk_lit (x `shift_op` fromIntegral n))
+ platform <- getPlatform
+ pure $ mk_lit platform (x `shift_op` fromIntegral n)
divop_one str name divop mk_lit = mkRule str name 2 $ do
[a0,a1] <- getArgs
- n <- isNumberLiteral a0
- d <- isNumberLiteral a1
+ n <- isBignumLiteral a0
+ d <- isBignumLiteral a1
guard (d /= 0)
- pure $ Lit (mk_lit (n `divop` d))
+ platform <- getPlatform
+ pure $ mk_lit platform (n `divop` d)
divop_both str name divop mk_lit ty = mkRule str name 2 $ do
[a0,a1] <- getArgs
- n <- isNumberLiteral a0
- d <- isNumberLiteral a1
+ n <- isBignumLiteral a0
+ d <- isBignumLiteral a1
guard (d /= 0)
let (r,s) = n `divop` d
- pure $ mkCoreUbxTup [ty,ty] [Lit (mk_lit r), Lit (mk_lit s)]
+ platform <- getPlatform
+ pure $ mkCoreUbxTup [ty,ty] [mk_lit platform r, mk_lit platform s]
integer_encode_float :: RealFloat a => String -> Name -> (a -> CoreExpr) -> CoreRule
integer_encode_float str name mk_lit = mkRule str name 2 $ do
[a0,a1] <- getArgs
x <- isIntegerLiteral a0
- y <- isIntLiteral a1
+ y <- isNumberLiteral a1
-- check that y (a target Int) is in the host Int range
guard (y <= fromIntegral (maxBound :: Int))
pure (mk_lit $ encodeFloat x (fromInteger y))
diff --git a/compiler/GHC/Core/SimpleOpt.hs b/compiler/GHC/Core/SimpleOpt.hs
index d741aa0351..720bc895c8 100644
--- a/compiler/GHC/Core/SimpleOpt.hs
+++ b/compiler/GHC/Core/SimpleOpt.hs
@@ -4,8 +4,6 @@
-}
-{-# LANGUAGE MultiWayIf #-}
-
module GHC.Core.SimpleOpt (
SimpleOpts (..), defaultSimpleOpts,
@@ -1284,36 +1282,15 @@ than the ordinary arity of the dfun: see Note [DFun unfoldings] in GHC.Core
exprIsLiteral_maybe :: InScopeEnv -> CoreExpr -> Maybe Literal
-- Same deal as exprIsConApp_maybe, but much simpler
-- Nevertheless we do need to look through unfoldings for
--- Integer and string literals, which are vigorously hoisted to top level
+-- string literals, which are vigorously hoisted to top level
-- and not subsequently inlined
exprIsLiteral_maybe env@(_, id_unf) e
= case e of
Lit l -> Just l
Tick _ e' -> exprIsLiteral_maybe env e' -- dubious?
- Var v
- | Just rhs <- expandUnfolding_maybe (id_unf v)
- , Just l <- exprIsLiteral_maybe env rhs
- -> Just l
- Var v
- | Just rhs <- expandUnfolding_maybe (id_unf v)
- , Just b <- matchBignum env rhs
- -> Just b
- e
- | Just b <- matchBignum env e
- -> Just b
-
- | otherwise
- -> Nothing
- where
- matchBignum env e
- | Just (_env,_fb,dc,_tys,[arg]) <- exprIsConApp_maybe env e
- , Just (LitNumber _ i) <- exprIsLiteral_maybe env arg
- = if
- | dc == naturalNSDataCon -> Just (mkLitNatural i)
- | dc == integerISDataCon -> Just (mkLitInteger i)
- | otherwise -> Nothing
- | otherwise
- = Nothing
+ Var v -> expandUnfolding_maybe (id_unf v)
+ >>= exprIsLiteral_maybe env
+ _ -> Nothing
{-
Note [exprIsLambda_maybe]
diff --git a/compiler/GHC/Core/Unfold.hs b/compiler/GHC/Core/Unfold.hs
index f8dadf8c16..dbc6b1e7fd 100644
--- a/compiler/GHC/Core/Unfold.hs
+++ b/compiler/GHC/Core/Unfold.hs
@@ -621,8 +621,7 @@ sizeExpr opts !bOMB_OUT_SIZE top_args expr
-- | Finds a nominal size of a string literal.
litSize :: Literal -> Int
-- Used by GHC.Core.Unfold.sizeExpr
-litSize (LitNumber LitNumInteger _) = 100 -- Note [Size of literal integers]
-litSize (LitNumber LitNumNatural _) = 100
+litSize (LitNumber LitNumBigNat _) = 100
litSize (LitString str) = 10 + 10 * ((BS.length str + 3) `div` 4)
-- If size could be 0 then @f "x"@ might be too small
-- [Sept03: make literal strings a bit bigger to avoid fruitless
diff --git a/compiler/GHC/CoreToStg.hs b/compiler/GHC/CoreToStg.hs
index a258a424dc..8d99965513 100644
--- a/compiler/GHC/CoreToStg.hs
+++ b/compiler/GHC/CoreToStg.hs
@@ -386,10 +386,9 @@ coreToStgExpr
-- on these components, but it in turn is not scrutinised as the basis for any
-- decisions. Hence no black holes.
--- No LitInteger's or LitNatural's should be left by the time this is called.
+-- No bignum literal should be left by the time this is called.
-- CorePrep should have converted them all to a real core representation.
-coreToStgExpr (Lit (LitNumber LitNumInteger _)) = panic "coreToStgExpr: LitInteger"
-coreToStgExpr (Lit (LitNumber LitNumNatural _)) = panic "coreToStgExpr: LitNatural"
+coreToStgExpr (Lit (LitNumber LitNumBigNat _)) = panic "coreToStgExpr: LitNumBigNat"
coreToStgExpr (Lit l) = return (StgLit l)
coreToStgExpr (Var v) = coreToStgApp v [] []
coreToStgExpr (Coercion _)
diff --git a/compiler/GHC/CoreToStg/Prep.hs b/compiler/GHC/CoreToStg/Prep.hs
index 30c28a6db2..675ef7776c 100644
--- a/compiler/GHC/CoreToStg/Prep.hs
+++ b/compiler/GHC/CoreToStg/Prep.hs
@@ -131,8 +131,7 @@ The goal of this pass is to prepare for code generation.
9. Replace (lazy e) by e. See Note [lazyId magic] in GHC.Types.Id.Make
Also replace (noinline e) by e.
-10. Convert bignum literals (LitNatural and LitInteger) into their
- core representation.
+10. Convert bignum literals into their core representation.
11. Uphold tick consistency while doing this: We move ticks out of
(non-type) applications where we can, and make sure that we
@@ -2146,37 +2145,9 @@ mkConvertNumLiteral hsc_env = do
let
convertNumLit nt i = case nt of
- LitNumInteger -> Just (convertInteger i)
- LitNumNatural -> Just (convertNatural i)
+ LitNumBigNat -> Just (convertBignatPrim i)
_ -> Nothing
- convertInteger i
- | platformInIntRange platform i -- fit in a Int#
- = mkConApp integerISDataCon [Lit (mkLitInt platform i)]
-
- | otherwise -- build a BigNat and embed into IN or IP
- = let con = if i > 0 then integerIPDataCon else integerINDataCon
- in mkBigNum con (convertBignatPrim (abs i))
-
- convertNatural i
- | platformInWordRange platform i -- fit in a Word#
- = mkConApp naturalNSDataCon [Lit (mkLitWord platform i)]
-
- | otherwise --build a BigNat and embed into NB
- = mkBigNum naturalNBDataCon (convertBignatPrim i)
-
- -- we can't simply generate:
- --
- -- NB (bigNatFromWordList# [W# 10, W# 20])
- --
- -- using `mkConApp` because it isn't in ANF form. Instead we generate:
- --
- -- case bigNatFromWordList# [W# 10, W# 20] of ba { DEFAULT -> NB ba }
- --
- -- via `mkCoreApps`
-
- mkBigNum con ba = mkCoreApps (Var (dataConWorkId con)) [ba]
-
convertBignatPrim i =
let
target = targetPlatform dflags
diff --git a/compiler/GHC/HsToCore/Match/Literal.hs b/compiler/GHC/HsToCore/Match/Literal.hs
index c19dceabb8..95c4285422 100644
--- a/compiler/GHC/HsToCore/Match/Literal.hs
+++ b/compiler/GHC/HsToCore/Match/Literal.hs
@@ -108,7 +108,7 @@ dsLit l = do
HsDoublePrim _ fl -> return (Lit (LitDouble (rationalFromFractionalLit fl)))
HsChar _ c -> return (mkCharExpr c)
HsString _ str -> mkStringExprFS str
- HsInteger _ i _ -> return (mkIntegerExpr i)
+ HsInteger _ i _ -> return (mkIntegerExpr platform i)
HsInt _ i -> return (mkIntExpr platform (il_value i))
HsRat _ fl ty -> dsFractionalLitToRational fl ty
@@ -199,15 +199,17 @@ dsFractionalLitToRational :: FractionalLit -> Type -> DsM CoreExpr
dsFractionalLitToRational fl@FL{ fl_signi = signi, fl_exp = exp, fl_exp_base = base } ty
-- We compute "small" rationals here and now
| abs exp <= 100
- = let !val = rationalFromFractionalLit fl
- !num = mkIntegerExpr (numerator val)
- !denom = mkIntegerExpr (denominator val)
+ = do
+ platform <- targetPlatform <$> getDynFlags
+ let !val = rationalFromFractionalLit fl
+ !num = mkIntegerExpr platform (numerator val)
+ !denom = mkIntegerExpr platform (denominator val)
(ratio_data_con, integer_ty)
= case tcSplitTyConApp ty of
(tycon, [i_ty]) -> assert (isIntegerTy i_ty && tycon `hasKey` ratioTyConKey)
(head (tyConDataCons tycon), i_ty)
x -> pprPanic "dsLit" (ppr x)
- in return $! (mkCoreConApps ratio_data_con [Type integer_ty, num, denom])
+ return $! (mkCoreConApps ratio_data_con [Type integer_ty, num, denom])
-- Large rationals will be computed at runtime.
| otherwise
= do
@@ -216,14 +218,16 @@ dsFractionalLitToRational fl@FL{ fl_signi = signi, fl_exp = exp, fl_exp_base = b
Base10 -> mkRationalBase10Name
mkRational <- dsLookupGlobalId mkRationalName
litR <- dsRational signi
- let litE = mkIntegerExpr exp
+ platform <- targetPlatform <$> getDynFlags
+ let litE = mkIntegerExpr platform exp
return (mkCoreApps (Var mkRational) [litR, litE])
dsRational :: Rational -> DsM CoreExpr
dsRational (n :% d) = do
+ platform <- targetPlatform <$> getDynFlags
dcn <- dsLookupDataCon ratioDataConName
- let cn = mkIntegerExpr n
- let dn = mkIntegerExpr d
+ let cn = mkIntegerExpr platform n
+ let dn = mkIntegerExpr platform d
return $ mkCoreConApps dcn [Type integerTy, cn, dn]
diff --git a/compiler/GHC/HsToCore/Pmc/Solver/Types.hs b/compiler/GHC/HsToCore/Pmc/Solver/Types.hs
index a111bbdd33..1fcaf44a4f 100644
--- a/compiler/GHC/HsToCore/Pmc/Solver/Types.hs
+++ b/compiler/GHC/HsToCore/Pmc/Solver/Types.hs
@@ -1,6 +1,7 @@
{-# LANGUAGE ApplicativeDo #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE ViewPatterns #-}
+{-# LANGUAGE MultiWayIf #-}
-- | Domain types used in "GHC.HsToCore.Pmc.Solver".
-- The ultimate goal is to define 'Nabla', which models normalised refinement
@@ -49,6 +50,7 @@ import GHC.Core.DataCon
import GHC.Core.ConLike
import GHC.Utils.Outputable
import GHC.Utils.Panic.Plain
+import GHC.Utils.Misc (lastMaybe)
import GHC.Data.List.SetOps (unionLists)
import GHC.Data.Maybe
import GHC.Core.Type
@@ -620,17 +622,24 @@ coreExprAsPmLit e = case collectArgs e of
| Just dc <- isDataConWorkId_maybe x
, dc `elem` [intDataCon, wordDataCon, charDataCon, floatDataCon, doubleDataCon]
-> literalToPmLit (exprType e) l
- (Var x, [_ty, Lit n, Lit d])
+ (Var x, [Lit (LitNumber _ l)])
+ | Just (ty,l) <- bignum_lit_maybe x l
+ -> Just (PmLit ty (PmLitInt l))
+ (Var x, [_ty, n_arg, d_arg])
| Just dc <- isDataConWorkId_maybe x
, dataConName dc == ratioDataConName
+ , Just (PmLit _ (PmLitInt n)) <- coreExprAsPmLit n_arg
+ , Just (PmLit _ (PmLitInt d)) <- coreExprAsPmLit d_arg
-- HACK: just assume we have a literal double. This case only occurs for
-- overloaded lits anyway, so we immediately override type information
- -> literalToPmLit (exprType e) (mkLitDouble (litValue n % litValue d))
+ -> literalToPmLit (exprType e) (mkLitDouble (n % d))
+
(Var x, args)
-- See Note [Detecting overloaded literals with -XRebindableSyntax]
| is_rebound_name x fromIntegerName
- , [Lit l] <- dropWhile (not . is_lit) args
- -> literalToPmLit (literalType l) l >>= overloadPmLit (exprType e)
+ , Just arg <- lastMaybe args
+ , Just (_ty,l) <- bignum_conapp_maybe arg
+ -> Just (PmLit integerTy (PmLitInt l)) >>= overloadPmLit (exprType e)
(Var x, args)
-- See Note [Detecting overloaded literals with -XRebindableSyntax]
-- fromRational <expr>
@@ -644,16 +653,16 @@ coreExprAsPmLit e = case collectArgs e of
-- See Note [Dealing with rationals with large exponents]
-- mkRationalBase* <rational> <exponent>
| Just exp_base <- is_larg_exp_ratio x
- , [r, Lit exp] <- dropWhile (not . is_ratio) args
- , (Var x, [_ty, Lit n, Lit d]) <- collectArgs r
+ , [r, exp] <- dropWhile (not . is_ratio) args
+ , (Var x, [_ty, n_arg, d_arg]) <- collectArgs r
, Just dc <- isDataConWorkId_maybe x
, dataConName dc == ratioDataConName
+ , Just (PmLit _ (PmLitInt n)) <- coreExprAsPmLit n_arg
+ , Just (PmLit _ (PmLitInt d)) <- coreExprAsPmLit d_arg
+ , Just (_exp_ty,exp') <- bignum_conapp_maybe exp
-> do
- n' <- isLitValue_maybe n
- d' <- isLitValue_maybe d
- exp' <- isLitValue_maybe exp
- let rational = (abs n') :% d'
- let neg = if n' < 0 then 1 else 0
+ let rational = (abs n) :% d
+ let neg = if n < 0 then 1 else 0
let frac = mkFractionalLit NoSourceText False rational exp' exp_base
Just $ PmLit (exprType e) (PmLitOverRat neg frac)
@@ -675,8 +684,20 @@ coreExprAsPmLit e = case collectArgs e of
_ -> Nothing
where
- is_lit Lit{} = True
- is_lit _ = False
+ bignum_conapp_maybe (App (Var x) (Lit (LitNumber _ l)))
+ = bignum_lit_maybe x l
+ bignum_conapp_maybe _ = Nothing
+
+ bignum_lit_maybe x l
+ | Just dc <- isDataConWorkId_maybe x
+ = if | dc == integerISDataCon -> Just (integerTy,l)
+ | dc == integerIPDataCon -> Just (integerTy,l)
+ | dc == integerINDataCon -> Just (integerTy,negate l)
+ | dc == naturalNSDataCon -> Just (naturalTy,l)
+ | dc == naturalNBDataCon -> Just (naturalTy,l)
+ | otherwise -> Nothing
+ bignum_lit_maybe _ _ = Nothing
+
is_ratio (Type _) = False
is_ratio r
| Just (tc, _) <- splitTyConApp_maybe (exprType r)
diff --git a/compiler/GHC/HsToCore/Quote.hs b/compiler/GHC/HsToCore/Quote.hs
index ea185b076f..032c003c6a 100644
--- a/compiler/GHC/HsToCore/Quote.hs
+++ b/compiler/GHC/HsToCore/Quote.hs
@@ -1422,7 +1422,9 @@ repTy (HsIParamTy _ n t) = do
repTy ty = notHandled (ThExoticFormOfType ty)
repTyLit :: HsTyLit -> MetaM (Core (M TH.TyLit))
-repTyLit (HsNumTy _ i) = rep2 numTyLitName [mkIntegerExpr i]
+repTyLit (HsNumTy _ i) = do
+ platform <- getPlatform
+ rep2 numTyLitName [mkIntegerExpr platform i]
repTyLit (HsStrTy _ s) = do { s' <- mkStringExprFS s
; rep2 strTyLitName [s']
}
@@ -2174,7 +2176,8 @@ globalVar name
; rep2_nwDsM mk_varg [pkg,mod,occ] }
| otherwise
= do { MkC occ <- nameLit name
- ; MkC uni <- coreIntegerLit (toInteger $ getKey (getUnique name))
+ ; platform <- targetPlatform <$> getDynFlags
+ ; let uni = mkIntegerExpr platform (toInteger $ getKey (getUnique name))
; rep2_nwDsM mkNameLName [occ,uni] }
where
mod = assert (isExternalName name) nameModule name
@@ -3035,9 +3038,6 @@ coreIntLit :: Int -> MetaM (Core Int)
coreIntLit i = do platform <- getPlatform
return (MkC (mkIntExprInt platform i))
-coreIntegerLit :: MonadThings m => Integer -> m (Core Integer)
-coreIntegerLit i = pure (MkC (mkIntegerExpr i))
-
coreVar :: Id -> Core TH.Name -- The Id has type Name
coreVar id = MkC (Var id)
diff --git a/compiler/GHC/StgToByteCode.hs b/compiler/GHC/StgToByteCode.hs
index 1ba0687a9b..e056dadc2b 100644
--- a/compiler/GHC/StgToByteCode.hs
+++ b/compiler/GHC/StgToByteCode.hs
@@ -1716,11 +1716,9 @@ pushLiteral padded lit =
LitNumWord32 -> code Word32Rep
LitNumInt64 -> code Int64Rep
LitNumWord64 -> code Word64Rep
- -- No LitInteger's or LitNatural's should be left by the time this is
- -- called. CorePrep should have converted them all to a real core
- -- representation.
- LitNumInteger -> panic "pushAtom: LitInteger"
- LitNumNatural -> panic "pushAtom: LitNatural"
+ -- No LitNumBigNat should be left by the time this is called. CorePrep
+ -- should have converted them all to a real core representation.
+ LitNumBigNat -> panic "pushAtom: LitNumBigNat"
-- | Push an atom for constructor (i.e., PACK instruction) onto the stack.
-- This is slightly different to @pushAtom@ due to the fact that we allow
diff --git a/compiler/GHC/Tc/Instance/Class.hs b/compiler/GHC/Tc/Instance/Class.hs
index f80d3eaf93..757226ed28 100644
--- a/compiler/GHC/Tc/Instance/Class.hs
+++ b/compiler/GHC/Tc/Instance/Class.hs
@@ -359,8 +359,8 @@ matchKnownNat :: DynFlags
-> Bool -- True <=> caller is the short-cut solver
-- See Note [Shortcut solving: overlap]
-> Class -> [Type] -> TcM ClsInstResult
-matchKnownNat _ _ clas [ty] -- clas = KnownNat
- | Just n <- isNumLitTy ty = makeLitDict clas ty (mkNaturalExpr n)
+matchKnownNat dflags _ clas [ty] -- clas = KnownNat
+ | Just n <- isNumLitTy ty = makeLitDict clas ty (mkNaturalExpr (targetPlatform dflags) n)
matchKnownNat df sc clas tys = matchInstEnv df sc clas tys
-- See Note [Fabricating Evidence for Literals in Backpack] for why
-- this lookup into the instance environment is required.
diff --git a/compiler/GHC/Tc/Plugin.hs b/compiler/GHC/Tc/Plugin.hs
index a62ac86734..f65b30db27 100644
--- a/compiler/GHC/Tc/Plugin.hs
+++ b/compiler/GHC/Tc/Plugin.hs
@@ -24,6 +24,7 @@ module GHC.Tc.Plugin (
-- * Getting the TcM state
getTopEnv,
+ getTargetPlatform,
getEnvs,
getInstEnvs,
getFamInstEnvs,
@@ -51,6 +52,8 @@ module GHC.Tc.Plugin (
import GHC.Prelude
+import GHC.Platform (Platform)
+
import qualified GHC.Tc.Utils.Monad as TcM
import qualified GHC.Tc.Solver.Monad as TcS
import qualified GHC.Tc.Utils.Env as TcM
@@ -132,6 +135,10 @@ tcLookupId = unsafeTcPluginTcM . TcM.tcLookupId
getTopEnv :: TcPluginM HscEnv
getTopEnv = unsafeTcPluginTcM TcM.getTopEnv
+getTargetPlatform :: TcPluginM Platform
+getTargetPlatform = unsafeTcPluginTcM TcM.getPlatform
+
+
getEnvs :: TcPluginM (TcGblEnv, TcLclEnv)
getEnvs = unsafeTcPluginTcM TcM.getEnvs
diff --git a/compiler/GHC/Types/Literal.hs b/compiler/GHC/Types/Literal.hs
index 968e26c03b..4b6775cc58 100644
--- a/compiler/GHC/Types/Literal.hs
+++ b/compiler/GHC/Types/Literal.hs
@@ -31,7 +31,7 @@ module GHC.Types.Literal
, mkLitWord64, mkLitWord64Wrap, mkLitWord64Unchecked
, mkLitFloat, mkLitDouble
, mkLitChar, mkLitString
- , mkLitInteger, mkLitNatural
+ , mkLitBigNat
, mkLitNumber, mkLitNumberWrap
-- ** Operations on Literals
@@ -67,7 +67,6 @@ module GHC.Types.Literal
import GHC.Prelude
import GHC.Builtin.Types.Prim
-import {-# SOURCE #-} GHC.Builtin.Types
import GHC.Core.Type
import GHC.Utils.Outputable
import GHC.Data.FastString
@@ -162,8 +161,7 @@ data Literal
-- | Numeric literal type
data LitNumType
- = LitNumInteger -- ^ @Integer@ (see Note [BigNum literals])
- | LitNumNatural -- ^ @Natural@ (see Note [BigNum literals])
+ = LitNumBigNat -- ^ @Bignat@ (see Note [BigNum literals])
| LitNumInt -- ^ @Int#@ - according to target machine
| LitNumInt8 -- ^ @Int8#@ - exactly 8 bits
| LitNumInt16 -- ^ @Int16#@ - exactly 16 bits
@@ -179,8 +177,7 @@ data LitNumType
-- | Indicate if a numeric literal type supports negative numbers
litNumIsSigned :: LitNumType -> Bool
litNumIsSigned nt = case nt of
- LitNumInteger -> True
- LitNumNatural -> False
+ LitNumBigNat -> False
LitNumInt -> True
LitNumInt8 -> True
LitNumInt16 -> True
@@ -195,8 +192,7 @@ litNumIsSigned nt = case nt of
-- | Number of bits
litNumBitSize :: Platform -> LitNumType -> Maybe Word
litNumBitSize platform nt = case nt of
- LitNumInteger -> Nothing
- LitNumNatural -> Nothing
+ LitNumBigNat -> Nothing
LitNumInt -> Just (fromIntegral (platformWordSizeInBits platform))
LitNumInt8 -> Just 8
LitNumInt16 -> Just 16
@@ -217,16 +213,28 @@ instance Binary LitNumType where
{-
Note [BigNum literals]
~~~~~~~~~~~~~~~~~~~~~~
-GHC supports 2 kinds of arbitrary precision integers (a.k.a BigNum):
+GHC supports 2 kinds of arbitrary precision numbers (a.k.a BigNum):
- * Natural: natural represented as a Word# or as a BigNat
+ * data Natural = NS Word# | NB BigNat#
- * Integer: integer represented a an Int# or as a BigNat (Integer's
- constructors indicate the sign)
+ * data Integer = IS Int# | IN BigNat# | IP BigNat#
-BigNum literal instances are removed from Core during the CorePrep phase. They
-are replaced with expression to build them at runtime from machine literals
-(Word#, Int#, etc.) or from a list of Word#s.
+In the past, we had Core constructors to represent Integer and Natural literals.
+These literals were then lowered into their real Core representation only in
+Core prep. The issue with this approach is that literals have two
+representations and we have to ensure that we handle them the same everywhere
+(in every optimisation, etc.).
+
+For example (0 :: Integer) was representable in Core with both:
+
+ Lit (LitNumber LitNumInteger 0) -- literal
+ App (Var integerISDataCon) (Lit (LitNumber LitNumInt 0)) -- real representation
+
+Nowadays we always use the real representation for Integer and Natural literals.
+However we still have two representations for BigNat# literals. BigNat# literals
+are still lowered in Core prep into a call to a constructor function (BigNat# is
+ByteArray# and we don't have ByteArray# literals yet so we have to build them at
+runtime).
Note [String literals]
~~~~~~~~~~~~~~~~~~~~~~
@@ -340,9 +348,8 @@ mkLitNumberWrap platform nt i = case nt of
LitNumWord16 -> wrap @Word16
LitNumWord32 -> wrap @Word32
LitNumWord64 -> wrap @Word64
- LitNumInteger -> LitNumber nt i
- LitNumNatural
- | i < 0 -> panic "mkLitNumberWrap: trying to create a negative Natural"
+ LitNumBigNat
+ | i < 0 -> panic "mkLitNumberWrap: trying to create a negative BigNat"
| otherwise -> LitNumber nt i
where
wrap :: forall a. (Integral a, Num a) => Literal
@@ -389,8 +396,7 @@ litNumRange platform nt = case nt of
LitNumWord16 -> bounded_range @Word16
LitNumWord32 -> bounded_range @Word32
LitNumWord64 -> bounded_range @Word64
- LitNumNatural -> (Just 0, Nothing)
- LitNumInteger -> (Nothing, Nothing)
+ LitNumBigNat -> (Just 0, Nothing)
where
bounded_range :: forall a . (Integral a, Bounded a) => (Maybe Integer,Maybe Integer)
bounded_range = case boundedRange @a of
@@ -572,20 +578,14 @@ mkLitString :: String -> Literal
-- stored UTF-8 encoded
mkLitString s = LitString (bytesFS $ mkFastString s)
-mkLitInteger :: Integer -> Literal
-mkLitInteger x = LitNumber LitNumInteger x
-
-mkLitNatural :: Integer -> Literal
-mkLitNatural x = assertPpr (inNaturalRange x) (integer x)
- (LitNumber LitNumNatural x)
+mkLitBigNat :: Integer -> Literal
+mkLitBigNat x = assertPpr (x >= 0) (integer x)
+ (LitNumber LitNumBigNat x)
isLitRubbish :: Literal -> Bool
isLitRubbish (LitRubbish {}) = True
isLitRubbish _ = False
-inNaturalRange :: Integer -> Bool
-inNaturalRange x = x >= 0
-
inBoundedRange :: forall a. (Bounded a, Integral a) => Integer -> Bool
inBoundedRange x = x >= toInteger (minBound :: a) &&
x <= toInteger (maxBound :: a)
@@ -606,8 +606,7 @@ isMinBound platform (LitNumber nt i) = case nt of
LitNumWord16 -> i == 0
LitNumWord32 -> i == 0
LitNumWord64 -> i == 0
- LitNumNatural -> i == 0
- LitNumInteger -> False
+ LitNumBigNat -> i == 0
isMinBound _ _ = False
isMaxBound :: Platform -> Literal -> Bool
@@ -623,8 +622,7 @@ isMaxBound platform (LitNumber nt i) = case nt of
LitNumWord16 -> i == toInteger (maxBound :: Word16)
LitNumWord32 -> i == toInteger (maxBound :: Word32)
LitNumWord64 -> i == toInteger (maxBound :: Word64)
- LitNumNatural -> False
- LitNumInteger -> False
+ LitNumBigNat -> False
isMaxBound _ _ = False
inCharRange :: Char -> Bool
@@ -645,7 +643,7 @@ isOneLit (LitDouble 1) = True
isOneLit _ = False
-- | Returns the 'Integer' contained in the 'Literal', for when that makes
--- sense, i.e. for 'Char', 'Int', 'Word', 'LitInteger' and 'LitNatural'.
+-- sense, i.e. for 'Char' and numbers.
litValue :: Literal -> Integer
litValue l = case isLitValue_maybe l of
Just x -> x
@@ -769,8 +767,7 @@ litIsTrivial :: Literal -> Bool
-- c.f. GHC.Core.Utils.exprIsTrivial
litIsTrivial (LitString _) = False
litIsTrivial (LitNumber nt _) = case nt of
- LitNumInteger -> False
- LitNumNatural -> False
+ LitNumBigNat -> False
LitNumInt -> True
LitNumInt8 -> True
LitNumInt16 -> True
@@ -787,9 +784,8 @@ litIsTrivial _ = True
litIsDupable :: Platform -> Literal -> Bool
-- c.f. GHC.Core.Utils.exprIsDupable
litIsDupable platform x = case x of
- (LitNumber nt i) -> case nt of
- LitNumInteger -> platformInIntRange platform i
- LitNumNatural -> platformInWordRange platform i
+ LitNumber nt i -> case nt of
+ LitNumBigNat -> i <= platformMaxWord platform * 8 -- arbitrary, reasonable
LitNumInt -> True
LitNumInt8 -> True
LitNumInt16 -> True
@@ -800,8 +796,8 @@ litIsDupable platform x = case x of
LitNumWord16 -> True
LitNumWord32 -> True
LitNumWord64 -> True
- (LitString _) -> False
- _ -> True
+ LitString _ -> False
+ _ -> True
litFitsInChar :: Literal -> Bool
litFitsInChar (LitNumber _ i) = i >= toInteger (ord minBound)
@@ -810,8 +806,7 @@ litFitsInChar _ = False
litIsLifted :: Literal -> Bool
litIsLifted (LitNumber nt _) = case nt of
- LitNumInteger -> True
- LitNumNatural -> True
+ LitNumBigNat -> True
LitNumInt -> False
LitNumInt8 -> False
LitNumInt16 -> False
@@ -839,8 +834,7 @@ literalType (LitFloat _) = floatPrimTy
literalType (LitDouble _) = doublePrimTy
literalType (LitLabel _ _ _) = addrPrimTy
literalType (LitNumber lt _) = case lt of
- LitNumInteger -> integerTy
- LitNumNatural -> naturalTy
+ LitNumBigNat -> byteArrayPrimTy
LitNumInt -> intPrimTy
LitNumInt8 -> int8PrimTy
LitNumInt16 -> int16PrimTy
@@ -889,10 +883,9 @@ pprLiteral _ (LitString s) = pprHsBytes s
pprLiteral _ (LitNullAddr) = text "__NULL"
pprLiteral _ (LitFloat f) = float (fromRat f) <> primFloatSuffix
pprLiteral _ (LitDouble d) = double (fromRat d) <> primDoubleSuffix
-pprLiteral add_par (LitNumber nt i)
+pprLiteral _ (LitNumber nt i)
= case nt of
- LitNumInteger -> pprIntegerVal add_par i
- LitNumNatural -> pprIntegerVal add_par i
+ LitNumBigNat -> integer i
LitNumInt -> pprPrimInt i
LitNumInt8 -> pprPrimInt8 i
LitNumInt16 -> pprPrimInt16 i
@@ -911,17 +904,12 @@ pprLiteral add_par (LitLabel l mb fod) =
pprLiteral _ (LitRubbish rep)
= text "RUBBISH" <> parens (ppr rep)
-pprIntegerVal :: (SDoc -> SDoc) -> Integer -> SDoc
--- See Note [Printing of literals in Core].
-pprIntegerVal add_par i | i < 0 = add_par (integer i)
- | otherwise = integer i
-
{-
Note [Printing of literals in Core]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-The function `add_par` is used to wrap parenthesis around negative integers
-(`LitInteger`) and labels (`LitLabel`), if they occur in a context requiring
-an atomic thing (for example function application).
+The function `add_par` is used to wrap parenthesis around labels (`LitLabel`),
+if they occur in a context requiring an atomic thing (for example function
+application).
Although not all Core literals would be valid Haskell, we are trying to stay
as close as possible to Haskell syntax in the printing of Core, to make it
@@ -949,7 +937,7 @@ LitWord 1##
LitWordN 1##N
LitFloat -1.0#
LitDouble -1.0##
-LitInteger -1 (-1)
+LitBigNat 1
LitLabel "__label" ... ("__label" ...)
LitRubbish "RUBBISH[...]"
diff --git a/testsuite/tests/lib/integer/all.T b/testsuite/tests/lib/integer/all.T
index 4366955e81..96cb055b9c 100644
--- a/testsuite/tests/lib/integer/all.T
+++ b/testsuite/tests/lib/integer/all.T
@@ -5,12 +5,7 @@ test('plusMinusInteger', [omit_ways(['ghci'])], compile_and_run, [''])
test('integerConstantFolding', normal, makefile_test, ['integerConstantFolding'])
test('naturalConstantFolding', normal, makefile_test, ['naturalConstantFolding'])
-# we ignore_stderr because there are 2 overlapping rules that are reported in
-# debug mode:
-# Rules.findBest: rule overlap (Rule 1 wins)
-# Rule 1: "Integer -> Int# (wrap)"
-# Rule 2: "Int# -> Integer -> Int#"
-test('fromToInteger', [ignore_stderr], makefile_test, ['fromToInteger'])
+test('fromToInteger', normal, makefile_test, ['fromToInteger'])
test('IntegerConversionRules', [], makefile_test, ['IntegerConversionRules'])
test('gcdInteger', normal, compile_and_run, [''])
diff --git a/testsuite/tests/numeric/should_compile/T14170.stdout b/testsuite/tests/numeric/should_compile/T14170.stdout
index a4fe7ecd7b..89e0f1b461 100644
--- a/testsuite/tests/numeric/should_compile/T14170.stdout
+++ b/testsuite/tests/numeric/should_compile/T14170.stdout
@@ -1,7 +1,7 @@
==================== Tidy Core ====================
Result size of Tidy Core
- = {terms: 16, types: 6, coercions: 0, joins: 0/0}
+ = {terms: 17, types: 6, coercions: 0, joins: 0/0}
NatVal.$trModule4 :: GHC.Prim.Addr#
[GblId,
@@ -37,8 +37,8 @@ NatVal.$trModule
foo :: Integer
[GblId,
Unf=Unf{Src=<vanilla>, TopLvl=True, Value=True, ConLike=True,
- WorkFree=True, Expandable=True, Guidance=IF_ARGS [] 100 0}]
-foo = 0
+ WorkFree=True, Expandable=True, Guidance=IF_ARGS [] 10 10}]
+foo = GHC.Num.Integer.IS 0#
diff --git a/testsuite/tests/numeric/should_compile/T14465.stdout b/testsuite/tests/numeric/should_compile/T14465.stdout
index 808b75f633..de0c34607d 100644
--- a/testsuite/tests/numeric/should_compile/T14465.stdout
+++ b/testsuite/tests/numeric/should_compile/T14465.stdout
@@ -1,7 +1,7 @@
==================== Tidy Core ====================
Result size of Tidy Core
- = {terms: 35, types: 14, coercions: 0, joins: 0/0}
+ = {terms: 37, types: 14, coercions: 0, joins: 0/0}
ten :: Natural
[GblId,
@@ -42,8 +42,8 @@ M.$trModule = GHC.Types.Module M.$trModule3 M.$trModule1
M.minusOne1 :: Natural
[GblId,
Unf=Unf{Src=<vanilla>, TopLvl=True, Value=True, ConLike=True,
- WorkFree=True, Expandable=True, Guidance=IF_ARGS [] 100 0}]
-M.minusOne1 = 1
+ WorkFree=True, Expandable=True, Guidance=IF_ARGS [] 10 10}]
+M.minusOne1 = GHC.Num.Natural.NS 1##
minusOne :: Natural
[GblId,
@@ -58,8 +58,8 @@ minusOne
twoTimesTwo :: Natural
[GblId,
Unf=Unf{Src=<vanilla>, TopLvl=True, Value=True, ConLike=True,
- WorkFree=True, Expandable=True, Guidance=IF_ARGS [] 100 0}]
-twoTimesTwo = 4
+ WorkFree=True, Expandable=True, Guidance=IF_ARGS [] 10 10}]
+twoTimesTwo = GHC.Num.Natural.NS 4##
plusOne :: Natural -> Natural
[GblId,
diff --git a/testsuite/tests/numeric/should_compile/T20245.hs b/testsuite/tests/numeric/should_compile/T20245.hs
new file mode 100644
index 0000000000..1196987cf9
--- /dev/null
+++ b/testsuite/tests/numeric/should_compile/T20245.hs
@@ -0,0 +1,9 @@
+module T20245 where
+
+import GHC.Num.Integer
+
+foo :: Int
+foo = case 2 of
+ IS _ -> 9999
+ IP _ -> 7777
+ IN _ -> 7777
diff --git a/testsuite/tests/numeric/should_compile/T20245.stderr b/testsuite/tests/numeric/should_compile/T20245.stderr
new file mode 100644
index 0000000000..e3fe0ed315
--- /dev/null
+++ b/testsuite/tests/numeric/should_compile/T20245.stderr
@@ -0,0 +1,9 @@
+
+==================== Tidy Core ====================
+Result size of Tidy Core
+ = {terms: 3, types: 1, coercions: 0, joins: 0/0}
+
+foo = I# 9999#
+
+
+
diff --git a/testsuite/tests/numeric/should_compile/all.T b/testsuite/tests/numeric/should_compile/all.T
index 425d0dbd85..c95296fcde 100644
--- a/testsuite/tests/numeric/should_compile/all.T
+++ b/testsuite/tests/numeric/should_compile/all.T
@@ -11,3 +11,4 @@ test('T10929', normal, compile, [''])
test('T16402', [ grep_errmsg(r'and'), when(wordsize(32), expect_broken(19024)) ], compile, [''])
test('T19892', normal, compile, ['-O -ddump-rule-firings'])
test('T20062', [ grep_errmsg(r'integer') ], compile, ['-ddump-simpl -O -dsuppress-all'])
+test('T20245', normal, compile, ['-ddump-simpl -O -dsuppress-all -dno-typeable-binds'])
diff --git a/testsuite/tests/simplCore/should_compile/T15445.stderr b/testsuite/tests/simplCore/should_compile/T15445.stderr
index 3421b37072..5e8a086e6d 100644
--- a/testsuite/tests/simplCore/should_compile/T15445.stderr
+++ b/testsuite/tests/simplCore/should_compile/T15445.stderr
@@ -1,6 +1,6 @@
Rule fired: Class op + (BUILTIN)
Rule fired: Class op fromInteger (BUILTIN)
-Rule fired: Integer -> Int# (wrap) (BUILTIN)
+Rule fired: Int# -> Integer -> Int# (GHC.Num.Integer)
Rule fired: SPEC plusTwoRec (T15445a)
Rule fired: SPEC $fShow[] (GHC.Show)
Rule fired: Class op >> (BUILTIN)
diff --git a/testsuite/tests/simplCore/should_compile/T8832.stdout-ws-32 b/testsuite/tests/simplCore/should_compile/T8832.stdout-ws-32
index 459d2689c7..53b2c046c1 100644
--- a/testsuite/tests/simplCore/should_compile/T8832.stdout-ws-32
+++ b/testsuite/tests/simplCore/should_compile/T8832.stdout-ws-32
@@ -6,4 +6,4 @@ w = GHC.Types.W# 0##
w8 = GHC.Word.W8# 0##8
w16 = GHC.Word.W16# 0##16
w32 = GHC.Word.W32# 0##32
-z = 0
+z = GHC.Num.Integer.IS 0#
diff --git a/testsuite/tests/simplCore/should_compile/T8832.stdout-ws-64 b/testsuite/tests/simplCore/should_compile/T8832.stdout-ws-64
index 657f517c68..625102854d 100644
--- a/testsuite/tests/simplCore/should_compile/T8832.stdout-ws-64
+++ b/testsuite/tests/simplCore/should_compile/T8832.stdout-ws-64
@@ -8,4 +8,4 @@ w8 = GHC.Word.W8# 0##8
w16 = GHC.Word.W16# 0##16
w32 = GHC.Word.W32# 0##32
w64 = GHC.Word.W64# 0##
-z = 0
+z = GHC.Num.Integer.IS 0#
diff --git a/testsuite/tests/tcplugins/ArgsPlugin.hs b/testsuite/tests/tcplugins/ArgsPlugin.hs
index c25c8dc8a3..19e99bedd0 100644
--- a/testsuite/tests/tcplugins/ArgsPlugin.hs
+++ b/testsuite/tests/tcplugins/ArgsPlugin.hs
@@ -22,13 +22,15 @@ import GHC.Core.Type
import GHC.Plugins
( Plugin )
import GHC.Tc.Plugin
- ( TcPluginM )
+ ( TcPluginM, getTargetPlatform )
import GHC.Tc.Types
( TcPluginSolveResult(..) )
import GHC.Tc.Types.Constraint
( Ct(..) )
import GHC.Tc.Types.Evidence
( EvBindsVar, EvTerm(EvExpr) )
+import GHC.Platform
+ ( Platform )
-- common
import Common
@@ -62,11 +64,12 @@ solver args defs _ev _gs _ds ws = do
argsVal = case args of
arg : _ -> read arg
_ -> error "ArgsPlugin: expected at least one argument"
- solved <- catMaybes <$> traverse ( solveCt defs argsVal ) ws
+ platform <- getTargetPlatform
+ solved <- catMaybes <$> traverse ( solveCt platform defs argsVal ) ws
pure $ TcPluginOk solved []
-solveCt :: PluginDefs -> Integer -> Ct -> TcPluginM ( Maybe (EvTerm, Ct) )
-solveCt ( PluginDefs {..} ) i ct@( CDictCan { cc_class, cc_tyargs } )
+solveCt :: Platform -> PluginDefs -> Integer -> Ct -> TcPluginM ( Maybe (EvTerm, Ct) )
+solveCt platform ( PluginDefs {..} ) i ct@( CDictCan { cc_class, cc_tyargs } )
| className cc_class == className myClass
, [tyArg] <- cc_tyargs
, tyArg `eqType` integerTy
@@ -74,6 +77,6 @@ solveCt ( PluginDefs {..} ) i ct@( CDictCan { cc_class, cc_tyargs } )
evTerm :: EvTerm
evTerm = EvExpr $
mkCoreConApps ( classDataCon cc_class )
- [ Type integerTy, mkIntegerExpr i ]
+ [ Type integerTy, mkIntegerExpr platform i ]
= pure $ Just ( evTerm, ct )
-solveCt _ _ ct = pure Nothing
+solveCt _ _ _ ct = pure Nothing