module LLVM.Internal.Linking
  ( loadLibraryPermanently
  , getSymbolAddressInProcess
  )where

import LLVM.Prelude

import Foreign.C.String
import Foreign.Ptr
import LLVM.Internal.Coding
import LLVM.Internal.OrcJIT
import qualified LLVM.Internal.FFI.OrcJIT as FFI
import qualified LLVM.Internal.FFI.DynamicLibrary as DL
import qualified LLVM.Internal.FFI.RTDyldMemoryManager as Dyld

-- | Get the address of the given symbol in
--   the current process' address space.
getSymbolAddressInProcess
  :: MangledSymbol -> IO WordPtr
getSymbolAddressInProcess :: MangledSymbol -> IO WordPtr
getSymbolAddressInProcess (MangledSymbol Ptr SymbolStringPtr
sym) = do
  CString
symStr <- Ptr SymbolStringPtr -> IO CString
FFI.mangledSymbolString Ptr SymbolStringPtr
sym
  Word64 -> WordPtr
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word64 -> WordPtr) -> IO Word64 -> IO WordPtr
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> CString -> IO Word64
Dyld.getSymbolAddressInProcess CString
symStr

-- | Loads the given dynamic library permanently. If 'Nothing'
--   is given, this will make the symbols from the current
--   process available.
loadLibraryPermanently
  :: Maybe FilePath
  -> IO Bool
loadLibraryPermanently :: Maybe FilePath -> IO Bool
loadLibraryPermanently (Just FilePath
fp) = LLVMBool -> IO Bool
forall (d :: * -> *) h c. (DecodeM d h c, HasCallStack) => c -> d h
decodeM (LLVMBool -> IO Bool) -> IO LLVMBool -> IO Bool
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< FilePath -> (CString -> IO LLVMBool) -> IO LLVMBool
forall a. FilePath -> (CString -> IO a) -> IO a
withCString FilePath
fp CString -> IO LLVMBool
DL.loadLibraryPermanently
loadLibraryPermanently Maybe FilePath
Nothing = LLVMBool -> IO Bool
forall (d :: * -> *) h c. (DecodeM d h c, HasCallStack) => c -> d h
decodeM (LLVMBool -> IO Bool) -> IO LLVMBool -> IO Bool
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< CString -> IO LLVMBool
DL.loadLibraryPermanently CString
forall a. Ptr a
nullPtr