Added Bytecode generation Logic for datatypes and binary expressions

This commit is contained in:
Jochen Seyfried 2024-05-05 16:56:19 +02:00
parent 261cf2f6fa
commit bd3988004c
7 changed files with 168 additions and 0 deletions

View File

@ -2,6 +2,7 @@ package abstractSyntaxTree.Datatype;
import TypeCheck.AbstractType; import TypeCheck.AbstractType;
import TypeCheck.TypeCheckResult; import TypeCheck.TypeCheckResult;
import org.objectweb.asm.*;
public class BoolDatatype extends AbstractType implements IDatatype{ public class BoolDatatype extends AbstractType implements IDatatype{
boolean value; boolean value;
@ -14,4 +15,13 @@ public class BoolDatatype extends AbstractType implements IDatatype{
setTypeCheckResult(result); setTypeCheckResult(result);
return result; return result;
} }
@Override
public void CodeGen(MethodVisitor mv) throws Exception {
if(value) {
mv.visitInsn(Opcodes.ICONST_1); // Pushes the int 1 on the stack (true)
} else {
mv.visitInsn(Opcodes.ICONST_0); // 0 for false
}
}
} }

View File

@ -2,6 +2,7 @@ package abstractSyntaxTree.Datatype;
import TypeCheck.AbstractType; import TypeCheck.AbstractType;
import TypeCheck.TypeCheckResult; import TypeCheck.TypeCheckResult;
import org.objectweb.asm.MethodVisitor;
public class CharDatatype extends AbstractType implements IDatatype{ public class CharDatatype extends AbstractType implements IDatatype{
char value; char value;
@ -14,4 +15,13 @@ public class CharDatatype extends AbstractType implements IDatatype{
setTypeCheckResult(result); setTypeCheckResult(result);
return result; return result;
} }
@Override
public void CodeGen(MethodVisitor mv) throws Exception {
// Possible use of BIPUSH and SIPUSH if the value is small enough
//This saves space in the bytecode which is not very relevant at this point, but could be implemented anyway
mv.visitLdcInsn((int)value);
}
} }

View File

@ -1,10 +1,15 @@
package abstractSyntaxTree.Datatype; package abstractSyntaxTree.Datatype;
import TypeCheck.TypeCheckResult; import TypeCheck.TypeCheckResult;
import org.objectweb.asm.MethodVisitor;
public interface IDatatype { public interface IDatatype {
// typeCheck method // typeCheck method
TypeCheckResult typeCheck() throws Exception; TypeCheckResult typeCheck() throws Exception;
// visit method for code generation // visit method for code generation
void CodeGen(MethodVisitor mv) throws Exception;
} }
//TODO: Check if we need to differentiate between primitive types and reference types --> for example in "=="

View File

@ -2,6 +2,8 @@ package abstractSyntaxTree.Datatype;
import TypeCheck.AbstractType; import TypeCheck.AbstractType;
import TypeCheck.TypeCheckResult; import TypeCheck.TypeCheckResult;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
public class IntDatatype extends AbstractType implements IDatatype{ public class IntDatatype extends AbstractType implements IDatatype{
int value; int value;
@ -14,4 +16,19 @@ public class IntDatatype extends AbstractType implements IDatatype{
setTypeCheckResult(result); setTypeCheckResult(result);
return result; return result;
} }
// visit method for code generation
@Override
public void CodeGen(MethodVisitor mv) throws Exception {
//Example of using BIPUSH and SIPUSH for optimizing bytecode size
if (value >= Byte.MIN_VALUE && value <= Byte.MAX_VALUE)
mv.visitIntInsn(Opcodes.BIPUSH, value);
else if (value >= Short.MIN_VALUE && value <= Short.MAX_VALUE)
mv.visitIntInsn(Opcodes.SIPUSH, value);
else
mv.visitLdcInsn(value);
}
} }

View File

@ -4,6 +4,8 @@ import TypeCheck.AbstractType;
import TypeCheck.TypeCheckResult; import TypeCheck.TypeCheckResult;
import abstractSyntaxTree.Class.FieldDecl; import abstractSyntaxTree.Class.FieldDecl;
import abstractSyntaxTree.Class.MethodDecl; import abstractSyntaxTree.Class.MethodDecl;
import jdk.jshell.spi.ExecutionControl;
import org.objectweb.asm.MethodVisitor;
import java.util.List; import java.util.List;
@ -31,4 +33,13 @@ public class RefType extends AbstractType implements IDatatype {
setTypeCheckResult(result); setTypeCheckResult(result);
return result; return result;
} }
// Method for code generation which iterates over all the field declarations
// and method declarations and calls their CodeGen methods
@Override
public void CodeGen(MethodVisitor mv) throws Exception {
throw new ExecutionControl.NotImplementedException("CodeGen not implemented for RefType");
}
} }

