Example usage for org.eclipse.jdt.core.dom CreationReference setType

List of usage examples for org.eclipse.jdt.core.dom CreationReference setType

Introduction

In this page you can find the example usage for org.eclipse.jdt.core.dom CreationReference setType.

Prototype

public void setType(Type type) 

Source Link

Document

Sets the type of this creation reference expression.

Usage

From source file:org.decojer.cavaj.transformers.TrExpressions.java

License:Open Source License

private boolean transformOperations(@Nonnull final BB bb) {
    while (bb.getOps() > 0) {
        if (isStackUnderflow(bb)) {
            if (!mitigateStackUnderflow(bb)) {
                return false;
            }// www  .j  av a  2s.  c o m
            if (bb.isRemoved()) {
                // is also a possible form of stack underflow mitigation
                return true;
            }
            // something has been mitigated...may be not to the full extend, try again
            continue;
        }
        final Op op = bb.removeOp(0);
        switch (op.getOptype()) {
        case ADD: {
            bb.push(newInfixExpressionPop(InfixExpression.Operator.PLUS, bb, op));
            break;
        }
        case ALOAD: {
            final ArrayAccess arrayAccess = setOp(getAst().newArrayAccess(), op);
            arrayAccess.setIndex(wrap(bb.pop()));
            arrayAccess.setArray(wrap(bb.pop(), Priority.ARRAY_INDEX));
            bb.push(arrayAccess);
            break;
        }
        case AND: {
            bb.push(newInfixExpressionPop(InfixExpression.Operator.AND, bb, op));
            break;
        }
        case ARRAYLENGTH: {
            final Expression expression = bb.pop();
            if (expression instanceof Name) {
                // annotationsVisible.length
                bb.push(setOp(
                        getAst().newQualifiedName((Name) wrap(expression), getAst().newSimpleName("length")),
                        op));
                break;
            }
            // FieldAccess or MethodInvocation:
            // this.code.length, getInterfaces().length
            final FieldAccess fieldAccess = setOp(getAst().newFieldAccess(), op);
            fieldAccess.setExpression(wrap(expression, Priority.MEMBER_ACCESS));
            fieldAccess.setName(getAst().newSimpleName("length"));
            bb.push(fieldAccess);
            break;
        }
        case ASTORE: {
            final Expression rightOperand = bb.pop();
            final Expression indexExpression = bb.pop();
            final Expression arrayRefExpression = bb.pop();
            if (arrayRefExpression instanceof ArrayCreation) {
                final ArrayCreation arrayCreation = (ArrayCreation) arrayRefExpression;
                ArrayInitializer arrayInitializer = arrayCreation.getInitializer();
                if (arrayInitializer == null) {
                    arrayInitializer = setOp(getAst().newArrayInitializer(), op);
                    arrayCreation.setInitializer(arrayInitializer);
                    // TODO for higher performance and for full array creation removement we
                    // could defer the 0-fill and rewrite to the final A/STORE phase
                    final Object sizeExpression = arrayCreation.dimensions().get(0);
                    final Number size = sizeExpression instanceof Expression
                            ? getNumberValue((Expression) sizeExpression)
                            : null;
                    assert size != null;
                    final T t = peekT(op);
                    assert t != null;
                    // not all indexes may be set, null/0/false in JVM 7 are not set, fill
                    for (int i = size.intValue(); i-- > 0;) {
                        arrayInitializer.expressions().add(newLiteral(t, null, getM(), op));
                    }
                    arrayCreation.dimensions().clear();
                }
                final Number numberValue = getNumberValue(indexExpression);
                assert numberValue != null;
                arrayInitializer.expressions().set(numberValue.intValue(), wrap(rightOperand));
                break;
            }
            final ArrayAccess arrayAccess = setOp(getAst().newArrayAccess(), op);
            arrayAccess.setArray(wrap(arrayRefExpression, Priority.ARRAY_INDEX));
            arrayAccess.setIndex(wrap(indexExpression));
            final Assignment assignment = newAssignment(Assignment.Operator.ASSIGN, arrayAccess, rightOperand,
                    op);
            // TODO a = a +/- 1 => a++ / a--
            // TODO a = a <op> expr => a <op>= expr
            // inline assignment, DUP(_X1) -> PUT
            if (!bb.isStackEmpty() && bb.peek() == rightOperand) {
                bb.pop();
                bb.push(assignment);
                break;
            }
            bb.addStmt(setOp(getAst().newExpressionStatement(assignment), op));
            break;
        }
        case CAST: {
            final CAST cop = (CAST) op;
            final CastExpression castExpression = setOp(getAst().newCastExpression(), op);
            castExpression.setType(newType(cop.getToT(), getM()));
            castExpression.setExpression(wrap(bb.pop(), Priority.TYPE_CAST));
            bb.push(castExpression);
            break;
        }
        case CMP: {
            // pseudo expression for following JCND, not really the correct
            // answer for -1, 0, 1
            bb.push(newInfixExpressionPop(InfixExpression.Operator.LESS_EQUALS, bb, op));
            break;
        }
        case DIV: {
            bb.push(newInfixExpressionPop(InfixExpression.Operator.DIVIDE, bb, op));
            break;
        }
        case DUP: {
            final DUP cop = (DUP) op;
            switch (cop.getKind()) {
            // for all following variants: don't change op without copying!
            case DUP:
                bb.push(bb.peek());
                break;
            case DUP_X1: {
                final Expression e1 = bb.pop();
                final Expression e2 = bb.pop();
                bb.push(e1);
                bb.push(e2);
                bb.push(e1);
                break;
            }
            case DUP_X2: {
                final Expression e1 = bb.pop();
                final Expression e2 = bb.pop();
                if (!isWide(e2)) {
                    final Expression e3 = bb.pop();
                    bb.push(e1);
                    bb.push(e3);
                    bb.push(e2);
                    bb.push(e1);
                    break;
                }
                bb.push(e1);
                bb.push(e2);
                bb.push(e1);
                break;
            }
            case DUP2: {
                final Expression e1 = bb.peek();
                if (!isWide(e1)) {
                    final Expression e2 = bb.peek(1);
                    bb.push(e2);
                    bb.push(e1);
                    break;
                }
                bb.push(e1);
                break;
            }
            case DUP2_X1: {
                final Expression e1 = bb.pop();
                if (!isWide(e1)) {
                    final Expression e2 = bb.pop();
                    final Expression e3 = bb.pop();
                    bb.push(e2);
                    bb.push(e1);
                    bb.push(e3);
                    bb.push(e2);
                    bb.push(e1);
                    break;
                }
                final Expression e3 = bb.pop();
                bb.push(e1);
                bb.push(e3);
                bb.push(e1);
                break;
            }
            case DUP2_X2: {
                final Expression e1 = bb.pop();
                if (!isWide(e1)) {
                    final Expression e2 = bb.pop();
                    final Expression e3 = bb.pop();
                    if (!isWide(e3)) {
                        final Expression e4 = bb.pop();
                        bb.push(e2);
                        bb.push(e1);
                        bb.push(e4);
                        bb.push(e3);
                        bb.push(e2);
                        bb.push(e1);
                        break;
                    }
                    bb.push(e2);
                    bb.push(e1);
                    bb.push(e3);
                    bb.push(e2);
                    bb.push(e1);
                    break;
                }
                final Expression e3 = bb.pop();
                if (!isWide(e3)) {
                    final Expression e4 = bb.pop();
                    bb.push(e1);
                    bb.push(e4);
                    bb.push(e3);
                    bb.push(e1);
                    break;
                }
                bb.push(e1);
                bb.push(e3);
                bb.push(e1);
                break;
            }
            default:
                log.warn(getM() + ": Unknown DUP type '" + cop.getKind() + "'!");
            }
            break;
        }
        case FILLARRAY: {
            final FILLARRAY cop = (FILLARRAY) op;
            final T t = peekT(op);
            final T componentT = t.getComponentT();
            assert componentT != null;

            Expression expression = bb.pop();
            if (!(expression instanceof ArrayCreation)) {
                // LOAD 0, NEWARRAY, STORE 0, LOAD 0, FILLARRAY <end>
                // TODO Dalvik: if STORE x / LOAD x are compressed then we shouldn't need this:
                expression = setOp(getAst().newArrayCreation(), op);
                ((ArrayCreation) expression).setType((ArrayType) newType(t, getM()));
            }
            final ArrayInitializer arrayInitializer = setOp(getAst().newArrayInitializer(), op);
            final Object[] values = cop.getValues();
            assert values != null;
            for (final Object value : values) {
                arrayInitializer.expressions().add(newLiteral(componentT, value, getM(), op));
            }
            ((ArrayCreation) expression).setInitializer(arrayInitializer);

            bb.push(expression);
            break;
        }
        case GET: {
            final GET cop = (GET) op;
            if (rewriteCachedClassLiteral(bb, cop)) {
                break;
            }
            final F f = cop.getF();
            if (f.isStatic()) {
                // Eclipse AST expects a Name for f.getT(), not a Type:
                // is OK - f.getT() cannot be generic
                bb.push(setOp(getAst().newQualifiedName(newTypeName(f.getT(), getM()),
                        newSimpleName(f.getName(), getAst())), op));
                break;
            }
            final FieldAccess fieldAccess = setOp(getAst().newFieldAccess(), op);
            fieldAccess.setExpression(wrap(bb.pop(), Priority.MEMBER_ACCESS));
            fieldAccess.setName(newSimpleName(f.getName(), getAst()));
            bb.push(fieldAccess);
            break;
        }
        case GOTO: {
            // not really necessary, but important for
            // 1) correct opPc blocks
            // 2) line numbers

            // TODO put line number anywhere?
            // remember as pseudo statement? but problem with boolean ops
            break;
        }
        case INC: {
            final INC cop = (INC) op;
            final int value = cop.getValue();
            if (value == 1 || value == -1) {
                // ++ / --
                if (rewriteInlinePrefixIncDec(bb, cop) || rewriteInlinePostfixIncDec(bb, cop)) {
                    break;
                }
                if (bb.isStackEmpty()) {
                    bb.addStmt(setOp(getAst().newExpressionStatement(newPrefixExpression(
                            cop.getValue() == 1 ? PrefixExpression.Operator.INCREMENT
                                    : PrefixExpression.Operator.DECREMENT,
                            getVarExpression(cop.getReg(), cop.getPc(), op), op)), op));
                    break;
                }
                log.warn(getM() + ": Inline ++/--!");
                break;
            }
            if (rewriteInlineRegAssignment(bb, cop)) {
                break;
            }
            if (bb.isStackEmpty()) {
                bb.addStmt(setOp(
                        getAst().newExpressionStatement(newAssignment(
                                value >= 0 ? Assignment.Operator.PLUS_ASSIGN : Assignment.Operator.MINUS_ASSIGN,
                                getVarExpression(cop.getReg(), cop.getPc(), op),
                                newLiteral(cop.getT(), value >= 0 ? value : -value, getCfg().getM(), op), op)),
                        op));
                break;
            }
            log.warn(getM() + ": Inline INC with value '" + value + "'!");
            break;
        }
        case INSTANCEOF: {
            final INSTANCEOF cop = (INSTANCEOF) op;
            final InstanceofExpression instanceofExpression = setOp(getAst().newInstanceofExpression(), op);
            instanceofExpression.setLeftOperand(wrap(bb.pop(), Priority.INSTANCEOF));
            instanceofExpression.setRightOperand(newType(cop.getT(), getM()));
            bb.push(instanceofExpression);
            break;
        }
        case INVOKE: {
            final INVOKE cop = (INVOKE) op;
            final M m = cop.getM();

            // read method invokation arguments, handle varargs
            final List<Expression> arguments = Lists.newArrayList();
            final int params = m.getParamTs().length;
            if (params > 0) {
                if (m.isVarargs()) {
                    final Expression array = bb.pop();
                    if (array instanceof ArrayCreation) {
                        final ArrayInitializer initializer = ((ArrayCreation) array).getInitializer();
                        if (initializer != null) {
                            for (final Expression e : (List<Expression>) initializer.expressions()) {
                                // wrap() in addAll(), DUP could happen with receiver & argument
                                arguments.add(e);
                            }
                            Collections.reverse(arguments);
                        }
                    } else {
                        // can happen if forwarded as variable
                        arguments.add(array);
                    }
                } else {
                    arguments.add(bb.pop());
                }
                // now add remaining parameters that cannot be varargs
                for (int i = params - 1; i-- > 0;) {
                    arguments.add(bb.pop());
                }
                Collections.reverse(arguments);
            }

            final Expression methodExpression;
            if (cop.isDirect()) {
                final Expression expression = bb.pop();
                if (m.isConstructor()) {
                    methodExpression = null;
                    final T ownerT = m.getT();
                    if (expression instanceof ThisExpression) {
                        enumConstructor: if (ownerT != null && ownerT.is(Enum.class)
                                && !getCfg().getCu().check(DFlag.IGNORE_ENUM)) {
                            if (arguments.size() < 2) {
                                log.warn(getM() + ": Super constructor invocation '" + m
                                        + "' for enum has less than 2 arguments!");
                                break enumConstructor;
                            }
                            if (!m.getParamTs()[0].is(String.class)) {
                                log.warn(getM() + ": Super constructor invocation '" + m
                                        + "' for enum must contain string literal as first parameter!");
                                break enumConstructor;
                            }
                            if (m.getParamTs()[1] != T.INT) {
                                log.warn(getM() + ": Super constructor invocation '" + m
                                        + "' for enum must contain number literal as first parameter!");
                                break enumConstructor;
                            }
                            arguments.remove(0);
                            arguments.remove(0);
                        }
                        if (ownerT != null && ownerT.is(getCfg().getT())) {
                            final ConstructorInvocation constructorInvocation = getAst()
                                    .newConstructorInvocation();
                            wrapAddAll(constructorInvocation.arguments(), arguments);
                            bb.addStmt(setOp(constructorInvocation, op));
                            break;
                        }
                        if (arguments.size() == 0) {
                            // implicit super callout, more checks possible but not necessary
                            break;
                        }
                        final SuperConstructorInvocation superConstructorInvocation = getAst()
                                .newSuperConstructorInvocation();
                        wrapAddAll(superConstructorInvocation.arguments(), arguments);
                        bb.addStmt(setOp(superConstructorInvocation, op));
                        break;
                    }
                    if (expression instanceof ClassInstanceCreation) {
                        if (ownerT != null && ownerT.isInner()
                                && !getCfg().getCu().check(DFlag.IGNORE_CONSTRUCTOR_THIS)) {
                            // inner class constructor invocation has synthetic this reference
                            // as first argument: remove
                            if (arguments.size() == 0) {
                                log.warn(getM()
                                        + ": Inner class constructor invocation has no synthetic this reference as first argument! No arguments given.");
                            } else if (!(arguments.get(0) instanceof ThisExpression)) {
                                log.warn(getM()
                                        + ": Inner class constructor invocation has no synthetic this reference as first argument! Wrong first argument: "
                                        + arguments.get(0));
                            } else {
                                arguments.remove(0);
                            }
                        }
                        wrapAddAll(((ClassInstanceCreation) expression).arguments(), arguments);
                        // normally there was a DUP in advance, don't use:
                        // basicBlock.pushExpression(classInstanceCreation);
                        break;
                    }
                    log.warn(getM()
                            + ": Constructor expects expression class 'ThisExpression' or 'ClassInstanceCreation' but is '"
                            + expression.getClass() + "' with value: " + expression);
                    break;
                }
                if (expression instanceof ThisExpression && !m.getAf(AF.PRIVATE)) {
                    final SuperMethodInvocation superMethodInvocation = getAst().newSuperMethodInvocation();
                    superMethodInvocation.setName(newSimpleName(m.getName(), getAst()));
                    wrapAddAll(superMethodInvocation.arguments(), arguments);
                    methodExpression = superMethodInvocation;
                } else {
                    // could be private method call in same object, nothing special in syntax,
                    // just used together with "this."
                    final MethodInvocation methodInvocation = getAst().newMethodInvocation();
                    methodInvocation.setExpression(wrap(expression, Priority.METHOD_CALL));
                    methodInvocation.setName(newSimpleName(m.getName(), getAst()));
                    wrapAddAll(methodInvocation.arguments(), arguments);
                    methodExpression = methodInvocation;
                }
            } else if (m.isDynamic()) {
                final Object[] bsArgs = cop.getBsArgs();
                if (isLambdaBootstrapMethod(cop.getBsM()) && bsArgs != null && bsArgs.length > 1
                        && bsArgs[1] instanceof M) {
                    final M dynamicM = (M) bsArgs[1];
                    if (dynamicM.isSynthetic()) {
                        // is lambda
                        final LambdaExpression lambdaExpression = getAst().newLambdaExpression();
                        // init lambda parameters
                        final T[] paramTs = dynamicM.getParamTs();
                        final A[][] paramAss = dynamicM.getParamAss();
                        // first m.paramTs.length parameters are for outer capture inits
                        for (int i = m.getParamTs().length; i < paramTs.length; ++i) {
                            lambdaExpression.parameters().add(newSingleVariableDeclaration(dynamicM, paramTs,
                                    paramAss, i, this.cfg.getT()));
                        }
                        // init lambda body
                        final CFG lambdaCfg = dynamicM.getCfg();
                        assert lambdaCfg != null;
                        if (lambdaCfg.getBlock() == null) {
                            // if synthetics are not decompiled...
                            // lambda methods are synthetic: init block, could later add more
                            // checks and alternatives here if obfuscators play with these flags
                            lambdaCfg.setBlock((Block) lambdaExpression.getBody());
                            lambdaCfg.decompile();
                        } else if (lambdaCfg.getBlock().getParent() instanceof MethodDeclaration) {
                            // if synthetics are decompiled...but not for re-decompilation:
                            // don't show this recognized (normally synthetic) method
                            // declaration
                            lambdaCfg.getBlock().delete(); // delete from parent
                            dynamicM.setAstNode(null);
                            // is our new lambda body
                            lambdaExpression.setBody(lambdaCfg.getBlock());
                        }
                        methodExpression = lambdaExpression;
                    } else {
                        // is a method reference, 4 different variants possible
                        if (dynamicM.isConstructor()) {
                            final CreationReference methodReference = getAst().newCreationReference();
                            final T ownerT = dynamicM.getT();
                            assert ownerT != null;
                            methodReference.setType(newType(ownerT, getM()));
                            methodExpression = methodReference;
                        } else if (dynamicM.isStatic()) {
                            final TypeMethodReference methodReference = getAst().newTypeMethodReference();
                            final T ownerT = dynamicM.getT();
                            assert ownerT != null;
                            methodReference.setType(newType(ownerT, getM()));
                            methodReference.setName(newSimpleName(dynamicM.getName(), getAst()));
                            methodExpression = methodReference;
                        } else {
                            assert arguments
                                    .size() == 1 : "expression method reference doesn't have 1 argument";

                            final ExpressionMethodReference methodReference = getAst()
                                    .newExpressionMethodReference();
                            methodReference.setExpression(arguments.get(0));
                            methodReference.setName(newSimpleName(dynamicM.getName(), getAst()));
                            methodExpression = methodReference;
                        }
                        // TODO is in bytecode via lambda, we could let it be or recognize this
                        // pattern and shorten down to getAst().newSuperMethodReference();
                    }
                } else {
                    final MethodInvocation methodInvocation = getAst().newMethodInvocation();
                    methodInvocation.setName(newSimpleName(m.getName(), getAst()));
                    wrapAddAll(methodInvocation.arguments(), arguments);
                    methodExpression = methodInvocation;
                }
            } else if (m.isStatic()) {
                final MethodInvocation methodInvocation = getAst().newMethodInvocation();
                methodInvocation.setExpression(newTypeName(m.getT(), getM()));
                methodInvocation.setName(newSimpleName(m.getName(), getAst()));
                wrapAddAll(methodInvocation.arguments(), arguments);
                methodExpression = methodInvocation;
            } else {
                if (rewriteStringAppend(bb, cop)) {
                    break;
                }
                final MethodInvocation methodInvocation = getAst().newMethodInvocation();
                final Expression expression = bb.pop();
                // TODO need this for switch(this.ordinal) rewrites, delete later?
                // if (!(expression instanceof ThisExpression)) {
                methodInvocation.setExpression(wrap(expression, Priority.METHOD_CALL));
                // }
                methodInvocation.setName(newSimpleName(m.getName(), getAst()));
                wrapAddAll(methodInvocation.arguments(), arguments);
                methodExpression = methodInvocation;
            }
            setOp(methodExpression, op);
            final T returnT = m.getReturnT();
            if (returnT == T.VOID) {
                bb.addStmt(setOp(setOp(getAst().newExpressionStatement(methodExpression), op), op));
                break;
            }
            assert methodExpression != null;
            bb.push(methodExpression);
            break;
        }
        case JCMP: {
            final JCMP cop = (JCMP) op;
            // invert all operators and switch out edge predicates
            final InfixExpression.Operator operator;
            switch (cop.getCmpType()) {
            case T_EQ:
                operator = InfixExpression.Operator.EQUALS;
                break;
            case T_GE:
                operator = InfixExpression.Operator.GREATER_EQUALS;
                break;
            case T_GT:
                operator = InfixExpression.Operator.GREATER;
                break;
            case T_LE:
                operator = InfixExpression.Operator.LESS_EQUALS;
                break;
            case T_LT:
                operator = InfixExpression.Operator.LESS;
                break;
            case T_NE:
                operator = InfixExpression.Operator.NOT_EQUALS;
                break;
            default:
                log.warn(getM() + ": Unknown cmp type '" + cop.getCmpType() + "'!");
                operator = null;
            }
            final IfStatement ifStatement = getAst().newIfStatement();
            ifStatement.setExpression(newInfixExpressionPop(operator, bb, op));
            bb.addStmt(setOp(ifStatement, op));
            break;
        }
        case JCND: {
            final JCND cop = (JCND) op;
            Expression expression = bb.pop();
            // check preceding CMP
            if (expression instanceof InfixExpression
                    && ((InfixExpression) expression).getOperator() == InfixExpression.Operator.LESS_EQUALS) {
                // preceding compare expression (CMP result: -1 / 0 / 1)
                final InfixExpression.Operator operator;
                switch (cop.getCmpType()) {
                case T_EQ:
                    operator = InfixExpression.Operator.EQUALS;
                    break;
                case T_GE:
                    operator = InfixExpression.Operator.GREATER_EQUALS;
                    break;
                case T_GT:
                    operator = InfixExpression.Operator.GREATER;
                    break;
                case T_LE:
                    operator = InfixExpression.Operator.LESS_EQUALS;
                    break;
                case T_LT:
                    operator = InfixExpression.Operator.LESS;
                    break;
                case T_NE:
                    operator = InfixExpression.Operator.NOT_EQUALS;
                    break;
                default:
                    log.warn(getM() + ": Unknown cmp type '" + cop.getCmpType() + "'!");
                    operator = null;
                }
                ((InfixExpression) expression).setOperator(operator);
            } else if (peekT(op).isRef()) {
                final InfixExpression.Operator operator;
                switch (cop.getCmpType()) {
                case T_EQ:
                    operator = InfixExpression.Operator.EQUALS;
                    break;
                case T_NE:
                    operator = InfixExpression.Operator.NOT_EQUALS;
                    break;
                default:
                    log.warn(getM() + ": Unknown cmp type '" + cop.getCmpType() + "' for null-expression!");
                    operator = null;
                }
                expression = newInfixExpression(operator, expression, newLiteral(T.REF, null, getM(), op), op);
            } else if (peekT(op).is(T.BOOLEAN)) {
                // "!a" or "a == 0"?
                switch (cop.getCmpType()) {
                case T_EQ:
                    // "== 0" means "is false"
                    expression = not(expression);
                    break;
                case T_NE:
                    // "!= 0" means "is true"
                    break;
                default:
                    log.warn(getM() + ": Unknown cmp type '" + cop.getCmpType() + "' for boolean expression '"
                            + expression + "'!");
                }
            } else {
                final InfixExpression.Operator operator;
                switch (cop.getCmpType()) {
                case T_EQ:
                    operator = InfixExpression.Operator.EQUALS;
                    break;
                case T_GE:
                    operator = InfixExpression.Operator.GREATER_EQUALS;
                    break;
                case T_GT:
                    operator = InfixExpression.Operator.GREATER;
                    break;
                case T_LE:
                    operator = InfixExpression.Operator.LESS_EQUALS;
                    break;
                case T_LT:
                    operator = InfixExpression.Operator.LESS;
                    break;
                case T_NE:
                    operator = InfixExpression.Operator.NOT_EQUALS;
                    break;
                default:
                    log.warn(getM() + ": Unknown cmp type '" + cop.getCmpType() + "' for 0-expression!");
                    operator = null;
                }
                expression = newInfixExpression(operator, expression, newLiteral(T.INT, 0, getM(), op), op);
            }
            final IfStatement ifStatement = getAst().newIfStatement();
            ifStatement.setExpression(wrap(expression));
            bb.addStmt(setOp(ifStatement, op));
            break;
        }
        case JSR: {
            // <finally> till JVM 6 (50), we don't really push something at the sub BB, we
            // rewrite this or catch the stack underflow for the STORE
            break;
        }
        case LOAD: {
            final LOAD cop = (LOAD) op;
            /*
             * final V v = getCfg().getFrameVar(cop.getReg(), cop.getPc()); if (v == null ||
             * v.getName() == null) { // temporary local final Expression expression =
             * bb.get(cop.getReg()); if (expression != null) { bb.push(bb.get(cop.getReg()));
             * break; } }
             */

            // must not access method parameters for fieldInits...
            fieldInitCheck: if (isFieldInit()) {
                if (!getM().isConstructor()) {
                    setFieldInit(false);
                    break fieldInitCheck;
                }
                final R r = getCfg().getInFrame(op).load(cop.getReg());
                if (r == null) {
                    break fieldInitCheck;
                }
                if (!r.isMethodParam()) {
                    setFieldInit(false);
                    break fieldInitCheck;
                }
                if (cop.getReg() == 0) {
                    break fieldInitCheck; // this
                }
                // only synthetic parameters are allowed
                final T ownerT = getM().getT();
                if (ownerT != null && ownerT.isInner()
                        && !getCfg().getCu().check(DFlag.IGNORE_CONSTRUCTOR_THIS)) {
                    if (cop.getReg() == 1 && r.getT().is(getM().getParamTs()[0])) {
                        break fieldInitCheck;
                    }
                }
                setFieldInit(false);
            }
            bb.push(getVarExpression(cop.getReg(), cop.getPc(), op));
            break;
        }
        case MONITOR: {
            final MONITOR cop = (MONITOR) op;

            switch (cop.getKind()) {
            case ENTER: {
                final SynchronizedStatement synchronizedStatement = setOp(getAst().newSynchronizedStatement(),
                        op);
                synchronizedStatement.setExpression(wrap(bb.pop()));
                bb.addStmt(setOp(synchronizedStatement, op));
                break;
            }
            case EXIT: {
                // for now: same as ENTER, blocks don't work here,
                // use getOp() to distinguish in control flow analysis
                final SynchronizedStatement synchronizedStatement = setOp(getAst().newSynchronizedStatement(),
                        op);
                synchronizedStatement.setExpression(wrap(bb.pop()));
                bb.addStmt(setOp(synchronizedStatement, op));
                break;
            }
            default:
                log.warn(getM() + ": Unknown monitor kind '" + cop.getKind() + "'!");
            }
            break;
        }
        case MUL: {
            bb.push(newInfixExpressionPop(InfixExpression.Operator.TIMES, bb, op));
            break;
        }
        case NEG: {
            bb.push(newPrefixExpression(PrefixExpression.Operator.MINUS, bb.pop(), op));
            break;
        }
        case NEW: {
            final NEW cop = (NEW) op;

            final ClassInstanceCreation classInstanceCreation = setOp(getAst().newClassInstanceCreation(), op);

            final String thisName = getCfg().getT().getName();
            final T newT = cop.getT();
            final String newName = newT.getName();
            // check for valid inner anonymous
            anonymous: if (newT.validateQualifierName(thisName)) {
                try {
                    // anonymous classes typically use a number postfix, try it
                    Integer.parseInt(newName.substring(thisName.length() + 1));

                    if (newT.isDeclaration()) {
                        // anonymous inner can only have a single interface
                        // (with generic super "Object") or a super class
                        final T[] interfaceTs = newT.getInterfaceTs();
                        switch (interfaceTs.length) {
                        case 0: {
                            final T superT = newT.getSuperT();
                            assert superT != null;
                            classInstanceCreation.setType(newType(superT, getM()));
                            break;
                        }
                        case 1: {
                            final T interfaceT = interfaceTs[0];
                            assert interfaceT != null;
                            classInstanceCreation.setType(newType(interfaceT, getM()));
                            break;
                        }
                        default:
                            break anonymous;
                        }
                        final AnonymousClassDeclaration anonymousClassDeclaration = setOp(
                                getAst().newAnonymousClassDeclaration(), op);
                        newT.setAstNode(anonymousClassDeclaration);
                        classInstanceCreation.setAnonymousClassDeclaration(anonymousClassDeclaration);
                        bb.push(classInstanceCreation);
                        break;
                    }
                } catch (final NumberFormatException e) {
                    // no int
                }
            }
            classInstanceCreation.setType(newType(newT, getM()));
            bb.push(classInstanceCreation);
            break;
        }
        case NEWARRAY: {
            final NEWARRAY cop = (NEWARRAY) op;
            final ArrayCreation arrayCreation = setOp(getAst().newArrayCreation(), op);
            arrayCreation.setType((ArrayType) newType(cop.getT(), getM()));
            for (int i = cop.getDimensions(); i-- > 0;) {
                arrayCreation.dimensions().add(0, wrap(bb.pop()));
            }
            bb.push(arrayCreation);
            break;
        }
        case OR: {
            bb.push(newInfixExpressionPop(InfixExpression.Operator.OR, bb, op));
            break;
        }
        case POP: {
            final POP cop = (POP) op;
            switch (cop.getKind()) {
            case POP2: {
                final Expression e = bb.pop();
                if (Expressions.isStatementExpression(e)) {
                    bb.addStmt(setOp(getAst().newExpressionStatement(wrap(e)), op));
                } else if (e instanceof SimpleName) {
                    // exception or simple literal
                    break;
                } else if (isBoolean(e) && !(e instanceof BooleanLiteral)) {
                    if (getCfg().getT().isAtLeast(Version.JVM_4)) {
                        log.warn(getM() + ": Boolean expression POP in '" + cop
                                + "' for >= JVM 5 code! Rewriting to empty if.");
                    }
                    final IfStatement ifStatement = getAst().newIfStatement();
                    ifStatement.setExpression(wrap(e));
                    ifStatement.setThenStatement(getAst().newEmptyStatement());
                    bb.addStmt(setOp(ifStatement, op));
                }
                if (isWide(e)) {
                    break;
                }
                // fall through for second pop iff none-wide
            }
            case POP: {
                final Expression e = bb.pop();
                if (Expressions.isStatementExpression(e)) {
                    bb.addStmt(setOp(getAst().newExpressionStatement(wrap(e)), op));
                } else if (e instanceof SimpleName) {
                    // exception or simple literal
                    break;
                } else if (isBoolean(e) && !(e instanceof BooleanLiteral)) {
                    if (getCfg().getT().isAtLeast(Version.JVM_4)) {
                        log.warn(getM() + ": Boolean expression POP in '" + cop
                                + "' for >= JVM 5 code! Rewriting to empty if.");
                    }
                    final IfStatement ifStatement = getAst().newIfStatement();
                    ifStatement.setExpression(wrap(e));
                    ifStatement.setThenStatement(getAst().newEmptyStatement());
                    bb.addStmt(setOp(ifStatement, op));
                }
                break;
            }
            default:
                log.warn(getM() + ": Unknown POP type '" + cop.getKind() + "'!");
            }
            break;
        }
        case PUSH: {
            final PUSH cop = (PUSH) op;
            final T t = getCfg().getOutFrame(op).peek().getT();
            assert t != null;
            bb.push(newLiteral(t, cop.getValue(), getCfg().getM(), op));
            break;
        }
        case PUT: {
            final PUT cop = (PUT) op;
            final F f = cop.getF();
            final Expression rightOperand = bb.pop();
            assert rightOperand != null;
            if (rewriteFieldInit(bb, f, rightOperand)) {
                // was a constructor or initializer field init, done
                break;
            }
            Expression leftOperand;
            if (f.isStatic()) {
                leftOperand = getAst().newQualifiedName(newTypeName(f.getT(), getM()),
                        newSimpleName(f.getName(), getAst()));
            } else {
                final FieldAccess fieldAccess = getAst().newFieldAccess();
                fieldAccess.setExpression(wrap(bb.pop(), Priority.MEMBER_ACCESS));
                fieldAccess.setName(newSimpleName(f.getName(), getAst()));
                leftOperand = fieldAccess;
            }
            assert leftOperand != null;
            final Assignment assignment = newAssignment(Assignment.Operator.ASSIGN, leftOperand, rightOperand,
                    op);
            // TODO a = a +/- 1 => a++ / a--
            // TODO a = a <op> expr => a <op>= expr
            // inline assignment, DUP(_X1) -> PUT
            if (!bb.isStackEmpty() && bb.peek() == rightOperand) {
                bb.pop();
                bb.push(assignment);
                break;
            }
            if (!bb.isStackEmpty() && rightOperand instanceof InfixExpression
                    && (((InfixExpression) rightOperand).getOperator() == InfixExpression.Operator.PLUS
                            || ((InfixExpression) rightOperand)
                                    .getOperator() == InfixExpression.Operator.MINUS)) {
                // if i'm an peek-1 or peek+1 expression, than we can post-inc/dec
                // TODO more checks!
                bb.push(newPostfixExpression(
                        ((InfixExpression) rightOperand).getOperator() == InfixExpression.Operator.PLUS
                                ? PostfixExpression.Operator.INCREMENT
                                : PostfixExpression.Operator.DECREMENT,
                        bb.pop(), op));
                break;
            }
            bb.addStmt(setOp(getAst().newExpressionStatement(assignment), op));
            break;
        }
        case REM: {
            bb.push(newInfixExpressionPop(InfixExpression.Operator.REMAINDER, bb, op));
            break;
        }
        case RET: {
            // TODO
            break;
        }
        case RETURN: {
            final RETURN cop = (RETURN) op;
            final ReturnStatement returnStatement = getAst().newReturnStatement();
            if (cop.getT() != T.VOID) {
                returnStatement.setExpression(wrap(bb.pop()));
            }
            bb.addStmt(setOp(returnStatement, op));
            break;
        }
        case SHL: {
            bb.push(newInfixExpressionPop(InfixExpression.Operator.LEFT_SHIFT, bb, op));
            break;
        }
        case SHR: {
            final SHR cop = (SHR) op;
            bb.push(newInfixExpressionPop(cop.isUnsigned() ? InfixExpression.Operator.RIGHT_SHIFT_UNSIGNED
                    : InfixExpression.Operator.RIGHT_SHIFT_SIGNED, bb, op));
            break;
        }
        case STORE: {
            final STORE cop = (STORE) op;
            final Expression rightOperand = bb.pop();

            // handle exception name expression
            exceptionNameExpression: if (rightOperand instanceof SimpleName) {
                // should be an uninitialized, temporary exception name expression
                final ASTNode parent = rightOperand.getParent();
                if (!(parent instanceof VariableDeclarationFragment)) {
                    break exceptionNameExpression;
                }
                assert ((SimpleName) rightOperand).getIdentifier().equals(Expressions.EXCEPTION_NAME_TMP);
                // also renames the parent temporary throwable declaration name,
                // later used for creating catch control statements
                ((SimpleName) rightOperand).setIdentifier(getVarName(cop.getReg(), cop.getPc() + 1));
                break; // STORE end
            }
            // handle inline assignments via DUP -> STORE
            final boolean isInlineAssignment = !bb.isStackEmpty() && bb.peek() == rightOperand;

            // handle variable declaration assignments
            final V v = getCfg().getFrameVar(cop.getReg(), cop.getPc() + 1);
            if (v == null /* tmp hack */ || v.getName() == null) {
                // temporary local
                // bb.set(cop.getReg(), rightOperand);
                // break;
                // TODO else not really necessary later if this is sure
            } else {
                // TODO if () int i = 0 else int i = 1 ???
                if (!isInlineAssignment && v.getPcs()[0] /* TODO */ == cop.getPc() + 1) {
                    final VariableDeclarationFragment variableDeclarationFragment = getAst()
                            .newVariableDeclarationFragment();
                    variableDeclarationFragment.setName(newSimpleName(v.getName(), getAst()));
                    variableDeclarationFragment.setInitializer(wrap(rightOperand, Priority.ASSIGNMENT));
                    final VariableDeclarationStatement variableDeclarationStatement = getAst()
                            .newVariableDeclarationStatement(variableDeclarationFragment);
                    variableDeclarationStatement.setType(newType(v.getT(), getM()));
                    bb.addStmt(setOp(variableDeclarationStatement, op));
                    break;
                }
            }

            final Assignment assignment = newAssignment(Assignment.Operator.ASSIGN,
                    getVarExpression(cop.getReg(), cop.getPc() + 1, op), rightOperand, op);

            if (isInlineAssignment) {
                bb.pop();
                bb.push(assignment);
                break;
            }
            if (!rewriteStorePreIncDec(bb, assignment)) {
                bb.addStmt(setOp(getAst().newExpressionStatement(assignment), op));
            }
            break;
        }
        case SUB: {
            bb.push(newInfixExpressionPop(InfixExpression.Operator.MINUS, bb, op));
            break;
        }
        case SWAP: {
            final Expression e1 = bb.pop();
            final Expression e2 = bb.pop();
            bb.push(e1);
            bb.push(e2);
            break;
        }
        case SWITCH: {
            final SWITCH cop = (SWITCH) op;

            final Expression switchExpression = bb.pop();
            assert switchExpression != null;
            if (rewriteSwitchEnum(bb, cop, switchExpression)) {
                break;
            }
            if (rewriteSwitchString(bb, cop, switchExpression)) {
                break;
            }
            final T t = peekT(op);
            if (t == T.CHAR) {
                rewriteSwitchChar(bb);
            }
            final SwitchStatement switchStatement = getAst().newSwitchStatement();
            switchStatement.setExpression(wrap(switchExpression));
            bb.addStmt(setOp(switchStatement, op));
            break;
        }
        case THROW: {
            final Expression exceptionExpression = bb.pop();
            assert exceptionExpression != null;
            final ThrowStatement throwStatement = getAst().newThrowStatement();
            throwStatement.setExpression(wrap(exceptionExpression));
            bb.addStmt(setOp(throwStatement, op));
            break;
        }
        case XOR: {
            final Expression rightOperand = bb.pop();
            // "a ^ -1" => "~a"
            if (rightOperand instanceof NumberLiteral
                    && ((NumberLiteral) rightOperand).getToken().equals("-1")) {
                bb.push(newPrefixExpression(PrefixExpression.Operator.COMPLEMENT, bb.pop(), op));
                break;
            }
            // "a ^ true" => "!a" (found in JVM 1.2 boolean expressions)
            if (rightOperand instanceof BooleanLiteral && getBooleanValue(rightOperand) == Boolean.TRUE) {
                bb.push(newPrefixExpression(PrefixExpression.Operator.NOT, bb.pop(), op));
                break;
            }
            bb.push(newInfixExpression(InfixExpression.Operator.XOR, bb.pop(), rightOperand, op));
            break;
        }
        default:
            throw new DecoJerException("Unknown intermediate vm operation '" + op + "'!");
        }
    }
    return true;
}