module LLVM.Wrapper.Linker ( LinkerMode(..)
                           , linkModules ) where

import qualified LLVM.FFI.Linker as FFI
import LLVM.FFI.Linker (LinkerMode(..))
import qualified LLVM.FFI.Core as FFI
import LLVM.Wrapper.Core
import LLVM.Wrapper.Internal

import Foreign.C.String (peekCString)
import Foreign.Marshal.Alloc (alloca)
import Foreign.Marshal.Utils (toBool)
import Foreign.Storable (peek)
import Foreign.ForeignPtr.Safe (withForeignPtr)

import Data.IORef

linkModules :: Module -> Module -> LinkerMode -> IO (Maybe String)
linkModules (MkModule dest _) (MkModule src srcOurs) mode =
    withForeignPtr dest $ \dest' ->
    withForeignPtr src $ \src' ->
    alloca $ \msgPtr -> do
               result <- FFI.linkModules dest' src' (FFI.fromLinkerMode mode) msgPtr
               writeIORef srcOurs False
               msg <- peek msgPtr
               if not . toBool $ result
                 then return Nothing
                 else do str <- peekCString msg
                         FFI.disposeMessage msg
                         return (Just str)