{-# LANGUAGE TypeFamilies #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE UndecidableInstances #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE TypeOperators #-} {-# OPTIONS_GHC -fno-warn-orphans #-} module LLVM.Extra.Multi.Vector.Memory where import qualified LLVM.Extra.Multi.Vector as MultiVector import qualified LLVM.Extra.Multi.Vector.Instance as Inst import qualified LLVM.Extra.Multi.Value.Memory as MultiMem import LLVM.Extra.MemoryPrivate (decomposeFromLoad, composeFromStore, ) import qualified LLVM.Core as LLVM import LLVM.Core (CodeGenFunction, Value, ) import qualified Type.Data.Num.Decimal as TypeNum import Type.Data.Num.Decimal ((:*:), ) import Foreign.Ptr (Ptr, ) import Control.Applicative (liftA2, liftA3, ) import Data.Word (Word8, Word16, Word32, Word64) import Data.Int (Int8, Int16, Int32, Int64) class (TypeNum.Positive n, MultiVector.C a, LLVM.IsSized (Struct n a)) => C n a where {-# MINIMAL (load|decompose), (store|compose) #-} type Struct n a :: * load :: Value (Ptr (Struct n a)) -> CodeGenFunction r (MultiVector.T n a) load ptr = decompose =<< LLVM.load ptr store :: MultiVector.T n a -> Value (Ptr (Struct n a)) -> CodeGenFunction r () store r ptr = flip LLVM.store ptr =<< compose r decompose :: Value (Struct n a) -> CodeGenFunction r (MultiVector.T n a) decompose = decomposeFromLoad load compose :: MultiVector.T n a -> CodeGenFunction r (Value (Struct n a)) compose = composeFromStore store instance (TypeNum.Positive n, TypeNum.Positive (n :*: TypeNum.D8)) => C n Word8 where type Struct n Word8 = LLVM.Vector n Word8 load = fmap MultiVector.consPrim . LLVM.load store = LLVM.store . MultiVector.deconsPrim decompose = return . MultiVector.consPrim compose = return . MultiVector.deconsPrim instance (TypeNum.Positive n, TypeNum.Positive (n :*: TypeNum.D16)) => C n Word16 where type Struct n Word16 = LLVM.Vector n Word16 load = fmap MultiVector.consPrim . LLVM.load store = LLVM.store . MultiVector.deconsPrim decompose = return . MultiVector.consPrim compose = return . MultiVector.deconsPrim instance (TypeNum.Positive n, TypeNum.Positive (n :*: TypeNum.D32)) => C n Word32 where type Struct n Word32 = LLVM.Vector n Word32 load = fmap MultiVector.consPrim . LLVM.load store = LLVM.store . MultiVector.deconsPrim decompose = return . MultiVector.consPrim compose = return . MultiVector.deconsPrim instance (TypeNum.Positive n, TypeNum.Positive (n :*: TypeNum.D64)) => C n Word64 where type Struct n Word64 = LLVM.Vector n Word64 load = fmap MultiVector.consPrim . LLVM.load store = LLVM.store . MultiVector.deconsPrim decompose = return . MultiVector.consPrim compose = return . MultiVector.deconsPrim instance (TypeNum.Positive n, TypeNum.Positive (n :*: TypeNum.D8)) => C n Int8 where type Struct n Int8 = LLVM.Vector n Int8 load = fmap MultiVector.consPrim . LLVM.load store = LLVM.store . MultiVector.deconsPrim decompose = return . MultiVector.consPrim compose = return . MultiVector.deconsPrim instance (TypeNum.Positive n, TypeNum.Positive (n :*: TypeNum.D16)) => C n Int16 where type Struct n Int16 = LLVM.Vector n Int16 load = fmap MultiVector.consPrim . LLVM.load store = LLVM.store . MultiVector.deconsPrim decompose = return . MultiVector.consPrim compose = return . MultiVector.deconsPrim instance (TypeNum.Positive n, TypeNum.Positive (n :*: TypeNum.D32)) => C n Int32 where type Struct n Int32 = LLVM.Vector n Int32 load = fmap MultiVector.consPrim . LLVM.load store = LLVM.store . MultiVector.deconsPrim decompose = return . MultiVector.consPrim compose = return . MultiVector.deconsPrim instance (TypeNum.Positive n, TypeNum.Positive (n :*: TypeNum.D64)) => C n Int64 where type Struct n Int64 = LLVM.Vector n Int64 load = fmap MultiVector.consPrim . LLVM.load store = LLVM.store . MultiVector.deconsPrim decompose = return . MultiVector.consPrim compose = return . MultiVector.deconsPrim instance (TypeNum.Positive n, TypeNum.Positive (n :*: TypeNum.D32)) => C n Float where type Struct n Float = LLVM.Vector n Float load = fmap MultiVector.consPrim . LLVM.load store = LLVM.store . MultiVector.deconsPrim decompose = return . MultiVector.consPrim compose = return . MultiVector.deconsPrim instance (TypeNum.Positive n, TypeNum.Positive (n :*: TypeNum.D64)) => C n Double where type Struct n Double = LLVM.Vector n Double load = fmap MultiVector.consPrim . LLVM.load store = LLVM.store . MultiVector.deconsPrim decompose = return . MultiVector.consPrim compose = return . MultiVector.deconsPrim instance (C n a, C n b) => C n (a,b) where type Struct n (a,b) = (LLVM.Struct (Struct n a, (Struct n b, ()))) decompose ab = liftA2 MultiVector.zip (decompose =<< LLVM.extractvalue ab TypeNum.d0) (decompose =<< LLVM.extractvalue ab TypeNum.d1) compose ab = case MultiVector.unzip ab of (a,b) -> do sa <- compose a sb <- compose b ra <- LLVM.insertvalue (LLVM.value LLVM.undef) sa TypeNum.d0 LLVM.insertvalue ra sb TypeNum.d1 instance (C n a, C n b, C n c) => C n (a,b,c) where type Struct n (a,b,c) = (LLVM.Struct (Struct n a, (Struct n b, (Struct n c, ())))) decompose abc = liftA3 MultiVector.zip3 (decompose =<< LLVM.extractvalue abc TypeNum.d0) (decompose =<< LLVM.extractvalue abc TypeNum.d1) (decompose =<< LLVM.extractvalue abc TypeNum.d2) compose abc = case MultiVector.unzip3 abc of (a,b,c) -> do sa <- compose a sb <- compose b sc <- compose c ra <- LLVM.insertvalue (LLVM.value LLVM.undef) sa TypeNum.d0 rb <- LLVM.insertvalue ra sb TypeNum.d1 LLVM.insertvalue rb sc TypeNum.d2 -- orphan instance (C n a) => MultiMem.C (LLVM.Vector n a) where type Struct (LLVM.Vector n a) = Struct n a load = fmap Inst.toMultiValue . load store = store . Inst.fromMultiValue decompose = fmap Inst.toMultiValue . decompose compose = compose . Inst.fromMultiValue