1 {-# LANGUAGE OverloadedStrings #-}
2 {-# LANGUAGE ForeignFunctionInterface #-}
3 module Mate.MethodPool where
6 import qualified Data.Map as M
7 import qualified Data.ByteString.Lazy as B
12 import Foreign.C.Types
13 import Foreign.StablePtr
18 import Harpy.X86Disassembler
20 import Mate.BasicBlocks
22 import Mate.X86CodeGen
25 foreign import ccall "get_mmap"
26 get_mmap :: IO (Ptr ())
28 foreign import ccall "set_mmap"
29 set_mmap :: Ptr () -> IO ()
31 foreign export ccall getMethodEntry :: CUInt -> Ptr () -> Ptr () -> IO CUInt
32 getMethodEntry :: CUInt -> Ptr () -> Ptr () -> IO CUInt
33 getMethodEntry signal_from ptr_mmap ptr_cmap = do
34 mmap <- ptr2mmap ptr_mmap
35 cmap <- ptr2cmap ptr_cmap
37 let w32_from = fromIntegral signal_from
38 let mi@(MethodInfo method cm _) = cmap M.! w32_from
39 -- TODO(bernhard): replace parsing with some kind of classpool
40 cls <- parseClassFile $ toString $ cm `B.append` ".class"
41 case M.lookup mi mmap of
43 printf "getMethodEntry(from 0x%08x): no method \"%s\" found. compile it\n" w32_from (show mi)
44 hmap <- parseMethod cls method
48 entry <- compileBB hmap' mi
49 return $ fromIntegral $ ((fromIntegral $ ptrToIntPtr entry) :: Word32)
50 Nothing -> error $ (show method) ++ " not found. abort"
51 Just w32 -> return (fromIntegral w32)
55 -- (entry, _) <- testCase "./tests/Fib.class" "fib"
56 -- let int_entry = ((fromIntegral $ ptrToIntPtr entry) :: Word32)
57 -- let mmap = M.insert ("fib" :: String) int_entry M.empty
58 -- mapM_ (\(x,y) -> printf "%s at 0x%08x\n" x y) $ M.toList mmap
59 -- mmap2ptr mmap >>= set_mmap
60 -- demo_mmap -- access Data.Map from C
62 initMethodPool :: IO ()
64 mmap2ptr M.empty >>= set_mmap
65 cmap2ptr M.empty >>= set_cmap
67 compileBB :: MapBB -> MethodInfo -> IO (Ptr Word8)
68 compileBB hmap methodinfo = do
69 mmap <- get_mmap >>= ptr2mmap
70 cmap <- get_cmap >>= ptr2cmap
72 -- TODO(bernhard): replace parsing with some kind of classpool
73 cls <- parseClassFile $ toString $ (cName methodinfo) `B.append` ".class"
74 let ebb = emitFromBB cls hmap
75 (_, Right ((entry, _, _, new_cmap), disasm)) <- runCodeGen ebb () ()
76 let w32_entry = ((fromIntegral $ ptrToIntPtr entry) :: Word32)
78 let mmap' = M.insert methodinfo w32_entry mmap
79 let cmap' = M.union cmap new_cmap -- prefers elements in cmap
80 mmap2ptr mmap' >>= set_mmap
81 cmap2ptr cmap' >>= set_cmap
84 mapM_ (putStrLn . showAtt) disasm
85 -- UNCOMMENT NEXT LINE FOR GDB FUN
87 -- (1) start it with `gdb ./mate' and then `run <classfile>'
88 -- (2) on getLine, press ctrl+c
89 -- (3) `br *0x<addr>'; obtain the address from the disasm above
90 -- (4) `cont' and press enter
94 foreign import ccall "dynamic"
95 code_void :: FunPtr (IO ()) -> (IO ())
97 executeFuncPtr :: Ptr Word8 -> IO ()
98 executeFuncPtr entry = code_void $ ((castPtrToFunPtr entry) :: FunPtr (IO ()))
100 -- TODO(bernhard): make some typeclass magic 'n stuff
101 mmap2ptr :: MMap -> IO (Ptr ())
103 ptr_mmap <- newStablePtr mmap
104 return $ castStablePtrToPtr ptr_mmap
106 ptr2mmap :: Ptr () -> IO MMap
107 ptr2mmap vmap = deRefStablePtr $ ((castPtrToStablePtr vmap) :: StablePtr MMap)
109 cmap2ptr :: CMap -> IO (Ptr ())
111 ptr_cmap <- newStablePtr cmap
112 return $ castStablePtrToPtr ptr_cmap
114 ptr2cmap :: Ptr () -> IO CMap
115 ptr2cmap vmap = deRefStablePtr $ ((castPtrToStablePtr vmap) :: StablePtr cmap)