boolean (Statement stat, SSAConstructorSparseEx ssa) { if (stat.type == StatementType.IF && stat.getExprents() == null) { IfStatement statement = (IfStatement)stat; Exprent ifHeadExpr = statement.getHeadexprent(); Set<Integer> ifHeadExprBytecode = (ifHeadExpr == null ? null : ifHeadExpr.bytecode); if (statement.iftype == IfStatement.IFTYPE_IFELSE) { Statement ifStatement = statement.getIfstat(); Statement elseStatement = statement.getElsestat(); if (ifStatement.getExprents() != null && ifStatement.getExprents().size() == 1 && elseStatement.getExprents() != null && elseStatement.getExprents().size() == 1 && ifStatement.getAllSuccessorEdges().size() == 1 && elseStatement.getAllSuccessorEdges().size() == 1 && ifStatement.getAllSuccessorEdges().get(0).getDestination() == elseStatement.getAllSuccessorEdges().get(0).getDestination()) { Exprent ifExpr = ifStatement.getExprents().get(0); Exprent elseExpr = elseStatement.getExprents().get(0); if (ifExpr.type == Exprent.EXPRENT_ASSIGNMENT && elseExpr.type == Exprent.EXPRENT_ASSIGNMENT) { AssignmentExprent ifAssign = (AssignmentExprent)ifExpr; AssignmentExprent elseAssign = (AssignmentExprent)elseExpr; if (ifAssign.getLeft().type == Exprent.EXPRENT_VAR && elseAssign.getLeft().type == Exprent.EXPRENT_VAR) { VarExprent ifVar = (VarExprent)ifAssign.getLeft(); VarExprent elseVar = (VarExprent)elseAssign.getLeft(); if (ifVar.getIndex() == elseVar.getIndex() && ifVar.isStack()) { // ifVar.getIndex() >= VarExprent.STACK_BASE) { boolean found = false; for (Entry<VarVersionPair, FastSparseSet<Integer>> ent : ssa.getPhi().entrySet()) { if (ent.getKey().var == ifVar.getIndex()) { if (ent.getValue().contains(ifVar.getVersion()) && ent.getValue().contains(elseVar.getVersion())) { found = true; break; } } } if (found) { List<Exprent> data = new ArrayList<>(statement.getFirst().getExprents()); List<Exprent> operands = Arrays.asList(statement.getHeadexprent().getCondition(), ifAssign.getRight(), elseAssign.getRight()); data.add(new AssignmentExprent(ifVar, new FunctionExprent(FunctionExprent.FUNCTION_IIF, operands, ifHeadExprBytecode), ifHeadExprBytecode)); statement.setExprents(data); if (statement.getAllSuccessorEdges().isEmpty()) { StatEdge ifEdge = ifStatement.getAllSuccessorEdges().get(0); StatEdge edge = new StatEdge(ifEdge.getType(), statement, ifEdge.getDestination()); statement.addSuccessor(edge); if (ifEdge.closure != null) { ifEdge.closure.addLabeledEdge(edge); } } SequenceHelper.destroyAndFlattenStatement(statement); return true; } } } } else if (ifExpr.type == Exprent.EXPRENT_EXIT && elseExpr.type == Exprent.EXPRENT_EXIT) { ExitExprent ifExit = (ExitExprent)ifExpr; ExitExprent elseExit = (ExitExprent)elseExpr; if (ifExit.getExitType() == elseExit.getExitType() && ifExit.getValue() != null && elseExit.getValue() != null && ifExit.getExitType() == ExitExprent.EXIT_RETURN) { // throw is dangerous, because of implicit casting to a common superclass // e.g. throws IOException and throw true?new RuntimeException():new IOException(); won't work if (ifExit.getExitType() == ExitExprent.EXIT_THROW && !ifExit.getValue().getExprType().equals(elseExit.getValue().getExprType())) { // note: getExprType unreliable at this point! return false; } // avoid flattening to 'iff' if any of the branches is an 'iff' already if (isIff(ifExit.getValue()) || isIff(elseExit.getValue())) { return false; } List<Exprent> data = new ArrayList<>(statement.getFirst().getExprents()); data.add(new ExitExprent(ifExit.getExitType(), new FunctionExprent(FunctionExprent.FUNCTION_IIF, Arrays.asList( statement.getHeadexprent().getCondition(), ifExit.getValue(), elseExit.getValue()), ifHeadExprBytecode), ifExit.getRetType(), ifHeadExprBytecode)); statement.setExprents(data); StatEdge retEdge = ifStatement.getAllSuccessorEdges().get(0); Statement closure = retEdge.closure == statement ? statement.getParent() : retEdge.closure; statement.addSuccessor(new StatEdge(EdgeType.BREAK, statement, retEdge.getDestination(), closure)); SequenceHelper.destroyAndFlattenStatement(statement); return true; } } } } } return false; } private static boolean isIff(Exprent exp) { return exp.type == Exprent.EXPRENT_FUNCTION && ((FunctionExprent) exp).getFuncType() == FunctionExprent.FUNCTION_IIF; } private static boolean collapseInlinedClass14(Statement stat) { boolean ret = class14Builder.match(stat); if (ret) { String class_name = (String)class14Builder.getVariableValue("$classname$"); AssignmentExprent assignment = (AssignmentExprent)class14Builder.getVariableValue("$assignfield$"); FieldExprent fieldExpr = (FieldExprent)class14Builder.getVariableValue("$field$"); assignment.replaceExprent(assignment.getRight(), new ConstExprent(VarType.VARTYPE_CLASS, class_name, null)); List<Exprent> data = new ArrayList<>(stat.getFirst().getExprents()); stat.setExprents(data); SequenceHelper.destroyAndFlattenStatement(stat); ClassWrapper wrapper = (ClassWrapper)DecompilerContext.getProperty(DecompilerContext.CURRENT_CLASS_WRAPPER); if (wrapper != null) { wrapper.getHiddenMembers().add(InterpreterUtil.makeUniqueKey(fieldExpr.getName(), fieldExpr.getDescriptor().descriptorString)); } } return ret; } }