diff options
Diffstat (limited to 'plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/PPandMMHelper.java')
-rw-r--r-- | plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/PPandMMHelper.java | 154 |
1 files changed, 154 insertions, 0 deletions
diff --git a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/PPandMMHelper.java b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/PPandMMHelper.java new file mode 100644 index 000000000000..aacb61f339ab --- /dev/null +++ b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/PPandMMHelper.java @@ -0,0 +1,154 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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 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.sforms.DirectGraph; +import org.jetbrains.java.decompiler.modules.decompiler.sforms.DirectNode; +import org.jetbrains.java.decompiler.modules.decompiler.sforms.FlattenStatementsHelper; +import org.jetbrains.java.decompiler.modules.decompiler.stats.RootStatement; +import org.jetbrains.java.decompiler.struct.gen.VarType; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; + +public class PPandMMHelper { + + private boolean exprentReplaced; + + public boolean findPPandMM(RootStatement root) { + + FlattenStatementsHelper flatthelper = new FlattenStatementsHelper(); + DirectGraph dgraph = flatthelper.buildDirectGraph(root); + + LinkedList<DirectNode> stack = new LinkedList<DirectNode>(); + stack.add(dgraph.first); + + HashSet<DirectNode> setVisited = new HashSet<DirectNode>(); + + boolean res = false; + + while (!stack.isEmpty()) { + + DirectNode node = stack.removeFirst(); + + if (setVisited.contains(node)) { + continue; + } + setVisited.add(node); + + res |= processExprentList(node.exprents); + + stack.addAll(node.succs); + } + + return res; + } + + private boolean processExprentList(List<Exprent> lst) { + + boolean result = false; + + for (int i = 0; i < lst.size(); i++) { + Exprent exprent = lst.get(i); + exprentReplaced = false; + + Exprent retexpr = processExprentRecursive(exprent); + if (retexpr != null) { + lst.set(i, retexpr); + + result = true; + i--; // process the same exprent again + } + + result |= exprentReplaced; + } + + return result; + } + + private Exprent processExprentRecursive(Exprent exprent) { + + boolean replaced = true; + while (replaced) { + replaced = false; + + for (Exprent expr : exprent.getAllExprents()) { + Exprent retexpr = processExprentRecursive(expr); + if (retexpr != null) { + exprent.replaceExprent(expr, retexpr); + replaced = true; + exprentReplaced = true; + break; + } + } + } + + if (exprent.type == Exprent.EXPRENT_ASSIGNMENT) { + AssignmentExprent as = (AssignmentExprent)exprent; + + if (as.getRight().type == Exprent.EXPRENT_FUNCTION) { + FunctionExprent func = (FunctionExprent)as.getRight(); + + VarType midlayer = null; + if (func.getFunctype() >= FunctionExprent.FUNCTION_I2L && + func.getFunctype() <= FunctionExprent.FUNCTION_I2S) { + midlayer = func.getSimpleCastType(); + if (func.getLstOperands().get(0).type == Exprent.EXPRENT_FUNCTION) { + func = (FunctionExprent)func.getLstOperands().get(0); + } + else { + return null; + } + } + + if (func.getFunctype() == FunctionExprent.FUNCTION_ADD || + func.getFunctype() == FunctionExprent.FUNCTION_SUB) { + Exprent econd = func.getLstOperands().get(0); + Exprent econst = func.getLstOperands().get(1); + + if (econst.type != Exprent.EXPRENT_CONST && econd.type == Exprent.EXPRENT_CONST && + func.getFunctype() == FunctionExprent.FUNCTION_ADD) { + econd = econst; + econst = func.getLstOperands().get(0); + } + + if (econst.type == Exprent.EXPRENT_CONST && ((ConstExprent)econst).hasValueOne()) { + Exprent left = as.getLeft(); + + VarType condtype = econd.getExprType(); + if (left.equals(econd) && (midlayer == null || midlayer.equals(condtype))) { + FunctionExprent ret = new FunctionExprent( + func.getFunctype() == FunctionExprent.FUNCTION_ADD ? FunctionExprent.FUNCTION_PPI : FunctionExprent.FUNCTION_MMI, + Arrays.asList(new Exprent[]{econd})); + ret.setImplicitType(condtype); + + exprentReplaced = true; + return ret; + } + } + } + } + } + + return null; + } +} |