From 35b99a40959c904cad677f32214a9af481846f49 Mon Sep 17 00:00:00 2001 From: Fayez Abu Alia Date: Wed, 28 Feb 2018 15:59:21 +0100 Subject: [PATCH] =?UTF-8?q?Bytecode=20kann=20f=C3=BCr=20folgende=20Operati?= =?UTF-8?q?onen=20+,-,*,/,%=20erzeugt=20werden?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bytecode/BytecodeGenMethod.java | 242 +++++++++++++++--- test/bytecode/Op.jav | 46 +++- 2 files changed, 245 insertions(+), 43 deletions(-) diff --git a/src/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java b/src/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java index df714015..49a6750e 100644 --- a/src/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java +++ b/src/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java @@ -16,6 +16,7 @@ import de.dhbwstuttgart.exceptions.NotImplementedException; import de.dhbwstuttgart.syntaxtree.statement.*; import org.objectweb.asm.ClassWriter; import org.objectweb.asm.Handle; +import org.objectweb.asm.Label; import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Opcodes; import org.objectweb.asm.Type; @@ -107,7 +108,6 @@ public class BytecodeGenMethod implements StatementVisitor{ @Override public void visit(Block block) { for(Statement stmt : block.getStatements()) { -// System.out.println(where); stmt.accept(this); } } @@ -116,15 +116,20 @@ public class BytecodeGenMethod implements StatementVisitor{ public void visit(SuperCall superCall) { superCall.receiver.accept(this); superCall.arglist.accept(this); - mv.visitMethodInsn(Opcodes.INVOKESPECIAL, Type.getInternalName(Object.class), superCall.name, "()V",isInterface); + mv.visitMethodInsn(Opcodes.INVOKESPECIAL, Type.getInternalName(Object.class), + superCall.name, "()V",isInterface); } // ?? @Override public void visit(LocalVar localVar) { + // wenn String + String zuerst wird ein StringBuilder initialisiert dann + // wird die lokale Var geladen. Sonst wird zuerst die lokale Var geladen. + mv.visitVarInsn(Opcodes.ALOAD, paramsAndLocals.get(localVar.name)); + if(isBinaryExp) { - getVlaue(getResolvedType(localVar.getType())); + getVlaueIns(getResolvedType(localVar.getType())); } } // ?? @@ -152,27 +157,175 @@ public class BytecodeGenMethod implements StatementVisitor{ assign.rightSide.accept(this); } if(isBinaryExp) { - doAssign(getResolvedType(assign.lefSide.getType())); + getValueOfIns(getResolvedType(assign.lefSide.getType())); isBinaryExp = false; } assign.lefSide.accept(this); } - + /* + * Die folgeneden Fälle müssen noch betrachtet werden: + * - Long OPARATION Integer usw. + * */ @Override public void visit(BinaryExpr binary) { + String typeOfBinary = getResolvedType(binary.getType()); + if(typeOfBinary.equals(Type.getInternalName(String.class))) { + mv.visitTypeInsn(Opcodes.NEW, Type.getInternalName(StringBuilder.class)); + mv.visitInsn(Opcodes.DUP); + mv.visitMethodInsn(Opcodes.INVOKESPECIAL, Type.getInternalName(StringBuilder.class), + "", "()V", false); + } binary.lexpr.accept(this); binary.rexpr.accept(this); switch (binary.operation.toString()) { case "ADD": - mv.visitInsn(Opcodes.IADD); + doVisitAddOpInsn(typeOfBinary); break; - + + case "SUB": + doVisitSubOpInsn(typeOfBinary); + break; + + case "MUL": + doVisitMulOpInsn(typeOfBinary); + break; + + case "DIV": + doVisitDivOpInsn(typeOfBinary); + break; + + case "MOD": + doVisitModOpInsn(typeOfBinary); + break; + + case "LESSTHAN": + doVisitLessOpInsn(typeOfBinary); + break; + default: break; } } - + // TODO + private void doVisitLessOpInsn(String typeOfBinary) { + switch (typeOfBinary) { + case "java/lang/Long": + mv.visitInsn(Opcodes.LCMP); + break; + case "java/lang/Double": + mv.visitInsn(Opcodes.DCMPG); + break; + case "java/lang/Float": + mv.visitInsn(Opcodes.FCMPG); + break; + default: + Label greaterEq = new Label(); + mv.visitJumpInsn(Opcodes.IF_ICMPGE, greaterEq); + mv.visitInsn(Opcodes.ICONST_1); + Label lessThan = new Label(); + mv.visitJumpInsn(Opcodes.GOTO, lessThan); + mv.visitLabel(greaterEq); + mv.visitInsn(Opcodes.ICONST_0); + mv.visitLabel(lessThan); + break; + } + } + + private void doVisitModOpInsn(String typeOfBinary) { + switch (typeOfBinary) { + case "java/lang/Long": + mv.visitInsn(Opcodes.LREM); + break; + case "java/lang/Double": + mv.visitInsn(Opcodes.DREM); + break; + case "java/lang/Float": + mv.visitInsn(Opcodes.FREM); + break; + default: + mv.visitInsn(Opcodes.IREM); + break; + } + } + + private void doVisitDivOpInsn(String typeOfBinary) { + switch (typeOfBinary) { + case "java/lang/Long": + mv.visitInsn(Opcodes.LDIV); + break; + case "java/lang/Double": + mv.visitInsn(Opcodes.DDIV); + break; + case "java/lang/Float": + mv.visitInsn(Opcodes.FDIV); + break; + default: + mv.visitInsn(Opcodes.IDIV); + break; + } + } + + private void doVisitMulOpInsn(String typeOfBinary) { + switch (typeOfBinary) { + case "java/lang/Long": + mv.visitInsn(Opcodes.LMUL); + break; + case "java/lang/Double": + mv.visitInsn(Opcodes.DMUL); + break; + case "java/lang/Float": + mv.visitInsn(Opcodes.FMUL); + break; + default: + mv.visitInsn(Opcodes.IMUL); + break; + } + } + + private void doVisitSubOpInsn(String typeOfBinary) { + switch (typeOfBinary) { + case "java/lang/Long": + mv.visitInsn(Opcodes.LSUB); + break; + case "java/lang/Double": + mv.visitInsn(Opcodes.DSUB); + break; + case "java/lang/Float": + mv.visitInsn(Opcodes.FSUB); + break; + default: + mv.visitInsn(Opcodes.ISUB); + break; + } + + } + + private void doVisitAddOpInsn(String typeOfBinary) { + switch (typeOfBinary) { + case "java/lang/Byte": + mv.visitInsn(Opcodes.IADD); + break; + case "java/lang/Short": + mv.visitInsn(Opcodes.IADD); + break; + case "java/lang/Integer": + mv.visitInsn(Opcodes.IADD); + break; + case "java/lang/Long": + mv.visitInsn(Opcodes.LADD); + break; + case "java/lang/Double": + mv.visitInsn(Opcodes.DADD); + break; + case "java/lang/Float": + mv.visitInsn(Opcodes.FADD); + break; + default: + break; + } + } + @Override public void visit(LambdaExpression lambdaExpression) { this.lamCounter++; @@ -429,41 +582,45 @@ public class BytecodeGenMethod implements StatementVisitor{ @Override public void visit(Literal literal) { Object value = literal.value; - String typeOfLiteral = resultSet.resolveType(literal.getType()).resolvedType.acceptTV(new TypeToDescriptor()); - if(this.isBinaryExp) { - getVlaue(typeOfLiteral); - }else { - doAssign(typeOfLiteral, value); - } + String typeOfLiteral = resultSet.resolveType( + literal.getType()).resolvedType.acceptTV(new TypeToDescriptor()); + doAssign(typeOfLiteral, value); } - private void getVlaue(String typeOfLiteral) { - switch (typeOfLiteral) { + private void getVlaueIns(String type) { + switch (type) { case "java/lang/String": + mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, Type.getInternalName(StringBuilder.class), + "append", "(Ljava/lang/String;)Ljava/lang/StringBuilder;", false); + break; case "java/lang/Boolean": break; case "java/lang/Byte": - mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Byte", "valueOf", - "(B)Ljava/lang/Byte;", false); + mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Byte", "byteValue", + "()B", false); break; case "java/lang/Short": - mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Short", "valueOf", - "(S)Ljava/lang/Short;", false); + mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Short", "shortValue", + "()S", false); break; case "java/lang/Integer": mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Integer", "intValue", "()I", false); break; case "java/lang/Long": - mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Long", "valueOf", - "(J)Ljava/lang/Long;", false); + mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Long", "longValue", + "()J", false); break; case "java/lang/Float": + mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Float", "floatValue", + "()F", false); break; case "java/lang/Double": + mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Double", "doubleValue", + "()D", false); break; case "java/lang/Character": break; @@ -482,24 +639,24 @@ public class BytecodeGenMethod implements StatementVisitor{ break; case "java/lang/Byte": visitByteLiteral(((Double) value).byteValue(),false); - mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Byte", "valueOf", - "(B)Ljava/lang/Byte;", false); + if(!this.isBinaryExp) + getValueOfIns(type); break; case "java/lang/Short": visitShortLiteral(((Double) value).shortValue(),false); - mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Short", "valueOf", - "(S)Ljava/lang/Short;", false); + if(!this.isBinaryExp) + getValueOfIns(type); break; case "java/lang/Integer": //zweite Argument isLong visitIntegerLiteral(((Double) value).intValue(), false); - mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Integer", "valueOf", - "(I)Ljava/lang/Integer;", false); + if(!this.isBinaryExp) + getValueOfIns(type); break; case "java/lang/Long": visitLongLiteral(((Double) value).longValue(), true); - mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Long", "valueOf", - "(J)Ljava/lang/Long;", false); + if(!this.isBinaryExp) + getValueOfIns(type); break; case "java/lang/Float": visitFloatLiteral(((Double) value).floatValue()); @@ -515,11 +672,15 @@ public class BytecodeGenMethod implements StatementVisitor{ } } - private void doAssign(String type) { + private void getValueOfIns(String type) { switch (type) { case "java/lang/String": + mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/StringBuilder", "toString", + "()Ljava/lang/String;", false); break; case "java/lang/Boolean": + mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Boolean", "valueOf", + "(Z)Ljava/lang/Boolean;", false); break; case "java/lang/Byte": mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Byte", "valueOf", @@ -538,10 +699,16 @@ public class BytecodeGenMethod implements StatementVisitor{ "(J)Ljava/lang/Long;", false); break; case "java/lang/Float": + mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Float", "valueOf", + "(F)Ljava/lang/Float;", false); break; case "java/lang/Double": + mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Double", "valueOf", + "(D)Ljava/lang/Double;", false); break; case "java/lang/Character": + mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Character", "valueOf", + "(C)Ljava/lang/Character;", false); break; default: break; @@ -550,8 +717,8 @@ public class BytecodeGenMethod implements StatementVisitor{ private void visitCharLiteral(Character value) { mv.visitIntInsn(Opcodes.BIPUSH, (int) value); - mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Character", "valueOf", - "(C)Ljava/lang/Character;", false); + if(!this.isBinaryExp) + getValueOfIns(Type.getInternalName(Character.class)); } private void visitDoubleLiteral(Double value) { @@ -562,8 +729,8 @@ public class BytecodeGenMethod implements StatementVisitor{ }else { mv.visitLdcInsn(value); } - mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Double", "valueOf", - "(D)Ljava/lang/Double;", false); + if(!this.isBinaryExp) + getValueOfIns(Type.getInternalName(Double.class)); } private void visitFloatLiteral(Float value) { @@ -573,8 +740,8 @@ public class BytecodeGenMethod implements StatementVisitor{ }else { mv.visitLdcInsn(value); } - mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Float", "valueOf", - "(F)Ljava/lang/Float;", false); + if(!this.isBinaryExp) + getValueOfIns(Type.getInternalName(Float.class)); } private void visitLongLiteral(Long value, boolean isLong) { @@ -622,6 +789,7 @@ public class BytecodeGenMethod implements StatementVisitor{ }else { mv.visitInsn(Opcodes.ICONST_0); } + // muss noch getestet werden. mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;", false); } diff --git a/test/bytecode/Op.jav b/test/bytecode/Op.jav index 9c05b0a2..3a8d157a 100644 --- a/test/bytecode/Op.jav +++ b/test/bytecode/Op.jav @@ -1,12 +1,46 @@ import java.lang.Integer; +import java.lang.String; +import java.lang.Long; +import java.lang.Float; +import java.lang.Double; +import java.lang.Boolean; class Op { - m(Integer a, Integer b) { - Integer c = a+b; -// d = a-b; -// e = a*b; -// f = a/b; - + addInt(Integer a, Integer b) { + Integer c = a+b; + return c; + } + addString(String a, String b) { + String c = a+b; + return c; + } + addLong(Long a, Long b) { + Long c = a+b; + return c; + } + addFloat(Float a, Float b) { + Float c = a+b; + return c; + } + addDouble(Double a, Double b) { + Double c = a+b; + return c; + } + + subInt(Integer a, Integer b) { + Integer c = a-b; + return c; + } + subLong(Long a, Long b) { + Long c = a-b; + return c; + } + subFloat(Float a, Float b) { + Float c = a-b; + return c; + } + subDouble(Double a, Double b) { + Double c = a-b; return c; } } \ No newline at end of file