Bytecode kann für folgende Operationen +,-,*,/,% erzeugt werden

This commit is contained in:
Fayez Abu Alia 2018-02-28 15:59:21 +01:00
parent 6b57aacef0
commit 35b99a4095
2 changed files with 245 additions and 43 deletions

View File

@ -16,6 +16,7 @@ import de.dhbwstuttgart.exceptions.NotImplementedException;
import de.dhbwstuttgart.syntaxtree.statement.*; import de.dhbwstuttgart.syntaxtree.statement.*;
import org.objectweb.asm.ClassWriter; import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Handle; import org.objectweb.asm.Handle;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes; import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type; import org.objectweb.asm.Type;
@ -107,7 +108,6 @@ public class BytecodeGenMethod implements StatementVisitor{
@Override @Override
public void visit(Block block) { public void visit(Block block) {
for(Statement stmt : block.getStatements()) { for(Statement stmt : block.getStatements()) {
// System.out.println(where);
stmt.accept(this); stmt.accept(this);
} }
} }
@ -116,15 +116,20 @@ public class BytecodeGenMethod implements StatementVisitor{
public void visit(SuperCall superCall) { public void visit(SuperCall superCall) {
superCall.receiver.accept(this); superCall.receiver.accept(this);
superCall.arglist.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 @Override
public void visit(LocalVar localVar) { 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)); mv.visitVarInsn(Opcodes.ALOAD, paramsAndLocals.get(localVar.name));
if(isBinaryExp) { if(isBinaryExp) {
getVlaue(getResolvedType(localVar.getType())); getVlaueIns(getResolvedType(localVar.getType()));
} }
} }
// ?? // ??
@ -152,27 +157,175 @@ public class BytecodeGenMethod implements StatementVisitor{
assign.rightSide.accept(this); assign.rightSide.accept(this);
} }
if(isBinaryExp) { if(isBinaryExp) {
doAssign(getResolvedType(assign.lefSide.getType())); getValueOfIns(getResolvedType(assign.lefSide.getType()));
isBinaryExp = false; isBinaryExp = false;
} }
assign.lefSide.accept(this); assign.lefSide.accept(this);
} }
/*
* Die folgeneden Fälle müssen noch betrachtet werden:
* - Long OPARATION Integer usw.
* */
@Override @Override
public void visit(BinaryExpr binary) { 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),
"<init>", "()V", false);
}
binary.lexpr.accept(this); binary.lexpr.accept(this);
binary.rexpr.accept(this); binary.rexpr.accept(this);
switch (binary.operation.toString()) { switch (binary.operation.toString()) {
case "ADD": case "ADD":
mv.visitInsn(Opcodes.IADD); doVisitAddOpInsn(typeOfBinary);
break; 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: default:
break; 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 @Override
public void visit(LambdaExpression lambdaExpression) { public void visit(LambdaExpression lambdaExpression) {
this.lamCounter++; this.lamCounter++;
@ -429,41 +582,45 @@ public class BytecodeGenMethod implements StatementVisitor{
@Override @Override
public void visit(Literal literal) { public void visit(Literal literal) {
Object value = literal.value; Object value = literal.value;
String typeOfLiteral = resultSet.resolveType(literal.getType()).resolvedType.acceptTV(new TypeToDescriptor()); String typeOfLiteral = resultSet.resolveType(
if(this.isBinaryExp) { literal.getType()).resolvedType.acceptTV(new TypeToDescriptor());
getVlaue(typeOfLiteral);
}else {
doAssign(typeOfLiteral, value);
}
doAssign(typeOfLiteral, value);
} }
private void getVlaue(String typeOfLiteral) { private void getVlaueIns(String type) {
switch (typeOfLiteral) { switch (type) {
case "java/lang/String": case "java/lang/String":
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, Type.getInternalName(StringBuilder.class),
"append", "(Ljava/lang/String;)Ljava/lang/StringBuilder;", false);
break; break;
case "java/lang/Boolean": case "java/lang/Boolean":
break; break;
case "java/lang/Byte": case "java/lang/Byte":
mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Byte", "valueOf", mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Byte", "byteValue",
"(B)Ljava/lang/Byte;", false); "()B", false);
break; break;
case "java/lang/Short": case "java/lang/Short":
mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Short", "valueOf", mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Short", "shortValue",
"(S)Ljava/lang/Short;", false); "()S", false);
break; break;
case "java/lang/Integer": case "java/lang/Integer":
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Integer", "intValue", mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Integer", "intValue",
"()I", false); "()I", false);
break; break;
case "java/lang/Long": case "java/lang/Long":
mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Long", "valueOf", mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Long", "longValue",
"(J)Ljava/lang/Long;", false); "()J", false);
break; break;
case "java/lang/Float": case "java/lang/Float":
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Float", "floatValue",
"()F", false);
break; break;
case "java/lang/Double": case "java/lang/Double":
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Double", "doubleValue",
"()D", false);
break; break;
case "java/lang/Character": case "java/lang/Character":
break; break;
@ -482,24 +639,24 @@ public class BytecodeGenMethod implements StatementVisitor{
break; break;
case "java/lang/Byte": case "java/lang/Byte":
visitByteLiteral(((Double) value).byteValue(),false); visitByteLiteral(((Double) value).byteValue(),false);
mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Byte", "valueOf", if(!this.isBinaryExp)
"(B)Ljava/lang/Byte;", false); getValueOfIns(type);
break; break;
case "java/lang/Short": case "java/lang/Short":
visitShortLiteral(((Double) value).shortValue(),false); visitShortLiteral(((Double) value).shortValue(),false);
mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Short", "valueOf", if(!this.isBinaryExp)
"(S)Ljava/lang/Short;", false); getValueOfIns(type);
break; break;
case "java/lang/Integer": case "java/lang/Integer":
//zweite Argument isLong //zweite Argument isLong
visitIntegerLiteral(((Double) value).intValue(), false); visitIntegerLiteral(((Double) value).intValue(), false);
mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Integer", "valueOf", if(!this.isBinaryExp)
"(I)Ljava/lang/Integer;", false); getValueOfIns(type);
break; break;
case "java/lang/Long": case "java/lang/Long":
visitLongLiteral(((Double) value).longValue(), true); visitLongLiteral(((Double) value).longValue(), true);
mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Long", "valueOf", if(!this.isBinaryExp)
"(J)Ljava/lang/Long;", false); getValueOfIns(type);
break; break;
case "java/lang/Float": case "java/lang/Float":
visitFloatLiteral(((Double) value).floatValue()); 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) { switch (type) {
case "java/lang/String": case "java/lang/String":
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/StringBuilder", "toString",
"()Ljava/lang/String;", false);
break; break;
case "java/lang/Boolean": case "java/lang/Boolean":
mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Boolean", "valueOf",
"(Z)Ljava/lang/Boolean;", false);
break; break;
case "java/lang/Byte": case "java/lang/Byte":
mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Byte", "valueOf", mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Byte", "valueOf",
@ -538,10 +699,16 @@ public class BytecodeGenMethod implements StatementVisitor{
"(J)Ljava/lang/Long;", false); "(J)Ljava/lang/Long;", false);
break; break;
case "java/lang/Float": case "java/lang/Float":
mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Float", "valueOf",
"(F)Ljava/lang/Float;", false);
break; break;
case "java/lang/Double": case "java/lang/Double":
mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Double", "valueOf",
"(D)Ljava/lang/Double;", false);
break; break;
case "java/lang/Character": case "java/lang/Character":
mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Character", "valueOf",
"(C)Ljava/lang/Character;", false);
break; break;
default: default:
break; break;
@ -550,8 +717,8 @@ public class BytecodeGenMethod implements StatementVisitor{
private void visitCharLiteral(Character value) { private void visitCharLiteral(Character value) {
mv.visitIntInsn(Opcodes.BIPUSH, (int) value); mv.visitIntInsn(Opcodes.BIPUSH, (int) value);
mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Character", "valueOf", if(!this.isBinaryExp)
"(C)Ljava/lang/Character;", false); getValueOfIns(Type.getInternalName(Character.class));
} }
private void visitDoubleLiteral(Double value) { private void visitDoubleLiteral(Double value) {
@ -562,8 +729,8 @@ public class BytecodeGenMethod implements StatementVisitor{
}else { }else {
mv.visitLdcInsn(value); mv.visitLdcInsn(value);
} }
mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Double", "valueOf", if(!this.isBinaryExp)
"(D)Ljava/lang/Double;", false); getValueOfIns(Type.getInternalName(Double.class));
} }
private void visitFloatLiteral(Float value) { private void visitFloatLiteral(Float value) {
@ -573,8 +740,8 @@ public class BytecodeGenMethod implements StatementVisitor{
}else { }else {
mv.visitLdcInsn(value); mv.visitLdcInsn(value);
} }
mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Float", "valueOf", if(!this.isBinaryExp)
"(F)Ljava/lang/Float;", false); getValueOfIns(Type.getInternalName(Float.class));
} }
private void visitLongLiteral(Long value, boolean isLong) { private void visitLongLiteral(Long value, boolean isLong) {
@ -622,6 +789,7 @@ public class BytecodeGenMethod implements StatementVisitor{
}else { }else {
mv.visitInsn(Opcodes.ICONST_0); mv.visitInsn(Opcodes.ICONST_0);
} }
// muss noch getestet werden.
mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Boolean", "valueOf", mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Boolean", "valueOf",
"(Z)Ljava/lang/Boolean;", false); "(Z)Ljava/lang/Boolean;", false);
} }

View File

@ -1,12 +1,46 @@
import java.lang.Integer; 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 { class Op {
m(Integer a, Integer b) { addInt(Integer a, Integer b) {
Integer c = a+b; Integer c = a+b;
// d = a-b; return c;
// e = a*b; }
// f = a/b; 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; return c;
} }
} }