Search in sources :

Example 1 with TryCatchEdge

use of org.mapleir.flowgraph.edges.TryCatchEdge 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 2 with TryCatchEdge

use of org.mapleir.flowgraph.edges.TryCatchEdge in project maple-ir by LLVM-but-worse.

the class NaturalisationPass1 method mergeImmediates.

int mergeImmediates() {
    class MergePair {

        final BasicBlock src;

        final BasicBlock dst;

        MergePair(BasicBlock src, BasicBlock dst) {
            this.src = src;
            this.dst = dst;
        }
    }
    List<MergePair> merges = new ArrayList<>();
    Map<BasicBlock, BasicBlock> remap = new HashMap<>();
    Map<BasicBlock, List<ExceptionRange<BasicBlock>>> ranges = new HashMap<>();
    for (BasicBlock b : builder.graph.vertices()) {
        BasicBlock in = b.getIncomingImmediate();
        if (in == null) {
            continue;
        }
        if (in.isFlagSet(BasicBlock.FLAG_NO_MERGE)) {
            continue;
        }
        Set<FlowEdge<BasicBlock>> inSuccs = in.getSuccessors(e -> !(e instanceof TryCatchEdge));
        if (inSuccs.size() != 1 || builder.graph.getReverseEdges(b).size() != 1) {
            continue;
        }
        List<ExceptionRange<BasicBlock>> range1 = b.getProtectingRanges();
        List<ExceptionRange<BasicBlock>> range2 = in.getProtectingRanges();
        if (!range1.equals(range2)) {
            continue;
        }
        ranges.put(b, range1);
        ranges.put(in, range2);
        merges.add(new MergePair(in, b));
        remap.put(in, in);
        remap.put(b, b);
    }
    for (MergePair p : merges) {
        BasicBlock src = remap.get(p.src);
        BasicBlock dst = p.dst;
        dst.transfer(src);
        for (FlowEdge<BasicBlock> e : builder.graph.getEdges(dst)) {
            // to clone these.
            if (e.getType() != FlowEdges.TRYCATCH) {
                BasicBlock edst = e.dst();
                edst = remap.getOrDefault(edst, edst);
                builder.graph.addEdge(src, e.clone(src, edst));
            }
        }
        builder.graph.removeVertex(dst);
        remap.put(dst, src);
        for (ExceptionRange<BasicBlock> r : ranges.get(src)) {
            r.removeVertex(dst);
        }
        for (ExceptionRange<BasicBlock> r : ranges.get(dst)) {
            r.removeVertex(dst);
        }
    // System.out.printf("Merged %s into %s.%n", dst.getId(), src.getId());
    }
    // we need to update the assigns map if we change the cfg.
    for (Entry<Local, Set<BasicBlock>> e : builder.assigns.entrySet()) {
        Set<BasicBlock> set = e.getValue();
        Set<BasicBlock> copy = new HashSet<>(set);
        for (BasicBlock b : copy) {
            BasicBlock r = remap.getOrDefault(b, b);
            if (r != b) {
                set.remove(b);
                set.add(r);
            }
        }
    }
    return merges.size();
}
Also used : FlowEdge(org.mapleir.flowgraph.edges.FlowEdge) Set(java.util.Set) HashSet(java.util.HashSet) HashMap(java.util.HashMap) BasicBlock(org.mapleir.ir.cfg.BasicBlock) ArrayList(java.util.ArrayList) Local(org.mapleir.ir.locals.Local) TryCatchEdge(org.mapleir.flowgraph.edges.TryCatchEdge) ExceptionRange(org.mapleir.flowgraph.ExceptionRange) ArrayList(java.util.ArrayList) List(java.util.List) HashSet(java.util.HashSet)

Aggregations

FlowEdge (org.mapleir.flowgraph.edges.FlowEdge)2 TryCatchEdge (org.mapleir.flowgraph.edges.TryCatchEdge)2 BasicBlock (org.mapleir.ir.cfg.BasicBlock)2 Local (org.mapleir.ir.locals.Local)2 ArrayList (java.util.ArrayList)1 HashMap (java.util.HashMap)1 HashSet (java.util.HashSet)1 List (java.util.List)1 Set (java.util.Set)1 ExceptionRange (org.mapleir.flowgraph.ExceptionRange)1 ConditionalJumpEdge (org.mapleir.flowgraph.edges.ConditionalJumpEdge)1 SwitchEdge (org.mapleir.flowgraph.edges.SwitchEdge)1 UnconditionalJumpEdge (org.mapleir.flowgraph.edges.UnconditionalJumpEdge)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