diff options
Diffstat (limited to 'src/org/jetbrains/java/decompiler/modules/decompiler/SecondaryFunctionsHelper.java')
-rw-r--r-- | src/org/jetbrains/java/decompiler/modules/decompiler/SecondaryFunctionsHelper.java | 822 |
1 files changed, 413 insertions, 409 deletions
diff --git a/src/org/jetbrains/java/decompiler/modules/decompiler/SecondaryFunctionsHelper.java b/src/org/jetbrains/java/decompiler/modules/decompiler/SecondaryFunctionsHelper.java index e8f1e0a..8dcf9d5 100644 --- a/src/org/jetbrains/java/decompiler/modules/decompiler/SecondaryFunctionsHelper.java +++ b/src/org/jetbrains/java/decompiler/modules/decompiler/SecondaryFunctionsHelper.java @@ -1,428 +1,432 @@ /* - * Fernflower - The Analytical Java Decompiler - * http://www.reversed-java.com + * Copyright 2000-2014 JetBrains s.r.o. * - * (C) 2008 - 2010, Stiver + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * This software is NEITHER public domain NOR free software - * as per GNU License. See license.txt for more details. + * http://www.apache.org/licenses/LICENSE-2.0 * - * This software is distributed WITHOUT ANY WARRANTY; without - * even the implied warranty of MERCHANTABILITY or FITNESS FOR - * A PARTICULAR PURPOSE. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ - package org.jetbrains.java.decompiler.modules.decompiler; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; - - import org.jetbrains.java.decompiler.code.CodeConstants; import org.jetbrains.java.decompiler.main.DecompilerContext; import org.jetbrains.java.decompiler.main.collectors.CounterContainer; -import org.jetbrains.java.decompiler.modules.decompiler.exps.AssignmentExprent; -import org.jetbrains.java.decompiler.modules.decompiler.exps.ConstExprent; -import org.jetbrains.java.decompiler.modules.decompiler.exps.Exprent; -import org.jetbrains.java.decompiler.modules.decompiler.exps.FunctionExprent; -import org.jetbrains.java.decompiler.modules.decompiler.exps.IfExprent; -import org.jetbrains.java.decompiler.modules.decompiler.exps.VarExprent; +import org.jetbrains.java.decompiler.modules.decompiler.exps.*; import org.jetbrains.java.decompiler.modules.decompiler.stats.IfStatement; import org.jetbrains.java.decompiler.modules.decompiler.stats.Statement; import org.jetbrains.java.decompiler.modules.decompiler.vars.VarProcessor; import org.jetbrains.java.decompiler.modules.decompiler.vars.VarVersionPaar; import org.jetbrains.java.decompiler.struct.gen.VarType; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; + public class SecondaryFunctionsHelper { - private static final int[] funcsnot = new int[] { - FunctionExprent.FUNCTION_NE, - FunctionExprent.FUNCTION_EQ, - FunctionExprent.FUNCTION_GE, - FunctionExprent.FUNCTION_LT, - FunctionExprent.FUNCTION_LE, - FunctionExprent.FUNCTION_GT, - FunctionExprent.FUNCTION_COR, - FunctionExprent.FUNCTION_CADD - }; - - private static final HashMap<Integer, Integer[]> mapNumComparisons = new HashMap<Integer, Integer[]>(); - - static { - mapNumComparisons.put(FunctionExprent.FUNCTION_EQ, new Integer[] {FunctionExprent.FUNCTION_LT, FunctionExprent.FUNCTION_EQ, FunctionExprent.FUNCTION_GT}); - mapNumComparisons.put(FunctionExprent.FUNCTION_NE, new Integer[] {FunctionExprent.FUNCTION_GE, FunctionExprent.FUNCTION_NE, FunctionExprent.FUNCTION_LE}); - mapNumComparisons.put(FunctionExprent.FUNCTION_GT, new Integer[] {FunctionExprent.FUNCTION_GE, FunctionExprent.FUNCTION_GT, null}); - mapNumComparisons.put(FunctionExprent.FUNCTION_GE, new Integer[] {null, FunctionExprent.FUNCTION_GE, FunctionExprent.FUNCTION_GT}); - mapNumComparisons.put(FunctionExprent.FUNCTION_LT, new Integer[] {null, FunctionExprent.FUNCTION_LT, FunctionExprent.FUNCTION_LE}); - mapNumComparisons.put(FunctionExprent.FUNCTION_LE, new Integer[] {FunctionExprent.FUNCTION_LT, FunctionExprent.FUNCTION_LE, null}); - } - - - public static boolean identifySecondaryFunctions(Statement stat) { - - if(stat.getExprents() == null) { - // if(){;}else{...} -> if(!){...} - if(stat.type == Statement.TYPE_IF) { - IfStatement ifelsestat = (IfStatement)stat; - Statement ifstat = ifelsestat.getIfstat(); - - if(ifelsestat.iftype == IfStatement.IFTYPE_IFELSE && ifstat.getExprents() != null && - ifstat.getExprents().isEmpty() && (ifstat.getAllSuccessorEdges().isEmpty() || !ifstat.getAllSuccessorEdges().get(0).explicit)) { - - // move else to the if position - ifelsestat.getStats().removeWithKey(ifstat.id); - - ifelsestat.iftype = IfStatement.IFTYPE_IF; - ifelsestat.setIfstat(ifelsestat.getElsestat()); - ifelsestat.setElsestat(null); - - if(ifelsestat.getAllSuccessorEdges().isEmpty() && !ifstat.getAllSuccessorEdges().isEmpty()) { - StatEdge endedge = ifstat.getAllSuccessorEdges().get(0); - - ifstat.removeSuccessor(endedge); - endedge.setSource(ifelsestat); - if(endedge.closure != null) { - ifelsestat.getParent().addLabeledEdge(endedge); - } - ifelsestat.addSuccessor(endedge); - } - - ifelsestat.getFirst().removeSuccessor(ifelsestat.getIfEdge()); - - ifelsestat.setIfEdge(ifelsestat.getElseEdge()); - ifelsestat.setElseEdge(null); - - // negate head expression - ifelsestat.setNegated(!ifelsestat.isNegated()); - ifelsestat.getHeadexprentList().set(0, ((IfExprent)ifelsestat.getHeadexprent().copy()).negateIf()); - - return true; - } - } - } - - - boolean replaced = true; - while(replaced) { - replaced = false; - - List<Object> lstObjects = new ArrayList<Object>(stat.getExprents()==null?stat.getSequentialObjects():stat.getExprents()); - - for(int i=0;i<lstObjects.size();i++) { - Object obj = lstObjects.get(i); - - if(obj instanceof Statement) { - if(identifySecondaryFunctions((Statement)obj)) { - replaced = true; - break; - } - } else if(obj instanceof Exprent) { - Exprent retexpr = identifySecondaryFunctions((Exprent)obj, true); - if(retexpr != null) { - if(stat.getExprents()==null) { - // only head expressions can be replaced! - stat.replaceExprent((Exprent)obj, retexpr); - } else { - stat.getExprents().set(i, retexpr); - } - replaced = true; - break; - } - } - } - } - - return false; - } - - - private static Exprent identifySecondaryFunctions(Exprent exprent, boolean statement_level) { - - if(exprent.type == Exprent.EXPRENT_FUNCTION) { - FunctionExprent fexpr = (FunctionExprent)exprent; - - switch(fexpr.getFunctype()) { - case FunctionExprent.FUNCTION_BOOLNOT: - - Exprent retparam = propagateBoolNot(fexpr); - - if(retparam != null) { - return retparam; - } - - break; - case FunctionExprent.FUNCTION_EQ: - case FunctionExprent.FUNCTION_NE: - case FunctionExprent.FUNCTION_GT: - case FunctionExprent.FUNCTION_GE: - case FunctionExprent.FUNCTION_LT: - case FunctionExprent.FUNCTION_LE: - Exprent expr1 = fexpr.getLstOperands().get(0); - Exprent expr2 = fexpr.getLstOperands().get(1); - - if(expr1.type == Exprent.EXPRENT_CONST) { - expr2 = expr1; - expr1 = fexpr.getLstOperands().get(1); - } - - if(expr1.type == Exprent.EXPRENT_FUNCTION && expr2.type == Exprent.EXPRENT_CONST) { - FunctionExprent funcexpr = (FunctionExprent)expr1; - ConstExprent cexpr = (ConstExprent)expr2; - - int functype = funcexpr.getFunctype(); - if(functype == FunctionExprent.FUNCTION_LCMP || functype == FunctionExprent.FUNCTION_FCMPG || - functype == FunctionExprent.FUNCTION_FCMPL || functype == FunctionExprent.FUNCTION_DCMPG || - functype == FunctionExprent.FUNCTION_DCMPL) { - - int desttype = -1; - - Integer[] destcons = mapNumComparisons.get(fexpr.getFunctype()); - if(destcons != null) { - int index = cexpr.getIntValue()+1; - if(index >= 0 && index <= 2) { - Integer destcon = destcons[index]; - if(destcon != null) { - desttype = destcon.intValue(); - } - } - } - - if(desttype >= 0) { - return new FunctionExprent(desttype, funcexpr.getLstOperands()); - } - } - } - } - } - - - boolean replaced = true; - while(replaced) { - replaced = false; - - for(Exprent expr: exprent.getAllExprents()) { - Exprent retexpr = identifySecondaryFunctions(expr, false); - if(retexpr != null) { - exprent.replaceExprent(expr, retexpr); - replaced = true; - break; - } - } - } - - switch(exprent.type) { - case Exprent.EXPRENT_FUNCTION: - FunctionExprent fexpr = (FunctionExprent)exprent; - List<Exprent> lstOperands = fexpr.getLstOperands(); - - switch(fexpr.getFunctype()) { - case FunctionExprent.FUNCTION_XOR: - for(int i=0;i<2;i++) { - Exprent operand = lstOperands.get(i); - VarType operandtype = operand.getExprType(); - - if(operand.type == Exprent.EXPRENT_CONST && - operandtype.type != CodeConstants.TYPE_BOOLEAN) { - ConstExprent cexpr = (ConstExprent)operand; - long val; - if(operandtype.type == CodeConstants.TYPE_LONG) { - val = ((Long)cexpr.getValue()).longValue(); - } else { - val = ((Integer)cexpr.getValue()).intValue(); - } - - if(val == -1) { - List<Exprent> lstBitNotOperand = new ArrayList<Exprent>(); - lstBitNotOperand.add(lstOperands.get(1-i)); - return new FunctionExprent(FunctionExprent.FUNCTION_BITNOT, lstBitNotOperand); - } - } - } - break; - case FunctionExprent.FUNCTION_EQ: - case FunctionExprent.FUNCTION_NE: - if(lstOperands.get(0).getExprType().type == CodeConstants.TYPE_BOOLEAN && - lstOperands.get(1).getExprType().type == CodeConstants.TYPE_BOOLEAN) { - for(int i=0;i<2;i++) { - if(lstOperands.get(i).type == Exprent.EXPRENT_CONST) { - ConstExprent cexpr = (ConstExprent)lstOperands.get(i); - int val = ((Integer)cexpr.getValue()).intValue(); - - if((fexpr.getFunctype() == FunctionExprent.FUNCTION_EQ && val == 1) || - (fexpr.getFunctype() == FunctionExprent.FUNCTION_NE && val == 0)) { - return lstOperands.get(1-i); - } else { - List<Exprent> lstNotOperand = new ArrayList<Exprent>(); - lstNotOperand.add(lstOperands.get(1-i)); - return new FunctionExprent(FunctionExprent.FUNCTION_BOOLNOT, lstNotOperand); - } - } - } - } - break; - case FunctionExprent.FUNCTION_BOOLNOT: - if(lstOperands.get(0).type == Exprent.EXPRENT_CONST) { - int val = ((ConstExprent)lstOperands.get(0)).getIntValue(); - if(val == 0) { - return new ConstExprent(VarType.VARTYPE_BOOLEAN, new Integer(1)); - } else { - return new ConstExprent(VarType.VARTYPE_BOOLEAN, new Integer(0)); - } - } - break; - case FunctionExprent.FUNCTION_IIF: - Exprent expr1 = lstOperands.get(1); - Exprent expr2 = lstOperands.get(2); - - if(expr1.type == Exprent.EXPRENT_CONST && expr2.type == Exprent.EXPRENT_CONST) { - ConstExprent cexpr1 = (ConstExprent)expr1; - ConstExprent cexpr2 = (ConstExprent)expr2; - - if(cexpr1.getExprType().type == CodeConstants.TYPE_BOOLEAN && - cexpr2.getExprType().type == CodeConstants.TYPE_BOOLEAN) { - - if(cexpr1.getIntValue() == 0 && cexpr2.getIntValue() != 0) { - return new FunctionExprent(FunctionExprent.FUNCTION_BOOLNOT, Arrays.asList(new Exprent[] {lstOperands.get(0)})); - } else if(cexpr1.getIntValue() != 0 && cexpr2.getIntValue() == 0) { - return lstOperands.get(0); - } - } - } - break; - case FunctionExprent.FUNCTION_LCMP: - case FunctionExprent.FUNCTION_FCMPL: - case FunctionExprent.FUNCTION_FCMPG: - case FunctionExprent.FUNCTION_DCMPL: - case FunctionExprent.FUNCTION_DCMPG: - int var = DecompilerContext.getCountercontainer().getCounterAndIncrement(CounterContainer.VAR_COUNTER); - VarType type = lstOperands.get(0).getExprType(); - VarProcessor processor = (VarProcessor)DecompilerContext.getProperty(DecompilerContext.CURRENT_VAR_PROCESSOR); - - FunctionExprent iff = new FunctionExprent(FunctionExprent.FUNCTION_IIF, Arrays.asList(new Exprent[] { - new FunctionExprent(FunctionExprent.FUNCTION_LT, Arrays.asList(new Exprent[] {new VarExprent(var, type, processor), - ConstExprent.getZeroConstant(type.type)})), - new ConstExprent(VarType.VARTYPE_INT, new Integer(-1)), - new ConstExprent(VarType.VARTYPE_INT, new Integer(1))})); - - FunctionExprent head = new FunctionExprent(FunctionExprent.FUNCTION_EQ, Arrays.asList(new Exprent[] { - new AssignmentExprent(new VarExprent(var, type, processor), new FunctionExprent(FunctionExprent.FUNCTION_SUB, - Arrays.asList(new Exprent[] {lstOperands.get(0), lstOperands.get(1)}))), - ConstExprent.getZeroConstant(type.type)})); - - processor.setVarType(new VarVersionPaar(var, 0), type); - - return new FunctionExprent(FunctionExprent.FUNCTION_IIF, Arrays.asList(new Exprent[] { - head, new ConstExprent(VarType.VARTYPE_INT, new Integer(0)), iff})); - } - break; - case Exprent.EXPRENT_ASSIGNMENT: // check for conditional assignment - AssignmentExprent asexpr = (AssignmentExprent)exprent; - Exprent right = asexpr.getRight(); - Exprent left = asexpr.getLeft(); - - if(right.type == Exprent.EXPRENT_FUNCTION) { - FunctionExprent func = (FunctionExprent)right; - - VarType midlayer = null; - if(func.getFunctype() >= FunctionExprent.FUNCTION_I2L && - func.getFunctype() <= FunctionExprent.FUNCTION_I2S) { - right = func.getLstOperands().get(0); - midlayer = func.getSimpleCastType(); - if(right.type == Exprent.EXPRENT_FUNCTION) { - func = (FunctionExprent)right; - } else { - return null; - } - } - - List<Exprent> lstFuncOperands = func.getLstOperands(); - - Exprent cond = null; - - switch(func.getFunctype()) { - case FunctionExprent.FUNCTION_ADD: - case FunctionExprent.FUNCTION_AND: - case FunctionExprent.FUNCTION_OR: - case FunctionExprent.FUNCTION_XOR: - if(left.equals(lstFuncOperands.get(1))) { - cond = lstFuncOperands.get(0); - break; - } - case FunctionExprent.FUNCTION_SUB: - case FunctionExprent.FUNCTION_MUL: - case FunctionExprent.FUNCTION_DIV: - case FunctionExprent.FUNCTION_REM: - case FunctionExprent.FUNCTION_SHL: - case FunctionExprent.FUNCTION_SHR: - case FunctionExprent.FUNCTION_USHR: - if(left.equals(lstFuncOperands.get(0))) { - cond = lstFuncOperands.get(1); - } - } - - if(cond!=null && (midlayer == null || midlayer.equals(cond.getExprType()))) { - asexpr.setRight(cond); - asexpr.setCondtype(func.getFunctype()); - } - } - break; - case Exprent.EXPRENT_INVOCATION: - if(!statement_level) { // simplify if exprent is a real expression. The opposite case is pretty absurd, can still happen however (and happened at least once). - Exprent retexpr = ConcatenationHelper.contractStringConcat(exprent); - if(!exprent.equals(retexpr)) { - return retexpr; - } - } - } - - return null; - - } - - public static Exprent propagateBoolNot(Exprent exprent) { - - if(exprent.type == Exprent.EXPRENT_FUNCTION) { - FunctionExprent fexpr = (FunctionExprent)exprent; - - if(fexpr.getFunctype() == FunctionExprent.FUNCTION_BOOLNOT) { - - Exprent param = fexpr.getLstOperands().get(0); - - if(param.type == Exprent.EXPRENT_FUNCTION) { - FunctionExprent fparam = (FunctionExprent)param; - - int ftype = fparam.getFunctype(); - switch(ftype) { - case FunctionExprent.FUNCTION_BOOLNOT: - Exprent newexpr = fparam.getLstOperands().get(0); - Exprent retexpr = propagateBoolNot(newexpr); - return retexpr == null?newexpr:retexpr; - case FunctionExprent.FUNCTION_CADD: - case FunctionExprent.FUNCTION_COR: - List<Exprent> operands = fparam.getLstOperands(); - for(int i=0;i<operands.size();i++) { - Exprent newparam = new FunctionExprent(FunctionExprent.FUNCTION_BOOLNOT, - Arrays.asList(new Exprent[]{operands.get(i)})); - - Exprent retparam = propagateBoolNot(newparam); - operands.set(i, retparam == null?newparam:retparam); - } - case FunctionExprent.FUNCTION_EQ: - case FunctionExprent.FUNCTION_NE: - case FunctionExprent.FUNCTION_LT: - case FunctionExprent.FUNCTION_GE: - case FunctionExprent.FUNCTION_GT: - case FunctionExprent.FUNCTION_LE: - fparam.setFunctype(funcsnot[ftype-FunctionExprent.FUNCTION_EQ]); - return fparam; - } - } - } - } - - return null; - } - + private static final int[] funcsnot = new int[]{ + FunctionExprent.FUNCTION_NE, + FunctionExprent.FUNCTION_EQ, + FunctionExprent.FUNCTION_GE, + FunctionExprent.FUNCTION_LT, + FunctionExprent.FUNCTION_LE, + FunctionExprent.FUNCTION_GT, + FunctionExprent.FUNCTION_COR, + FunctionExprent.FUNCTION_CADD + }; + + private static final HashMap<Integer, Integer[]> mapNumComparisons = new HashMap<Integer, Integer[]>(); + + static { + mapNumComparisons.put(FunctionExprent.FUNCTION_EQ, + new Integer[]{FunctionExprent.FUNCTION_LT, FunctionExprent.FUNCTION_EQ, FunctionExprent.FUNCTION_GT}); + mapNumComparisons.put(FunctionExprent.FUNCTION_NE, + new Integer[]{FunctionExprent.FUNCTION_GE, FunctionExprent.FUNCTION_NE, FunctionExprent.FUNCTION_LE}); + mapNumComparisons.put(FunctionExprent.FUNCTION_GT, new Integer[]{FunctionExprent.FUNCTION_GE, FunctionExprent.FUNCTION_GT, null}); + mapNumComparisons.put(FunctionExprent.FUNCTION_GE, new Integer[]{null, FunctionExprent.FUNCTION_GE, FunctionExprent.FUNCTION_GT}); + mapNumComparisons.put(FunctionExprent.FUNCTION_LT, new Integer[]{null, FunctionExprent.FUNCTION_LT, FunctionExprent.FUNCTION_LE}); + mapNumComparisons.put(FunctionExprent.FUNCTION_LE, new Integer[]{FunctionExprent.FUNCTION_LT, FunctionExprent.FUNCTION_LE, null}); + } + + + public static boolean identifySecondaryFunctions(Statement stat) { + + if (stat.getExprents() == null) { + // if(){;}else{...} -> if(!){...} + if (stat.type == Statement.TYPE_IF) { + IfStatement ifelsestat = (IfStatement)stat; + Statement ifstat = ifelsestat.getIfstat(); + + if (ifelsestat.iftype == IfStatement.IFTYPE_IFELSE && ifstat.getExprents() != null && + ifstat.getExprents().isEmpty() && (ifstat.getAllSuccessorEdges().isEmpty() || !ifstat.getAllSuccessorEdges().get(0).explicit)) { + + // move else to the if position + ifelsestat.getStats().removeWithKey(ifstat.id); + + ifelsestat.iftype = IfStatement.IFTYPE_IF; + ifelsestat.setIfstat(ifelsestat.getElsestat()); + ifelsestat.setElsestat(null); + + if (ifelsestat.getAllSuccessorEdges().isEmpty() && !ifstat.getAllSuccessorEdges().isEmpty()) { + StatEdge endedge = ifstat.getAllSuccessorEdges().get(0); + + ifstat.removeSuccessor(endedge); + endedge.setSource(ifelsestat); + if (endedge.closure != null) { + ifelsestat.getParent().addLabeledEdge(endedge); + } + ifelsestat.addSuccessor(endedge); + } + + ifelsestat.getFirst().removeSuccessor(ifelsestat.getIfEdge()); + + ifelsestat.setIfEdge(ifelsestat.getElseEdge()); + ifelsestat.setElseEdge(null); + + // negate head expression + ifelsestat.setNegated(!ifelsestat.isNegated()); + ifelsestat.getHeadexprentList().set(0, ((IfExprent)ifelsestat.getHeadexprent().copy()).negateIf()); + + return true; + } + } + } + + + boolean replaced = true; + while (replaced) { + replaced = false; + + List<Object> lstObjects = new ArrayList<Object>(stat.getExprents() == null ? stat.getSequentialObjects() : stat.getExprents()); + + for (int i = 0; i < lstObjects.size(); i++) { + Object obj = lstObjects.get(i); + + if (obj instanceof Statement) { + if (identifySecondaryFunctions((Statement)obj)) { + replaced = true; + break; + } + } + else if (obj instanceof Exprent) { + Exprent retexpr = identifySecondaryFunctions((Exprent)obj, true); + if (retexpr != null) { + if (stat.getExprents() == null) { + // only head expressions can be replaced! + stat.replaceExprent((Exprent)obj, retexpr); + } + else { + stat.getExprents().set(i, retexpr); + } + replaced = true; + break; + } + } + } + } + + return false; + } + + + private static Exprent identifySecondaryFunctions(Exprent exprent, boolean statement_level) { + + if (exprent.type == Exprent.EXPRENT_FUNCTION) { + FunctionExprent fexpr = (FunctionExprent)exprent; + + switch (fexpr.getFunctype()) { + case FunctionExprent.FUNCTION_BOOLNOT: + + Exprent retparam = propagateBoolNot(fexpr); + + if (retparam != null) { + return retparam; + } + + break; + case FunctionExprent.FUNCTION_EQ: + case FunctionExprent.FUNCTION_NE: + case FunctionExprent.FUNCTION_GT: + case FunctionExprent.FUNCTION_GE: + case FunctionExprent.FUNCTION_LT: + case FunctionExprent.FUNCTION_LE: + Exprent expr1 = fexpr.getLstOperands().get(0); + Exprent expr2 = fexpr.getLstOperands().get(1); + + if (expr1.type == Exprent.EXPRENT_CONST) { + expr2 = expr1; + expr1 = fexpr.getLstOperands().get(1); + } + + if (expr1.type == Exprent.EXPRENT_FUNCTION && expr2.type == Exprent.EXPRENT_CONST) { + FunctionExprent funcexpr = (FunctionExprent)expr1; + ConstExprent cexpr = (ConstExprent)expr2; + + int functype = funcexpr.getFunctype(); + if (functype == FunctionExprent.FUNCTION_LCMP || functype == FunctionExprent.FUNCTION_FCMPG || + functype == FunctionExprent.FUNCTION_FCMPL || functype == FunctionExprent.FUNCTION_DCMPG || + functype == FunctionExprent.FUNCTION_DCMPL) { + + int desttype = -1; + + Integer[] destcons = mapNumComparisons.get(fexpr.getFunctype()); + if (destcons != null) { + int index = cexpr.getIntValue() + 1; + if (index >= 0 && index <= 2) { + Integer destcon = destcons[index]; + if (destcon != null) { + desttype = destcon.intValue(); + } + } + } + + if (desttype >= 0) { + return new FunctionExprent(desttype, funcexpr.getLstOperands()); + } + } + } + } + } + + + boolean replaced = true; + while (replaced) { + replaced = false; + + for (Exprent expr : exprent.getAllExprents()) { + Exprent retexpr = identifySecondaryFunctions(expr, false); + if (retexpr != null) { + exprent.replaceExprent(expr, retexpr); + replaced = true; + break; + } + } + } + + switch (exprent.type) { + case Exprent.EXPRENT_FUNCTION: + FunctionExprent fexpr = (FunctionExprent)exprent; + List<Exprent> lstOperands = fexpr.getLstOperands(); + + switch (fexpr.getFunctype()) { + case FunctionExprent.FUNCTION_XOR: + for (int i = 0; i < 2; i++) { + Exprent operand = lstOperands.get(i); + VarType operandtype = operand.getExprType(); + + if (operand.type == Exprent.EXPRENT_CONST && + operandtype.type != CodeConstants.TYPE_BOOLEAN) { + ConstExprent cexpr = (ConstExprent)operand; + long val; + if (operandtype.type == CodeConstants.TYPE_LONG) { + val = ((Long)cexpr.getValue()).longValue(); + } + else { + val = ((Integer)cexpr.getValue()).intValue(); + } + + if (val == -1) { + List<Exprent> lstBitNotOperand = new ArrayList<Exprent>(); + lstBitNotOperand.add(lstOperands.get(1 - i)); + return new FunctionExprent(FunctionExprent.FUNCTION_BITNOT, lstBitNotOperand); + } + } + } + break; + case FunctionExprent.FUNCTION_EQ: + case FunctionExprent.FUNCTION_NE: + if (lstOperands.get(0).getExprType().type == CodeConstants.TYPE_BOOLEAN && + lstOperands.get(1).getExprType().type == CodeConstants.TYPE_BOOLEAN) { + for (int i = 0; i < 2; i++) { + if (lstOperands.get(i).type == Exprent.EXPRENT_CONST) { + ConstExprent cexpr = (ConstExprent)lstOperands.get(i); + int val = ((Integer)cexpr.getValue()).intValue(); + + if ((fexpr.getFunctype() == FunctionExprent.FUNCTION_EQ && val == 1) || + (fexpr.getFunctype() == FunctionExprent.FUNCTION_NE && val == 0)) { + return lstOperands.get(1 - i); + } + else { + List<Exprent> lstNotOperand = new ArrayList<Exprent>(); + lstNotOperand.add(lstOperands.get(1 - i)); + return new FunctionExprent(FunctionExprent.FUNCTION_BOOLNOT, lstNotOperand); + } + } + } + } + break; + case FunctionExprent.FUNCTION_BOOLNOT: + if (lstOperands.get(0).type == Exprent.EXPRENT_CONST) { + int val = ((ConstExprent)lstOperands.get(0)).getIntValue(); + if (val == 0) { + return new ConstExprent(VarType.VARTYPE_BOOLEAN, new Integer(1)); + } + else { + return new ConstExprent(VarType.VARTYPE_BOOLEAN, new Integer(0)); + } + } + break; + case FunctionExprent.FUNCTION_IIF: + Exprent expr1 = lstOperands.get(1); + Exprent expr2 = lstOperands.get(2); + + if (expr1.type == Exprent.EXPRENT_CONST && expr2.type == Exprent.EXPRENT_CONST) { + ConstExprent cexpr1 = (ConstExprent)expr1; + ConstExprent cexpr2 = (ConstExprent)expr2; + + if (cexpr1.getExprType().type == CodeConstants.TYPE_BOOLEAN && + cexpr2.getExprType().type == CodeConstants.TYPE_BOOLEAN) { + + if (cexpr1.getIntValue() == 0 && cexpr2.getIntValue() != 0) { + return new FunctionExprent(FunctionExprent.FUNCTION_BOOLNOT, Arrays.asList(new Exprent[]{lstOperands.get(0)})); + } + else if (cexpr1.getIntValue() != 0 && cexpr2.getIntValue() == 0) { + return lstOperands.get(0); + } + } + } + break; + case FunctionExprent.FUNCTION_LCMP: + case FunctionExprent.FUNCTION_FCMPL: + case FunctionExprent.FUNCTION_FCMPG: + case FunctionExprent.FUNCTION_DCMPL: + case FunctionExprent.FUNCTION_DCMPG: + int var = DecompilerContext.getCountercontainer().getCounterAndIncrement(CounterContainer.VAR_COUNTER); + VarType type = lstOperands.get(0).getExprType(); + VarProcessor processor = (VarProcessor)DecompilerContext.getProperty(DecompilerContext.CURRENT_VAR_PROCESSOR); + + FunctionExprent iff = new FunctionExprent(FunctionExprent.FUNCTION_IIF, Arrays.asList(new Exprent[]{ + new FunctionExprent(FunctionExprent.FUNCTION_LT, Arrays.asList(new Exprent[]{new VarExprent(var, type, processor), + ConstExprent.getZeroConstant(type.type)})), + new ConstExprent(VarType.VARTYPE_INT, new Integer(-1)), + new ConstExprent(VarType.VARTYPE_INT, new Integer(1))})); + + FunctionExprent head = new FunctionExprent(FunctionExprent.FUNCTION_EQ, Arrays.asList(new Exprent[]{ + new AssignmentExprent(new VarExprent(var, type, processor), new FunctionExprent(FunctionExprent.FUNCTION_SUB, + Arrays.asList( + new Exprent[]{lstOperands.get(0), + lstOperands.get(1)}))), + ConstExprent.getZeroConstant(type.type)})); + + processor.setVarType(new VarVersionPaar(var, 0), type); + + return new FunctionExprent(FunctionExprent.FUNCTION_IIF, Arrays.asList(new Exprent[]{ + head, new ConstExprent(VarType.VARTYPE_INT, new Integer(0)), iff})); + } + break; + case Exprent.EXPRENT_ASSIGNMENT: // check for conditional assignment + AssignmentExprent asexpr = (AssignmentExprent)exprent; + Exprent right = asexpr.getRight(); + Exprent left = asexpr.getLeft(); + + if (right.type == Exprent.EXPRENT_FUNCTION) { + FunctionExprent func = (FunctionExprent)right; + + VarType midlayer = null; + if (func.getFunctype() >= FunctionExprent.FUNCTION_I2L && + func.getFunctype() <= FunctionExprent.FUNCTION_I2S) { + right = func.getLstOperands().get(0); + midlayer = func.getSimpleCastType(); + if (right.type == Exprent.EXPRENT_FUNCTION) { + func = (FunctionExprent)right; + } + else { + return null; + } + } + + List<Exprent> lstFuncOperands = func.getLstOperands(); + + Exprent cond = null; + + switch (func.getFunctype()) { + case FunctionExprent.FUNCTION_ADD: + case FunctionExprent.FUNCTION_AND: + case FunctionExprent.FUNCTION_OR: + case FunctionExprent.FUNCTION_XOR: + if (left.equals(lstFuncOperands.get(1))) { + cond = lstFuncOperands.get(0); + break; + } + case FunctionExprent.FUNCTION_SUB: + case FunctionExprent.FUNCTION_MUL: + case FunctionExprent.FUNCTION_DIV: + case FunctionExprent.FUNCTION_REM: + case FunctionExprent.FUNCTION_SHL: + case FunctionExprent.FUNCTION_SHR: + case FunctionExprent.FUNCTION_USHR: + if (left.equals(lstFuncOperands.get(0))) { + cond = lstFuncOperands.get(1); + } + } + + if (cond != null && (midlayer == null || midlayer.equals(cond.getExprType()))) { + asexpr.setRight(cond); + asexpr.setCondtype(func.getFunctype()); + } + } + break; + case Exprent.EXPRENT_INVOCATION: + if (!statement_level) { // simplify if exprent is a real expression. The opposite case is pretty absurd, can still happen however (and happened at least once). + Exprent retexpr = ConcatenationHelper.contractStringConcat(exprent); + if (!exprent.equals(retexpr)) { + return retexpr; + } + } + } + + return null; + } + + public static Exprent propagateBoolNot(Exprent exprent) { + + if (exprent.type == Exprent.EXPRENT_FUNCTION) { + FunctionExprent fexpr = (FunctionExprent)exprent; + + if (fexpr.getFunctype() == FunctionExprent.FUNCTION_BOOLNOT) { + + Exprent param = fexpr.getLstOperands().get(0); + + if (param.type == Exprent.EXPRENT_FUNCTION) { + FunctionExprent fparam = (FunctionExprent)param; + + int ftype = fparam.getFunctype(); + switch (ftype) { + case FunctionExprent.FUNCTION_BOOLNOT: + Exprent newexpr = fparam.getLstOperands().get(0); + Exprent retexpr = propagateBoolNot(newexpr); + return retexpr == null ? newexpr : retexpr; + case FunctionExprent.FUNCTION_CADD: + case FunctionExprent.FUNCTION_COR: + List<Exprent> operands = fparam.getLstOperands(); + for (int i = 0; i < operands.size(); i++) { + Exprent newparam = new FunctionExprent(FunctionExprent.FUNCTION_BOOLNOT, + Arrays.asList(new Exprent[]{operands.get(i)})); + + Exprent retparam = propagateBoolNot(newparam); + operands.set(i, retparam == null ? newparam : retparam); + } + case FunctionExprent.FUNCTION_EQ: + case FunctionExprent.FUNCTION_NE: + case FunctionExprent.FUNCTION_LT: + case FunctionExprent.FUNCTION_GE: + case FunctionExprent.FUNCTION_GT: + case FunctionExprent.FUNCTION_LE: + fparam.setFunctype(funcsnot[ftype - FunctionExprent.FUNCTION_EQ]); + return fparam; + } + } + } + } + + return null; + } } |