Search in sources :

Example 1 with UnconditionalJumpStmt

use of org.mapleir.ir.code.stmt.UnconditionalJumpStmt in project maple-ir by LLVM-but-worse.

the class ControlFlowGraphDumper method naturalise.

private void naturalise() {
    for (int i = 0; i < order.size(); i++) {
        BasicBlock b = order.get(i);
        for (FlowEdge<BasicBlock> e : new HashSet<>(cfg.getEdges(b))) {
            BasicBlock dst = e.dst();
            if (e instanceof ImmediateEdge && order.indexOf(dst) != i + 1) {
                // Fix immediates
                b.add(new UnconditionalJumpStmt(dst));
                cfg.removeEdge(b, e);
                cfg.addEdge(b, new UnconditionalJumpEdge<>(b, dst));
            } else if (e instanceof UnconditionalJumpEdge && order.indexOf(dst) == i + 1) {
                // Remove extraneous gotos
                for (ListIterator<Stmt> it = b.listIterator(b.size()); it.hasPrevious(); ) {
                    if (it.previous() instanceof UnconditionalJumpStmt) {
                        it.remove();
                        break;
                    }
                }
                cfg.removeEdge(b, e);
                cfg.addEdge(b, new ImmediateEdge<>(b, dst));
            }
        }
    }
}
Also used : ImmediateEdge(org.mapleir.flowgraph.edges.ImmediateEdge) BasicBlock(org.mapleir.ir.cfg.BasicBlock) UnconditionalJumpEdge(org.mapleir.flowgraph.edges.UnconditionalJumpEdge) UnconditionalJumpStmt(org.mapleir.ir.code.stmt.UnconditionalJumpStmt)

Example 2 with UnconditionalJumpStmt

use of org.mapleir.ir.code.stmt.UnconditionalJumpStmt in project maple-ir by LLVM-but-worse.

the class SSAGenPass method splitBlock.

