case Const.INSTANCEOF:
{
int index= bytes.readUnsignedShort();
InstanceofExpression ex= new InstanceofExpression();
Expression objectref= stack.pop();
ex.setLeftOperand(objectref);
ConstantClass c= (ConstantClass) constantPool.getConstant(index);
ObjectType type= new ObjectType(c.getBytes(constantPool).replace('/', '.'));
ex.setRightOperand(type);
ex.widen(objectref);
instruction= ex;
break;
}
case Const.ACONST_NULL:
instruction= new NullLiteral();
break;
case Const.JSR:
{
instruction= new JumpSubRoutine(currentIndex + bytes.readShort());
opStackDelta= 0;
break;
}
case Const.JSR_W:
{
instruction= new JumpSubRoutine(currentIndex + bytes.readInt());
break;
}
case Const.IFEQ:
instruction= createConditional(currentIndex, InfixExpression.Operator.EQUALS, NumberLiteral.create(0));
break;
case Const.IFNE:
instruction= createConditional(currentIndex, InfixExpression.Operator.NOT_EQUALS, NumberLiteral.create(0));
break;
case Const.IFGE:
instruction= createConditional(currentIndex, InfixExpression.Operator.GREATER_EQUALS, NumberLiteral.create(0));
break;
case Const.IFGT:
instruction= createConditional(currentIndex, InfixExpression.Operator.GREATER, NumberLiteral.create(0));
break;
case Const.IFLE:
instruction= createConditional(currentIndex, InfixExpression.Operator.LESS_EQUALS, NumberLiteral.create(0));
break;
case Const.IFLT:
instruction= createConditional(currentIndex, InfixExpression.Operator.LESS, NumberLiteral.create(0));
break;
case Const.IFNONNULL:
instruction= createConditional(currentIndex, InfixExpression.Operator.NOT_EQUALS, new NullLiteral());
break;
case Const.IFNULL:
instruction= createConditional(currentIndex, InfixExpression.Operator.EQUALS, new NullLiteral());
break;
case Const.IF_ACMPEQ:
case Const.IF_ICMPEQ:
instruction= createConditional(currentIndex, InfixExpression.Operator.EQUALS);
break;
case Const.IF_ACMPNE:
case Const.IF_ICMPNE:
instruction= createConditional(currentIndex, InfixExpression.Operator.NOT_EQUALS);
break;
case Const.IF_ICMPGE:
instruction= createConditional(currentIndex, InfixExpression.Operator.GREATER_EQUALS);
break;
case Const.IF_ICMPGT:
instruction= createConditional(currentIndex, InfixExpression.Operator.GREATER);
break;
case Const.IF_ICMPLE:
instruction= createConditional(currentIndex, InfixExpression.Operator.LESS_EQUALS);
break;
case Const.IF_ICMPLT:
instruction= createConditional(currentIndex, InfixExpression.Operator.LESS);
break;
case Const.LCMP:
case Const.FCMPL:
case Const.FCMPG:
case Const.DCMPL:
case Const.DCMPG:
{
MethodBinding binding= MethodBinding.lookup("javascript.Utils", "cmp", "(DDI)I");
MethodInvocation mi= new MethodInvocation(methodDecl, binding);
Expression value2= stack.pop();
mi.addArgument(stack.pop());
mi.addArgument(value2);
int gORl= 0;
if (instructionType.getName().endsWith("g"))
gORl= 1;
else if (instructionType.getName().endsWith("l"))
gORl= -1;
mi.addArgument(NumberLiteral.create(gORl));
instruction= mi;
break;
}
case Const.GOTO:
{
instruction= new Jump(currentIndex + bytes.readShort());
break;
}
case Const.GOTO_W:
{
instruction= new Jump(currentIndex + bytes.readInt());
break;
}
case Const.NEW:
{
ConstantClass c= (ConstantClass) constantPool.getConstant(bytes.readUnsignedShort());
ObjectType type= new ObjectType(c.getBytes(constantPool).replace('/', '.'));
instruction= new ClassInstanceCreation(type);
}
break;
case Const.NEWARRAY:
{
String componentSignature= BasicType.getType(bytes.readByte()).getSignature();
List<ASTNode> dimensions= new ArrayList<ASTNode>();
dimensions.add(stack.pop());
ArrayCreation ac= new ArrayCreation(methodDecl, new ObjectType("[" + componentSignature), dimensions);
instruction= ac;
break;
}
case Const.ANEWARRAY:
{
ConstantClass c= (ConstantClass) constantPool.getConstant(bytes.readUnsignedShort());
String componentSignature= c.getBytes(constantPool).replace('/', '.');
Type arrayType;
if (componentSignature.startsWith("["))
{
arrayType= new ObjectType("[" + componentSignature);
}
else
{
arrayType= new ObjectType("[L" + componentSignature + ";");
}
List<ASTNode> dimensions= new ArrayList<ASTNode>();
dimensions.add(stack.pop());
ArrayCreation ac= new ArrayCreation(methodDecl, arrayType, dimensions);
instruction= ac;
break;
}
case Const.MULTIANEWARRAY:
{
ConstantClass c= (ConstantClass) constantPool.getConstant(bytes.readUnsignedShort());
ObjectType arrayType= new ObjectType(c.getBytes(constantPool).replace('/', '.'));
int dimCount= bytes.readUnsignedByte();
opStackDelta= 1 - dimCount;
List<ASTNode> dimensions= new ArrayList<ASTNode>();
for (int i= 0; i < dimCount; i++)
{
dimensions.add(0, stack.pop());
}
ArrayCreation ac= new ArrayCreation(methodDecl, arrayType, dimensions);
instruction= ac;
break;
}
case Const.PUTSTATIC:
case Const.PUTFIELD:
{
Assignment a= new Assignment(Assignment.Operator.ASSIGN);
Expression rhs= stack.pop();
int index= bytes.readUnsignedShort();
ConstantFieldref fieldRef= (ConstantFieldref) constantPool.getConstant(index, Constants.CONSTANT_Fieldref);
FieldAccess fa= new FieldWrite();
fa.setName(getFieldName(fieldRef));
fa.setType(new ObjectType(fieldRef.getClass(constantPool)));
fa.initialize(methodDecl);
if (opcode == Const.PUTFIELD)
{
fa.setExpression(stack.pop());
}
a.setLeftHandSide(fa);
a.setRightHandSide(rhs);
instruction= a;
break;
}
case Const.GETFIELD:
{
int index= bytes.readUnsignedShort();
ConstantFieldref fieldRef= (ConstantFieldref) constantPool.getConstant(index, Constants.CONSTANT_Fieldref);
Expression ex= stack.pop();
FieldAccess fa= new FieldRead();
fa.setType(new ObjectType(fieldRef.getClass(constantPool)));
fa.setName(getFieldName(fieldRef));
fa.setExpression(ex);
fa.initialize(methodDecl);
instruction= fa;
break;
}
case Const.GETSTATIC:
{
int index= bytes.readUnsignedShort();
ConstantFieldref fieldRef= (ConstantFieldref) constantPool.getConstant(index, Constants.CONSTANT_Fieldref);
FieldAccess fa= new FieldRead();
fa.setType(new ObjectType(fieldRef.getClass(constantPool)));
fa.setName(getFieldName(fieldRef));
fa.initialize(methodDecl);
instruction= fa;
break;
}
case Const.DUP:
{
dup1();
instruction= stack.pop();
break;
}
case Const.DUP2:
if (form.getIndex() == 0)
{
dup2();
instruction= stack.pop();
}
else
{
dup1();
instruction= stack.pop();
}
break;
case Const.DUP_X1:
{
dup1();
stack.rotate(2);
instruction= stack.pop();
break;
}
case Const.DUP_X2:
{
if (form.getIndex() == 0)
{
dup1();
stack.rotate(3);
}
else
{
dup1();
stack.rotate(2);
}
instruction= stack.pop();
break;
}
case Const.DUP2_X1:
if (form.getIndex() == 0)
{
dup2();
stack.rotate(4);
stack.rotate(4);
}
else
{
dup1();
stack.rotate(2);
}
instruction= stack.pop();
break;
case Const.DUP2_X2:
if (form.getIndex() == 0)
{
dup2();
stack.rotate(5);
stack.rotate(5);
}
else if (form.getIndex() == 1)
{
dup1();
stack.rotate(3);
}
else if (form.getIndex() == 2)
{
dup2();
stack.rotate(4);
stack.rotate(4);
}
else
{
dup1();
stack.rotate(2);
}
instruction= stack.pop();
break;
case Const.SWAP:
{
stack.rotate(1);
instruction= new NoOperation();
break;
}
case Const.I2S:
case Const.I2F:
case Const.L2I:
case Const.F2I:
case Const.F2L:
case Const.L2F:
case Const.L2D:
case Const.D2I:
case Const.D2L:
case Const.D2F:
case Const.I2B:
case Const.I2C:
instruction= new PrimitiveCast(opcode, stack.pop(), form.getResultType());
break;
case Const.I2L:
stack.peek().setTypeBinding(Type.LONG);
instruction= new NoOperation();
break;
case Const.I2D:
case Const.F2D:
stack.peek().setTypeBinding(Type.DOUBLE);
instruction= new NoOperation();
break;
case Const.INEG:
case Const.LNEG:
case Const.FNEG:
case Const.DNEG:
instruction= createPrefix(PrefixExpression.MINUS, stack.pop(), form.getResultType());
break;
case Const.ISHR:
case Const.LSHR:
instruction= createInfixRightLeft(InfixExpression.Operator.RIGHT_SHIFT_SIGNED, stack.pop(), stack.pop(), form.getResultType());
break;
case Const.ISHL:
case Const.LSHL:
instruction= createInfixRightLeft(InfixExpression.Operator.LEFT_SHIFT, stack.pop(), stack.pop(), form.getResultType());
break;
case Const.IUSHR:
case Const.LUSHR:
instruction= createInfixRightLeft(InfixExpression.Operator.RIGHT_SHIFT_UNSIGNED, stack.pop(), stack.pop(), form.getResultType());
break;
case Const.IADD:
case Const.LADD:
case Const.FADD:
case Const.DADD:
instruction= createInfixRightLeft(InfixExpression.Operator.PLUS, stack.pop(), stack.pop(), form.getResultType());
break;
case Const.ISUB:
case Const.LSUB:
case Const.FSUB:
case Const.DSUB:
instruction= createInfixRightLeft(InfixExpression.Operator.MINUS, stack.pop(), stack.pop(), form.getResultType());
break;
case Const.IMUL:
case Const.LMUL:
case Const.FMUL:
case Const.DMUL:
instruction= createInfixRightLeft(InfixExpression.Operator.TIMES, stack.pop(), stack.pop(), form.getResultType());
break;
case Const.IDIV:
case Const.LDIV:
case Const.FDIV:
case Const.DDIV:
instruction= createInfixRightLeft(InfixExpression.Operator.DIVIDE, stack.pop(), stack.pop(), form.getResultType());
break;
case Const.IREM:
case Const.LREM:
case Const.FREM:
case Const.DREM:
instruction= createInfixRightLeft(InfixExpression.Operator.REMAINDER, stack.pop(), stack.pop(), form.getResultType());
break;
case Const.IXOR:
case Const.LXOR:
instruction= createInfixRightLeft(InfixExpression.Operator.XOR, stack.pop(), stack.pop(), form.getResultType());
break;
case Const.IAND:
case Const.LAND:
instruction= createInfixRightLeft(InfixExpression.Operator.AND, stack.pop(), stack.pop(), form.getResultType());
break;
case Const.IOR:
case Const.LOR:
instruction= createInfixRightLeft(InfixExpression.Operator.OR, stack.pop(), stack.pop(), form.getResultType());
break;
case Const.IINC:
{
boolean isWide= wide;
int index= readUnsigned();
wide= isWide;
int constByte= readSigned();
VariableBinding reference= createVariableBinding(index, Type.INT, true);
reference.setField(false);
Assignment assign= new Assignment(Assignment.Operator.PLUS_ASSIGN);
assign.setLeftHandSide(reference);
assign.setRightHandSide(NumberLiteral.create(new Integer(constByte)));
instruction= assign;
break;
}
case Const.ARRAYLENGTH:
{
Expression arrayRef= stack.pop();
FieldAccess access= new FieldRead();
access.setExpression(arrayRef);
access.setName("length");
instruction= access;
break;
}
case Const.WIDE:
wide= true;
return new NoOperation();
case Const.ILOAD_0:
case Const.ILOAD_1:
case Const.ILOAD_2:
case Const.ILOAD_3:
{
VariableBinding reference= createVariableBinding(opcode - Const.ILOAD_0, Type.INT, false);
reference.setField(false);
instruction= reference;
break;
}
case Const.LLOAD_0:
case Const.LLOAD_1:
case Const.LLOAD_2:
case Const.LLOAD_3:
{
VariableBinding reference= createVariableBinding(opcode - Const.LLOAD_0, Type.LONG, false);
reference.setField(false);
instruction= reference;
break;
}
case Const.FLOAD_0:
case Const.FLOAD_1:
case Const.FLOAD_2:
case Const.FLOAD_3:
{
VariableBinding reference= createVariableBinding(opcode - Const.FLOAD_0, Type.FLOAT, false);
reference.setField(false);
instruction= reference;
break;
}
case Const.DLOAD_0:
case Const.DLOAD_1:
case Const.DLOAD_2:
case Const.DLOAD_3:
{
VariableBinding reference= createVariableBinding(opcode - Const.DLOAD_0, Type.DOUBLE, false);
reference.setField(false);
instruction= reference;
break;
}
case Const.ALOAD_0:
case Const.ALOAD_1:
case Const.ALOAD_2:
case Const.ALOAD_3:
{
if (opcode == Const.ALOAD_0 && !Modifier.isStatic(methodDecl.getAccess()))
{
ThisExpression reference= new ThisExpression();
instruction= reference;
}
else
{
VariableBinding reference= createVariableBinding(opcode - Const.ALOAD_0, Type.OBJECT, false);
reference.setField(true);
instruction= reference;
}
break;
}
case Const.ILOAD:
case Const.LLOAD:
case Const.FLOAD:
case Const.DLOAD:
{
VariableBinding reference= createVariableBinding(readUnsigned(), form.getResultType(), false);
reference.setField(false);
instruction= reference;
break;
}
case Const.ALOAD:
{
VariableBinding reference= createVariableBinding(readUnsigned(), Type.OBJECT, false);
reference.setField(true);
instruction= reference;
break;
}
case Const.BALOAD:
case Const.CALOAD:
case Const.SALOAD:
case Const.IALOAD:
case Const.LALOAD:
case Const.FALOAD:
case Const.DALOAD:
case Const.AALOAD:
{
Expression index= stack.pop();
Expression arrayRef= stack.pop();
ArrayAccess aa;
aa= new ArrayAccess();
aa.setTypeBinding(form.getResultType());
aa.setArray(arrayRef);
aa.setIndex(index);
instruction= aa;
break;
}
case Const.BASTORE:
case Const.CASTORE:
case Const.SASTORE:
case Const.IASTORE:
case Const.LASTORE:
case Const.FASTORE:
case Const.DASTORE:
case Const.AASTORE:
{
Expression value= stack.pop();
Expression index= stack.pop();
Expression arrayRef= stack.pop();
if (arrayRef instanceof ArrayCreation)
{
ArrayCreation ac= (ArrayCreation) arrayRef;
if (ac.getInitializer() == null)
{
ac.setInitializer(new ArrayInitializer());
}
ac.getInitializer().getExpressions().add(value);
instruction= new NoOperation();
break;
}
Assignment a= new Assignment(Assignment.Operator.ASSIGN);
ArrayAccess aa;
aa= new ArrayAccess();
aa.setArray(arrayRef);
aa.setIndex(index);
a.setLeftHandSide(aa);
a.setRightHandSide(value);
instruction= a;
break;
}
case Const.DSTORE:
case Const.DSTORE_0:
case Const.DSTORE_1:
case Const.DSTORE_2:
case Const.DSTORE_3:
{
int index;
if (opcode == Const.DSTORE)
{
index= readUnsigned();
}
else
{
index= opcode - Const.DSTORE_0;
}
Assignment a= new Assignment(Assignment.Operator.ASSIGN);
VariableBinding reference= createVariableBinding(index, Type.DOUBLE, true);
reference.setField(false);
a.setLeftHandSide(reference);
a.setRightHandSide(stack.pop());
instruction= a;
break;
}
case Const.FSTORE:
case Const.FSTORE_0:
case Const.FSTORE_1:
case Const.FSTORE_2:
case Const.FSTORE_3:
{
int index;
if (opcode == Const.FSTORE)
{
index= readUnsigned();
}
else
{
index= opcode - Const.FSTORE_0;
}
Assignment a= new Assignment(Assignment.Operator.ASSIGN);
VariableBinding reference= createVariableBinding(index, Type.FLOAT, true);
reference.setField(false);
a.setLeftHandSide(reference);
a.setRightHandSide(stack.pop());
instruction= a;
break;
}
case Const.ISTORE:
case Const.ISTORE_0:
case Const.ISTORE_1:
case Const.ISTORE_2:
case Const.ISTORE_3:
{
int index;
if (opcode == Const.ISTORE)
{
index= readUnsigned();
}
else
{
index= opcode - Const.ISTORE_0;
}
Assignment a= new Assignment(Assignment.Operator.ASSIGN);
VariableBinding reference= createVariableBinding(index, Type.INT, true);
reference.setField(false);
a.setLeftHandSide(reference);
a.setRightHandSide(stack.pop());
instruction= a;
break;
}
case Const.LSTORE:
case Const.LSTORE_0:
case Const.LSTORE_1:
case Const.LSTORE_2:
case Const.LSTORE_3:
{
int index;
if (opcode == Const.LSTORE)
{
index= readUnsigned();
}
else
{
index= opcode - Const.LSTORE_0;
}
Assignment a= new Assignment(Assignment.Operator.ASSIGN);
VariableBinding reference= createVariableBinding(index, Type.LONG, true);
reference.setField(false);
a.setLeftHandSide(reference);
a.setRightHandSide(stack.pop());
instruction= a;
break;
}
case Const.ASTORE:
case Const.ASTORE_0:
case Const.ASTORE_1:
case Const.ASTORE_2:
case Const.ASTORE_3:
{
Assignment a= new Assignment(Assignment.Operator.ASSIGN);
int index;
if (opcode == Const.ASTORE)
{
index= readUnsigned();
}
else
{
index= (opcode - Const.ASTORE_0);
}
VariableBinding reference= createVariableBinding(index, Type.OBJECT, true);
a.setLeftHandSide(reference);
if (stack.size() > 0)
{
a.setRightHandSide(stack.pop());
}
instruction= a;
break;
}
case Const.ATHROW:
{
ThrowStatement throwStmt= new ThrowStatement();
throwStmt.setExpression(stack.pop());
instruction= throwStmt;
break;
}
case Const.ICONST_M1:
case Const.ICONST_0:
case Const.ICONST_1:
case Const.ICONST_2:
case Const.ICONST_3:
case Const.ICONST_4:
case Const.ICONST_5:
instruction= NumberLiteral.create(new Integer(-1 + opcode - Const.ICONST_M1));
break;
case Const.LCONST_0:
case Const.LCONST_1:
instruction= NumberLiteral.create(new Long(opcode - Const.LCONST_0));
break;
case Const.FCONST_0:
case Const.FCONST_1:
case Const.FCONST_2:
instruction= NumberLiteral.create(new Float(opcode - Const.FCONST_0));
break;
case Const.DCONST_0:
case Const.DCONST_1:
instruction= NumberLiteral.create(new Double(opcode - Const.DCONST_0));
break;
case Const.BIPUSH:
{
NumberLiteral literal= NumberLiteral.create(new Byte(bytes.readByte()));
instruction= literal;
break;
}
case Const.SIPUSH:
{
NumberLiteral il= NumberLiteral.create(new Short(bytes.readShort()));
instruction= il;
break;
}
case Const.LDC:
case Const.LDC_W:
case Const.LDC2_W:
{
int index;
if (opcode == Const.LDC)
{
index= bytes.readUnsignedByte();
}
else
{
index= bytes.readUnsignedShort();
}
Constant constant= constantPool.getConstant(index);
if (opcode == Const.LDC2_W && (constant.getTag() != Constants.CONSTANT_Double && constant.getTag() != Constants.CONSTANT_Long))
throw new RuntimeException("LDC2_W must load long or double");
if (constant.getTag() == Constants.CONSTANT_Integer)
{
instruction= NumberLiteral.create(new Integer(((ConstantInteger) constant).getBytes()));
}
else if (constant.getTag() == Constants.CONSTANT_Float)
{
instruction= NumberLiteral.create(new Float(((ConstantFloat) constant).getBytes()));
}
else if (constant.getTag() == Constants.CONSTANT_Long)
{
instruction= NumberLiteral.create(new Long(((ConstantLong) constant).getBytes()));
}
else if (constant.getTag() == Constants.CONSTANT_Double)
{
instruction= NumberLiteral.create(new Double(((ConstantDouble) constant).getBytes()));
}
else if (constant.getTag() == Constants.CONSTANT_Utf8)
{
instruction= new StringLiteral(((ConstantUtf8) constant).getBytes());
}
else if (constant.getTag() == Constants.CONSTANT_String)
{
int k= ((ConstantString) constant).getStringIndex();
constant= constantPool.getConstant(k, Constants.CONSTANT_Utf8);
instruction= new StringLiteral(((ConstantUtf8) constant).getBytes());
}
else if (constant.getTag() == Constants.CONSTANT_Class)
{
Signature signature= Project.getSingleton().getSignature(((ConstantClass) constant).getBytes(constantPool));
instruction= new ClassLiteral(signature);
}
else
{
throw new RuntimeException("Cannot handle constant tag: " + constant.getTag());
}
break;
}
case Const.RET:
{
int index= readUnsigned();
ReturnStatement r= new ReturnStatement(currentIndex, currentIndex);
r.setExpression(createVariableBinding(index, Type.INT, false));
instruction= r;
break;
}
case Const.RETURN:
case Const.IRETURN:
case Const.FRETURN:
case Const.LRETURN:
case Const.DRETURN:
case Const.ARETURN:
{
ReturnStatement r= new ReturnStatement(currentIndex, currentIndex);
if (opcode != Const.RETURN)
{
r.setExpression(stack.pop());
}
instruction= r;
break;
}
case Const.POP:
case Const.POP2:
{
if (opcode == Const.POP2 && form.getIndex() == 1)
{
ASTNode a= stack.pop();
// cNode.block.appendChild(a);
a= stack.pop();
// cNode.block.appendChild(a);
// throw new UnsupportedOperationException("InstructionType " + instructionType.getName() + " not supported");
}
else
{
ASTNode a= stack.pop();
if (!(a instanceof VariableBinding))
{
// be an ASTNode,
// because it has no location.
cNode.block.appendChild(a);
}
}
instruction= new NoOperation();
break;
}
case Const.NOP:
// Format: nop
// Operand stack: ... -> ...
return new NoOperation();
case Const.XXXUNUSEDXXX:
// Format: xxxunusedxxx
// Operand stack: ... -> ...
logger.info("Byte code contains unused operation (Ignored)");
return new NoOperation();
case Const.INVOKEINTERFACE:
// Format: invokeinterface, index(short), count(byte), 0(byte)
// Operand stack: ..., objectref(), arg1(), ...(), argN() -> ...
case Const.INVOKESPECIAL:
// Format: invokespecial
// Operand stack: ..., objectref(), arg1(), ...(), argN() -> ...
case Const.INVOKEVIRTUAL:
// Format: invokevirtual
// Operand stack: ..., objectref(), arg1(), ...(), argN() -> ...
case Const.INVOKESTATIC:
{
// Format: invokestatic, index(short)
// Operand stack: ..., arg1(), ...(), argN() -> ...
int index= bytes.readUnsignedShort();
MethodBinding methodBinding= MethodBinding.lookup(index, constantPool);
MethodInvocation invocation= new MethodInvocation(methodDecl, methodBinding);
// Processor.getLogger().finer(method.getName() + "->" +
// invocation.binding);
int nArgs= methodBinding.getParameterTypes().length;
int kk= stack.size() - nArgs;
for (int i= 0; i < nArgs; i++)
{
Expression arg= (Expression) stack.get(kk);
stack.remove(kk);
invocation.addArgument(arg);
}
opStackDelta= -nArgs;