added boolean expression assembly

This commit is contained in:
mrab 2024-05-14 10:28:57 +02:00
parent d54c7cd7e6
commit 09469e0e45
3 changed files with 60 additions and 10 deletions

View File

@ -5,7 +5,8 @@ module ByteCode.ClassFile(
ClassFile(..), ClassFile(..),
Operation(..), Operation(..),
serialize, serialize,
emptyClassFile emptyClassFile,
opcodeEncodingLength
) where ) where
import Data.Word import Data.Word
@ -41,6 +42,7 @@ data Operation = Opiadd
| Opreturn | Opreturn
| Opireturn | Opireturn
| Opareturn | Opareturn
| Opgoto Word16
| Opsipush Word16 | Opsipush Word16
| Opldc_w Word16 | Opldc_w Word16
| Opaload Word16 | Opaload Word16
@ -87,6 +89,35 @@ emptyClassFile = ClassFile {
attributes = [] 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 class Serializable a where
serialize :: a -> [Word8] serialize :: a -> [Word8]
@ -126,6 +157,7 @@ instance Serializable Operation where
serialize Opreturn = [0xB1] serialize Opreturn = [0xB1]
serialize Opireturn = [0xAC] serialize Opireturn = [0xAC]
serialize Opareturn = [0xB0] serialize Opareturn = [0xB0]
serialize (Opgoto index) = 0xA7 : unpackWord16 index
serialize (Opsipush index) = 0x11 : unpackWord16 index serialize (Opsipush index) = 0x11 : unpackWord16 index
serialize (Opldc_w index) = 0x13 : unpackWord16 index serialize (Opldc_w index) = 0x13 : unpackWord16 index
serialize (Opaload index) = [0xC4, 0x19] ++ unpackWord16 index serialize (Opaload index) = [0xC4, 0x19] ++ unpackWord16 index

View File

@ -10,10 +10,11 @@ module ByteCode.ClassFile.Generator(
) where ) where
import ByteCode.Constants import ByteCode.Constants
import ByteCode.ClassFile (ClassFile (..), ConstantInfo (..), MemberInfo(..), Operation(..), Attribute(..)) import ByteCode.ClassFile (ClassFile (..), ConstantInfo (..), MemberInfo(..), Operation(..), Attribute(..), opcodeEncodingLength)
import Ast import Ast
import Data.Char import Data.Char
import Data.List import Data.List
import Data.Word
type ClassFileBuilder a = a -> ClassFile -> ClassFile type ClassFileBuilder a = a -> ClassFile -> ClassFile
@ -176,13 +177,22 @@ returnOperation dtype
| otherwise = Opareturn | otherwise = Opareturn
binaryOperation :: BinaryOperator -> Operation binaryOperation :: BinaryOperator -> Operation
binaryOperation Addition = Opiadd binaryOperation Addition = Opiadd
binaryOperation Subtraction = Opisub binaryOperation Subtraction = Opisub
binaryOperation Multiplication = Opimul binaryOperation Multiplication = Opimul
binaryOperation Division = Opidiv binaryOperation Division = Opidiv
binaryOperation BitwiseAnd = Opiand binaryOperation BitwiseAnd = Opiand
binaryOperation BitwiseOr = Opior binaryOperation BitwiseOr = Opior
binaryOperation BitwiseXor = Opixor 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 :: Assembler MethodDeclaration
assembleMethod (MethodDeclaration _ _ _ (Block statements)) (constants, ops) = assembleMethod (MethodDeclaration _ _ _ (Block statements)) (constants, ops) =
@ -203,6 +213,14 @@ assembleExpression (TypedExpression _ (BinaryOperation op a b)) (constants, ops)
(bConstants, bOps) = assembleExpression b (aConstants, aOps) (bConstants, bOps) = assembleExpression b (aConstants, aOps)
in in
(bConstants, bOps ++ [binaryOperation op]) (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) = assembleExpression (TypedExpression _ (CharacterLiteral literal)) (constants, ops) =
(constants, ops ++ [Opsipush (fromIntegral (ord literal))]) (constants, ops ++ [Opsipush (fromIntegral (ord literal))])
assembleExpression (TypedExpression _ (BooleanLiteral literal)) (constants, ops) = assembleExpression (TypedExpression _ (BooleanLiteral literal)) (constants, ops) =

View File

@ -9,7 +9,7 @@ import ByteCode.ClassFile
import Data.ByteString (pack, writeFile) import Data.ByteString (pack, writeFile)
main = do 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 typedAST = head (typeCheckCompilationUnit untypedAST)
let abstractClassFile = classBuilder typedAST emptyClassFile let abstractClassFile = classBuilder typedAST emptyClassFile
let assembledClassFile = pack (serialize abstractClassFile) let assembledClassFile = pack (serialize abstractClassFile)