private BasicBlock splitBlock(BasicBlock b, int to) {
    /* eg. split the block as follows:
		 * 
		 *  NAME:
		 *    stmt1
		 *    stmt2
		 *    stmt3
		 *    stmt4
		 *    stmt5
		 *    jump L1, L2
		 *   [jump edge to L1]
		 *   [jump edge to L2]
		 *   [exception edges]
		 * 
		 * split at 3, create a new block (incoming 
		 * immediate), transfer instruction from 0
		 * to index into new block, create immediate
		 * edge to old block, clone exception edges,
		 * redirect pred edges.
		 * 
		 * 1/9/16: we also need to modify the last
		 *         statement of the pred blocks to
		 *         point to NAME'.
		 * 
		 *  NAME':
		 *    stmt1
		 *    stmt2
		 *    stmt3
		 *   [immediate to NAME]
		 *  NAME:
		 *    stmt4
		 *    stmt5
		 *    jump L1, L2
		 *   [jump edge to L1]
		 *   [jump edge to L2]
		 *   [exception edges]
		 */
    // split block
    ControlFlowGraph cfg = builder.graph;
    BasicBlock newBlock = new BasicBlock(cfg, graphSize++, new LabelNode());
    b.transferUp(newBlock, to);
    cfg.addVertex(newBlock);
    // redo ranges
    for (ExceptionRange<BasicBlock> er : cfg.getRanges()) {
        if (er.containsVertex(b))
            er.addVertexBefore(b, newBlock);
    }
    // redirect b preds into newBlock and remove them.
    Set<FlowEdge<BasicBlock>> oldEdges = new HashSet<>(cfg.getReverseEdges(b));
    for (FlowEdge<BasicBlock> e : oldEdges) {
        BasicBlock p = e.src();
        FlowEdge<BasicBlock> c;
        if (e instanceof TryCatchEdge) {
            // b is ehandler
            TryCatchEdge<BasicBlock> tce = (TryCatchEdge<BasicBlock>) e;
            if (tce.dst() != tce.erange.getHandler()) {
                System.err.println(builder.method.owner + "#" + builder.method.name);
                System.err.println(cfg);
                System.err.println("Very odd split case. please investigate");
                System.err.println("Offending postsplit block: " + b);
                System.err.println("Offending newblock: " + newBlock);
                System.err.println("Offending edge: " + tce);
                System.err.println("Offending erange: " + tce.erange);
            }
            if (tce.erange.getHandler() != newBlock) {
                tce.erange.setHandler(newBlock);
                cfg.addEdge(tce.src(), tce.clone(tce.src(), null));
                cfg.removeEdge(tce.src(), tce);
            }
        } else {
            c = e.clone(p, newBlock);
            cfg.addEdge(p, c);
            cfg.removeEdge(p, e);
        }
        // Fix flow instruction targets
        if (!p.isEmpty()) {
            Stmt last = p.get(p.size() - 1);
            int op = last.getOpcode();
            if (e instanceof ConditionalJumpEdge) {
                if (op != Opcode.COND_JUMP)
                    throw new IllegalArgumentException("wrong flow instruction");
                ConditionalJumpStmt j = (ConditionalJumpStmt) last;
                // assertTarget(last, j.getTrueSuccessor(), b);
                if (j.getTrueSuccessor() == b)
                    j.setTrueSuccessor(newBlock);
            } else if (e instanceof UnconditionalJumpEdge) {
                if (op != Opcode.UNCOND_JUMP)
                    throw new IllegalArgumentException("wrong flow instruction");
                UnconditionalJumpStmt j = (UnconditionalJumpStmt) last;
                assertTarget(j, j.getTarget(), b);
                j.setTarget(newBlock);
            } else if (e instanceof SwitchEdge) {
                if (op != Opcode.SWITCH_JUMP)
                    throw new IllegalArgumentException("wrong flow instruction.");
                SwitchStmt s = (SwitchStmt) last;
                for (Entry<Integer, BasicBlock> en : s.getTargets().entrySet()) {
                    BasicBlock t = en.getValue();
                    if (t == b) {
                        en.setValue(newBlock);
                    }
                }
            }
        }
    }
    if (!checkCloneHandler(newBlock)) {
        System.err.println(cfg);
        System.err.println(newBlock.getDisplayName());
        System.err.println(b.getDisplayName());
        throw new IllegalStateException("the new block should always need a handler..?");
    }
    // clone exception edges
    for (FlowEdge<BasicBlock> e : cfg.getEdges(b)) {
        if (e.getType() == FlowEdges.TRYCATCH) {
            // second param is discarded (?)
            TryCatchEdge<BasicBlock> c = ((TryCatchEdge<BasicBlock>) e).clone(newBlock, null);
            cfg.addEdge(newBlock, c);
        }
    }
    // create immediate to newBlock
    cfg.addEdge(newBlock, new ImmediateEdge<>(newBlock, b));
    // update assigns
    Set<Local> assignedLocals = new HashSet<>();
    for (Stmt stmt : b) if (stmt.getOpcode() == Opcode.LOCAL_STORE)
        assignedLocals.add(((CopyVarStmt) stmt).getVariable().getLocal());
    for (Stmt stmt : newBlock) {
        if (stmt.getOpcode() == Opcode.LOCAL_STORE) {
            Local copyLocal = ((CopyVarStmt) stmt).getVariable().getLocal();
            Set<BasicBlock> set = builder.assigns.get(copyLocal);
            set.add(newBlock);
            if (!assignedLocals.contains(copyLocal))
                set.remove(b);
        }
    }
    return newBlock;
}
Also used : LabelNode(org.objectweb.asm.tree.LabelNode) TryCatchEdge(org.mapleir.flowgraph.edges.TryCatchEdge) SwitchStmt(org.mapleir.ir.code.stmt.SwitchStmt) CopyVarStmt(org.mapleir.ir.code.stmt.copy.CopyVarStmt) PopStmt(org.mapleir.ir.code.stmt.PopStmt) ThrowStmt(org.mapleir.ir.code.stmt.ThrowStmt) UnconditionalJumpStmt(org.mapleir.ir.code.stmt.UnconditionalJumpStmt) Stmt(org.mapleir.ir.code.Stmt) CopyPhiStmt(org.mapleir.ir.code.stmt.copy.CopyPhiStmt) ConditionalJumpStmt(org.mapleir.ir.code.stmt.ConditionalJumpStmt) AbstractCopyStmt(org.mapleir.ir.code.stmt.copy.AbstractCopyStmt) UnconditionalJumpEdge(org.mapleir.flowgraph.edges.UnconditionalJumpEdge) FlowEdge(org.mapleir.flowgraph.edges.FlowEdge) SwitchStmt(org.mapleir.ir.code.stmt.SwitchStmt) SwitchEdge(org.mapleir.flowgraph.edges.SwitchEdge) CopyVarStmt(org.mapleir.ir.code.stmt.copy.CopyVarStmt) BasicBlock(org.mapleir.ir.cfg.BasicBlock) BasicLocal(org.mapleir.ir.locals.impl.BasicLocal) Local(org.mapleir.ir.locals.Local) VersionedLocal(org.mapleir.ir.locals.impl.VersionedLocal) Constraint(org.mapleir.ir.cfg.builder.ssaopt.Constraint) UnconditionalJumpStmt(org.mapleir.ir.code.stmt.UnconditionalJumpStmt) ConditionalJumpStmt(org.mapleir.ir.code.stmt.ConditionalJumpStmt) ConditionalJumpEdge(org.mapleir.flowgraph.edges.ConditionalJumpEdge) ControlFlowGraph(org.mapleir.ir.cfg.ControlFlowGraph)

