Search in sources :

Example 1 with FlowEdge

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

the class SSABlockLivenessAnalyser method compute.

public void compute() {
    // negative handling always goes after positive and any adds
    while (!queue.isEmpty()) {
        BasicBlock b = queue.remove();
        // System.out.println("\n\nProcessing " + b.getId());
        GenericBitSet<Local> oldIn = new GenericBitSet<>(in.get(b));
        GenericBitSet<Local> curIn = new GenericBitSet<>(use.get(b));
        GenericBitSet<Local> curOut = locals.createBitSet();
        // out[n] = U(s in succ[n])(in[s])
        for (FlowEdge<BasicBlock> succEdge : cfg.getEdges(b)) curOut.addAll(in.get(succEdge.dst()));
        // negative phi handling for defs
        for (FlowEdge<BasicBlock> succEdge : cfg.getEdges(b)) curOut.removeAll(phiDef.get(succEdge.dst()));
        // positive phi handling for uses, see ยง5.4.2 "Meaning of copy statements in Sreedhar's method"
        for (FlowEdge<BasicBlock> succEdge : cfg.getEdges(b)) curOut.addAll(phiUse.get(succEdge.dst()).getNonNull(b));
        // negative phi handling for uses
        for (FlowEdge<BasicBlock> predEdge : cfg.getReverseEdges(b)) curIn.removeAll(phiUse.get(b).getNonNull(predEdge.src()).relativeComplement(use.get(b)));
        // positive phi handling for defs
        curIn.addAll(phiDef.get(b));
        oldIn.addAll(phiDef.get(b));
        // in[n] = use[n] U(out[n] - def[n])
        curIn.addAll(curOut.relativeComplement(def.get(b)));
        in.put(b, curIn);
        out.put(b, curOut);
        // queue preds if dataflow state changed
        if (!oldIn.equals(curIn)) {
            cfg.getReverseEdges(b).stream().map(e -> e.src()).forEach(this::enqueue);
        // for (BasicBlock b2 : cfg.vertices())
        // System.out.println(b2.getId() + " |||| IN: " + in.get(b2) + " ||||| OUT: " + out.get(b2));
        }
    }
}
Also used : Local(org.mapleir.ir.locals.Local) ListIterator(java.util.ListIterator) VarExpr(org.mapleir.ir.code.expr.VarExpr) GenericBitSet(org.mapleir.stdlib.collections.bitset.GenericBitSet) Expr(org.mapleir.ir.code.Expr) FlowEdge(org.mapleir.flowgraph.edges.FlowEdge) PhiExpr(org.mapleir.ir.code.expr.PhiExpr) ControlFlowGraph(org.mapleir.ir.cfg.ControlFlowGraph) LocalsPool(org.mapleir.ir.locals.LocalsPool) Stmt(org.mapleir.ir.code.Stmt) CopyVarStmt(org.mapleir.ir.code.stmt.copy.CopyVarStmt) NullPermeableHashMap(org.mapleir.stdlib.collections.map.NullPermeableHashMap) CopyPhiStmt(org.mapleir.ir.code.stmt.copy.CopyPhiStmt) Opcode(org.mapleir.ir.code.Opcode) FlowEdges(org.mapleir.flowgraph.edges.FlowEdges) Map(java.util.Map) Queue(java.util.Queue) LinkedList(java.util.LinkedList) BasicBlock(org.mapleir.ir.cfg.BasicBlock) BasicBlock(org.mapleir.ir.cfg.BasicBlock) Local(org.mapleir.ir.locals.Local) GenericBitSet(org.mapleir.stdlib.collections.bitset.GenericBitSet)

Example 2 with FlowEdge

use of org.mapleir.flowgraph.edges.FlowEdge 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 FlowEdge

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

the class LiftConstructorCallsPass method tryLift.

