packages feed

synthesizer-llvm-0.5: src/Synthesizer/LLVM/Debug/Storable.hs

{-# LANGUAGE Rank2Types #-}
module Synthesizer.LLVM.Debug.Storable where

import qualified Synthesizer.LLVM.Debug.Counter as Counter

import qualified Types.Data.Num as TypeNum
import qualified LLVM.Core as LLVM
import LLVM.Core (Array, ConstValue, constOf, )

import qualified System.IO as IO
import Numeric (showHex, )

import qualified Data.IORef as IORef
import qualified Data.List as List
import qualified Foreign.Marshal.Utils as Marshal
import Foreign.Marshal.Array (advancePtr, )
import Foreign.Storable (Storable, peek, peekByteOff, sizeOf, alignment, )
import Foreign.Ptr (Ptr, castPtr, )
import Data.Word (Word8, Word32, )
import qualified System.Unsafe as Unsafe

import qualified Control.Monad.Trans.Reader as R
import Control.Monad (when, )
import Data.Maybe (fromMaybe, )


data Dump = Dump

dumpCounter :: IORef.IORef (Counter.T Dump)
dumpCounter =
   Unsafe.performIO $ Counter.new

format :: Storable a => a -> IO String
format a =
   Marshal.with a $ \ptr ->
      fmap (concatMap (\byte ->
               (if byte<16 then ('0':) else id) (showHex byte ""))) $
      mapM peek
         (List.take (sizeOf a) $
          List.iterate (flip advancePtr 1) $
          (castPtr ptr :: Ptr Word8))

dump :: Storable a => FilePath -> a -> R.ReaderT (Counter.T Dump) IO ()
dump path a =
   R.ReaderT $ \cnt ->
   IO.withBinaryFile
      (path ++ Counter.format 3 cnt ++ ".dump")
      IO.WriteMode $ \h ->
   Marshal.with a $ \ptr ->
   IO.hPutBuf h ptr (sizeOf a)


type ArrayElem = Word32

{-
Unfortunately, you cannot 'alloca' or 'malloc' the constructed array,
because an IsSized instance is missing.
We may employ a specialised reifyIntegral for this purpose.
-}
withConstArray ::
   Storable a =>
   a ->
   (forall n. TypeNum.NaturalT n => ConstValue (Array n ArrayElem) -> b) ->
   IO b
withConstArray a f =
   Marshal.with a $ \ptr -> do
      content <-
         mapM
            (peekByteOff ptr)
            (takeWhile (< sizeOf a) [0,(sizeOf (undefined :: ArrayElem))..])
          :: IO [ArrayElem]
      return $
         fromMaybe (error "Debug.Storable.withConstArray: length must always be non-negative") $
         TypeNum.reifyNaturalD (fromIntegral (length content))
            (\n ->
               let makeArray ::
                      TypeNum.NaturalT n =>
                      n -> [ConstValue ArrayElem] ->
                      ConstValue (Array n ArrayElem)
                   makeArray _ = LLVM.constArray
               in  f (makeArray n (map constOf content)))


traceMalloc :: Storable a => a -> Int -> Ptr a -> IO (Ptr a)
traceMalloc a size ptr = do
   when False $ putStrLn $
      showString "%addr" . shows ptr .
      showString " = call float* @malloc(i8* getelementptr (i8* null, i32 " .
      shows size .
      showString "))   ; alignment " . shows (alignment a) $
      ""
   return ptr