Example 3 with UnconditionalJumpStmt

use of org.mapleir.ir.code.stmt.UnconditionalJumpStmt in project maple-ir by LLVM-but-worse.

the class ConstantExpressionEvaluatorPass method eliminateBranch.

private void eliminateBranch(ControlFlowGraph cfg, BasicBlock b, ConditionalJumpStmt cond, int insnIndex, boolean val) {
    if (val) {
        // remove immediate edge (it will never be taken)
        for (FlowEdge<BasicBlock> fe : new HashSet<>(cfg.getEdges(b))) {
            if (fe.getType() == FlowEdges.IMMEDIATE) {
                cfg.exciseEdge(fe);
            }
        }
        // create new jump and update cfg
        UnconditionalJumpStmt newJump = new UnconditionalJumpStmt(cond.getTrueSuccessor());
        b.set(insnIndex, newJump);
        UnconditionalJumpEdge<BasicBlock> uje = new UnconditionalJumpEdge<>(b, cond.getTrueSuccessor());
        cfg.addEdge(b, uje);
    } else {
        // always false, keep immediate (fallthrough) and remove the conditional branch.
        // remove statement amd uses in d/u map
        cfg.exciseStmt(cond);
        // remove conditional edge
        for (FlowEdge<BasicBlock> fe : new HashSet<>(cfg.getEdges(b))) {
            if (fe.getType() == FlowEdges.COND) {
                if (fe.dst() != cond.getTrueSuccessor()) {
                    throw new IllegalStateException(fe + ", " + cond);
                }
                cfg.exciseEdge(fe);
            }
        }
    }
}
Also used : BasicBlock(org.mapleir.ir.cfg.BasicBlock) UnconditionalJumpEdge(org.mapleir.flowgraph.edges.UnconditionalJumpEdge) HashSet(java.util.HashSet) UnconditionalJumpStmt(org.mapleir.ir.code.stmt.UnconditionalJumpStmt)

Aggregations

UnconditionalJumpEdge (org.mapleir.flowgraph.edges.UnconditionalJumpEdge)3 BasicBlock (org.mapleir.ir.cfg.BasicBlock)3 UnconditionalJumpStmt (org.mapleir.ir.code.stmt.UnconditionalJumpStmt)3 HashSet (java.util.HashSet)1 ConditionalJumpEdge (org.mapleir.flowgraph.edges.ConditionalJumpEdge)1 FlowEdge (org.mapleir.flowgraph.edges.FlowEdge)1 ImmediateEdge (org.mapleir.flowgraph.edges.ImmediateEdge)1 SwitchEdge (org.mapleir.flowgraph.edges.SwitchEdge)1 TryCatchEdge (org.mapleir.flowgraph.edges.TryCatchEdge)1 ControlFlowGraph (org.mapleir.ir.cfg.ControlFlowGraph)1 Constraint (org.mapleir.ir.cfg.builder.ssaopt.Constraint)1 Stmt (org.mapleir.ir.code.Stmt)1 ConditionalJumpStmt (org.mapleir.ir.code.stmt.ConditionalJumpStmt)1 PopStmt (org.mapleir.ir.code.stmt.PopStmt)1 SwitchStmt (org.mapleir.ir.code.stmt.SwitchStmt)1 ThrowStmt (org.mapleir.ir.code.stmt.ThrowStmt)1 AbstractCopyStmt (org.mapleir.ir.code.stmt.copy.AbstractCopyStmt)1 CopyPhiStmt (org.mapleir.ir.code.stmt.copy.CopyPhiStmt)1 CopyVarStmt (org.mapleir.ir.code.stmt.copy.CopyVarStmt)1 Local (org.mapleir.ir.locals.Local)1