Search in sources :

Example 1 with WhileIntermediate

use of org.candle.decompiler.intermediate.code.loop.WhileIntermediate in project candle-decompiler by bradsdavis.

the class ConditionToWhileLoop method visitBooleanBranchIntermediate.

@Override
public void visitBooleanBranchIntermediate(BooleanBranchIntermediate line) {
    List<AbstractIntermediate> predecessors = Graphs.predecessorListOf(igc.getGraph(), line);
    CycleDetector<AbstractIntermediate, IntermediateEdge> cycleDetector = new CycleDetector<AbstractIntermediate, IntermediateEdge>(igc.getGraph());
    if (!cycleDetector.detectCyclesContainingVertex(line)) {
        return;
    }
    //first, determine if the condition has two incoming lines.
    if (predecessors.size() >= 2) {
        //check to see that 1 predecessor is a GOTO.
        TreeSet<GoToIntermediate> incomingGotoNonNested = new TreeSet<GoToIntermediate>(new IntermediateComparator());
        TreeSet<GoToIntermediate> incomingGotoNested = new TreeSet<GoToIntermediate>(new IntermediateComparator());
        GoToIntermediate nestedLine = null;
        AbstractIntermediate otherLine = null;
        //classify.
        for (AbstractIntermediate predecessor : predecessors) {
            //check to see if 1 is GOTO.
            if (predecessor instanceof GoToIntermediate) {
                if (isNested(line, predecessor)) {
                    incomingGotoNested.add((GoToIntermediate) predecessor);
                } else {
                    incomingGotoNonNested.add((GoToIntermediate) predecessor);
                }
                continue;
            } else {
                otherLine = predecessor;
            }
        }
        //if there are more than one GOTO statements that are not-nested, return.
        if (incomingGotoNonNested.size() > 1) {
            return;
        }
        nestedLine = getCandidateGoto(incomingGotoNonNested, incomingGotoNested);
        //stop if both conditions aren't met.
        if (nestedLine == null || otherLine == null) {
            return;
        }
        //check to validate that the GOTO instruction is less than the other incoming...
        if (comparator.before(otherLine, line)) {
            //take the lower condition...
            BranchHandle refHandle = null;
            if (comparator.before(nestedLine, line)) {
                refHandle = (BranchHandle) nestedLine.getInstruction();
            } else {
                refHandle = (BranchHandle) line.getInstruction();
            }
            WhileIntermediate whileIntermediate = new WhileIntermediate(refHandle, line);
            //add this to the graph.
            this.igc.getGraph().addVertex(whileIntermediate);
            //get the incoming from the goto...
            igc.redirectPredecessors(nestedLine, whileIntermediate);
            igc.redirectSuccessors(line, whileIntermediate);
            //now, create line from other to while.
            this.igc.getGraph().addEdge(otherLine, whileIntermediate);
            //now, remove the GOTO and Conditional Vertex from graph.
            igc.getGraph().removeVertex(nestedLine);
            igc.getGraph().removeVertex(line);
            //now, the other GOTO lines coming in should all be CONTINUE statements...
            for (GoToIntermediate gotoIntermediate : incomingGotoNested) {
                Continue continueExpression = new Continue(gotoIntermediate.getInstruction());
                StatementIntermediate continueIntermediate = new StatementIntermediate(gotoIntermediate.getInstruction(), continueExpression);
                //add the node...
                igc.getGraph().addVertex(continueIntermediate);
                igc.redirectPredecessors(gotoIntermediate, continueIntermediate);
                //remove vertex.
                igc.getGraph().removeVertex(gotoIntermediate);
                //now, add line to the loop.
                igc.getGraph().addEdge(continueIntermediate, whileIntermediate);
            }
            updateEdges(whileIntermediate);
        }
    }
}
Also used : AbstractIntermediate(org.candle.decompiler.intermediate.code.AbstractIntermediate) WhileIntermediate(org.candle.decompiler.intermediate.code.loop.WhileIntermediate) GoToIntermediate(org.candle.decompiler.intermediate.code.GoToIntermediate) BranchHandle(org.apache.bcel.generic.BranchHandle) IntermediateComparator(org.candle.decompiler.intermediate.code.IntermediateComparator) Continue(org.candle.decompiler.intermediate.expression.Continue) IntermediateEdge(org.candle.decompiler.intermediate.graph.edge.IntermediateEdge) CycleDetector(org.jgrapht.alg.CycleDetector) TreeSet(java.util.TreeSet) StatementIntermediate(org.candle.decompiler.intermediate.code.StatementIntermediate)

Aggregations

TreeSet (java.util.TreeSet)1 BranchHandle (org.apache.bcel.generic.BranchHandle)1 AbstractIntermediate (org.candle.decompiler.intermediate.code.AbstractIntermediate)1 GoToIntermediate (org.candle.decompiler.intermediate.code.GoToIntermediate)1 IntermediateComparator (org.candle.decompiler.intermediate.code.IntermediateComparator)1 StatementIntermediate (org.candle.decompiler.intermediate.code.StatementIntermediate)1 WhileIntermediate (org.candle.decompiler.intermediate.code.loop.WhileIntermediate)1 Continue (org.candle.decompiler.intermediate.expression.Continue)1 IntermediateEdge (org.candle.decompiler.intermediate.graph.edge.IntermediateEdge)1 CycleDetector (org.jgrapht.alg.CycleDetector)1