View File

@ -3,7 +3,9 @@ package abstractSyntaxTree.Expression;
import TypeCheck.TypeCheckResult; import TypeCheck.TypeCheckResult;
import TypeCheck.TypeCheckHelper; import TypeCheck.TypeCheckHelper;
import TypeCheck.AbstractType; import TypeCheck.AbstractType;
import org.objectweb.asm.*;
import java.beans.Expression;
import java.util.Objects; import java.util.Objects;
public class BinaryExpression extends AbstractType implements IExpression{ public class BinaryExpression extends AbstractType implements IExpression{
@ -54,4 +56,115 @@ public class BinaryExpression extends AbstractType implements IExpression{
setTypeCheckResult(result); setTypeCheckResult(result);
return result; return result;
} }
@Override
public void CodeGen(MethodVisitor mv) throws Exception {
// Label for the jump instruction
Label operationFalse = new Label(); //Operation is false
Label operationTrue = new Label(); //Operation is true
// Labels are placed at the end of this method
Label expressionEnd = new Label(); //End of the whole expression
// Bytecode for the binary operation
switch (operator) {
case "&&":
left.CodeGen(mv);
mv.visitJumpInsn(Opcodes.IFEQ, operationFalse); // IFEQ --> "if equals to zero" (false) --> if left exp is false
right.CodeGen(mv);
mv.visitJumpInsn(Opcodes.IFEQ, operationFalse); // If right exp is false, jump to the end of the whole expression
mv.visitJumpInsn(Opcodes.GOTO, operationTrue); // If it reaches this point, the right exp is true
break;
case "||":
left.CodeGen(mv);
mv.visitJumpInsn(Opcodes.IFNE, operationTrue); // IFNE --> "if not equals to zero" (true) --> if left exp is true
right.CodeGen(mv);
mv.visitJumpInsn(Opcodes.IFNE, operationTrue);
break;
case "==":
// Keep in mind that only primitive types are allowed in this case (at this time)
left.CodeGen(mv);
right.CodeGen(mv);
mv.visitJumpInsn(Opcodes.IF_ICMPEQ, operationTrue); // If the two values are equal, jump to the end of the expression
break;
case "<":
left.CodeGen(mv);
right.CodeGen(mv);
mv.visitJumpInsn(Opcodes.IF_ICMPLT, operationTrue); // Checks only on less than, not equal
break;
case ">":
left.CodeGen(mv);
right.CodeGen(mv);
mv.visitJumpInsn(Opcodes.IF_ICMPGT, operationTrue); // Checks only on greater than, not equal
break;
case "<=":
left.CodeGen(mv);
right.CodeGen(mv);
mv.visitJumpInsn(Opcodes.IF_ICMPLE, operationTrue); // Checks on less than OR equal
break;
case ">=":
left.CodeGen(mv);
right.CodeGen(mv);
mv.visitJumpInsn(Opcodes.IF_ICMPGE, operationTrue); // Checks on greater than OR equal
break;
case "!=":
left.CodeGen(mv);
right.CodeGen(mv);
mv.visitJumpInsn(Opcodes.IF_ICMPNE, operationTrue); // Checks on not equal
break;
case "+":
left.CodeGen(mv);
right.CodeGen(mv);
mv.visitInsn(Opcodes.IADD);
break;
case "-":
left.CodeGen(mv);
right.CodeGen(mv);
mv.visitInsn(Opcodes.ISUB);
break;
case "*":
left.CodeGen(mv);
right.CodeGen(mv);
mv.visitInsn(Opcodes.IMUL);
break;
case "/":
left.CodeGen(mv);
right.CodeGen(mv);
mv.visitInsn(Opcodes.IDIV);
break;
default:
throw new Exception("Unknown operator: " + operator);
}
mv.visitLabel(operationFalse);
mv.visitInsn(Opcodes.ICONST_0); // Push false on the stack
mv.visitJumpInsn(Opcodes.GOTO, expressionEnd); // Jump to the end of the expression (skip the true push)
mv.visitLabel(operationTrue);
mv.visitInsn(Opcodes.ICONST_1); // Push true on the stack
mv.visitLabel(expressionEnd);
}
} }

View File

@ -1,10 +1,12 @@
package abstractSyntaxTree.Expression; package abstractSyntaxTree.Expression;
import TypeCheck.TypeCheckResult; import TypeCheck.TypeCheckResult;
import org.objectweb.asm.MethodVisitor;
public interface IExpression { public interface IExpression {
// typeCheck method // typeCheck method
TypeCheckResult typeCheck() throws Exception; TypeCheckResult typeCheck() throws Exception;
// visit method for code generation // visit method for code generation
void CodeGen(MethodVisitor mv) throws Exception;
} }