diff --git a/.gitignore b/.gitignore index 88556f5e3..8ad5607a8 100644 --- a/.gitignore +++ b/.gitignore @@ -13,5 +13,8 @@ bin # IDEs .classpath +*.iml .idea/ - +.DS_Store +.project +.settings/ diff --git a/.idea/uiDesigner.xml b/.idea/uiDesigner.xml deleted file mode 100644 index e96534fb2..000000000 --- a/.idea/uiDesigner.xml +++ /dev/null @@ -1,124 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/JavaTXcompiler.iml b/JavaTXcompiler.iml deleted file mode 100644 index 20953853b..000000000 --- a/JavaTXcompiler.iml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/doc/doc.iml b/doc/doc.iml deleted file mode 100644 index 8021953ed..000000000 --- a/doc/doc.iml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/pom.xml b/pom.xml index cda43dc11..5c0c35ee4 100644 --- a/pom.xml +++ b/pom.xml @@ -31,6 +31,11 @@ org.reflections reflections 0.9.11 + + + org.ow2.asm + asm-all + [4.0.0,) diff --git a/src/JavaCompilerCore1.iml b/src/JavaCompilerCore1.iml deleted file mode 100644 index b107a2dd8..000000000 --- a/src/JavaCompilerCore1.iml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/src/de/dhbwstuttgart/bytecode/BytecodeGen.java b/src/de/dhbwstuttgart/bytecode/BytecodeGen.java new file mode 100644 index 000000000..6f0ac91ee --- /dev/null +++ b/src/de/dhbwstuttgart/bytecode/BytecodeGen.java @@ -0,0 +1,386 @@ +package de.dhbwstuttgart.bytecode; + +import java.awt.List; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; + +import org.objectweb.asm.ClassWriter; +import org.objectweb.asm.FieldVisitor; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; + +import de.dhbwstuttgart.parser.SyntaxTreeGenerator.AssignToLocal; +import de.dhbwstuttgart.syntaxtree.*; +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.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.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.ExtendsWildcardType; +import de.dhbwstuttgart.syntaxtree.type.GenericRefType; +import de.dhbwstuttgart.syntaxtree.type.RefType; +import de.dhbwstuttgart.syntaxtree.type.SuperWildcardType; +import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; + +public class BytecodeGen implements ASTVisitor { + + ClassWriter cw =new ClassWriter(ClassWriter.COMPUTE_FRAMES|ClassWriter.COMPUTE_MAXS); +// String methDesc; + + String type; + + String className; + + // stores parameter, local vars and the next index on the local variable table, which use for aload_i, astore_i,... + HashMap paramsAndLocals;// = new HashMap<>(); + byte[] bytecode; + HashMap classFiles; + + public BytecodeGen(HashMap classFiles) { + this.classFiles = classFiles; + paramsAndLocals = new HashMap<>(); + } + + @Override + public void visit(SourceFile sourceFile) { + for(ClassOrInterface cl : sourceFile.getClasses()) { + BytecodeGen classGen = new BytecodeGen(classFiles); + cl.accept(classGen); + classGen.writeClass(cl.getClassName().toString()); + } + } + + private void writeClass(String name) { + bytecode = cw.toByteArray(); + classFiles.put(name, bytecode); + + } + + public HashMap getClassFiles() { + return classFiles; + } + @Override + public void visit(ClassOrInterface classOrInterface) { + className = classOrInterface.getClassName().toString(); + // access flages?? + cw.visit(Opcodes.V1_8, classOrInterface.getModifiers()+Opcodes.ACC_SUPER, classOrInterface.getClassName().toString() + , null, classOrInterface.getSuperClass().toString(), null); + + // for each field in the class + for(Field f : classOrInterface.getFieldDecl()) { + System.out.println("get Fields"); + System.out.println(f.getName()); + f.accept(this); + } + + for(Constructor c : classOrInterface.getConstructors()) { + c.accept(this); + } + + for(Method m : classOrInterface.getMethods()) { + m.accept(this); + } + cw.visitSource(classOrInterface.getClassName().toString()+".jav", null); + } + + @Override + public void visit(Constructor field) { + Descriptor desc = new Descriptor(field); + MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "", desc.getDesc(), null, null); + mv.visitCode(); + System.out.println("-----Constructor-----"); + BytecodeGenMethod gen = new BytecodeGenMethod(className,field, mv,paramsAndLocals,desc.getDesc(),cw); + + mv.visitInsn(Opcodes.RETURN); + mv.visitMaxs(0, 0); + mv.visitEnd(); + } + + @Override + public void visit(Method method) { + method.getParameterList().accept(this); + Descriptor methDesc = new Descriptor(method); + System.out.println("-----Method-----"); + MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, method.getName(), methDesc.getDesc(), null, null); + mv.visitCode(); + + BytecodeGenMethod gen = new BytecodeGenMethod(className,method, mv,paramsAndLocals,methDesc.getDesc(),cw); + mv.visitMaxs(0, 0); + mv.visitEnd(); + } + + @Override + public void visit(ParameterList formalParameters) { + Iterator itr = formalParameters.iterator(); + int i = 1; + while(itr.hasNext()) { + FormalParameter fp = itr.next(); + paramsAndLocals.put(fp.getName(), i); + fp.accept(this); + i++; + } + } + + @Override + public void visit(FormalParameter formalParameter) { + formalParameter.getType().accept(this); + } + + @Override + public void visit(RefType refType) { + type = "L"+refType.toString()+";"; + } + + @Override + public void visit(SuperWildcardType superWildcardType) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(TypePlaceholder typePlaceholder) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(ExtendsWildcardType extendsWildcardType) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(GenericRefType genericRefType) { + // TODO Auto-generated method stub + + } + + // ?? + @Override + public void visit(FieldVar fieldVar) { + System.out.println("in fieldvar"); +// cw.newField(fieldVar.receiver.toString(), fieldVar.fieldVarName.toString(), fieldVar.getType().toString()); + FieldVisitor fv = cw.visitField(Opcodes.ACC_PRIVATE, fieldVar.fieldVarName, "L"+fieldVar.getType()+";", null, null); + fv.visitEnd(); + } + + // access flages?? modifiers + @Override + public void visit(Field field) { + System.out.println("in field"); + FieldVisitor fv = cw.visitField(Opcodes.ACC_PRIVATE, field.getName(), "L"+field.getType().toString().replace(".", "/")+";", null, null); + fv.visitEnd(); + } + + @Override + public void visit(LambdaExpression lambdaExpression) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(Assign assign) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(Binary binary) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(Block block) { + // TODO Auto-generated method stub + + } + + @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(ForStmt forStmt) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(IfStmt ifStmt) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(InstanceOf instanceOf) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(LocalVar localVar) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(LocalVarDecl localVarDecl) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(MethodCall methodCall) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(NewClass methodCall) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(NewArray newArray) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(Receiver receiver) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(Return aReturn) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(ReturnVoid aReturn) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(StaticClassName staticClassName) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(Super aSuper) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(This aThis) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(UnaryPlus unaryPlus) { + // TODO Auto-generated method stub + + } + + @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) { + // TODO Auto-generated method stub + + } + // ??? + @Override + public void visit(Literal literal) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(ArgumentList argumentList) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(GenericTypeVar genericTypeVar) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(GenericDeclarationList genericTypeVars) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(AssignToField assignLeftSide) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(AssignToLocal assignLeftSide) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(SuperCall superCall) { + // TODO Auto-generated method stub + + } + +} diff --git a/src/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java b/src/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java new file mode 100644 index 000000000..c65e691ca --- /dev/null +++ b/src/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java @@ -0,0 +1,360 @@ +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 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 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 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(".", "/"), "", 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()); + } + +} diff --git a/src/de/dhbwstuttgart/bytecode/Descriptor.java b/src/de/dhbwstuttgart/bytecode/Descriptor.java new file mode 100644 index 000000000..41f7ab5db --- /dev/null +++ b/src/de/dhbwstuttgart/bytecode/Descriptor.java @@ -0,0 +1,54 @@ +package de.dhbwstuttgart.bytecode; + +import java.awt.List; +import java.util.Iterator; + +import de.dhbwstuttgart.syntaxtree.Constructor; +import de.dhbwstuttgart.syntaxtree.FormalParameter; +import de.dhbwstuttgart.syntaxtree.Method; +import de.dhbwstuttgart.syntaxtree.statement.ArgumentList; +import de.dhbwstuttgart.syntaxtree.statement.Expression; +import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric; + +public class Descriptor { + String desc; + + public Descriptor(Method method) { + desc = "("; + Iterator itr = method.getParameterList().iterator(); + while(itr.hasNext()) { + FormalParameter fp = itr.next(); + desc = desc + "L"+fp.getType().toString().replace(".", "/") + ";"; + } + if(method.getReturnType().toString().equals("void")){ + desc = desc + ")V"; + }else { + desc = desc + ")" + "L"+method.getReturnType().toString().replace(".", "/")+";"; + } + + } + + public Descriptor(Constructor constructor) { + desc = "("; + Iterator itr = constructor.getParameterList().iterator(); + while(itr.hasNext()) { + FormalParameter fp = itr.next(); + desc = desc + "L"+fp.getType().toString().replace(".", "/") + ";"; + } + desc = desc + ")V"; + } + + public Descriptor(ArgumentList argList, RefTypeOrTPHOrWildcardOrGeneric returnType) { + desc = "("; + for(Expression e : argList.getArguments()) { + desc = desc + "L"+e.getType().toString().replace(".", "/") + ";"; + } + desc = desc + ")"+returnType.toString(); + + } + + public String getDesc() { + return this.desc; + } + +} diff --git a/src/de/dhbwstuttgart/bytecode/Test.java b/src/de/dhbwstuttgart/bytecode/Test.java new file mode 100644 index 000000000..baa707e7c --- /dev/null +++ b/src/de/dhbwstuttgart/bytecode/Test.java @@ -0,0 +1,129 @@ +package de.dhbwstuttgart.bytecode; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.lang.invoke.CallSite; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.net.URL; +import java.net.URLClassLoader; + +import org.objectweb.asm.ClassReader; +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; + +public class Test { + private static final String rootDirectory = System.getProperty("user.dir")+"/bin/de/dhbwstuttgart/bytecode/"; + protected static ClassLoader getClassLoader() throws Exception{ + File file = new File(rootDirectory); + URL url = file.toURI().toURL(); + URL[] urls = new URL[]{url}; + System.out.println(urls[0]); + return new URLClassLoader(urls); + } + + public static void main(String[] args) { + // Test Lambda + ClassWriter cw =new ClassWriter(ClassWriter.COMPUTE_MAXS); + cw.visit(Opcodes.V1_8, Opcodes.ACC_PUBLIC+Opcodes.ACC_SUPER, "TestClass", null, "java/lang/Object", null); + + // Create Constructor + MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "", "(Ljava/lang/Boolean;)V", null, null); + mv.visitVarInsn(Opcodes.ALOAD, 0); + + mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object", "", "()V"); + +// mv.visitMethodInsn(INVOKEDYNAMIC, "#0", "run", "()Ljava/lang/Runnable"); + + MethodType mt = MethodType.methodType(CallSite.class, MethodHandles.Lookup.class, + String.class, MethodType.class); + + Handle bootstrap = new Handle(Opcodes.H_INVOKESTATIC, "java/lang/invoke/LambdaMetafactory", + "metafactory", mt.toMethodDescriptorString()); + + mv.visitInvokeDynamicInsn("run", "()Ljava/lang/Runnable;", bootstrap); + + mv.visitVarInsn(Opcodes.ASTORE, 1); + mv.visitVarInsn(Opcodes.ALOAD, 1); + mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, "java/lang/Runnable", "run", "()V"); + mv.visitInsn(Opcodes.RETURN); + mv.visitMaxs(1, 2); + mv.visitEnd(); + + cw.visitEnd(); + + byte[] b = cw.toByteArray(); + + +// Test if statement +/* ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES|ClassWriter.COMPUTE_MAXS); + + cw.visit(Opcodes.V1_8, Opcodes.ACC_PUBLIC+Opcodes.ACC_SUPER, "TestIf", null, "java/lang/Object", null); + MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "", "(Ljava/lang/Boolean;)V", null, null); + mv.visitCode(); + +// Label l0 = new Label(); +// mv.visitLabel(l0); + + mv.visitVarInsn(Opcodes.ALOAD, 0); + + mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object", "", "()V"); + +// Label l1 = new Label(); +// mv.visitLabel(l1); + mv.visitVarInsn(Opcodes.ALOAD, 1); + mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Boolean", "booleanValue", "()Z"); + + Label label = new Label(); + mv.visitJumpInsn(Opcodes.IFEQ, label); + + mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;"); + mv.visitLdcInsn("1"); + mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V"); + + Label endLabel = new Label(); + mv.visitJumpInsn(Opcodes.GOTO, endLabel); + + mv.visitLabel(label); + mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;"); + mv.visitLdcInsn("0"); + mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V"); + + + + mv.visitLabel(endLabel); + mv.visitInsn(Opcodes.RETURN); + +// Label l2 = new Label(); +// mv.visitLabel(l2); + +// mv.visitLocalVariable("this", "LTestIf;", null, l0, l2, 0); +// mv.visitLocalVariable("b", "Ljava/lang/Boolean;", null, l0, l2, 1); + mv.visitMaxs(2, 2); + mv.visitEnd(); + + cw.visitEnd(); + byte[] b = cw.toByteArray(); +*/ + FileOutputStream output; + + try { + output = new FileOutputStream(new File(System.getProperty("user.dir")+"/testBytecode/TestClass.class")); + output.write(b); + output.close(); + } catch (FileNotFoundException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + } +} diff --git a/src/de/dhbwstuttgart/bytecode/TestClass.java b/src/de/dhbwstuttgart/bytecode/TestClass.java new file mode 100644 index 000000000..168447af7 --- /dev/null +++ b/src/de/dhbwstuttgart/bytecode/TestClass.java @@ -0,0 +1,8 @@ +package de.dhbwstuttgart.bytecode; + +public class TestClass { + public TestClass() { + Runnable lam = () -> System.out.println("lambda"); + lam.run(); + } +} diff --git a/src/de/dhbwstuttgart/bytecode/TestIf.java b/src/de/dhbwstuttgart/bytecode/TestIf.java new file mode 100644 index 000000000..36e3c7065 --- /dev/null +++ b/src/de/dhbwstuttgart/bytecode/TestIf.java @@ -0,0 +1,11 @@ +package de.dhbwstuttgart.bytecode; + +public class TestIf { + public TestIf(Boolean b) { + if(b) { + System.out.println("1"); + }else { + System.out.println("0"); + } + } +} diff --git a/src/de/dhbwstuttgart/parser/SyntaxTreeGenerator/SyntaxTreeGenerator.java b/src/de/dhbwstuttgart/parser/SyntaxTreeGenerator/SyntaxTreeGenerator.java index 2556a3dcd..172cdbcf1 100644 --- a/src/de/dhbwstuttgart/parser/SyntaxTreeGenerator/SyntaxTreeGenerator.java +++ b/src/de/dhbwstuttgart/parser/SyntaxTreeGenerator/SyntaxTreeGenerator.java @@ -182,9 +182,9 @@ public class SyntaxTreeGenerator{ block = stmtGen.convert(body.block()); } if(parentClass.equals(new JavaClassName(name))){ - return new Constructor(name, retType, modifiers, parameterList, block, gtvDeclarations, header.getStart(), fieldInitializations, superClass); + return new Constructor(modifiers, name, retType, modifiers, parameterList, block, gtvDeclarations, header.getStart(), fieldInitializations, superClass); }else{ - return new Method(name, retType, modifiers, parameterList,block, gtvDeclarations, header.getStart()); + return new Method(modifiers, name, retType, modifiers, parameterList,block, gtvDeclarations, header.getStart()); } } @@ -259,12 +259,15 @@ public class SyntaxTreeGenerator{ return ret; } + /** + * http://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.8.9 + */ private Constructor generateStandardConstructor(String className, JavaClassName parentClass, RefType superClass, GenericDeclarationList classGenerics, Token offset){ RefType classType = ClassOrInterface.generateTypeOfClass(reg.getName(className), classGenerics, offset); int modifiers = 0; ParameterList params = new ParameterList(new ArrayList<>(), offset); Block block = new Block(new ArrayList<>(), offset); - return new Constructor(className, classType, modifiers, params, block, classGenerics, offset, fieldInitializations, superClass); + return new Constructor(Modifier.PUBLIC, className, classType, modifiers, params, block, classGenerics, offset, fieldInitializations, superClass); } private RefType convert(Java8Parser.SuperclassContext superclass) { diff --git a/src/de/dhbwstuttgart/syntaxtree/Constructor.java b/src/de/dhbwstuttgart/syntaxtree/Constructor.java index 3423e3775..2fdfb04e9 100644 --- a/src/de/dhbwstuttgart/syntaxtree/Constructor.java +++ b/src/de/dhbwstuttgart/syntaxtree/Constructor.java @@ -14,9 +14,9 @@ public class Constructor extends Method { //TODO: Constructor braucht ein super-Statement - public Constructor(String name, RefTypeOrTPHOrWildcardOrGeneric returnType, int modifiers, ParameterList parameterList, Block codeInsideConstructor, + public Constructor(int modifier, String name, RefTypeOrTPHOrWildcardOrGeneric returnType, int modifiers, ParameterList parameterList, Block codeInsideConstructor, GenericDeclarationList gtvDeclarations, Token offset, List fieldInitializations, RefType superClass) { - super(name, returnType, modifiers, parameterList, prepareBlock(codeInsideConstructor,fieldInitializations, superClass), gtvDeclarations, offset); + super(modifier, name, returnType, modifiers, parameterList, prepareBlock(codeInsideConstructor,fieldInitializations, superClass), gtvDeclarations, offset); } diff --git a/src/de/dhbwstuttgart/syntaxtree/Method.java b/src/de/dhbwstuttgart/syntaxtree/Method.java index 9e81605d1..3686fb4ee 100644 --- a/src/de/dhbwstuttgart/syntaxtree/Method.java +++ b/src/de/dhbwstuttgart/syntaxtree/Method.java @@ -29,7 +29,7 @@ public class Method extends Field implements IItemWithOffset private ExceptionList exceptionlist; private GenericDeclarationList generics; - public Method(String name, RefTypeOrTPHOrWildcardOrGeneric returnType, int modifiers, ParameterList parameterList, Block block, + public Method(int modifier, String name, RefTypeOrTPHOrWildcardOrGeneric returnType, int modifiers, ParameterList parameterList, Block block, GenericDeclarationList gtvDeclarations, Token offset) { super(name, returnType, modifiers, offset); this.parameterlist = parameterList; diff --git a/src/de/dhbwstuttgart/syntaxtree/factory/ASTFactory.java b/src/de/dhbwstuttgart/syntaxtree/factory/ASTFactory.java index ec1e786cf..b3f628a7c 100644 --- a/src/de/dhbwstuttgart/syntaxtree/factory/ASTFactory.java +++ b/src/de/dhbwstuttgart/syntaxtree/factory/ASTFactory.java @@ -83,7 +83,7 @@ public class ASTFactory { return null; } - return new de.dhbwstuttgart.syntaxtree.Constructor(name,returnType, modifier, parameterList, block, gtvDeclarations, offset, new ArrayList<>(), + return new de.dhbwstuttgart.syntaxtree.Constructor(constructor.getModifiers(), name,returnType, modifier, parameterList, block, gtvDeclarations, offset, new ArrayList<>(), createType(inClass.getSuperclass())); } @@ -107,7 +107,7 @@ public class ASTFactory { Token offset = new NullToken(); int modifier = jreMethod.getModifiers(); - return new Method(name,returnType, modifier, parameterList, block, gtvDeclarations, offset); + return new Method(jreMethod.getModifiers(), name,returnType, modifier, parameterList, block, gtvDeclarations, offset); } public static GenericDeclarationList createGenerics(TypeVariable[] typeParameters, Class context, String methodName){ diff --git a/src/de/dhbwstuttgart/syntaxtree/statement/ArgumentList.java b/src/de/dhbwstuttgart/syntaxtree/statement/ArgumentList.java index 75c92370d..c4b8367dc 100644 --- a/src/de/dhbwstuttgart/syntaxtree/statement/ArgumentList.java +++ b/src/de/dhbwstuttgart/syntaxtree/statement/ArgumentList.java @@ -2,6 +2,7 @@ package de.dhbwstuttgart.syntaxtree.statement; import de.dhbwstuttgart.syntaxtree.ASTVisitor; +import de.dhbwstuttgart.syntaxtree.StatementVisitor; import de.dhbwstuttgart.syntaxtree.SyntaxTreeNode; import org.antlr.v4.runtime.Token; @@ -24,4 +25,8 @@ public class ArgumentList extends SyntaxTreeNode public void accept(ASTVisitor visitor) { visitor.visit(this); } + + public void accept(StatementVisitor visitor) { + visitor.visit(this); + } } diff --git a/test/bytecode/JavaTXCompilerTest.java b/test/bytecode/JavaTXCompilerTest.java new file mode 100644 index 000000000..fbbea261c --- /dev/null +++ b/test/bytecode/JavaTXCompilerTest.java @@ -0,0 +1,72 @@ +package bytecode; + +import de.dhbwstuttgart.bytecode.BytecodeGen; +import de.dhbwstuttgart.core.JavaTXCompiler; +import de.dhbwstuttgart.exceptions.DebugException; +import de.dhbwstuttgart.syntaxtree.SourceFile; +import org.junit.Test; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Set; + +import static org.junit.Assert.*; + +public class JavaTXCompilerTest { + + private static final String rootDirectory = System.getProperty("user.dir")+"/test/javFiles/"; + private static final List filesToTest = new ArrayList<>(); + + @Test + public void test() throws IOException, java.lang.ClassNotFoundException { + filesToTest.add(new File(rootDirectory+"EmptyClass.jav")); + JavaTXCompiler compiler = new JavaTXCompiler(filesToTest); + for(File f : filesToTest){ + String content = readFile(f.getPath(), StandardCharsets.UTF_8); + HashMap bytecode = this.getBytecode(compiler.sourceFiles.get(f)); + this.writeClassFile(bytecode, "EmptyClass"); + } + + } + + + public HashMap getBytecode(SourceFile sf) { + HashMap classFiles = new HashMap<>(); + BytecodeGen bytecodeGen = new BytecodeGen(classFiles); + bytecodeGen.visit(sf); + return bytecodeGen.getClassFiles(); + } + + public void writeClassFile(HashMap classFiles, String name) { + FileOutputStream output; + byte[] bytecode = classFiles.get(name); + try { + System.out.println("generating .class file"); + output = new FileOutputStream(new File(System.getProperty("user.dir") + "/testBytecode/" +name+".class")); + output.write(bytecode); + output.close(); + System.out.println(".class file generated"); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + static String readFile(String path, Charset encoding) + throws IOException + { + byte[] encoded = Files.readAllBytes(Paths.get(path)); + return new String(encoded, encoding); + } + +} \ No newline at end of file diff --git a/test/javFiles/test1.jav b/test/javFiles/test1.jav new file mode 100644 index 000000000..4b34948e9 --- /dev/null +++ b/test/javFiles/test1.jav @@ -0,0 +1,7 @@ +class Faculty { + + int a; + m (int x) { + return a+x; + } +} diff --git a/test/test.iml b/test/test.iml deleted file mode 100644 index a6c28e92b..000000000 --- a/test/test.iml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file