blob: aacb61f339ab4638096e8d2236869b154e5b2d5d [file] [log] [blame]
/*
* 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;
}
}