From 43f017a224cabf7d428029ae645a2a322e3819b7 Mon Sep 17 00:00:00 2001 From: Fayez Abu Alia Date: Wed, 23 Aug 2017 17:26:59 +0200 Subject: [PATCH 1/5] Bytecode TEst --- .classpath | 1 + src/.DS_Store | Bin 0 -> 6148 bytes src/de/.DS_Store | Bin 0 -> 6148 bytes src/de/dhbwstuttgart/bytecode/Test.java | 129 ++++++++++++++++++ src/de/dhbwstuttgart/bytecode/TestClass.java | 8 ++ src/de/dhbwstuttgart/bytecode/TestIf.java | 11 ++ .../dhbwstuttgart/core/ConsoleInterface.java | 3 - src/de/dhbwstuttgart/core/JavaTXCompiler.java | 1 - .../parser/ClassNotFoundException.java | 4 - test/.DS_Store | Bin 0 -> 6148 bytes test/javFiles/test1.jav | 7 + test/parser/FeatherWeightJavaTest.java | 1 - test/parser/FieldTest.java | 1 - test/typeinference/JavaTXCompilerTest.java | 1 - 14 files changed, 156 insertions(+), 11 deletions(-) create mode 100644 src/.DS_Store create mode 100644 src/de/.DS_Store create mode 100644 src/de/dhbwstuttgart/bytecode/Test.java create mode 100644 src/de/dhbwstuttgart/bytecode/TestClass.java create mode 100644 src/de/dhbwstuttgart/bytecode/TestIf.java delete mode 100644 src/de/dhbwstuttgart/parser/ClassNotFoundException.java create mode 100644 test/.DS_Store create mode 100644 test/javFiles/test1.jav diff --git a/.classpath b/.classpath index bebca6c3..22ddf0a0 100644 --- a/.classpath +++ b/.classpath @@ -17,5 +17,6 @@ + diff --git a/src/.DS_Store b/src/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..9981f41022baf2b38aab1cef992fa01a00ee1547 GIT binary patch literal 6148 zcmeH~Jr2S!425mzfW*>~F$)La1`&c2Z~+8mLt;SeIXcfj3>0Qmp=ZhdVmDUXH#D_~ z==L#eM0ycfz>TuDFfv6xlR+-S{d_&$ZdWU$&5~Av_cFTv+DB3WDnJFO02QDD(@`Lg z^2KsGkHjaT0#slk3fT9dz>PK8g8u11@DTv)PskGnRa-YW=-UzAegcr#QM`h?;d-$JSd%S?3XDGjE&~G<_^ARH(%^L_W3-BrYhbe?g-fHQr-`z-tSfOA*q@qsk>6e z0Vyz5;69gYum8{VKl=YENh>KJ1#U_KTWnvp8$PLO>+Eq}Ya4w>_ndFK8|Ojc5apN{ j<(LaE$B&VedClkC?+VAnpfetHqJ9Qk7nv0JZv}n;s*)El literal 0 HcmV?d00001 diff --git a/src/de/dhbwstuttgart/bytecode/Test.java b/src/de/dhbwstuttgart/bytecode/Test.java new file mode 100644 index 00000000..baa707e7 --- /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 00000000..168447af --- /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 00000000..36e3c706 --- /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/core/ConsoleInterface.java b/src/de/dhbwstuttgart/core/ConsoleInterface.java index 7c574456..c86afbe3 100755 --- a/src/de/dhbwstuttgart/core/ConsoleInterface.java +++ b/src/de/dhbwstuttgart/core/ConsoleInterface.java @@ -1,8 +1,5 @@ package de.dhbwstuttgart.core; - -import de.dhbwstuttgart.parser.ClassNotFoundException; - import java.io.File; import java.io.IOException; import java.util.*; diff --git a/src/de/dhbwstuttgart/core/JavaTXCompiler.java b/src/de/dhbwstuttgart/core/JavaTXCompiler.java index 36cb6617..34e821f1 100644 --- a/src/de/dhbwstuttgart/core/JavaTXCompiler.java +++ b/src/de/dhbwstuttgart/core/JavaTXCompiler.java @@ -1,7 +1,6 @@ package de.dhbwstuttgart.core; import de.dhbwstuttgart.exceptions.DebugException; -import de.dhbwstuttgart.parser.ClassNotFoundException; import de.dhbwstuttgart.parser.JavaTXParser; import de.dhbwstuttgart.syntaxtree.ClassOrInterface; import de.dhbwstuttgart.syntaxtree.SourceFile; diff --git a/src/de/dhbwstuttgart/parser/ClassNotFoundException.java b/src/de/dhbwstuttgart/parser/ClassNotFoundException.java deleted file mode 100644 index 08609467..00000000 --- a/src/de/dhbwstuttgart/parser/ClassNotFoundException.java +++ /dev/null @@ -1,4 +0,0 @@ -package de.dhbwstuttgart.parser; -public class ClassNotFoundException extends Exception{ - -} diff --git a/test/.DS_Store b/test/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..732178d7d20ed2b10df9fbc96895a227e2961738 GIT binary patch literal 6148 zcmeHK%TB{U3>-rb5fxI89QPOagQzO}06#!UgH#j|L?}{kx$)bKAE`irD+gpt_H4YK zU1bh&3_#Y0-8HZRP|+3fpC8+yFrIII3Sq1+2>F_8C2Jn?r! z(>?Tkr?d)B+c}C0ITdo?kQ<wRFsw3Zw$5z)1o9J`}oQ9XLALr-Q*p0OEpaGp=oxAQnv!>%h^G8Jaki=v0Xj zL!8chiMl#)baXl-h7XCGB_sX!|5 zPZf~G=5Dj*%SCUUy{7isLcga^##$?9uvSd8R?G)&#aCbIimtg|2ab+LXWr<<{1H%H K(o%uHP~Z~^B_v<~ literal 0 HcmV?d00001 diff --git a/test/javFiles/test1.jav b/test/javFiles/test1.jav new file mode 100644 index 00000000..4b34948e --- /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/parser/FeatherWeightJavaTest.java b/test/parser/FeatherWeightJavaTest.java index 12db947f..84113e0c 100644 --- a/test/parser/FeatherWeightJavaTest.java +++ b/test/parser/FeatherWeightJavaTest.java @@ -1,6 +1,5 @@ package parser; -import de.dhbwstuttgart.parser.ClassNotFoundException; import de.dhbwstuttgart.parser.JavaTXParser; import de.dhbwstuttgart.syntaxtree.ClassOrInterface; import de.dhbwstuttgart.syntaxtree.Field; diff --git a/test/parser/FieldTest.java b/test/parser/FieldTest.java index 464e2007..134943e0 100644 --- a/test/parser/FieldTest.java +++ b/test/parser/FieldTest.java @@ -1,6 +1,5 @@ package parser; -import de.dhbwstuttgart.parser.ClassNotFoundException; import de.dhbwstuttgart.parser.JavaTXParser; import de.dhbwstuttgart.syntaxtree.ClassOrInterface; import de.dhbwstuttgart.syntaxtree.Field; diff --git a/test/typeinference/JavaTXCompilerTest.java b/test/typeinference/JavaTXCompilerTest.java index e774e4d4..dbd924a4 100644 --- a/test/typeinference/JavaTXCompilerTest.java +++ b/test/typeinference/JavaTXCompilerTest.java @@ -2,7 +2,6 @@ package typeinference; import de.dhbwstuttgart.core.JavaTXCompiler; import de.dhbwstuttgart.exceptions.DebugException; -import de.dhbwstuttgart.parser.ClassNotFoundException; import de.dhbwstuttgart.syntaxtree.SourceFile; import de.dhbwstuttgart.syntaxtree.SyntaxTreeNode; import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; From d245aa736779a241f81b5a4b42128178e2dac7b3 Mon Sep 17 00:00:00 2001 From: JanUlrich Date: Wed, 30 Aug 2017 17:20:59 +0200 Subject: [PATCH 2/5] Added Modifier to Method --- .../parser/SyntaxTreeGenerator/SyntaxTreeGenerator.java | 9 ++++++--- src/de/dhbwstuttgart/syntaxtree/Constructor.java | 4 ++-- src/de/dhbwstuttgart/syntaxtree/Method.java | 2 +- src/de/dhbwstuttgart/syntaxtree/factory/ASTFactory.java | 4 ++-- 4 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/de/dhbwstuttgart/parser/SyntaxTreeGenerator/SyntaxTreeGenerator.java b/src/de/dhbwstuttgart/parser/SyntaxTreeGenerator/SyntaxTreeGenerator.java index dd6fe176..f16fc404 100644 --- a/src/de/dhbwstuttgart/parser/SyntaxTreeGenerator/SyntaxTreeGenerator.java +++ b/src/de/dhbwstuttgart/parser/SyntaxTreeGenerator/SyntaxTreeGenerator.java @@ -233,9 +233,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()); } } @@ -310,12 +310,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 3423e377..2fdfb04e 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 67d81cb4..7f74fed1 100755 --- 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, TypeScope 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 5dba40a1..088af7c6 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){ From 9a233e437b09d72b57ccedb1caf7de0137c71f61 Mon Sep 17 00:00:00 2001 From: Fayez Abu Alia Date: Wed, 30 Aug 2017 18:08:05 +0200 Subject: [PATCH 3/5] bytecode --- .../dhbwstuttgart/bytecode/BytecodeGen.java | 414 ++++++++++++++++++ .../bytecode/BytecodeGenMethod.java | 242 ++++++++++ test/bytecode/JavaTXCompilerTest.java | 81 ++++ 3 files changed, 737 insertions(+) create mode 100644 src/de/dhbwstuttgart/bytecode/BytecodeGen.java create mode 100644 src/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java create mode 100644 test/bytecode/JavaTXCompilerTest.java diff --git a/src/de/dhbwstuttgart/bytecode/BytecodeGen.java b/src/de/dhbwstuttgart/bytecode/BytecodeGen.java new file mode 100644 index 00000000..4919918b --- /dev/null +++ b/src/de/dhbwstuttgart/bytecode/BytecodeGen.java @@ -0,0 +1,414 @@ +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 org.objectweb.asm.Type; + +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; + // 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; + } + + @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) { + // access flages?? + cw.visit(Opcodes.V1_8, classOrInterface.getModifiers(), classOrInterface.getClassName().toString() + , null, classOrInterface.getSuperClass().toString(), null); + // for each field in the class + for(Field f : classOrInterface.getFieldDecl()) { + 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) { + String methDesc = getConsDesc(field); + MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "", methDesc, null, null); + mv.visitCode(); + + BytecodeGenMethod gen = new BytecodeGenMethod(field, mv,paramsAndLocals,true); + + mv.visitInsn(Opcodes.RETURN); + mv.visitEnd(); + } + + private String getConsDesc(Constructor field) { + String methDesc; + methDesc = "("; + field.getParameterList().accept(this); + Iterator itr = field.getParameterList().iterator(); + while(itr.hasNext()) { + FormalParameter fp = itr.next(); + methDesc = methDesc + "L"+fp.getType().toString() + ";"; + } + methDesc = methDesc + ")V"; + return methDesc; + } + + @Override + public void visit(Method method) { +// ParameterList pl = method.getParameterList(); + String methDesc = getMethDesc(method); +// methDesc = "("; +// method.getParameterList().accept(this); +// methDesc = methDesc + ")" + method.getReturnType().toString(); + + // create method descriptor (p1,p2,...)RT +// String methDesc = "("; + +// Iterator itr = pl.iterator(); +// while(itr.hasNext()) { +// FormalParameter fp = itr.next(); +//// fp.getType().accept(this); +// methDesc = methDesc + "L"+fp.getType().toString() + ";"; +// i++; +// } +// methDesc = methDesc + ")" + method.getReturnType().toString(); + + MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, method.getName(), methDesc, null, null); + mv.visitCode(); + + BytecodeGenMethod gen = new BytecodeGenMethod(method, mv,paramsAndLocals,false); + + } + + private String getMethDesc(Method method) { + String methDesc; + methDesc = "("; + method.getParameterList().accept(this); + Iterator itr = method.getParameterList().iterator(); + while(itr.hasNext()) { + FormalParameter fp = itr.next(); + methDesc = methDesc + "L"+fp.getType().toString() + ";"; + } + methDesc = methDesc + ")" + method.getReturnType().toString(); + return methDesc; + } + + @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) { +// cw.newField(fieldVar.receiver.toString(), fieldVar.fieldVarName.toString(), fieldVar.getType().toString()); + } + + // access flages?? modifiers + @Override + public void visit(Field field) { + FieldVisitor fv = cw.visitField(Opcodes.ACC_PRIVATE, field.getName(), "L"+field.getType()+";", 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 00000000..8a1d1cb4 --- /dev/null +++ b/src/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java @@ -0,0 +1,242 @@ +package de.dhbwstuttgart.bytecode; + +import java.util.HashMap; + +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; + +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.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; + +public class BytecodeGenMethod implements StatementVisitor{ + + private Method m; + private MethodVisitor mv; + private HashMap paramsAndLocals = new HashMap<>(); + + public BytecodeGenMethod(Method m, MethodVisitor mv, HashMap paramsAndLocals, + boolean isConstructor) { + if(isConstructor) { + +// mv.visitVarInsn(Opcodes.ALOAD, 0); +// mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object", "", "()V"); + } + this.m = m; + this.mv = mv; + this.paramsAndLocals = paramsAndLocals; + this.m.block.accept(this); + + } + + @Override + public void visit(Block block) { + for(Statement stmt : block.getStatements()) { + stmt.accept(this); + } + } + + @Override + public void visit(SuperCall superCall) { + superCall.receiver.accept(this); + superCall.arglist.accept(this); + mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object", superCall.name, "()V"); + } + + // ?? + @Override + public void visit(LocalVar localVar) { + + } + // ?? + @Override + public void visit(LocalVarDecl localVarDecl) { + // TODO Auto-generated method stub + Integer i; + + } + // int c = 5;??? + @Override + public void visit(Assign assign) { + assign.rightSide.accept(this); +// int index = paramsAndLocals.get(assign.lefSide.getName()); +// mv.visitVarInsn(Opcodes.ASTORE, index); + } + + @Override + public void visit(Binary binary) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(LambdaExpression lambdaExpression) { + // 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(FieldVar fieldVar) { + // 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(MethodCall methodCall) { + + } + + @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) { + receiver.expr.accept(this); + } + + @Override + public void visit(Return aReturn) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(ReturnVoid aReturn) { + mv.visitInsn(Opcodes.RETURN); + } + + @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) { + mv.visitVarInsn(Opcodes.ALOAD, 0); + } + + @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(AssignToField assignLeftSide) { + // TODO Auto-generated method stub + + } + + @Override + public void visit(AssignToLocal assignLeftSide) { + // TODO Auto-generated method stub + + } + +} diff --git a/test/bytecode/JavaTXCompilerTest.java b/test/bytecode/JavaTXCompilerTest.java new file mode 100644 index 00000000..16e96e5a --- /dev/null +++ b/test/bytecode/JavaTXCompilerTest.java @@ -0,0 +1,81 @@ +package bytecode; + +import de.dhbwstuttgart.bytecode.BytecodeGen; +import de.dhbwstuttgart.core.JavaTXCompiler; +import de.dhbwstuttgart.exceptions.DebugException; +import de.dhbwstuttgart.syntaxtree.SourceFile; +import de.dhbwstuttgart.syntaxtree.SyntaxTreeNode; +import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; +import de.dhbwstuttgart.syntaxtree.visual.ASTPrinter; +import de.dhbwstuttgart.syntaxtree.visual.ASTTypePrinter; +import de.dhbwstuttgart.syntaxtree.visual.OutputGenerator; +import de.dhbwstuttgart.typedeployment.TypeInsert; +import de.dhbwstuttgart.typedeployment.TypeInsertFactory; +import de.dhbwstuttgart.typedeployment.TypeInsertPoint; +import de.dhbwstuttgart.typeinference.ResultSet; +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 extends JavaTXCompiler { + + 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")); + for(File f : filesToTest){ + SourceFile sf = this.parse(f); + String content = readFile(f.getPath(), StandardCharsets.UTF_8); + HashMap bytecode = this.getBytecode(sf); + 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 From 4c213eb3cfebdecfbed5fc088d8208eaae592e5b Mon Sep 17 00:00:00 2001 From: Fayez Abu Alia Date: Thu, 5 Oct 2017 18:25:52 +0200 Subject: [PATCH 4/5] generate bytecode --- .../dhbwstuttgart/bytecode/BytecodeGen.java | 82 +++----- .../bytecode/BytecodeGenMethod.java | 198 ++++++++++++++---- src/de/dhbwstuttgart/bytecode/Descriptor.java | 54 +++++ 3 files changed, 239 insertions(+), 95 deletions(-) create mode 100644 src/de/dhbwstuttgart/bytecode/Descriptor.java diff --git a/src/de/dhbwstuttgart/bytecode/BytecodeGen.java b/src/de/dhbwstuttgart/bytecode/BytecodeGen.java index 4919918b..6f0ac91e 100644 --- a/src/de/dhbwstuttgart/bytecode/BytecodeGen.java +++ b/src/de/dhbwstuttgart/bytecode/BytecodeGen.java @@ -9,7 +9,6 @@ import org.objectweb.asm.ClassWriter; import org.objectweb.asm.FieldVisitor; 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.*; @@ -54,13 +53,17 @@ public class BytecodeGen implements ASTVisitor { // 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<>(); + HashMap paramsAndLocals;// = new HashMap<>(); byte[] bytecode; HashMap classFiles; public BytecodeGen(HashMap classFiles) { this.classFiles = classFiles; + paramsAndLocals = new HashMap<>(); } @Override @@ -83,11 +86,15 @@ public class BytecodeGen implements ASTVisitor { } @Override public void visit(ClassOrInterface classOrInterface) { + className = classOrInterface.getClassName().toString(); // access flages?? - cw.visit(Opcodes.V1_8, classOrInterface.getModifiers(), classOrInterface.getClassName().toString() + 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); } @@ -103,69 +110,30 @@ public class BytecodeGen implements ASTVisitor { @Override public void visit(Constructor field) { - String methDesc = getConsDesc(field); - MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "", methDesc, null, null); + Descriptor desc = new Descriptor(field); + MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "", desc.getDesc(), null, null); mv.visitCode(); - - BytecodeGenMethod gen = new BytecodeGenMethod(field, mv,paramsAndLocals,true); + 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(); } - - private String getConsDesc(Constructor field) { - String methDesc; - methDesc = "("; - field.getParameterList().accept(this); - Iterator itr = field.getParameterList().iterator(); - while(itr.hasNext()) { - FormalParameter fp = itr.next(); - methDesc = methDesc + "L"+fp.getType().toString() + ";"; - } - methDesc = methDesc + ")V"; - return methDesc; - } @Override public void visit(Method method) { -// ParameterList pl = method.getParameterList(); - String methDesc = getMethDesc(method); -// methDesc = "("; -// method.getParameterList().accept(this); -// methDesc = methDesc + ")" + method.getReturnType().toString(); - - // create method descriptor (p1,p2,...)RT -// String methDesc = "("; - -// Iterator itr = pl.iterator(); -// while(itr.hasNext()) { -// FormalParameter fp = itr.next(); -//// fp.getType().accept(this); -// methDesc = methDesc + "L"+fp.getType().toString() + ";"; -// i++; -// } -// methDesc = methDesc + ")" + method.getReturnType().toString(); - - MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, method.getName(), methDesc, null, null); + 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(method, mv,paramsAndLocals,false); - + BytecodeGenMethod gen = new BytecodeGenMethod(className,method, mv,paramsAndLocals,methDesc.getDesc(),cw); + mv.visitMaxs(0, 0); + mv.visitEnd(); } - private String getMethDesc(Method method) { - String methDesc; - methDesc = "("; - method.getParameterList().accept(this); - Iterator itr = method.getParameterList().iterator(); - while(itr.hasNext()) { - FormalParameter fp = itr.next(); - methDesc = methDesc + "L"+fp.getType().toString() + ";"; - } - methDesc = methDesc + ")" + method.getReturnType().toString(); - return methDesc; - } - @Override public void visit(ParameterList formalParameters) { Iterator itr = formalParameters.iterator(); @@ -215,13 +183,17 @@ public class BytecodeGen implements ASTVisitor { // ?? @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) { - FieldVisitor fv = cw.visitField(Opcodes.ACC_PRIVATE, field.getName(), "L"+field.getType()+";", null, null); + System.out.println("in field"); + FieldVisitor fv = cw.visitField(Opcodes.ACC_PRIVATE, field.getName(), "L"+field.getType().toString().replace(".", "/")+";", null, null); fv.visitEnd(); } diff --git a/src/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java b/src/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java index 8a1d1cb4..c65e691c 100644 --- a/src/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java +++ b/src/de/dhbwstuttgart/bytecode/BytecodeGenMethod.java @@ -1,9 +1,18 @@ 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; @@ -16,6 +25,7 @@ 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; @@ -38,31 +48,63 @@ 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; - public BytecodeGenMethod(Method m, MethodVisitor mv, HashMap paramsAndLocals, - boolean isConstructor) { - if(isConstructor) { + //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) { -// mv.visitVarInsn(Opcodes.ALOAD, 0); -// mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object", "", "()V"); - } + 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"); } } @@ -70,39 +112,73 @@ public class BytecodeGenMethod implements StatementVisitor{ public void visit(SuperCall superCall) { superCall.receiver.accept(this); superCall.arglist.accept(this); - mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object", superCall.name, "()V"); +// 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) { - // TODO Auto-generated method stub - Integer i; - +// Integer i; + paramsAndLocals.put(localVarDecl.getName(), paramsAndLocals.size()+1); + System.out.println("In localVarDecl"); } - // int c = 5;??? + @Override public void visit(Assign assign) { - assign.rightSide.accept(this); -// int index = paramsAndLocals.get(assign.lefSide.getName()); -// mv.visitVarInsn(Opcodes.ASTORE, index); + 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) { - // TODO Auto-generated method stub - + System.out.println("++ In Binary: "); } @Override public void visit(LambdaExpression lambdaExpression) { - // TODO Auto-generated method stub + 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 @@ -119,8 +195,19 @@ public class BytecodeGenMethod implements StatementVisitor{ @Override public void visit(FieldVar fieldVar) { - // TODO Auto-generated method stub + 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 @@ -131,8 +218,7 @@ public class BytecodeGenMethod implements StatementVisitor{ @Override public void visit(IfStmt ifStmt) { - // TODO Auto-generated method stub - + System.out.println("++ IF-Statment: "); } @Override @@ -143,13 +229,38 @@ public class BytecodeGenMethod implements StatementVisitor{ @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) { - // TODO Auto-generated method stub + 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 @@ -160,13 +271,14 @@ public class BytecodeGenMethod implements StatementVisitor{ @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) { - // TODO Auto-generated method stub - + mv.visitInsn(Opcodes.ARETURN); } @Override @@ -176,25 +288,27 @@ public class BytecodeGenMethod implements StatementVisitor{ @Override public void visit(StaticClassName staticClassName) { - // TODO Auto-generated method stub - + 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) { - // TODO Auto-generated method stub - + 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) { - // TODO Auto-generated method stub - + System.out.println("++ In UnaryPlus: "); } @Override @@ -211,32 +325,36 @@ public class BytecodeGenMethod implements StatementVisitor{ @Override public void visit(Null aNull) { - // TODO Auto-generated method stub - + mv.visitInsn(Opcodes.ACONST_NULL); } @Override public void visit(Literal literal) { - // TODO Auto-generated method stub - + // value? + mv.visitLdcInsn(literal.getType().toString()); } @Override public void visit(ArgumentList argumentList) { - // TODO Auto-generated method stub - + for(Expression al : argumentList.getArguments()) { + al.accept(this); + } } @Override public void visit(AssignToField assignLeftSide) { - // TODO Auto-generated method stub - + // 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) { - // TODO Auto-generated method stub - + 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 00000000..41f7ab5d --- /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; + } + +} From 6738eecdf37ce8827512c7ac8d254341de7fbf9d Mon Sep 17 00:00:00 2001 From: JanUlrich Date: Thu, 5 Oct 2017 19:21:30 +0200 Subject: [PATCH 5/5] Merge --- .gitignore | 3 ++- .../Maven__org_ow2_asm_asm_all_6_0_BETA.xml | 13 +++++++++++++ JavaTXcompiler.iml | 1 + pom.xml | 5 +++++ .../syntaxtree/statement/ArgumentList.java | 5 +++++ test/bytecode/JavaTXCompilerTest.java | 15 +++------------ 6 files changed, 29 insertions(+), 13 deletions(-) create mode 100644 .idea/libraries/Maven__org_ow2_asm_asm_all_6_0_BETA.xml diff --git a/.gitignore b/.gitignore index c71c9ed2..77e5f2f1 100644 --- a/.gitignore +++ b/.gitignore @@ -13,4 +13,5 @@ bin # IDEs .classpath - +*.iml +.idea/ diff --git a/.idea/libraries/Maven__org_ow2_asm_asm_all_6_0_BETA.xml b/.idea/libraries/Maven__org_ow2_asm_asm_all_6_0_BETA.xml new file mode 100644 index 00000000..20d5330e --- /dev/null +++ b/.idea/libraries/Maven__org_ow2_asm_asm_all_6_0_BETA.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/JavaTXcompiler.iml b/JavaTXcompiler.iml index 20953853..f53d2064 100644 --- a/JavaTXcompiler.iml +++ b/JavaTXcompiler.iml @@ -21,5 +21,6 @@ + \ No newline at end of file diff --git a/pom.xml b/pom.xml index fed9a769..7bbd8abd 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/de/dhbwstuttgart/syntaxtree/statement/ArgumentList.java b/src/de/dhbwstuttgart/syntaxtree/statement/ArgumentList.java index 75c92370..c4b8367d 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 index 16e96e5a..fbbea261 100644 --- a/test/bytecode/JavaTXCompilerTest.java +++ b/test/bytecode/JavaTXCompilerTest.java @@ -4,15 +4,6 @@ import de.dhbwstuttgart.bytecode.BytecodeGen; import de.dhbwstuttgart.core.JavaTXCompiler; import de.dhbwstuttgart.exceptions.DebugException; import de.dhbwstuttgart.syntaxtree.SourceFile; -import de.dhbwstuttgart.syntaxtree.SyntaxTreeNode; -import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder; -import de.dhbwstuttgart.syntaxtree.visual.ASTPrinter; -import de.dhbwstuttgart.syntaxtree.visual.ASTTypePrinter; -import de.dhbwstuttgart.syntaxtree.visual.OutputGenerator; -import de.dhbwstuttgart.typedeployment.TypeInsert; -import de.dhbwstuttgart.typedeployment.TypeInsertFactory; -import de.dhbwstuttgart.typedeployment.TypeInsertPoint; -import de.dhbwstuttgart.typeinference.ResultSet; import org.junit.Test; import java.io.File; @@ -30,7 +21,7 @@ import java.util.Set; import static org.junit.Assert.*; -public class JavaTXCompilerTest extends JavaTXCompiler { +public class JavaTXCompilerTest { private static final String rootDirectory = System.getProperty("user.dir")+"/test/javFiles/"; private static final List filesToTest = new ArrayList<>(); @@ -38,10 +29,10 @@ public class JavaTXCompilerTest extends JavaTXCompiler { @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){ - SourceFile sf = this.parse(f); String content = readFile(f.getPath(), StandardCharsets.UTF_8); - HashMap bytecode = this.getBytecode(sf); + HashMap bytecode = this.getBytecode(compiler.sourceFiles.get(f)); this.writeClassFile(bytecode, "EmptyClass"); }