module LLVM.Internal.OrcJIT.LinkingLayer 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.OrcJIT
import LLVM.Internal.Coding
import LLVM.Internal.ObjectFile
import qualified LLVM.Internal.FFI.ShortByteString as SBS
import qualified LLVM.Internal.FFI.PtrHierarchy as FFI
import qualified LLVM.Internal.FFI.OrcJIT as FFI
import qualified LLVM.Internal.FFI.OrcJIT.LinkingLayer as FFI
class LinkingLayer l where
getLinkingLayer :: l -> Ptr FFI.LinkingLayer
getCleanups :: l -> IORef [IO ()]
disposeLinkingLayer :: LinkingLayer l => l -> IO ()
disposeLinkingLayer l = do
FFI.disposeLinkingLayer (getLinkingLayer l)
sequence_ =<< readIORef (getCleanups l)
addObjectFile :: LinkingLayer l => l -> FFI.ModuleKey -> ObjectFile -> IO ()
addObjectFile linkingLayer k (ObjectFile obj) = flip runAnyContT return $ do
errMsg <- alloca
liftIO $
FFI.addObjectFile
(getLinkingLayer linkingLayer)
k
obj
errMsg
data ObjectLinkingLayer = ObjectLinkingLayer {
linkingLayer :: !(Ptr FFI.ObjectLinkingLayer),
cleanupActions :: !(IORef [IO ()])
}
instance LinkingLayer ObjectLinkingLayer where
getLinkingLayer (ObjectLinkingLayer ptr _) = FFI.upCast ptr
getCleanups = cleanupActions
newObjectLinkingLayer :: ExecutionSession -> (FFI.ModuleKey -> IO (Ptr FFI.SymbolResolver)) -> IO ObjectLinkingLayer
newObjectLinkingLayer (ExecutionSession es) getResolver = do
cleanups <- liftIO (newIORef [])
getResolver' <- allocFunPtr cleanups (FFI.wrapGetSymbolResolver getResolver)
linkingLayer <- FFI.createObjectLinkingLayer es getResolver'
return $ ObjectLinkingLayer linkingLayer cleanups
withObjectLinkingLayer :: ExecutionSession -> (FFI.ModuleKey -> IO (Ptr FFI.SymbolResolver)) -> (ObjectLinkingLayer -> IO a) -> IO a
withObjectLinkingLayer es resolver = bracket (newObjectLinkingLayer es resolver) disposeLinkingLayer
findSymbol :: LinkingLayer l => l -> ShortByteString -> Bool -> IO (Either JITSymbolError JITSymbol)
findSymbol linkingLayer symbol exportedSymbolsOnly =
SBS.useAsCString symbol $ \symbol' ->
flip runAnyContT return $ do
exportedSymbolsOnly' <- encodeM exportedSymbolsOnly
symbol <- anyContToM $ bracket
(FFI.findSymbol (getLinkingLayer linkingLayer) symbol' exportedSymbolsOnly') FFI.disposeSymbol
decodeM symbol
findSymbolIn :: LinkingLayer l => l -> FFI.ModuleKey -> ShortByteString -> Bool -> IO (Either JITSymbolError JITSymbol)
findSymbolIn linkingLayer handle symbol exportedSymbolsOnly =
SBS.useAsCString symbol $ \symbol' ->
flip runAnyContT return $ do
exportedSymbolsOnly' <- encodeM exportedSymbolsOnly
symbol <- anyContToM $ bracket
(FFI.findSymbolIn (getLinkingLayer linkingLayer) handle symbol' exportedSymbolsOnly') FFI.disposeSymbol
decodeM symbol