From f0b4e78c77e6503703fd7ace19e203ce06718397 Mon Sep 17 00:00:00 2001 From: Bernhard Urban Date: Sun, 22 Apr 2012 20:42:50 +0200 Subject: [PATCH] codegen: correct argument handling after a call, we have to decrement the stack pointer again, according how many arguments that method has. also, we have to push the result in %eax only when there's a result (i.e. /= void) --- Makefile | 9 +++++++-- Mate/Utilities.hs | 16 ++++++++++++++++ Mate/X86CodeGen.hs | 12 ++++++++---- tests/ArgumentPassing1.java | 21 +++++++++++++++++++++ 4 files changed, 52 insertions(+), 6 deletions(-) create mode 100644 tests/ArgumentPassing1.java diff --git a/Makefile b/Makefile index 69884dc..f3b274d 100644 --- a/Makefile +++ b/Makefile @@ -17,8 +17,13 @@ GHC_LD := -optl-Xlinker -optl-x all: mate $(CLASS_FILES) test: mate $(CLASS_FILES) - ./$< tests/Fib.class - ./$< tests/Fac.class + ./$< tests/Fib.class | grep mainresult + @printf "should be: 0x%08x\n" 0x09de8d6d + ./$< tests/Fac.class | grep mainresult + @printf "should be: 0x%08x\n" 0x58980 + ./$< tests/ArgumentPassing1.class | grep mainresult + @printf "should be: 0x%08x\n" 0x92 + @printf "should be: 0x%08x\n" $$(((0 - 0x1337) & 0xffffffff)) %.class: %.java $(JAVAC) $< diff --git a/Mate/Utilities.hs b/Mate/Utilities.hs index ed92530..637d4d1 100644 --- a/Mate/Utilities.hs +++ b/Mate/Utilities.hs @@ -32,3 +32,19 @@ buildMethodID cls idx = (rc `B.append` dot) `B.append` (ntName nt) `B.append` nt dot :: B.ByteString -- TODO(bernhard): WTF? why -XOverloadedStrings doesn't apply here? dot = B.pack $ map (fromIntegral . ord) "." + +methodGetArgsCount :: Class Resolved -> Word16 -> Word32 +methodGetArgsCount cls idx = fromIntegral $ length args + where + (CMethod _ nt) = (constsPool cls) M.! idx + (MethodSignature args _) = ntSignature nt + +-- TODO(bernhard): Extend it to more than just int, and provide typeinformation +methodHaveReturnValue :: Class Resolved -> Word16 -> Bool +methodHaveReturnValue cls idx = case ret of + ReturnsVoid -> False; + (Returns IntType) -> True; + _ -> error "methodHaveReturnValue: todo" + where + (CMethod _ nt) = (constsPool cls) M.! idx + (MethodSignature _ ret) = ntSignature nt diff --git a/Mate/X86CodeGen.hs b/Mate/X86CodeGen.hs index dea2a4b..df251a6 100644 --- a/Mate/X86CodeGen.hs +++ b/Mate/X86CodeGen.hs @@ -7,6 +7,7 @@ import Data.Int 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 @@ -179,10 +180,11 @@ emitFromBB cls hmap = do -- 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 (0xffffffff :: Word32) >> emit8 (0x90 :: Word8) - -- discard arguments (TODO(bernhard): don't hardcode it) - add esp (4 :: Word32) - -- push result on stack (TODO(bernhard): if any) - push eax + -- 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, cls, cpidx)) emit' insn = emit insn >> return Nothing @@ -197,9 +199,11 @@ emitFromBB cls hmap = do 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) diff --git a/tests/ArgumentPassing1.java b/tests/ArgumentPassing1.java new file mode 100644 index 0000000..7867cfd --- /dev/null +++ b/tests/ArgumentPassing1.java @@ -0,0 +1,21 @@ +package tests; + +public class ArgumentPassing1 { + public static void main(String []args) { + myadder(23, 4, 0x77); // 0x92 + noreturn(23, 4, 0x77); // nothing + noargs(); // 0x1337 + } + + public static int myadder(int a, int b, int c) { + return a + b + c; + } + + public static void noreturn(int a, int b, int c) { + return; + } + + public static int noargs() { + return -0x1337; + } +} -- 2.25.1