private boolean tryLift(MethodNode m, ControlFlowGraph cfg) {
    Local lvar0_0 = cfg.getLocals().get(0, 0, false);
    /* only contains synthetic copies */
    BasicBlock entry = cfg.getEntries().iterator().next();
    for (BasicBlock b : cfg.vertices()) {
        for (Stmt stmt : b) {
            for (Expr e : stmt.enumerateOnlyChildren()) {
                if (e.getOpcode() == INVOKE) {
                    InvocationExpr invoke = (InvocationExpr) e;
                    if (invoke.getOwner().equals(m.owner.superName) && invoke.getName().equals("<init>")) {
                        Expr p1 = invoke.getPhysicalReceiver();
                        if (p1.getOpcode() == LOCAL_LOAD && ((VarExpr) p1).getLocal() == lvar0_0) {
                            Set<FlowEdge<BasicBlock>> predsEdges = cfg.getReverseEdges(b);
                            FlowEdge<BasicBlock> incoming;
                            if (predsEdges.size() == 1 && ((incoming = predsEdges.iterator().next()).getType() == FlowEdges.IMMEDIATE) && incoming.src() == entry) {
                                // BasicBlock liftBlock = new BasicBlock(cfg, cfg.vertices().size() + 1, new LabelNode());
                                /* split the block before the invocation and 
									 * insert a new block. */
                                split(cfg, b, stmt);
                                return true;
                            } else {
                                System.err.printf(" warn(nolift) for %s in %n%s%n", invoke, ControlFlowGraph.printBlock(b));
                                System.err.printf("  preds: %s%n", predsEdges);
                            }
                        } else {
                            throw new IllegalStateException(String.format("broken super call: %s", invoke));
                        }
                    }
                }
            }
        }
    }
    return false;
}
Also used : FlowEdge(org.mapleir.flowgraph.edges.FlowEdge) InvocationExpr(org.mapleir.ir.code.expr.invoke.InvocationExpr) VarExpr(org.mapleir.ir.code.expr.VarExpr) Expr(org.mapleir.ir.code.Expr) BasicBlock(org.mapleir.ir.cfg.BasicBlock) Local(org.mapleir.ir.locals.Local) VarExpr(org.mapleir.ir.code.expr.VarExpr) InvocationExpr(org.mapleir.ir.code.expr.invoke.InvocationExpr) Stmt(org.mapleir.ir.code.Stmt)

Example 4 with FlowEdge

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

the class SSAGenPass method search.

