import Data.Maybe
import qualified Data.Map as M
import qualified Data.ByteString.Lazy as B
+import Control.Monad
import Foreign
import Foreign.C.Types
import Harpy.X86Disassembler
import Mate.BasicBlocks
+import Mate.Types
import Mate.Utilities
+import Mate.ClassPool
foreign import ccall "dynamic"
code_int :: FunPtr (CInt -> CInt -> IO CInt) -> (CInt -> CInt -> IO CInt)
foreign import ccall "register_signal"
register_signal :: IO ()
-foreign import ccall "get_cmap"
- get_cmap :: IO (Ptr ())
-
-foreign import ccall "set_cmap"
- set_cmap :: Ptr () -> IO ()
-
test_01, test_02, test_03 :: IO ()
test_01 = do
register_signal
- (entry, end) <- testCase "./tests/Fib.class" "fib"
+ (entry, end) <- testCase "./tests/Fib" "fib"
let entryFuncPtr = ((castPtrToFunPtr entry) :: FunPtr (CInt -> CInt -> IO CInt))
mapM_ (\x -> do
test_02 = do
- (entry,_) <- testCase "./tests/While.class" "f"
+ (entry,_) <- testCase "./tests/While" "f"
let entryFuncPtr = ((castPtrToFunPtr entry) :: FunPtr (CInt -> CInt -> IO CInt))
result <- code_int entryFuncPtr 5 4
let iresult :: Int; iresult = fromIntegral result
test_03 = do
- (entry,_) <- testCase "./tests/While.class" "g"
+ (entry,_) <- testCase "./tests/While" "g"
let entryFuncPtr = ((castPtrToFunPtr entry) :: FunPtr (CInt -> CInt -> IO CInt))
result <- code_int entryFuncPtr 5 4
let iresult :: Int; iresult = fromIntegral result
printf "result of g(4,3): %3d\t\t%s\n" iresult2 kk2
-testCase :: String -> B.ByteString -> IO (Ptr Word8, Int)
+testCase :: B.ByteString -> B.ByteString -> IO (Ptr Word8, Int)
testCase cf method = do
- cls <- parseClassFile cf
+ cls <- getClassFile cf
hmap <- parseMethod cls method
printMapBB hmap
case hmap of
type CompileInfo = (EntryPoint, BBStarts, Int, CMap)
--- B.ByteString: encoded name: <Class>.<methodname><signature>
--- Class Resolved: classfile
--- Word16: index of invoke-instruction
-type MethodInfo = (B.ByteString, Class Resolved, Word16)
-
--- Word32 = point of method call in generated code
--- MethodInfo = relevant information about callee
-type CMap = M.Map Word32 MethodInfo
-
emitFromBB :: Class Resolved -> MapBB -> CodeGen e s (CompileInfo, [Instruction])
emitFromBB cls hmap = do
let calls' = calls `M.union` (M.fromList $ catMaybes cs)
case successor bb of
Return -> return (calls', bbstarts')
+ FallThrough t -> do
+ efBB (t, hmap M.! t) calls' bbstarts' lmap
OneTarget t -> do
efBB (t, hmap M.! t) calls' bbstarts' lmap
TwoTarget t1 t2 -> do
let l = buildMethodID cls cpidx
calladdr <- getCodeOffset
let w32_calladdr = w32_ep + (fromIntegral calladdr) :: Word32
- newNamedLabel (toString l) >>= defineLabel
- -- TODO(bernhard): better try SIGILL instead of SIGSEGV?
- mov (Addr 0) eax
- -- discard arguments (TODO(bernhard): don't hardcode it)
- add esp (4 :: Word32)
- -- push result on stack (TODO(bernhard): if any)
- push eax
- return $ Just $ (w32_calladdr, (l, cls, cpidx))
+ newNamedLabel (show l) >>= defineLabel
+ -- causes SIGILL. in the signal handler we patch it to the acutal call.
+ -- place a nop at the end, therefore the disasm doesn't screw up
+ emit32 (0xffff9090 :: Word32) >> emit8 (0x90 :: Word8)
+ -- discard arguments on stack
+ let argcnt = (methodGetArgsCount cls cpidx) * 4
+ when (argcnt > 0) (add esp argcnt)
+ -- push result on stack if method has a return value
+ when (methodHaveReturnValue cls cpidx) (push eax)
+ return $ Just $ (w32_calladdr, l)
emit' insn = emit insn >> return Nothing
emit :: J.Instruction -> CodeGen e s ()
call (trapaddr - w32_calladdr)
add esp (4 :: Word32)
emit (BIPUSH val) = push ((fromIntegral val) :: Word32)
+ emit (SIPUSH val) = push ((fromIntegral $ ((fromIntegral val) :: Int16)) :: Word32)
emit (ICONST_0) = push (0 :: Word32)
emit (ICONST_1) = push (1 :: Word32)
emit (ICONST_2) = push (2 :: Word32)
+ emit (ICONST_4) = push (4 :: Word32)
emit (ICONST_5) = push (5 :: Word32)
emit (ILOAD_ x) = do
push (Disp (cArgs_ x), ebp)
mov esp ebp
pop ebp
ret
- emit _ = do cmovbe eax eax -- dummy
+ emit invalid = error $ "insn not implemented yet: " ++ (show invalid)
cArgs x = (8 + 4 * (fromIntegral x))
cArgs_ x = (8 + 4 * case x of I0 -> 0; I1 -> 1; I2 -> 2; I3 -> 3)