llvm-0.0.2: LLVM/Core/Value.hs
{-# LANGUAGE
DeriveDataTypeable
, ExistentialQuantification
, FunctionalDependencies
, MultiParamTypeClasses
, UndecidableInstances
#-}
module LLVM.Core.Value
(
-- * Values
-- * Opaque wrapper for LLVM's basic value type
AnyValue
, DynamicValue(..)
, mkAnyValue
, typeOfDyn
-- ** Type classes
, Value(..)
, Params(..)
, ConstValue
, GlobalValue
, GlobalVariable
, Arithmetic
, Integer
, Real
, Vector
, Global(..)
, GlobalVar(..)
, Function(..)
, TypedValue(..)
, Argument(..)
, Instruction(..)
-- * Constants
, ConstInt(..)
, ConstReal(..)
, ConstArray(..)
-- ** Useful functions
, params
, getName
, setName
, dumpValue
) where
import Control.Applicative ((<$>))
import Data.Typeable (Typeable)
import Foreign.C.String (peekCString, withCString)
import Foreign.Marshal.Array (allocaArray, peekArray)
import Foreign.Ptr (nullPtr)
import Prelude hiding (Integer, Real)
import System.IO.Unsafe (unsafePerformIO)
import qualified LLVM.Core.FFI as FFI
import LLVM.Core.Type ((:->)(..))
import qualified LLVM.Core.Type as T
-- import Debug.Trace
class Value a where
valueRef :: a -> FFI.ValueRef
anyValue :: a -> AnyValue
class DynamicValue a where
fromAnyValue :: AnyValue -> a
class Params t v | t -> v where
fromAnyList :: t -> [AnyValue] -> (v, [AnyValue])
-- | Recover the type of a value in a manner that preserves static
-- type safety.
class (T.Type t, Value v) => TypedValue v t | v -> t where
typeOf :: v -- ^ value is not inspected
-> t
data AnyValue = forall a. Value a => AnyValue a
deriving (Typeable)
instance DynamicValue AnyValue where
fromAnyValue = id
instance Value FFI.ValueRef where
valueRef = id
anyValue = AnyValue
mkAnyValue :: Value a => a -> AnyValue
mkAnyValue = AnyValue
class Value a => ConstValue a
class Value a => Arithmetic a
class Arithmetic a => Integer a
class Arithmetic a => Real a
class Arithmetic a => Vector a
class ConstValue a => GlobalValue a
class GlobalValue a => GlobalVariable a
instance Value AnyValue where
valueRef (AnyValue a) = valueRef a
anyValue = id
instance ConstValue AnyValue
instance GlobalValue AnyValue
instance GlobalVariable AnyValue
instance Arithmetic AnyValue
instance Integer AnyValue
instance Real AnyValue
getName :: Value v => v -> IO String
getName v = do
namePtr <- FFI.getValueName (valueRef v)
if namePtr == nullPtr
then return []
else peekCString namePtr
setName :: Value v => v -> String -> IO ()
setName v name = withCString name (FFI.setValueName (valueRef v))
dumpValue :: Value v => v -> IO ()
dumpValue = FFI.dumpValue . valueRef
newtype Instruction a = Instruction AnyValue
deriving (DynamicValue, Typeable, Value)
newtype Global t = Global AnyValue
deriving (ConstValue, DynamicValue, GlobalValue, Typeable, Value)
newtype GlobalVar t = GlobalVar AnyValue
deriving (ConstValue, DynamicValue, GlobalValue, GlobalVariable,
Typeable, Value)
fromAny :: (DynamicValue v, TypedValue v t, T.Type t) => t -> [AnyValue] -> (v, [AnyValue])
fromAny _ (x:xs) = (fromAnyValue x,xs)
fromAny _ _ = error "LLVM.Core.Value.fromAny: empty list"
globalVarType :: GlobalVar t -> t
globalVarType _ = undefined
instance T.Type t => TypedValue (GlobalVar t) t where
typeOf = globalVarType
data Function r p = Function {
fromFunction :: AnyValue
}
deriving (Typeable)
instance ConstValue (Function r p)
instance GlobalValue (Function r p)
instance GlobalVariable (Function r p)
instance DynamicValue (Function r p) where
fromAnyValue = Function
instance Value (Function r p) where
valueRef = valueRef . anyValue
anyValue = fromFunction
newtype Argument t = Argument AnyValue
deriving (DynamicValue, Typeable, Value)
instance (T.DynamicType r, T.Params p) => TypedValue (Function r p) (T.Function r p) where
typeOf _ = T.function undefined undefined
instance (Params b c) => Params (a :-> b) (Argument a :-> c) where
fromAnyList t (x:xs) = let (y,ys) = fromAnyList (T.cdr t) xs
in (Argument x :-> y,ys)
fromAnyList _ _ = error "LLVM.Core.Value.fromAnyList(:->): empty list"
newtype ConstInt t = ConstInt AnyValue
deriving (Arithmetic, ConstValue, DynamicValue, Integer, Typeable, Value)
instance TypedValue (ConstInt T.Int1) T.Int1 where
typeOf = T.int1
instance TypedValue (Argument T.Int1) T.Int1 where
typeOf = T.int1
instance TypedValue (Instruction T.Int1) T.Int1 where
typeOf = T.int1
instance Params T.Int1 (Argument T.Int1) where
fromAnyList = fromAny
instance TypedValue (ConstInt T.Int8) T.Int8 where
typeOf = T.int8
instance TypedValue (Argument T.Int8) T.Int8 where
typeOf = T.int8
instance TypedValue (Instruction T.Int8) T.Int8 where
typeOf = T.int8
instance Params T.Int8 (Argument T.Int8) where
fromAnyList = fromAny
instance TypedValue (ConstInt T.Int16) T.Int16 where
typeOf = T.int16
instance TypedValue (Argument T.Int16) T.Int16 where
typeOf = T.int16
instance Params T.Int16 (Argument T.Int16) where
fromAnyList = fromAny
instance TypedValue (ConstInt T.Int32) T.Int32 where
typeOf = T.int32
instance TypedValue (Argument T.Int32) T.Int32 where
typeOf = T.int32
instance TypedValue (Instruction T.Int32) T.Int32 where
typeOf = T.int32
instance Params T.Int32 (Argument T.Int32) where
fromAnyList = fromAny
instance TypedValue (ConstInt T.Int64) T.Int64 where
typeOf = T.int64
instance TypedValue (Argument T.Int64) T.Int64 where
typeOf = T.int64
instance TypedValue (Instruction T.Int64) T.Int64 where
typeOf = T.int64
instance Params T.Int64 (Argument T.Int64) where
fromAnyList = fromAny
newtype ConstArray t = ConstArray AnyValue
deriving (ConstValue, DynamicValue, Typeable, Value)
instance (T.DynamicType a) => TypedValue (ConstArray a) (T.Array a) where
typeOf _ = T.array undefined 0
instance (T.DynamicType t) => TypedValue (Instruction (T.Array t)) (T.Array t) where
typeOf _ = T.array undefined 0
instance (T.DynamicType t) => TypedValue (Instruction (T.Pointer t)) (T.Pointer t) where
typeOf _ = T.pointer undefined
instance (T.DynamicType t) => Params (T.Pointer t) (Instruction (T.Pointer t)) where
fromAnyList = fromAny
newtype ConstReal t = ConstReal AnyValue
deriving (Arithmetic, ConstValue, DynamicValue, Real, Typeable, Value)
instance TypedValue (ConstReal T.Float) T.Float where
typeOf = T.float
instance TypedValue (Argument T.Float) T.Float where
typeOf = T.float
instance Params T.Float (Argument T.Float) where
fromAnyList = fromAny
instance TypedValue (ConstReal T.Double) T.Double where
typeOf = T.double
instance TypedValue (Argument T.Double) T.Double where
typeOf = T.double
instance Params T.Double (Argument T.Double) where
fromAnyList = fromAny
instance TypedValue (ConstReal T.X86Float80) T.X86Float80 where
typeOf = T.x86Float80
instance TypedValue (Argument T.X86Float80) T.X86Float80 where
typeOf = T.x86Float80
instance Params T.X86Float80 (Argument T.X86Float80) where
fromAnyList = fromAny
instance TypedValue (ConstReal T.Float128) T.Float128 where
typeOf = T.float128
instance TypedValue (Argument T.Float128) T.Float128 where
typeOf = T.float128
instance Params T.Float128 (Argument T.Float128) where
fromAnyList = fromAny
instance TypedValue (ConstReal T.PPCFloat128) T.PPCFloat128 where
typeOf = T.ppcFloat128
instance TypedValue (Argument T.PPCFloat128) T.PPCFloat128 where
typeOf = T.ppcFloat128
instance Params T.PPCFloat128 (Argument T.PPCFloat128) where
fromAnyList = fromAny
countParams :: Function r p -> Int
countParams = fromIntegral . FFI.countParams . valueRef
listParams :: Function r p -> [AnyValue]
listParams f = unsafePerformIO $ do
let len = countParams f
allocaArray len $ \ptr -> do
FFI.getParams (valueRef f) ptr
map mkAnyValue <$> peekArray len ptr
params :: (T.DynamicType r, T.Params p, Params p v) => Function r p -> v
params f = case fromAnyList (T.params (typeOf f)) (listParams f) of
(p, []) -> p
_ -> error "LLVM.Core.Value.params: incompletely consumed params"
typeOfDyn :: Value a => a -> T.AnyType
typeOfDyn val = unsafePerformIO $ T.mkAnyType <$> FFI.typeOf (valueRef val)