{-# 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 ::
ExecutionSession ->
ShortByteString ->
Maybe (IO ()) ->
IO JITCompileCallbackManager
newJITCompileCallbackManager (ExecutionSession es) triple errorHandler = flip runAnyContT return $ do
triple' <- encodeM triple
(errorHandler', cleanup) <- encodeM errorHandler
callbackMgr <- liftIO (FFI.createLocalCompileCallbackManager es triple' errorHandler')
return (CallbackMgr callbackMgr cleanup)
disposeJITCompileCallbackManager :: JITCompileCallbackManager -> IO ()
disposeJITCompileCallbackManager (CallbackMgr mgr cleanup) =
FFI.disposeCallbackManager mgr >> cleanup
withJITCompileCallbackManager ::
ExecutionSession ->
ShortByteString ->
Maybe (IO ()) ->
(JITCompileCallbackManager -> IO a) ->
IO a
withJITCompileCallbackManager es triple errorHandler =
bracket
(newJITCompileCallbackManager es triple errorHandler)
disposeJITCompileCallbackManager
newCompileOnDemandLayer :: CompileLayer l =>
ExecutionSession ->
l ->
TargetMachine ->
(ModuleKey -> IO (Ptr FFI.SymbolResolver)) ->
(ModuleKey -> Ptr FFI.SymbolResolver -> IO ()) ->
(Ptr FFI.Function -> IO [Ptr FFI.Function]) ->
JITCompileCallbackManager ->
IndirectStubsManagerBuilder ->
Bool ->
IO (CompileOnDemandLayer l)
newCompileOnDemandLayer (ExecutionSession es) baseLayer tm getSymbolResolver setSymbolResolver partition (CallbackMgr callbackMgr _) (StubsMgr stubsMgr) cloneStubs =
flip runAnyContT return $ do
cleanups <- liftIO (newIORef [])
dl <- createRegisteredDataLayout tm cleanups
getSymbolResolver' <- liftIO (allocFunPtr cleanups (FFI.wrapGetSymbolResolver getSymbolResolver))
setSymbolResolver' <- liftIO (allocFunPtr cleanups (FFI.wrapSetSymbolResolver setSymbolResolver))
partitionAct <- encodeM partition
partition' <- liftIO $ partitionAct cleanups
cloneStubs' <- encodeM cloneStubs
cl <-
liftIO
(FFI.createCompileOnDemandLayer
es
(getCompileLayer baseLayer)
getSymbolResolver'
setSymbolResolver'
partition'
callbackMgr
stubsMgr
cloneStubs')
return (CompileOnDemandLayer cl dl cleanups)
withCompileOnDemandLayer ::
CompileLayer l =>
ExecutionSession ->
l ->
TargetMachine ->
(ModuleKey -> IO (Ptr FFI.SymbolResolver)) ->
(ModuleKey -> Ptr FFI.SymbolResolver -> IO ()) ->
(Ptr FFI.Function -> IO [Ptr FFI.Function]) ->
JITCompileCallbackManager ->
IndirectStubsManagerBuilder ->
Bool ->
(CompileOnDemandLayer l -> IO a) ->
IO a
withCompileOnDemandLayer es l tm getSymbolResolver setSymbolResolver partition callbackMgr stubsMgr cloneStubs =
bracket
(newCompileOnDemandLayer es l tm getSymbolResolver setSymbolResolver partition callbackMgr stubsMgr cloneStubs)
disposeCompileLayer