package st.gravel.support.compiler;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import st.gravel.support.compiler.jvm.ALoad;
import st.gravel.support.compiler.jvm.AReturn;
import st.gravel.support.compiler.jvm.AStore;
import st.gravel.support.compiler.jvm.AThrow;
import st.gravel.support.compiler.jvm.AndThenElse;
import st.gravel.support.compiler.jvm.ArrayLength;
import st.gravel.support.compiler.jvm.ByteArrayStore;
import st.gravel.support.compiler.jvm.CastArrayToObject;
import st.gravel.support.compiler.jvm.CastBooleanToObject;
import st.gravel.support.compiler.jvm.CastByteToObject;
import st.gravel.support.compiler.jvm.CastCharToObject;
import st.gravel.support.compiler.jvm.CastDefinedToObject;
import st.gravel.support.compiler.jvm.CastDoubleToObject;
import st.gravel.support.compiler.jvm.CastFloatToObject;
import st.gravel.support.compiler.jvm.CastIntToObject;
import st.gravel.support.compiler.jvm.CastLongToObject;
import st.gravel.support.compiler.jvm.CastObjectToArray;
import st.gravel.support.compiler.jvm.CastObjectToBoolean;
import st.gravel.support.compiler.jvm.CastObjectToByte;
import st.gravel.support.compiler.jvm.CastObjectToChar;
import st.gravel.support.compiler.jvm.CastObjectToDefined;
import st.gravel.support.compiler.jvm.CastObjectToDouble;
import st.gravel.support.compiler.jvm.CastObjectToFloat;
import st.gravel.support.compiler.jvm.CastObjectToInt;
import st.gravel.support.compiler.jvm.CastObjectToLong;
import st.gravel.support.compiler.jvm.CastObjectToShort;
import st.gravel.support.compiler.jvm.Dup;
import st.gravel.support.compiler.jvm.DupX1;
import st.gravel.support.compiler.jvm.DupX2;
import st.gravel.support.compiler.jvm.DynamicCreateInstance;
import st.gravel.support.compiler.jvm.DynamicFieldRead;
import st.gravel.support.compiler.jvm.DynamicFieldWrite;
import st.gravel.support.compiler.jvm.DynamicGlobalRead;
import st.gravel.support.compiler.jvm.DynamicGlobalWrite;
import st.gravel.support.compiler.jvm.DynamicLiteralBlockMessageSend;
import st.gravel.support.compiler.jvm.DynamicMessageSend;
import st.gravel.support.compiler.jvm.DynamicSuperSend;
import st.gravel.support.compiler.jvm.Frame;
import st.gravel.support.compiler.jvm.GetField;
import st.gravel.support.compiler.jvm.GetStatic;
import st.gravel.support.compiler.jvm.ILoad;
import st.gravel.support.compiler.jvm.IStore;
import st.gravel.support.compiler.jvm.IdentityCast;
import st.gravel.support.compiler.jvm.IfBooleanObjectThenElse;
import st.gravel.support.compiler.jvm.IfBooleanValueThenElse;
import st.gravel.support.compiler.jvm.IfObjectIsNullThenElse;
import st.gravel.support.compiler.jvm.IfObjectsEqualThenElse;
import st.gravel.support.compiler.jvm.IncrementLocal;
import st.gravel.support.compiler.jvm.InvokeInterface;
import st.gravel.support.compiler.jvm.InvokeSpecial;
import st.gravel.support.compiler.jvm.InvokeStatic;
import st.gravel.support.compiler.jvm.InvokeVirtual;
import st.gravel.support.compiler.jvm.JVMInstruction;
import st.gravel.support.compiler.jvm.JVMInstructionVisitor;
import st.gravel.support.compiler.jvm.JVMLocalDeclaration;
import st.gravel.support.compiler.jvm.JVMMethod;
import st.gravel.support.compiler.jvm.LabelLineNumber;
import st.gravel.support.compiler.jvm.NewArray;
import st.gravel.support.compiler.jvm.NewInstance;
import st.gravel.support.compiler.jvm.ObjectArrayLoad;
import st.gravel.support.compiler.jvm.ObjectArrayStore;
import st.gravel.support.compiler.jvm.OrThenElse;
import st.gravel.support.compiler.jvm.Pop;
import st.gravel.support.compiler.jvm.PushChar;
import st.gravel.support.compiler.jvm.PushDouble;
import st.gravel.support.compiler.jvm.PushFalse;
import st.gravel.support.compiler.jvm.PushFloat;
import st.gravel.support.compiler.jvm.PushInt;
import st.gravel.support.compiler.jvm.PushNull;
import st.gravel.support.compiler.jvm.PushString;
import st.gravel.support.compiler.jvm.PushTrue;
import st.gravel.support.compiler.jvm.PutField;
import st.gravel.support.compiler.jvm.PutStatic;
import st.gravel.support.compiler.jvm.Return;
import st.gravel.support.compiler.jvm.Subtract;
import st.gravel.support.compiler.jvm.TryCatch;
import st.gravel.support.compiler.jvm.WhileFalseLoop;
import st.gravel.support.compiler.jvm.WhileGreaterThanLoop;
import st.gravel.support.compiler.jvm.WhileLessThanLoop;
import st.gravel.support.compiler.jvm.WhileTrueLoop;
import st.gravel.support.jvm.ArrayExtensions;
import st.gravel.support.jvm.Block1;
public class ASMMethodWriter extends JVMInstructionVisitor<Void> implements
Opcodes {
private ClassWriter cw;
private MethodVisitor mv;
public ASMMethodWriter(ClassWriter cw) {
this.cw = cw;
}
@Override
protected Object clone() throws CloneNotSupportedException {
throw new UnsupportedOperationException("Not Implemented Yet");
}
public double fromage(Object x) {
return (Double) x;
}
public void logToErr(final String string) {
mv.visitFieldInsn(GETSTATIC, "java/lang/System", "err",
"Ljava/io/PrintStream;");
mv.visitLdcInsn(string);
mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println",
"(Ljava/lang/String;)V");
}
private void produceLocalVariableInfo(Label startLabel,
JVMLocalDeclaration[] jvmLocalDeclarations) {
Label varLabel = new Label();
mv.visitLabel(varLabel);
for (JVMLocalDeclaration local : jvmLocalDeclarations) {
mv.visitLocalVariable(local.varName(), local.type()
.descriptorString(), null, startLabel, varLabel, local
.index());
}
}
public void pushDouble(double value) {
if (value == 0.0d) {
mv.visitInsn(DCONST_0);
return;
}
if (value == 1.0d) {
mv.visitInsn(DCONST_1);
return;
}
mv.visitLdcInsn(value);
return;
}
public void pushFloat(float value) {
if (value == 0.0f) {
mv.visitInsn(FCONST_0);
return;
}
if (value == 1.0f) {
mv.visitInsn(FCONST_1);
return;
}
if (value == 2.0f) {
mv.visitInsn(FCONST_2);
return;
}
mv.visitLdcInsn(value);
return;
}
public void pushInt(int i) {
switch (i) {
case (0):
mv.visitInsn(ICONST_0);
return;
case (1):
mv.visitInsn(ICONST_1);
return;
case (2):
mv.visitInsn(ICONST_2);
return;
case (3):
mv.visitInsn(ICONST_3);
return;
case (4):
mv.visitInsn(ICONST_4);
return;
case (5):
mv.visitInsn(ICONST_5);
return;
}
if (i >= Byte.MIN_VALUE && i <= Byte.MAX_VALUE) {
mv.visitIntInsn(BIPUSH, i);
return;
}
if (i >= Short.MIN_VALUE && i <= Short.MAX_VALUE) {
mv.visitIntInsn(SIPUSH, i);
return;
}
mv.visitLdcInsn(i);
}
public Void visit_(JVMInstruction node) {
// logToErr("Start: " + node);
node.accept_(this);
return null;
}
@Override
public Void visitALoad_(ALoad node) {
mv.visitVarInsn(ALOAD, node.index());
return null;
}
@Override
public Void visitAndThenElse_(AndThenElse node) {
Label falseLabel = new Label();
Label endLabel = new Label();
visit_(node.left());
mv.visitJumpInsn(IFEQ, falseLabel);
visit_(node.right());
mv.visitJumpInsn(IFEQ, falseLabel);
visit_(node.trueFrame());
mv.visitJumpInsn(GOTO, endLabel);
mv.visitLabel(falseLabel);
visit_(node.falseFrame());
mv.visitLabel(endLabel);
return null;
}
@Override
public Void visitAReturn_(AReturn node) {
mv.visitInsn(ARETURN);
return null;
}
@Override
public Void visitArrayLength_(ArrayLength node) {
mv.visitInsn(ARRAYLENGTH);
return null;
}
@Override
public Void visitAStore_(AStore node) {
mv.visitVarInsn(ASTORE, node.index());
return null;
}
@Override
public Void visitAThrow_(AThrow node) {
mv.visitInsn(ATHROW);
return null;
}
@Override
public Void visitByteArrayStore_(ByteArrayStore node) {
mv.visitInsn(BASTORE);
return null;
}
@Override
public Void visitCastArrayToObject_(CastArrayToObject node) {
return null;
}
@Override
public Void visitCastBooleanToObject_(CastBooleanToObject node) {
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Boolean", "valueOf",
"(Z)Ljava/lang/Boolean;");
return null;
}
@Override
public Void visitCastByteToObject_(CastByteToObject node) {
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "valueOf",
"(I)Ljava/lang/Integer;");
return null;
}
@Override
public Void visitCastCharToObject_(CastCharToObject node) {
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Character", "valueOf",
"(C)Ljava/lang/Character;");
return null;
}
@Override
public Void visitCastDefinedToObject_(CastDefinedToObject node) {
return null;
}
@Override
public Void visitCastDoubleToObject_(CastDoubleToObject node) {
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Double", "valueOf",
"(D)Ljava/lang/Double;");
return null;
}
@Override
public Void visitCastFloatToObject_(CastFloatToObject node) {
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Float", "valueOf",
"(F)Ljava/lang/Float;");
return null;
}
@Override
public Void visitCastIntToObject_(CastIntToObject node) {
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "valueOf",
"(I)Ljava/lang/Integer;");
return null;
}
@Override
public Void visitCastLongToObject_(CastLongToObject _anObject) {
mv.visitMethodInsn(INVOKESTATIC, "java/math/BigInteger", "valueOf",
"(J)Ljava/math/BigInteger;");
return null;
}
@Override
public Void visitCastObjectToArray_(CastObjectToArray node) {
mv.visitTypeInsn(CHECKCAST, "[" + node.elementType().descriptorString());
return null;
}
@Override
public Void visitCastObjectToBoolean_(CastObjectToBoolean _anObject) {
mv.visitTypeInsn(CHECKCAST, "java/lang/Boolean");
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Boolean", "booleanValue",
"()Z");
return null;
}
@Override
public Void visitCastObjectToByte_(CastObjectToByte _anObject) {
mv.visitTypeInsn(CHECKCAST, "java/lang/Integer");
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Integer", "intValue",
"()I");
return null;
}
@Override
public Void visitCastObjectToChar_(CastObjectToChar _anObject) {
mv.visitTypeInsn(CHECKCAST, "java/lang/Character");
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Character", "charValue",
"()C");
return null;
}
@Override
public Void visitCastObjectToDefined_(CastObjectToDefined node) {
mv.visitTypeInsn(CHECKCAST, node.type().className());
return null;
}
@Override
public Void visitCastObjectToDouble_(CastObjectToDouble node) {
mv.visitTypeInsn(CHECKCAST, "java/lang/Double");
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Double", "doubleValue",
"()D");
return null;
}
@Override
public Void visitCastObjectToFloat_(CastObjectToFloat _anObject) {
mv.visitTypeInsn(CHECKCAST, "java/lang/Float");
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Float", "floatValue",
"()F");
return null;
}
@Override
public Void visitCastObjectToInt_(CastObjectToInt node) {
mv.visitTypeInsn(CHECKCAST, "java/lang/Integer");
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Integer", "intValue",
"()I");
return null;
}
@Override
public Void visitCastObjectToLong_(CastObjectToLong _anObject) {
mv.visitMethodInsn(INVOKESTATIC,
"st/gravel/support/jvm/IntegerExtensions", "asLong",
"(Ljava/lang/Object;)J");
return null;
}
@Override
public Void visitCastObjectToShort_(CastObjectToShort _anObject) {
mv.visitTypeInsn(CHECKCAST, "java/lang/Short");
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Short", "shortValue",
"()S");
return null;
}
@Override
public Void visitDup_(Dup _anObject) {
mv.visitInsn(DUP);
return null;
}
@Override
public Void visitDupX1_(DupX1 _anObject) {
mv.visitInsn(DUP_X1);
return null;
}
@Override
public Void visitDupX2_(DupX2 _anObject) {
mv.visitInsn(DUP_X2);
return null;
}
@Override
public Void visitDynamicCreateInstance_(DynamicCreateInstance node) {
mv.visitInvokeDynamicInsn("new", node.methodType()
.descriptorString(), BootstrapHandles.constructorBootstrap, node.reference());
return null;
}
@Override
public Void visitDynamicFieldRead_(DynamicFieldRead node) {
mv.visitInvokeDynamicInsn(node.name(), node.methodType()
.descriptorString(), BootstrapHandles.fieldReadBootstrap);
return null;
}
@Override
public Void visitDynamicFieldWrite_(DynamicFieldWrite node) {
mv.visitInvokeDynamicInsn(node.name(), node.methodType()
.descriptorString(), BootstrapHandles.fieldWriteBootstrap);
return null;
}
@Override
public Void visitDynamicGlobalRead_(DynamicGlobalRead node) {
mv.visitInvokeDynamicInsn(node.name(), node.methodType()
.descriptorString(), BootstrapHandles.globalReadBootstrap, node
.namespace());
return null;
}
@Override
public Void visitDynamicGlobalWrite_(DynamicGlobalWrite node) {
mv.visitInvokeDynamicInsn(node.name(), node.methodType()
.descriptorString(), BootstrapHandles.globalWriteBootstrap,
node.namespace());
return null;
}
@Override
public Void visitDynamicLiteralBlockMessageSend_(
DynamicLiteralBlockMessageSend node) {
String astConstantsString = ArrayExtensions.join_(
node.blockSendConstants(), new Block1<String, String>() {
@Override
public String value_(String arg1) {
return (arg1 == null ? "" : arg1) + ';';
}
});
String copiedArgumentsString = ArrayExtensions.join_(
node.copiedArguments(), new Block1<String, String>() {
@Override
public String value_(String arg1) {
return arg1 + ';';
}
});
mv.visitInvokeDynamicInsn(node.functionName(), node.signature()
.descriptorString(),
BootstrapHandles.literalBlockSendBootstrap, node
.constantOwner().dottedClassName(), astConstantsString,
copiedArgumentsString);
return null;
}
@Override
public Void visitDynamicMessageSend_(DynamicMessageSend node) {
mv.visitInvokeDynamicInsn(node.functionName(), node.signature()
.descriptorString(), BootstrapHandles.bootstrap);
return null;
}
@Override
public Void visitDynamicSuperSend_(DynamicSuperSend node) {
mv.visitInvokeDynamicInsn(node.functionName(), node.signature()
.descriptorString(), BootstrapHandles.superBootstrap, node
.superReference());
return null;
}
@Override
public Void visitFrame_(Frame frame) {
for (JVMInstruction insn : frame.instructions())
visit_(insn);
return null;
}
@Override
public Void visitGetField_(GetField node) {
mv.visitFieldInsn(GETFIELD, node.ownerType().className(), node.name(),
node.type().descriptorString());
return null;
}
@Override
public Void visitGetStatic_(GetStatic node) {
mv.visitFieldInsn(GETSTATIC, node.ownerType().className(), node.name(),
node.type().descriptorString());
return null;
}
@Override
public Void visitIdentityCast_(IdentityCast _anObject) {
return null;
}
@Override
public Void visitIfBooleanObjectThenElse_(IfBooleanObjectThenElse node) {
mv.visitTypeInsn(CHECKCAST, "java/lang/Boolean");
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Boolean", "booleanValue",
"()Z");
Label elseLabel = new Label();
mv.visitJumpInsn(IFEQ, elseLabel);
visit_(node.trueFrame());
Label end = new Label();
mv.visitJumpInsn(GOTO, end);
mv.visitLabel(elseLabel);
visit_(node.falseFrame());
mv.visitLabel(end);
return null;
}
@Override
public Void visitIfBooleanValueThenElse_(IfBooleanValueThenElse node) {
Label elseLabel = new Label();
mv.visitJumpInsn(IFEQ, elseLabel);
visit_(node.trueFrame());
Label end = new Label();
mv.visitJumpInsn(GOTO, end);
mv.visitLabel(elseLabel);
visit_(node.falseFrame());
mv.visitLabel(end);
return null;
}
@Override
public Void visitIfObjectIsNullThenElse_(IfObjectIsNullThenElse node) {
Label elseLabel = new Label();
mv.visitJumpInsn(IFNONNULL, elseLabel);
visit_(node.trueFrame());
Label end = new Label();
mv.visitJumpInsn(GOTO, end);
mv.visitLabel(elseLabel);
visit_(node.falseFrame());
mv.visitLabel(end);
return null;
}
@Override
public Void visitIfObjectsEqualThenElse_(IfObjectsEqualThenElse node) {
Label elseLabel = new Label();
mv.visitJumpInsn(IF_ACMPNE, elseLabel);
visit_(node.trueFrame());
Label end = new Label();
mv.visitJumpInsn(GOTO, end);
mv.visitLabel(elseLabel);
visit_(node.falseFrame());
mv.visitLabel(end);
return null;
}
@Override
public Void visitILoad_(ILoad node) {
mv.visitVarInsn(ILOAD, node.index());
return null;
}
@Override
public Void visitIncrementLocal_(IncrementLocal node) {
mv.visitIincInsn(node.local().index(), node.increment());
return null;
}
@Override
public Void visitInvokeInterface_(InvokeInterface node) {
mv.visitMethodInsn(INVOKEINTERFACE, node.ownerType().className(),
node.name(), node.signature().descriptorString());
return null;
}
@Override
public Void visitInvokeSpecial_(InvokeSpecial node) {
mv.visitMethodInsn(INVOKESPECIAL, node.ownerType().className(),
node.name(), node.signature().descriptorString());
return null;
}
@Override
public Void visitInvokeStatic_(InvokeStatic node) {
mv.visitMethodInsn(INVOKESTATIC, node.ownerType().className(),
node.name(), node.signature().descriptorString());
return null;
}
@Override
public Void visitInvokeVirtual_(InvokeVirtual node) {
mv.visitMethodInsn(INVOKEVIRTUAL, node.ownerType().className(),
node.name(), node.signature().descriptorString());
return null;
}
@Override
public Void visitIStore_(IStore node) {
mv.visitVarInsn(ISTORE, node.index());
return null;
}
@Override
public Void visitLabelLineNumber_(LabelLineNumber node) {
Label l1 = new Label();
mv.visitLabel(l1);
mv.visitLineNumber(node.line(), l1);
return null;
}
@Override
public Void visitNewArray_(NewArray node) {
if (node.elementType().isObjectType())
mv.visitTypeInsn(ANEWARRAY, "java/lang/Object");
else if (node.elementType().isByteType())
mv.visitIntInsn(NEWARRAY, T_BYTE);
return null;
}
@Override
public Void visitNewInstance_(NewInstance node) {
mv.visitTypeInsn(NEW, node.type().className());
return null;
}
@Override
public Void visitObjectArrayLoad_(ObjectArrayLoad node) {
mv.visitInsn(AALOAD);
return null;
}
@Override
public Void visitObjectArrayStore_(ObjectArrayStore node) {
mv.visitInsn(AASTORE);
return null;
}
@Override
public Void visitOrThenElse_(OrThenElse node) {
Label trueLabel = new Label();
Label endLabel = new Label();
visit_(node.left());
mv.visitJumpInsn(IFNE, trueLabel);
visit_(node.right());
mv.visitJumpInsn(IFNE, trueLabel);
visit_(node.falseFrame());
mv.visitJumpInsn(GOTO, endLabel);
mv.visitLabel(trueLabel);
visit_(node.trueFrame());
mv.visitLabel(endLabel);
return null;
}
@Override
public Void visitPop_(Pop node) {
mv.visitInsn(POP);
return null;
}
@Override
public Void visitPushChar_(PushChar node) {
mv.visitIntInsn(BIPUSH, node.value());
return null;
}
@Override
public Void visitPushDouble_(PushDouble node) {
pushDouble(node.value());
return null;
}
@Override
public Void visitPushFalse_(PushFalse node) {
mv.visitInsn(ICONST_0);
return null;
}
@Override
public Void visitPushFloat_(PushFloat node) {
pushFloat(node.value());
return null;
}
@Override
public Void visitPushInt_(PushInt node) {
pushInt(node.value());
return null;
}
@Override
public Void visitPushNull_(PushNull node) {
mv.visitInsn(ACONST_NULL);
return null;
}
@Override
public Void visitPushString_(PushString node) {
mv.visitLdcInsn(node.value());
return null;
}
@Override
public Void visitPushTrue_(PushTrue node) {
mv.visitInsn(ICONST_1);
return null;
}
@Override
public Void visitPutField_(PutField node) {
mv.visitFieldInsn(PUTFIELD, node.ownerType().className(), node.name(),
node.type().descriptorString());
return null;
}
@Override
public Void visitPutStatic_(PutStatic node) {
mv.visitFieldInsn(PUTSTATIC, node.ownerType().className(), node.name(),
node.type().descriptorString());
return null;
}
@Override
public Void visitReturn_(Return node) {
mv.visitInsn(RETURN);
return null;
}
@Override
public Void visitSubtract_(Subtract node) {
mv.visitInsn(ISUB);
return null;
}
@Override
public Void visitTryCatch_(TryCatch node) {
Label nlrTryStart = new Label();
Label nlrTryEnd = new Label();
Label nlrTryHandler = new Label();
mv.visitTryCatchBlock(nlrTryStart, nlrTryEnd, nlrTryHandler, node
.exception().className());
mv.visitLabel(nlrTryStart);
visit_(node.tryFrame());
mv.visitLabel(nlrTryEnd);
Label endLabel = new Label();
if (node.doFrame() != null) {
visit_(node.doFrame());
}
mv.visitJumpInsn(GOTO, endLabel);
mv.visitLabel(nlrTryHandler);
visit_(node.catchFrame());
mv.visitLabel(endLabel);
return null;
}
@Override
public Void visitWhileFalseLoop_(WhileFalseLoop node) {
Label topLabel = new Label();
Label doLabel = new Label();
Label endLabel = new Label();
mv.visitLabel(topLabel);
visit_(node.testFrame());
mv.visitJumpInsn(IFEQ, doLabel);
mv.visitJumpInsn(GOTO, endLabel);
mv.visitLabel(doLabel);
visit_(node.doFrame());
mv.visitJumpInsn(GOTO, topLabel);
mv.visitLabel(endLabel);
return null;
}
@Override
public Void visitWhileGreaterThanLoop_(WhileGreaterThanLoop node) {
Label testLabel = new Label();
Label endLabel = new Label();
mv.visitLabel(testLabel);
visit_(node.testFrame());
mv.visitJumpInsn(IF_ICMPLT, endLabel);
visit_(node.doFrame());
mv.visitJumpInsn(GOTO, testLabel);
mv.visitLabel(endLabel);
return null;
}
@Override
public Void visitWhileLessThanLoop_(WhileLessThanLoop node) {
Label testLabel = new Label();
Label endLabel = new Label();
mv.visitLabel(testLabel);
visit_(node.testFrame());
mv.visitJumpInsn(IF_ICMPGT, endLabel);
visit_(node.doFrame());
mv.visitJumpInsn(GOTO, testLabel);
mv.visitLabel(endLabel);
return null;
}
@Override
public Void visitWhileTrueLoop_(WhileTrueLoop node) {
Label topLabel = new Label();
Label doLabel = new Label();
Label endLabel = new Label();
mv.visitLabel(topLabel);
visit_(node.testFrame());
mv.visitJumpInsn(IFNE, doLabel);
mv.visitJumpInsn(GOTO, endLabel);
mv.visitLabel(doLabel);
visit_(node.doFrame());
mv.visitJumpInsn(GOTO, topLabel);
mv.visitLabel(endLabel);
return null;
}
public void write(JVMMethod method) {
mv = cw.visitMethod(ACC_PUBLIC + (method.isStatic() ? ACC_STATIC : 0),
method.name(), method.signature().descriptorString(), null,
null);
mv.visitCode();
// logToErr("Method: " + method);
Label startLabel = new Label();
mv.visitLabel(startLabel);
for (JVMInstruction inst : method.instructions()) {
inst.accept_(this);
}
produceLocalVariableInfo(startLabel, method.locals());
mv.visitMaxs(0, 0);
mv.visitEnd();
}
}