codegen: correct argument handling
authorBernhard Urban <lewurm@gmail.com>
Sun, 22 Apr 2012 18:42:50 +0000 (20:42 +0200)
committerBernhard Urban <lewurm@gmail.com>
Sun, 22 Apr 2012 18:42:50 +0000 (20:42 +0200)
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
Mate/Utilities.hs
Mate/X86CodeGen.hs
tests/ArgumentPassing1.java [new file with mode: 0644]

index 69884dc212cc7bcbe9257279eacb308fbb2f92ce..f3b274d244f65fea73c43f1072fdd5a112e34d5e 100644 (file)
--- 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) $<
index ed92530ff70f1c36229dbb301474a95669c5ecf1..637d4d150c129cd81bbf28b12cc95e1f742d82a1 100644 (file)
@@ -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
index dea2a4b0eb8e2c6c5575e80da79b5be40b28014f..df251a67abc38ef3d06ec948b7f20638088ab521 100644 (file)
@@ -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 (file)
index 0000000..7867cfd
--- /dev/null
@@ -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;
+       }
+}