From b6548e83436936b5fce5384002e437aaf64c850e Mon Sep 17 00:00:00 2001 From: Bernhard Urban Date: Thu, 26 Apr 2012 14:26:27 +0200 Subject: [PATCH] codegen: implement `newarray' and `arraylength' the length is stored at offset 0. --- Mate/X86CodeGen.hs | 37 +++++++++++++++++++++++++++++++------ tests/Array1.java | 8 ++++++++ 2 files changed, 39 insertions(+), 6 deletions(-) create mode 100644 tests/Array1.java diff --git a/Mate/X86CodeGen.hs b/Mate/X86CodeGen.hs index 0e8d98e..c71494e 100644 --- a/Mate/X86CodeGen.hs +++ b/Mate/X86CodeGen.hs @@ -3,6 +3,7 @@ module Mate.X86CodeGen where import Data.Binary +import Data.BinaryState import Data.Int import Data.Maybe import qualified Data.Map as M @@ -233,16 +234,31 @@ emitFromBB method cls hmap = do call (trapaddr - w32_calladdr) add esp (4 :: Word32) emit DUP = push (Disp 0, esp) + emit ARRAYLENGTH = do + pop eax + push (Disp 0, eax) + emit (NEWARRAY typ) = do + let tsize = case decodeS (0 :: Integer) (B.pack [typ]) of + T_INT -> 4 + _ -> error $ "newarray: type not implemented yet" + -- get length from stack, but leave it there + mov eax (Disp 0, esp) + mov ebx (tsize :: Word32) + -- multiple amount with native size of one element + mul ebx -- result is in eax + add eax (4 :: Word32) -- for "length" entry + -- push amount of bytes to allocate + push eax + callMalloc + pop eax -- ref to arraymemory + pop ebx -- length + mov (Disp 0, eax) ebx -- store length at offset 0 + push eax -- push ref again emit (NEW objidx) = do let objname = buildClassID cls objidx amount <- liftIO $ getMethodSize objname push (amount :: Word32) - calladdr <- getCurrentOffset - let w32_calladdr = 5 + calladdr - let malloaddr = (fromIntegral getMallocAddr :: Word32) - call (malloaddr - w32_calladdr) - add esp (4 :: Word32) - push eax + callMalloc -- TODO(bernhard): save reference somewhere for GC -- set method table pointer mtable <- liftIO $ getMethodTable objname @@ -329,6 +345,15 @@ emitFromBB method cls hmap = do ret emit invalid = error $ "insn not implemented yet: " ++ (show invalid) + callMalloc :: CodeGen e s () + callMalloc = do + calladdr <- getCurrentOffset + let w32_calladdr = 5 + calladdr + let malloaddr = (fromIntegral getMallocAddr :: Word32) + call (malloaddr - w32_calladdr) + add esp (4 :: Word32) + push eax + -- for locals we use a different storage cArgs :: Word8 -> Word32 cArgs x = if (x' >= thisMethodArgCnt) diff --git a/tests/Array1.java b/tests/Array1.java new file mode 100644 index 0000000..87cd795 --- /dev/null +++ b/tests/Array1.java @@ -0,0 +1,8 @@ +package tests; + +public class Array1 { + public static void main(String []args) { + int []arr = new int[0x8]; + System.out.printf(arr.length); + } +} -- 2.25.1