{-# LANGUAGE MultiParamTypeClasses, OverloadedStrings #-}
module LLVM.Internal.OrcJIT.CompileOnDemandLayer where
import LLVM.Prelude
import Control.Exception
import Control.Monad.AnyCont
import Control.Monad.IO.Class
import Data.IORef
import Foreign.Ptr
import LLVM.Internal.Coding
import LLVM.Internal.OrcJIT
import LLVM.Internal.OrcJIT.CompileLayer
import LLVM.Internal.Target
import qualified LLVM.Internal.FFI.DataLayout as FFI
import qualified LLVM.Internal.FFI.OrcJIT as FFI
import qualified LLVM.Internal.FFI.OrcJIT.CompileOnDemandLayer as FFI
import qualified LLVM.Internal.FFI.PtrHierarchy as FFI
type PartitioningFn = Ptr FFI.Function -> IO [Ptr FFI.Function]
data JITCompileCallbackManager =
CallbackMgr !(Ptr FFI.JITCompileCallbackManager)
!(IO ())
newtype IndirectStubsManagerBuilder =
StubsMgr (Ptr FFI.IndirectStubsManagerBuilder)
data CompileOnDemandLayer baseLayer =
CompileOnDemandLayer {
compileLayer :: !(Ptr FFI.CompileOnDemandLayer),
dataLayout :: !(Ptr FFI.DataLayout),
cleanupActions :: !(IORef [IO ()])
}
deriving Eq
instance CompileLayer (CompileOnDemandLayer l) where
getCompileLayer = FFI.upCast . compileLayer
getDataLayout = dataLayout
getCleanups = cleanupActions
instance MonadIO m =>
EncodeM m PartitioningFn (IORef [IO ()] -> IO (FunPtr FFI.PartitioningFn)) where
encodeM partition = return $ \cleanups -> do
allocFunPtr
cleanups
(FFI.wrapPartitioningFn
(\f set -> do
fs <- partition f
traverse_ (FFI.insertFun set) fs
return ()))
instance (MonadIO m, MonadAnyCont IO m) =>
EncodeM m (Maybe (IO ())) (FFI.TargetAddress, IO ()) where
encodeM Nothing = return (FFI.TargetAddress 0, return ())
encodeM (Just f) = do
f' <- anyContToM $ bracketOnError (FFI.wrapErrorHandler f) freeHaskellFunPtr
return
( (FFI.TargetAddress . fromIntegral . ptrToWordPtr . castFunPtrToPtr) f'
, freeHaskellFunPtr f')
newIndirectStubsManagerBuilder ::
ShortByteString ->
IO IndirectStubsManagerBuilder
newIndirectStubsManagerBuilder triple =
flip runAnyContT return $ do
triple' <- encodeM triple
stubsMgr <- liftIO (FFI.createLocalIndirectStubsManagerBuilder triple')
return (StubsMgr stubsMgr)
disposeIndirectStubsManagerBuilder :: IndirectStubsManagerBuilder -> IO ()
disposeIndirectStubsManagerBuilder (StubsMgr stubsMgr) =
FFI.disposeIndirectStubsManagerBuilder stubsMgr
withIndirectStubsManagerBuilder ::
ShortByteString ->
(IndirectStubsManagerBuilder -> IO a) ->
IO a
withIndirectStubsManagerBuilder triple =
bracket
(newIndirectStubsManagerBuilder triple)
disposeIndirectStubsManagerBuilder
newJITCompileCallbackManager ::
ShortByteString ->
Maybe (IO ()) ->
IO JITCompileCallbackManager
newJITCompileCallbackManager triple errorHandler = flip runAnyContT return $ do
triple' <- encodeM triple
(errorHandler', cleanup) <- encodeM errorHandler
callbackMgr <- liftIO (FFI.createLocalCompileCallbackManager triple' errorHandler')
return (CallbackMgr callbackMgr cleanup)
disposeJITCompileCallbackManager :: JITCompileCallbackManager -> IO ()
disposeJITCompileCallbackManager (CallbackMgr mgr cleanup) =
FFI.disposeCallbackManager mgr >> cleanup
withJITCompileCallbackManager ::
ShortByteString ->
Maybe (IO ()) ->
(JITCompileCallbackManager -> IO a) ->
IO a
withJITCompileCallbackManager triple errorHandler =
bracket
(newJITCompileCallbackManager triple errorHandler)
disposeJITCompileCallbackManager
newCompileOnDemandLayer :: CompileLayer l =>
l ->
TargetMachine ->
(Ptr FFI.Function -> IO [Ptr FFI.Function]) ->
JITCompileCallbackManager ->
IndirectStubsManagerBuilder ->
Bool ->
IO (CompileOnDemandLayer l)
newCompileOnDemandLayer baseLayer tm partition (CallbackMgr callbackMgr _) (StubsMgr stubsMgr) cloneStubs =
flip runAnyContT return $ do
cleanups <- liftIO (newIORef [])
dl <- createRegisteredDataLayout tm cleanups
partitionAct <- encodeM partition
partition' <- liftIO $ partitionAct cleanups
cloneStubs' <- encodeM cloneStubs
cl <-
liftIO
(FFI.createCompileOnDemandLayer
(getCompileLayer baseLayer)
partition'
callbackMgr
stubsMgr
cloneStubs')
return (CompileOnDemandLayer cl dl cleanups)
withCompileOnDemandLayer ::
CompileLayer l =>
l ->
TargetMachine ->
(Ptr FFI.Function -> IO [Ptr FFI.Function]) ->
JITCompileCallbackManager ->
IndirectStubsManagerBuilder ->
Bool ->
(CompileOnDemandLayer l -> IO a) ->
IO a
withCompileOnDemandLayer l tm partition callbackMgr stubsMgr cloneStubs =
bracket
(newCompileOnDemandLayer l tm partition callbackMgr stubsMgr cloneStubs)
disposeCompileLayer