packages feed

nvvm-0.7.5.0: Foreign/NVVM/Error.chs

{-# LANGUAGE DeriveDataTypeable #-}
--------------------------------------------------------------------------------
-- |
-- Module    : Foreign.NVVM.Error
-- Copyright : [2016] Trevor L. McDonell
-- License   : BSD
--
-- Error handling
--
--------------------------------------------------------------------------------

module Foreign.NVVM.Error (

  Status(..),
  describe,
  resultIfOk, nothingIfOk,
  nvvmError, nvvmErrorIO, requireSDK,

) where

import Foreign.NVVM.Internal.C2HS
import Foreign.C.String

import Control.Exception
import Data.Typeable
import Language.Haskell.TH
import Text.Printf

#include "cbits/stubs.h"
{# context lib="nvvm" #}


-- Return codes
-- ------------

-- | NVVM API function return code
--
{# enum nvvmResult as Status
  { underscoreToCase
  , NVVM_SUCCESS                   as Success
  , NVVM_ERROR_IR_VERSION_MISMATCH as IRVersionMismatch
  , NVVM_ERROR_INVALID_IR          as InvalidIR
  , NVVM_ERROR_COMPILATION         as CompilationFailure
  }
  with prefix="NVVM_ERROR" deriving (Eq, Show) #}


-- | Get the descriptive message string for the given result code
--
{#
  fun pure unsafe nvvmGetErrorString as describe
    { cFromEnum `Status'
    }
    -> `String' peekCString*
#}


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

data NVVMException
  = ExitCode Status
  | UserError String
  deriving Typeable

instance Exception NVVMException

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


-- | Throw an exception. Exceptions may be thrown from pure code, but can only
-- be caught in the 'IO' monad.
--
{-# RULES "nvvmError/IO" nvvmError = nvvmErrorIO #-}
{-# NOINLINE [1] nvvmError #-}
nvvmError :: String -> a
nvvmError s = throw (UserError s)

-- | Raise an NVVM exception in the 'IO' monad
--
nvvmErrorIO :: String -> IO a
nvvmErrorIO s = throwIO (UserError s)

-- |
-- A specially formatted error message
--
requireSDK :: Name -> Double -> a
requireSDK n v = nvvmError $ printf "'%s' requires at least cuda-%3.1f\n" (show n) v


-- Helper functions
-- ----------------

-- | Return the result of a function on successful execution, otherwise throw an
-- exception.
--
{-# INLINE resultIfOk #-}
resultIfOk :: (Status, a) -> IO a
resultIfOk (status, result) =
  case status of
    Success -> return $! result
    _       -> throwIO (ExitCode status)

-- | Throw an exception on an unsuccessful return code
--
{-# INLINE nothingIfOk #-}
nothingIfOk :: Status -> IO ()
nothingIfOk status =
  case status of
    Success -> return ()
    _       -> throwIO (ExitCode status)