mirror of
https://github.com/JonathanFleischmann/CompilerULTIMATE.git
synced 2024-12-28 02:08:04 +00:00
Merge branch 'main' of https://github.com/JonathanFleischmann/CompilerULTIMATE
This commit is contained in:
commit
7b53346580
Binary file not shown.
@ -98,9 +98,7 @@ public class Compiler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
generateByteCodeFileFromFile(List.of("src/main/resources/JavaTestfiles/ClassWithConstructor.java",
|
generateByteCodeFileFromFile(List.of("src/main/resources/JavaTestfiles/ClassCanBeBytecoded.java"),
|
||||||
"src/main/resources/JavaTestfiles/ClassWithConstructorAndMethodCall.java",
|
List.of("ClassCanBeBytecoded"));
|
||||||
"src/main/resources/JavaTestfiles/ComplexClass.java"),
|
|
||||||
List.of("ClassWithConstructor","ClassWithConstructorAndMethodCall","ComplexClass"));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,23 +15,20 @@ public class MethodContext {
|
|||||||
public record LocalVariable(String name, int index, Type type) {
|
public record LocalVariable(String name, int index, Type type) {
|
||||||
}
|
}
|
||||||
|
|
||||||
private Label startLabel;
|
|
||||||
private Label endLabel;
|
|
||||||
private MethodVisitor mv;
|
private MethodVisitor mv;
|
||||||
private ClassContext classContext;
|
private final ClassContext classContext;
|
||||||
private int localVarIndex = 0;
|
private int localVarIndex = 0;
|
||||||
private final Map<String, LocalVariable> variableIndex = new HashMap<>();
|
private final Map<String, LocalVariable> variableIndex = new HashMap<>();
|
||||||
private Stack<Integer> stack = new Stack<>();
|
private Stack<Integer> stack = new Stack<>();
|
||||||
private int maxStack = 0;
|
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) {
|
public MethodContext(ClassContext classContext, MethodVisitor mv) {
|
||||||
startLabel = new Label();
|
|
||||||
endLabel = new Label();
|
|
||||||
this.mv = mv;
|
this.mv = mv;
|
||||||
this.classContext = classContext;
|
this.classContext = classContext;
|
||||||
registerVariable("this", classContext.getType());
|
registerVariable("this", classContext.getType());
|
||||||
mv.visitCode();
|
mv.visitCode();
|
||||||
mv.visitLabel(startLabel);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void registerVariable(String name, Type type) {
|
public void registerVariable(String name, Type type) {
|
||||||
@ -79,7 +76,6 @@ public class MethodContext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void wrapUp() {
|
public void wrapUp() {
|
||||||
mv.visitLabel(endLabel);
|
|
||||||
System.out.println("maxStack: " + maxStack + " localVarIndex: " + localVarIndex);
|
System.out.println("maxStack: " + maxStack + " localVarIndex: " + localVarIndex);
|
||||||
mv.visitMaxs(maxStack, localVarIndex);
|
mv.visitMaxs(maxStack, localVarIndex);
|
||||||
mv.visitEnd();
|
mv.visitEnd();
|
||||||
|
@ -82,17 +82,15 @@ public class TypedAssignment implements TypedStatement {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void codeGen(MethodContext ctx) {
|
public void codeGen(MethodContext ctx) {
|
||||||
if(value instanceof TypedNew) {
|
if(value instanceof TypedNew || value instanceof TypedMethodCall) {
|
||||||
value.codeGen(ctx);
|
value.codeGen(ctx);
|
||||||
getOwnerChain(ctx);
|
getOwnerChain(ctx);
|
||||||
} else {
|
} else {
|
||||||
ctx.pushStack("this");
|
|
||||||
getOwnerChain(ctx);
|
getOwnerChain(ctx);
|
||||||
value.codeGen(ctx);
|
value.codeGen(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//save value
|
||||||
//save value in field
|
|
||||||
if (location.getField()) {
|
if (location.getField()) {
|
||||||
|
|
||||||
String receiver = ctx.getClassContext().getName();
|
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());
|
ctx.getMv().visitFieldInsn(Opcodes.PUTFIELD, receiver, location.getName(), value.getType().getDescriptor());
|
||||||
System.out.println("PUTFIELD: " + receiver + " " + location.getName() + " " + value.getType().getDescriptor());
|
System.out.println("PUTFIELD: " + receiver + " " + location.getName() + " " + value.getType().getDescriptor());
|
||||||
|
ctx.popStack();
|
||||||
} else {
|
} else {
|
||||||
if(value.getType().getKind() == Type.Kind.REFERENCE) {
|
if(value.getType().getKind() == Type.Kind.REFERENCE) {
|
||||||
System.out.println("ASTORE " + ctx.getLocalVar(location.getName()).get().index());
|
System.out.println("ASTORE " + ctx.getLocalVar(location.getName()).get().index());
|
||||||
ctx.getMv().visitVarInsn(Opcodes.ASTORE, ctx.getLocalVar(location.getName()).get().index());
|
ctx.getMv().visitVarInsn(Opcodes.ASTORE, ctx.getLocalVar(location.getName()).get().index());
|
||||||
} else {
|
} else {
|
||||||
|
System.out.println("ISTORE " + ctx.getLocalVar(location.getName()).get().index());
|
||||||
ctx.getMv().visitVarInsn(Opcodes.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) {
|
private void getOwnerChain(MethodContext ctx) {
|
||||||
if (location.getRecursiveOwnerChain() != null) {
|
if (location.getRecursiveOwnerChain() != null) {
|
||||||
location.getRecursiveOwnerChain().codeGen(ctx);
|
location.getRecursiveOwnerChain().codeGen(ctx);
|
||||||
ctx.pushAnonToStack();
|
}
|
||||||
|
if (location.getRecursiveOwnerChain() == null && location.getField()) {
|
||||||
|
ctx.pushStack("this");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -206,5 +206,7 @@ public class TypedBinary implements TypedExpression {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
ctx.popStack();
|
ctx.popStack();
|
||||||
|
ctx.popStack();
|
||||||
|
ctx.pushAnonToStack();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ import de.maishai.typedast.MethodContext;
|
|||||||
import de.maishai.typedast.TypedStatement;
|
import de.maishai.typedast.TypedStatement;
|
||||||
import de.maishai.typedast.Type;
|
import de.maishai.typedast.Type;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
import org.objectweb.asm.Opcodes;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
public class TypedBreak implements TypedStatement {
|
public class TypedBreak implements TypedStatement {
|
||||||
@ -17,6 +18,9 @@ public class TypedBreak implements TypedStatement {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void codeGen(MethodContext ctx) {
|
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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -205,38 +205,4 @@ public class TypedClass implements TypedNode {
|
|||||||
|
|
||||||
return cw.toByteArray();
|
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");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,8 @@ package de.maishai.typedast.typedclass;
|
|||||||
import de.maishai.ast.records.*;
|
import de.maishai.ast.records.*;
|
||||||
import de.maishai.typedast.*;
|
import de.maishai.typedast.*;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
import org.objectweb.asm.Label;
|
||||||
|
import org.objectweb.asm.Opcodes;
|
||||||
|
|
||||||
import static de.maishai.typedast.Help.TypedExpressionHelp.convertExpression;
|
import static de.maishai.typedast.Help.TypedExpressionHelp.convertExpression;
|
||||||
|
|
||||||
@ -33,6 +35,19 @@ public class TypedDoWhile implements TypedStatement {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void codeGen(MethodContext ctx) {
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -108,16 +108,29 @@ public class TypedFieldVarAccess implements TypedExpression {
|
|||||||
public void codeGen(MethodContext ctx) {
|
public void codeGen(MethodContext ctx) {
|
||||||
if (recursiveOwnerChain != null) {
|
if (recursiveOwnerChain != null) {
|
||||||
recursiveOwnerChain.codeGen(ctx);
|
recursiveOwnerChain.codeGen(ctx);
|
||||||
|
ctx.popStack();
|
||||||
}
|
}
|
||||||
if (field && recursiveOwnerChain == null) {
|
if (field && recursiveOwnerChain == null) {
|
||||||
ctx.pushStack("this");
|
ctx.pushStack("this");
|
||||||
|
ctx.popStack();
|
||||||
}
|
}
|
||||||
if (field) {
|
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 {
|
} else {
|
||||||
int loadOpcode = type.getKind() == Type.Kind.REFERENCE ? Opcodes.ALOAD : Opcodes.ILOAD;
|
int loadOpcode = type.getKind() == Type.Kind.REFERENCE ? Opcodes.ALOAD : Opcodes.ILOAD;
|
||||||
ctx.getMv().visitVarInsn(loadOpcode, ctx.getLocalVar(name).get().index());
|
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());
|
System.out.println(loadOpcode == Opcodes.ALOAD ? "ALOAD " + ctx.getLocalVar(name).get().index() : "ILOAD " + ctx.getLocalVar(name).get().index());
|
||||||
}
|
}
|
||||||
|
ctx.pushAnonToStack();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,8 @@ import de.maishai.typedast.*;
|
|||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
|
import org.objectweb.asm.Label;
|
||||||
|
import org.objectweb.asm.Opcodes;
|
||||||
|
|
||||||
import static de.maishai.typedast.Help.TypedExpressionHelp.convertExpression;
|
import static de.maishai.typedast.Help.TypedExpressionHelp.convertExpression;
|
||||||
|
|
||||||
@ -42,6 +44,21 @@ public class TypedFor implements TypedStatement {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void codeGen(MethodContext ctx) {
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -51,6 +51,7 @@ public class TypedIfElse implements TypedStatement {
|
|||||||
Label end = new Label();
|
Label end = new Label();
|
||||||
typedCon.codeGen(ctx);
|
typedCon.codeGen(ctx);
|
||||||
ctx.getMv().visitJumpInsn(Opcodes.IFEQ, falseLabel);
|
ctx.getMv().visitJumpInsn(Opcodes.IFEQ, falseLabel);
|
||||||
|
ctx.popStack();
|
||||||
ifTypedBlock.codeGen(ctx);
|
ifTypedBlock.codeGen(ctx);
|
||||||
ctx.getMv().visitJumpInsn(Opcodes.GOTO, end);
|
ctx.getMv().visitJumpInsn(Opcodes.GOTO, end);
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@ import de.maishai.typedast.*;
|
|||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
|
import org.objectweb.asm.Opcodes;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -85,6 +86,31 @@ public class TypedMethodCall implements TypedExpression, TypedStatement {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void codeGen(MethodContext ctx) {
|
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");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -57,11 +57,6 @@ public class TypedNew implements TypedExpression, TypedStatement {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void codeGen(MethodContext ctx) {
|
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());
|
ctx.getMv().visitTypeInsn(Opcodes.NEW, type.getReference());
|
||||||
System.out.println("NEW " + type.getReference());
|
System.out.println("NEW " + type.getReference());
|
||||||
ctx.pushAnonToStack();
|
ctx.pushAnonToStack();
|
||||||
@ -72,6 +67,9 @@ public class TypedNew implements TypedExpression, TypedStatement {
|
|||||||
arg.codeGen(ctx);
|
arg.codeGen(ctx);
|
||||||
}
|
}
|
||||||
ctx.getMv().visitMethodInsn(Opcodes.INVOKESPECIAL, type.getReference(), "<init>", CodeGenUtils.generateDescriptor(args.stream().map(TypedExpression::getType).toList(), Type.VOID), false);
|
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));
|
System.out.println("INVOKESPECIAL " + type.getReference() + "<init> " + CodeGenUtils.generateDescriptor(args.stream().map(TypedExpression::getType).toList(), Type.VOID));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -49,13 +49,15 @@ public class TypedReturn implements TypedStatement {
|
|||||||
public void codeGen(MethodContext ctx) {
|
public void codeGen(MethodContext ctx) {
|
||||||
if (ret == null) {
|
if (ret == null) {
|
||||||
ctx.getMv().visitInsn(Opcodes.RETURN);
|
ctx.getMv().visitInsn(Opcodes.RETURN);
|
||||||
|
System.out.println("RETURN");
|
||||||
} else {
|
} else {
|
||||||
System.out.println("return: " + ret);
|
|
||||||
ret.codeGen(ctx);
|
ret.codeGen(ctx);
|
||||||
if (ret.getType().getKind() != Type.Kind.REFERENCE) {
|
if (ret.getType().getKind() != Type.Kind.REFERENCE) {
|
||||||
ctx.getMv().visitInsn(Opcodes.IRETURN);
|
ctx.getMv().visitInsn(Opcodes.IRETURN);
|
||||||
|
System.out.println("IRETURN");
|
||||||
} else {
|
} else {
|
||||||
ctx.getMv().visitInsn(Opcodes.ARETURN);
|
ctx.getMv().visitInsn(Opcodes.ARETURN);
|
||||||
|
System.out.println("ARETURN");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,6 +3,9 @@ package de.maishai.typedast.typedclass;
|
|||||||
import de.maishai.ast.records.*;
|
import de.maishai.ast.records.*;
|
||||||
import de.maishai.typedast.*;
|
import de.maishai.typedast.*;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
import org.objectweb.asm.Label;
|
||||||
|
import org.objectweb.asm.Opcodes;
|
||||||
|
|
||||||
|
|
||||||
import static de.maishai.typedast.Help.TypedExpressionHelp.convertExpression;
|
import static de.maishai.typedast.Help.TypedExpressionHelp.convertExpression;
|
||||||
|
|
||||||
@ -33,6 +36,17 @@ public class TypedWhile implements TypedStatement {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void codeGen(MethodContext ctx) {
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
17
src/main/resources/JavaTestfiles/ClassCanBeBytecoded.java
Normal file
17
src/main/resources/JavaTestfiles/ClassCanBeBytecoded.java
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user