{-# LANGUAGE CPP #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE TemplateHaskell #-}
module Data.Array.Accelerate.LLVM.Native.Compile.Module (
Module,
compileModule,
execute, executeMain,
nm,
) where
import Data.Array.Accelerate.Error
import Data.Array.Accelerate.Lifetime
import qualified Data.Array.Accelerate.LLVM.Native.Debug as Debug
import Control.Exception
import Control.Concurrent
import Data.List
import Foreign.LibFFI
import Foreign.Ptr
import Text.Printf
data Module = Module {-# UNPACK #-} !(Lifetime FunctionTable)
data FunctionTable = FunctionTable { functionTable :: [Function] }
type Function = (String, FunPtr ())
instance Show Module where
showsPrec p (Module m)
= showsPrec p (unsafeGetValue m)
instance Show FunctionTable where
showsPrec _ f
= showString "<<"
. showString (intercalate "," [ n | (n,_) <- functionTable f ])
. showString ">>"
{-# INLINEABLE execute #-}
execute
:: Module
-> String
-> ((String, [Arg] -> IO ()) -> IO a)
-> IO a
execute mdl@(Module ft) name k =
withLifetime ft $ \FunctionTable{..} ->
case lookup name functionTable of
Just f -> k (name, \argv -> callFFI f retVoid argv)
Nothing -> $internalError "execute" (printf "function '%s' not found in module: %s\n" name (show mdl))
{-# INLINEABLE executeMain #-}
executeMain
:: Module
-> ((String, [Arg] -> IO ()) -> IO a)
-> IO a
executeMain (Module ft) k =
withLifetime ft $ \FunctionTable{..} ->
case functionTable of
[] -> $internalError "executeMain" "no functions defined in module"
(name,f):_ -> k (name, \argv -> callFFI f retVoid argv)
nm :: Module -> IO [String]
nm (Module ft) =
withLifetime ft $ \FunctionTable{..} ->
return $ map fst functionTable
compileModule :: (([Function] -> IO ()) -> IO ()) -> IO Module
compileModule compile = mask $ \restore -> do
main <- myThreadId
mfuns <- newEmptyMVar
mdone <- newEmptyMVar
_ <- forkIO . reflectExceptionsTo main . restore . compile $ \funs -> do
putMVar mfuns funs
takeMVar mdone
message "worker thread shutting down"
funs <- takeMVar mfuns
ftab <- newLifetime (FunctionTable funs)
addFinalizer ftab (finalise mdone)
return (Module ftab)
reflectExceptionsTo :: ThreadId -> IO () -> IO ()
reflectExceptionsTo tid action =
catchNonThreadKilled action (throwTo tid)
catchNonThreadKilled :: IO a -> (SomeException -> IO a) -> IO a
catchNonThreadKilled action handler =
action `catch` \e ->
case fromException e of
Just ThreadKilled -> throwIO e
_ -> handler e
finalise :: MVar () -> IO ()
finalise done = do
message "finalising function table"
putMVar done ()
{-# INLINE message #-}
message :: String -> IO ()
message msg = Debug.traceIO Debug.dump_exec ("exec: " ++ msg)