diff options
author | Sylvain Henry <hsyl20@gmail.com> | 2018-06-15 16:23:53 -0400 |
---|---|---|
committer | Ben Gamari <ben@smart-cactus.org> | 2018-06-15 16:23:54 -0400 |
commit | fe770c211631e7b4c9b0b1e88ef9b6046c6585ef (patch) | |
tree | e6a061a92d8d0d71d40c699982ee471627d816e0 /compiler | |
parent | 42f3b53b5bc4674e41f16de08094821fe1aaec00 (diff) | |
download | haskell-fe770c211631e7b4c9b0b1e88ef9b6046c6585ef.tar.gz |
Built-in Natural literals in Core
Add support for built-in Natural literals in Core.
- Replace MachInt,MachWord, LitInteger, etc. with a single LitNumber
constructor with a LitNumType field
- Support built-in Natural literals
- Add desugar warning for negative literals
- Move Maybe(..) from GHC.Base to GHC.Maybe for module dependency
reasons
This patch introduces only a few rules for Natural literals (compared
to Integer's rules). Factorization of the built-in rules for numeric
literals will be done in another patch as this one is already big to
review.
Test Plan:
validate
test build with integer-simple
Reviewers: hvr, bgamari, goldfire, Bodigrim, simonmar
Reviewed By: bgamari
Subscribers: phadej, simonpj, RyanGlScott, carter, hsyl20, rwbarton,
thomie
GHC Trac Issues: #14170, #14465
Differential Revision: https://phabricator.haskell.org/D4212
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/basicTypes/Literal.hs | 409 | ||||
-rw-r--r-- | compiler/codeGen/StgCmmCon.hs | 2 | ||||
-rw-r--r-- | compiler/codeGen/StgCmmUtils.hs | 11 | ||||
-rw-r--r-- | compiler/coreSyn/CorePrep.hs | 76 | ||||
-rw-r--r-- | compiler/coreSyn/CoreUnfold.hs | 3 | ||||
-rw-r--r-- | compiler/coreSyn/CoreUtils.hs | 19 | ||||
-rw-r--r-- | compiler/coreSyn/MkCore.hs | 10 | ||||
-rw-r--r-- | compiler/deSugar/MatchLit.hs | 86 | ||||
-rw-r--r-- | compiler/ghci/ByteCodeAsm.hs | 12 | ||||
-rw-r--r-- | compiler/ghci/ByteCodeGen.hs | 42 | ||||
-rw-r--r-- | compiler/iface/TcIface.hs | 8 | ||||
-rw-r--r-- | compiler/main/TidyPgm.hs | 103 | ||||
-rw-r--r-- | compiler/prelude/PrelNames.hs | 39 | ||||
-rw-r--r-- | compiler/prelude/PrelRules.hs | 220 | ||||
-rw-r--r-- | compiler/prelude/TysWiredIn.hs | 6 | ||||
-rw-r--r-- | compiler/simplStg/UnariseStg.hs | 12 | ||||
-rw-r--r-- | compiler/stgSyn/CoreToStg.hs | 7 |
17 files changed, 664 insertions, 401 deletions
diff --git a/compiler/basicTypes/Literal.hs b/compiler/basicTypes/Literal.hs index 0392a98274..21f4a92290 100644 --- a/compiler/basicTypes/Literal.hs +++ b/compiler/basicTypes/Literal.hs @@ -5,12 +5,13 @@ \section[Literal]{@Literal@: Machine literals (unboxed, of course)} -} -{-# LANGUAGE CPP, DeriveDataTypeable #-} +{-# LANGUAGE CPP, DeriveDataTypeable, ScopedTypeVariables #-} module Literal ( -- * Main data type Literal(..) -- Exported to ParseIface + , LitNumType(..) -- ** Creating Literals , mkMachInt, mkMachIntWrap, mkMachIntWrapC @@ -19,12 +20,15 @@ module Literal , mkMachWord64, mkMachWord64Wrap , mkMachFloat, mkMachDouble , mkMachChar, mkMachString - , mkLitInteger + , mkLitInteger, mkLitNatural + , mkLitNumber, mkLitNumberWrap -- ** Operations on Literals , literalType , absentLiteralOf , pprLiteral + , litNumIsSigned + , litNumCheckRange -- ** Predicates on Literals and their contents , litIsDupable, litIsTrivial, litIsLifted @@ -35,6 +39,7 @@ module Literal -- ** Coercions , word2IntLit, int2WordLit + , narrowLit , narrow8IntLit, narrow16IntLit, narrow32IntLit , narrow8WordLit, narrow16WordLit, narrow32WordLit , char2IntLit, int2CharLit @@ -66,6 +71,7 @@ import Data.Word import Data.Char import Data.Maybe ( isJust ) import Data.Data ( Data ) +import Data.Proxy import Numeric ( fromRat ) {- @@ -95,6 +101,10 @@ data Literal -- First the primitive guys MachChar Char -- ^ @Char#@ - at least 31 bits. Create with 'mkMachChar' + | LitNumber !LitNumType !Integer Type + -- ^ Any numeric literal that can be + -- internally represented with an Integer + | MachStr ByteString -- ^ A string-literal: stored and emitted -- UTF-8 encoded, we'll arrange to decode it -- at runtime. Also emitted with a @'\0'@ @@ -104,11 +114,6 @@ data Literal -- that can be represented as a Literal. Create -- with 'nullAddrLit' - | MachInt Integer -- ^ @Int#@ - according to target machine - | MachInt64 Integer -- ^ @Int64#@ - exactly 64 bits - | MachWord Integer -- ^ @Word#@ - according to target machine - | MachWord64 Integer -- ^ @Word64#@ - exactly 64 bits - | MachFloat Rational -- ^ @Float#@. Create with 'mkMachFloat' | MachDouble Rational -- ^ @Double#@. Create with 'mkMachDouble' @@ -123,11 +128,28 @@ data Literal -- the label expects. Only applicable with -- @stdcall@ labels. @Just x@ => @\<x\>@ will -- be appended to label name when emitting assembly. - - | LitInteger Integer Type -- ^ Integer literals - -- See Note [Integer literals] deriving Data +-- | Numeric literal type +data LitNumType + = LitNumInteger -- ^ @Integer@ (see Note [Integer literals]) + | LitNumNatural -- ^ @Natural@ (see Note [Natural literals]) + | LitNumInt -- ^ @Int#@ - according to target machine + | LitNumInt64 -- ^ @Int64#@ - exactly 64 bits + | LitNumWord -- ^ @Word#@ - according to target machine + | LitNumWord64 -- ^ @Word64#@ - exactly 64 bits + deriving (Data,Enum,Eq,Ord) + +-- | Indicate if a numeric literal type supports negative numbers +litNumIsSigned :: LitNumType -> Bool +litNumIsSigned nt = case nt of + LitNumInteger -> True + LitNumNatural -> False + LitNumInt -> True + LitNumInt64 -> True + LitNumWord -> False + LitNumWord64 -> False + {- Note [Integer literals] ~~~~~~~~~~~~~~~~~~~~~~~ @@ -146,26 +168,33 @@ below), we don't have convenient access to the mkInteger Id. So we just use an error thunk, and fill in the real Id when we do tcIfaceLit in TcIface. +Note [Natural literals] +~~~~~~~~~~~~~~~~~~~~~~~ +Similar to Integer literals. -Binary instance -} +instance Binary LitNumType where + put_ bh numTyp = putByte bh (fromIntegral (fromEnum numTyp)) + get bh = do + h <- getByte bh + return (toEnum (fromIntegral h)) + instance Binary Literal where put_ bh (MachChar aa) = do putByte bh 0; put_ bh aa put_ bh (MachStr ab) = do putByte bh 1; put_ bh ab put_ bh (MachNullAddr) = do putByte bh 2 - put_ bh (MachInt ad) = do putByte bh 3; put_ bh ad - put_ bh (MachInt64 ae) = do putByte bh 4; put_ bh ae - put_ bh (MachWord af) = do putByte bh 5; put_ bh af - put_ bh (MachWord64 ag) = do putByte bh 6; put_ bh ag - put_ bh (MachFloat ah) = do putByte bh 7; put_ bh ah - put_ bh (MachDouble ai) = do putByte bh 8; put_ bh ai + put_ bh (MachFloat ah) = do putByte bh 3; put_ bh ah + put_ bh (MachDouble ai) = do putByte bh 4; put_ bh ai put_ bh (MachLabel aj mb fod) - = do putByte bh 9 + = do putByte bh 5 put_ bh aj put_ bh mb put_ bh fod - put_ bh (LitInteger i _) = do putByte bh 10; put_ bh i + put_ bh (LitNumber nt i _) + = do putByte bh 6 + put_ bh nt + put_ bh i get bh = do h <- getByte bh case h of @@ -178,32 +207,31 @@ instance Binary Literal where 2 -> do return (MachNullAddr) 3 -> do - ad <- get bh - return (MachInt ad) - 4 -> do - ae <- get bh - return (MachInt64 ae) - 5 -> do - af <- get bh - return (MachWord af) - 6 -> do - ag <- get bh - return (MachWord64 ag) - 7 -> do ah <- get bh return (MachFloat ah) - 8 -> do + 4 -> do ai <- get bh return (MachDouble ai) - 9 -> do + 5 -> do aj <- get bh mb <- get bh fod <- get bh return (MachLabel aj mb fod) _ -> do - i <- get bh - -- See Note [Integer literals] - return $ mkLitInteger i (panic "Evaluated the place holder for mkInteger") + nt <- get bh + i <- get bh + let t = case nt of + LitNumInt -> intPrimTy + LitNumInt64 -> int64PrimTy + LitNumWord -> wordPrimTy + LitNumWord64 -> word64PrimTy + -- See Note [Integer literals] + LitNumInteger -> + panic "Evaluated the place holder for mkInteger" + -- and Note [Natural literals] + LitNumNatural -> + panic "Evaluated the place holder for mkNatural" + return (LitNumber nt i t) instance Outputable Literal where ppr lit = pprLiteral (\d -> d) lit @@ -242,79 +270,116 @@ doesn't yield a warning. Instead we simply squash the value into the *target* Int/Word range. -} +-- | Wrap a literal number according to its type +wrapLitNumber :: DynFlags -> Literal -> Literal +wrapLitNumber dflags v@(LitNumber nt i t) = case nt of + LitNumInt -> case platformWordSize (targetPlatform dflags) of + 4 -> LitNumber nt (toInteger (fromIntegral i :: Int32)) t + 8 -> LitNumber nt (toInteger (fromIntegral i :: Int64)) t + w -> panic ("wrapLitNumber: Unknown platformWordSize: " ++ show w) + LitNumWord -> case platformWordSize (targetPlatform dflags) of + 4 -> LitNumber nt (toInteger (fromIntegral i :: Word32)) t + 8 -> LitNumber nt (toInteger (fromIntegral i :: Word64)) t + w -> panic ("wrapLitNumber: Unknown platformWordSize: " ++ show w) + LitNumInt64 -> LitNumber nt (toInteger (fromIntegral i :: Int64)) t + LitNumWord64 -> LitNumber nt (toInteger (fromIntegral i :: Word64)) t + LitNumInteger -> v + LitNumNatural -> v +wrapLitNumber _ x = x + +-- | Create a numeric 'Literal' of the given type +mkLitNumberWrap :: DynFlags -> LitNumType -> Integer -> Type -> Literal +mkLitNumberWrap dflags nt i t = wrapLitNumber dflags (LitNumber nt i t) + +-- | Check that a given number is in the range of a numeric literal +litNumCheckRange :: DynFlags -> LitNumType -> Integer -> Bool +litNumCheckRange dflags nt i = case nt of + LitNumInt -> inIntRange dflags i + LitNumWord -> inWordRange dflags i + LitNumInt64 -> inInt64Range i + LitNumWord64 -> inWord64Range i + LitNumNatural -> i >= 0 + LitNumInteger -> True + +-- | Create a numeric 'Literal' of the given type +mkLitNumber :: DynFlags -> LitNumType -> Integer -> Type -> Literal +mkLitNumber dflags nt i t = + ASSERT2(litNumCheckRange dflags nt i, integer i) + (LitNumber nt i t) + -- | Creates a 'Literal' of type @Int#@ mkMachInt :: DynFlags -> Integer -> Literal mkMachInt dflags x = ASSERT2( inIntRange dflags x, integer x ) - MachInt x - -wrapInt :: DynFlags -> Integer -> Integer -wrapInt dflags i - = case platformWordSize (targetPlatform dflags) of - 4 -> toInteger (fromIntegral i :: Int32) - 8 -> toInteger (fromIntegral i :: Int64) - w -> panic ("toIntRange: Unknown platformWordSize: " ++ show w) + (mkMachIntUnchecked x) -- | Creates a 'Literal' of type @Int#@. -- If the argument is out of the (target-dependent) range, it is wrapped. -- See Note [Word/Int underflow/overflow] mkMachIntWrap :: DynFlags -> Integer -> Literal -mkMachIntWrap dflags i = MachInt (wrapInt dflags i) +mkMachIntWrap dflags i = wrapLitNumber dflags $ mkMachIntUnchecked i + +-- | Creates a 'Literal' of type @Int#@ without checking its range. +mkMachIntUnchecked :: Integer -> Literal +mkMachIntUnchecked i = LitNumber LitNumInt i intPrimTy -- | Creates a 'Literal' of type @Int#@, as well as a 'Bool'ean flag indicating -- overflow. That is, if the argument is out of the (target-dependent) range -- the argument is wrapped and the overflow flag will be set. -- See Note [Word/Int underflow/overflow] mkMachIntWrapC :: DynFlags -> Integer -> (Literal, Bool) -mkMachIntWrapC dflags i = (MachInt i', i /= i') +mkMachIntWrapC dflags i = (n, i /= i') where - i' = wrapInt dflags i + n@(LitNumber _ i' _) = mkMachIntWrap dflags i -- | Creates a 'Literal' of type @Word#@ mkMachWord :: DynFlags -> Integer -> Literal mkMachWord dflags x = ASSERT2( inWordRange dflags x, integer x ) - MachWord x - -wrapWord :: DynFlags -> Integer -> Integer -wrapWord dflags i - = case platformWordSize (targetPlatform dflags) of - 4 -> toInteger (fromIntegral i :: Word32) - 8 -> toInteger (fromIntegral i :: Word64) - w -> panic ("toWordRange: Unknown platformWordSize: " ++ show w) + (mkMachWordUnchecked x) -- | Creates a 'Literal' of type @Word#@. -- If the argument is out of the (target-dependent) range, it is wrapped. -- See Note [Word/Int underflow/overflow] mkMachWordWrap :: DynFlags -> Integer -> Literal -mkMachWordWrap dflags i = MachWord (wrapWord dflags i) +mkMachWordWrap dflags i = wrapLitNumber dflags $ mkMachWordUnchecked i + +-- | Creates a 'Literal' of type @Word#@ without checking its range. +mkMachWordUnchecked :: Integer -> Literal +mkMachWordUnchecked i = LitNumber LitNumWord i wordPrimTy -- | Creates a 'Literal' of type @Word#@, as well as a 'Bool'ean flag indicating -- carry. That is, if the argument is out of the (target-dependent) range -- the argument is wrapped and the carry flag will be set. -- See Note [Word/Int underflow/overflow] mkMachWordWrapC :: DynFlags -> Integer -> (Literal, Bool) -mkMachWordWrapC dflags i = (MachWord i', i /= i') +mkMachWordWrapC dflags i = (n, i /= i') where - i' = wrapWord dflags i + n@(LitNumber _ i' _) = mkMachWordWrap dflags i -- | Creates a 'Literal' of type @Int64#@ mkMachInt64 :: Integer -> Literal -mkMachInt64 x = ASSERT2( inInt64Range x, integer x ) - MachInt64 x +mkMachInt64 x = ASSERT2( inInt64Range x, integer x ) (mkMachInt64Unchecked x) -- | Creates a 'Literal' of type @Int64#@. -- If the argument is out of the range, it is wrapped. -mkMachInt64Wrap :: Integer -> Literal -mkMachInt64Wrap i = MachInt64 (toInteger (fromIntegral i :: Int64)) +mkMachInt64Wrap :: DynFlags -> Integer -> Literal +mkMachInt64Wrap dflags i = wrapLitNumber dflags $ mkMachInt64Unchecked i + +-- | Creates a 'Literal' of type @Int64#@ without checking its range. +mkMachInt64Unchecked :: Integer -> Literal +mkMachInt64Unchecked i = LitNumber LitNumInt64 i int64PrimTy -- | Creates a 'Literal' of type @Word64#@ mkMachWord64 :: Integer -> Literal -mkMachWord64 x = ASSERT2( inWord64Range x, integer x ) - MachWord64 x +mkMachWord64 x = ASSERT2( inWord64Range x, integer x ) (mkMachWord64Unchecked x) -- | Creates a 'Literal' of type @Word64#@. -- If the argument is out of the range, it is wrapped. -mkMachWord64Wrap :: Integer -> Literal -mkMachWord64Wrap i = MachWord64 (toInteger (fromIntegral i :: Word64)) +mkMachWord64Wrap :: DynFlags -> Integer -> Literal +mkMachWord64Wrap dflags i = wrapLitNumber dflags $ mkMachWord64Unchecked i + +-- | Creates a 'Literal' of type @Word64#@ without checking its range. +mkMachWord64Unchecked :: Integer -> Literal +mkMachWord64Unchecked i = LitNumber LitNumWord64 i word64PrimTy -- | Creates a 'Literal' of type @Float#@ mkMachFloat :: Rational -> Literal @@ -335,12 +400,19 @@ mkMachString :: String -> Literal mkMachString s = MachStr (fastStringToByteString $ mkFastString s) mkLitInteger :: Integer -> Type -> Literal -mkLitInteger = LitInteger +mkLitInteger x ty = LitNumber LitNumInteger x ty + +mkLitNatural :: Integer -> Type -> Literal +mkLitNatural x ty = ASSERT2( inNaturalRange x, integer x ) + (LitNumber LitNumNatural x ty) inIntRange, inWordRange :: DynFlags -> Integer -> Bool inIntRange dflags x = x >= tARGET_MIN_INT dflags && x <= tARGET_MAX_INT dflags inWordRange dflags x = x >= 0 && x <= tARGET_MAX_WORD dflags +inNaturalRange :: Integer -> Bool +inNaturalRange x = x >= 0 + inInt64Range, inWord64Range :: Integer -> Bool inInt64Range x = x >= toInteger (minBound :: Int64) && x <= toInteger (maxBound :: Int64) @@ -352,49 +424,39 @@ inCharRange c = c >= '\0' && c <= chr tARGET_MAX_CHAR -- | Tests whether the literal represents a zero of whatever type it is isZeroLit :: Literal -> Bool -isZeroLit (MachInt 0) = True -isZeroLit (MachInt64 0) = True -isZeroLit (MachWord 0) = True -isZeroLit (MachWord64 0) = True -isZeroLit (MachFloat 0) = True -isZeroLit (MachDouble 0) = True -isZeroLit _ = False +isZeroLit (LitNumber _ 0 _) = True +isZeroLit (MachFloat 0) = True +isZeroLit (MachDouble 0) = True +isZeroLit _ = False -- | Returns the 'Integer' contained in the 'Literal', for when that makes --- sense, i.e. for 'Char', 'Int', 'Word' and 'LitInteger'. +-- sense, i.e. for 'Char', 'Int', 'Word', 'LitInteger' and 'LitNatural'. litValue :: Literal -> Integer litValue l = case isLitValue_maybe l of Just x -> x Nothing -> pprPanic "litValue" (ppr l) -- | Returns the 'Integer' contained in the 'Literal', for when that makes --- sense, i.e. for 'Char', 'Int', 'Word' and 'LitInteger'. +-- sense, i.e. for 'Char' and numbers. isLitValue_maybe :: Literal -> Maybe Integer -isLitValue_maybe (MachChar c) = Just $ toInteger $ ord c -isLitValue_maybe (MachInt i) = Just i -isLitValue_maybe (MachInt64 i) = Just i -isLitValue_maybe (MachWord i) = Just i -isLitValue_maybe (MachWord64 i) = Just i -isLitValue_maybe (LitInteger i _) = Just i -isLitValue_maybe _ = Nothing +isLitValue_maybe (MachChar c) = Just $ toInteger $ ord c +isLitValue_maybe (LitNumber _ i _) = Just i +isLitValue_maybe _ = Nothing -- | Apply a function to the 'Integer' contained in the 'Literal', for when that --- makes sense, e.g. for 'Char', 'Int', 'Word' and 'LitInteger'. For --- fixed-size integral literals, the result will be wrapped in --- accordance with the semantics of the target type. +-- makes sense, e.g. for 'Char' and numbers. +-- For fixed-size integral literals, the result will be wrapped in accordance +-- with the semantics of the target type. -- See Note [Word/Int underflow/overflow] mapLitValue :: DynFlags -> (Integer -> Integer) -> Literal -> Literal -mapLitValue _ f (MachChar c) = mkMachChar (fchar c) +mapLitValue _ f (MachChar c) = mkMachChar (fchar c) where fchar = chr . fromInteger . f . toInteger . ord -mapLitValue dflags f (MachInt i) = mkMachIntWrap dflags (f i) -mapLitValue _ f (MachInt64 i) = mkMachInt64Wrap (f i) -mapLitValue dflags f (MachWord i) = mkMachWordWrap dflags (f i) -mapLitValue _ f (MachWord64 i) = mkMachWord64Wrap (f i) -mapLitValue _ f (LitInteger i t) = mkLitInteger (f i) t -mapLitValue _ _ l = pprPanic "mapLitValue" (ppr l) +mapLitValue dflags f (LitNumber nt i t) = wrapLitNumber dflags + (LitNumber nt (f i) t) +mapLitValue _ _ l = pprPanic "mapLitValue" (ppr l) -- | Indicate if the `Literal` contains an 'Integer' value, e.g. 'Char', --- 'Int', 'Word' and 'LitInteger'. +-- 'Int', 'Word', 'LitInteger' and 'LitNatural'. isLitValue :: Literal -> Bool isLitValue = isJust . isLitValue_maybe @@ -411,43 +473,42 @@ narrow8IntLit, narrow16IntLit, narrow32IntLit, :: Literal -> Literal word2IntLit, int2WordLit :: DynFlags -> Literal -> Literal -word2IntLit dflags (MachWord w) - | w > tARGET_MAX_INT dflags = MachInt (w - tARGET_MAX_WORD dflags - 1) - | otherwise = MachInt w +word2IntLit dflags (LitNumber LitNumWord w _) + | w > tARGET_MAX_INT dflags = mkMachInt dflags (w - tARGET_MAX_WORD dflags - 1) + | otherwise = mkMachInt dflags w word2IntLit _ l = pprPanic "word2IntLit" (ppr l) -int2WordLit dflags (MachInt i) - | i < 0 = MachWord (1 + tARGET_MAX_WORD dflags + i) -- (-1) ---> tARGET_MAX_WORD - | otherwise = MachWord i +int2WordLit dflags (LitNumber LitNumInt i _) + | i < 0 = mkMachWord dflags (1 + tARGET_MAX_WORD dflags + i) -- (-1) ---> tARGET_MAX_WORD + | otherwise = mkMachWord dflags i int2WordLit _ l = pprPanic "int2WordLit" (ppr l) -narrow8IntLit (MachInt i) = MachInt (toInteger (fromInteger i :: Int8)) -narrow8IntLit l = pprPanic "narrow8IntLit" (ppr l) -narrow16IntLit (MachInt i) = MachInt (toInteger (fromInteger i :: Int16)) -narrow16IntLit l = pprPanic "narrow16IntLit" (ppr l) -narrow32IntLit (MachInt i) = MachInt (toInteger (fromInteger i :: Int32)) -narrow32IntLit l = pprPanic "narrow32IntLit" (ppr l) -narrow8WordLit (MachWord w) = MachWord (toInteger (fromInteger w :: Word8)) -narrow8WordLit l = pprPanic "narrow8WordLit" (ppr l) -narrow16WordLit (MachWord w) = MachWord (toInteger (fromInteger w :: Word16)) -narrow16WordLit l = pprPanic "narrow16WordLit" (ppr l) -narrow32WordLit (MachWord w) = MachWord (toInteger (fromInteger w :: Word32)) -narrow32WordLit l = pprPanic "narrow32WordLit" (ppr l) - -char2IntLit (MachChar c) = MachInt (toInteger (ord c)) +-- | Narrow a literal number (unchecked result range) +narrowLit :: forall a. Integral a => Proxy a -> Literal -> Literal +narrowLit _ (LitNumber nt i t) = LitNumber nt (toInteger (fromInteger i :: a)) t +narrowLit _ l = pprPanic "narrowLit" (ppr l) + +narrow8IntLit = narrowLit (Proxy :: Proxy Int8) +narrow16IntLit = narrowLit (Proxy :: Proxy Int16) +narrow32IntLit = narrowLit (Proxy :: Proxy Int32) +narrow8WordLit = narrowLit (Proxy :: Proxy Word8) +narrow16WordLit = narrowLit (Proxy :: Proxy Word16) +narrow32WordLit = narrowLit (Proxy :: Proxy Word32) + +char2IntLit (MachChar c) = mkMachIntUnchecked (toInteger (ord c)) char2IntLit l = pprPanic "char2IntLit" (ppr l) -int2CharLit (MachInt i) = MachChar (chr (fromInteger i)) -int2CharLit l = pprPanic "int2CharLit" (ppr l) +int2CharLit (LitNumber _ i _) = MachChar (chr (fromInteger i)) +int2CharLit l = pprPanic "int2CharLit" (ppr l) -float2IntLit (MachFloat f) = MachInt (truncate f) +float2IntLit (MachFloat f) = mkMachIntUnchecked (truncate f) float2IntLit l = pprPanic "float2IntLit" (ppr l) -int2FloatLit (MachInt i) = MachFloat (fromInteger i) -int2FloatLit l = pprPanic "int2FloatLit" (ppr l) +int2FloatLit (LitNumber _ i _) = MachFloat (fromInteger i) +int2FloatLit l = pprPanic "int2FloatLit" (ppr l) -double2IntLit (MachDouble f) = MachInt (truncate f) +double2IntLit (MachDouble f) = mkMachIntUnchecked (truncate f) double2IntLit l = pprPanic "double2IntLit" (ppr l) -int2DoubleLit (MachInt i) = MachDouble (fromInteger i) -int2DoubleLit l = pprPanic "int2DoubleLit" (ppr l) +int2DoubleLit (LitNumber _ i _) = MachDouble (fromInteger i) +int2DoubleLit l = pprPanic "int2DoubleLit" (ppr l) float2DoubleLit (MachFloat f) = MachDouble f float2DoubleLit l = pprPanic "float2DoubleLit" (ppr l) @@ -498,24 +559,41 @@ nullAddrLit = MachNullAddr litIsTrivial :: Literal -> Bool -- c.f. CoreUtils.exprIsTrivial litIsTrivial (MachStr _) = False -litIsTrivial (LitInteger {}) = False +litIsTrivial (LitNumber nt _ _) = case nt of + LitNumInteger -> False + LitNumNatural -> False + LitNumInt -> True + LitNumInt64 -> True + LitNumWord -> True + LitNumWord64 -> True litIsTrivial _ = True -- | True if code space does not go bad if we duplicate this literal --- Currently we treat it just like 'litIsTrivial' litIsDupable :: DynFlags -> Literal -> Bool -- c.f. CoreUtils.exprIsDupable litIsDupable _ (MachStr _) = False -litIsDupable dflags (LitInteger i _) = inIntRange dflags i +litIsDupable dflags (LitNumber nt i _) = case nt of + LitNumInteger -> inIntRange dflags i + LitNumNatural -> inIntRange dflags i + LitNumInt -> True + LitNumInt64 -> True + LitNumWord -> True + LitNumWord64 -> True litIsDupable _ _ = True litFitsInChar :: Literal -> Bool -litFitsInChar (MachInt i) = i >= toInteger (ord minBound) - && i <= toInteger (ord maxBound) -litFitsInChar _ = False +litFitsInChar (LitNumber _ i _) = i >= toInteger (ord minBound) + && i <= toInteger (ord maxBound) +litFitsInChar _ = False litIsLifted :: Literal -> Bool -litIsLifted (LitInteger {}) = True +litIsLifted (LitNumber nt _ _) = case nt of + LitNumInteger -> True + LitNumNatural -> True + LitNumInt -> False + LitNumInt64 -> False + LitNumWord -> False + LitNumWord64 -> False litIsLifted _ = False {- @@ -525,17 +603,13 @@ litIsLifted _ = False -- | Find the Haskell 'Type' the literal occupies literalType :: Literal -> Type -literalType MachNullAddr = addrPrimTy -literalType (MachChar _) = charPrimTy -literalType (MachStr _) = addrPrimTy -literalType (MachInt _) = intPrimTy -literalType (MachWord _) = wordPrimTy -literalType (MachInt64 _) = int64PrimTy -literalType (MachWord64 _) = word64PrimTy -literalType (MachFloat _) = floatPrimTy -literalType (MachDouble _) = doublePrimTy +literalType MachNullAddr = addrPrimTy +literalType (MachChar _) = charPrimTy +literalType (MachStr _) = addrPrimTy +literalType (MachFloat _) = floatPrimTy +literalType (MachDouble _) = doublePrimTy literalType (MachLabel _ _ _) = addrPrimTy -literalType (LitInteger _ t) = t +literalType (LitNumber _ _ t) = t absentLiteralOf :: TyCon -> Maybe Literal -- Return a literal of the appropriate primitive @@ -545,12 +619,13 @@ absentLiteralOf tc = lookupUFM absent_lits (tyConName tc) absent_lits :: UniqFM Literal absent_lits = listToUFM [ (addrPrimTyConKey, MachNullAddr) , (charPrimTyConKey, MachChar 'x') - , (intPrimTyConKey, MachInt 0) - , (int64PrimTyConKey, MachInt64 0) + , (intPrimTyConKey, mkMachIntUnchecked 0) + , (int64PrimTyConKey, mkMachInt64Unchecked 0) + , (wordPrimTyConKey, mkMachWordUnchecked 0) + , (word64PrimTyConKey, mkMachWord64Unchecked 0) , (floatPrimTyConKey, MachFloat 0) , (doublePrimTyConKey, MachDouble 0) - , (wordPrimTyConKey, MachWord 0) - , (word64PrimTyConKey, MachWord64 0) ] + ] {- Comparison @@ -558,32 +633,27 @@ absent_lits = listToUFM [ (addrPrimTyConKey, MachNullAddr) -} cmpLit :: Literal -> Literal -> Ordering -cmpLit (MachChar a) (MachChar b) = a `compare` b -cmpLit (MachStr a) (MachStr b) = a `compare` b -cmpLit (MachNullAddr) (MachNullAddr) = EQ -cmpLit (MachInt a) (MachInt b) = a `compare` b -cmpLit (MachWord a) (MachWord b) = a `compare` b -cmpLit (MachInt64 a) (MachInt64 b) = a `compare` b -cmpLit (MachWord64 a) (MachWord64 b) = a `compare` b -cmpLit (MachFloat a) (MachFloat b) = a `compare` b -cmpLit (MachDouble a) (MachDouble b) = a `compare` b +cmpLit (MachChar a) (MachChar b) = a `compare` b +cmpLit (MachStr a) (MachStr b) = a `compare` b +cmpLit (MachNullAddr) (MachNullAddr) = EQ +cmpLit (MachFloat a) (MachFloat b) = a `compare` b +cmpLit (MachDouble a) (MachDouble b) = a `compare` b cmpLit (MachLabel a _ _) (MachLabel b _ _) = a `compare` b -cmpLit (LitInteger a _) (LitInteger b _) = a `compare` b -cmpLit lit1 lit2 | litTag lit1 < litTag lit2 = LT - | otherwise = GT +cmpLit (LitNumber nt1 a _) (LitNumber nt2 b _) + | nt1 == nt2 = a `compare` b + | otherwise = nt1 `compare` nt2 +cmpLit lit1 lit2 + | litTag lit1 < litTag lit2 = LT + | otherwise = GT litTag :: Literal -> Int litTag (MachChar _) = 1 litTag (MachStr _) = 2 litTag (MachNullAddr) = 3 -litTag (MachInt _) = 4 -litTag (MachWord _) = 5 -litTag (MachInt64 _) = 6 -litTag (MachWord64 _) = 7 -litTag (MachFloat _) = 8 -litTag (MachDouble _) = 9 -litTag (MachLabel _ _ _) = 10 -litTag (LitInteger {}) = 11 +litTag (MachFloat _) = 4 +litTag (MachDouble _) = 5 +litTag (MachLabel _ _ _) = 6 +litTag (LitNumber {}) = 7 {- Printing @@ -595,13 +665,16 @@ pprLiteral :: (SDoc -> SDoc) -> Literal -> SDoc pprLiteral _ (MachChar c) = pprPrimChar c pprLiteral _ (MachStr s) = pprHsBytes s pprLiteral _ (MachNullAddr) = text "__NULL" -pprLiteral _ (MachInt i) = pprPrimInt i -pprLiteral _ (MachInt64 i) = pprPrimInt64 i -pprLiteral _ (MachWord w) = pprPrimWord w -pprLiteral _ (MachWord64 w) = pprPrimWord64 w pprLiteral _ (MachFloat f) = float (fromRat f) <> primFloatSuffix pprLiteral _ (MachDouble d) = double (fromRat d) <> primDoubleSuffix -pprLiteral add_par (LitInteger i _) = pprIntegerVal add_par i +pprLiteral add_par (LitNumber nt i _) + = case nt of + LitNumInteger -> pprIntegerVal add_par i + LitNumNatural -> pprIntegerVal add_par i + LitNumInt -> pprPrimInt i + LitNumInt64 -> pprPrimInt64 i + LitNumWord -> pprPrimWord i + LitNumWord64 -> pprPrimWord64 i pprLiteral add_par (MachLabel l mb fod) = add_par (text "__label" <+> b <+> ppr fod) where b = case mb of Nothing -> pprHsString l diff --git a/compiler/codeGen/StgCmmCon.hs b/compiler/codeGen/StgCmmCon.hs index 8dadb4ede7..f2287e0fbd 100644 --- a/compiler/codeGen/StgCmmCon.hs +++ b/compiler/codeGen/StgCmmCon.hs @@ -198,7 +198,7 @@ because they don't support cross package data references well. buildDynCon' dflags platform binder _ _cc con [arg] | maybeIntLikeCon con , platformOS platform /= OSMinGW32 || not (positionIndependent dflags) - , NonVoid (StgLitArg (MachInt val)) <- arg + , NonVoid (StgLitArg (LitNumber LitNumInt val _)) <- arg , val <= fromIntegral (mAX_INTLIKE dflags) -- Comparisons at type Integer! , val >= fromIntegral (mIN_INTLIKE dflags) -- ...ditto... = do { let intlike_lbl = mkCmmClosureLabel rtsUnitId (fsLit "stg_INTLIKE") diff --git a/compiler/codeGen/StgCmmUtils.hs b/compiler/codeGen/StgCmmUtils.hs index 94013f5c6d..99fa550b83 100644 --- a/compiler/codeGen/StgCmmUtils.hs +++ b/compiler/codeGen/StgCmmUtils.hs @@ -94,10 +94,10 @@ cgLit other_lit = do dflags <- getDynFlags mkSimpleLit :: DynFlags -> Literal -> CmmLit mkSimpleLit dflags (MachChar c) = CmmInt (fromIntegral (ord c)) (wordWidth dflags) mkSimpleLit dflags MachNullAddr = zeroCLit dflags -mkSimpleLit dflags (MachInt i) = CmmInt i (wordWidth dflags) -mkSimpleLit _ (MachInt64 i) = CmmInt i W64 -mkSimpleLit dflags (MachWord i) = CmmInt i (wordWidth dflags) -mkSimpleLit _ (MachWord64 i) = CmmInt i W64 +mkSimpleLit dflags (LitNumber LitNumInt i _) = CmmInt i (wordWidth dflags) +mkSimpleLit _ (LitNumber LitNumInt64 i _) = CmmInt i W64 +mkSimpleLit dflags (LitNumber LitNumWord i _) = CmmInt i (wordWidth dflags) +mkSimpleLit _ (LitNumber LitNumWord64 i _) = CmmInt i W64 mkSimpleLit _ (MachFloat r) = CmmFloat r W32 mkSimpleLit _ (MachDouble r) = CmmFloat r W64 mkSimpleLit _ (MachLabel fs ms fod) @@ -529,8 +529,7 @@ emitCmmLitSwitch scrut branches deflt = do -- We find the necessary type information in the literals in the branches let signed = case head branches of - (MachInt _, _) -> True - (MachInt64 _, _) -> True + (LitNumber nt _ _, _) -> litNumIsSigned nt _ -> False let range | signed = (tARGET_MIN_INT dflags, tARGET_MAX_INT dflags) diff --git a/compiler/coreSyn/CorePrep.hs b/compiler/coreSyn/CorePrep.hs index 75301791b4..9c2954d4ef 100644 --- a/compiler/coreSyn/CorePrep.hs +++ b/compiler/coreSyn/CorePrep.hs @@ -8,8 +8,9 @@ Core pass to saturate constructors and PrimOps {-# LANGUAGE BangPatterns, CPP, MultiWayIf #-} module CorePrep ( - corePrepPgm, corePrepExpr, cvtLitInteger, - lookupMkIntegerName, lookupIntegerSDataConName + corePrepPgm, corePrepExpr, cvtLitInteger, cvtLitNatural, + lookupMkIntegerName, lookupIntegerSDataConName, + lookupMkNaturalName, lookupNaturalSDataConName ) where #include "HsVersions.h" @@ -122,11 +123,13 @@ The goal of this pass is to prepare for code generation. special case where we use the S# constructor for Integers that are in the range of Int. -11. Uphold tick consistency while doing this: We move ticks out of +11. Same for LitNatural. + +12. Uphold tick consistency while doing this: We move ticks out of (non-type) applications where we can, and make sure that we annotate according to scoping rules when floating. -12. Collect cost centres (including cost centres in unfoldings) if we're in +13. Collect cost centres (including cost centres in unfoldings) if we're in profiling mode. We have to do this here beucase we won't have unfoldings after this pass (see `zapUnfolding` and Note [Drop unfoldings and rules]. @@ -608,9 +611,12 @@ cpeRhsE :: CorePrepEnv -> CoreExpr -> UniqSM (Floats, CpeRhs) cpeRhsE _env expr@(Type {}) = return (emptyFloats, expr) cpeRhsE _env expr@(Coercion {}) = return (emptyFloats, expr) -cpeRhsE env (Lit (LitInteger i _)) +cpeRhsE env (Lit (LitNumber LitNumInteger i _)) = cpeRhsE env (cvtLitInteger (cpe_dynFlags env) (getMkIntegerId env) (cpe_integerSDataCon env) i) +cpeRhsE env (Lit (LitNumber LitNumNatural i _)) + = cpeRhsE env (cvtLitNatural (cpe_dynFlags env) (getMkNaturalId env) + (cpe_naturalSDataCon env) i) cpeRhsE _env expr@(Lit {}) = return (emptyFloats, expr) cpeRhsE env expr@(Var {}) = cpeApp env expr cpeRhsE env expr@(App {}) = cpeApp env expr @@ -693,6 +699,24 @@ cvtLitInteger dflags mk_integer _ i bits = 31 mask = 2 ^ bits - 1 +cvtLitNatural :: DynFlags -> Id -> Maybe DataCon -> Integer -> CoreExpr +-- Here we convert a literal Natural to the low-level +-- representation. +-- See Note [Natural literals] in Literal +cvtLitNatural dflags _ (Just sdatacon) i + | inWordRange dflags i -- Special case for small naturals + = mkConApp sdatacon [Lit (mkMachWord dflags i)] + +cvtLitNatural dflags mk_natural _ i + = mkApps (Var mk_natural) [words] + where words = mkListExpr wordTy (f i) + f 0 = [] + f x = let low = x .&. mask + high = x `shiftR` bits + in mkConApp wordDataCon [Lit (mkMachWord dflags low)] : f high + bits = 32 + mask = 2 ^ bits - 1 + -- --------------------------------------------------------------------------- -- CpeBody: produces a result satisfying CpeBody -- --------------------------------------------------------------------------- @@ -1388,8 +1412,8 @@ canFloatFromNoCaf platform (Floats ok_to_spec fs) rhs -- the new binding is static. However it can't mention -- any non-static things or it would *already* be Caffy rhs_ok = rhsIsStatic platform (\_ -> False) - (\i -> pprPanic "rhsIsStatic" (integer i)) - -- Integer literals should not show up + (\_nt i -> pprPanic "rhsIsStatic" (integer i)) + -- Integer or Natural literals should not show up wantFloatNested :: RecFlag -> Demand -> Bool -> Floats -> CpeRhs -> Bool wantFloatNested is_rec dmd is_unlifted floats rhs @@ -1498,7 +1522,9 @@ data CorePrepEnv -- see Note [lazyId magic], Note [Inlining in CorePrep] -- and Note [CorePrep inlines trivial CoreExpr not Id] (#12076) , cpe_mkIntegerId :: Id + , cpe_mkNaturalId :: Id , cpe_integerSDataCon :: Maybe DataCon + , cpe_naturalSDataCon :: Maybe DataCon } lookupMkIntegerName :: DynFlags -> HscEnv -> IO Id @@ -1506,13 +1532,24 @@ lookupMkIntegerName dflags hsc_env = guardIntegerUse dflags $ liftM tyThingId $ lookupGlobal hsc_env mkIntegerName +lookupMkNaturalName :: DynFlags -> HscEnv -> IO Id +lookupMkNaturalName dflags hsc_env + = guardNaturalUse dflags $ liftM tyThingId $ + lookupGlobal hsc_env mkNaturalName + lookupIntegerSDataConName :: DynFlags -> HscEnv -> IO (Maybe DataCon) lookupIntegerSDataConName dflags hsc_env = case cIntegerLibraryType of IntegerGMP -> guardIntegerUse dflags $ liftM (Just . tyThingDataCon) $ lookupGlobal hsc_env integerSDataConName IntegerSimple -> return Nothing --- | Helper for 'lookupMkIntegerName' and 'lookupIntegerSDataConName' +lookupNaturalSDataConName :: DynFlags -> HscEnv -> IO (Maybe DataCon) +lookupNaturalSDataConName dflags hsc_env = case cIntegerLibraryType of + IntegerGMP -> guardNaturalUse dflags $ liftM (Just . tyThingDataCon) $ + lookupGlobal hsc_env naturalSDataConName + IntegerSimple -> return Nothing + +-- | Helper for 'lookupMkIntegerName', 'lookupIntegerSDataConName' guardIntegerUse :: DynFlags -> IO a -> IO a guardIntegerUse dflags act | thisPackage dflags == primUnitId @@ -1521,15 +1558,33 @@ guardIntegerUse dflags act = return $ panic "Can't use Integer in integer-*" | otherwise = act +-- | Helper for 'lookupMkNaturalName', 'lookupNaturalSDataConName' +-- +-- Just like we can't use Integer literals in `integer-*`, we can't use Natural +-- literals in `base`. If we do, we get interface loading error for GHC.Natural. +guardNaturalUse :: DynFlags -> IO a -> IO a +guardNaturalUse dflags act + | thisPackage dflags == primUnitId + = return $ panic "Can't use Natural in ghc-prim" + | thisPackage dflags == integerUnitId + = return $ panic "Can't use Natural in integer-*" + | thisPackage dflags == baseUnitId + = return $ panic "Can't use Natural in base" + | otherwise = act + mkInitialCorePrepEnv :: DynFlags -> HscEnv -> IO CorePrepEnv mkInitialCorePrepEnv dflags hsc_env = do mkIntegerId <- lookupMkIntegerName dflags hsc_env + mkNaturalId <- lookupMkNaturalName dflags hsc_env integerSDataCon <- lookupIntegerSDataConName dflags hsc_env + naturalSDataCon <- lookupNaturalSDataConName dflags hsc_env return $ CPE { cpe_dynFlags = dflags, cpe_env = emptyVarEnv, cpe_mkIntegerId = mkIntegerId, - cpe_integerSDataCon = integerSDataCon + cpe_mkNaturalId = mkNaturalId, + cpe_integerSDataCon = integerSDataCon, + cpe_naturalSDataCon = naturalSDataCon } extendCorePrepEnv :: CorePrepEnv -> Id -> Id -> CorePrepEnv @@ -1554,6 +1609,9 @@ lookupCorePrepEnv cpe id getMkIntegerId :: CorePrepEnv -> Id getMkIntegerId = cpe_mkIntegerId +getMkNaturalId :: CorePrepEnv -> Id +getMkNaturalId = cpe_mkNaturalId + ------------------------------------------------------------------------------ -- Cloning binders -- --------------------------------------------------------------------------- diff --git a/compiler/coreSyn/CoreUnfold.hs b/compiler/coreSyn/CoreUnfold.hs index 3d26d3c721..7bd512d98f 100644 --- a/compiler/coreSyn/CoreUnfold.hs +++ b/compiler/coreSyn/CoreUnfold.hs @@ -701,7 +701,8 @@ sizeExpr dflags bOMB_OUT_SIZE top_args expr -- | Finds a nominal size of a string literal. litSize :: Literal -> Int -- Used by CoreUnfold.sizeExpr -litSize (LitInteger {}) = 100 -- Note [Size of literal integers] +litSize (LitNumber LitNumInteger _ _) = 100 -- Note [Size of literal integers] +litSize (LitNumber LitNumNatural _ _) = 100 litSize (MachStr 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/coreSyn/CoreUtils.hs b/compiler/coreSyn/CoreUtils.hs index 88e1f7167e..8f4f84b550 100644 --- a/compiler/coreSyn/CoreUtils.hs +++ b/compiler/coreSyn/CoreUtils.hs @@ -2409,12 +2409,13 @@ and 'execute' it rather than allocating it statically. -- | This function is called only on *top-level* right-hand sides. -- Returns @True@ if the RHS can be allocated statically in the output, -- with no thunks involved at all. -rhsIsStatic :: Platform - -> (Name -> Bool) -- Which names are dynamic - -> (Integer -> CoreExpr) -- Desugaring for integer literals (disgusting) - -- C.f. Note [Disgusting computation of CafRefs] - -- in TidyPgm - -> CoreExpr -> Bool +rhsIsStatic + :: Platform + -> (Name -> Bool) -- Which names are dynamic + -> (LitNumType -> Integer -> Maybe CoreExpr) + -- Desugaring for some literals (disgusting) + -- C.f. Note [Disgusting computation of CafRefs] in TidyPgm + -> CoreExpr -> Bool -- It's called (i) in TidyPgm.hasCafRefs to decide if the rhs is, or -- refers to, CAFs; (ii) in CoreToStg to decide whether to put an -- update flag on it and (iii) in DsExpr to decide how to expand @@ -2469,7 +2470,7 @@ rhsIsStatic :: Platform -- -- c) don't look through unfolding of f in (f x). -rhsIsStatic platform is_dynamic_name cvt_integer rhs = is_static False rhs +rhsIsStatic platform is_dynamic_name cvt_literal rhs = is_static False rhs where is_static :: Bool -- True <=> in a constructor argument; must be atomic -> CoreExpr -> Bool @@ -2479,7 +2480,9 @@ rhsIsStatic platform is_dynamic_name cvt_integer rhs = is_static False rhs && is_static in_arg e is_static in_arg (Cast e _) = is_static in_arg e is_static _ (Coercion {}) = True -- Behaves just like a literal - is_static in_arg (Lit (LitInteger i _)) = is_static in_arg (cvt_integer i) + is_static in_arg (Lit (LitNumber nt i _)) = case cvt_literal nt i of + Just e -> is_static in_arg e + Nothing -> True is_static _ (Lit (MachLabel {})) = False is_static _ (Lit _) = True -- A MachLabel (foreign import "&foo") in an argument diff --git a/compiler/coreSyn/MkCore.hs b/compiler/coreSyn/MkCore.hs index aad6d14a90..ef9da21e9a 100644 --- a/compiler/coreSyn/MkCore.hs +++ b/compiler/coreSyn/MkCore.hs @@ -260,13 +260,9 @@ mkIntegerExpr i = do t <- lookupTyCon integerTyConName return (Lit (mkLitInteger i (mkTyConTy t))) -- | Create a 'CoreExpr' which will evaluate to the given @Natural@ --- --- TODO: should we add LitNatural to Core? -mkNaturalExpr :: MonadThings m => Integer -> m CoreExpr -- Result :: Natural -mkNaturalExpr i = do iExpr <- mkIntegerExpr i - fiExpr <- lookupId naturalFromIntegerName - return (mkCoreApps (Var fiExpr) [iExpr]) - +mkNaturalExpr :: MonadThings m => Integer -> m CoreExpr +mkNaturalExpr i = do t <- lookupTyCon naturalTyConName + return (Lit (mkLitNatural i (mkTyConTy t))) -- | Create a 'CoreExpr' which will evaluate to the given @Float@ mkFloatExpr :: Float -> CoreExpr diff --git a/compiler/deSugar/MatchLit.hs b/compiler/deSugar/MatchLit.hs index d715439015..ca7ef0af2f 100644 --- a/compiler/deSugar/MatchLit.hs +++ b/compiler/deSugar/MatchLit.hs @@ -77,32 +77,32 @@ See also below where we look for @DictApps@ for \tr{plusInt}, etc. -} dsLit :: HsLit GhcRn -> DsM CoreExpr -dsLit (HsStringPrim _ s) = return (Lit (MachStr s)) -dsLit (HsCharPrim _ c) = return (Lit (MachChar c)) -dsLit (HsIntPrim _ i) = return (Lit (MachInt i)) -dsLit (HsWordPrim _ w) = return (Lit (MachWord w)) -dsLit (HsInt64Prim _ i) = return (Lit (MachInt64 i)) -dsLit (HsWord64Prim _ w) = return (Lit (MachWord64 w)) -dsLit (HsFloatPrim _ f) = return (Lit (MachFloat (fl_value f))) -dsLit (HsDoublePrim _ d) = return (Lit (MachDouble (fl_value d))) -dsLit (HsChar _ c) = return (mkCharExpr c) -dsLit (HsString _ str) = mkStringExprFS str -dsLit (HsInteger _ i _) = mkIntegerExpr i -dsLit (HsInt _ i) = do dflags <- getDynFlags - return (mkIntExpr dflags (il_value i)) - -dsLit (HsRat _ (FL _ _ val) ty) = do - num <- mkIntegerExpr (numerator val) - denom <- mkIntegerExpr (denominator val) - return (mkCoreConApps ratio_data_con [Type integer_ty, num, denom]) - where - (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) - -dsLit (XLit x) = pprPanic "dsLit" (ppr x) +dsLit l = do + dflags <- getDynFlags + case l of + HsStringPrim _ s -> return (Lit (MachStr s)) + HsCharPrim _ c -> return (Lit (MachChar c)) + HsIntPrim _ i -> return (Lit (mkMachIntWrap dflags i)) + HsWordPrim _ w -> return (Lit (mkMachWordWrap dflags w)) + HsInt64Prim _ i -> return (Lit (mkMachInt64Wrap dflags i)) + HsWord64Prim _ w -> return (Lit (mkMachWord64Wrap dflags w)) + HsFloatPrim _ f -> return (Lit (MachFloat (fl_value f))) + HsDoublePrim _ d -> return (Lit (MachDouble (fl_value d))) + HsChar _ c -> return (mkCharExpr c) + HsString _ str -> mkStringExprFS str + HsInteger _ i _ -> mkIntegerExpr i + HsInt _ i -> return (mkIntExpr dflags (il_value i)) + XLit x -> pprPanic "dsLit" (ppr x) + HsRat _ (FL _ _ val) ty -> do + num <- mkIntegerExpr (numerator val) + denom <- mkIntegerExpr (denominator val) + return (mkCoreConApps ratio_data_con [Type integer_ty, num, denom]) + where + (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) dsOverLit :: HsOverLit GhcTc -> DsM CoreExpr dsOverLit lit = do { dflags <- getDynFlags @@ -161,20 +161,30 @@ warnAboutOverflowedLiterals :: DynFlags -> HsOverLit GhcTc -> DsM () warnAboutOverflowedLiterals dflags lit | wopt Opt_WarnOverflowedLiterals dflags , Just (i, tc) <- getIntegralLit lit - = if tc == intTyConName then check i tc (Proxy :: Proxy Int) - else if tc == int8TyConName then check i tc (Proxy :: Proxy Int8) - else if tc == int16TyConName then check i tc (Proxy :: Proxy Int16) - else if tc == int32TyConName then check i tc (Proxy :: Proxy Int32) - else if tc == int64TyConName then check i tc (Proxy :: Proxy Int64) - else if tc == wordTyConName then check i tc (Proxy :: Proxy Word) - else if tc == word8TyConName then check i tc (Proxy :: Proxy Word8) - else if tc == word16TyConName then check i tc (Proxy :: Proxy Word16) - else if tc == word32TyConName then check i tc (Proxy :: Proxy Word32) - else if tc == word64TyConName then check i tc (Proxy :: Proxy Word64) + = if tc == intTyConName then check i tc (Proxy :: Proxy Int) + else if tc == int8TyConName then check i tc (Proxy :: Proxy Int8) + else if tc == int16TyConName then check i tc (Proxy :: Proxy Int16) + else if tc == int32TyConName then check i tc (Proxy :: Proxy Int32) + else if tc == int64TyConName then check i tc (Proxy :: Proxy Int64) + else if tc == wordTyConName then check i tc (Proxy :: Proxy Word) + else if tc == word8TyConName then check i tc (Proxy :: Proxy Word8) + else if tc == word16TyConName then check i tc (Proxy :: Proxy Word16) + else if tc == word32TyConName then check i tc (Proxy :: Proxy Word32) + else if tc == word64TyConName then check i tc (Proxy :: Proxy Word64) + else if tc == naturalTyConName then checkPositive i tc else return () | otherwise = return () where + checkPositive :: Integer -> Name -> DsM () + checkPositive i tc + = when (i < 0) $ do + warnDs (Reason Opt_WarnOverflowedLiterals) + (vcat [ text "Literal" <+> integer i + <+> text "is negative but" <+> ppr tc + <+> ptext (sLit "only supports positive numbers") + ]) + check :: forall a. (Bounded a, Integral a) => Integer -> Name -> Proxy a -> DsM () check i tc _proxy = when (i < minB || i > maxB) $ do @@ -389,8 +399,8 @@ hsLitKey :: DynFlags -> HsLit GhcTc -> Literal -- HsLit does not. hsLitKey dflags (HsIntPrim _ i) = mkMachIntWrap dflags i hsLitKey dflags (HsWordPrim _ w) = mkMachWordWrap dflags w -hsLitKey _ (HsInt64Prim _ i) = mkMachInt64Wrap i -hsLitKey _ (HsWord64Prim _ w) = mkMachWord64Wrap w +hsLitKey dflags (HsInt64Prim _ i) = mkMachInt64Wrap dflags i +hsLitKey dflags (HsWord64Prim _ w) = mkMachWord64Wrap dflags w hsLitKey _ (HsCharPrim _ c) = mkMachChar c hsLitKey _ (HsFloatPrim _ f) = mkMachFloat (fl_value f) hsLitKey _ (HsDoublePrim _ d) = mkMachDouble (fl_value d) diff --git a/compiler/ghci/ByteCodeAsm.hs b/compiler/ghci/ByteCodeAsm.hs index 920bc4ac2b..f7cea3b567 100644 --- a/compiler/ghci/ByteCodeAsm.hs +++ b/compiler/ghci/ByteCodeAsm.hs @@ -444,17 +444,19 @@ assembleI dflags i = case i of -- On Windows, stdcall labels have a suffix indicating the no. of -- arg words, e.g. foo@8. testcase: ffi012(ghci) literal (MachLabel fs _ _) = litlabel fs - literal (MachWord w) = int (fromIntegral w) - literal (MachInt j) = int (fromIntegral j) literal MachNullAddr = int 0 literal (MachFloat r) = float (fromRational r) literal (MachDouble r) = double (fromRational r) literal (MachChar c) = int (ord c) - literal (MachInt64 ii) = int64 (fromIntegral ii) - literal (MachWord64 ii) = int64 (fromIntegral ii) literal (MachStr bs) = lit [BCONPtrStr bs] -- MachStr requires a zero-terminator when emitted - literal LitInteger{} = panic "ByteCodeAsm.literal: LitInteger" + literal (LitNumber nt i _) = case nt of + LitNumInt -> int (fromIntegral i) + LitNumWord -> int (fromIntegral i) + LitNumInt64 -> int64 (fromIntegral i) + LitNumWord64 -> int64 (fromIntegral i) + LitNumInteger -> panic "ByteCodeAsm.literal: LitNumInteger" + LitNumNatural -> panic "ByteCodeAsm.literal: LitNumNatural" litlabel fs = lit [BCONPtrLbl fs] addr (RemotePtr a) = words [fromIntegral a] diff --git a/compiler/ghci/ByteCodeGen.hs b/compiler/ghci/ByteCodeGen.hs index 74168ac442..022fe89306 100644 --- a/compiler/ghci/ByteCodeGen.hs +++ b/compiler/ghci/ByteCodeGen.hs @@ -996,8 +996,8 @@ doCase d s p (_,scrut) bndr alts is_unboxed_tuple | otherwise = DiscrP (fromIntegral (dataConTag dc - fIRST_TAG)) my_discr (LitAlt l, _, _) - = case l of MachInt i -> DiscrI (fromInteger i) - MachWord w -> DiscrW (fromInteger w) + = case l of LitNumber LitNumInt i _ -> DiscrI (fromInteger i) + LitNumber LitNumWord w _ -> DiscrW (fromInteger w) MachFloat r -> DiscrF (fromRational r) MachDouble r -> DiscrD (fromRational r) MachChar i -> DiscrI (ord i) @@ -1233,7 +1233,7 @@ generateCCall d0 s p (CCallSpec target cconv safety) fn args_r_to_l push_r = if returns_void then nilOL - else unitOL (PUSH_UBX (mkDummyLiteral r_rep) (trunc16W r_sizeW)) + else unitOL (PUSH_UBX (mkDummyLiteral dflags r_rep) (trunc16W r_sizeW)) -- generate the marshalling code we're going to call @@ -1297,16 +1297,16 @@ primRepToFFIType dflags r -- Make a dummy literal, to be used as a placeholder for FFI return -- values on the stack. -mkDummyLiteral :: PrimRep -> Literal -mkDummyLiteral pr +mkDummyLiteral :: DynFlags -> PrimRep -> Literal +mkDummyLiteral dflags pr = case pr of - IntRep -> MachInt 0 - WordRep -> MachWord 0 + IntRep -> mkMachInt dflags 0 + WordRep -> mkMachWord dflags 0 + Int64Rep -> mkMachInt64 0 + Word64Rep -> mkMachWord64 0 AddrRep -> MachNullAddr DoubleRep -> MachDouble 0 FloatRep -> MachFloat 0 - Int64Rep -> MachInt64 0 - Word64Rep -> MachWord64 0 _ -> pprPanic "mkDummyLiteral" (ppr pr) @@ -1505,11 +1505,11 @@ pushAtom d p (AnnVar var) | otherwise -- var must be a global variable = do topStrings <- getTopStrings + dflags <- getDynFlags case lookupVarEnv topStrings var of - Just ptr -> pushAtom d p $ AnnLit $ MachWord $ fromIntegral $ - ptrToWordPtr $ fromRemotePtr ptr + Just ptr -> pushAtom d p $ AnnLit $ mkMachWord dflags $ + fromIntegral $ ptrToWordPtr $ fromRemotePtr ptr Nothing -> do - dflags <- getDynFlags let sz = idSizeCon dflags var MASSERT( sz == wordSize dflags ) return (unitOL (PUSH_G (getName var)), sz) @@ -1524,19 +1524,21 @@ pushAtom _ _ (AnnLit lit) = do case lit of MachLabel _ _ _ -> code N - MachWord _ -> code N - MachInt _ -> code N - MachWord64 _ -> code L - MachInt64 _ -> code L MachFloat _ -> code F MachDouble _ -> code D MachChar _ -> code N MachNullAddr -> code N MachStr _ -> code N - -- No LitInteger's should be left by the time this is called. - -- CorePrep should have converted them all to a real core - -- representation. - LitInteger {} -> panic "pushAtom: LitInteger" + LitNumber nt _ _ -> case nt of + LitNumInt -> code N + LitNumWord -> code N + LitNumInt64 -> code L + LitNumWord64 -> code L + -- 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" pushAtom _ _ expr = pprPanic "ByteCodeGen.pushAtom" diff --git a/compiler/iface/TcIface.hs b/compiler/iface/TcIface.hs index 9d04bf2fb3..bffda71f0a 100644 --- a/compiler/iface/TcIface.hs +++ b/compiler/iface/TcIface.hs @@ -1367,9 +1367,15 @@ tcIfaceLit :: Literal -> IfL Literal -- Integer literals deserialise to (LitInteger i <error thunk>) -- so tcIfaceLit just fills in the type. -- See Note [Integer literals] in Literal -tcIfaceLit (LitInteger i _) +tcIfaceLit (LitNumber LitNumInteger i _) = do t <- tcIfaceTyConByName integerTyConName return (mkLitInteger i (mkTyConTy t)) +-- Natural literals deserialise to (LitNatural i <error thunk>) +-- so tcIfaceLit just fills in the type. +-- See Note [Natural literals] in Literal +tcIfaceLit (LitNumber LitNumNatural i _) + = do t <- tcIfaceTyConByName naturalTyConName + return (mkLitNatural i (mkTyConTy t)) tcIfaceLit lit = return lit ------------------------- diff --git a/compiler/main/TidyPgm.hs b/compiler/main/TidyPgm.hs index 1728bc0a69..f98e65e471 100644 --- a/compiler/main/TidyPgm.hs +++ b/compiler/main/TidyPgm.hs @@ -1093,9 +1093,14 @@ tidyTopBinds :: HscEnv tidyTopBinds hsc_env this_mod unfold_env init_occ_env binds = do mkIntegerId <- lookupMkIntegerName dflags hsc_env + mkNaturalId <- lookupMkNaturalName dflags hsc_env integerSDataCon <- lookupIntegerSDataConName dflags hsc_env - let cvt_integer = cvtLitInteger dflags mkIntegerId integerSDataCon - result = tidy cvt_integer init_env binds + naturalSDataCon <- lookupNaturalSDataConName dflags hsc_env + let cvt_literal nt i = case nt of + LitNumInteger -> Just (cvtLitInteger dflags mkIntegerId integerSDataCon i) + LitNumNatural -> Just (cvtLitNatural dflags mkNaturalId naturalSDataCon i) + _ -> Nothing + result = tidy cvt_literal init_env binds seqBinds (snd result) `seq` return result -- This seqBinds avoids a spike in space usage (see #13564) where @@ -1104,34 +1109,35 @@ tidyTopBinds hsc_env this_mod unfold_env init_occ_env binds init_env = (init_occ_env, emptyVarEnv) tidy _ env [] = (env, []) - tidy cvt_integer env (b:bs) - = let (env1, b') = tidyTopBind dflags this_mod - cvt_integer unfold_env env b - (env2, bs') = tidy cvt_integer env1 bs + tidy cvt_literal env (b:bs) + = let (env1, b') = tidyTopBind dflags this_mod cvt_literal unfold_env + env b + (env2, bs') = tidy cvt_literal env1 bs in (env2, b':bs') ------------------------ tidyTopBind :: DynFlags -> Module - -> (Integer -> CoreExpr) + -> (LitNumType -> Integer -> Maybe CoreExpr) -> UnfoldEnv -> TidyEnv -> CoreBind -> (TidyEnv, CoreBind) -tidyTopBind dflags this_mod cvt_integer unfold_env +tidyTopBind dflags this_mod cvt_literal unfold_env (occ_env,subst1) (NonRec bndr rhs) = (tidy_env2, NonRec bndr' rhs') where Just (name',show_unfold) = lookupVarEnv unfold_env bndr - caf_info = hasCafRefs dflags this_mod (subst1, cvt_integer) + caf_info = hasCafRefs dflags this_mod + (subst1, cvt_literal) (idArity bndr) rhs (bndr', rhs') = tidyTopPair dflags show_unfold tidy_env2 caf_info name' (bndr, rhs) subst2 = extendVarEnv subst1 bndr bndr' tidy_env2 = (occ_env, subst2) -tidyTopBind dflags this_mod cvt_integer unfold_env +tidyTopBind dflags this_mod cvt_literal unfold_env (occ_env, subst1) (Rec prs) = (tidy_env2, Rec prs') where @@ -1150,7 +1156,7 @@ tidyTopBind dflags this_mod cvt_integer unfold_env -- the group may refer indirectly to a CAF (because then, they all do). caf_info | or [ mayHaveCafRefs (hasCafRefs dflags this_mod - (subst1, cvt_integer) + (subst1, cvt_literal) (idArity bndr) rhs) | (bndr,rhs) <- prs ] = MayHaveCafRefs | otherwise = NoCafRefs @@ -1296,25 +1302,28 @@ We compute hasCafRefs here, because IdInfo is supposed to be finalised after TidyPgm. But CorePrep does some transformations that affect CAF-hood. So we have to *predict* the result here, which is revolting. -In particular CorePrep expands Integer literals. So in the prediction code -here we resort to applying the same expansion (cvt_integer). Ugh! +In particular CorePrep expands Integer and Natural literals. So in the +prediction code here we resort to applying the same expansion (cvt_literal). +Ugh! -} -type CafRefEnv = (VarEnv Id, Integer -> CoreExpr) +type CafRefEnv = (VarEnv Id, LitNumType -> Integer -> Maybe CoreExpr) -- The env finds the Caf-ness of the Id - -- The Integer -> CoreExpr is the desugaring function for Integer literals + -- The LitNumType -> Integer -> CoreExpr is the desugaring functions for + -- Integer and Natural literals -- See Note [Disgusting computation of CafRefs] hasCafRefs :: DynFlags -> Module -> CafRefEnv -> Arity -> CoreExpr -> CafInfo -hasCafRefs dflags this_mod p@(_,cvt_integer) arity expr +hasCafRefs dflags this_mod (subst, cvt_literal) arity expr | is_caf || mentions_cafs = MayHaveCafRefs | otherwise = NoCafRefs where - mentions_cafs = cafRefsE p expr + mentions_cafs = cafRefsE expr is_dynamic_name = isDllName dflags this_mod - is_caf = not (arity > 0 || rhsIsStatic (targetPlatform dflags) is_dynamic_name cvt_integer expr) + is_caf = not (arity > 0 || rhsIsStatic (targetPlatform dflags) is_dynamic_name + cvt_literal expr) -- NB. we pass in the arity of the expression, which is expected -- to be calculated by exprArity. This is because exprArity @@ -1322,34 +1331,36 @@ hasCafRefs dflags this_mod p@(_,cvt_integer) arity expr -- CorePrep later on, and we don't want to duplicate that -- knowledge in rhsIsStatic below. -cafRefsE :: CafRefEnv -> Expr a -> Bool -cafRefsE p (Var id) = cafRefsV p id -cafRefsE p (Lit lit) = cafRefsL p lit -cafRefsE p (App f a) = cafRefsE p f || cafRefsE p a -cafRefsE p (Lam _ e) = cafRefsE p e -cafRefsE p (Let b e) = cafRefsEs p (rhssOfBind b) || cafRefsE p e -cafRefsE p (Case e _ _ alts) = cafRefsE p e || cafRefsEs p (rhssOfAlts alts) -cafRefsE p (Tick _n e) = cafRefsE p e -cafRefsE p (Cast e _co) = cafRefsE p e -cafRefsE _ (Type _) = False -cafRefsE _ (Coercion _) = False - -cafRefsEs :: CafRefEnv -> [Expr a] -> Bool -cafRefsEs _ [] = False -cafRefsEs p (e:es) = cafRefsE p e || cafRefsEs p es - -cafRefsL :: CafRefEnv -> Literal -> Bool --- Don't forget that mk_integer id might have Caf refs! --- We first need to convert the Integer into its final form, to --- see whether mkInteger is used. -cafRefsL p@(_, cvt_integer) (LitInteger i _) = cafRefsE p (cvt_integer i) -cafRefsL _ _ = False - -cafRefsV :: CafRefEnv -> Id -> Bool -cafRefsV (subst, _) id - | not (isLocalId id) = mayHaveCafRefs (idCafInfo id) - | Just id' <- lookupVarEnv subst id = mayHaveCafRefs (idCafInfo id') - | otherwise = False + cafRefsE :: Expr a -> Bool + cafRefsE (Var id) = cafRefsV id + cafRefsE (Lit lit) = cafRefsL lit + cafRefsE (App f a) = cafRefsE f || cafRefsE a + cafRefsE (Lam _ e) = cafRefsE e + cafRefsE (Let b e) = cafRefsEs (rhssOfBind b) || cafRefsE e + cafRefsE (Case e _ _ alts) = cafRefsE e || cafRefsEs (rhssOfAlts alts) + cafRefsE (Tick _n e) = cafRefsE e + cafRefsE (Cast e _co) = cafRefsE e + cafRefsE (Type _) = False + cafRefsE (Coercion _) = False + + cafRefsEs :: [Expr a] -> Bool + cafRefsEs [] = False + cafRefsEs (e:es) = cafRefsE e || cafRefsEs es + + cafRefsL :: Literal -> Bool + -- Don't forget that mk_integer id might have Caf refs! + -- We first need to convert the Integer into its final form, to + -- see whether mkInteger is used. Same for LitNatural. + cafRefsL (LitNumber nt i _) = case cvt_literal nt i of + Just e -> cafRefsE e + Nothing -> False + cafRefsL _ = False + + cafRefsV :: Id -> Bool + cafRefsV id + | not (isLocalId id) = mayHaveCafRefs (idCafInfo id) + | Just id' <- lookupVarEnv subst id = mayHaveCafRefs (idCafInfo id') + | otherwise = False {- diff --git a/compiler/prelude/PrelNames.hs b/compiler/prelude/PrelNames.hs index 5ed67d591f..d971a8be90 100644 --- a/compiler/prelude/PrelNames.hs +++ b/compiler/prelude/PrelNames.hs @@ -358,7 +358,9 @@ basicKnownKeyNames -- Natural naturalTyConName, - naturalFromIntegerName, + naturalFromIntegerName, naturalToIntegerName, + plusNaturalName, minusNaturalName, timesNaturalName, mkNaturalName, + wordToNaturalName, -- Float/Double rationalToFloatName, @@ -435,7 +437,7 @@ basicKnownKeyNames , eqTyConName ] ++ case cIntegerLibraryType of - IntegerGMP -> [integerSDataConName] + IntegerGMP -> [integerSDataConName,naturalSDataConName] IntegerSimple -> [] genericTyConNames :: [Name] @@ -473,8 +475,8 @@ pRELUDE = mkBaseModule_ pRELUDE_NAME gHC_PRIM, gHC_TYPES, gHC_GENERICS, gHC_MAGIC, gHC_CLASSES, gHC_BASE, gHC_ENUM, gHC_GHCI, gHC_CSTRING, - gHC_SHOW, gHC_READ, gHC_NUM, gHC_INTEGER_TYPE, gHC_NATURAL, gHC_LIST, - gHC_TUPLE, dATA_TUPLE, dATA_EITHER, dATA_STRING, + gHC_SHOW, gHC_READ, gHC_NUM, gHC_MAYBE, gHC_INTEGER_TYPE, gHC_NATURAL, + gHC_LIST, gHC_TUPLE, dATA_TUPLE, dATA_EITHER, dATA_STRING, dATA_FOLDABLE, dATA_TRAVERSABLE, gHC_CONC, gHC_IO, gHC_IO_Exception, gHC_ST, gHC_ARR, gHC_STABLE, gHC_PTR, gHC_ERR, gHC_REAL, @@ -497,6 +499,7 @@ gHC_GHCI = mkBaseModule (fsLit "GHC.GHCi") gHC_SHOW = mkBaseModule (fsLit "GHC.Show") gHC_READ = mkBaseModule (fsLit "GHC.Read") gHC_NUM = mkBaseModule (fsLit "GHC.Num") +gHC_MAYBE = mkBaseModule (fsLit "GHC.Maybe") gHC_INTEGER_TYPE= mkIntegerModule (fsLit "GHC.Integer.Type") gHC_NATURAL = mkBaseModule (fsLit "GHC.Natural") gHC_LIST = mkBaseModule (fsLit "GHC.List") @@ -1121,7 +1124,7 @@ integerTyConName, mkIntegerName, integerSDataConName, andIntegerName, orIntegerName, xorIntegerName, complementIntegerName, shiftLIntegerName, shiftRIntegerName, bitIntegerName :: Name integerTyConName = tcQual gHC_INTEGER_TYPE (fsLit "Integer") integerTyConKey -integerSDataConName = dcQual gHC_INTEGER_TYPE (fsLit n) integerSDataConKey +integerSDataConName = dcQual gHC_INTEGER_TYPE (fsLit n) integerSDataConKey where n = case cIntegerLibraryType of IntegerGMP -> "S#" IntegerSimple -> panic "integerSDataConName evaluated for integer-simple" @@ -1169,12 +1172,25 @@ shiftRIntegerName = varQual gHC_INTEGER_TYPE (fsLit "shiftRInteger") shi bitIntegerName = varQual gHC_INTEGER_TYPE (fsLit "bitInteger") bitIntegerIdKey -- GHC.Natural types -naturalTyConName :: Name +naturalTyConName, naturalSDataConName :: Name naturalTyConName = tcQual gHC_NATURAL (fsLit "Natural") naturalTyConKey +naturalSDataConName = dcQual gHC_NATURAL (fsLit n) naturalSDataConKey + where n = case cIntegerLibraryType of + IntegerGMP -> "NatS#" + IntegerSimple -> panic "naturalSDataConName evaluated for integer-simple" naturalFromIntegerName :: Name naturalFromIntegerName = varQual gHC_NATURAL (fsLit "naturalFromInteger") naturalFromIntegerIdKey +naturalToIntegerName, plusNaturalName, minusNaturalName, timesNaturalName, + mkNaturalName, wordToNaturalName :: Name +naturalToIntegerName = varQual gHC_NATURAL (fsLit "naturalToInteger") naturalToIntegerIdKey +plusNaturalName = varQual gHC_NATURAL (fsLit "plusNatural") plusNaturalIdKey +minusNaturalName = varQual gHC_NATURAL (fsLit "minusNatural") minusNaturalIdKey +timesNaturalName = varQual gHC_NATURAL (fsLit "timesNatural") timesNaturalIdKey +mkNaturalName = varQual gHC_NATURAL (fsLit "mkNatural") mkNaturalIdKey +wordToNaturalName = varQual gHC_NATURAL (fsLit "wordToNatural#") wordToNaturalIdKey + -- GHC.Real types and classes rationalTyConName, ratioTyConName, ratioDataConName, realClassName, integralClassName, realFracClassName, fractionalClassName, @@ -2388,8 +2404,17 @@ makeStaticKey :: Unique makeStaticKey = mkPreludeMiscIdUnique 561 -- Natural -naturalFromIntegerIdKey :: Unique +naturalFromIntegerIdKey, naturalToIntegerIdKey, plusNaturalIdKey, + minusNaturalIdKey, timesNaturalIdKey, mkNaturalIdKey, + naturalSDataConKey, wordToNaturalIdKey :: Unique naturalFromIntegerIdKey = mkPreludeMiscIdUnique 562 +naturalToIntegerIdKey = mkPreludeMiscIdUnique 563 +plusNaturalIdKey = mkPreludeMiscIdUnique 564 +minusNaturalIdKey = mkPreludeMiscIdUnique 565 +timesNaturalIdKey = mkPreludeMiscIdUnique 566 +mkNaturalIdKey = mkPreludeMiscIdUnique 567 +naturalSDataConKey = mkPreludeMiscIdUnique 568 +wordToNaturalIdKey = mkPreludeMiscIdUnique 569 {- ************************************************************************ diff --git a/compiler/prelude/PrelRules.hs b/compiler/prelude/PrelRules.hs index 84e4173a28..369ba4c264 100644 --- a/compiler/prelude/PrelRules.hs +++ b/compiler/prelude/PrelRules.hs @@ -371,12 +371,11 @@ cmpOp dflags cmp = go -- These compares are at different types go (MachChar i1) (MachChar i2) = done (i1 `cmp` i2) - go (MachInt i1) (MachInt i2) = done (i1 `cmp` i2) - go (MachInt64 i1) (MachInt64 i2) = done (i1 `cmp` i2) - go (MachWord i1) (MachWord i2) = done (i1 `cmp` i2) - go (MachWord64 i1) (MachWord64 i2) = done (i1 `cmp` i2) go (MachFloat i1) (MachFloat i2) = done (i1 `cmp` i2) go (MachDouble i1) (MachDouble i2) = done (i1 `cmp` i2) + go (LitNumber nt1 i1 _) (LitNumber nt2 i2 _) + | nt1 /= nt2 = Nothing + | otherwise = done (i1 `cmp` i2) go _ _ = Nothing -------------------------- @@ -386,12 +385,13 @@ negOp _ (MachFloat 0.0) = Nothing -- can't represent -0.0 as a Rational negOp dflags (MachFloat f) = Just (mkFloatVal dflags (-f)) negOp _ (MachDouble 0.0) = Nothing negOp dflags (MachDouble d) = Just (mkDoubleVal dflags (-d)) -negOp dflags (MachInt i) = intResult dflags (-i) +negOp dflags (LitNumber nt i t) + | litNumIsSigned nt = Just (Lit (mkLitNumberWrap dflags nt (-i) t)) negOp _ _ = Nothing complementOp :: DynFlags -> Literal -> Maybe CoreExpr -- Binary complement -complementOp dflags (MachWord i) = wordResult dflags (complement i) -complementOp dflags (MachInt i) = intResult dflags (complement i) +complementOp dflags (LitNumber nt i t) = + Just (Lit (mkLitNumberWrap dflags nt (complement i) t)) complementOp _ _ = Nothing -------------------------- @@ -403,7 +403,7 @@ intOp2 = intOp2' . const intOp2' :: (Integral a, Integral b) => (DynFlags -> a -> b -> Integer) -> DynFlags -> Literal -> Literal -> Maybe CoreExpr -intOp2' op dflags (MachInt i1) (MachInt i2) = +intOp2' op dflags (LitNumber LitNumInt i1 _) (LitNumber LitNumInt i2 _) = let o = op dflags in intResult dflags (fromInteger i1 `o` fromInteger i2) intOp2' _ _ _ _ = Nothing -- Could find LitLit @@ -411,7 +411,7 @@ intOp2' _ _ _ _ = Nothing -- Could find LitLit intOpC2 :: (Integral a, Integral b) => (a -> b -> Integer) -> DynFlags -> Literal -> Literal -> Maybe CoreExpr -intOpC2 op dflags (MachInt i1) (MachInt i2) = do +intOpC2 op dflags (LitNumber LitNumInt i1 _) (LitNumber LitNumInt i2 _) = do intCResult dflags (fromInteger i1 `op` fromInteger i2) intOpC2 _ _ _ _ = Nothing -- Could find LitLit @@ -438,14 +438,14 @@ retLitNoC l = do dflags <- getDynFlags wordOp2 :: (Integral a, Integral b) => (a -> b -> Integer) -> DynFlags -> Literal -> Literal -> Maybe CoreExpr -wordOp2 op dflags (MachWord w1) (MachWord w2) +wordOp2 op dflags (LitNumber LitNumWord w1 _) (LitNumber LitNumWord w2 _) = wordResult dflags (fromInteger w1 `op` fromInteger w2) wordOp2 _ _ _ _ = Nothing -- Could find LitLit wordOpC2 :: (Integral a, Integral b) => (a -> b -> Integer) -> DynFlags -> Literal -> Literal -> Maybe CoreExpr -wordOpC2 op dflags (MachWord w1) (MachWord w2) = +wordOpC2 op dflags (LitNumber LitNumWord w1 _) (LitNumber LitNumWord w2 _) = wordCResult dflags (fromInteger w1 `op` fromInteger w2) wordOpC2 _ _ _ _ = Nothing -- Could find LitLit @@ -454,7 +454,7 @@ shiftRule :: (DynFlags -> Integer -> Int -> Integer) -> RuleM CoreExpr -- See Note [Guarding against silly shifts] shiftRule shift_op = do { dflags <- getDynFlags - ; [e1, Lit (MachInt shift_len)] <- getArgs + ; [e1, Lit (LitNumber LitNumInt shift_len _)] <- getArgs ; case e1 of _ | shift_len == 0 -> return e1 @@ -463,13 +463,10 @@ shiftRule shift_op ("Bad shift length" ++ show shift_len)) -- Do the shift at type Integer, but shift length is Int - Lit (MachInt x) + Lit (LitNumber nt x t) -> let op = shift_op dflags - in liftMaybe $ intResult dflags (x `op` fromInteger shift_len) - - Lit (MachWord x) - -> let op = shift_op dflags - in liftMaybe $ wordResult dflags (x `op` fromInteger shift_len) + y = x `op` fromInteger shift_len + in liftMaybe $ Just (Lit (mkLitNumberWrap dflags nt y t)) _ -> mzero } @@ -560,20 +557,26 @@ mkRuleFn dflags Le _ (Lit lit) | isMaxBound dflags lit = Just $ trueValInt dfla mkRuleFn _ _ _ _ = Nothing isMinBound :: DynFlags -> Literal -> Bool -isMinBound _ (MachChar c) = c == minBound -isMinBound dflags (MachInt i) = i == tARGET_MIN_INT dflags -isMinBound _ (MachInt64 i) = i == toInteger (minBound :: Int64) -isMinBound _ (MachWord i) = i == 0 -isMinBound _ (MachWord64 i) = i == 0 -isMinBound _ _ = False +isMinBound _ (MachChar c) = c == minBound +isMinBound dflags (LitNumber nt i _) = case nt of + LitNumInt -> i == tARGET_MIN_INT dflags + LitNumInt64 -> i == toInteger (minBound :: Int64) + LitNumWord -> i == 0 + LitNumWord64 -> i == 0 + LitNumNatural -> i == 0 + LitNumInteger -> False +isMinBound _ _ = False isMaxBound :: DynFlags -> Literal -> Bool -isMaxBound _ (MachChar c) = c == maxBound -isMaxBound dflags (MachInt i) = i == tARGET_MAX_INT dflags -isMaxBound _ (MachInt64 i) = i == toInteger (maxBound :: Int64) -isMaxBound dflags (MachWord i) = i == tARGET_MAX_WORD dflags -isMaxBound _ (MachWord64 i) = i == toInteger (maxBound :: Word64) -isMaxBound _ _ = False +isMaxBound _ (MachChar c) = c == maxBound +isMaxBound dflags (LitNumber nt i _) = case nt of + LitNumInt -> i == tARGET_MAX_INT dflags + LitNumInt64 -> i == toInteger (maxBound :: Int64) + LitNumWord -> i == tARGET_MAX_WORD dflags + LitNumWord64 -> i == toInteger (maxBound :: Word64) + LitNumNatural -> False + LitNumInteger -> False +isMaxBound _ _ = False -- | Create an Int literal expression while ensuring the given Integer is in the -- target Int range @@ -961,7 +964,7 @@ tagToEnumRule :: RuleM CoreExpr -- If data T a = A | B | C -- then tag2Enum# (T ty) 2# --> B ty tagToEnumRule = do - [Type ty, Lit (MachInt i)] <- getArgs + [Type ty, Lit (LitNumber LitNumInt i _)] <- getArgs case splitTyConApp_maybe ty of Just (tycon, tc_args) | isEnumerationTyCon tycon -> do let tag = fromInteger i @@ -1135,7 +1138,7 @@ builtinRules [ nonZeroLit 1 >> binaryLit (intOp2 div) , leftZero zeroi , do - [arg, Lit (MachInt d)] <- getArgs + [arg, Lit (LitNumber LitNumInt d _)] <- getArgs Just n <- return $ exactLog2 d dflags <- getDynFlags return $ Var (mkPrimOpId ISraOp) `App` arg `App` mkIntVal dflags n @@ -1144,7 +1147,7 @@ builtinRules [ nonZeroLit 1 >> binaryLit (intOp2 mod) , leftZero zeroi , do - [arg, Lit (MachInt d)] <- getArgs + [arg, Lit (LitNumber LitNumInt d _)] <- getArgs Just _ <- return $ exactLog2 d dflags <- getDynFlags return $ Var (mkPrimOpId AndIOp) @@ -1152,6 +1155,7 @@ builtinRules ] ] ++ builtinIntegerRules + ++ builtinNaturalRules {-# NOINLINE builtinRules #-} -- there is no benefit to inlining these yet, despite this, GHC produces -- unfoldings for this regardless since the floated list entries look small. @@ -1268,6 +1272,31 @@ builtinIntegerRules = = BuiltinRule { ru_name = fsLit str, ru_fn = name, ru_nargs = 2, ru_try = match_rationalTo mkLit } +builtinNaturalRules :: [CoreRule] +builtinNaturalRules = + [rule_binop "plusNatural" plusNaturalName (+) + ,rule_partial_binop "minusNatural" minusNaturalName (\a b -> if a >= b then Just (a - b) else Nothing) + ,rule_binop "timesNatural" timesNaturalName (*) + ,rule_NaturalFromInteger "naturalFromInteger" naturalFromIntegerName + ,rule_NaturalToInteger "naturalToInteger" naturalToIntegerName + ,rule_WordToNatural "wordToNatural" wordToNaturalName + ] + where rule_binop str name op + = BuiltinRule { ru_name = fsLit str, ru_fn = name, ru_nargs = 2, + ru_try = match_Natural_binop op } + rule_partial_binop str name op + = BuiltinRule { ru_name = fsLit str, ru_fn = name, ru_nargs = 2, + ru_try = match_Natural_partial_binop op } + rule_NaturalToInteger str name + = BuiltinRule { ru_name = fsLit str, ru_fn = name, ru_nargs = 1, + ru_try = match_NaturalToInteger } + rule_NaturalFromInteger str name + = BuiltinRule { ru_name = fsLit str, ru_fn = name, ru_nargs = 1, + ru_try = match_NaturalFromInteger } + rule_WordToNatural str name + = BuiltinRule { ru_name = fsLit str, ru_fn = name, ru_nargs = 1, + ru_try = match_WordToNatural } + --------------------------------------------------- -- The rule is this: -- unpackFoldrCString# "foo" c (unpackFoldrCString# "baz" c n) @@ -1359,34 +1388,65 @@ match_IntToInteger = match_IntToInteger_unop id match_WordToInteger :: RuleFun match_WordToInteger _ id_unf id [xl] - | Just (MachWord x) <- exprIsLiteral_maybe id_unf xl + | Just (LitNumber LitNumWord x _) <- exprIsLiteral_maybe id_unf xl = case splitFunTy_maybe (idType id) of Just (_, integerTy) -> - Just (Lit (LitInteger x integerTy)) + Just (Lit (mkLitInteger x integerTy)) _ -> panic "match_WordToInteger: Id has the wrong type" match_WordToInteger _ _ _ _ = Nothing match_Int64ToInteger :: RuleFun match_Int64ToInteger _ id_unf id [xl] - | Just (MachInt64 x) <- exprIsLiteral_maybe id_unf xl + | Just (LitNumber LitNumInt64 x _) <- exprIsLiteral_maybe id_unf xl = case splitFunTy_maybe (idType id) of Just (_, integerTy) -> - Just (Lit (LitInteger x integerTy)) + Just (Lit (mkLitInteger x integerTy)) _ -> panic "match_Int64ToInteger: Id has the wrong type" match_Int64ToInteger _ _ _ _ = Nothing match_Word64ToInteger :: RuleFun match_Word64ToInteger _ id_unf id [xl] - | Just (MachWord64 x) <- exprIsLiteral_maybe id_unf xl + | Just (LitNumber LitNumWord64 x _) <- exprIsLiteral_maybe id_unf xl = case splitFunTy_maybe (idType id) of Just (_, integerTy) -> - Just (Lit (LitInteger x integerTy)) + Just (Lit (mkLitInteger x integerTy)) _ -> panic "match_Word64ToInteger: Id has the wrong type" match_Word64ToInteger _ _ _ _ = Nothing +match_NaturalToInteger :: RuleFun +match_NaturalToInteger _ id_unf id [xl] + | Just (LitNumber LitNumNatural x _) <- exprIsLiteral_maybe id_unf xl + = case splitFunTy_maybe (idType id) of + Just (_, naturalTy) -> + Just (Lit (LitNumber LitNumInteger x naturalTy)) + _ -> + panic "match_NaturalToInteger: Id has the wrong type" +match_NaturalToInteger _ _ _ _ = Nothing + +match_NaturalFromInteger :: RuleFun +match_NaturalFromInteger _ id_unf id [xl] + | Just (LitNumber LitNumInteger x _) <- exprIsLiteral_maybe id_unf xl + , x >= 0 + = case splitFunTy_maybe (idType id) of + Just (_, naturalTy) -> + Just (Lit (LitNumber LitNumNatural x naturalTy)) + _ -> + panic "match_NaturalFromInteger: Id has the wrong type" +match_NaturalFromInteger _ _ _ _ = Nothing + +match_WordToNatural :: RuleFun +match_WordToNatural _ id_unf id [xl] + | Just (LitNumber LitNumWord x _) <- exprIsLiteral_maybe id_unf xl + = case splitFunTy_maybe (idType id) of + Just (_, naturalTy) -> + Just (Lit (LitNumber LitNumNatural x naturalTy)) + _ -> + panic "match_WordToNatural: Id has the wrong type" +match_WordToNatural _ _ _ _ = Nothing + ------------------------------------------------- {- Note [Rewriting bitInteger] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -1397,7 +1457,7 @@ constant-folding (see Trac #8832). The bitInteger rule above provides constant f specifically for this function. There is, however, a bit of trickiness here when it comes to ranges. While the -AST encodes all integers (even MachInts) as Integers, `bit` expects the bit +AST encodes all integers as Integers, `bit` expects the bit index to be given as an Int. Hence we coerce to an Int in the rule definition. This will behave a bit funny for constants larger than the word size, but the user should expect some funniness given that they will have at very least ignored a @@ -1407,7 +1467,7 @@ warning in this case. match_bitInteger :: RuleFun -- Just for GHC.Integer.Type.bitInteger :: Int# -> Integer match_bitInteger dflags id_unf fn [arg] - | Just (MachInt x) <- exprIsLiteral_maybe id_unf arg + | Just (LitNumber LitNumInt x _) <- exprIsLiteral_maybe id_unf arg , x >= 0 , x <= (wordSizeInBits dflags - 1) -- Make sure x is small enough to yield a decently small iteger @@ -1417,7 +1477,7 @@ match_bitInteger dflags id_unf fn [arg] , let x_int = fromIntegral x :: Int = case splitFunTy_maybe (idType fn) of Just (_, integerTy) - -> Just (Lit (LitInteger (bit x_int) integerTy)) + -> Just (Lit (LitNumber LitNumInteger (bit x_int) integerTy)) _ -> panic "match_IntToInteger_unop: Id has the wrong type" match_bitInteger _ _ _ _ = Nothing @@ -1428,71 +1488,86 @@ match_Integer_convert :: Num a => (DynFlags -> a -> Expr CoreBndr) -> RuleFun match_Integer_convert convert dflags id_unf _ [xl] - | Just (LitInteger x _) <- exprIsLiteral_maybe id_unf xl + | Just (LitNumber LitNumInteger x _) <- exprIsLiteral_maybe id_unf xl = Just (convert dflags (fromInteger x)) match_Integer_convert _ _ _ _ _ = Nothing match_Integer_unop :: (Integer -> Integer) -> RuleFun match_Integer_unop unop _ id_unf _ [xl] - | Just (LitInteger x i) <- exprIsLiteral_maybe id_unf xl - = Just (Lit (LitInteger (unop x) i)) + | Just (LitNumber LitNumInteger x i) <- exprIsLiteral_maybe id_unf xl + = Just (Lit (LitNumber LitNumInteger (unop x) i)) match_Integer_unop _ _ _ _ _ = Nothing match_IntToInteger_unop :: (Integer -> Integer) -> RuleFun match_IntToInteger_unop unop _ id_unf fn [xl] - | Just (MachInt x) <- exprIsLiteral_maybe id_unf xl + | Just (LitNumber LitNumInt x _) <- exprIsLiteral_maybe id_unf xl = case splitFunTy_maybe (idType fn) of Just (_, integerTy) -> - Just (Lit (LitInteger (unop x) integerTy)) + Just (Lit (LitNumber LitNumInteger (unop x) integerTy)) _ -> panic "match_IntToInteger_unop: Id has the wrong type" match_IntToInteger_unop _ _ _ _ _ = Nothing match_Integer_binop :: (Integer -> Integer -> Integer) -> RuleFun match_Integer_binop binop _ id_unf _ [xl,yl] - | Just (LitInteger x i) <- exprIsLiteral_maybe id_unf xl - , Just (LitInteger y _) <- exprIsLiteral_maybe id_unf yl - = Just (Lit (LitInteger (x `binop` y) i)) + | Just (LitNumber LitNumInteger x i) <- exprIsLiteral_maybe id_unf xl + , Just (LitNumber LitNumInteger y _) <- exprIsLiteral_maybe id_unf yl + = Just (Lit (mkLitInteger (x `binop` y) i)) match_Integer_binop _ _ _ _ _ = Nothing +match_Natural_binop :: (Integer -> Integer -> Integer) -> RuleFun +match_Natural_binop binop _ id_unf _ [xl,yl] + | Just (LitNumber LitNumNatural x i) <- exprIsLiteral_maybe id_unf xl + , Just (LitNumber LitNumNatural y _) <- exprIsLiteral_maybe id_unf yl + = Just (Lit (mkLitNatural (x `binop` y) i)) +match_Natural_binop _ _ _ _ _ = Nothing + +match_Natural_partial_binop :: (Integer -> Integer -> Maybe Integer) -> RuleFun +match_Natural_partial_binop binop _ id_unf _ [xl,yl] + | Just (LitNumber LitNumNatural x i) <- exprIsLiteral_maybe id_unf xl + , Just (LitNumber LitNumNatural y _) <- exprIsLiteral_maybe id_unf yl + , Just z <- x `binop` y + = Just (Lit (mkLitNatural z i)) +match_Natural_partial_binop _ _ _ _ _ = Nothing + -- This helper is used for the quotRem and divMod functions match_Integer_divop_both :: (Integer -> Integer -> (Integer, Integer)) -> RuleFun match_Integer_divop_both divop _ id_unf _ [xl,yl] - | Just (LitInteger x t) <- exprIsLiteral_maybe id_unf xl - , Just (LitInteger y _) <- exprIsLiteral_maybe id_unf yl + | Just (LitNumber LitNumInteger x t) <- exprIsLiteral_maybe id_unf xl + , Just (LitNumber LitNumInteger y _) <- exprIsLiteral_maybe id_unf yl , y /= 0 , (r,s) <- x `divop` y - = Just $ mkCoreUbxTup [t,t] [Lit (LitInteger r t), Lit (LitInteger s t)] + = Just $ mkCoreUbxTup [t,t] [Lit (mkLitInteger r t), Lit (mkLitInteger s t)] match_Integer_divop_both _ _ _ _ _ = Nothing -- This helper is used for the quot and rem functions match_Integer_divop_one :: (Integer -> Integer -> Integer) -> RuleFun match_Integer_divop_one divop _ id_unf _ [xl,yl] - | Just (LitInteger x i) <- exprIsLiteral_maybe id_unf xl - , Just (LitInteger y _) <- exprIsLiteral_maybe id_unf yl + | Just (LitNumber LitNumInteger x i) <- exprIsLiteral_maybe id_unf xl + , Just (LitNumber LitNumInteger y _) <- exprIsLiteral_maybe id_unf yl , y /= 0 - = Just (Lit (LitInteger (x `divop` y) i)) + = Just (Lit (mkLitInteger (x `divop` y) i)) match_Integer_divop_one _ _ _ _ _ = Nothing match_Integer_Int_binop :: (Integer -> Int -> Integer) -> RuleFun match_Integer_Int_binop binop _ id_unf _ [xl,yl] - | Just (LitInteger x i) <- exprIsLiteral_maybe id_unf xl - , Just (MachInt y) <- exprIsLiteral_maybe id_unf yl - = Just (Lit (LitInteger (x `binop` fromIntegral y) i)) + | Just (LitNumber LitNumInteger x i) <- exprIsLiteral_maybe id_unf xl + , Just (LitNumber LitNumInt y _) <- exprIsLiteral_maybe id_unf yl + = Just (Lit (mkLitInteger (x `binop` fromIntegral y) i)) match_Integer_Int_binop _ _ _ _ _ = Nothing match_Integer_binop_Prim :: (Integer -> Integer -> Bool) -> RuleFun match_Integer_binop_Prim binop dflags id_unf _ [xl, yl] - | Just (LitInteger x _) <- exprIsLiteral_maybe id_unf xl - , Just (LitInteger y _) <- exprIsLiteral_maybe id_unf yl + | Just (LitNumber LitNumInteger x _) <- exprIsLiteral_maybe id_unf xl + , Just (LitNumber LitNumInteger y _) <- exprIsLiteral_maybe id_unf yl = Just (if x `binop` y then trueValInt dflags else falseValInt dflags) match_Integer_binop_Prim _ _ _ _ _ = Nothing match_Integer_binop_Ordering :: (Integer -> Integer -> Ordering) -> RuleFun match_Integer_binop_Ordering binop _ id_unf _ [xl, yl] - | Just (LitInteger x _) <- exprIsLiteral_maybe id_unf xl - , Just (LitInteger y _) <- exprIsLiteral_maybe id_unf yl + | Just (LitNumber LitNumInteger x _) <- exprIsLiteral_maybe id_unf xl + , Just (LitNumber LitNumInteger y _) <- exprIsLiteral_maybe id_unf yl = Just $ case x `binop` y of LT -> ltVal EQ -> eqVal @@ -1503,8 +1578,8 @@ match_Integer_Int_encodeFloat :: RealFloat a => (a -> Expr CoreBndr) -> RuleFun match_Integer_Int_encodeFloat mkLit _ id_unf _ [xl,yl] - | Just (LitInteger x _) <- exprIsLiteral_maybe id_unf xl - , Just (MachInt y) <- exprIsLiteral_maybe id_unf yl + | Just (LitNumber LitNumInteger x _) <- exprIsLiteral_maybe id_unf xl + , Just (LitNumber LitNumInt y _) <- exprIsLiteral_maybe id_unf yl = Just (mkLit $ encodeFloat x (fromInteger y)) match_Integer_Int_encodeFloat _ _ _ _ _ = Nothing @@ -1522,14 +1597,14 @@ match_rationalTo :: RealFloat a => (a -> Expr CoreBndr) -> RuleFun match_rationalTo mkLit _ id_unf _ [xl, yl] - | Just (LitInteger x _) <- exprIsLiteral_maybe id_unf xl - , Just (LitInteger y _) <- exprIsLiteral_maybe id_unf yl + | Just (LitNumber LitNumInteger x _) <- exprIsLiteral_maybe id_unf xl + , Just (LitNumber LitNumInteger y _) <- exprIsLiteral_maybe id_unf yl , y /= 0 = Just (mkLit (fromRational (x % y))) match_rationalTo _ _ _ _ _ = Nothing match_decodeDouble :: RuleFun -match_decodeDouble _ id_unf fn [xl] +match_decodeDouble dflags id_unf fn [xl] | Just (MachDouble x) <- exprIsLiteral_maybe id_unf xl = case splitFunTy_maybe (idType fn) of Just (_, res) @@ -1537,8 +1612,8 @@ match_decodeDouble _ id_unf fn [xl] -> case decodeFloat (fromRational x :: Double) of (y, z) -> Just $ mkCoreUbxTup [integerTy, intHashTy] - [Lit (LitInteger y integerTy), - Lit (MachInt (toInteger z))] + [Lit (mkLitInteger y integerTy), + Lit (mkMachInt dflags (toInteger z))] _ -> pprPanic "match_decodeDouble: Id has the wrong type" (ppr fn <+> dcolon <+> ppr (idType fn)) @@ -1670,7 +1745,8 @@ tx_con_tte dflags (DataAlt dc) -- See Note [caseRules for tagToEnum] tx_con_dtt :: Type -> AltCon -> AltCon tx_con_dtt _ DEFAULT = DEFAULT -tx_con_dtt ty (LitAlt (MachInt i)) = DataAlt (get_con ty (fromInteger i)) +tx_con_dtt ty (LitAlt (LitNumber LitNumInt i _)) + = DataAlt (get_con ty (fromInteger i)) tx_con_dtt _ alt = pprPanic "caseRules" (ppr alt) get_con :: Type -> ConTagZ -> DataCon @@ -1711,7 +1787,7 @@ We don't want to get this! DEFAULT -> e1 DEFAULT -> e2 -Instead, we deal with turning one branch into DEAFULT in SimplUtils +Instead, we deal with turning one branch into DEFAULT in SimplUtils (add_default in mkCase3). Note [caseRules for dataToTag] diff --git a/compiler/prelude/TysWiredIn.hs b/compiler/prelude/TysWiredIn.hs index 1156d810b9..b96581e482 100644 --- a/compiler/prelude/TysWiredIn.hs +++ b/compiler/prelude/TysWiredIn.hs @@ -271,11 +271,11 @@ nilDataConName = mkWiredInDataConName BuiltInSyntax gHC_TYPES (fsLit "[]") ni consDataConName = mkWiredInDataConName BuiltInSyntax gHC_TYPES (fsLit ":") consDataConKey consDataCon maybeTyConName, nothingDataConName, justDataConName :: Name -maybeTyConName = mkWiredInTyConName UserSyntax gHC_BASE (fsLit "Maybe") +maybeTyConName = mkWiredInTyConName UserSyntax gHC_MAYBE (fsLit "Maybe") maybeTyConKey maybeTyCon -nothingDataConName = mkWiredInDataConName UserSyntax gHC_BASE (fsLit "Nothing") +nothingDataConName = mkWiredInDataConName UserSyntax gHC_MAYBE (fsLit "Nothing") nothingDataConKey nothingDataCon -justDataConName = mkWiredInDataConName UserSyntax gHC_BASE (fsLit "Just") +justDataConName = mkWiredInDataConName UserSyntax gHC_MAYBE (fsLit "Just") justDataConKey justDataCon wordTyConName, wordDataConName, word8TyConName, word8DataConName :: Name diff --git a/compiler/simplStg/UnariseStg.hs b/compiler/simplStg/UnariseStg.hs index bcf699b369..5c271c2ea0 100644 --- a/compiler/simplStg/UnariseStg.hs +++ b/compiler/simplStg/UnariseStg.hs @@ -203,7 +203,7 @@ import CoreSyn import DataCon import FastString (FastString, mkFastString) import Id -import Literal (Literal (..), literalType) +import Literal import MkCore (aBSENT_SUM_FIELD_ERROR_ID) import MkId (voidPrimId, voidArgId) import MonadUtils (mapAccumLM) @@ -211,7 +211,7 @@ import Outputable import RepType import StgSyn import Type -import TysPrim (intPrimTy) +import TysPrim (intPrimTy,wordPrimTy,word64PrimTy) import TysWiredIn import UniqSupply import Util @@ -478,7 +478,7 @@ unariseSumAlt rho _ (DEFAULT, _, e) unariseSumAlt rho args (DataAlt sumCon, bs, e) = do let rho' = mapSumIdBinders bs args rho e' <- unariseExpr rho' e - return ( LitAlt (MachInt (fromIntegral (dataConTag sumCon))), [], e' ) + return ( LitAlt (LitNumber LitNumInt (fromIntegral (dataConTag sumCon)) intPrimTy), [], e' ) unariseSumAlt _ scrt alt = pprPanic "unariseSumAlt" (ppr scrt $$ ppr alt) @@ -564,7 +564,7 @@ mkUbxSum dc ty_args args0 tag = dataConTag dc layout' = layoutUbxSum sum_slots (mapMaybe (typeSlotTy . stgArgType) args0) - tag_arg = StgLitArg (MachInt (fromIntegral tag)) + tag_arg = StgLitArg (LitNumber LitNumInt (fromIntegral tag) intPrimTy) arg_idxs = IM.fromList (zipEqual "mkUbxSum" layout' args0) mkTupArgs :: Int -> [SlotTy] -> IM.IntMap StgArg -> [StgArg] @@ -579,8 +579,8 @@ mkUbxSum dc ty_args args0 slotRubbishArg :: SlotTy -> StgArg slotRubbishArg PtrSlot = StgVarArg aBSENT_SUM_FIELD_ERROR_ID -- See Note [aBSENT_SUM_FIELD_ERROR_ID] in MkCore - slotRubbishArg WordSlot = StgLitArg (MachWord 0) - slotRubbishArg Word64Slot = StgLitArg (MachWord64 0) + slotRubbishArg WordSlot = StgLitArg (LitNumber LitNumWord 0 wordPrimTy) + slotRubbishArg Word64Slot = StgLitArg (LitNumber LitNumWord64 0 word64PrimTy) slotRubbishArg FloatSlot = StgLitArg (MachFloat 0) slotRubbishArg DoubleSlot = StgLitArg (MachDouble 0) in diff --git a/compiler/stgSyn/CoreToStg.hs b/compiler/stgSyn/CoreToStg.hs index e2ed3953ae..fdd8d5bef3 100644 --- a/compiler/stgSyn/CoreToStg.hs +++ b/compiler/stgSyn/CoreToStg.hs @@ -390,9 +390,10 @@ coreToStgExpr -- on these components, but it in turn is not scrutinised as the basis for any -- decisions. Hence no black holes. --- No LitInteger's should be left by the time this is called. CorePrep --- should have converted them all to a real core representation. -coreToStgExpr (Lit (LitInteger {})) = panic "coreToStgExpr: LitInteger" +-- 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. +coreToStgExpr (Lit (LitNumber LitNumInteger _ _)) = panic "coreToStgExpr: LitInteger" +coreToStgExpr (Lit (LitNumber LitNumNatural _ _)) = panic "coreToStgExpr: LitNatural" coreToStgExpr (Lit l) = return (StgLit l, emptyFVInfo) coreToStgExpr (Var v) = coreToStgApp Nothing v [] [] coreToStgExpr (Coercion _) = coreToStgApp Nothing coercionTokenId [] [] |