{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE LambdaCase #-}
module Futhark.Representation.Primitive
(
IntType (..), allIntTypes
, FloatType (..), allFloatTypes
, PrimType (..), allPrimTypes
, IntValue(..)
, intValue, intValueType, valueIntegral
, FloatValue(..)
, floatValue, floatValueType
, PrimValue(..)
, primValueType
, blankPrimValue
, UnOp (..), allUnOps
, BinOp (..), allBinOps
, ConvOp (..), allConvOps
, CmpOp (..), allCmpOps
, doUnOp
, doComplement
, doAbs, doFAbs
, doSSignum, doUSignum
, doBinOp
, doAdd, doMul, doSDiv, doSMod
, doPow
, doConvOp
, doZExt, doSExt
, doFPConv
, doFPToUI, doFPToSI
, doUIToFP, doSIToFP
, intToInt64, intToWord64
, doCmpOp
, doCmpEq
, doCmpUlt, doCmpUle
, doCmpSlt, doCmpSle
, doFCmpLt, doFCmpLe
, binOpType
, unOpType
, cmpOpType
, convOpType
, primFuns
, zeroIsh
, oneIsh
, negativeIsh
, primBitSize
, primByteSize
, intByteSize
, floatByteSize
, commutativeBinOp
, convOpFun
, prettySigned
)
where
import Control.Applicative
import Data.Binary.IEEE754 (floatToWord, wordToFloat, doubleToWord, wordToDouble)
import Data.Bits
import Data.Int (Int16, Int32, Int64, Int8)
import qualified Data.Map as M
import Data.Word
import Prelude
import Futhark.Util.Pretty
import Futhark.Util (roundFloat, roundDouble)
data IntType = Int8
| Int16
| Int32
| Int64
deriving (Eq, Ord, Show, Enum, Bounded)
instance Pretty IntType where
ppr Int8 = text "i8"
ppr Int16 = text "i16"
ppr Int32 = text "i32"
ppr Int64 = text "i64"
allIntTypes :: [IntType]
allIntTypes = [minBound..maxBound]
data FloatType = Float32
| Float64
deriving (Eq, Ord, Show, Enum, Bounded)
instance Pretty FloatType where
ppr Float32 = text "f32"
ppr Float64 = text "f64"
allFloatTypes :: [FloatType]
allFloatTypes = [minBound..maxBound]
data PrimType = IntType IntType
| FloatType FloatType
| Bool
| Cert
deriving (Eq, Ord, Show)
instance Enum PrimType where
toEnum 0 = IntType Int8
toEnum 1 = IntType Int16
toEnum 2 = IntType Int32
toEnum 3 = IntType Int64
toEnum 4 = FloatType Float32
toEnum 5 = FloatType Float64
toEnum 6 = Bool
toEnum _ = Cert
fromEnum (IntType Int8) = 0
fromEnum (IntType Int16) = 1
fromEnum (IntType Int32) = 2
fromEnum (IntType Int64) = 3
fromEnum (FloatType Float32) = 4
fromEnum (FloatType Float64) = 5
fromEnum Bool = 6
fromEnum Cert = 7
instance Bounded PrimType where
minBound = IntType Int8
maxBound = Cert
instance Pretty PrimType where
ppr (IntType t) = ppr t
ppr (FloatType t) = ppr t
ppr Bool = text "bool"
ppr Cert = text "cert"
allPrimTypes :: [PrimType]
allPrimTypes = map IntType allIntTypes ++
map FloatType allFloatTypes ++
[Bool, Cert]
data IntValue = Int8Value !Int8
| Int16Value !Int16
| Int32Value !Int32
| Int64Value !Int64
deriving (Eq, Ord, Show)
instance Pretty IntValue where
ppr (Int8Value v) = text $ show v ++ "i8"
ppr (Int16Value v) = text $ show v ++ "i16"
ppr (Int32Value v) = text $ show v ++ "i32"
ppr (Int64Value v) = text $ show v ++ "i64"
intValue :: Integral int => IntType -> int -> IntValue
intValue Int8 = Int8Value . fromIntegral
intValue Int16 = Int16Value . fromIntegral
intValue Int32 = Int32Value . fromIntegral
intValue Int64 = Int64Value . fromIntegral
intValueType :: IntValue -> IntType
intValueType Int8Value{} = Int8
intValueType Int16Value{} = Int16
intValueType Int32Value{} = Int32
intValueType Int64Value{} = Int64
valueIntegral ::Integral int => IntValue -> int
valueIntegral (Int8Value v) = fromIntegral v
valueIntegral (Int16Value v) = fromIntegral v
valueIntegral (Int32Value v) = fromIntegral v
valueIntegral (Int64Value v) = fromIntegral v
data FloatValue = Float32Value !Float
| Float64Value !Double
deriving (Eq, Ord, Show)
instance Pretty FloatValue where
ppr (Float32Value v)
| isInfinite v, v >= 0 = text "f32.inf"
| isInfinite v, v < 0 = text "-f32.inf"
| isNaN v = text "f32.nan"
| otherwise = text $ show v ++ "f32"
ppr (Float64Value v)
| isInfinite v, v >= 0 = text "f64.inf"
| isInfinite v, v < 0 = text "-f64.inf"
| isNaN v = text "f64.nan"
| otherwise = text $ show v ++ "f64"
floatValue :: Real num => FloatType -> num -> FloatValue
floatValue Float32 = Float32Value . fromRational . toRational
floatValue Float64 = Float64Value . fromRational . toRational
floatValueType :: FloatValue -> FloatType
floatValueType Float32Value{} = Float32
floatValueType Float64Value{} = Float64
data PrimValue = IntValue !IntValue
| FloatValue !FloatValue
| BoolValue !Bool
| Checked
deriving (Eq, Ord, Show)
instance Pretty PrimValue where
ppr (IntValue v) = ppr v
ppr (BoolValue True) = text "true"
ppr (BoolValue False) = text "false"
ppr (FloatValue v) = ppr v
ppr Checked = text "checked"
primValueType :: PrimValue -> PrimType
primValueType (IntValue v) = IntType $ intValueType v
primValueType (FloatValue v) = FloatType $ floatValueType v
primValueType BoolValue{} = Bool
primValueType Checked = Cert
blankPrimValue :: PrimType -> PrimValue
blankPrimValue (IntType Int8) = IntValue $ Int8Value 0
blankPrimValue (IntType Int16) = IntValue $ Int16Value 0
blankPrimValue (IntType Int32) = IntValue $ Int32Value 0
blankPrimValue (IntType Int64) = IntValue $ Int64Value 0
blankPrimValue (FloatType Float32) = FloatValue $ Float32Value 0.0
blankPrimValue (FloatType Float64) = FloatValue $ Float64Value 0.0
blankPrimValue Bool = BoolValue False
blankPrimValue Cert = Checked
data UnOp = Not
| Complement IntType
| Abs IntType
| FAbs FloatType
| SSignum IntType
| USignum IntType
deriving (Eq, Ord, Show)
data BinOp = Add IntType
| FAdd FloatType
| Sub IntType
| FSub FloatType
| Mul IntType
| FMul FloatType
| UDiv IntType
| SDiv IntType
| FDiv FloatType
| UMod IntType
| SMod IntType
| SQuot IntType
| SRem IntType
| SMin IntType
| UMin IntType
| FMin FloatType
| SMax IntType
| UMax IntType
| FMax FloatType
| Shl IntType
| LShr IntType
| AShr IntType
| And IntType
| Or IntType
| Xor IntType
| Pow IntType
| FPow FloatType
| LogAnd
| LogOr
deriving (Eq, Ord, Show)
data CmpOp = CmpEq PrimType
| CmpUlt IntType
| CmpUle IntType
| CmpSlt IntType
| CmpSle IntType
| FCmpLt FloatType
| FCmpLe FloatType
| CmpLlt
| CmpLle
deriving (Eq, Ord, Show)
data ConvOp = ZExt IntType IntType
| SExt IntType IntType
| FPConv FloatType FloatType
| FPToUI FloatType IntType
| FPToSI FloatType IntType
| UIToFP IntType FloatType
| SIToFP IntType FloatType
| IToB IntType
| BToI IntType
deriving (Eq, Ord, Show)
allUnOps :: [UnOp]
allUnOps = Not :
map Complement [minBound..maxBound] ++
map Abs [minBound..maxBound] ++
map FAbs [minBound..maxBound] ++
map SSignum [minBound..maxBound] ++
map USignum [minBound..maxBound]
allBinOps :: [BinOp]
allBinOps = concat [ map Add allIntTypes
, map FAdd allFloatTypes
, map Sub allIntTypes
, map FSub allFloatTypes
, map Mul allIntTypes
, map FMul allFloatTypes
, map UDiv allIntTypes
, map SDiv allIntTypes
, map FDiv allFloatTypes
, map UMod allIntTypes
, map SMod allIntTypes
, map SQuot allIntTypes
, map SRem allIntTypes
, map SMin allIntTypes
, map UMin allIntTypes
, map FMin allFloatTypes
, map SMax allIntTypes
, map UMax allIntTypes
, map FMax allFloatTypes
, map Shl allIntTypes
, map LShr allIntTypes
, map AShr allIntTypes
, map And allIntTypes
, map Or allIntTypes
, map Xor allIntTypes
, map Pow allIntTypes
, map FPow allFloatTypes
, [LogAnd, LogOr]
]
allCmpOps :: [CmpOp]
allCmpOps = concat [ map CmpEq allPrimTypes
, map CmpUlt allIntTypes
, map CmpUle allIntTypes
, map CmpSlt allIntTypes
, map CmpSle allIntTypes
, map FCmpLt allFloatTypes
, map FCmpLe allFloatTypes
]
allConvOps :: [ConvOp]
allConvOps = concat [ ZExt <$> allIntTypes <*> allIntTypes
, SExt <$> allIntTypes <*> allIntTypes
, FPConv <$> allFloatTypes <*> allFloatTypes
, FPToUI <$> allFloatTypes <*> allIntTypes
, FPToSI <$> allFloatTypes <*> allIntTypes
, UIToFP <$> allIntTypes <*> allFloatTypes
, SIToFP <$> allIntTypes <*> allFloatTypes
, IToB <$> allIntTypes
, BToI <$> allIntTypes
]
doUnOp :: UnOp -> PrimValue -> Maybe PrimValue
doUnOp Not (BoolValue b) = Just $ BoolValue $ not b
doUnOp Complement{} (IntValue v) = Just $ IntValue $ doComplement v
doUnOp Abs{} (IntValue v) = Just $ IntValue $ doAbs v
doUnOp FAbs{} (FloatValue v) = Just $ FloatValue $ doFAbs v
doUnOp SSignum{} (IntValue v) = Just $ IntValue $ doSSignum v
doUnOp USignum{} (IntValue v) = Just $ IntValue $ doUSignum v
doUnOp _ _ = Nothing
doComplement :: IntValue -> IntValue
doComplement v = intValue (intValueType v) $ complement $ intToInt64 v
doAbs :: IntValue -> IntValue
doAbs v = intValue (intValueType v) $ abs $ intToInt64 v
doFAbs :: FloatValue -> FloatValue
doFAbs v = floatValue (floatValueType v) $ abs $ floatToDouble v
doSSignum :: IntValue -> IntValue
doSSignum v = intValue (intValueType v) $ signum $ intToInt64 v
doUSignum :: IntValue -> IntValue
doUSignum v = intValue (intValueType v) $ signum $ intToWord64 v
doBinOp :: BinOp -> PrimValue -> PrimValue -> Maybe PrimValue
doBinOp Add{} = doIntBinOp doAdd
doBinOp FAdd{} = doFloatBinOp (+) (+)
doBinOp Sub{} = doIntBinOp doSub
doBinOp FSub{} = doFloatBinOp (-) (-)
doBinOp Mul{} = doIntBinOp doMul
doBinOp FMul{} = doFloatBinOp (*) (*)
doBinOp UDiv{} = doRiskyIntBinOp doUDiv
doBinOp SDiv{} = doRiskyIntBinOp doSDiv
doBinOp FDiv{} = doFloatBinOp (/) (/)
doBinOp UMod{} = doRiskyIntBinOp doUMod
doBinOp SMod{} = doRiskyIntBinOp doSMod
doBinOp SQuot{} = doRiskyIntBinOp doSQuot
doBinOp SRem{} = doRiskyIntBinOp doSRem
doBinOp SMin{} = doIntBinOp doSMin
doBinOp UMin{} = doIntBinOp doUMin
doBinOp FMin{} = doFloatBinOp min min
doBinOp SMax{} = doIntBinOp doSMax
doBinOp UMax{} = doIntBinOp doUMax
doBinOp FMax{} = doFloatBinOp max max
doBinOp Shl{} = doIntBinOp doShl
doBinOp LShr{} = doIntBinOp doLShr
doBinOp AShr{} = doIntBinOp doAShr
doBinOp And{} = doIntBinOp doAnd
doBinOp Or{} = doIntBinOp doOr
doBinOp Xor{} = doIntBinOp doXor
doBinOp Pow{} = doRiskyIntBinOp doPow
doBinOp FPow{} = doFloatBinOp (**) (**)
doBinOp LogAnd{} = doBoolBinOp (&&)
doBinOp LogOr{} = doBoolBinOp (||)
doIntBinOp :: (IntValue -> IntValue -> IntValue) -> PrimValue -> PrimValue
-> Maybe PrimValue
doIntBinOp f (IntValue v1) (IntValue v2) =
Just $ IntValue $ f v1 v2
doIntBinOp _ _ _ = Nothing
doRiskyIntBinOp :: (IntValue -> IntValue -> Maybe IntValue) -> PrimValue -> PrimValue
-> Maybe PrimValue
doRiskyIntBinOp f (IntValue v1) (IntValue v2) =
IntValue <$> f v1 v2
doRiskyIntBinOp _ _ _ = Nothing
doFloatBinOp :: (Float -> Float -> Float)
-> (Double -> Double -> Double)
-> PrimValue -> PrimValue
-> Maybe PrimValue
doFloatBinOp f32 _ (FloatValue (Float32Value v1)) (FloatValue (Float32Value v2)) =
Just $ FloatValue $ Float32Value $ f32 v1 v2
doFloatBinOp _ f64 (FloatValue (Float64Value v1)) (FloatValue (Float64Value v2)) =
Just $ FloatValue $ Float64Value $ f64 v1 v2
doFloatBinOp _ _ _ _ = Nothing
doBoolBinOp :: (Bool -> Bool -> Bool) -> PrimValue -> PrimValue
-> Maybe PrimValue
doBoolBinOp f (BoolValue v1) (BoolValue v2) =
Just $ BoolValue $ f v1 v2
doBoolBinOp _ _ _ = Nothing
doAdd :: IntValue -> IntValue -> IntValue
doAdd v1 v2 = intValue (intValueType v1) $ intToInt64 v1 + intToInt64 v2
doSub :: IntValue -> IntValue -> IntValue
doSub v1 v2 = intValue (intValueType v1) $ intToInt64 v1 - intToInt64 v2
doMul :: IntValue -> IntValue -> IntValue
doMul v1 v2 = intValue (intValueType v1) $ intToInt64 v1 * intToInt64 v2
doUDiv :: IntValue -> IntValue -> Maybe IntValue
doUDiv v1 v2
| zeroIshInt v2 = Nothing
| otherwise = Just $ intValue (intValueType v1) $ intToWord64 v1 `div` intToWord64 v2
doSDiv :: IntValue -> IntValue -> Maybe IntValue
doSDiv v1 v2
| zeroIshInt v2 = Nothing
| otherwise = Just $ intValue (intValueType v1) $ intToInt64 v1 `div` intToInt64 v2
doUMod :: IntValue -> IntValue -> Maybe IntValue
doUMod v1 v2
| zeroIshInt v2 = Nothing
| otherwise = Just $ intValue (intValueType v1) $ intToWord64 v1 `mod` intToWord64 v2
doSMod :: IntValue -> IntValue -> Maybe IntValue
doSMod v1 v2
| zeroIshInt v2 = Nothing
| otherwise = Just $ intValue (intValueType v1) $ intToInt64 v1 `mod` intToInt64 v2
doSQuot :: IntValue -> IntValue -> Maybe IntValue
doSQuot v1 v2
| zeroIshInt v2 = Nothing
| otherwise = Just $ intValue (intValueType v1) $ intToInt64 v1 `quot` intToInt64 v2
doSRem :: IntValue -> IntValue -> Maybe IntValue
doSRem v1 v2
| zeroIshInt v2 = Nothing
| otherwise = Just $ intValue (intValueType v1) $ intToInt64 v1 `rem` intToInt64 v2
doSMin :: IntValue -> IntValue -> IntValue
doSMin v1 v2 = intValue (intValueType v1) $ intToInt64 v1 `min` intToInt64 v2
doUMin :: IntValue -> IntValue -> IntValue
doUMin v1 v2 = intValue (intValueType v1) $ intToWord64 v1 `min` intToWord64 v2
doSMax :: IntValue -> IntValue -> IntValue
doSMax v1 v2 = intValue (intValueType v1) $ intToInt64 v1 `max` intToInt64 v2
doUMax :: IntValue -> IntValue -> IntValue
doUMax v1 v2 = intValue (intValueType v1) $ intToWord64 v1 `max` intToWord64 v2
doShl :: IntValue -> IntValue -> IntValue
doShl v1 v2 = intValue (intValueType v1) $ intToInt64 v1 `shift` intToInt v2
doLShr :: IntValue -> IntValue -> IntValue
doLShr v1 v2 = intValue (intValueType v1) $ intToWord64 v1 `shift` negate (intToInt v2)
doAShr :: IntValue -> IntValue -> IntValue
doAShr v1 v2 = intValue (intValueType v1) $ intToInt64 v1 `shift` negate (intToInt v2)
doAnd :: IntValue -> IntValue -> IntValue
doAnd v1 v2 = intValue (intValueType v1) $ intToWord64 v1 .&. intToWord64 v2
doOr :: IntValue -> IntValue -> IntValue
doOr v1 v2 = intValue (intValueType v1) $ intToWord64 v1 .|. intToWord64 v2
doXor :: IntValue -> IntValue -> IntValue
doXor v1 v2 = intValue (intValueType v1) $ intToWord64 v1 `xor` intToWord64 v2
doPow :: IntValue -> IntValue -> Maybe IntValue
doPow v1 v2
| negativeIshInt v2 = Nothing
| otherwise = Just $ intValue (intValueType v1) $ intToInt64 v1 ^ intToInt64 v2
doConvOp :: ConvOp -> PrimValue -> Maybe PrimValue
doConvOp (ZExt _ to) (IntValue v) = Just $ IntValue $ doZExt v to
doConvOp (SExt _ to) (IntValue v) = Just $ IntValue $ doSExt v to
doConvOp (FPConv _ to) (FloatValue v) = Just $ FloatValue $ doFPConv v to
doConvOp (FPToUI _ to) (FloatValue v) = Just $ IntValue $ doFPToUI v to
doConvOp (FPToSI _ to) (FloatValue v) = Just $ IntValue $ doFPToSI v to
doConvOp (UIToFP _ to) (IntValue v) = Just $ FloatValue $ doUIToFP v to
doConvOp (SIToFP _ to) (IntValue v) = Just $ FloatValue $ doSIToFP v to
doConvOp (IToB _) (IntValue v) = Just $ BoolValue $ intToInt64 v /= 0
doConvOp (BToI to) (BoolValue v) = Just $ IntValue $ intValue to $ if v then 1 else 0::Int
doConvOp _ _ = Nothing
doZExt :: IntValue -> IntType -> IntValue
doZExt (Int8Value x) t = intValue t $ toInteger (fromIntegral x :: Word8)
doZExt (Int16Value x) t = intValue t $ toInteger (fromIntegral x :: Word16)
doZExt (Int32Value x) t = intValue t $ toInteger (fromIntegral x :: Word32)
doZExt (Int64Value x) t = intValue t $ toInteger (fromIntegral x :: Word64)
doSExt :: IntValue -> IntType -> IntValue
doSExt (Int8Value x) t = intValue t $ toInteger x
doSExt (Int16Value x) t = intValue t $ toInteger x
doSExt (Int32Value x) t = intValue t $ toInteger x
doSExt (Int64Value x) t = intValue t $ toInteger x
doFPConv :: FloatValue -> FloatType -> FloatValue
doFPConv (Float32Value v) Float32 = Float32Value v
doFPConv (Float64Value v) Float32 = Float32Value $ fromRational $ toRational v
doFPConv (Float64Value v) Float64 = Float64Value v
doFPConv (Float32Value v) Float64 = Float64Value $ fromRational $ toRational v
doFPToUI :: FloatValue -> IntType -> IntValue
doFPToUI v t = intValue t (truncate $ floatToDouble v :: Word64)
doFPToSI :: FloatValue -> IntType -> IntValue
doFPToSI v t = intValue t (truncate $ floatToDouble v :: Word64)
doUIToFP :: IntValue -> FloatType -> FloatValue
doUIToFP v t = floatValue t $ intToWord64 v
doSIToFP :: IntValue -> FloatType -> FloatValue
doSIToFP v t = floatValue t $ intToInt64 v
doCmpOp :: CmpOp -> PrimValue -> PrimValue -> Maybe Bool
doCmpOp CmpEq{} v1 v2 = Just $ v1 == v2
doCmpOp CmpUlt{} (IntValue v1) (IntValue v2) = Just $ doCmpUlt v1 v2
doCmpOp CmpUle{} (IntValue v1) (IntValue v2) = Just $ doCmpUle v1 v2
doCmpOp CmpSlt{} (IntValue v1) (IntValue v2) = Just $ doCmpSlt v1 v2
doCmpOp CmpSle{} (IntValue v1) (IntValue v2) = Just $ doCmpSle v1 v2
doCmpOp FCmpLt{} (FloatValue v1) (FloatValue v2) = Just $ doFCmpLt v1 v2
doCmpOp FCmpLe{} (FloatValue v1) (FloatValue v2) = Just $ doFCmpLe v1 v2
doCmpOp CmpLlt{} (BoolValue v1) (BoolValue v2) = Just $ not v1 && v2
doCmpOp CmpLle{} (BoolValue v1) (BoolValue v2) = Just $ not (v1 && not v2)
doCmpOp _ _ _ = Nothing
doCmpEq :: PrimValue -> PrimValue -> Bool
doCmpEq v1 v2 = v1 == v2
doCmpUlt :: IntValue -> IntValue -> Bool
doCmpUlt v1 v2 = intToWord64 v1 < intToWord64 v2
doCmpUle :: IntValue -> IntValue -> Bool
doCmpUle v1 v2 = intToWord64 v1 <= intToWord64 v2
doCmpSlt :: IntValue -> IntValue -> Bool
doCmpSlt = (<)
doCmpSle :: IntValue -> IntValue -> Bool
doCmpSle = (<=)
doFCmpLt :: FloatValue -> FloatValue -> Bool
doFCmpLt = (<)
doFCmpLe :: FloatValue -> FloatValue -> Bool
doFCmpLe = (<=)
intToWord64 :: IntValue -> Word64
intToWord64 (Int8Value v) = fromIntegral (fromIntegral v :: Word8)
intToWord64 (Int16Value v) = fromIntegral (fromIntegral v :: Word16)
intToWord64 (Int32Value v) = fromIntegral (fromIntegral v :: Word32)
intToWord64 (Int64Value v) = fromIntegral (fromIntegral v :: Word64)
intToInt64 :: IntValue -> Int64
intToInt64 (Int8Value v) = fromIntegral v
intToInt64 (Int16Value v) = fromIntegral v
intToInt64 (Int32Value v) = fromIntegral v
intToInt64 (Int64Value v) = fromIntegral v
intToInt :: IntValue -> Int
intToInt = fromIntegral . intToInt64
floatToDouble :: FloatValue -> Double
floatToDouble (Float32Value v) = fromRational $ toRational v
floatToDouble (Float64Value v) = v
binOpType :: BinOp -> PrimType
binOpType (Add t) = IntType t
binOpType (Sub t) = IntType t
binOpType (Mul t) = IntType t
binOpType (SDiv t) = IntType t
binOpType (SMod t) = IntType t
binOpType (SQuot t) = IntType t
binOpType (SRem t) = IntType t
binOpType (UDiv t) = IntType t
binOpType (UMod t) = IntType t
binOpType (SMin t) = IntType t
binOpType (UMin t) = IntType t
binOpType (FMin t) = FloatType t
binOpType (SMax t) = IntType t
binOpType (UMax t) = IntType t
binOpType (FMax t) = FloatType t
binOpType (Shl t) = IntType t
binOpType (LShr t) = IntType t
binOpType (AShr t) = IntType t
binOpType (And t) = IntType t
binOpType (Or t) = IntType t
binOpType (Xor t) = IntType t
binOpType (Pow t) = IntType t
binOpType (FPow t) = FloatType t
binOpType LogAnd = Bool
binOpType LogOr = Bool
binOpType (FAdd t) = FloatType t
binOpType (FSub t) = FloatType t
binOpType (FMul t) = FloatType t
binOpType (FDiv t) = FloatType t
cmpOpType :: CmpOp -> PrimType
cmpOpType (CmpEq t) = t
cmpOpType (CmpSlt t) = IntType t
cmpOpType (CmpSle t) = IntType t
cmpOpType (CmpUlt t) = IntType t
cmpOpType (CmpUle t) = IntType t
cmpOpType (FCmpLt t) = FloatType t
cmpOpType (FCmpLe t) = FloatType t
cmpOpType CmpLlt = Bool
cmpOpType CmpLle = Bool
unOpType :: UnOp -> PrimType
unOpType (SSignum t) = IntType t
unOpType (USignum t) = IntType t
unOpType Not = Bool
unOpType (Complement t) = IntType t
unOpType (Abs t) = IntType t
unOpType (FAbs t) = FloatType t
convOpType :: ConvOp -> (PrimType, PrimType)
convOpType (ZExt from to) = (IntType from, IntType to)
convOpType (SExt from to) = (IntType from, IntType to)
convOpType (FPConv from to) = (FloatType from, FloatType to)
convOpType (FPToUI from to) = (FloatType from, IntType to)
convOpType (FPToSI from to) = (FloatType from, IntType to)
convOpType (UIToFP from to) = (IntType from, FloatType to)
convOpType (SIToFP from to) = (IntType from, FloatType to)
convOpType (IToB from) = (IntType from, Bool)
convOpType (BToI to) = (Bool, IntType to)
primFuns :: M.Map String ([PrimType], PrimType,
[PrimValue] -> Maybe PrimValue)
primFuns = M.fromList
[ f32 "sqrt32" sqrt, f64 "sqrt64" sqrt
, f32 "log32" log, f64 "log64" log
, f32 "log10_32" (logBase 10), f64 "log10_64" (logBase 10)
, f32 "log2_32" (logBase 2), f64 "log2_64" (logBase 2)
, f32 "exp32" exp, f64 "exp64" exp
, f32 "sin32" sin, f64 "sin64" sin
, f32 "cos32" cos, f64 "cos64" cos
, f32 "tan32" tan, f64 "tan64" tan
, f32 "asin32" asin, f64 "asin64" asin
, f32 "acos32" acos, f64 "acos64" acos
, f32 "atan32" atan, f64 "atan64" atan
, f32 "round32" roundFloat, f64 "round64" roundDouble
, ("atan2_32",
([FloatType Float32, FloatType Float32], FloatType Float32,
\case
[FloatValue (Float32Value x), FloatValue (Float32Value y)] ->
Just $ FloatValue $ Float32Value $ atan2 x y
_ -> Nothing))
, ("atan2_64",
([FloatType Float64, FloatType Float64], FloatType Float64,
\case
[FloatValue (Float64Value x), FloatValue (Float64Value y)] ->
Just $ FloatValue $ Float64Value $ atan2 x y
_ -> Nothing))
, ("isinf32",
([FloatType Float32], Bool,
\case
[FloatValue (Float32Value x)] -> Just $ BoolValue $ isInfinite x
_ -> Nothing))
, ("isinf64",
([FloatType Float64], Bool,
\case
[FloatValue (Float64Value x)] -> Just $ BoolValue $ isInfinite x
_ -> Nothing))
, ("isnan32",
([FloatType Float32], Bool,
\case
[FloatValue (Float32Value x)] -> Just $ BoolValue $ isNaN x
_ -> Nothing))
, ("isnan64",
([FloatType Float64], Bool,
\case
[FloatValue (Float64Value x)] -> Just $ BoolValue $ isNaN x
_ -> Nothing))
, ("to_bits32",
([FloatType Float32], IntType Int32,
\case
[FloatValue (Float32Value x)] ->
Just $ IntValue $ Int32Value $ fromIntegral $ floatToWord x
_ -> Nothing))
, ("to_bits64",
([FloatType Float64], IntType Int64,
\case
[FloatValue (Float64Value x)] ->
Just $ IntValue $ Int64Value $ fromIntegral $ doubleToWord x
_ -> Nothing))
, ("from_bits32",
([IntType Int32], FloatType Float32,
\case
[IntValue (Int32Value x)] ->
Just $ FloatValue $ Float32Value $ wordToFloat $ fromIntegral x
_ -> Nothing))
, ("from_bits64",
([IntType Int64], FloatType Float64,
\case
[IntValue (Int64Value x)] ->
Just $ FloatValue $ Float64Value $ wordToDouble $ fromIntegral x
_ -> Nothing))
]
where f32 s f = (s, ([FloatType Float32], FloatType Float32, f32PrimFun f))
f64 s f = (s, ([FloatType Float64], FloatType Float64, f64PrimFun f))
f32PrimFun f [FloatValue (Float32Value x)] =
Just $ FloatValue $ Float32Value $ f x
f32PrimFun _ _ = Nothing
f64PrimFun f [FloatValue (Float64Value x)] =
Just $ FloatValue $ Float64Value $ f x
f64PrimFun _ _ = Nothing
zeroIsh :: PrimValue -> Bool
zeroIsh (IntValue k) = zeroIshInt k
zeroIsh (FloatValue (Float32Value k)) = k == 0
zeroIsh (FloatValue (Float64Value k)) = k == 0
zeroIsh (BoolValue False) = True
zeroIsh _ = False
oneIsh :: PrimValue -> Bool
oneIsh (IntValue (Int8Value k)) = k == 1
oneIsh (IntValue (Int16Value k)) = k == 1
oneIsh (IntValue (Int32Value k)) = k == 1
oneIsh (IntValue (Int64Value k)) = k == 1
oneIsh (FloatValue (Float32Value k)) = k == 1
oneIsh (FloatValue (Float64Value k)) = k == 1
oneIsh (BoolValue True) = True
oneIsh _ = False
negativeIsh :: PrimValue -> Bool
negativeIsh (IntValue k) = negativeIshInt k
negativeIsh (FloatValue (Float32Value k)) = k < 0
negativeIsh (FloatValue (Float64Value k)) = k < 0
negativeIsh (BoolValue _) = False
negativeIsh Checked = False
zeroIshInt :: IntValue -> Bool
zeroIshInt (Int8Value k) = k == 0
zeroIshInt (Int16Value k) = k == 0
zeroIshInt (Int32Value k) = k == 0
zeroIshInt (Int64Value k) = k == 0
negativeIshInt :: IntValue -> Bool
negativeIshInt (Int8Value k) = k < 0
negativeIshInt (Int16Value k) = k < 0
negativeIshInt (Int32Value k) = k < 0
negativeIshInt (Int64Value k) = k < 0
primBitSize :: PrimType -> Int
primBitSize = (*8) . primByteSize
primByteSize :: Num a => PrimType -> a
primByteSize (IntType t) = intByteSize t
primByteSize (FloatType t) = floatByteSize t
primByteSize Bool = 1
primByteSize Cert = 1
intByteSize :: Num a => IntType -> a
intByteSize Int8 = 1
intByteSize Int16 = 2
intByteSize Int32 = 4
intByteSize Int64 = 8
floatByteSize :: Num a => FloatType -> a
floatByteSize Float32 = 4
floatByteSize Float64 = 8
commutativeBinOp :: BinOp -> Bool
commutativeBinOp Add{} = True
commutativeBinOp FAdd{} = True
commutativeBinOp Mul{} = True
commutativeBinOp FMul{} = True
commutativeBinOp And{} = True
commutativeBinOp Or{} = True
commutativeBinOp Xor{} = True
commutativeBinOp LogOr{} = True
commutativeBinOp LogAnd{} = True
commutativeBinOp SMax{} = True
commutativeBinOp SMin{} = True
commutativeBinOp UMax{} = True
commutativeBinOp UMin{} = True
commutativeBinOp FMax{} = True
commutativeBinOp FMin{} = True
commutativeBinOp _ = False
instance Pretty BinOp where
ppr (Add t) = taggedI "add" t
ppr (FAdd t) = taggedF "fadd" t
ppr (Sub t) = taggedI "sub" t
ppr (FSub t) = taggedF "fsub" t
ppr (Mul t) = taggedI "mul" t
ppr (FMul t) = taggedF "fmul" t
ppr (UDiv t) = taggedI "udiv" t
ppr (UMod t) = taggedI "umod" t
ppr (SDiv t) = taggedI "sdiv" t
ppr (SMod t) = taggedI "smod" t
ppr (SQuot t) = taggedI "squot" t
ppr (SRem t) = taggedI "srem" t
ppr (FDiv t) = taggedF "fdiv" t
ppr (SMin t) = taggedI "smin" t
ppr (UMin t) = taggedI "umin" t
ppr (FMin t) = taggedF "fmin" t
ppr (SMax t) = taggedI "smax" t
ppr (UMax t) = taggedI "umax" t
ppr (FMax t) = taggedF "fmax" t
ppr (Shl t) = taggedI "shl" t
ppr (LShr t) = taggedI "lshr" t
ppr (AShr t) = taggedI "ashr" t
ppr (And t) = taggedI "and" t
ppr (Or t) = taggedI "or" t
ppr (Xor t) = taggedI "xor" t
ppr (Pow t) = taggedI "pow" t
ppr (FPow t) = taggedF "fpow" t
ppr LogAnd = text "logand"
ppr LogOr = text "logor"
instance Pretty CmpOp where
ppr (CmpEq t) = text "eq_" <> ppr t
ppr (CmpUlt t) = taggedI "ult" t
ppr (CmpUle t) = taggedI "ule" t
ppr (CmpSlt t) = taggedI "slt" t
ppr (CmpSle t) = taggedI "sle" t
ppr (FCmpLt t) = taggedF "lt" t
ppr (FCmpLe t) = taggedF "le" t
ppr CmpLlt = text "llt"
ppr CmpLle = text "lle"
instance Pretty ConvOp where
ppr op = convOp (convOpFun op) from to
where (from, to) = convOpType op
instance Pretty UnOp where
ppr Not = text "!"
ppr (Abs t) = taggedI "abs" t
ppr (FAbs t) = taggedF "fabs" t
ppr (SSignum t) = taggedI "ssignum" t
ppr (USignum t) = taggedI "usignum" t
ppr (Complement t) = taggedI "complement" t
convOpFun :: ConvOp -> String
convOpFun ZExt{} = "zext"
convOpFun SExt{} = "sext"
convOpFun FPConv{} = "fpconv"
convOpFun FPToUI{} = "fptoui"
convOpFun FPToSI{} = "fptosi"
convOpFun UIToFP{} = "uitofp"
convOpFun SIToFP{} = "sitofp"
convOpFun IToB{} = "itob"
convOpFun BToI{} = "btoi"
taggedI :: String -> IntType -> Doc
taggedI s Int8 = text $ s ++ "8"
taggedI s Int16 = text $ s ++ "16"
taggedI s Int32 = text $ s ++ "32"
taggedI s Int64 = text $ s ++ "64"
taggedF :: String -> FloatType -> Doc
taggedF s Float32 = text $ s ++ "32"
taggedF s Float64 = text $ s ++ "64"
convOp :: (Pretty from, Pretty to) => String -> from -> to -> Doc
convOp s from to = text s <> text "_" <> ppr from <> text "_" <> ppr to
prettySigned :: Bool -> PrimType -> String
prettySigned True (IntType it) = 'u' : drop 1 (pretty it)
prettySigned _ t = pretty t