This commit is contained in:
laurenz 2024-05-20 21:50:15 +02:00
commit 7b53346580
16 changed files with 130 additions and 60 deletions

Binary file not shown.

View File

@ -98,9 +98,7 @@ public class Compiler {
}
public static void main(String[] args) {
generateByteCodeFileFromFile(List.of("src/main/resources/JavaTestfiles/ClassWithConstructor.java",
"src/main/resources/JavaTestfiles/ClassWithConstructorAndMethodCall.java",
"src/main/resources/JavaTestfiles/ComplexClass.java"),
List.of("ClassWithConstructor","ClassWithConstructorAndMethodCall","ComplexClass"));
generateByteCodeFileFromFile(List.of("src/main/resources/JavaTestfiles/ClassCanBeBytecoded.java"),
List.of("ClassCanBeBytecoded"));
}
}

View File

@ -15,23 +15,20 @@ public class MethodContext {
public record LocalVariable(String name, int index, Type type) {
}
private Label startLabel;
private Label endLabel;
private MethodVisitor mv;
private ClassContext classContext;
private final ClassContext classContext;
private int localVarIndex = 0;
private final Map<String, LocalVariable> variableIndex = new HashMap<>();
private Stack<Integer> stack = new Stack<>();
private int maxStack = 0;
//used to jump out of loops with break
private final Stack<Label> breakLabels = new Stack<>();
public MethodContext(ClassContext classContext, MethodVisitor mv) {
startLabel = new Label();
endLabel = new Label();
this.mv = mv;
this.classContext = classContext;
registerVariable("this", classContext.getType());
mv.visitCode();
mv.visitLabel(startLabel);
}
public void registerVariable(String name, Type type) {
@ -79,7 +76,6 @@ public class MethodContext {
}
public void wrapUp() {
mv.visitLabel(endLabel);
System.out.println("maxStack: " + maxStack + " localVarIndex: " + localVarIndex);
mv.visitMaxs(maxStack, localVarIndex);
mv.visitEnd();

View File

@ -82,17 +82,15 @@ public class TypedAssignment implements TypedStatement {
@Override
public void codeGen(MethodContext ctx) {
if(value instanceof TypedNew) {
if(value instanceof TypedNew || value instanceof TypedMethodCall) {
value.codeGen(ctx);
getOwnerChain(ctx);
} else {
ctx.pushStack("this");
getOwnerChain(ctx);
value.codeGen(ctx);
}
//save value in field
//save value
if (location.getField()) {
String receiver = ctx.getClassContext().getName();
@ -101,22 +99,25 @@ public class TypedAssignment implements TypedStatement {
}
ctx.getMv().visitFieldInsn(Opcodes.PUTFIELD, receiver, location.getName(), value.getType().getDescriptor());
System.out.println("PUTFIELD: " + receiver + " " + location.getName() + " " + value.getType().getDescriptor());
ctx.popStack();
} else {
if(value.getType().getKind() == Type.Kind.REFERENCE) {
System.out.println("ASTORE " + ctx.getLocalVar(location.getName()).get().index());
ctx.getMv().visitVarInsn(Opcodes.ASTORE, ctx.getLocalVar(location.getName()).get().index());
} else {
System.out.println("ISTORE " + ctx.getLocalVar(location.getName()).get().index());
ctx.getMv().visitVarInsn(Opcodes.ISTORE, ctx.getLocalVar(location.getName()).get().index());
}
}
//ctx.popStack();
//ctx.popStack();
ctx.popStack();
}
private void getOwnerChain(MethodContext ctx) {
if (location.getRecursiveOwnerChain() != null) {
location.getRecursiveOwnerChain().codeGen(ctx);
ctx.pushAnonToStack();
}
if (location.getRecursiveOwnerChain() == null && location.getField()) {
ctx.pushStack("this");
}
}
}

View File

@ -206,5 +206,7 @@ public class TypedBinary implements TypedExpression {
}
}
ctx.popStack();
ctx.popStack();
ctx.pushAnonToStack();
}
}

View File

@ -5,6 +5,7 @@ import de.maishai.typedast.MethodContext;
import de.maishai.typedast.TypedStatement;
import de.maishai.typedast.Type;
import lombok.Data;
import org.objectweb.asm.Opcodes;
@Data
public class TypedBreak implements TypedStatement {
@ -17,6 +18,9 @@ public class TypedBreak implements TypedStatement {
@Override
public void codeGen(MethodContext ctx) {
if (ctx.getBreakLabels().isEmpty()) {
throw new RuntimeException("Break statement outside of loop");
}
ctx.getMv().visitJumpInsn(Opcodes.GOTO, ctx.getBreakLabels().pop());
}
}

View File

@ -205,38 +205,4 @@ public class TypedClass implements TypedNode {
return cw.toByteArray();
}
public static void main(String[] args) {
TypedClass c = new TypedClass();
c.setClassName("SomeClass");
//Fields
TypedDeclaration f1 = new TypedDeclaration("someNumber", Type.INT);
TypedDeclaration f2 = new TypedDeclaration("someChar", Type.CHAR);
c.typedDeclarations = List.of(f1, f2);
//Constructors
TypedConstructor constructor = new TypedConstructor("SomeClass", List.of(new TypedParameter("test", Type.INT)), new TypedBlock(new ArrayList<>(), new ArrayList<>()));
c.typedConstructors = List.of(constructor);
//Methods
c.typedMethods = new ArrayList<>();
TypedMethod m = new TypedMethod();
m.setName("someMethod");
m.setReturnType(Type.INT);
m.setTypedParameters(List.of(new TypedParameter("test", Type.INT)));
TypedIfElse ifs = new TypedIfElse();
TypedBinary cond = new TypedBinary();
cond.setOp(Operator.GT);
//cond.setLeft(??);
cond.setRight(new TypedIntLiteral(12));
ifs.setTypedCon(cond);
m.setTypedBlock(new TypedBlock(List.of(), List.of(ifs, new TypedReturn())));
c.typedMethods.add(m);
//codeGen
byte[] code = c.codeGen();
CodeGenUtils.writeClassfile(code, "SomeClass");
}
}

View File

@ -3,6 +3,8 @@ package de.maishai.typedast.typedclass;
import de.maishai.ast.records.*;
import de.maishai.typedast.*;
import lombok.Data;
import org.objectweb.asm.Label;
import org.objectweb.asm.Opcodes;
import static de.maishai.typedast.Help.TypedExpressionHelp.convertExpression;
@ -33,6 +35,19 @@ public class TypedDoWhile implements TypedStatement {
@Override
public void codeGen(MethodContext ctx) {
Label loopStart = new Label();
Label loopEnd = new Label();
ctx.getBreakLabels().push(loopEnd);
ctx.getMv().visitLabel(loopStart);
typedBlock.codeGen(ctx);
cond.codeGen(ctx);
ctx.getMv().visitJumpInsn(Opcodes.IFNE, loopStart);
ctx.popStack();
ctx.getMv().visitLabel(loopEnd);
}
}

View File

@ -108,16 +108,29 @@ public class TypedFieldVarAccess implements TypedExpression {
public void codeGen(MethodContext ctx) {
if (recursiveOwnerChain != null) {
recursiveOwnerChain.codeGen(ctx);
ctx.popStack();
}
if (field && recursiveOwnerChain == null) {
ctx.pushStack("this");
ctx.popStack();
}
if (field) {
ctx.getMv().visitFieldInsn(Opcodes.GETFIELD, recursiveOwnerChain.getType().getReference(), name, type.getDescriptor());
String ownerChainName;
if (recursiveOwnerChain != null) {
ownerChainName = recursiveOwnerChain.getType().getReference();
} else {
if (type.getKind() == Type.Kind.REFERENCE) {
ownerChainName = type.getReference();
} else {
ownerChainName = ctx.getClassContext().getName();
}
}
ctx.getMv().visitFieldInsn(Opcodes.GETFIELD, ownerChainName, name, type.getDescriptor());
} else {
int loadOpcode = type.getKind() == Type.Kind.REFERENCE ? Opcodes.ALOAD : Opcodes.ILOAD;
ctx.getMv().visitVarInsn(loadOpcode, ctx.getLocalVar(name).get().index());
System.out.println(loadOpcode == Opcodes.ALOAD ? "ALOAD " + ctx.getLocalVar(name).get().index() : "ILOAD " + ctx.getLocalVar(name).get().index());
}
ctx.pushAnonToStack();
}
}

View File

@ -5,6 +5,8 @@ import de.maishai.typedast.*;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.objectweb.asm.Label;
import org.objectweb.asm.Opcodes;
import static de.maishai.typedast.Help.TypedExpressionHelp.convertExpression;
@ -42,6 +44,21 @@ public class TypedFor implements TypedStatement {
@Override
public void codeGen(MethodContext ctx) {
Label loopStart = new Label();
Label loopUpdate = new Label();
Label loopEnd = new Label();
ctx.getBreakLabels().push(loopEnd);
assign.codeGen(ctx);
ctx.getMv().visitLabel(loopStart);
cond.codeGen(ctx);
ctx.getMv().visitJumpInsn(Opcodes.IFEQ, loopEnd);
ctx.popStack();
typedBlock.codeGen(ctx);
ctx.getMv().visitLabel(loopUpdate);
inc.codeGen(ctx);
ctx.getMv().visitJumpInsn(Opcodes.GOTO, loopStart);
ctx.getMv().visitLabel(loopEnd);
}
}

View File

@ -51,6 +51,7 @@ public class TypedIfElse implements TypedStatement {
Label end = new Label();
typedCon.codeGen(ctx);
ctx.getMv().visitJumpInsn(Opcodes.IFEQ, falseLabel);
ctx.popStack();
ifTypedBlock.codeGen(ctx);
ctx.getMv().visitJumpInsn(Opcodes.GOTO, end);

View File

@ -6,6 +6,7 @@ import de.maishai.typedast.*;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.objectweb.asm.Opcodes;
import java.util.ArrayList;
import java.util.List;
@ -85,6 +86,31 @@ public class TypedMethodCall implements TypedExpression, TypedStatement {
@Override
public void codeGen(MethodContext ctx) {
getOwnerChain(ctx);
for (TypedExpression arg : args) {
arg.codeGen(ctx);
}
String descriptor = CodeGenUtils.generateDescriptor(args.stream().map(TypedExpression::getType).toList(), type);
String methodOwnerClass;
if (recipient.getRecursiveOwnerChain() == null) {
methodOwnerClass = ctx.getClassContext().getName();
} else {
methodOwnerClass = recipient.getRecursiveOwnerChain().getType().getReference();
}
ctx.getMv().visitMethodInsn(Opcodes.INVOKEVIRTUAL, methodOwnerClass, recipient.getName(), descriptor, false);
System.out.println("INVOKEVIRTUAL " + methodOwnerClass + " " + recipient.getName() + " " + descriptor);
ctx.popStack(); // pop the owner
for (TypedExpression arg : args) {
ctx.popStack();
}
ctx.pushAnonToStack();
}
private void getOwnerChain(MethodContext ctx) {
if (recipient.getRecursiveOwnerChain() != null) {
recipient.getRecursiveOwnerChain().codeGen(ctx);
} else {
ctx.pushStack("this");
}
}
}

View File

@ -57,11 +57,6 @@ public class TypedNew implements TypedExpression, TypedStatement {
@Override
public void codeGen(MethodContext ctx) {
//pop the stack
//ctx.popStack();
//ctx.getMv().visitInsn(Opcodes.POP);
//System.out.println("Popped stack");
ctx.getMv().visitTypeInsn(Opcodes.NEW, type.getReference());
System.out.println("NEW " + type.getReference());
ctx.pushAnonToStack();
@ -72,6 +67,9 @@ public class TypedNew implements TypedExpression, TypedStatement {
arg.codeGen(ctx);
}
ctx.getMv().visitMethodInsn(Opcodes.INVOKESPECIAL, type.getReference(), "<init>", CodeGenUtils.generateDescriptor(args.stream().map(TypedExpression::getType).toList(), Type.VOID), false);
for (TypedExpression arg : args) {
ctx.popStack();
}
System.out.println("INVOKESPECIAL " + type.getReference() + "<init> " + CodeGenUtils.generateDescriptor(args.stream().map(TypedExpression::getType).toList(), Type.VOID));
}
}

View File

@ -49,13 +49,15 @@ public class TypedReturn implements TypedStatement {
public void codeGen(MethodContext ctx) {
if (ret == null) {
ctx.getMv().visitInsn(Opcodes.RETURN);
System.out.println("RETURN");
} else {
System.out.println("return: " + ret);
ret.codeGen(ctx);
if (ret.getType().getKind() != Type.Kind.REFERENCE) {
ctx.getMv().visitInsn(Opcodes.IRETURN);
System.out.println("IRETURN");
} else {
ctx.getMv().visitInsn(Opcodes.ARETURN);
System.out.println("ARETURN");
}
}

View File

@ -3,6 +3,9 @@ package de.maishai.typedast.typedclass;
import de.maishai.ast.records.*;
import de.maishai.typedast.*;
import lombok.Data;
import org.objectweb.asm.Label;
import org.objectweb.asm.Opcodes;
import static de.maishai.typedast.Help.TypedExpressionHelp.convertExpression;
@ -33,6 +36,17 @@ public class TypedWhile implements TypedStatement {
@Override
public void codeGen(MethodContext ctx) {
Label loopStart = new Label();
Label loopEnd = new Label();
ctx.getBreakLabels().push(loopEnd);
ctx.getMv().visitLabel(loopStart);
cond.codeGen(ctx);
ctx.getMv().visitJumpInsn(Opcodes.IFEQ, loopEnd);
ctx.popStack();
typedBlock.codeGen(ctx);
ctx.getMv().visitJumpInsn(Opcodes.GOTO, loopStart);
ctx.getMv().visitLabel(loopEnd);
}
}

View File

@ -0,0 +1,17 @@
public class ClassCanBeBytecoded {
public ClassCanBeBytecoded c;
public int x;
public ClassCanBeBytecoded() {
}
public int test(int var1) {
for (int i = 0; i < 12; i = i + 1) {
var1 = this.c.c.c.c.x + this.x;
if (var1 * 3 == 0) {
break;
}
}
return var1;
}
}