From 09469e0e4541a7d59e690aa3ffe6ed79e02b86da Mon Sep 17 00:00:00 2001 From: mrab Date: Tue, 14 May 2024 10:28:57 +0200 Subject: [PATCH] added boolean expression assembly --- src/ByteCode/ClassFile.hs | 34 ++++++++++++++++++++++++++++- src/ByteCode/ClassFile/Generator.hs | 34 ++++++++++++++++++++++------- src/Main.hs | 2 +- 3 files changed, 60 insertions(+), 10 deletions(-) diff --git a/src/ByteCode/ClassFile.hs b/src/ByteCode/ClassFile.hs index bdae918..a27be11 100644 --- a/src/ByteCode/ClassFile.hs +++ b/src/ByteCode/ClassFile.hs @@ -5,7 +5,8 @@ module ByteCode.ClassFile( ClassFile(..), Operation(..), serialize, - emptyClassFile + emptyClassFile, + opcodeEncodingLength ) where import Data.Word @@ -41,6 +42,7 @@ data Operation = Opiadd | Opreturn | Opireturn | Opareturn + | Opgoto Word16 | Opsipush Word16 | Opldc_w Word16 | Opaload Word16 @@ -87,6 +89,35 @@ emptyClassFile = ClassFile { attributes = [] } +opcodeEncodingLength :: Operation -> Word16 +opcodeEncodingLength Opiadd = 1 +opcodeEncodingLength Opisub = 1 +opcodeEncodingLength Opimul = 1 +opcodeEncodingLength Opidiv = 1 +opcodeEncodingLength Opiand = 1 +opcodeEncodingLength Opior = 1 +opcodeEncodingLength Opixor = 1 +opcodeEncodingLength Opineg = 1 +opcodeEncodingLength (Opif_icmplt _) = 3 +opcodeEncodingLength (Opif_icmple _) = 3 +opcodeEncodingLength (Opif_icmpgt _) = 3 +opcodeEncodingLength (Opif_icmpge _) = 3 +opcodeEncodingLength (Opif_icmpeq _) = 3 +opcodeEncodingLength (Opif_icmpne _) = 3 +opcodeEncodingLength Opaconst_null = 1 +opcodeEncodingLength Opreturn = 1 +opcodeEncodingLength Opireturn = 1 +opcodeEncodingLength Opareturn = 1 +opcodeEncodingLength (Opgoto _) = 3 +opcodeEncodingLength (Opsipush _) = 3 +opcodeEncodingLength (Opldc_w _) = 3 +opcodeEncodingLength (Opaload _) = 3 +opcodeEncodingLength (Opiload _) = 3 +opcodeEncodingLength (Opastore _) = 3 +opcodeEncodingLength (Opistore _) = 3 +opcodeEncodingLength (Opputfield _) = 3 +opcodeEncodingLength (OpgetField _) = 3 + class Serializable a where serialize :: a -> [Word8] @@ -126,6 +157,7 @@ instance Serializable Operation where serialize Opreturn = [0xB1] serialize Opireturn = [0xAC] serialize Opareturn = [0xB0] + serialize (Opgoto index) = 0xA7 : unpackWord16 index serialize (Opsipush index) = 0x11 : unpackWord16 index serialize (Opldc_w index) = 0x13 : unpackWord16 index serialize (Opaload index) = [0xC4, 0x19] ++ unpackWord16 index diff --git a/src/ByteCode/ClassFile/Generator.hs b/src/ByteCode/ClassFile/Generator.hs index a80c081..8f7287a 100644 --- a/src/ByteCode/ClassFile/Generator.hs +++ b/src/ByteCode/ClassFile/Generator.hs @@ -10,10 +10,11 @@ module ByteCode.ClassFile.Generator( ) where import ByteCode.Constants -import ByteCode.ClassFile (ClassFile (..), ConstantInfo (..), MemberInfo(..), Operation(..), Attribute(..)) +import ByteCode.ClassFile (ClassFile (..), ConstantInfo (..), MemberInfo(..), Operation(..), Attribute(..), opcodeEncodingLength) import Ast import Data.Char import Data.List +import Data.Word type ClassFileBuilder a = a -> ClassFile -> ClassFile @@ -176,13 +177,22 @@ returnOperation dtype | otherwise = Opareturn binaryOperation :: BinaryOperator -> Operation -binaryOperation Addition = Opiadd -binaryOperation Subtraction = Opisub -binaryOperation Multiplication = Opimul -binaryOperation Division = Opidiv -binaryOperation BitwiseAnd = Opiand -binaryOperation BitwiseOr = Opior -binaryOperation BitwiseXor = Opixor +binaryOperation Addition = Opiadd +binaryOperation Subtraction = Opisub +binaryOperation Multiplication = Opimul +binaryOperation Division = Opidiv +binaryOperation BitwiseAnd = Opiand +binaryOperation BitwiseOr = Opior +binaryOperation BitwiseXor = Opixor + +comparisonOperation :: BinaryOperator -> Word16 -> Operation +comparisonOperation CompareEqual branchLocation = Opif_icmpeq branchLocation +comparisonOperation CompareNotEqual branchLocation = Opif_icmpne branchLocation +comparisonOperation CompareLessThan branchLocation = Opif_icmplt branchLocation +comparisonOperation CompareLessOrEqual branchLocation = Opif_icmple branchLocation +comparisonOperation CompareGreaterThan branchLocation = Opif_icmpgt branchLocation +comparisonOperation CompareGreaterOrEqual branchLocation = Opif_icmpge branchLocation + assembleMethod :: Assembler MethodDeclaration assembleMethod (MethodDeclaration _ _ _ (Block statements)) (constants, ops) = @@ -203,6 +213,14 @@ assembleExpression (TypedExpression _ (BinaryOperation op a b)) (constants, ops) (bConstants, bOps) = assembleExpression b (aConstants, aOps) in (bConstants, bOps ++ [binaryOperation op]) + | elem op [CompareEqual, CompareNotEqual, CompareLessThan, CompareLessOrEqual, CompareGreaterThan, CompareGreaterOrEqual] = let + (aConstants, aOps) = assembleExpression a (constants, ops) + (bConstants, bOps) = assembleExpression b (aConstants, aOps) + current_offset = sum (map opcodeEncodingLength bOps) + cmp_op = comparisonOperation op (fromIntegral (current_offset + 10)) + cmp_ops = [cmp_op, Opsipush 1, Opgoto (fromIntegral (current_offset + 13)), Opsipush 0] + in + (bConstants, bOps ++ cmp_ops) assembleExpression (TypedExpression _ (CharacterLiteral literal)) (constants, ops) = (constants, ops ++ [Opsipush (fromIntegral (ord literal))]) assembleExpression (TypedExpression _ (BooleanLiteral literal)) (constants, ops) = diff --git a/src/Main.hs b/src/Main.hs index 5ad66c4..130ed20 100644 --- a/src/Main.hs +++ b/src/Main.hs @@ -9,7 +9,7 @@ import ByteCode.ClassFile import Data.ByteString (pack, writeFile) main = do - let untypedAST = parse $ alexScanTokens "class Testklasse {int a; int b; void something(){} void something_else(){} Testklasse(){}}" + let untypedAST = parse $ alexScanTokens "class Testklasse {int a; int b; void something(){} void something_else(){}}" let typedAST = head (typeCheckCompilationUnit untypedAST) let abstractClassFile = classBuilder typedAST emptyClassFile let assembledClassFile = pack (serialize abstractClassFile)