hLLVM-0.5.0.0: src/Llvm/Data/Conversion/LabelMapM.hs
{-# OPTIONS_GHC -cpp #-}
{-# LANGUAGE TemplateHaskell #-}
module Llvm.Data.Conversion.LabelMapM
(IdLabelMap,labelFor,LabelMapM(..),runLabelMapM,emptyIdLabelMap
,typeDefs,a2h,invertMap)
where
import qualified Compiler.Hoopl as H
import qualified Data.Map as M
import qualified Llvm.Data.Ast as A
import Control.Applicative
import Control.Monad (ap, liftM)
#ifdef DEBUG
import Debug.Trace
import Llvm.Data.AsmPrint
import Llvm.Data.AstWriter
#endif
#define FLC (I.FileLoc $(I.srcLoc))
{-
-- LabelMapM monad is a CheckingFuelMonad with a data structure IdLabelMap to track
-- the mapping between LLVM labels and Hoopl labels and the original order LLVM labels
-- the mapping will be used to convert Hoopl labels back to LLVM labels to make
-- llvm-as happy
-}
data IdLabelMap =
IdLabelMap
{ a2h :: M.Map A.LabelId H.Label
-- | readonly value, it should be converted to a reader monad later
, typedefs :: M.Map A.LocalId A.Type
} deriving (Show)
data LabelMapM m a = LabelMapM { unIlM :: IdLabelMap -> m (IdLabelMap, a) }
instance Functor m => Functor (LabelMapM m) where
fmap f mla = LabelMapM $ \iLm -> let ma = unIlM mla iLm
fx = \(im, a) -> (im, f a)
in fmap fx ma
instance (Functor m, Applicative m, Monad m, H.UniqueMonad m) => Applicative (LabelMapM m) where
pure = return
(<*>) = ap
-- | we need to get a fresh Hoopl label for each LLVM label, so we use Hoopl Unique Monad
instance (Applicative m, H.UniqueMonad m) => Monad (LabelMapM m) where
return x = LabelMapM $ \iLm -> return (iLm, x)
iLmM >>= k = LabelMapM $ \iLm -> unIlM iLmM iLm >>= \(iLm1, x) -> unIlM (k x) iLm1
labelFor :: H.UniqueMonad m => A.LabelId -> LabelMapM m H.Label
labelFor al = LabelMapM $ \iLm -> case M.lookup al (a2h iLm) of
Just hl -> return (iLm, hl)
Nothing -> do { hl <- H.freshLabel
; let a2h' = M.insert al hl (a2h iLm)
; return (iLm { a2h = a2h'}, hl)
}
typeDefs :: H.UniqueMonad m => LabelMapM m (M.Map A.LocalId A.Type)
typeDefs = LabelMapM $ \iLm -> return (iLm, typedefs iLm)
revertMap :: A.LabelId -> A.BlockLabel
revertMap (A.LabelNumber _) = error "irrefutable"
revertMap x = A.ExplicitBlockLabel x
emptyIdLabelMap td = IdLabelMap { a2h = M.empty, typedefs = td}
runLabelMapM :: H.UniqueMonad m => IdLabelMap -> LabelMapM m a -> m (IdLabelMap, a)
runLabelMapM iLm (LabelMapM f) = f iLm
invertMap :: (Ord k, Ord v) => M.Map k v -> M.Map v k
invertMap m = foldl (\p (k,v) -> if M.member v p then
error $ "irrefutable error in invertMap, the values are not unique"
else
M.insert v k p
) M.empty (M.toList m)