#if __GLASGOW_HASKELL__ >= 701
#endif
module CmmNode
( CmmNode(..)
, UpdFrameOffset, Convention(..), ForeignConvention(..), ForeignTarget(..)
, mapExp, mapExpDeep, wrapRecExp, foldExp, foldExpDeep, wrapRecExpf
, mapExpM, mapExpDeepM, wrapRecExpM
)
where
import CmmExpr
import CmmDecl
import FastString
import ForeignCall
import SMRep
import Compiler.Hoopl
import Data.Maybe
import Data.List (tails)
import Prelude hiding (succ)
data CmmNode e x where
CmmEntry :: Label -> CmmNode C O
CmmComment :: FastString -> CmmNode O O
CmmAssign :: CmmReg -> CmmExpr -> CmmNode O O
CmmStore :: CmmExpr -> CmmExpr -> CmmNode O O
CmmUnsafeForeignCall ::
ForeignTarget ->
[CmmFormal] ->
[CmmActual] ->
CmmNode O O
CmmBranch :: Label -> CmmNode O C
CmmCondBranch :: {
cml_pred :: CmmExpr,
cml_true, cml_false :: Label
} -> CmmNode O C
CmmSwitch :: CmmExpr -> [Maybe Label] -> CmmNode O C
CmmCall :: {
cml_target :: CmmExpr,
cml_cont :: Maybe Label,
cml_args :: ByteOff,
cml_ret_args :: ByteOff,
cml_ret_off :: ByteOff
} -> CmmNode O C
CmmForeignCall :: {
tgt :: ForeignTarget,
res :: [CmmFormal],
args :: [CmmActual],
succ :: Label,
updfr :: UpdFrameOffset,
intrbl:: Bool
} -> CmmNode O C
instance Eq (CmmNode e x) where
(CmmEntry a) == (CmmEntry a') = a==a'
(CmmComment a) == (CmmComment a') = a==a'
(CmmAssign a b) == (CmmAssign a' b') = a==a' && b==b'
(CmmStore a b) == (CmmStore a' b') = a==a' && b==b'
(CmmUnsafeForeignCall a b c) == (CmmUnsafeForeignCall a' b' c') = a==a' && b==b' && c==c'
(CmmBranch a) == (CmmBranch a') = a==a'
(CmmCondBranch a b c) == (CmmCondBranch a' b' c') = a==a' && b==b' && c==c'
(CmmSwitch a b) == (CmmSwitch a' b') = a==a' && b==b'
(CmmCall a b c d e) == (CmmCall a' b' c' d' e') = a==a' && b==b' && c==c' && d==d' && e==e'
(CmmForeignCall a b c d e f) == (CmmForeignCall a' b' c' d' e' f') = a==a' && b==b' && c==c' && d==d' && e==e' && f==f'
_ == _ = False
instance NonLocal CmmNode where
entryLabel (CmmEntry l) = l
successors (CmmBranch l) = [l]
successors (CmmCondBranch {cml_true=t, cml_false=f}) = [f, t]
successors (CmmSwitch _ ls) = catMaybes ls
successors (CmmCall {cml_cont=l}) = maybeToList l
successors (CmmForeignCall {succ=l}) = [l]
instance HooplNode CmmNode where
mkBranchNode label = CmmBranch label
mkLabelNode label = CmmEntry label
type UpdFrameOffset = ByteOff
data Convention
= NativeDirectCall
| NativeNodeCall
| NativeReturn
| Slow
| GC
| PrimOpCall
| PrimOpReturn
| Foreign
ForeignConvention
| Private
deriving( Eq )
data ForeignConvention
= ForeignConvention
CCallConv
[ForeignHint]
[ForeignHint]
deriving Eq
data ForeignTarget
= ForeignTarget
CmmExpr
ForeignConvention
| PrimTarget
CallishMachOp
deriving Eq
instance UserOfLocalRegs (CmmNode e x) where
foldRegsUsed f z n = case n of
CmmAssign _ expr -> fold f z expr
CmmStore addr rval -> fold f (fold f z addr) rval
CmmUnsafeForeignCall t _ args -> fold f (fold f z t) args
CmmCondBranch expr _ _ -> fold f z expr
CmmSwitch expr _ -> fold f z expr
CmmCall {cml_target=tgt} -> fold f z tgt
CmmForeignCall {tgt=tgt, args=args} -> fold f (fold f z tgt) args
_ -> z
where fold :: forall a b.
UserOfLocalRegs a =>
(b -> LocalReg -> b) -> b -> a -> b
fold f z n = foldRegsUsed f z n
instance UserOfLocalRegs ForeignTarget where
foldRegsUsed _f z (PrimTarget _) = z
foldRegsUsed f z (ForeignTarget e _) = foldRegsUsed f z e
instance DefinerOfLocalRegs (CmmNode e x) where
foldRegsDefd f z n = case n of
CmmAssign lhs _ -> fold f z lhs
CmmUnsafeForeignCall _ fs _ -> fold f z fs
CmmForeignCall {res=res} -> fold f z res
_ -> z
where fold :: forall a b.
DefinerOfLocalRegs a =>
(b -> LocalReg -> b) -> b -> a -> b
fold f z n = foldRegsDefd f z n
instance UserOfSlots (CmmNode e x) where
foldSlotsUsed f z n = case n of
CmmAssign _ expr -> fold f z expr
CmmStore addr rval -> fold f (fold f z addr) rval
CmmUnsafeForeignCall _ _ args -> fold f z args
CmmCondBranch expr _ _ -> fold f z expr
CmmSwitch expr _ -> fold f z expr
CmmCall {cml_target=tgt} -> fold f z tgt
CmmForeignCall {tgt=tgt, args=args} -> fold f (fold f z tgt) args
_ -> z
where fold :: forall a b.
UserOfSlots a =>
(b -> SubArea -> b) -> b -> a -> b
fold f z n = foldSlotsUsed f z n
instance UserOfSlots ForeignTarget where
foldSlotsUsed f z (ForeignTarget e _) = foldSlotsUsed f z e
foldSlotsUsed _f z (PrimTarget _) = z
instance DefinerOfSlots (CmmNode e x) where
foldSlotsDefd f z n = case n of
CmmStore (CmmStackSlot a i) expr -> f z (a, i, widthInBytes $ typeWidth $ cmmExprType expr)
CmmForeignCall {res=res} -> fold f z $ map foreign_call_slot res
_ -> z
where
fold :: forall a b.
DefinerOfSlots a =>
(b -> SubArea -> b) -> b -> a -> b
fold f z n = foldSlotsDefd f z n
foreign_call_slot r = case widthInBytes $ typeWidth $ localRegType r of w -> (RegSlot r, w, w)
mapForeignTarget :: (CmmExpr -> CmmExpr) -> ForeignTarget -> ForeignTarget
mapForeignTarget exp (ForeignTarget e c) = ForeignTarget (exp e) c
mapForeignTarget _ m@(PrimTarget _) = m
wrapRecExp :: (CmmExpr -> CmmExpr) -> CmmExpr -> CmmExpr
wrapRecExp f (CmmMachOp op es) = f (CmmMachOp op $ map (wrapRecExp f) es)
wrapRecExp f (CmmLoad addr ty) = f (CmmLoad (wrapRecExp f addr) ty)
wrapRecExp f e = f e
mapExp :: (CmmExpr -> CmmExpr) -> CmmNode e x -> CmmNode e x
mapExp _ f@(CmmEntry _) = f
mapExp _ m@(CmmComment _) = m
mapExp f (CmmAssign r e) = CmmAssign r (f e)
mapExp f (CmmStore addr e) = CmmStore (f addr) (f e)
mapExp f (CmmUnsafeForeignCall tgt fs as) = CmmUnsafeForeignCall (mapForeignTarget f tgt) fs (map f as)
mapExp _ l@(CmmBranch _) = l
mapExp f (CmmCondBranch e ti fi) = CmmCondBranch (f e) ti fi
mapExp f (CmmSwitch e tbl) = CmmSwitch (f e) tbl
mapExp f (CmmCall tgt mb_id o i s) = CmmCall (f tgt) mb_id o i s
mapExp f (CmmForeignCall tgt fs as succ updfr intrbl) = CmmForeignCall (mapForeignTarget f tgt) fs (map f as) succ updfr intrbl
mapExpDeep :: (CmmExpr -> CmmExpr) -> CmmNode e x -> CmmNode e x
mapExpDeep f = mapExp $ wrapRecExp f
mapForeignTargetM :: (CmmExpr -> Maybe CmmExpr) -> ForeignTarget -> Maybe ForeignTarget
mapForeignTargetM f (ForeignTarget e c) = (\x -> ForeignTarget x c) `fmap` f e
mapForeignTargetM _ (PrimTarget _) = Nothing
wrapRecExpM :: (CmmExpr -> Maybe CmmExpr) -> (CmmExpr -> Maybe CmmExpr)
wrapRecExpM f n@(CmmMachOp op es) = maybe (f n) (f . CmmMachOp op) (mapListM (wrapRecExpM f) es)
wrapRecExpM f n@(CmmLoad addr ty) = maybe (f n) (f . flip CmmLoad ty) (wrapRecExpM f addr)
wrapRecExpM f e = f e
mapExpM :: (CmmExpr -> Maybe CmmExpr) -> CmmNode e x -> Maybe (CmmNode e x)
mapExpM _ (CmmEntry _) = Nothing
mapExpM _ (CmmComment _) = Nothing
mapExpM f (CmmAssign r e) = CmmAssign r `fmap` f e
mapExpM f (CmmStore addr e) = (\[addr', e'] -> CmmStore addr' e') `fmap` mapListM f [addr, e]
mapExpM _ (CmmBranch _) = Nothing
mapExpM f (CmmCondBranch e ti fi) = (\x -> CmmCondBranch x ti fi) `fmap` f e
mapExpM f (CmmSwitch e tbl) = (\x -> CmmSwitch x tbl) `fmap` f e
mapExpM f (CmmCall tgt mb_id o i s) = (\x -> CmmCall x mb_id o i s) `fmap` f tgt
mapExpM f (CmmUnsafeForeignCall tgt fs as)
= case mapForeignTargetM f tgt of
Just tgt' -> Just (CmmUnsafeForeignCall tgt' fs (mapListJ f as))
Nothing -> (\xs -> CmmUnsafeForeignCall tgt fs xs) `fmap` mapListM f as
mapExpM f (CmmForeignCall tgt fs as succ updfr intrbl)
= case mapForeignTargetM f tgt of
Just tgt' -> Just (CmmForeignCall tgt' fs (mapListJ f as) succ updfr intrbl)
Nothing -> (\xs -> CmmForeignCall tgt fs xs succ updfr intrbl) `fmap` mapListM f as
mapListM :: (a -> Maybe a) -> [a] -> Maybe [a]
mapListM f xs = let (b, r) = mapListT f xs
in if b then Just r else Nothing
mapListJ :: (a -> Maybe a) -> [a] -> [a]
mapListJ f xs = snd (mapListT f xs)
mapListT :: (a -> Maybe a) -> [a] -> (Bool, [a])
mapListT f xs = foldr g (False, []) (zip3 (tails xs) xs (map f xs))
where g (_, y, Nothing) (True, ys) = (True, y:ys)
g (_, _, Just y) (True, ys) = (True, y:ys)
g (ys', _, Nothing) (False, _) = (False, ys')
g (_, _, Just y) (False, ys) = (True, y:ys)
mapExpDeepM :: (CmmExpr -> Maybe CmmExpr) -> CmmNode e x -> Maybe (CmmNode e x)
mapExpDeepM f = mapExpM $ wrapRecExpM f
foldExpForeignTarget :: (CmmExpr -> z -> z) -> ForeignTarget -> z -> z
foldExpForeignTarget exp (ForeignTarget e _) z = exp e z
foldExpForeignTarget _ (PrimTarget _) z = z
wrapRecExpf :: (CmmExpr -> z -> z) -> CmmExpr -> z -> z
wrapRecExpf f e@(CmmMachOp _ es) z = foldr (wrapRecExpf f) (f e z) es
wrapRecExpf f e@(CmmLoad addr _) z = wrapRecExpf f addr (f e z)
wrapRecExpf f e z = f e z
foldExp :: (CmmExpr -> z -> z) -> CmmNode e x -> z -> z
foldExp _ (CmmEntry {}) z = z
foldExp _ (CmmComment {}) z = z
foldExp f (CmmAssign _ e) z = f e z
foldExp f (CmmStore addr e) z = f addr $ f e z
foldExp f (CmmUnsafeForeignCall t _ as) z = foldr f (foldExpForeignTarget f t z) as
foldExp _ (CmmBranch _) z = z
foldExp f (CmmCondBranch e _ _) z = f e z
foldExp f (CmmSwitch e _) z = f e z
foldExp f (CmmCall {cml_target=tgt}) z = f tgt z
foldExp f (CmmForeignCall {tgt=tgt, args=args}) z = foldr f (foldExpForeignTarget f tgt z) args
foldExpDeep :: (CmmExpr -> z -> z) -> CmmNode e x -> z -> z
foldExpDeep f = foldExp $ wrapRecExpf f