JavaCompilerCore/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java
Fayez Abu Alia ad36158a47 Test dateien
2017-10-05 20:23:27 +02:00

361 lines
11 KiB
Java

package de.dhbwstuttgart.bytecode;
import java.io.PrintStream;
import java.lang.invoke.CallSite;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.security.GeneralSecurityException;
import java.util.HashMap;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Handle;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import de.dhbwstuttgart.parser.SyntaxTreeGenerator.AssignToLocal;
import de.dhbwstuttgart.syntaxtree.Method;
import de.dhbwstuttgart.syntaxtree.StatementVisitor;
import de.dhbwstuttgart.syntaxtree.statement.ArgumentList;
import de.dhbwstuttgart.syntaxtree.statement.Assign;
import de.dhbwstuttgart.syntaxtree.statement.AssignToField;
import de.dhbwstuttgart.syntaxtree.statement.Binary;
import de.dhbwstuttgart.syntaxtree.statement.Block;
import de.dhbwstuttgart.syntaxtree.statement.CastExpr;
import de.dhbwstuttgart.syntaxtree.statement.DoStmt;
import de.dhbwstuttgart.syntaxtree.statement.EmptyStmt;
import de.dhbwstuttgart.syntaxtree.statement.Expression;
import de.dhbwstuttgart.syntaxtree.statement.FieldVar;
import de.dhbwstuttgart.syntaxtree.statement.ForStmt;
import de.dhbwstuttgart.syntaxtree.statement.IfStmt;
import de.dhbwstuttgart.syntaxtree.statement.InstanceOf;
import de.dhbwstuttgart.syntaxtree.statement.LambdaExpression;
import de.dhbwstuttgart.syntaxtree.statement.LocalVar;
import de.dhbwstuttgart.syntaxtree.statement.LocalVarDecl;
import de.dhbwstuttgart.syntaxtree.statement.MethodCall;
import de.dhbwstuttgart.syntaxtree.statement.NewArray;
import de.dhbwstuttgart.syntaxtree.statement.NewClass;
import de.dhbwstuttgart.syntaxtree.statement.Receiver;
import de.dhbwstuttgart.syntaxtree.statement.Return;
import de.dhbwstuttgart.syntaxtree.statement.ReturnVoid;
import de.dhbwstuttgart.syntaxtree.statement.Statement;
import de.dhbwstuttgart.syntaxtree.statement.StaticClassName;
import de.dhbwstuttgart.syntaxtree.statement.Super;
import de.dhbwstuttgart.syntaxtree.statement.SuperCall;
import de.dhbwstuttgart.syntaxtree.statement.This;
import de.dhbwstuttgart.syntaxtree.statement.UnaryPlus;
import de.dhbwstuttgart.syntaxtree.statement.WhileStmt;
import de.dhbwstuttgart.syntaxtree.statement.literal.Literal;
import de.dhbwstuttgart.syntaxtree.statement.literal.Null;
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
public class BytecodeGenMethod implements StatementVisitor{
private Method m;
private MethodVisitor mv;
private HashMap<String, Integer> paramsAndLocals = new HashMap<>();
private String desc;
private String className;
private int lamCounter;
private ClassWriter cw;
//for tests **
private String fieldName;
private String fieldDesc;
private Expression rightSideTemp;
private String where;
public BytecodeGenMethod(String className, Method m, MethodVisitor mv, HashMap<String, Integer> paramsAndLocals,
String desc, ClassWriter cw) {
this.where = "NORMAL METHOD";
this.className = className;
this.m = m;
this.mv = mv;
this.paramsAndLocals = paramsAndLocals;
this.desc = desc;
this.cw = cw;
this.lamCounter = -1;
this.m.block.accept(this);
}
public BytecodeGenMethod(LambdaExpression lambdaExpression, MethodVisitor mv,
HashMap<String, Integer> paramsAndLocals, String desc) {
System.out.println("++++++IN LAMBDA -------");
this.where = "&&&&&&&& LAMBDA METHOD";
this.mv = mv;
this.paramsAndLocals = paramsAndLocals;
this.desc = desc;
this.lamCounter = -1;
lambdaExpression.methodBody.accept(this);
}
@Override
public void visit(Block block) {
for(Statement stmt : block.getStatements()) {
System.out.println(where);
System.out.println("Stmt : " + stmt.toString());
stmt.accept(this);
System.out.println("--------------------------\n");
}
}
@Override
public void visit(SuperCall superCall) {
superCall.receiver.accept(this);
superCall.arglist.accept(this);
// mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object", superCall.name, desc,false);
mv.visitMethodInsn(Opcodes.INVOKESPECIAL, Type.getInternalName(Object.class), superCall.name, desc,false);
}
// ??
@Override
public void visit(LocalVar localVar) {
System.out.println("in Local Var");
}
// ??
@Override
public void visit(LocalVarDecl localVarDecl) {
// Integer i;
paramsAndLocals.put(localVarDecl.getName(), paramsAndLocals.size()+1);
System.out.println("In localVarDecl");
}
@Override
public void visit(Assign assign) {
System.out.println("Assign : \nright = "+assign.rightSide + "\nLeft = " + assign.lefSide);
if(assign.lefSide.getClass().equals(AssignToField.class)) {
// load_0, ldc or .. then putfield
this.rightSideTemp = assign.rightSide;
assign.lefSide.accept(this);
}else {
assign.rightSide.accept(this);
assign.lefSide.accept(this);
}
}
@Override
public void visit(Binary binary) {
System.out.println("++ In Binary: ");
}
@Override
public void visit(LambdaExpression lambdaExpression) {
System.out.println("\n++ In Lambda: ");
this.lamCounter++;
//Call site, which, when invoked, returns an instance of the functional interface to which
//the lambda is being converted
MethodType mt = MethodType.methodType(CallSite.class, MethodHandles.Lookup.class, String.class,
MethodType.class, MethodType.class, MethodHandle.class, MethodType.class);
Handle bootstrap = new Handle(Opcodes.H_INVOKESTATIC, "java/lang/invoke/LambdaMetafactory",
"metafactory", mt.toMethodDescriptorString(), false);
String methodName = "lambda$new$" + this.lamCounter;
// Type erasure
Type arg1 = Type.getMethodType("()V");
// real Type
Type arg3 = Type.getMethodType("()V");
Handle arg2 = new Handle(Opcodes.H_INVOKESTATIC, this.className, methodName,
arg3.toString(),false);
mv.visitInvokeDynamicInsn("run", "()Ljava/lang/Runnable;", bootstrap,
arg1, arg2,arg3);
MethodVisitor mvLambdaBody = cw.visitMethod(Opcodes.ACC_PRIVATE+ Opcodes.ACC_STATIC + Opcodes.ACC_SYNTHETIC,
methodName, arg3.toString(), null, null);
// new BytecodeGenLambda(lambdaExpression, mvLambdaBody);
new BytecodeGenMethod(lambdaExpression, mvLambdaBody, new HashMap<>(), arg3.toString());
mvLambdaBody.visitMaxs(0, 0);
mvLambdaBody.visitEnd();
}
@Override
public void visit(CastExpr castExpr) {
// TODO Auto-generated method stub
}
@Override
public void visit(EmptyStmt emptyStmt) {
// TODO Auto-generated method stub
}
@Override
public void visit(FieldVar fieldVar) {
System.out.println("in fieldVar " + fieldVar.fieldVarName + " ** receiver: "+fieldVar.receiver);
fieldName = fieldVar.fieldVarName;
fieldDesc = fieldVar.getType().toString();
fieldVar.receiver.accept(this);
// test (if)
if(!fieldVar.receiver.getClass().equals(StaticClassName.class)) {
mv.visitFieldInsn(Opcodes.GETFIELD,fieldVar.getType().toString(),fieldName ,fieldDesc);
}
// mv.visitFieldInsn(Opcodes.GETSTATIC, fieldVar.receiver.getType().toString().replace(".", "/"),
// fieldVar.fieldVarName, fieldVar.getType().toString());
}
@Override
public void visit(ForStmt forStmt) {
// TODO Auto-generated method stub
}
@Override
public void visit(IfStmt ifStmt) {
System.out.println("++ IF-Statment: ");
}
@Override
public void visit(InstanceOf instanceOf) {
// TODO Auto-generated method stub
}
@Override
public void visit(MethodCall methodCall) {
System.out.println(" In Methodcall: (" +methodCall.name+")" );
System.out.println(" Method-Receiver: "+methodCall.receiver.expr);
methodCall.receiver.accept(this);
methodCall.arglist.accept(this);
Descriptor mDesc = new Descriptor(methodCall.arglist, methodCall.getType());
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, methodCall.receiver.expr.getType().toString(),
methodCall.name, mDesc.getDesc(), false);
// test
if(!methodCall.getType().toString().equals("V")) {
mv.visitInsn(Opcodes.POP);
}
}
@Override
public void visit(NewClass methodCall) {
System.out.println("In NewClass: ");
System.out.println("name: " + methodCall.name + " *** " + "Receiver: " + methodCall.receiver);
mv.visitTypeInsn(Opcodes.NEW, methodCall.name.replace(".", "/"));
mv.visitInsn(Opcodes.DUP);
// creates Descriptor
methodCall.arglist.accept(this);
String d = "(";
for(Expression e : methodCall.arglist.getArguments()) {
d = d + "L"+e.getType().toString().replace(".", "/") + ";";
}
d += ")V";
mv.visitMethodInsn(Opcodes.INVOKESPECIAL, methodCall.name.replace(".", "/"), "<init>", d, false);
}
@Override
public void visit(NewArray newArray) {
// TODO Auto-generated method stub
}
@Override
public void visit(Receiver receiver) {
System.out.println(" in Receiver");
System.out.println(" expr : " + receiver.expr);
receiver.expr.accept(this);
}
@Override
public void visit(Return aReturn) {
mv.visitInsn(Opcodes.ARETURN);
}
@Override
public void visit(ReturnVoid aReturn) {
mv.visitInsn(Opcodes.RETURN);
}
@Override
public void visit(StaticClassName staticClassName) {
System.out.println("In StaticClassName: ");
// mv.visitMethodInsn(Opcodes.INVOKESTATIC, staticClassName.getType().toString().replace(".", "/"),
// staticClassName.toString(), staticClassName.getType().toString(), false);
mv.visitFieldInsn(Opcodes.GETSTATIC, staticClassName.getType().toString().replace(".", "/"),
fieldName, fieldDesc);
}
@Override
public void visit(Super aSuper) {
System.out.println(">> In Super: ");
}
@Override
public void visit(This aThis) {
System.out.println("-> IN This");
mv.visitVarInsn(Opcodes.ALOAD, 0);
}
@Override
public void visit(UnaryPlus unaryPlus) {
System.out.println("++ In UnaryPlus: ");
}
@Override
public void visit(WhileStmt whileStmt) {
// TODO Auto-generated method stub
}
@Override
public void visit(DoStmt whileStmt) {
// TODO Auto-generated method stub
}
@Override
public void visit(Null aNull) {
mv.visitInsn(Opcodes.ACONST_NULL);
}
@Override
public void visit(Literal literal) {
// value?
mv.visitLdcInsn(literal.getType().toString());
}
@Override
public void visit(ArgumentList argumentList) {
for(Expression al : argumentList.getArguments()) {
al.accept(this);
}
}
@Override
public void visit(AssignToField assignLeftSide) {
// Loads the an object reference from the local variable
// array slot onto the top of the operand stack.
assignLeftSide.field.receiver.accept(this);
this.rightSideTemp.accept(this);
mv.visitFieldInsn(Opcodes.PUTFIELD, assignLeftSide.field.receiver.getType().toString(),
assignLeftSide.field.fieldVarName, assignLeftSide.field.getType().toString());
}
@Override
public void visit(AssignToLocal assignLeftSide) {
paramsAndLocals.put(assignLeftSide.localVar.name, paramsAndLocals.size()+1);
mv.visitVarInsn(Opcodes.ASTORE, paramsAndLocals.size());
}
}