From: Bernhard Urban Date: Mon, 23 Apr 2012 23:17:12 +0000 (+0200) Subject: codegen: fix bug in calling conv X-Git-Url: http://wien.tomnetworks.com/gitweb/?p=mate.git;a=commitdiff_plain;h=01ca2a0efa092664d7dd83fb8ac03d4ed550531d codegen: fix bug in calling conv the callee used elements of the callers stack as storage for local vars. don't do that. --- diff --git a/Makefile b/Makefile index fb4b5bc..9e1a9b4 100644 --- a/Makefile +++ b/Makefile @@ -33,6 +33,10 @@ test: mate $(CLASS_FILES) @printf "should be: 0x%08x\n" 0x55 ./$< tests/Static3 | grep mainresult @printf "should be: 0x%08x\n" 0x6dd + ./$< tests/CallConv1 | grep mainresult + @printf "should be: 0x%08x\n" 0x1337 + ./$< tests/CallConv2 | grep mainresult + @printf "should be: 0x%08x\n" 0x1337 %.class: %.java $(JAVAC) $< diff --git a/Mate/MethodPool.hs b/Mate/MethodPool.hs index aff4dfe..c76cf91 100644 --- a/Mate/MethodPool.hs +++ b/Mate/MethodPool.hs @@ -105,7 +105,7 @@ compileBB hmap methodinfo = do -- TODO(bernhard): replace parsing with some kind of classpool cls <- getClassFile (cName methodinfo) - let ebb = emitFromBB cls hmap + let ebb = emitFromBB (methName methodinfo) cls hmap (_, Right ((entry, _, _, new_tmap), disasm)) <- runCodeGen ebb () () let w32_entry = ((fromIntegral $ ptrToIntPtr entry) :: Word32) diff --git a/Mate/X86CodeGen.hs b/Mate/X86CodeGen.hs index ac51092..5720084 100644 --- a/Mate/X86CodeGen.hs +++ b/Mate/X86CodeGen.hs @@ -96,7 +96,7 @@ testCase cf method = do case hmap of Nothing -> error "sorry, no code generation" Just hmap' -> do - let ebb = emitFromBB cls hmap' + let ebb = emitFromBB method cls hmap' (_, Right ((entry, bbstarts, end, _), disasm)) <- runCodeGen ebb () () let int_entry = ((fromIntegral $ ptrToIntPtr entry) :: Int) printf "disasm:\n" @@ -115,13 +115,16 @@ type BBStarts = M.Map BlockID Int type CompileInfo = (EntryPoint, BBStarts, Int, TMap) -emitFromBB :: Class Resolved -> MapBB -> CodeGen e s (CompileInfo, [Instruction]) -emitFromBB cls hmap = do +emitFromBB :: B.ByteString -> Class Resolved -> MapBB -> CodeGen e s (CompileInfo, [Instruction]) +emitFromBB method cls hmap = do llmap <- sequence [newNamedLabel ("bb_" ++ show x) | (x,_) <- M.toList hmap] let lmap = zip (Prelude.fst $ unzip $ M.toList hmap) llmap ep <- getEntryPoint push ebp mov ebp esp + -- TODO(bernhard): determine a reasonable value. + -- e.g. (locals used) * 4 + sub esp (0x60 :: Word32) (calls, bbstarts) <- efBB (0,(hmap M.! 0)) M.empty M.empty lmap d <- disassemble @@ -205,9 +208,14 @@ emitFromBB cls hmap = do emit (ICONST_5) = push (5 :: Word32) emit (ILOAD_ x) = do push (Disp (cArgs_ x), ebp) + emit (ILOAD x) = do + push (Disp (cArgs x), ebp) emit (ISTORE_ x) = do pop eax mov (Disp (cArgs_ x), ebp) eax + emit (ISTORE x) = do + pop eax + mov (Disp (cArgs x), ebp) eax emit IADD = do pop ebx; pop eax; add eax ebx; push eax emit ISUB = do pop ebx; pop eax; sub eax ebx; push eax emit IMUL = do pop ebx; pop eax; mul ebx; push eax @@ -247,8 +255,22 @@ emitFromBB cls hmap = do ret 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) + -- for locals we use a different storage + cArgs :: Word8 -> Word32 + cArgs x = if (x' >= thisMethodArgCnt) + -- TODO(bernhard): maybe s/(-4)/(-8)/ + then fromIntegral $ (-4) * (x' - thisMethodArgCnt + 1) + else 8 + (4 * x') + where x' = fromIntegral x + + cArgs_ :: IMM -> Word32 + cArgs_ x = cArgs $ case x of I0 -> 0; I1 -> 1; I2 -> 2; I3 -> 3 + + thisMethodArgCnt :: Word32 + thisMethodArgCnt = fromIntegral $ length args + where + (Just m) = lookupMethod method cls + (MethodSignature args _) = methodSignature m -- sign extension from w8 to w32 (over s8) -- unfortunately, hs-java is using Word8 everywhere (while diff --git a/tests/CallConv1.java b/tests/CallConv1.java new file mode 100644 index 0000000..acb6a56 --- /dev/null +++ b/tests/CallConv1.java @@ -0,0 +1,21 @@ +package tests; + +public class CallConv1 { + public static void main(String []args) { + int sum = 0; + sum += manyVars(0x1348); + id(sum); // 0x1337 + } + + public static int id(int a) { + return a; + } + + public static int manyVars(int a) { + int b = 0x22; + int c = 0x33; + int d = 0x44; + + return (((a - b) - c) + d); + } +} diff --git a/tests/CallConv2.java b/tests/CallConv2.java new file mode 100644 index 0000000..ef8e3f8 --- /dev/null +++ b/tests/CallConv2.java @@ -0,0 +1,20 @@ +package tests; + +public class CallConv2 { + public static void main(String []args) { + int sum = 0; + sum += manyVars(0x125A, 0x11, 0x33, 0x44); + id(sum); // 0x1337 + } + + public static int id(int a) { + return a; + } + + public static int manyVars(int a, int b, int c, int d) { + int x = 0x88; + int y = 0x55; + + return ((((a - b) - c) + d) + x + y); + } +}