From 8b5650dd6104d1e350128fdcee37502d65824370 Mon Sep 17 00:00:00 2001 From: mrab Date: Tue, 7 May 2024 15:46:08 +0200 Subject: [PATCH] code serialization, minimal opcodes --- Test/TestByteCodeGenerator.hs | 18 +++---- src/ByteCode/ClassFile.hs | 73 ++++++++++++++++++++++++++++- src/ByteCode/ClassFile/Generator.hs | 9 ++-- 3 files changed, 86 insertions(+), 14 deletions(-) diff --git a/Test/TestByteCodeGenerator.hs b/Test/TestByteCodeGenerator.hs index d51239d..98e5949 100644 --- a/Test/TestByteCodeGenerator.hs +++ b/Test/TestByteCodeGenerator.hs @@ -15,11 +15,12 @@ expectedClass = ClassFile { Utf8Info "java/lang/Object", Utf8Info "", Utf8Info "()V", - ClassInfo 8, + Utf8Info "Code", + ClassInfo 9, Utf8Info "Testklasse" ], accessFlags = accessPublic, - thisClass = 7, + thisClass = 8, superClass = 1, fields = [], methods = [], @@ -35,21 +36,22 @@ expectedClassWithFields = ClassFile { Utf8Info "java/lang/Object", Utf8Info "", Utf8Info "()V", - ClassInfo 8, + Utf8Info "Code", + ClassInfo 9, Utf8Info "Testklasse", - FieldRefInfo (fromIntegral 7) (fromIntegral 10), - NameAndTypeInfo (fromIntegral 11) (fromIntegral 12), + FieldRefInfo (fromIntegral 8) (fromIntegral 11), + NameAndTypeInfo (fromIntegral 12) (fromIntegral 13), Utf8Info "testvariable", Utf8Info "I" ], accessFlags = accessPublic, - thisClass = 7, + thisClass = 8, superClass = 1, fields = [ MemberInfo { memberAccessFlags = accessPublic, - memberNameIndex = 11, - memberDescriptorIndex = 12, + memberNameIndex = 12, + memberDescriptorIndex = 13, memberAttributes = [] } ], diff --git a/src/ByteCode/ClassFile.hs b/src/ByteCode/ClassFile.hs index 8745f18..cd57d1a 100644 --- a/src/ByteCode/ClassFile.hs +++ b/src/ByteCode/ClassFile.hs @@ -22,7 +22,48 @@ data ConstantInfo = ClassInfo Word16 | Utf8Info [Char] deriving (Show, Eq) -data Attribute = Attribute Word16 [Word8] deriving (Show, Eq) + +{- + Code_attribute { + u2 attribute_name_index; + u4 attribute_length; + u2 max_stack; + u2 max_locals; + u4 code_length; + u1 code[code_length]; + u2 exception_table_length; + { u2 start_pc; + u2 end_pc; + u2 handler_pc; + u2 catch_type; + } exception_table[exception_table_length]; + u2 attributes_count; + attribute_info attributes[attributes_count]; +-} +--data Attribute = Attribute Word16 [Word8] deriving (Show, Eq) +data Operation = Iadd + | Isub + | Imul + | Idiv + | Return + | IReturn + | Sipush Word16 + | Ldc_w Word16 + | Aload Word16 + | Iload Word16 + | Astore Word16 + | Istore Word16 + | Putfield Word16 + | GetField Word16 + deriving (Show, Eq) + + +data Attribute = CodeAttribute { + attributeMaxStack :: Word16, + attributeMaxLocals :: Word16, + attributeCode :: [Operation] +} deriving (Show, Eq) + data MemberInfo = MemberInfo { memberAccessFlags :: Word16, @@ -72,8 +113,36 @@ instance Serializable MemberInfo where ++ unpackWord16 (fromIntegral (length (memberAttributes member))) ++ concatMap serialize (memberAttributes member) +instance Serializable Operation where + serialize Iadd = [0x60] + serialize Isub = [0x64] + serialize Imul = [0x68] + serialize Idiv = [0x6C] + serialize Return = [0xB1] + serialize IReturn = [0xAC] + serialize (Sipush index) = 0x11 : unpackWord16 index + serialize (Ldc_w index) = 0x13 : unpackWord16 index + serialize (Aload index) = [0xC4, 0x19] ++ unpackWord16 index + serialize (Iload index) = [0xC4, 0x15] ++ unpackWord16 index + serialize (Astore index) = [0xC4, 0x3A] ++ unpackWord16 index + serialize (Istore index) = [0xC4, 0x36] ++ unpackWord16 index + serialize (Putfield index) = 0xB5 : unpackWord16 index + serialize (GetField index) = 0xB4 : unpackWord16 index + instance Serializable Attribute where - serialize (Attribute nameIndex bytes) = unpackWord16 nameIndex ++ unpackWord32 (fromIntegral (length bytes)) ++ bytes + serialize (CodeAttribute { attributeMaxStack = maxStack, + attributeMaxLocals = maxLocals, + attributeCode = code }) = let + assembledCode = concat (map serialize code) + in + unpackWord16 7 -- attribute_name_index + ++ unpackWord32 (12 + (fromIntegral (length assembledCode))) -- attribute_length + ++ unpackWord16 maxStack -- max_stack + ++ unpackWord16 maxLocals -- max_locals + ++ unpackWord32 (fromIntegral (length assembledCode)) -- code_length + ++ assembledCode -- code + ++ unpackWord16 0 -- exception_table_length + ++ unpackWord16 0 -- attributes_count instance Serializable ClassFile where serialize classfile = unpackWord32 0xC0FEBABE -- magic diff --git a/src/ByteCode/ClassFile/Generator.hs b/src/ByteCode/ClassFile/Generator.hs index 5682326..cf7a719 100644 --- a/src/ByteCode/ClassFile/Generator.hs +++ b/src/ByteCode/ClassFile/Generator.hs @@ -15,7 +15,7 @@ datatypeDescriptor :: String -> String datatypeDescriptor "int" = "I" datatypeDescriptor "char" = "C" datatypeDescriptor "boolean" = "B" -datatypeDescriptor x = x +datatypeDescriptor x = "L" ++ x classBuilder :: ClassFileBuilder Class @@ -26,13 +26,14 @@ classBuilder (Class name methods fields) _ = let NameAndTypeInfo 5 6, Utf8Info "java/lang/Object", Utf8Info "", - Utf8Info "()V" + Utf8Info "()V", + Utf8Info "Code" ] - nameConstants = [ClassInfo 8, Utf8Info name] + nameConstants = [ClassInfo 9, Utf8Info name] nakedClassFile = ClassFile { constantPool = baseConstants ++ nameConstants, accessFlags = accessPublic, - thisClass = 7, + thisClass = 8, superClass = 1, fields = [], methods = [],