@@ -24,21 +24,25 @@ import GHC.Generics (Generic)
24
24
import System.Random (randomIO )
25
25
#ifdef FFI
26
26
import Ffi
27
- import Foreign.LibFFI.Base (newStorableStructArgRet , newStructCType )
27
+ import Foreign.LibFFI.Base (newStorableStructArgRet , newStructCType , sizeAndAlignmentOfCType )
28
28
import Foreign.LibFFI.FFITypes
29
29
import Foreign.LibFFI
30
30
#endif
31
31
32
+ import Control.Monad.Reader
32
33
import Data.Binary qualified (get , put )
33
34
import Data.Char (chr , ord )
35
+ import Data.IORef (IORef )
34
36
import Data.Text.Internal.Unsafe.Char
35
37
import Foreign.C (CDouble , newCString )
36
38
import Foreign.C.String (castCharToCChar )
37
- import Foreign.C.Types (CChar , CFloat , CInt )
39
+ import Foreign.C.Types (CChar , CFloat , CInt , CSChar , CUChar )
40
+ import Foreign.LibFFI.Internal (CType )
38
41
import Foreign.Marshal.Array
39
42
import Foreign.Ptr
40
43
import Foreign.Storable
41
44
import GHC.IO (unsafePerformIO )
45
+ import GHC.IORef
42
46
import GHC.Int qualified as Ghc.Int
43
47
44
48
data Instruction
@@ -298,9 +302,11 @@ showDebugInfo = do
298
302
vm <- get
299
303
-- Show the current instruction, two values from the stack, and the result
300
304
let inst = program vm V. ! pc vm
301
- let stack' = stack vm
302
- let stack'' = if length stack' > 1 then take 2 stack' else stack'
303
- return $ show (pc vm) ++ " \t " ++ show inst ++ " \t " ++ show stack'' ++ " \t " ++ show (safeHead $ callStack vm)
305
+ -- let stack' = stack vm
306
+ -- let stack'' = if length stack' > 1 then take 2 stack' else stack'
307
+ -- return $ show (pc vm) ++ "\t" ++ show inst ++ "\t" ++ show stack'' ++ "\t" ++ show (safeHead $ callStack vm)
308
+ let layers = length (callStack vm) - 1
309
+ return $ replicate layers ' ' ++ show (pc vm) ++ " " ++ show inst -- ++ " (" ++ show (stack vm) ++ ")"
304
310
305
311
run' :: Program -> StateT VM IO ()
306
312
run' program = do
@@ -450,27 +456,56 @@ instance IntoData (Ptr ()) where
450
456
clearMap :: Data. Map String Data -> Data. Map String Data
451
457
clearMap = Data.Map. delete " __name" . Data.Map. delete " __traits"
452
458
459
+
460
+ globalStructType :: IORef [Ptr CType ]
461
+ {-# NOINLINE globalStructType #-}
462
+ globalStructType = unsafePerformIO $ newIORef []
463
+
453
464
-- Only used for structs. I really don't like this
454
465
instance Storable Data where
455
466
sizeOf _ = 4
456
467
alignment _ = 4
457
- peek _ = error " peek"
468
+ peek ptr = do
469
+ types <- readIORef globalStructType
470
+ sizesAndAlignments <- mapM sizeAndAlignmentOfCType types
471
+ let typesAndOffsets = zip types (scanl (\ (o,_) (s,a) -> (o+ s,a)) (0 ,0 ) sizesAndAlignments)
472
+ b <- mapM mapData typesAndOffsets
473
+ return $ DList b
474
+ where
475
+ mapData :: (Ptr CType , (Int , Int )) -> IO Data
476
+ mapData tsa = do
477
+ let (t,(o,_)) = tsa
478
+ case () of _
479
+ | t == ffi_type_float -> do
480
+ return $ DFloat (realToFrac (unsafePerformIO $ peekByteOff ptr o :: CFloat ))
481
+ | t == ffi_type_sint32 -> do
482
+ return $ DInt (fromIntegral (unsafePerformIO $ peekByteOff ptr o :: CInt ))
483
+ | t == ffi_type_double -> do
484
+ return $ DDouble (realToFrac (unsafePerformIO $ peekByteOff ptr o :: CDouble ))
485
+ | t == ffi_type_pointer -> do
486
+ return $ DCPtr (unsafePerformIO $ peekByteOff ptr o :: WordPtr )
487
+ | t == ffi_type_uchar -> do
488
+ return $ DChar (toEnum (fromEnum (unsafePerformIO $ peekByteOff ptr o :: CUChar )))
489
+ | t == ffi_type_void -> do
490
+ return DNone
491
+ | otherwise -> error $ " mapData: Invalid type " ++ show t
492
+
493
+
458
494
poke ptr (DInt x) = poke (castPtr ptr) x
459
495
poke ptr (DFloat x) = poke (castPtr ptr) x
460
496
poke ptr (DString x) = poke (castPtr ptr) (unsafePerformIO $ newCString x)
461
497
poke ptr (DChar x) = poke (castPtr ptr) x
462
498
poke ptr (DMap x) = do
463
499
let values = reverse $ Data.Map. elems (clearMap x)
464
- let sizes = map sizeOf' values
500
+ let sizes = map sizeOfC values
465
501
mapM_ (\ (i, v) -> pokeByteOff ptr (sum $ take i sizes) v) (zip [0 .. ] values)
466
- where
467
- -- Normal sizeof crashes and I don't know why
468
- sizeOf' :: Data -> Int
469
- sizeOf' (DChar _) = 1
470
- sizeOf' (DDouble _) = 8
471
- sizeOf' _ = 4
472
502
poke _ x = error $ " unsupported poke " ++ show x
473
503
504
+ sizeOfC :: Data -> Int
505
+ sizeOfC (DChar _) = 1
506
+ sizeOfC (DDouble _) = 8
507
+ sizeOfC _ = 4
508
+
474
509
dataCType (DInt _) = ffi_type_sint32
475
510
dataCType (DFloat _) = ffi_type_float
476
511
dataCType (DString _) = ffi_type_pointer
@@ -579,6 +614,14 @@ runInstruction (CallFFI name from numArgs) = do
579
614
let retType = ret retT :: RetType ()
580
615
_ <- liftIO $ callFFI fun retType ffiArgs'
581
616
return ()
617
+ DMap x -> do
618
+ let keys = reverse (Data.Map. keys (clearMap x))
619
+ let types = map dataCType (Data.Map. elems (clearMap x))
620
+ liftIO $ writeIORef globalStructType types
621
+ (_,retType,_) <- liftIO (newStorableStructArgRet types :: IO (Data -> Arg , RetType Data , IO () ))
622
+ (DList values) <- liftIO $ callFFI fun retType ffiArgs'
623
+ let result = DMap $ Data.Map. fromList $ zip keys values
624
+ stackPushA result
582
625
_ -> error $ " Invalid return type: " ++ show retT
583
626
liftIO $ mapM_ (\ case Just x -> x; Nothing -> return () ) frees
584
627
#else
0 commit comments