llvm-hs-6.1.0: src/LLVM/Internal/OrcJIT/LinkingLayer.hs
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.PtrHierarchy as FFI
import qualified LLVM.Internal.FFI.OrcJIT.LinkingLayer as FFI
-- | After a 'CompileLayer' has compiled the modules to object code,
-- it passes the resulting object files to a 'LinkingLayer'.
class LinkingLayer l where
getLinkingLayer :: l -> Ptr FFI.LinkingLayer
getCleanups :: l -> IORef [IO ()]
-- | Dispose of a 'LinkingLayer'.
disposeLinkingLayer :: LinkingLayer l => l -> IO ()
disposeLinkingLayer l = do
FFI.disposeLinkingLayer (getLinkingLayer l)
sequence_ =<< readIORef (getCleanups l)
-- | Add an object file to the 'LinkingLayer'. The 'SymbolResolver' is used
-- to resolve external symbols in the module.
addObjectFile :: LinkingLayer l => l -> ObjectFile -> SymbolResolver
-> IO FFI.ObjectHandle
addObjectFile linkingLayer (ObjectFile obj) resolver = flip runAnyContT return $ do
resolverAct <- encodeM resolver
resolver' <- liftIO $ resolverAct (getCleanups linkingLayer)
errMsg <- alloca
liftIO $
FFI.addObjectFile
(getLinkingLayer linkingLayer)
obj
resolver'
errMsg
-- | Bare bones implementation of a 'LinkingLayer'.
data ObjectLinkingLayer = ObjectLinkingLayer {
linkingLayer :: !(Ptr FFI.ObjectLinkingLayer),
cleanupActions :: !(IORef [IO ()])
}
instance LinkingLayer ObjectLinkingLayer where
getLinkingLayer (ObjectLinkingLayer ptr _) = FFI.upCast ptr
getCleanups = cleanupActions
-- | Create a new 'ObjectLinkingLayer'. This should be disposed using
-- 'disposeLinkingLayer' when it is no longer needed.
newObjectLinkingLayer :: IO ObjectLinkingLayer
newObjectLinkingLayer = do
linkingLayer <- FFI.createObjectLinkingLayer
cleanups <- liftIO (newIORef [])
return $ ObjectLinkingLayer linkingLayer cleanups
-- | 'bracket'-style wrapper around 'newObjectLinkingLayer' and 'disposeLinkingLayer'.
withObjectLinkingLayer :: (ObjectLinkingLayer -> IO a) -> IO a
withObjectLinkingLayer = bracket newObjectLinkingLayer disposeLinkingLayer