packages feed

llvm-0.0.2: LLVM/Core.hs

{-# LANGUAGE FunctionalDependencies, MultiParamTypeClasses #-}

module LLVM.Core
    (
    -- * Modules
      createModule

    -- * Module providers
    , createModuleProviderForExistingModule

    -- * Types
    , addTypeName
    , deleteTypeName

    -- * Values
    , addGlobal
    , setInitializer

    -- ** Operations on functions
    , addFunction
    , deleteFunction
    , getNamedFunction

    -- * Basic blocks
    , appendBasicBlock
    , insertBasicBlock
    , deleteBasicBlock
    ) where

import Control.Applicative ((<$>))
import Foreign.C.String (withCString)
import Foreign.Marshal.Utils (toBool)
import Foreign.ForeignPtr (FinalizerPtr, newForeignPtr)
import Foreign.Ptr (Ptr, nullPtr)
import Prelude hiding (mod)

import qualified LLVM.Core.FFI as FFI
import qualified LLVM.Core.Builder as B
import qualified LLVM.Core.Type as T
import qualified LLVM.Core.Value as V


createModule :: String -> IO T.Module
createModule name =
    withCString name $ \namePtr -> do
      ptr <- FFI.moduleCreateWithName namePtr
      final <- h2c_module FFI.disposeModule
      T.Module <$> newForeignPtr final ptr

foreign import ccall "wrapper" h2c_module
    :: (FFI.ModuleRef -> IO ()) -> IO (FinalizerPtr a)


createModuleProviderForExistingModule :: T.Module -> IO T.ModuleProvider
createModuleProviderForExistingModule mod =
    T.withModule mod $ \modPtr -> do
        ptr <- FFI.createModuleProviderForExistingModule modPtr
        final <- h2c_moduleProvider FFI.disposeModuleProvider
        T.ModuleProvider <$> newForeignPtr final ptr

foreign import ccall "wrapper" h2c_moduleProvider
    :: (FFI.ModuleProviderRef -> IO ()) -> IO (FinalizerPtr a)


addTypeName :: (T.Type t) => T.Module -> t -> String -> IO Bool
addTypeName mod typ name =
    T.withModule mod $ \modPtr ->
      withCString name $ \namePtr ->
        toBool <$> FFI.addTypeName modPtr namePtr (T.typeRef typ)
                 
deleteTypeName :: T.Module -> String -> IO ()
deleteTypeName mod name =
    T.withModule mod $ \modPtr ->
      withCString name $ FFI.deleteTypeName modPtr

addGlobal :: (T.Type t) => T.Module -> t -> String -> IO (V.GlobalVar t)
addGlobal mod typ name =
    T.withModule mod $ \modPtr ->
      withCString name $ \namePtr ->
        V.GlobalVar . V.mkAnyValue <$> FFI.addGlobal modPtr (T.typeRef typ) namePtr

setInitializer :: V.ConstValue t => V.GlobalVar a -> t -> IO ()
setInitializer global cnst =
    FFI.setInitializer (V.valueRef global) (V.valueRef cnst)

addFunction :: (T.Params p) => T.Module -> String -> T.Function r p
            -> IO (V.Function r p)
addFunction mod name typ =
    T.withModule mod $ \modPtr ->
      withCString name $ \namePtr ->
        V.Function . V.mkAnyValue <$> FFI.addFunction modPtr namePtr (T.typeRef typ)

deleteFunction :: V.Function r p -> IO ()
deleteFunction = FFI.deleteFunction . V.valueRef

maybePtr :: (Ptr a -> b) -> Ptr a -> Maybe b
maybePtr f ptr | ptr /= nullPtr = Just (f ptr)
               | otherwise = Nothing

getNamedFunction :: T.Module -> String -> IO (Maybe (V.Function r p))
getNamedFunction mod name =
    T.withModule mod $ \modPtr ->
      withCString name $ \namePtr ->
        maybePtr (V.Function . V.mkAnyValue) <$> FFI.getNamedFunction modPtr namePtr

appendBasicBlock :: V.Function r p -> String -> IO B.BasicBlock
appendBasicBlock func name =
    withCString name $ \namePtr ->
      B.BasicBlock . V.mkAnyValue <$> FFI.appendBasicBlock (V.valueRef func) namePtr

insertBasicBlock :: B.BasicBlock -> String -> IO B.BasicBlock
insertBasicBlock before name =
    withCString name $ \namePtr ->
      B.BasicBlock . V.mkAnyValue <$> FFI.insertBasicBlock (V.valueRef before) namePtr

deleteBasicBlock :: B.BasicBlock -> IO ()
deleteBasicBlock = FFI.deleteBasicBlock . V.valueRef