packages feed

hLLVM-0.5.0.0: src/Llvm/Data/Ir.hs

{-# LANGUAGE GADTs #-}
module Llvm.Data.Ir
    (module Llvm.Data.Ir
    , module Llvm.Data.CoreIr
    , module Data.Word
    )
    where
import Llvm.Data.CoreIr
import qualified Llvm.Data.CoreIr as Ci
import qualified Compiler.Hoopl as H
import qualified Data.Set as S
import Data.Word (Word32)

{- An intermediate representation that is suitable for Hoopl -}

data Toplevel a = ToplevelTriple TlTriple
                | ToplevelDataLayout TlDataLayout
                | ToplevelAlias TlAlias
                | ToplevelDbgInit TlDbgInit
                | ToplevelStandaloneMd TlStandaloneMd
                | ToplevelNamedMd TlNamedMd
                | ToplevelDeclare TlDeclare
                | ToplevelDefine (TlDefine a)
                | ToplevelGlobal TlGlobal
                | ToplevelTypeDef TlTypeDef
                | ToplevelDepLibs TlDepLibs
                | ToplevelUnamedType TlUnamedType
                | ToplevelModuleAsm TlModuleAsm
                | ToplevelAttribute TlAttribute
                | ToplevelComdat TlComdat

data TlTriple = TlTriple Ci.TargetTriple deriving (Eq)

data TlDataLayout = TlDataLayout Ci.DataLayout deriving (Eq)

data TlAlias = TlAlias { tla_lhs :: Ci.GlobalId
                       , tla_visibility :: Maybe Ci.Visibility
                       , tla_dllstorage :: Maybe Ci.DllStorageClass
                       , tla_tls :: Maybe Ci.ThreadLocalStorage
                       , tla_addrnaming :: AddrNaming
                       , tla_linkage :: Maybe Ci.Linkage
                       , tla_aliasee :: Ci.Aliasee
                       } deriving (Eq, Ord, Show)

data TlDbgInit = TlDbgInit String Word32 deriving (Eq, Ord, Show)

data TlStandaloneMd = TlStandaloneMd String MetaKindedConst deriving (Eq, Ord, Show)

data TlNamedMd = TlNamedMd Ci.MdVar [Ci.MdNode] deriving (Eq, Ord, Show)

data TlDeclare = TlDeclare Ci.FunctionPrototype deriving (Eq)

type NOOP = ()

data TlDefine a = TlDefine Ci.FunctionPrototype H.Label (H.Graph (Node a) H.C H.C) 

data TlGlobal = TlGlobalDtype { tlg_lhs :: (Maybe Ci.GlobalId)
                              , tlg_linkage :: (Maybe Ci.Linkage)
                              , tlg_visibility :: (Maybe Ci.Visibility)
                              , tlg_dllstorage :: (Maybe Ci.DllStorageClass)
                              , tlg_tls :: (Maybe Ci.ThreadLocalStorage)
                              , tlg_addrnaming :: AddrNaming
                              , tlg_addrspace :: (Maybe Ci.AddrSpace)
                              , tlg_externallyInitialized :: (IsOrIsNot Ci.ExternallyInitialized)
                              , tlg_globalType :: Ci.GlobalType
                              , tlg_dtype :: Ci.Dtype
                              , tlg_const :: (Maybe Ci.Const)
                              , tlg_section :: (Maybe Ci.Section)
                              , tlg_comdat :: (Maybe Ci.Comdat)
                              , tlg_alignment :: (Maybe Ci.Alignment)
                              }
              | TlGlobalOpaque { tlg_lhs :: (Maybe Ci.GlobalId)
                               , tlg_linkage :: (Maybe Ci.Linkage)
                               , tlg_visiblity :: (Maybe Ci.Visibility)
                               , tlg_dllstorage :: (Maybe Ci.DllStorageClass)
                               , tlg_tls :: (Maybe Ci.ThreadLocalStorage)
                               , tlg_addrnaming :: AddrNaming
                               , tlg_addrspace :: (Maybe Ci.AddrSpace)
                               , tlg_externallyInitialized :: (IsOrIsNot Ci.ExternallyInitialized)
                               , tlg_globalType :: Ci.GlobalType
                               , tlg_otype :: (Ci.Type Ci.OpaqueB D)
                               , tlg_const :: (Maybe Ci.Const)
                               , tlg_section :: (Maybe Ci.Section)
                               , tlg_comdat :: (Maybe Ci.Comdat)
                               , tlg_alignment :: (Maybe Ci.Alignment)
                               } deriving (Eq, Ord, Show)

data TlTypeDef = TlDatTypeDef Ci.LocalId Ci.Dtype
               | TlOpqTypeDef Ci.LocalId (Ci.Type OpaqueB D)
               | TlFunTypeDef Ci.LocalId (Ci.Type CodeFunB X) deriving (Eq, Ord, Show)

data TlDepLibs = TlDepLibs [Ci.DqString] deriving (Eq, Ord, Show)

data TlUnamedType = TlUnamedType Word32 Ci.Dtype deriving (Eq, Ord, Show)

data TlModuleAsm = TlModuleAsm Ci.DqString deriving (Eq, Ord, Show)

data TlAttribute = TlAttribute Word32 [FunAttr] deriving (Eq, Ord, Show)

data TlComdat = TlComdat Ci.DollarId Ci.SelectionKind deriving (Eq, Ord, Show)

data Module a = Module [Toplevel a] 

-- each instruction represents a node
data Node a e x where
  Nlabel :: H.Label -> Node a H.C H.O
  Pinst  :: Ci.PhiInstWithDbg -> Node a H.O H.O
  Cinst  :: Ci.CInstWithDbg -> Node a H.O H.O
  Comment :: String -> Node a H.O H.O
  Tinst  :: Ci.TerminatorInstWithDbg -> Node a H.O H.C
  Additional :: a -> Node a H.O H.O

instance Show a => Show (Node a e x) where
  show x = case x of
    Nlabel v -> "Nlabel: Node C O:" ++ show v
    Pinst v -> "Pinst : Node O O:" ++ show v
    Cinst v -> "Cinst : Node O O:" ++ show v
    Tinst v -> "Tinst : Node O C:" ++ show v
    Comment s -> "Comment : Node O O:" ++ s
    Additional a -> "Additional : Node O O:" ++ show a

instance Eq a => Eq (Node a e x) where
  (==) x1 x2 = case (x1, x2) of
    (Nlabel l1, Nlabel l2) -> l1 == l2
    (Pinst v1, Pinst v2) -> v1 == v2
    (Cinst v1, Cinst v2) -> v1 == v2
    (Tinst v1, Tinst v2) -> v1 == v2
    (Comment v1, Comment v2) -> v1 == v2
    (Additional a1, Additional a2) -> a1 == a2
    (_, _) -> False

instance (Show a, Ord a) => Ord (Node a e x) where
  compare x1 x2 = case (x1, x2) of
    (Nlabel l1, Nlabel l2) -> compare l1 l2
    (Pinst v1, Pinst v2) -> compare v1 v2
    (Cinst v1, Cinst v2) -> compare v1 v2
    (Tinst v1, Tinst v2) -> compare v1 v2
    (Comment v1, Comment v2) -> compare v1 v2
    (Additional v1, Additional v2) -> compare v1 v2
    (_, _) -> compare (show x1) (show x2)

instance H.NonLocal (Node a) where
  entryLabel (Nlabel l) = l
  successors (Tinst (Ci.TerminatorInstWithDbg inst _)) = suc inst
    where
      suc (Ci.Unreachable) = []
      suc (Ci.Return _) = []
      suc (Ci.RetVoid) = []
      suc (Ci.Br l) = [l]
      suc (Ci.Cbr _ l1 l2) = [l1, l2]
      suc (Ci.IndirectBr _ ls) = ls
      suc (Ci.Switch _ d ls) = (d):(map snd ls)
      suc (Ci.Invoke  _ l1 l2 _) = [l1, l2]
      suc (Ci.InvokeCmd _ l1 l2) = [l1, l2]
      suc (Ci.Resume _) = error "what is resume"
      suc (Ci.Unwind) = error "what is unwind"

globalIdOfModule :: (Module a) -> S.Set (Ci.Dtype, Ci.GlobalId) -- this should be a map, globalid might have an opaque type
globalIdOfModule (Module tl) = foldl (\a b -> S.union a (globalIdOf b)) S.empty tl
                               where globalIdOf (ToplevelGlobal (TlGlobalDtype lhs _ _ _ _ _ _ _ _ t _ _ _ _)) =
                                       maybe S.empty (\x -> S.singleton (t, x)) lhs
                                     globalIdOf _ = S.empty