summaryrefslogtreecommitdiff
path: root/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/PPandMMHelper.java
diff options
context:
space:
mode:
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.java154
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;
+ }
+}