1 {-# LANGUAGE OverloadedStrings #-}
2 {-# LANGUAGE ForeignFunctionInterface #-}
3 module Mate.MethodPool where
6 import Data.String.Utils
7 import qualified Data.Map as M
8 import qualified Data.Set as S
9 import qualified Data.ByteString.Lazy as B
15 import Foreign.C.Types
16 import Foreign.C.String
17 import Foreign.StablePtr
23 import Harpy.X86Disassembler
25 import Mate.BasicBlocks
27 import Mate.X86CodeGen
32 foreign import ccall "dynamic"
33 code_void :: FunPtr (IO ()) -> (IO ())
36 foreign export ccall getMethodEntry :: CUInt -> Ptr () -> Ptr () -> IO CUInt
37 getMethodEntry :: CUInt -> Ptr () -> Ptr () -> IO CUInt
38 getMethodEntry signal_from ptr_mmap ptr_tmap = do
39 mmap <- ptr2mmap ptr_mmap
40 tmap <- ptr2tmap ptr_tmap
42 let w32_from = fromIntegral signal_from
43 let mi = tmap M.! w32_from
45 (MI mi'@(MethodInfo method cm sig)) -> do
46 case M.lookup mi' mmap of
48 cls <- getClassFile cm
49 printf "getMethodEntry(from 0x%08x): no method \"%s\" found. compile it\n" w32_from (show mi')
50 let mm = lookupMethod method cls
53 let flags = methodAccessFlags mm'
54 case S.member ACC_NATIVE flags of
56 hmap <- parseMethod cls method
60 entry <- compileBB hmap' mi'
61 return $ fromIntegral $ ((fromIntegral $ ptrToIntPtr entry) :: Word32)
62 Nothing -> error $ (show method) ++ " not found. abort"
64 let symbol = (replace "/" "_" $ toString cm) ++ "__" ++ (toString method) ++ "__" ++ (replace "(" "_" (replace ")" "_" $ toString $ encode sig))
65 printf "native-call: symbol: %s\n" symbol
66 nf <- loadNativeFunction symbol
67 let w32_nf = fromIntegral nf
68 let mmap' = M.insert mi' w32_nf mmap
69 mmap2ptr mmap' >>= set_methodmap
71 Nothing -> error $ (show method) ++ " not found. abort"
72 Just w32 -> return (fromIntegral w32)
73 _ -> error $ "getMethodEntry: no trapInfo. abort"
75 -- TODO(bernhard): UBERHAX. ghc patch?
76 foreign import ccall safe "lookupSymbol"
77 c_lookupSymbol :: CString -> IO (Ptr a)
79 loadNativeFunction :: String -> IO (CUInt)
80 loadNativeFunction sym = do
81 _ <- loadRawObject "ffi/native.o"
82 -- TODO(bernhard): WTF
83 resolveObjs (return ())
84 ptr <- withCString sym c_lookupSymbol
86 then error $ "dyn. loading of \"" ++ sym ++ "\" failed."
87 else return $ fromIntegral $ minusPtr ptr nullPtr
91 -- (entry, _) <- testCase "./tests/Fib.class" "fib"
92 -- let int_entry = ((fromIntegral $ ptrToIntPtr entry) :: Word32)
93 -- let mmap = M.insert ("fib" :: String) int_entry M.empty
94 -- mapM_ (\(x,y) -> printf "%s at 0x%08x\n" x y) $ M.toList mmap
95 -- mmap2ptr mmap >>= set_mmap
96 -- demo_mmap -- access Data.Map from C
98 initMethodPool :: IO ()
100 mmap2ptr M.empty >>= set_methodmap
101 tmap2ptr M.empty >>= set_trapmap
102 classmap2ptr M.empty >>= set_classmap
104 compileBB :: MapBB -> MethodInfo -> IO (Ptr Word8)
105 compileBB hmap methodinfo = do
106 mmap <- get_methodmap >>= ptr2mmap
107 tmap <- get_trapmap >>= ptr2tmap
109 -- TODO(bernhard): replace parsing with some kind of classpool
110 cls <- getClassFile (cName methodinfo)
111 let ebb = emitFromBB cls hmap
112 (_, Right ((entry, _, _, new_tmap), disasm)) <- runCodeGen ebb () ()
113 let w32_entry = ((fromIntegral $ ptrToIntPtr entry) :: Word32)
115 let mmap' = M.insert methodinfo w32_entry mmap
116 let tmap' = M.union tmap new_tmap -- prefers elements in cmap
117 mmap2ptr mmap' >>= set_methodmap
118 tmap2ptr tmap' >>= set_trapmap
121 mapM_ (putStrLn . showAtt) disasm
122 -- UNCOMMENT NEXT LINE FOR GDB FUN
124 -- (1) start it with `gdb ./mate' and then `run <classfile>'
125 -- (2) on getLine, press ctrl+c
126 -- (3) `br *0x<addr>'; obtain the address from the disasm above
127 -- (4) `cont' and press enter
131 executeFuncPtr :: Ptr Word8 -> IO ()
132 executeFuncPtr entry = code_void $ ((castPtrToFunPtr entry) :: FunPtr (IO ()))