{-# LANGUAGE CPP, GADTs, RankNTypes, ScopedTypeVariables, TypeFamilies #-}
#if __GLASGOW_HASKELL__ >= 701
{-# LANGUAGE Trustworthy #-}
#endif
module Compiler.Hoopl.XUtil
(
firstXfer, distributeXfer
, distributeFact, distributeFactBwd
, successorFacts
, joinFacts
, joinOutFacts
, joinMaps
, analyzeAndRewriteFwdBody, analyzeAndRewriteBwdBody
, analyzeAndRewriteFwdOx, analyzeAndRewriteBwdOx
)
where
import qualified Data.Map as M
import Data.Maybe
import Compiler.Hoopl.Collections
import Compiler.Hoopl.Checkpoint
import Compiler.Hoopl.Dataflow
import Compiler.Hoopl.Block
import Compiler.Hoopl.Graph
import Compiler.Hoopl.Label
analyzeAndRewriteFwdBody
:: forall m n f entries. (CheckpointMonad m, NonLocal n, LabelsPtr entries)
=> FwdPass m n f
-> entries -> Body n -> FactBase f
-> m (Body n, FactBase f)
analyzeAndRewriteBwdBody
:: forall m n f entries. (CheckpointMonad m, NonLocal n, LabelsPtr entries)
=> BwdPass m n f
-> entries -> Body n -> FactBase f
-> m (Body n, FactBase f)
analyzeAndRewriteFwdBody pass en = mapBodyFacts (analyzeAndRewriteFwd pass (JustC en))
analyzeAndRewriteBwdBody pass en = mapBodyFacts (analyzeAndRewriteBwd pass (JustC en))
mapBodyFacts :: (Monad m)
=> (Graph n C C -> Fact C f -> m (Graph n C C, Fact C f, MaybeO C f))
-> (Body n -> FactBase f -> m (Body n, FactBase f))
mapBodyFacts anal b f = anal (GMany NothingO b NothingO) f >>= bodyFacts
where
bodyFacts :: Monad m => (Graph n C C, Fact C f, MaybeO C f) -> m (Body n, Fact C f)
bodyFacts (GMany NothingO body NothingO, fb, NothingO) = return (body, fb)
analyzeAndRewriteFwdOx
:: forall m n f x. (CheckpointMonad m, NonLocal n)
=> FwdPass m n f -> Graph n O x -> f -> m (Graph n O x, FactBase f, MaybeO x f)
analyzeAndRewriteBwdOx
:: forall m n f x. (CheckpointMonad m, NonLocal n)
=> BwdPass m n f -> Graph n O x -> Fact x f -> m (Graph n O x, FactBase f, f)
noEntries :: MaybeC O Label
noEntries = NothingC
analyzeAndRewriteFwdOx pass g f = analyzeAndRewriteFwd pass noEntries g f
analyzeAndRewriteBwdOx pass g fb = analyzeAndRewriteBwd pass noEntries g fb >>= strip
where strip :: forall m a b c . Monad m => (a, b, MaybeO O c) -> m (a, b, c)
strip (a, b, JustO c) = return (a, b, c)
firstXfer :: NonLocal n => (n C O -> f -> f) -> (n C O -> FactBase f -> f)
firstXfer xfer n fb = xfer n $ fromJust $ lookupFact (entryLabel n) fb
distributeXfer :: NonLocal n
=> DataflowLattice f -> (n O C -> f -> f) -> (n O C -> f -> FactBase f)
distributeXfer lattice xfer n f =
mkFactBase lattice [ (l, xfer n f) | l <- successors n ]
distributeFact :: NonLocal n => n O C -> f -> FactBase f
distributeFact n f = mapFromList [ (l, f) | l <- successors n ]
distributeFactBwd :: NonLocal n => n C O -> f -> FactBase f
distributeFactBwd n f = mapSingleton (entryLabel n) f
successorFacts :: NonLocal n => n O C -> FactBase f -> [f]
successorFacts n fb = [ f | id <- successors n, let Just f = lookupFact id fb ]
joinFacts :: DataflowLattice f -> Label -> [f] -> f
joinFacts lat inBlock = foldr extend (fact_bot lat)
where extend new old = snd $ fact_join lat inBlock (OldFact old) (NewFact new)
{-# DEPRECATED joinOutFacts
"should be replaced by 'joinFacts lat l (successorFacts n f)'; as is, it uses the wrong Label" #-}
joinOutFacts :: (NonLocal node) => DataflowLattice f -> node O C -> FactBase f -> f
joinOutFacts lat n f = foldr join (fact_bot lat) facts
where join (lbl, new) old = snd $ fact_join lat lbl (OldFact old) (NewFact new)
facts = [(s, fromJust fact) | s <- successors n, let fact = lookupFact s f, isJust fact]
joinMaps :: Ord k => JoinFun v -> JoinFun (M.Map k v)
joinMaps eltJoin l (OldFact old) (NewFact new) = M.foldrWithKey add (NoChange, old) new
where
add k new_v (ch, joinmap) =
case M.lookup k joinmap of
Nothing -> (SomeChange, M.insert k new_v joinmap)
Just old_v -> case eltJoin l (OldFact old_v) (NewFact new_v) of
(SomeChange, v') -> (SomeChange, M.insert k v' joinmap)
(NoChange, _) -> (ch, joinmap)