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