private void search(BasicBlock b, Set<BasicBlock> vis) {
    if (vis.contains(b)) {
        return;
    }
    vis.add(b);
    searchImpl(b);
    List<FlowEdge<BasicBlock>> succs = new ArrayList<>();
    for (FlowEdge<BasicBlock> succE : builder.graph.getEdges(b)) {
        succs.add(succE);
    }
    succs.sort(Comparator.comparing(o -> o.dst()));
    for (FlowEdge<BasicBlock> succE : succs) {
        BasicBlock succ = succE.dst();
        fixPhiArgs(b, succ);
    }
    for (FlowEdge<BasicBlock> succE : succs) {
        BasicBlock succ = succE.dst();
        search(succ, vis);
    }
    unstackDefs(b);
    if (OPTIMISE) {
        optimisePhis(b);
    }
}
Also used : FlowEdge(org.mapleir.flowgraph.edges.FlowEdge) ConditionalJumpEdge(org.mapleir.flowgraph.edges.ConditionalJumpEdge) SwitchStmt(org.mapleir.ir.code.stmt.SwitchStmt) java.util(java.util) Constraint(org.mapleir.ir.cfg.builder.ssaopt.Constraint) ConstraintUtil(org.mapleir.ir.cfg.builder.ssaopt.ConstraintUtil) SSABlockLivenessAnalyser(org.mapleir.ir.algorithms.SSABlockLivenessAnalyser) FlowEdge(org.mapleir.flowgraph.edges.FlowEdge) ControlFlowGraph(org.mapleir.ir.cfg.ControlFlowGraph) ConstantExpr(org.mapleir.ir.code.expr.ConstantExpr) BasicLocal(org.mapleir.ir.locals.impl.BasicLocal) Type(org.objectweb.asm.Type) UnconditionalJumpEdge(org.mapleir.flowgraph.edges.UnconditionalJumpEdge) CopyVarStmt(org.mapleir.ir.code.stmt.copy.CopyVarStmt) SwitchEdge(org.mapleir.flowgraph.edges.SwitchEdge) Liveness(org.mapleir.ir.algorithms.Liveness) Opcode(org.mapleir.ir.code.Opcode) TarjanDominanceComputor(org.mapleir.flowgraph.algorithms.TarjanDominanceComputor) FlowEdges(org.mapleir.flowgraph.edges.FlowEdges) BasicBlock(org.mapleir.ir.cfg.BasicBlock) LatestValue(org.mapleir.ir.cfg.builder.ssaopt.LatestValue) InitialisedObjectExpr(org.mapleir.ir.code.expr.invoke.InitialisedObjectExpr) PopStmt(org.mapleir.ir.code.stmt.PopStmt) InvocationExpr(org.mapleir.ir.code.expr.invoke.InvocationExpr) ThrowStmt(org.mapleir.ir.code.stmt.ThrowStmt) Local(org.mapleir.ir.locals.Local) VarExpr(org.mapleir.ir.code.expr.VarExpr) ImmediateEdge(org.mapleir.flowgraph.edges.ImmediateEdge) Expr(org.mapleir.ir.code.Expr) VersionedLocal(org.mapleir.ir.locals.impl.VersionedLocal) CodeUnit(org.mapleir.ir.code.CodeUnit) PhiExpr(org.mapleir.ir.code.expr.PhiExpr) SimpleDfs(org.mapleir.stdlib.collections.graph.algorithms.SimpleDfs) LabelNode(org.objectweb.asm.tree.LabelNode) UnconditionalJumpStmt(org.mapleir.ir.code.stmt.UnconditionalJumpStmt) LocalsPool(org.mapleir.ir.locals.LocalsPool) Stmt(org.mapleir.ir.code.Stmt) NullPermeableHashMap(org.mapleir.stdlib.collections.map.NullPermeableHashMap) CopyPhiStmt(org.mapleir.ir.code.stmt.copy.CopyPhiStmt) ExceptionRange(org.mapleir.flowgraph.ExceptionRange) ConditionalJumpStmt(org.mapleir.ir.code.stmt.ConditionalJumpStmt) Entry(java.util.Map.Entry) AbstractCopyStmt(org.mapleir.ir.code.stmt.copy.AbstractCopyStmt) SetCreator(org.mapleir.stdlib.collections.map.SetCreator) TryCatchEdge(org.mapleir.flowgraph.edges.TryCatchEdge) BasicBlock(org.mapleir.ir.cfg.BasicBlock)

Example 5 with FlowEdge

use of org.mapleir.flowgraph.edges.FlowEdge 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)5 BasicBlock (org.mapleir.ir.cfg.BasicBlock)5 Local (org.mapleir.ir.locals.Local)5 Stmt (org.mapleir.ir.code.Stmt)4 TryCatchEdge (org.mapleir.flowgraph.edges.TryCatchEdge)3 ControlFlowGraph (org.mapleir.ir.cfg.ControlFlowGraph)3 Expr (org.mapleir.ir.code.Expr)3 VarExpr (org.mapleir.ir.code.expr.VarExpr)3 CopyPhiStmt (org.mapleir.ir.code.stmt.copy.CopyPhiStmt)3 ExceptionRange (org.mapleir.flowgraph.ExceptionRange)2 ConditionalJumpEdge (org.mapleir.flowgraph.edges.ConditionalJumpEdge)2 FlowEdges (org.mapleir.flowgraph.edges.FlowEdges)2 SwitchEdge (org.mapleir.flowgraph.edges.SwitchEdge)2 UnconditionalJumpEdge (org.mapleir.flowgraph.edges.UnconditionalJumpEdge)2 Constraint (org.mapleir.ir.cfg.builder.ssaopt.Constraint)2 Opcode (org.mapleir.ir.code.Opcode)2 PhiExpr (org.mapleir.ir.code.expr.PhiExpr)2 InvocationExpr (org.mapleir.ir.code.expr.invoke.InvocationExpr)2 ConditionalJumpStmt (org.mapleir.ir.code.stmt.ConditionalJumpStmt)2 PopStmt (org.mapleir.ir.code.stmt.PopStmt)2