ajhc-0.8.0.1: src/E/PrimOpt.hs
{-# LANGUAGE DoRec,ViewPatterns #-}
module E.PrimOpt(performPrimOpt) where
import Control.Monad.Fix()
import C.Prims
import Cmm.OpEval
import Doc.DocLike
import Doc.PPrint
import E.E
import E.Values
import Stats
import StringTable.Atom
import Support.CanType
import qualified Cmm.Op as Op
{-@Extensions
# Foreign Primitives
In addition to foreign imports of external functions as described in the FFI
spec. Jhc supports 'primitive' imports that let you communicate primitives
directly to the compiler. In general, these should not be used other than in the
implementation of the standard libraries. They generally do little error
checking as it is assumed you know what you are doing if you use them. All
haskell visible entities are introduced via foreign declarations in jhc.
They all have the form
foreign import primitive "specification" haskell_name :: type
where "specification" is one of the following
seq
: evaluate first argument to WHNF, then return the second argument
zero,one
: the values zero and one of any primitive type.
const.C_CONSTANT
: the text following const is directly inserted into the resulting C file
peek.TYPE
: the peek primitive for raw value TYPE
poke.TYPE
: the poke primitive for raw value TYPE
sizeOf.TYPE, alignmentOf.TYPE, minBound.TYPE, maxBound.TYPE, umaxBound.TYPE
: various properties of a given internal type.
error.MESSAGE
: results in an error with constant message MESSAGE.
constPeekByte
: peek of a constant value specialized to bytes, used internally by Jhc.String
box
: take an unboxed value and box it, the shape of the box is determined by the type at which this is imported
unbox
: take an boxed value and unbox it, the shape of the box is determined by the type at which this is imported
increment, decrement
: increment or decrement a numerical integral primitive value
fincrement, fdecrement
: increment or decrement a numerical floating point primitive value
exitFailure__
: abort the program immediately
C-- Primitive
: any C-- primitive may be imported in this manner.
-}
-- | this creates a string representing the type of primitive optimization was
-- performed for bookkeeping purposes
primConv cop t1 t2 e rt = EPrim (Op (Op.ConvOp cop t1) t2) [e] rt
performPrimOpt (ELit lc@LitCons { litArgs = xs }) = do
xs' <- mapM performPrimOpt xs
primOpt' (ELit lc { litArgs = xs' })
performPrimOpt (EPrim ap xs t) = do
xs' <- mapM performPrimOpt xs
primOpt' (EPrim ap xs' t)
performPrimOpt e = return e
primOpt' e@(EPrim s xs t) = do
let primopt (Op (Op.BinOp bop t1 t2) tr) [e1,e2] rt =
binOp bop t1 t2 tr e1 e2 rt
primopt (Op (Op.ConvOp cop t1) t2) [ELit (LitInt n t)] rt =
return $ ELit (LitInt (convNumber cop t1 t2 n) rt)
primopt (Op (Op.ConvOp cop t1) t2) [e1] rt = case convOp cop t1 t2 of
Nothing | getType e1 == rt -> return e1
Just cop' | cop' /= cop -> return $ primConv cop' t1 t2 e1 rt
_ -> fail "couldn't apply conversion optimization"
primopt (Op (Op.UnOp bop t1) tr) [e1] rt = unOp bop t1 tr e1 rt
primopt _ _ _ = fail "No Primitive optimization to apply"
case primopt s xs t of
Just n -> do
mtick (toAtom $ "E.PrimOpt." ++ braces (pprint s) ++ cextra s xs )
primOpt' n
Nothing -> return e
primOpt' e = return e
cextra Op {} [] = ""
cextra Op {} xs = '.':map f xs where
f ELit {} = 'c'
f EPrim {} = 'p'
f _ = 'e'
cextra _ _ = ""
instance Expression E E where
toBool True = ELit lTruezh
toBool False = ELit lFalsezh
toConstant (ELit (LitInt n t)) = return (n,t)
toConstant _ = Nothing
equalsExpression e1 e2 = e1 == e2
caseEquals scrut (n,t) e1 e2 = eCase scrut [Alt (LitInt n t) e1 ] e2
toExpression n t = (ELit (LitInt n t))
createBinOp bop t1 t2 tr e1 e2 str =
EPrim Op { primCOp = Op.BinOp bop t1 t2,
primRetTy = tr } [e1, e2] str
createUnOp bop t1 tr e1 str =
EPrim Op { primCOp = Op.UnOp bop t1,
primRetTy = tr } [e1] str
fromBinOp (EPrim Op { primCOp = Op.BinOp bop t1 t2,
primRetTy = tr } [e1, e2] str) =
Just (bop,t1,t2,tr,e1,e2,str)
fromBinOp _ = Nothing
fromUnOp (EPrim Op {
primCOp = Op.UnOp bop t1,
primRetTy = tr } [e1] str) = Just (bop,t1,tr,e1,str)
fromUnOp _ = Nothing