{-# LANGUAGE
  TemplateHaskell,
  MultiParamTypeClasses
  #-}
module LLVM.Internal.Atomicity where

import LLVM.Prelude

import Data.Maybe

import qualified LLVM.Internal.FFI.LLVMCTypes as FFI

import LLVM.Internal.Coding
import qualified LLVM.AST as A

genCodingInstance [t| Maybe A.MemoryOrdering |] ''FFI.MemoryOrdering [
  (FFI.memoryOrderingNotAtomic, Nothing),
  (FFI.memoryOrderingUnordered, Just A.Unordered),
  (FFI.memoryOrderingMonotonic, Just A.Monotonic),
  (FFI.memoryOrderingAcquire, Just A.Acquire),
  (FFI.memoryOrderingRelease, Just A.Release),
  (FFI.memoryOrderingAcquireRelease, Just A.AcquireRelease),
  (FFI.memoryOrderingSequentiallyConsistent, Just A.SequentiallyConsistent)
 ]

genCodingInstance [t| A.SynchronizationScope |] ''FFI.SynchronizationScope [
  (FFI.synchronizationScopeSingleThread, A.SingleThread),
  (FFI.synchronizationScopeSystem, A.System)
 ]

instance Monad m => EncodeM m (Maybe A.Atomicity) (FFI.SynchronizationScope, FFI.MemoryOrdering) where
  encodeM :: Maybe Atomicity -> m (SynchronizationScope, MemoryOrdering)
encodeM a :: Maybe Atomicity
a =
    (SynchronizationScope
 -> MemoryOrdering -> (SynchronizationScope, MemoryOrdering))
-> m (SynchronizationScope
      -> MemoryOrdering -> (SynchronizationScope, MemoryOrdering))
forall (m :: * -> *) a. Monad m => a -> m a
return (,) m (SynchronizationScope
   -> MemoryOrdering -> (SynchronizationScope, MemoryOrdering))
-> m SynchronizationScope
-> m (MemoryOrdering -> (SynchronizationScope, MemoryOrdering))
forall (m :: * -> *) a b. Monad m => m (a -> b) -> m a -> m b
`ap` SynchronizationScope -> m SynchronizationScope
forall (e :: * -> *) h c. EncodeM e h c => h -> e c
encodeM (SynchronizationScope
-> (Atomicity -> SynchronizationScope)
-> Maybe Atomicity
-> SynchronizationScope
forall b a. b -> (a -> b) -> Maybe a -> b
maybe SynchronizationScope
A.SingleThread Atomicity -> SynchronizationScope
forall a b. (a, b) -> a
fst Maybe Atomicity
a) m (MemoryOrdering -> (SynchronizationScope, MemoryOrdering))
-> m MemoryOrdering -> m (SynchronizationScope, MemoryOrdering)
forall (m :: * -> *) a b. Monad m => m (a -> b) -> m a -> m b
`ap` Maybe MemoryOrdering -> m MemoryOrdering
forall (e :: * -> *) h c. EncodeM e h c => h -> e c
encodeM ((Atomicity -> MemoryOrdering)
-> Maybe Atomicity -> Maybe MemoryOrdering
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM Atomicity -> MemoryOrdering
forall a b. (a, b) -> b
snd Maybe Atomicity
a)

instance Monad m => DecodeM m (Maybe A.Atomicity) (FFI.SynchronizationScope, FFI.MemoryOrdering) where
  decodeM :: (SynchronizationScope, MemoryOrdering) -> m (Maybe Atomicity)
decodeM (ss :: SynchronizationScope
ss, ao :: MemoryOrdering
ao) = (SynchronizationScope -> Maybe MemoryOrdering -> Maybe Atomicity)
-> m (SynchronizationScope
      -> Maybe MemoryOrdering -> Maybe Atomicity)
forall (m :: * -> *) a. Monad m => a -> m a
return ((MemoryOrdering -> Atomicity)
-> Maybe MemoryOrdering -> Maybe Atomicity
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM ((MemoryOrdering -> Atomicity)
 -> Maybe MemoryOrdering -> Maybe Atomicity)
-> (SynchronizationScope -> MemoryOrdering -> Atomicity)
-> SynchronizationScope
-> Maybe MemoryOrdering
-> Maybe Atomicity
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (,)) m (SynchronizationScope -> Maybe MemoryOrdering -> Maybe Atomicity)
-> m SynchronizationScope
-> m (Maybe MemoryOrdering -> Maybe Atomicity)
forall (m :: * -> *) a b. Monad m => m (a -> b) -> m a -> m b
`ap` SynchronizationScope -> m SynchronizationScope
forall (d :: * -> *) h c. DecodeM d h c => c -> d h
decodeM SynchronizationScope
ss m (Maybe MemoryOrdering -> Maybe Atomicity)
-> m (Maybe MemoryOrdering) -> m (Maybe Atomicity)
forall (m :: * -> *) a b. Monad m => m (a -> b) -> m a -> m b
`ap` MemoryOrdering -> m (Maybe MemoryOrdering)
forall (d :: * -> *) h c. DecodeM d h c => c -> d h
decodeM MemoryOrdering
ao

instance Monad m => EncodeM m A.Atomicity (FFI.SynchronizationScope, FFI.MemoryOrdering) where
  encodeM :: Atomicity -> m (SynchronizationScope, MemoryOrdering)
encodeM = Maybe Atomicity -> m (SynchronizationScope, MemoryOrdering)
forall (e :: * -> *) h c. EncodeM e h c => h -> e c
encodeM (Maybe Atomicity -> m (SynchronizationScope, MemoryOrdering))
-> (Atomicity -> Maybe Atomicity)
-> Atomicity
-> m (SynchronizationScope, MemoryOrdering)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Atomicity -> Maybe Atomicity
forall a. a -> Maybe a
Just

instance Monad m => DecodeM m A.Atomicity (FFI.SynchronizationScope, FFI.MemoryOrdering) where
  decodeM :: (SynchronizationScope, MemoryOrdering) -> m Atomicity
decodeM = (Maybe Atomicity -> Atomicity)
-> m (Maybe Atomicity) -> m Atomicity
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM Maybe Atomicity -> Atomicity
forall a. HasCallStack => Maybe a -> a
fromJust (m (Maybe Atomicity) -> m Atomicity)
-> ((SynchronizationScope, MemoryOrdering) -> m (Maybe Atomicity))
-> (SynchronizationScope, MemoryOrdering)
-> m Atomicity
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (SynchronizationScope, MemoryOrdering) -> m (Maybe Atomicity)
forall (d :: * -> *) h c. DecodeM d h c => c -> d h
decodeM

instance Monad m => EncodeM m A.MemoryOrdering FFI.MemoryOrdering where
  encodeM :: MemoryOrdering -> m MemoryOrdering
encodeM = Maybe MemoryOrdering -> m MemoryOrdering
forall (e :: * -> *) h c. EncodeM e h c => h -> e c
encodeM (Maybe MemoryOrdering -> m MemoryOrdering)
-> (MemoryOrdering -> Maybe MemoryOrdering)
-> MemoryOrdering
-> m MemoryOrdering
forall b c a. (b -> c) -> (a -> b) -> a -> c
. MemoryOrdering -> Maybe MemoryOrdering
forall a. a -> Maybe a
Just

instance Monad m => DecodeM m A.MemoryOrdering FFI.MemoryOrdering where
  decodeM :: MemoryOrdering -> m MemoryOrdering
decodeM = (Maybe MemoryOrdering -> MemoryOrdering)
-> m (Maybe MemoryOrdering) -> m MemoryOrdering
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM Maybe MemoryOrdering -> MemoryOrdering
forall a. HasCallStack => Maybe a -> a
fromJust (m (Maybe MemoryOrdering) -> m MemoryOrdering)
-> (MemoryOrdering -> m (Maybe MemoryOrdering))
-> MemoryOrdering
-> m MemoryOrdering
forall b c a. (b -> c) -> (a -> b) -> a -> c
. MemoryOrdering -> m (Maybe MemoryOrdering)
forall (d :: * -> *) h c. DecodeM d h c => c -> d h
decodeM