/*
* $Id$
*
* Copyright (C) 2003-2015 JNode.org
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; If not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
package org.jnode.vm.compiler.ir;
import static org.jnode.vm.compiler.ir.quad.BinaryOperation.DADD;
import static org.jnode.vm.compiler.ir.quad.BinaryOperation.DCMPG;
import static org.jnode.vm.compiler.ir.quad.BinaryOperation.DCMPL;
import static org.jnode.vm.compiler.ir.quad.BinaryOperation.DDIV;
import static org.jnode.vm.compiler.ir.quad.BinaryOperation.DMUL;
import static org.jnode.vm.compiler.ir.quad.BinaryOperation.DREM;
import static org.jnode.vm.compiler.ir.quad.BinaryOperation.DSUB;
import static org.jnode.vm.compiler.ir.quad.BinaryOperation.FADD;
import static org.jnode.vm.compiler.ir.quad.BinaryOperation.FCMPG;
import static org.jnode.vm.compiler.ir.quad.BinaryOperation.FCMPL;
import static org.jnode.vm.compiler.ir.quad.BinaryOperation.FDIV;
import static org.jnode.vm.compiler.ir.quad.BinaryOperation.FMUL;
import static org.jnode.vm.compiler.ir.quad.BinaryOperation.FREM;
import static org.jnode.vm.compiler.ir.quad.BinaryOperation.FSUB;
import static org.jnode.vm.compiler.ir.quad.BinaryOperation.IADD;
import static org.jnode.vm.compiler.ir.quad.BinaryOperation.IAND;
import static org.jnode.vm.compiler.ir.quad.BinaryOperation.IDIV;
import static org.jnode.vm.compiler.ir.quad.BinaryOperation.IMUL;
import static org.jnode.vm.compiler.ir.quad.BinaryOperation.IOR;
import static org.jnode.vm.compiler.ir.quad.BinaryOperation.IREM;
import static org.jnode.vm.compiler.ir.quad.BinaryOperation.ISHL;
import static org.jnode.vm.compiler.ir.quad.BinaryOperation.ISHR;
import static org.jnode.vm.compiler.ir.quad.BinaryOperation.ISUB;
import static org.jnode.vm.compiler.ir.quad.BinaryOperation.IUSHR;
import static org.jnode.vm.compiler.ir.quad.BinaryOperation.IXOR;
import static org.jnode.vm.compiler.ir.quad.BinaryOperation.LADD;
import static org.jnode.vm.compiler.ir.quad.BinaryOperation.LAND;
import static org.jnode.vm.compiler.ir.quad.BinaryOperation.LCMP;
import static org.jnode.vm.compiler.ir.quad.BinaryOperation.LDIV;
import static org.jnode.vm.compiler.ir.quad.BinaryOperation.LMUL;
import static org.jnode.vm.compiler.ir.quad.BinaryOperation.LOR;
import static org.jnode.vm.compiler.ir.quad.BinaryOperation.LREM;
import static org.jnode.vm.compiler.ir.quad.BinaryOperation.LSHL;
import static org.jnode.vm.compiler.ir.quad.BinaryOperation.LSHR;
import static org.jnode.vm.compiler.ir.quad.BinaryOperation.LSUB;
import static org.jnode.vm.compiler.ir.quad.BinaryOperation.LUSHR;
import static org.jnode.vm.compiler.ir.quad.BinaryOperation.LXOR;
import static org.jnode.vm.compiler.ir.quad.BranchCondition.IFEQ;
import static org.jnode.vm.compiler.ir.quad.BranchCondition.IFGE;
import static org.jnode.vm.compiler.ir.quad.BranchCondition.IFGT;
import static org.jnode.vm.compiler.ir.quad.BranchCondition.IFLE;
import static org.jnode.vm.compiler.ir.quad.BranchCondition.IFLT;
import static org.jnode.vm.compiler.ir.quad.BranchCondition.IFNE;
import static org.jnode.vm.compiler.ir.quad.BranchCondition.IFNONNULL;
import static org.jnode.vm.compiler.ir.quad.BranchCondition.IFNULL;
import static org.jnode.vm.compiler.ir.quad.BranchCondition.IF_ACMPEQ;
import static org.jnode.vm.compiler.ir.quad.BranchCondition.IF_ACMPNE;
import static org.jnode.vm.compiler.ir.quad.BranchCondition.IF_ICMPEQ;
import static org.jnode.vm.compiler.ir.quad.BranchCondition.IF_ICMPGE;
import static org.jnode.vm.compiler.ir.quad.BranchCondition.IF_ICMPGT;
import static org.jnode.vm.compiler.ir.quad.BranchCondition.IF_ICMPLE;
import static org.jnode.vm.compiler.ir.quad.BranchCondition.IF_ICMPLT;
import static org.jnode.vm.compiler.ir.quad.BranchCondition.IF_ICMPNE;
import static org.jnode.vm.compiler.ir.quad.UnaryOperation.D2F;
import static org.jnode.vm.compiler.ir.quad.UnaryOperation.D2I;
import static org.jnode.vm.compiler.ir.quad.UnaryOperation.D2L;
import static org.jnode.vm.compiler.ir.quad.UnaryOperation.DNEG;
import static org.jnode.vm.compiler.ir.quad.UnaryOperation.F2D;
import static org.jnode.vm.compiler.ir.quad.UnaryOperation.F2I;
import static org.jnode.vm.compiler.ir.quad.UnaryOperation.F2L;
import static org.jnode.vm.compiler.ir.quad.UnaryOperation.FNEG;
import static org.jnode.vm.compiler.ir.quad.UnaryOperation.I2B;
import static org.jnode.vm.compiler.ir.quad.UnaryOperation.I2C;
import static org.jnode.vm.compiler.ir.quad.UnaryOperation.I2D;
import static org.jnode.vm.compiler.ir.quad.UnaryOperation.I2F;
import static org.jnode.vm.compiler.ir.quad.UnaryOperation.I2L;
import static org.jnode.vm.compiler.ir.quad.UnaryOperation.I2S;
import static org.jnode.vm.compiler.ir.quad.UnaryOperation.INEG;
import static org.jnode.vm.compiler.ir.quad.UnaryOperation.L2D;
import static org.jnode.vm.compiler.ir.quad.UnaryOperation.L2F;
import static org.jnode.vm.compiler.ir.quad.UnaryOperation.L2I;
import static org.jnode.vm.compiler.ir.quad.UnaryOperation.LNEG;
import java.util.Iterator;
import java.util.List;
import org.jnode.vm.JvmType;
import org.jnode.vm.bytecode.BytecodeParser;
import org.jnode.vm.bytecode.BytecodeVisitor;
import org.jnode.vm.classmgr.Signature;
import org.jnode.vm.classmgr.VmByteCode;
import org.jnode.vm.classmgr.VmClassLoader;
import org.jnode.vm.classmgr.VmConstClass;
import org.jnode.vm.classmgr.VmConstFieldRef;
import org.jnode.vm.classmgr.VmConstIMethodRef;
import org.jnode.vm.classmgr.VmConstMethodRef;
import org.jnode.vm.classmgr.VmConstString;
import org.jnode.vm.classmgr.VmMethod;
import org.jnode.vm.classmgr.VmType;
import org.jnode.vm.compiler.ir.quad.ArrayAssignQuad;
import org.jnode.vm.compiler.ir.quad.ArrayLengthAssignQuad;
import org.jnode.vm.compiler.ir.quad.ArrayStoreQuad;
import org.jnode.vm.compiler.ir.quad.AssignQuad;
import org.jnode.vm.compiler.ir.quad.BinaryOperation;
import org.jnode.vm.compiler.ir.quad.BinaryQuad;
import org.jnode.vm.compiler.ir.quad.BranchCondition;
import org.jnode.vm.compiler.ir.quad.CheckcastQuad;
import org.jnode.vm.compiler.ir.quad.ConditionalBranchQuad;
import org.jnode.vm.compiler.ir.quad.ConstantClassAssignQuad;
import org.jnode.vm.compiler.ir.quad.ConstantRefAssignQuad;
import org.jnode.vm.compiler.ir.quad.ConstantStringAssignQuad;
import org.jnode.vm.compiler.ir.quad.InstanceofAssignQuad;
import org.jnode.vm.compiler.ir.quad.InterfaceCallAssignQuad;
import org.jnode.vm.compiler.ir.quad.InterfaceCallQuad;
import org.jnode.vm.compiler.ir.quad.MonitorenterQuad;
import org.jnode.vm.compiler.ir.quad.MonitorexitQuad;
import org.jnode.vm.compiler.ir.quad.NewMultiArrayAssignQuad;
import org.jnode.vm.compiler.ir.quad.NewObjectArrayAssignQuad;
import org.jnode.vm.compiler.ir.quad.NewPrimitiveArrayAssignQuad;
import org.jnode.vm.compiler.ir.quad.NewAssignQuad;
import org.jnode.vm.compiler.ir.quad.Quad;
import org.jnode.vm.compiler.ir.quad.RefAssignQuad;
import org.jnode.vm.compiler.ir.quad.RefStoreQuad;
import org.jnode.vm.compiler.ir.quad.SpecialCallAssignQuad;
import org.jnode.vm.compiler.ir.quad.SpecialCallQuad;
import org.jnode.vm.compiler.ir.quad.StaticCallAssignQuad;
import org.jnode.vm.compiler.ir.quad.StaticCallQuad;
import org.jnode.vm.compiler.ir.quad.StaticRefAssignQuad;
import org.jnode.vm.compiler.ir.quad.StaticRefStoreQuad;
import org.jnode.vm.compiler.ir.quad.LookupswitchQuad;
import org.jnode.vm.compiler.ir.quad.TableswitchQuad;
import org.jnode.vm.compiler.ir.quad.ThrowQuad;
import org.jnode.vm.compiler.ir.quad.UnaryQuad;
import org.jnode.vm.compiler.ir.quad.UnconditionalBranchQuad;
import org.jnode.vm.compiler.ir.quad.VarReturnQuad;
import org.jnode.vm.compiler.ir.quad.VariableRefAssignQuad;
import org.jnode.vm.compiler.ir.quad.VirtualCallAssignQuad;
import org.jnode.vm.compiler.ir.quad.VirtualCallQuad;
import org.jnode.vm.compiler.ir.quad.VoidReturnQuad;
import org.jnode.vm.facade.TypeSizeInfo;
/**
* Intermediate Representation Generator.
* Visits bytecodes of a given method and translates them into a
* list of Quads.
*/
public class IRGenerator<T> extends BytecodeVisitor {
private final Constant<T> NULL_CONSTANT = Constant.getInstance(0); //Constant.getInstance(null);
private int nArgs;
private int nLocals;
private int maxStack;
private int stackOffset;
private Variable<T>[] variables;
private int address;
private Iterator<IRBasicBlock<T>> basicBlockIterator;
private IRBasicBlock<T> currentBlock;
private TypeSizeInfo typeSizeInfo;
private VmClassLoader vmClassLoader;
public IRGenerator(IRControlFlowGraph<T> cfg, TypeSizeInfo typeSizeInfo, VmClassLoader loader) {
basicBlockIterator = cfg.iterator();
currentBlock = basicBlockIterator.next();
this.typeSizeInfo = typeSizeInfo;
this.vmClassLoader = loader;
}
public void setParser(BytecodeParser parser) {
}
public void startMethod(VmMethod method) {
VmByteCode code = method.getBytecode();
nArgs = method.getArgSlotCount();
nLocals = code.getNoLocals();
maxStack = code.getMaxStack();
stackOffset = nLocals;
variables = new Variable[nLocals + maxStack];
int index = 0;
int argCount = method.getNoArguments();
if (!method.isStatic()) {
variables[index] = new MethodArgument<T>(Operand.REFERENCE, index);
index += 1;
}
for (int i = 0; i < argCount; i++) {
VmType argType = method.getArgumentType(i);
int jvmType = argType.isPrimitive() ? argType.getJvmType() : JvmType.REFERENCE;
variables[index] = new MethodArgument<T>(Operand.UNKNOWN, index);
variables[index].setTypeFromJvmType(jvmType);
index += 1;
if (isCategory2(jvmType)) {
variables[index] = new MethodArgument<T>(Operand.UNKNOWN, index);
variables[index].setTypeFromJvmType(jvmType);
index += 1;
}
}
for (int i = nArgs; i < nLocals; i += 1) {
variables[index] = new LocalVariable<T>(Operand.UNKNOWN, index);
index += 1;
}
for (int i = 0; i < maxStack; i += 1) {
variables[index] = new StackVariable<T>(Operand.UNKNOWN, index);
index += 1;
}
currentBlock.setVariables(variables);
}
public void endMethod() {
}
public void startInstruction(int address) {
this.address = address;
if (address >= currentBlock.getEndPC()) {
IRBasicBlock lastBlock = currentBlock;
currentBlock = basicBlockIterator.next();
// Iterator<IRBasicBlock<T>> pi = currentBlock.getPredecessors().iterator();
// if (!pi.hasNext()) {
if (currentBlock.isStartOfExceptionHandler()) {
stackOffset = nLocals;
currentBlock.setStackOffset(stackOffset);
currentBlock.setVariables(variables.clone());
// currentBlock.getVariables()[stackOffset] = new ExceptionArgument(Operand.REFERENCE, stackOffset);
stackOffset++;
// TODO need to set variables also...
} else {
// return;
// }
if (lastBlock != currentBlock.getIDominator()) {
stackOffset = currentBlock.getStackOffset();
}
}
// while (pi.hasNext()) {
// IRBasicBlock irb = (IRBasicBlock) pi.next();
// Variable[] prevVars = irb.getVariables();
// if (prevVars != null) {
// int n = prevVars.length;
// variables = new Variable[n];
// for (int i=0; i<n; i+=1) {
// variables[i] = prevVars[i];
// }
// currentBlock.setVariables(variables);
// return;
// }
// }
// currentBlock.setVariables(currentBlock.getIDominator().getVariables());
}
if (address < currentBlock.getStartPC() || address >= currentBlock.getEndPC()) {
throw new AssertionError("instruction not in basic block!");
}
}
public void endInstruction() {
}
public void visit_nop() {
}
public void visit_aconst_null() {
variables[stackOffset].setType(Operand.REFERENCE);
currentBlock.add(new ConstantRefAssignQuad<T>(address, currentBlock, stackOffset,
NULL_CONSTANT));
stackOffset += 1;
}
public void visit_iconst(int value) {
Constant<T> c = Constant.getInstance(value);
Quad<T> quad = new ConstantRefAssignQuad<T>(address, currentBlock, stackOffset,
c);
currentBlock.add(quad);
stackOffset += 1;
}
public void visit_lconst(long value) {
Constant<T> c = Constant.getInstance(value);
variables[stackOffset].setType(Operand.LONG);
variables[stackOffset + 1].setType(Operand.LONG);
currentBlock.add(new ConstantRefAssignQuad<T>(address, currentBlock, stackOffset, c));
stackOffset += 2;
}
public void visit_fconst(float value) {
Constant<T> c = Constant.getInstance(value);
currentBlock.add(new ConstantRefAssignQuad<T>(address, currentBlock, stackOffset,
c));
stackOffset += 1;
}
public void visit_dconst(double value) {
Constant<T> c = Constant.getInstance(value);
currentBlock.add(new ConstantRefAssignQuad<T>(address, currentBlock, stackOffset, c));
stackOffset += 2;
}
public void visit_ldc(VmConstString value) {
currentBlock.add(new ConstantStringAssignQuad<T>(address, currentBlock, stackOffset, value));
stackOffset++;
}
public final void visit_ldc(VmConstClass value) {
currentBlock.add(new ConstantClassAssignQuad<T>(address, currentBlock, stackOffset, value));
stackOffset++;
}
public void visit_iload(int index) {
variables[index].setType(Operand.INT);
variables[stackOffset].setType(Operand.INT);
VariableRefAssignQuad<T> assignQuad = new VariableRefAssignQuad<T>(address, currentBlock,
stackOffset, index);
currentBlock.add(assignQuad);
stackOffset += 1;
}
public void visit_lload(int index) {
variables[index].setType(Operand.LONG);
variables[stackOffset].setType(Operand.LONG);
variables[stackOffset + 1].setType(Operand.LONG);
currentBlock.add(new VariableRefAssignQuad<T>(address, currentBlock,
stackOffset, index));
stackOffset += 2;
}
public void visit_fload(int index) {
variables[index].setType(Operand.FLOAT);
variables[stackOffset].setType(Operand.FLOAT);
currentBlock.add(new VariableRefAssignQuad<T>(address, currentBlock,
stackOffset, index));
stackOffset += 1;
}
public void visit_dload(int index) {
variables[index].setType(Operand.DOUBLE);
variables[stackOffset].setType(Operand.DOUBLE);
currentBlock.add(new VariableRefAssignQuad<T>(address, currentBlock,
stackOffset, index));
stackOffset += 2;
}
public void visit_aload(int index) {
variables[index].setType(Operand.REFERENCE);
variables[stackOffset].setType(Operand.REFERENCE);
currentBlock.add(new VariableRefAssignQuad<T>(address, currentBlock, stackOffset, index));
stackOffset += 1;
}
public void visit_iaload() {
visitArrayLoad(Operand.INT);
}
public void visit_laload() {
visitArrayLoad(Operand.LONG);
}
public void visit_faload() {
visitArrayLoad(Operand.FLOAT);
}
public void visit_daload() {
visitArrayLoad(Operand.DOUBLE);
}
public void visit_aaload() {
visitArrayLoad(Operand.REFERENCE);
}
public void visit_baload() {
visitArrayLoad(Operand.BYTE);
}
public void visit_caload() {
visitArrayLoad(Operand.CHAR);
}
public void visit_saload() {
visitArrayLoad(Operand.SHORT);
}
public void visit_istore(int index) {
stackOffset -= 1;
variables[index].setType(Operand.INT);
variables[stackOffset].setType(Operand.INT);
currentBlock.add(new VariableRefAssignQuad<T>(address, currentBlock, index, stackOffset));
}
public void visit_lstore(int index) {
stackOffset -= 2;
variables[index].setType(Operand.LONG);
variables[stackOffset].setType(Operand.LONG);
currentBlock.add(new VariableRefAssignQuad<T>(address, currentBlock, index, stackOffset));
}
public void visit_fstore(int index) {
stackOffset -= 1;
variables[index].setType(Operand.FLOAT);
variables[stackOffset].setType(Operand.FLOAT);
currentBlock.add(new VariableRefAssignQuad<T>(address, currentBlock, index, stackOffset));
}
public void visit_dstore(int index) {
stackOffset -= 2;
variables[index].setType(Operand.DOUBLE);
variables[stackOffset].setType(Operand.DOUBLE);
currentBlock.add(new VariableRefAssignQuad<T>(address, currentBlock, index, stackOffset));
}
public void visit_astore(int index) {
stackOffset -= 1;
variables[index].setType(Operand.REFERENCE);
variables[stackOffset].setType(Operand.REFERENCE);
currentBlock.add(new VariableRefAssignQuad<T>(address, currentBlock, index, stackOffset));
}
public void visit_iastore() {
visitArrayStore(Operand.INT);
}
public void visit_lastore() {
visitArrayStore(Operand.LONG);
}
public void visit_fastore() {
visitArrayStore(Operand.FLOAT);
}
public void visit_dastore() {
visitArrayStore(Operand.DOUBLE);
}
public void visit_aastore() {
visitArrayStore(Operand.REFERENCE);
}
public void visit_bastore() {
visitArrayStore(Operand.BYTE);
}
public void visit_castore() {
visitArrayStore(Operand.CHAR);
}
public void visit_sastore() {
visitArrayStore(Operand.SHORT);
}
public void visit_pop() {
stackOffset -= 1;
}
public void visit_pop2() {
stackOffset -= 2;
}
public void visit_dup() {
int index = stackOffset;
stackOffset -= 1;
currentBlock.add(new VariableRefAssignQuad<T>(address, currentBlock, index, stackOffset));
fixType(); //todo fix type for other dups like here
stackOffset += 2;
}
private void fixType() {
List<Quad<T>> quadList = currentBlock.getQuads();
VariableRefAssignQuad<T> currentQuad = (VariableRefAssignQuad<T>) quadList.get(quadList.size() - 1);
if (currentQuad.getLHS().getType() == JvmType.UNKNOWN) {
Operand<T> rhs = currentQuad.getRHS();
List<Quad<T>> quads = quadList;
for (int i = quads.size(); i -- > 0;){
Quad q = quads.get(i);
if (q instanceof AssignQuad) {
AssignQuad a = (AssignQuad) q;
Variable lhs = a.getLHS();
if (lhs.equals(rhs)) {
rhs.setType(lhs.getType());
currentQuad.getLHS().setType(lhs.getType());
break;
}
}
}
if (currentQuad.getLHS().getType() == JvmType.UNKNOWN) {
//todo throw exception here when types should be ok
}
}
}
public void visit_dup_x1() {
// int index = stackOffset;
// stackOffset -= 1;
// currentBlock.add(new VariableRefAssignQuad<T>(address, currentBlock, index, stackOffset - 1));
// currentBlock.add(new VariableRefAssignQuad<T>(address, currentBlock, index - 2, stackOffset));
// currentBlock.add(new VariableRefAssignQuad<T>(address, currentBlock, index - 1, stackOffset + 1));
// currentBlock.add(new VariableRefAssignQuad<T>(address, currentBlock, index, stackOffset - 1));
// stackOffset += 2;
int index = stackOffset;
stackOffset -= 1;
currentBlock.add(new VariableRefAssignQuad<T>(address, currentBlock, index, stackOffset));
fixType();
currentBlock.add(new VariableRefAssignQuad<T>(address, currentBlock, index - 1, stackOffset - 1));
fixType();
currentBlock.add(new VariableRefAssignQuad<T>(address, currentBlock, index - 2, stackOffset + 1));
fixType();
stackOffset += 2;
}
public void visit_dup_x2() {
//form 1
if (!isCategory2(getVariables()[stackOffset - 1].getType()) &&
!isCategory2(getVariables()[stackOffset - 2].getType())) {
int index = stackOffset;
stackOffset -= 1;
currentBlock.add(new VariableRefAssignQuad<T>(address, currentBlock, index, stackOffset));
fixType();
currentBlock.add(new VariableRefAssignQuad<T>(address, currentBlock, index - 1, stackOffset - 1));
fixType();
currentBlock.add(new VariableRefAssignQuad<T>(address, currentBlock, index - 2, stackOffset - 2));
fixType();
currentBlock.add(new VariableRefAssignQuad<T>(address, currentBlock, index - 3, stackOffset + 1));
fixType();
stackOffset += 2;
} else {
throw new IllegalArgumentException("byte code not yet supported");
}
}
public void visit_dup2() {
int index = stackOffset;
Variable var = currentBlock.getVariables()[index - 2];
if (var.getType() == Operand.LONG || var.getType() == Operand.DOUBLE) {
stackOffset -= 2;
currentBlock.add(new VariableRefAssignQuad<T>(address, currentBlock, index, stackOffset));
fixType();
stackOffset += 4;
} else {
stackOffset -= 1;
currentBlock.add(new VariableRefAssignQuad<T>(address, currentBlock, index + 1, stackOffset));
fixType();
stackOffset -= 1;
currentBlock.add(new VariableRefAssignQuad<T>(address, currentBlock, index, stackOffset));
fixType();
stackOffset += 4;
}
}
public void visit_dup2_x1() {
//todo
//form 2;
if (isCategory2(getVariables()[stackOffset - 1].getType()) &&
!isCategory2(getVariables()[stackOffset - 3].getType())) {
int index = stackOffset;
stackOffset -= 2;
currentBlock.add(new VariableRefAssignQuad<T>(address, currentBlock, index, stackOffset));
fixType();
//currentBlock.add(new VariableRefAssignQuad<T>(address, currentBlock, index - 1, stackOffset - 1));
currentBlock.add(new VariableRefAssignQuad<T>(address, currentBlock, index - 1, stackOffset - 1));
fixType();
currentBlock.add(new VariableRefAssignQuad<T>(address, currentBlock, index - 3, stackOffset + 2));
fixType();
//currentBlock.add(new VariableRefAssignQuad<T>(address, currentBlock, index - 4, stackOffset + 1));
stackOffset += 4;
} else {
throw new IllegalArgumentException("byte code not yet supported");
}
}
public void visit_dup2_x2() {
throw new IllegalArgumentException("byte code not yet supported");
}
public void visit_swap() {
throw new IllegalArgumentException("byte code not yet supported");
}
public void visit_iadd() {
currentBlock.add(doBinaryQuad(IADD, Operand.INT));
}
public void visit_ladd() {
currentBlock.add(doBinaryQuad(LADD, Operand.LONG));
}
public void visit_fadd() {
currentBlock.add(doBinaryQuad(FADD, Operand.FLOAT));
}
public void visit_dadd() {
currentBlock.add(doBinaryQuad(DADD, Operand.DOUBLE));
}
public void visit_isub() {
currentBlock.add(doBinaryQuad(ISUB, Operand.INT));
}
public void visit_lsub() {
currentBlock.add(doBinaryQuad(LSUB, Operand.LONG));
}
public void visit_fsub() {
currentBlock.add(doBinaryQuad(FSUB, Operand.FLOAT));
}
public void visit_dsub() {
currentBlock.add(doBinaryQuad(DSUB, Operand.DOUBLE));
}
public void visit_imul() {
currentBlock.add(doBinaryQuad(IMUL, Operand.INT));
}
public void visit_lmul() {
currentBlock.add(doBinaryQuad(LMUL, Operand.LONG));
}
public void visit_fmul() {
currentBlock.add(doBinaryQuad(FMUL, Operand.FLOAT));
}
public void visit_dmul() {
currentBlock.add(doBinaryQuad(DMUL, Operand.DOUBLE));
}
public void visit_idiv() {
currentBlock.add(doBinaryQuad(IDIV, Operand.INT));
}
public void visit_ldiv() {
currentBlock.add(doBinaryQuad(LDIV, Operand.LONG));
}
public void visit_fdiv() {
currentBlock.add(doBinaryQuad(FDIV, Operand.FLOAT));
}
public void visit_ddiv() {
currentBlock.add(doBinaryQuad(DDIV, Operand.DOUBLE));
}
public void visit_irem() {
currentBlock.add(doBinaryQuad(IREM, Operand.INT));
}
public void visit_lrem() {
currentBlock.add(doBinaryQuad(LREM, Operand.LONG));
}
public void visit_frem() {
currentBlock.add(doBinaryQuad(FREM, Operand.FLOAT));
}
public void visit_drem() {
currentBlock.add(doBinaryQuad(DREM, Operand.DOUBLE));
}
public void visit_ineg() {
int s1 = stackOffset - 1;
variables[s1].setType(Operand.INT);
currentBlock.add(new UnaryQuad<T>(address, currentBlock, s1, INEG, s1));
}
public void visit_lneg() {
int s1 = stackOffset - 2;
variables[s1].setType(Operand.LONG);
currentBlock.add(new UnaryQuad<T>(address, currentBlock, s1, LNEG, s1));
}
public void visit_fneg() {
int s1 = stackOffset - 1;
variables[s1].setType(Operand.FLOAT);
currentBlock.add(new UnaryQuad<T>(address, currentBlock, s1, FNEG, s1));
}
public void visit_dneg() {
int s1 = stackOffset - 2;
variables[s1].setType(Operand.DOUBLE);
currentBlock.add(new UnaryQuad<T>(address, currentBlock, s1, DNEG, s1));
}
public void visit_ishl() {
currentBlock.add(doBinaryQuad(ISHL, Operand.INT));
}
public void visit_lshl() {
stackOffset -= 1;
int s1 = stackOffset - 2;
variables[s1].setType(Operand.LONG);
variables[stackOffset].setType(Operand.INT);
currentBlock.add(new BinaryQuad<T>(address, currentBlock, s1, s1, LSHL, stackOffset));
}
public void visit_ishr() {
currentBlock.add(doBinaryQuad(ISHR, Operand.INT));
}
public void visit_lshr() {
stackOffset -= 1;
int s1 = stackOffset - 2;
variables[s1].setType(Operand.LONG);
variables[stackOffset].setType(Operand.INT);
currentBlock.add(new BinaryQuad<T>(address, currentBlock, s1, s1, LSHR, stackOffset));
}
public void visit_iushr() {
currentBlock.add(doBinaryQuad(IUSHR, Operand.INT));
}
public void visit_lushr() {
stackOffset -= 2;
int s1 = stackOffset - 1;
variables[s1].setType(Operand.LONG);
variables[s1 + 1].setType(Operand.LONG);
variables[stackOffset + 1].setType(Operand.INT);
currentBlock.add(new BinaryQuad<T>(address, currentBlock, s1, s1, LUSHR, stackOffset + 1));
stackOffset += 1;
}
public void visit_iand() {
currentBlock.add(doBinaryQuad(IAND, Operand.INT));
}
public void visit_land() {
currentBlock.add(doBinaryQuad(LAND, Operand.LONG));
}
public void visit_ior() {
currentBlock.add(doBinaryQuad(IOR, Operand.INT));
}
public void visit_lor() {
currentBlock.add(doBinaryQuad(LOR, Operand.LONG));
}
public void visit_ixor() {
currentBlock.add(doBinaryQuad(IXOR, Operand.INT));
}
public void visit_lxor() {
currentBlock.add(doBinaryQuad(LXOR, Operand.LONG));
}
public void visit_iinc(int index, int incValue) {
variables[index].setType(Operand.INT);
BinaryQuad<T> binaryQuad =
new BinaryQuad<T>(address, currentBlock, index, index, IADD, new IntConstant<T>(incValue));
currentBlock.add(binaryQuad.foldConstants());
}
public void visit_i2l() {
stackOffset -= 1;
variables[stackOffset].setType(Operand.LONG);
currentBlock.add(new UnaryQuad<T>(address, currentBlock, stackOffset, I2L, stackOffset));
stackOffset += 2;
}
public void visit_i2f() {
stackOffset -= 1;
variables[stackOffset].setType(Operand.FLOAT);
currentBlock.add(new UnaryQuad<T>(address, currentBlock, stackOffset, I2F, stackOffset));
stackOffset += 1;
}
public void visit_i2d() {
stackOffset -= 1;
variables[stackOffset].setType(Operand.DOUBLE);
currentBlock.add(new UnaryQuad<T>(address, currentBlock, stackOffset, I2D, stackOffset));
stackOffset += 2;
}
public void visit_l2i() {
stackOffset -= 2;
variables[stackOffset].setType(Operand.INT);
currentBlock.add(new UnaryQuad<T>(address, currentBlock, stackOffset, L2I, stackOffset));
stackOffset += 1;
}
public void visit_l2f() {
stackOffset -= 2;
variables[stackOffset].setType(Operand.FLOAT);
currentBlock.add(new UnaryQuad<T>(address, currentBlock, stackOffset, L2F, stackOffset));
stackOffset += 1;
}
public void visit_l2d() {
stackOffset -= 2;
variables[stackOffset].setType(Operand.DOUBLE);
currentBlock.add(new UnaryQuad<T>(address, currentBlock, stackOffset, L2D, stackOffset));
stackOffset += 2;
}
public void visit_f2i() {
stackOffset -= 1;
variables[stackOffset].setType(Operand.INT);
currentBlock.add(new UnaryQuad<T>(address, currentBlock, stackOffset, F2I, stackOffset));
stackOffset += 1;
}
public void visit_f2l() {
stackOffset -= 1;
variables[stackOffset].setType(Operand.LONG);
currentBlock.add(new UnaryQuad<T>(address, currentBlock, stackOffset, F2L, stackOffset));
stackOffset += 2;
}
public void visit_f2d() {
stackOffset -= 1;
variables[stackOffset].setType(Operand.DOUBLE);
currentBlock.add(new UnaryQuad<T>(address, currentBlock, stackOffset, F2D, stackOffset));
stackOffset += 2;
}
public void visit_d2i() {
stackOffset -= 2;
variables[stackOffset].setType(Operand.INT);
currentBlock.add(new UnaryQuad<T>(address, currentBlock, stackOffset, D2I, stackOffset));
stackOffset += 1;
}
public void visit_d2l() {
stackOffset -= 2;
variables[stackOffset].setType(Operand.LONG);
currentBlock.add(new UnaryQuad<T>(address, currentBlock, stackOffset, D2L, stackOffset));
stackOffset += 2;
}
public void visit_d2f() {
stackOffset -= 2;
variables[stackOffset].setType(Operand.FLOAT);
currentBlock.add(new UnaryQuad<T>(address, currentBlock, stackOffset, D2F, stackOffset));
stackOffset += 1;
}
public void visit_i2b() {
stackOffset -= 1;
variables[stackOffset].setType(Operand.BYTE);
currentBlock.add(new UnaryQuad<T>(address, currentBlock, stackOffset, I2B, stackOffset));
stackOffset += 1;
}
public void visit_i2c() {
stackOffset -= 1;
variables[stackOffset].setType(Operand.CHAR);
currentBlock.add(new UnaryQuad<T>(address, currentBlock, stackOffset, I2C, stackOffset));
stackOffset += 1;
}
public void visit_i2s() {
stackOffset -= 1;
variables[stackOffset].setType(Operand.SHORT);
currentBlock.add(new UnaryQuad<T>(address, currentBlock, stackOffset, I2S, stackOffset));
stackOffset += 1;
}
public void visit_lcmp() {
currentBlock.add(doBinaryQuad(LCMP, Operand.LONG));
}
public void visit_fcmpl() {
currentBlock.add(doBinaryQuad(FCMPL, Operand.FLOAT));
}
public void visit_fcmpg() {
currentBlock.add(doBinaryQuad(FCMPG, Operand.FLOAT));
}
public void visit_dcmpl() {
currentBlock.add(doBinaryQuad(DCMPL, Operand.DOUBLE));
}
public void visit_dcmpg() {
currentBlock.add(doBinaryQuad(DCMPG, Operand.DOUBLE));
}
public void visit_ifeq(int address) {
visitBranchCondition(address, IFEQ, Operand.INT);
}
public void visit_ifne(int address) {
visitBranchCondition(address, IFNE, Operand.INT);
}
public void visit_iflt(int address) {
visitBranchCondition(address, IFLT, Operand.INT);
}
public void visit_ifge(int address) {
visitBranchCondition(address, IFGE, Operand.INT);
}
public void visit_ifgt(int address) {
visitBranchCondition(address, IFGT, Operand.INT);
}
public void visit_ifle(int address) {
visitBranchCondition(address, IFLE, Operand.INT);
}
public void visit_if_icmpeq(int address) {
visitBranchCondition(address, IF_ICMPEQ, Operand.INT);
}
public void visit_if_icmpne(int address) {
visitBranchCondition(address, IF_ICMPNE, Operand.INT);
}
public void visit_if_icmplt(int address) {
visitBranchCondition(address, IF_ICMPLT, Operand.INT);
}
public void visit_if_icmpge(int address) {
visitBranchCondition(address, IF_ICMPGE, Operand.INT);
}
public void visit_if_icmpgt(int address) {
visitBranchCondition(address, IF_ICMPGT, Operand.INT);
}
public void visit_if_icmple(int address) {
visitBranchCondition(address, IF_ICMPLE, Operand.INT);
}
public void visit_if_acmpeq(int address) {
visitBranchCondition(address, IF_ACMPEQ, Operand.REFERENCE);
}
public void visit_if_acmpne(int address) {
visitBranchCondition(address, IF_ACMPNE, Operand.REFERENCE);
}
public void visit_goto(int address) {
currentBlock.add(new UnconditionalBranchQuad<T>(this.address, currentBlock, address));
setSuccessorStackOffset();
}
public void visit_tableswitch(int defValue, int lowValue, int highValue, int[] addresses) {
stackOffset -= 1;
currentBlock.add(new TableswitchQuad<T>(address, currentBlock, defValue, lowValue, highValue, addresses,
stackOffset));
setSuccessorStackOffset();
}
public void visit_lookupswitch(int defAddress, int[] matchValues, int[] addresses) {
stackOffset -= 1;
currentBlock.add(new LookupswitchQuad<T>(address, currentBlock, defAddress, matchValues, addresses,
stackOffset));
setSuccessorStackOffset();
}
public void visit_ireturn() {
stackOffset -= 1;
variables[stackOffset].setType(Operand.INT);
currentBlock.add(new VarReturnQuad<T>(address, currentBlock, stackOffset));
}
public void visit_lreturn() {
stackOffset -= 2;
variables[stackOffset].setType(Operand.LONG);
currentBlock.add(new VarReturnQuad<T>(address, currentBlock, stackOffset));
}
public void visit_freturn() {
stackOffset -= 1;
variables[stackOffset].setType(Operand.FLOAT);
currentBlock.add(new VarReturnQuad<T>(address, currentBlock, stackOffset));
}
public void visit_dreturn() {
stackOffset -= 2;
variables[stackOffset].setType(Operand.DOUBLE);
currentBlock.add(new VarReturnQuad<T>(address, currentBlock, stackOffset));
}
public void visit_areturn() {
stackOffset -= 1;
variables[stackOffset].setType(Operand.REFERENCE);
currentBlock.add(new VarReturnQuad<T>(address, currentBlock, stackOffset));
}
public void visit_return() {
currentBlock.add(new VoidReturnQuad<T>(address, currentBlock));
}
public void visit_getstatic(VmConstFieldRef fieldRef) {
fieldRef.resolve(vmClassLoader);
int jvmType = fieldRef.getResolvedVmField().getType().getJvmType();
variables[stackOffset].setTypeFromJvmType(jvmType);
currentBlock.add(new StaticRefAssignQuad<T>(address, currentBlock, stackOffset, fieldRef));
stackOffset += getCategory(jvmType);
}
public void visit_putstatic(VmConstFieldRef fieldRef) {
fieldRef.resolve(vmClassLoader);
int jvmType = fieldRef.getResolvedVmField().getType().getJvmType();
stackOffset -= getCategory(jvmType);
currentBlock.add(new StaticRefStoreQuad<T>(address, currentBlock, stackOffset, fieldRef));
}
public void visit_getfield(VmConstFieldRef fieldRef) {
fieldRef.resolve(vmClassLoader);
stackOffset -= 1;
int jvmType = fieldRef.getResolvedVmField().getType().getJvmType();
variables[stackOffset].setTypeFromJvmType(jvmType);
currentBlock.add(new RefAssignQuad<T>(address, currentBlock, stackOffset, fieldRef, stackOffset));
stackOffset += getCategory(jvmType);
}
public void visit_putfield(VmConstFieldRef fieldRef) {
fieldRef.resolve(vmClassLoader);
int jvmType = fieldRef.getResolvedVmField().getType().getJvmType();
stackOffset -= getCategory(jvmType);
int ref = stackOffset - 1;
currentBlock.add(new RefStoreQuad<T>(address, currentBlock, stackOffset, fieldRef, ref));
stackOffset -= 1;
}
public void visit_invokevirtual(VmConstMethodRef methodRef) {
methodRef.resolve(vmClassLoader);
VmMethod vmMethod = methodRef.getResolvedVmMethod();
int nrArguments = vmMethod.getNoArguments();
int[] varOffs = new int[nrArguments + 1];
for (int i = nrArguments; i-- > 0;) {
VmType argType = vmMethod.getArgumentType(i);
int stackChange;
int jvmType;
if (argType.isPrimitive()) {
jvmType = argType.getJvmType();
stackChange = getCategory(jvmType);
} else {
stackChange = 1;
jvmType = JvmType.REFERENCE;
}
stackOffset -= stackChange;
variables[stackOffset].setTypeFromJvmType(jvmType);
varOffs[i + 1] = stackOffset;
}
stackOffset--;
variables[stackOffset].setType(Operand.REFERENCE);
varOffs[0] = stackOffset;
int returnType = JvmType.getReturnType(methodRef.getSignature());
if (JvmType.VOID == returnType) {
currentBlock.add(new VirtualCallQuad(address, currentBlock, methodRef, varOffs));
} else {
currentBlock.add(new VirtualCallAssignQuad(address, currentBlock, stackOffset, methodRef, varOffs));
stackOffset += typeSizeInfo.getStackSlots(returnType);
}
// int argSlotCount = Signature.getArgSlotCount(typeSizeInfo, methodRef.getSignature());
// int returnType = JvmType.getReturnType(methodRef.getSignature());
// if (JvmType.VOID == returnType) {
// int[] varOffs = new int[argSlotCount + 1];
// for (int i = 0; i < argSlotCount; i++) {
// stackOffset--;
// variables[stackOffset].setType(Operand.INT);
// varOffs[i] = stackOffset;
// }
// stackOffset--;
// variables[argSlotCount].setType(Operand.REFERENCE);
// varOffs[argSlotCount] = stackOffset;
// currentBlock.add(new VirtualCallQuad(address, currentBlock, methodRef, varOffs));
// } else {
// int[] varOffs = new int[argSlotCount + 1];
// for (int i = 0; i < argSlotCount; i++) {
// stackOffset--;
// variables[stackOffset].setType(Operand.INT);
// varOffs[i] = stackOffset;
// }
// stackOffset--;
// variables[argSlotCount].setType(Operand.REFERENCE);
// varOffs[argSlotCount] = stackOffset;
// currentBlock.add(new VirtualCallAssignQuad(address, currentBlock, stackOffset, methodRef, varOffs));
// stackOffset += typeSizeInfo.getStackSlots(returnType);
// }
}
public void visit_invokespecial(VmConstMethodRef methodRef) {
methodRef.resolve(vmClassLoader);
VmMethod vmMethod = methodRef.getResolvedVmMethod();
int nrArguments = vmMethod.getNoArguments();
int[] varOffs = new int[nrArguments + 1];
for (int i = nrArguments; i-- > 0;) {
VmType argType = vmMethod.getArgumentType(i);
int stackChange;
int jvmType;
if (argType.isPrimitive()) {
jvmType = argType.getJvmType();
stackChange = getCategory(jvmType);
} else {
stackChange = 1;
jvmType = JvmType.REFERENCE;
}
stackOffset -= stackChange;
variables[stackOffset].setTypeFromJvmType(jvmType);
varOffs[i + 1] = stackOffset;
}
stackOffset--;
variables[stackOffset].setType(Operand.REFERENCE);
varOffs[0] = stackOffset;
int returnType = JvmType.getReturnType(methodRef.getSignature());
if (JvmType.VOID == returnType) {
currentBlock.add(new SpecialCallQuad(address, currentBlock, methodRef, varOffs));
} else {
currentBlock.add(new SpecialCallAssignQuad(address, currentBlock, stackOffset, methodRef, varOffs));
stackOffset += typeSizeInfo.getStackSlots(returnType);
}
// int argSlotCount = Signature.getArgSlotCount(typeSizeInfo, methodRef.getSignature());
// int returnType = JvmType.getReturnType(methodRef.getSignature());
// if (JvmType.VOID == returnType) {
// int[] varOffs = new int[argSlotCount + 1];
// for (int i = 0; i < argSlotCount; i++) {
// stackOffset--;
// variables[stackOffset].setType(Operand.INT);
// varOffs[i] = stackOffset;
// }
// stackOffset--;
// variables[argSlotCount].setType(Operand.REFERENCE);
// varOffs[argSlotCount] = stackOffset;
// currentBlock.add(new SpecialCallQuad(address, currentBlock, methodRef, varOffs));
// } else {
// int[] varOffs = new int[argSlotCount + 1];
// for (int i = 0; i < argSlotCount; i++) {
// stackOffset--;
// variables[stackOffset].setType(Operand.INT);
// varOffs[i] = stackOffset;
// }
// stackOffset--;
// variables[argSlotCount].setType(Operand.REFERENCE);
// varOffs[argSlotCount] = stackOffset;
// currentBlock.add(new SpecialCallAssignQuad(address, currentBlock, stackOffset, methodRef, varOffs));
// stackOffset++;
// }
}
public void visit_invokestatic(VmConstMethodRef methodRef) {
methodRef.resolve(vmClassLoader);
VmMethod vmMethod = methodRef.getResolvedVmMethod();
int nrArguments = vmMethod.getNoArguments();
int[] varOffs = new int[nrArguments];
for (int i = nrArguments; i-- > 0;) {
VmType argType = vmMethod.getArgumentType(i);
int stackChange;
int jvmType;
if (argType.isPrimitive()) {
jvmType = argType.getJvmType();
stackChange = getCategory(jvmType);
} else {
stackChange = 1;
jvmType = JvmType.REFERENCE;
}
stackOffset -= stackChange;
variables[stackOffset].setTypeFromJvmType(jvmType);
varOffs[i] = stackOffset;
}
int returnType = JvmType.getReturnType(methodRef.getSignature());
if (JvmType.VOID == returnType) {
currentBlock.add(new StaticCallQuad(address, currentBlock, methodRef, varOffs));
} else {
currentBlock.add(new StaticCallAssignQuad(address, currentBlock, stackOffset, methodRef, varOffs));
stackOffset += typeSizeInfo.getStackSlots(returnType);
}
// int argSlotCount = Signature.getArgSlotCount(typeSizeInfo, methodRef.getSignature());
// int returnType = JvmType.getReturnType(methodRef.getSignature());
// if (JvmType.VOID == returnType) {
// int[] varOffs = new int[argSlotCount];
// for (int i = 0; i < argSlotCount; i++) {
// stackOffset--;
// variables[stackOffset].setType(Operand.INT);
// varOffs[i] = stackOffset;
// }
// currentBlock.add(new StaticCallQuad<T>(address, currentBlock, methodRef, varOffs));
// } else {
// int[] varOffs = new int[argSlotCount];
// for (int i = 0; i < argSlotCount; i++) {
// stackOffset--;
// variables[stackOffset].setType(Operand.INT);
// varOffs[i] = stackOffset;
// }
// currentBlock.add(new StaticCallAssignQuad<T>(address, currentBlock, stackOffset, methodRef, varOffs));
// stackOffset++;
// }
}
public void visit_invokeinterface(VmConstIMethodRef methodRef, int count) {
methodRef.resolve(vmClassLoader);
VmMethod vmMethod = methodRef.getResolvedVmMethod();
int nrArguments = vmMethod.getNoArguments();
int[] varOffs = new int[nrArguments + 1];
for (int i = nrArguments; i-- > 0;) {
VmType argType = vmMethod.getArgumentType(i);
int stackChange;
int jvmType;
if (argType.isPrimitive()) {
jvmType = argType.getJvmType();
stackChange = getCategory(jvmType);
} else {
stackChange = 1;
jvmType = JvmType.REFERENCE;
}
stackOffset -= stackChange;
variables[stackOffset].setTypeFromJvmType(jvmType);
varOffs[i + 1] = stackOffset;
}
stackOffset--;
variables[stackOffset].setType(Operand.REFERENCE);
varOffs[0] = stackOffset;
int returnType = JvmType.getReturnType(methodRef.getSignature());
if (JvmType.VOID == returnType) {
currentBlock.add(new InterfaceCallQuad(address, currentBlock, methodRef, varOffs));
} else {
currentBlock.add(new InterfaceCallAssignQuad(address, currentBlock, stackOffset, methodRef, varOffs));
stackOffset += typeSizeInfo.getStackSlots(returnType);
}
// int argSlotCount = Signature.getArgSlotCount(typeSizeInfo, methodRef.getSignature());
// int returnType = JvmType.getReturnType(methodRef.getSignature());
// if (JvmType.VOID == returnType) {
// int[] varOffs = new int[argSlotCount + 1];
// for (int i = 0; i < argSlotCount; i++) {
// stackOffset--;
// variables[stackOffset].setType(Operand.INT);
// varOffs[i] = stackOffset;
// }
// stackOffset--;
// variables[argSlotCount].setType(Operand.REFERENCE);
// varOffs[argSlotCount] = stackOffset;
// currentBlock.add(new InterfaceCallQuad(address, currentBlock, methodRef, varOffs));
// } else {
// int[] varOffs = new int[argSlotCount + 1];
// for (int i = 0; i < argSlotCount; i++) {
// stackOffset--;
// variables[stackOffset].setType(Operand.INT);
// varOffs[i] = stackOffset;
// }
// stackOffset--;
// variables[argSlotCount].setType(Operand.REFERENCE);
// varOffs[argSlotCount] = stackOffset;
// currentBlock.add(new InterfaceCallAssignQuad(address, currentBlock, stackOffset, methodRef, varOffs));
// stackOffset += typeSizeInfo.getStackSlots(returnType);
// }
}
public void visit_new(VmConstClass clazz) {
currentBlock.add(new NewAssignQuad<T>(address, currentBlock, stackOffset, clazz));
stackOffset++;
}
public void visit_newarray(int type) {
stackOffset -= 1;
currentBlock.add(new NewPrimitiveArrayAssignQuad<T>(address, currentBlock, stackOffset, type, stackOffset));
stackOffset += 1;
}
public void visit_anewarray(VmConstClass clazz) {
stackOffset -= 1;
currentBlock.add(new NewObjectArrayAssignQuad<T>(address, currentBlock, stackOffset, clazz, stackOffset));
stackOffset += 1;
}
public void visit_arraylength() {
stackOffset -= 1;
currentBlock.add(new ArrayLengthAssignQuad(address, currentBlock, stackOffset, stackOffset));
stackOffset += 1;
}
public void visit_athrow() {
stackOffset -= 1;
currentBlock.add(new ThrowQuad<T>(address, currentBlock, stackOffset));
stackOffset = nLocals + 1;
}
public void visit_checkcast(VmConstClass clazz) {
stackOffset -= 1;
currentBlock.add(new CheckcastQuad<T>(address, currentBlock, clazz, stackOffset));
stackOffset += 1;
}
public void visit_instanceof(VmConstClass clazz) {
stackOffset -= 1;
currentBlock.add(new InstanceofAssignQuad<T>(address, currentBlock, stackOffset, clazz, stackOffset));
stackOffset += 1;
}
public void visit_monitorenter() {
stackOffset -= 1;
currentBlock.add(new MonitorenterQuad<T>(address, currentBlock, stackOffset));
}
public void visit_monitorexit() {
stackOffset -= 1;
currentBlock.add(new MonitorexitQuad<T>(address, currentBlock, stackOffset));
}
public void visit_multianewarray(VmConstClass clazz, int dimensions) {
stackOffset -= 1;
int[] sizes = new int[dimensions];
for (int i = 0; i < dimensions; i++) {
sizes[i] = stackOffset;
stackOffset -= 1;
}
stackOffset += 1;
currentBlock.add(new NewMultiArrayAssignQuad<T>(address, currentBlock, stackOffset, clazz, sizes));
stackOffset += 1;
}
public void visit_ifnull(int address) {
visitBranchCondition(address, IFNULL, Operand.REFERENCE);
}
public void visit_ifnonnull(int address) {
visitBranchCondition(address, IFNONNULL, Operand.REFERENCE);
}
public void visit_jsr(int address) {
throw new UnsupportedOperationException("Byte code not supported: jsr");
}
public void visit_ret(int index) {
throw new UnsupportedOperationException("Byte code not supported: ret");
}
// TODO
public Quad<T> doBinaryQuad(BinaryOperation op, int type) {
int sCount = 1;
if (type == Operand.DOUBLE || type == Operand.LONG) {
sCount = 2;
}
stackOffset -= sCount;
int s1 = stackOffset - sCount;
Variable[] variables = currentBlock.getVariables();
variables[s1].setType(type);
variables[stackOffset].setType(type);
BinaryQuad<T> bop = new BinaryQuad<T>(address, currentBlock, s1, s1, op, stackOffset);
if (op == BinaryOperation.LCMP || op == BinaryOperation.DCMPL || op == BinaryOperation.DCMPG) {
stackOffset -= 1;
}
return bop.foldConstants();
}
/**
* @return the variables
*/
public Variable<T>[] getVariables() {
return variables;
}
/**
* @return the number of args
*/
public int getNoArgs() {
return this.nArgs;
}
private void setSuccessorStackOffset() {
// this is needed for terniary operators, the stack is not the
// same as our dominator
for (IRBasicBlock b : currentBlock.getSuccessors()) {
b.setStackOffset(stackOffset);
}
}
//*********************** HELPER METHODS *****************************//
private void visitArrayLoad(int arrayType) {
stackOffset -= 1;
int ind = stackOffset;
int ref = stackOffset - 1;
variables[ind].setType(Operand.INT);
variables[ref].setType(Operand.REFERENCE);
currentBlock.add(new ArrayAssignQuad(address, currentBlock, ref, ind, ref, arrayType));
if (arrayType == Operand.LONG || arrayType == Operand.DOUBLE) {
stackOffset += 1;
}
}
private void visitArrayStore(int arrayType) {
stackOffset -= 1;
int disp = arrayType == Operand.LONG || arrayType == Operand.DOUBLE ? 1 : 0;
int val = stackOffset - disp;
int ind = stackOffset - disp - 1;
int ref = stackOffset - disp - 2;
variables[ind].setType(Operand.INT);
variables[val].setType(arrayType);
variables[ref].setType(Operand.REFERENCE);
currentBlock.add(new ArrayStoreQuad(address, currentBlock, val, ind, ref, arrayType));
stackOffset -= disp + 2;
}
private void visitBranchCondition(int address, BranchCondition condition, int type) {
if (condition.isUnary()) {
int s1 = stackOffset - 1;
Variable[] variables1 = currentBlock.getVariables();
variables1[s1].setType(type);
currentBlock.add(new ConditionalBranchQuad<T>(this.address, currentBlock, s1, condition, address));
stackOffset -= 1;
setSuccessorStackOffset();
} else {
int s1 = stackOffset - 2;
int s2 = stackOffset - 1;
Variable[] variables1 = currentBlock.getVariables();
variables1[s1].setType(type);
variables1[s2].setType(type);
currentBlock.add(new ConditionalBranchQuad<T>(this.address, currentBlock, s1, condition, s2, address));
stackOffset -= 2;
setSuccessorStackOffset();
}
}
//todo review useage; move this method to VmType ?
private int getCategory(int jvmType) {
return isCategory2(jvmType) ? 2 : 1;
}
private boolean isCategory2(int jvmType) {
return jvmType == JvmType.LONG || jvmType == JvmType.DOUBLE;
}
}