void (BasicBlockStatement stat, PrimitiveExpressionList data, StructClass cl) { ConstantPool pool = cl.getPool(); StructBootstrapMethodsAttribute bootstrap = cl.getAttribute(StructGeneralAttribute.ATTRIBUTE_BOOTSTRAP_METHODS); BasicBlock block = stat.getBlock(); ExpressionStack stack = data.getStack(); List<Exprent> exprList = data.getExpressions(); InstructionSequence seq = block.getSeq(); for (int i = 0; i < seq.length(); i++) { Instruction instr = seq.getInstr(i); Integer offset = block.getOriginalOffset(i); Set<Integer> offsets = offset >= 0 ? Set.of(offset) : null; switch (instr.opcode) { case opc_aconst_null: pushEx(stack, exprList, new ConstExprent(VarType.VARTYPE_NULL, null, offsets)); break; case opc_bipush: case opc_sipush: pushEx(stack, exprList, new ConstExprent(instr.operand(0), true, offsets)); break; case opc_lconst_0: case opc_lconst_1: pushEx(stack, exprList, new ConstExprent(VarType.VARTYPE_LONG, (long)(instr.opcode - opc_lconst_0), offsets)); break; case opc_fconst_0: case opc_fconst_1: case opc_fconst_2: pushEx(stack, exprList, new ConstExprent(VarType.VARTYPE_FLOAT, (float)(instr.opcode - opc_fconst_0), offsets)); break; case opc_dconst_0: case opc_dconst_1: pushEx(stack, exprList, new ConstExprent(VarType.VARTYPE_DOUBLE, (double)(instr.opcode - opc_dconst_0), offsets)); break; case opc_ldc: case opc_ldc_w: case opc_ldc2_w: { PooledConstant cn = pool.getConstant(instr.operand(0)); if (cn instanceof PrimitiveConstant) { pushEx(stack, exprList, new ConstExprent(constants[cn.type - CONSTANT_Integer], ((PrimitiveConstant)cn).value, offsets)); } else if (cn instanceof LinkConstant) { //TODO: for now treat Links as Strings pushEx(stack, exprList, new ConstExprent(VarType.VARTYPE_STRING, ((LinkConstant)cn).elementname, offsets)); } break; } case opc_iload: case opc_lload: case opc_fload: case opc_dload: case opc_aload: pushEx(stack, exprList, new VarExprent(instr.operand(0), varTypes[instr.opcode - opc_iload], varProcessor, offset)); break; case opc_iaload: case opc_laload: case opc_faload: case opc_daload: case opc_aaload: case opc_baload: case opc_caload: case opc_saload: { Exprent index = stack.pop(); Exprent arr = stack.pop(); VarType type = instr.opcode == opc_laload ? VarType.VARTYPE_LONG : instr.opcode == opc_daload ? VarType.VARTYPE_DOUBLE : null; pushEx(stack, exprList, new ArrayExprent(arr, index, arrTypes[instr.opcode - opc_iaload], offsets), type); break; } case opc_istore: case opc_lstore: case opc_fstore: case opc_dstore: case opc_astore: { Exprent value = stack.pop(); int varIndex = instr.operand(0); VarExprent left = new VarExprent(varIndex, varTypes[instr.opcode - opc_istore], varProcessor, nextMeaningfulOffset(block, i)); exprList.add(new AssignmentExprent(left, value, offsets)); break; } case opc_iastore: case opc_lastore: case opc_fastore: case opc_dastore: case opc_aastore: case opc_bastore: case opc_castore: case opc_sastore: { Exprent value = stack.pop(); Exprent index = stack.pop(); Exprent array = stack.pop(); ArrayExprent left = new ArrayExprent(array, index, arrTypes[instr.opcode - opc_iastore], offsets); exprList.add(new AssignmentExprent(left, value, offsets)); break; } case opc_iadd: case opc_ladd: case opc_fadd: case opc_dadd: case opc_isub: case opc_lsub: case opc_fsub: case opc_dsub: case opc_imul: case opc_lmul: case opc_fmul: case opc_dmul: case opc_idiv: case opc_ldiv: case opc_fdiv: case opc_ddiv: case opc_irem: case opc_lrem: case opc_frem: case opc_drem: pushEx(stack, exprList, new FunctionExprent(func1[(instr.opcode - opc_iadd) / 4], stack, offsets)); break; case opc_ishl: case opc_lshl: case opc_ishr: case opc_lshr: case opc_iushr: case opc_lushr: case opc_iand: case opc_land: case opc_ior: case opc_lor: case opc_ixor: case opc_lxor: pushEx(stack, exprList, new FunctionExprent(func2[(instr.opcode - opc_ishl) / 2], stack, offsets)); break; case opc_ineg: case opc_lneg: case opc_fneg: case opc_dneg: pushEx(stack, exprList, new FunctionExprent(FunctionExprent.FUNCTION_NEG, stack, offsets)); break; case opc_iinc: { VarExprent varExpr = new VarExprent(instr.operand(0), VarType.VARTYPE_INT, varProcessor); int type = instr.operand(1) < 0 ? FunctionExprent.FUNCTION_SUB : FunctionExprent.FUNCTION_ADD; List<Exprent> operands = Arrays.asList(varExpr.copy(), new ConstExprent(VarType.VARTYPE_INT, Math.abs(instr.operand(1)), null)); exprList.add(new AssignmentExprent(varExpr, new FunctionExprent(type, operands, offsets), offsets)); break; } case opc_i2l: case opc_i2f: case opc_i2d: case opc_l2i: case opc_l2f: case opc_l2d: case opc_f2i: case opc_f2l: case opc_f2d: case opc_d2i: case opc_d2l: case opc_d2f: case opc_i2b: case opc_i2c: case opc_i2s: pushEx(stack, exprList, new FunctionExprent(func3[instr.opcode - opc_i2l], stack, offsets)); break; case opc_lcmp: case opc_fcmpl: case opc_fcmpg: case opc_dcmpl: case opc_dcmpg: pushEx(stack, exprList, new FunctionExprent(func4[instr.opcode - opc_lcmp], stack, offsets)); break; case opc_ifeq: case opc_ifne: case opc_iflt: case opc_ifge: case opc_ifgt: case opc_ifle: exprList.add(new IfExprent(negIfs[func5[instr.opcode - opc_ifeq]], stack, offsets)); break; case opc_if_icmpeq: case opc_if_icmpne: case opc_if_icmplt: case opc_if_icmpge: case opc_if_icmpgt: case opc_if_icmple: case opc_if_acmpeq: case opc_if_acmpne: exprList.add(new IfExprent(negIfs[func6[instr.opcode - opc_if_icmpeq]], stack, offsets)); break; case opc_ifnull: case opc_ifnonnull: exprList.add(new IfExprent(negIfs[func7[instr.opcode - opc_ifnull]], stack, offsets)); break; case opc_tableswitch: case opc_lookupswitch: exprList.add(new SwitchExprent(stack.pop(), offsets)); break; case opc_ireturn: case opc_lreturn: case opc_freturn: case opc_dreturn: case opc_areturn: case opc_return: case opc_athrow: exprList.add(new ExitExprent(instr.opcode == opc_athrow ? ExitExprent.EXIT_THROW : ExitExprent.EXIT_RETURN, instr.opcode == opc_return ? null : stack.pop(), instr.opcode == opc_athrow ? null : methodDescriptor.ret, offsets)); break; case opc_monitorenter: case opc_monitorexit: exprList.add(new MonitorExprent(func8[instr.opcode - opc_monitorenter], stack.pop(), offsets)); break; case opc_checkcast: case opc_instanceof: stack.push(new ConstExprent(new VarType(pool.getPrimitiveConstant(instr.operand(0)).getString(), true), null, null)); case opc_arraylength: pushEx(stack, exprList, new FunctionExprent(functionMap.get(instr.opcode), stack, offsets)); break; case opc_getstatic: case opc_getfield: pushEx(stack, exprList, new FieldExprent(pool.getLinkConstant(instr.operand(0)), instr.opcode == opc_getstatic ? null : stack.pop(), offsets)); break; case opc_putstatic: case opc_putfield: Exprent valfield = stack.pop(); Exprent exprfield = new FieldExprent(pool.getLinkConstant(instr.operand(0)), instr.opcode == opc_putstatic ? null : stack.pop(), offsets); exprList.add(new AssignmentExprent(exprfield, valfield, offsets)); break; case opc_invokevirtual: case opc_invokespecial: case opc_invokestatic: case opc_invokeinterface: case opc_invokedynamic: if (instr.opcode != opc_invokedynamic || instr.bytecodeVersion >= CodeConstants.BYTECODE_JAVA_7) { LinkConstant invoke_constant = pool.getLinkConstant(instr.operand(0)); List<PooledConstant> bootstrap_arguments = null; if (instr.opcode == opc_invokedynamic && bootstrap != null) { bootstrap_arguments = bootstrap.getMethodArguments(invoke_constant.index1); } InvocationExprent exprinv = new InvocationExprent(instr.opcode, invoke_constant, bootstrap_arguments, stack, offsets); if (exprinv.getDescriptor().ret.getType() == CodeConstants.TYPE_VOID) { exprList.add(exprinv); } else { pushEx(stack, exprList, exprinv); } } break; case opc_new: case opc_anewarray: case opc_multianewarray: int dimensions = (instr.opcode == opc_new) ? 0 : (instr.opcode == opc_anewarray) ? 1 : instr.operand(1); VarType arrType = new VarType(pool.getPrimitiveConstant(instr.operand(0)).getString(), true); if (instr.opcode != opc_multianewarray) { arrType = arrType.resizeArrayDim(arrType.getArrayDim() + dimensions); } pushEx(stack, exprList, new NewExprent(arrType, stack, dimensions, offsets)); break; case opc_newarray: pushEx(stack, exprList, new NewExprent(new VarType(arrTypeIds[instr.operand(0) - 4], 1), stack, 1, offsets)); break; case opc_dup: pushEx(stack, exprList, stack.getByOffset(-1).copy()); break; case opc_dup_x1: insertByOffsetEx(-2, stack, exprList, -1); break; case opc_dup_x2: if (stack.getByOffset(-2).getExprType().getStackSize() == 2) { insertByOffsetEx(-2, stack, exprList, -1); } else { insertByOffsetEx(-3, stack, exprList, -1); } break; case opc_dup2: if (stack.getByOffset(-1).getExprType().getStackSize() == 2) { pushEx(stack, exprList, stack.getByOffset(-1).copy()); } else { pushEx(stack, exprList, stack.getByOffset(-2).copy()); pushEx(stack, exprList, stack.getByOffset(-2).copy()); } break; case opc_dup2_x1: if (stack.getByOffset(-1).getExprType().getStackSize() == 2) { insertByOffsetEx(-2, stack, exprList, -1); } else { insertByOffsetEx(-3, stack, exprList, -2); insertByOffsetEx(-3, stack, exprList, -1); } break; case opc_dup2_x2: if (stack.getByOffset(-1).getExprType().getStackSize() == 2) { if (stack.getByOffset(-2).getExprType().getStackSize() == 2) { insertByOffsetEx(-2, stack, exprList, -1); } else { insertByOffsetEx(-3, stack, exprList, -1); } } else { if (stack.getByOffset(-3).getExprType().getStackSize() == 2) { insertByOffsetEx(-3, stack, exprList, -2); insertByOffsetEx(-3, stack, exprList, -1); } else { insertByOffsetEx(-4, stack, exprList, -2); insertByOffsetEx(-4, stack, exprList, -1); } } break; case opc_swap: insertByOffsetEx(-2, stack, exprList, -1); stack.pop(); break; case opc_pop: stack.pop(); break; case opc_pop2: if (stack.getByOffset(-1).getExprType().getStackSize() == 1) { // Since value at the top of the stack is a value of category 1 (JVMS9 2.11.1) // we should remove one more item from the stack. // See JVMS9 pop2 chapter. stack.pop(); } stack.pop(); break; } } }