packages feed

accelerate-llvm-native-1.4.0.0: src/Data/Array/Accelerate/LLVM/Native/Link/Cache.hs

{-# LANGUAGE CPP #-}
-- |
-- Module      : Data.Array.Accelerate.LLVM.Native.Link.Cache
-- Copyright   : [2017..2020] The Accelerate Team
-- License     : BSD3
--
-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com>
-- Stability   : experimental
-- Portability : non-portable (GHC extensions)
--

module Data.Array.Accelerate.LLVM.Native.Link.Cache (

  LinkCache,
  new, LC.dlsym,

) where

import Data.Array.Accelerate.Debug.Internal                         ( tracyIsEnabled )

import Data.Array.Accelerate.LLVM.Native.Link.Object
import qualified Data.Array.Accelerate.LLVM.Link.Cache              as LC

import Control.Monad

#if defined(mingw32_HOST_OS)
import System.Win32.DLL
#else
import System.Posix.DynamicLinker
#endif

type LinkCache = LC.LinkCache FunctionTable ObjectCode

new :: IO LinkCache
new = do
  -- For whatever reason ghci isn't adding library dependencies to the
  -- dynamic link state, which means that dynamic linking will fail in
  -- tracy mode because we depend on tracy symbols exported by the
  -- accelerate library. This brings those symbols into scope so that they
  -- can be found by later calls to dlsym().
  --
  -- Additionally, the Accelerate library has been compiled with -rdynamic
  -- in order to bring all exported symbols into the global symbol table.
  -- This seems to be required so that dlsym() can find symbols from the
  -- GHC RTS when we are in compiled (not interpreted) mode. In non-ghci
  -- mode, loading the RTS dynamic library explicitly (as we do with the
  -- Accelerate library) causes segfaults; possibly because the RTS was
  -- otherwise linked statically into the executable.
  --
  -- Because the accelerate library lives somewhere in ~/.cabal/..., this
  -- hack prevents executables from running on any other machine than the
  -- one they were built on. Fortunately, this happens only in tracy mode.
  --
  when tracyIsEnabled $ void $
#if defined(mingw32_HOST_OS)
    loadLibrary ACCELERATE_DYLD_LIBRARY_PATH
#else
    dlopen ACCELERATE_DYLD_LIBRARY_PATH [RTLD_LAZY, RTLD_GLOBAL]
#endif
  LC.new