-- GENERATED by C->Haskell Compiler, version 0.17.2 Crystal Seed, 24 Jan 2009 (Haskell)
-- Edit the ORIGNAL .chs file instead!


{-# LINE 1 "./Foreign/CUDA/Runtime/Error.chs" #-}
{-# LANGUAGE BangPatterns             #-}
{-# LANGUAGE DeriveDataTypeable       #-}
{-# LANGUAGE ForeignFunctionInterface #-}
--------------------------------------------------------------------------------
-- |
-- Module    : Foreign.CUDA.Runtime.Error
-- Copyright : (c) [2009..2012] Trevor L. McDonell
-- License   : BSD
--
-- Error handling functions
--
--------------------------------------------------------------------------------

module Foreign.CUDA.Runtime.Error (

  Status(..), CUDAException(..),

  cudaError, describe, requireSDK,
  resultIfOk, nothingIfOk

) where

-- Friends
import Foreign.CUDA.Internal.C2HS

-- System
import Foreign.C
import Foreign.Ptr
import Data.Typeable
import Control.Exception
import System.IO.Unsafe



{-# LINE 34 "./Foreign/CUDA/Runtime/Error.chs" #-}



--------------------------------------------------------------------------------
-- Return Status
--------------------------------------------------------------------------------

-- |
-- Return codes from API functions
--
data Status = Success
            | MissingConfiguration
            | MemoryAllocation
            | InitializationError
            | LaunchFailure
            | PriorLaunchFailure
            | LaunchTimeout
            | LaunchOutOfResources
            | InvalidDeviceFunction
            | InvalidConfiguration
            | InvalidDevice
            | InvalidValue
            | InvalidPitchValue
            | InvalidSymbol
            | MapBufferObjectFailed
            | UnmapBufferObjectFailed
            | InvalidHostPointer
            | InvalidDevicePointer
            | InvalidTexture
            | InvalidTextureBinding
            | InvalidChannelDescriptor
            | InvalidMemcpyDirection
            | AddressOfConstant
            | TextureFetchFailed
            | TextureNotBound
            | SynchronizationError
            | InvalidFilterSetting
            | InvalidNormSetting
            | MixedDeviceExecution
            | CudartUnloading
            | Unknown
            | NotYetImplemented
            | MemoryValueTooLarge
            | InvalidResourceHandle
            | NotReady
            | InsufficientDriver
            | SetOnActiveProcess
            | InvalidSurface
            | NoDevice
            | ECCUncorrectable
            | SharedObjectSymbolNotFound
            | SharedObjectInitFailed
            | UnsupportedLimit
            | DuplicateVariableName
            | DuplicateTextureName
            | DuplicateSurfaceName
            | DevicesUnavailable
            | InvalidKernelImage
            | NoKernelImageForDevice
            | IncompatibleDriverContext
            | PeerAccessAlreadyEnabled
            | PeerAccessNotEnabled
            | DeviceAlreadyInUse
            | ProfilerDisabled
            | ProfilerNotInitialized
            | ProfilerAlreadyStarted
            | ProfilerAlreadyStopped
            | Assert
            | TooManyPeers
            | HostMemoryAlreadyRegistered
            | HostMemoryNotRegistered
            | OperatingSystem
            | PeerAccessUnsupported
            | LaunchMaxDepthExceeded
            | LaunchFileScopedTex
            | LaunchFileScopedSurf
            | SyncDepthExceeded
            | LaunchPendingCountExceeded
            | NotPermitted
            | NotSupported
            | HardwareStackError
            | IllegalInstruction
            | MisalignedAddress
            | InvalidAddressSpace
            | InvalidPc
            | IllegalAddress
            | InvalidPtx
            | InvalidGraphicsContext
            | StartupFailure
            | ApiFailureBase
            deriving (Eq,Show)
instance Enum Status where
  fromEnum Success = 0
  fromEnum MissingConfiguration = 1
  fromEnum MemoryAllocation = 2
  fromEnum InitializationError = 3
  fromEnum LaunchFailure = 4
  fromEnum PriorLaunchFailure = 5
  fromEnum LaunchTimeout = 6
  fromEnum LaunchOutOfResources = 7
  fromEnum InvalidDeviceFunction = 8
  fromEnum InvalidConfiguration = 9
  fromEnum InvalidDevice = 10
  fromEnum InvalidValue = 11
  fromEnum InvalidPitchValue = 12
  fromEnum InvalidSymbol = 13
  fromEnum MapBufferObjectFailed = 14
  fromEnum UnmapBufferObjectFailed = 15
  fromEnum InvalidHostPointer = 16
  fromEnum InvalidDevicePointer = 17
  fromEnum InvalidTexture = 18
  fromEnum InvalidTextureBinding = 19
  fromEnum InvalidChannelDescriptor = 20
  fromEnum InvalidMemcpyDirection = 21
  fromEnum AddressOfConstant = 22
  fromEnum TextureFetchFailed = 23
  fromEnum TextureNotBound = 24
  fromEnum SynchronizationError = 25
  fromEnum InvalidFilterSetting = 26
  fromEnum InvalidNormSetting = 27
  fromEnum MixedDeviceExecution = 28
  fromEnum CudartUnloading = 29
  fromEnum Unknown = 30
  fromEnum NotYetImplemented = 31
  fromEnum MemoryValueTooLarge = 32
  fromEnum InvalidResourceHandle = 33
  fromEnum NotReady = 34
  fromEnum InsufficientDriver = 35
  fromEnum SetOnActiveProcess = 36
  fromEnum InvalidSurface = 37
  fromEnum NoDevice = 38
  fromEnum ECCUncorrectable = 39
  fromEnum SharedObjectSymbolNotFound = 40
  fromEnum SharedObjectInitFailed = 41
  fromEnum UnsupportedLimit = 42
  fromEnum DuplicateVariableName = 43
  fromEnum DuplicateTextureName = 44
  fromEnum DuplicateSurfaceName = 45
  fromEnum DevicesUnavailable = 46
  fromEnum InvalidKernelImage = 47
  fromEnum NoKernelImageForDevice = 48
  fromEnum IncompatibleDriverContext = 49
  fromEnum PeerAccessAlreadyEnabled = 50
  fromEnum PeerAccessNotEnabled = 51
  fromEnum DeviceAlreadyInUse = 54
  fromEnum ProfilerDisabled = 55
  fromEnum ProfilerNotInitialized = 56
  fromEnum ProfilerAlreadyStarted = 57
  fromEnum ProfilerAlreadyStopped = 58
  fromEnum Assert = 59
  fromEnum TooManyPeers = 60
  fromEnum HostMemoryAlreadyRegistered = 61
  fromEnum HostMemoryNotRegistered = 62
  fromEnum OperatingSystem = 63
  fromEnum PeerAccessUnsupported = 64
  fromEnum LaunchMaxDepthExceeded = 65
  fromEnum LaunchFileScopedTex = 66
  fromEnum LaunchFileScopedSurf = 67
  fromEnum SyncDepthExceeded = 68
  fromEnum LaunchPendingCountExceeded = 69
  fromEnum NotPermitted = 70
  fromEnum NotSupported = 71
  fromEnum HardwareStackError = 72
  fromEnum IllegalInstruction = 73
  fromEnum MisalignedAddress = 74
  fromEnum InvalidAddressSpace = 75
  fromEnum InvalidPc = 76
  fromEnum IllegalAddress = 77
  fromEnum InvalidPtx = 78
  fromEnum InvalidGraphicsContext = 79
  fromEnum StartupFailure = 127
  fromEnum ApiFailureBase = 10000

  toEnum 0 = Success
  toEnum 1 = MissingConfiguration
  toEnum 2 = MemoryAllocation
  toEnum 3 = InitializationError
  toEnum 4 = LaunchFailure
  toEnum 5 = PriorLaunchFailure
  toEnum 6 = LaunchTimeout
  toEnum 7 = LaunchOutOfResources
  toEnum 8 = InvalidDeviceFunction
  toEnum 9 = InvalidConfiguration
  toEnum 10 = InvalidDevice
  toEnum 11 = InvalidValue
  toEnum 12 = InvalidPitchValue
  toEnum 13 = InvalidSymbol
  toEnum 14 = MapBufferObjectFailed
  toEnum 15 = UnmapBufferObjectFailed
  toEnum 16 = InvalidHostPointer
  toEnum 17 = InvalidDevicePointer
  toEnum 18 = InvalidTexture
  toEnum 19 = InvalidTextureBinding
  toEnum 20 = InvalidChannelDescriptor
  toEnum 21 = InvalidMemcpyDirection
  toEnum 22 = AddressOfConstant
  toEnum 23 = TextureFetchFailed
  toEnum 24 = TextureNotBound
  toEnum 25 = SynchronizationError
  toEnum 26 = InvalidFilterSetting
  toEnum 27 = InvalidNormSetting
  toEnum 28 = MixedDeviceExecution
  toEnum 29 = CudartUnloading
  toEnum 30 = Unknown
  toEnum 31 = NotYetImplemented
  toEnum 32 = MemoryValueTooLarge
  toEnum 33 = InvalidResourceHandle
  toEnum 34 = NotReady
  toEnum 35 = InsufficientDriver
  toEnum 36 = SetOnActiveProcess
  toEnum 37 = InvalidSurface
  toEnum 38 = NoDevice
  toEnum 39 = ECCUncorrectable
  toEnum 40 = SharedObjectSymbolNotFound
  toEnum 41 = SharedObjectInitFailed
  toEnum 42 = UnsupportedLimit
  toEnum 43 = DuplicateVariableName
  toEnum 44 = DuplicateTextureName
  toEnum 45 = DuplicateSurfaceName
  toEnum 46 = DevicesUnavailable
  toEnum 47 = InvalidKernelImage
  toEnum 48 = NoKernelImageForDevice
  toEnum 49 = IncompatibleDriverContext
  toEnum 50 = PeerAccessAlreadyEnabled
  toEnum 51 = PeerAccessNotEnabled
  toEnum 54 = DeviceAlreadyInUse
  toEnum 55 = ProfilerDisabled
  toEnum 56 = ProfilerNotInitialized
  toEnum 57 = ProfilerAlreadyStarted
  toEnum 58 = ProfilerAlreadyStopped
  toEnum 59 = Assert
  toEnum 60 = TooManyPeers
  toEnum 61 = HostMemoryAlreadyRegistered
  toEnum 62 = HostMemoryNotRegistered
  toEnum 63 = OperatingSystem
  toEnum 64 = PeerAccessUnsupported
  toEnum 65 = LaunchMaxDepthExceeded
  toEnum 66 = LaunchFileScopedTex
  toEnum 67 = LaunchFileScopedSurf
  toEnum 68 = SyncDepthExceeded
  toEnum 69 = LaunchPendingCountExceeded
  toEnum 70 = NotPermitted
  toEnum 71 = NotSupported
  toEnum 72 = HardwareStackError
  toEnum 73 = IllegalInstruction
  toEnum 74 = MisalignedAddress
  toEnum 75 = InvalidAddressSpace
  toEnum 76 = InvalidPc
  toEnum 77 = IllegalAddress
  toEnum 78 = InvalidPtx
  toEnum 79 = InvalidGraphicsContext
  toEnum 127 = StartupFailure
  toEnum 10000 = ApiFailureBase
  toEnum unmatched = error ("Status.toEnum: Cannot match " ++ show unmatched)

{-# LINE 46 "./Foreign/CUDA/Runtime/Error.chs" #-}


--------------------------------------------------------------------------------
-- Exceptions
--------------------------------------------------------------------------------

data CUDAException
  = ExitCode  Status
  | UserError String
  deriving Typeable

instance Exception CUDAException

instance Show CUDAException where
  showsPrec _ (ExitCode  s) = showString ("CUDA Exception: " ++ describe s)
  showsPrec _ (UserError s) = showString ("CUDA Exception: " ++ s)


-- |
-- Raise a 'CUDAException' in the IO Monad
--
cudaError :: String -> IO a
cudaError s = throwIO (UserError s)

-- |
-- A specially formatted error message
--
requireSDK :: Double -> String -> IO a
requireSDK v s = cudaError ("'" ++ s ++ "' requires at least cuda-" ++ show v)


--------------------------------------------------------------------------------
-- Helper Functions
--------------------------------------------------------------------------------

-- |
-- Return the descriptive string associated with a particular error code
--
describe :: (Status) -> (String)
describe a1 =
  unsafePerformIO $
  let {a1' = cFromEnum a1} in 
  let {res = describe'_ a1'} in
  peekCString res >>= \res' ->
  return (res')

{-# LINE 85 "./Foreign/CUDA/Runtime/Error.chs" #-}

--
-- Logically, this must be a pure function, returning a pointer to a statically
-- defined string constant.
--


-- |
-- Return the results of a function on successful execution, otherwise return
-- the error string associated with the return code
--
{-# INLINE resultIfOk #-}
resultIfOk :: (Status, a) -> IO a
resultIfOk (status, !result) =
    case status of
        Success -> return  result
        _       -> throwIO (ExitCode status)


-- |
-- Return the error string associated with an unsuccessful return code,
-- otherwise Nothing
--
{-# INLINE nothingIfOk #-}
nothingIfOk :: Status -> IO ()
nothingIfOk status =
    case status of
        Success -> return  ()
        _       -> throwIO (ExitCode status)


foreign import ccall unsafe "Foreign/CUDA/Runtime/Error.chs.h cudaGetErrorStringWrapper"
  describe'_ :: (CInt -> (Ptr CChar))