Search in sources :

Example 11 with AbstractCopyStmt

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

the class DeadCodeEliminationPass method process.

public void process(ControlFlowGraph cfg) {
    LocalsPool lp = cfg.getLocals();
    boolean c;
    do {
        c = false;
        SimpleDfs<BasicBlock> dfs = new SimpleDfs<>(cfg, cfg.getEntries().iterator().next(), SimpleDfs.PRE);
        List<BasicBlock> pre = dfs.getPreOrder();
        for (BasicBlock b : new HashSet<>(cfg.vertices())) {
            if (!pre.contains(b)) {
                // System.out.println("proc1: " + b);
                for (FlowEdge<BasicBlock> fe : new HashSet<>(cfg.getEdges(b))) {
                    cfg.exciseEdge(fe);
                }
                // System.out.println("removed: ");
                for (Stmt stmt : b) {
                    // System.out.println(" " + (b.indexOf(stmt)) + ". " + stmt);
                    if (stmt instanceof AbstractCopyStmt) {
                        AbstractCopyStmt copy = (AbstractCopyStmt) stmt;
                        lp.defs.remove(copy.getVariable().getLocal());
                    // System.out.println("  kill1 " + copy.getVariable().getLocal());
                    }
                    for (Expr e : stmt.enumerateOnlyChildren()) {
                        if (e.getOpcode() == Opcode.LOCAL_LOAD) {
                            VarExpr v = (VarExpr) e;
                            lp.uses.get(v.getLocal()).remove(v);
                        // System.out.println("  kill2 " + v.getLocal());
                        }
                    }
                }
                cfg.removeVertex(b);
                deadBlocks++;
                c = true;
            } else {
                // System.out.println("proc2: " + b);
                UnconditionalJumpEdge<BasicBlock> uncond = null;
                for (FlowEdge<BasicBlock> fe : cfg.getEdges(b)) {
                    if (fe.getType() == FlowEdges.UNCOND) {
                        uncond = (UnconditionalJumpEdge<BasicBlock>) fe;
                    }
                }
                if (uncond != null) {
                    BasicBlock dst = uncond.dst();
                    List<BasicBlock> verts = new ArrayList<>(cfg.vertices());
                    if (verts.indexOf(b) + 1 == verts.indexOf(dst)) {
                        ImmediateEdge<BasicBlock> im = new ImmediateEdge<>(b, dst);
                        cfg.exciseEdge(uncond);
                        cfg.addEdge(b, im);
                        Stmt stmt = b.remove(b.size() - 1);
                        if (stmt.getOpcode() != Opcode.UNCOND_JUMP) {
                            throw new IllegalStateException(b + " : " + stmt);
                        }
                        immediateJumps++;
                        c = true;
                    }
                }
                // if(cfg.getMethod().toString().equals("cf.k(IIIIII)V")) {}
                Iterator<Stmt> it = b.iterator();
                while (it.hasNext()) {
                    Stmt stmt = it.next();
                    if (stmt.getOpcode() == Opcode.LOCAL_STORE) {
                        AbstractCopyStmt copy = (AbstractCopyStmt) stmt;
                        if (copy.isSynthetic()) {
                            continue;
                        }
                        Local l = copy.getVariable().getLocal();
                        LocalsPool pool = cfg.getLocals();
                        // System.out.println("copy: "+ copy);
                        if (!ConstraintUtil.isUncopyable(copy.getExpression()) && pool.uses.get(l).size() == 0) {
                            for (Expr e : copy.getExpression().enumerateWithSelf()) {
                                if (e.getOpcode() == Opcode.LOCAL_LOAD) {
                                    VarExpr v = (VarExpr) e;
                                    Local l2 = v.getLocal();
                                    pool.uses.remove(l2);
                                }
                            }
                            pool.uses.remove(l);
                            pool.defs.remove(l);
                            it.remove();
                            deadLocals++;
                            c = true;
                        }
                    } else if (stmt.getOpcode() == Opcode.NOP) {
                        it.remove();
                        c = true;
                    }
                }
            }
        }
    // for now
    } while (c);
}
Also used : ImmediateEdge(org.mapleir.flowgraph.edges.ImmediateEdge) BasicBlock(org.mapleir.ir.cfg.BasicBlock) ArrayList(java.util.ArrayList) Local(org.mapleir.ir.locals.Local) SimpleDfs(org.mapleir.stdlib.collections.graph.algorithms.SimpleDfs) Stmt(org.mapleir.ir.code.Stmt) AbstractCopyStmt(org.mapleir.ir.code.stmt.copy.AbstractCopyStmt) LocalsPool(org.mapleir.ir.locals.LocalsPool) VarExpr(org.mapleir.ir.code.expr.VarExpr) Expr(org.mapleir.ir.code.Expr) AbstractCopyStmt(org.mapleir.ir.code.stmt.copy.AbstractCopyStmt) VarExpr(org.mapleir.ir.code.expr.VarExpr) HashSet(java.util.HashSet)

Example 12 with AbstractCopyStmt

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

the class SSAGenPass method updatePhiArgTypes.

private void updatePhiArgTypes(Set<BasicBlock> vis) {
    // update types for phi args
    for (BasicBlock b : order) {
        for (Stmt s : b) {
            if (s.getOpcode() != Opcode.PHI_STORE) {
                break;
            }
            CopyPhiStmt cps = (CopyPhiStmt) s;
            for (Entry<BasicBlock, Expr> e : cps.getExpression().getArguments().entrySet()) {
                BasicBlock src = e.getKey();
                if (vis.contains(src))
                    continue;
                VarExpr v = (VarExpr) e.getValue();
                Local l = v.getLocal();
                // what if the def is never reached?
                AbstractCopyStmt def = pool.defs.get(l);
                v.setType(def.getType());
            }
        }
    }
}
Also used : ConstantExpr(org.mapleir.ir.code.expr.ConstantExpr) InitialisedObjectExpr(org.mapleir.ir.code.expr.invoke.InitialisedObjectExpr) InvocationExpr(org.mapleir.ir.code.expr.invoke.InvocationExpr) VarExpr(org.mapleir.ir.code.expr.VarExpr) Expr(org.mapleir.ir.code.Expr) PhiExpr(org.mapleir.ir.code.expr.PhiExpr) BasicBlock(org.mapleir.ir.cfg.BasicBlock) VarExpr(org.mapleir.ir.code.expr.VarExpr) BasicLocal(org.mapleir.ir.locals.impl.BasicLocal) Local(org.mapleir.ir.locals.Local) VersionedLocal(org.mapleir.ir.locals.impl.VersionedLocal) AbstractCopyStmt(org.mapleir.ir.code.stmt.copy.AbstractCopyStmt) 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) CopyPhiStmt(org.mapleir.ir.code.stmt.copy.CopyPhiStmt)

Example 13 with AbstractCopyStmt

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

the class SSAGenPass method resolveShadowedLocals.

private void resolveShadowedLocals() {
    Set<VersionedLocal> visited = new HashSet<>();
    for (Entry<VersionedLocal, Set<VersionedLocal>> e : shadowed.entrySet()) {
        if (!visited.contains(e.getKey())) {
            Set<VersionedLocal> set = e.getValue();
            visited.addAll(set);
            Set<VersionedLocal> lvars = new HashSet<>();
            for (VersionedLocal l : set) {
                if (!l.isStack()) {
                    lvars.add(l);
                }
            }
            /* find a suitable spill variable:
				 *  favour lvars
				 *  favour lowest version */
            VersionedLocal spill;
            if (lvars.isEmpty()) {
                /* all vars are svars. */
                spill = findLowest(set);
            } else if (lvars.size() == 1) {
                spill = lvars.iterator().next();
            } else {
                /* multiple lvars. // TODO: tweak? */
                // System.err.println(e.getKey() + "    " + lvars);
                spill = findLowest(lvars);
            }
            // System.out.println(set + "  spill; " + spill);
            /* now that we've chosen a spill var, we
				 * find the original copy, i.e. the one
				 * which has a runtime computed value
				 * as it's rhs. we then replace the
				 * target of that copy to the spill
				 * var and remove the definitions of the
				 * shadowed vars. we then rename all
				 * uses of the shadowed vars with the
				 * spill. */
            Set<AbstractCopyStmt> orig = new HashSet<>();
            Set<VarExpr> spillUses = pool.uses.get(spill);
            // System.out.println(set);
            for (VersionedLocal vl : set) {
                AbstractCopyStmt copy = pool.defs.get(vl);
                // System.out.println(vl);
                Expr ex = copy.getExpression();
                if (vl != spill) {
                    if (ex.getOpcode() != Opcode.LOCAL_LOAD) {
                        orig.add(copy);
                    } else {
                        // System.out.println("del1: " + copy);
                        removeSimpleCopy(copy);
                    }
                    /* transfer the uses of each shadowed
						 * var to the spill var, since we
						 * rename all of the shadowed vars. */
                    Set<VarExpr> useSet = pool.uses.get(vl);
                    // System.out.println("uses of " + vl + " ; " + useSet);
                    for (VarExpr v : useSet) {
                        v.setLocal(spill);
                    }
                    spillUses.addAll(useSet);
                    useSet.clear();
                    pool.uses.remove(vl);
                } else {
                    // System.out.println("del2: " + copy);
                    removeSimpleCopy(copy);
                }
                pool.defs.remove(vl);
            }
            if (orig.size() != 1) {
                throw new UnsupportedOperationException(String.format("set:%s, spill:%s, orig:%s", set, spill, orig));
            }
            AbstractCopyStmt copy = orig.iterator().next();
            copy.getVariable().setLocal(spill);
            pool.defs.put(spill, copy);
        }
    }
}
Also used : VersionedLocal(org.mapleir.ir.locals.impl.VersionedLocal) ConstantExpr(org.mapleir.ir.code.expr.ConstantExpr) InitialisedObjectExpr(org.mapleir.ir.code.expr.invoke.InitialisedObjectExpr) InvocationExpr(org.mapleir.ir.code.expr.invoke.InvocationExpr) VarExpr(org.mapleir.ir.code.expr.VarExpr) Expr(org.mapleir.ir.code.Expr) PhiExpr(org.mapleir.ir.code.expr.PhiExpr) AbstractCopyStmt(org.mapleir.ir.code.stmt.copy.AbstractCopyStmt) VarExpr(org.mapleir.ir.code.expr.VarExpr)

Example 14 with AbstractCopyStmt

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

the class ExpressionEvaluator method eval.

public ConstantExpr eval(LocalsPool pool, Expr e) {
    if (e.getOpcode() == CONST_LOAD) {
        return ((ConstantExpr) e).copy();
    } else if (e.getOpcode() == ARITHMETIC) {
        ArithmeticExpr ae = (ArithmeticExpr) e;
        Expr l = ae.getLeft();
        Expr r = ae.getRight();
        Expr le = eval(pool, l);
        Expr re = eval(pool, r);
        if (le != null && re != null) {
            ConstantExpr lc = (ConstantExpr) le;
            ConstantExpr rc = (ConstantExpr) re;
            EvaluationFunctor<Number> b = factory.arithmetic(lc.getType(), rc.getType(), ae.getType(), ae.getOperator());
            return new ConstantExpr(b.eval(lc.getConstant(), rc.getConstant()));
        }
    } else if (e.getOpcode() == NEGATE) {
        NegationExpr neg = (NegationExpr) e;
        Expr e2 = eval(pool, neg.getExpression());
        if (e2 != null) {
            ConstantExpr ce = (ConstantExpr) e2;
            EvaluationFunctor<Number> b = factory.negate(e2.getType());
            return new ConstantExpr(b.eval(ce.getConstant()));
        }
    } else if (e.getOpcode() == LOCAL_LOAD) {
        VarExpr v = (VarExpr) e;
        Local l = v.getLocal();
        AbstractCopyStmt def = pool.defs.get(l);
        Expr rhs = def.getExpression();
        if (rhs.getOpcode() == LOCAL_LOAD) {
            VarExpr v2 = (VarExpr) rhs;
            // synthetic copies lhs = rhs;
            if (v2.getLocal() == l) {
                return null;
            }
        }
        return eval(pool, rhs);
    } else if (e.getOpcode() == CAST) {
        CastExpr cast = (CastExpr) e;
        Expr e2 = eval(pool, cast.getExpression());
        if (e2 != null) {
            ConstantExpr ce = (ConstantExpr) e2;
            if (!ce.getType().equals(cast.getExpression().getType())) {
                throw new IllegalStateException(ce.getType() + " : " + cast.getExpression().getType());
            }
            Type from = ce.getType();
            Type to = cast.getType();
            boolean p1 = TypeUtils.isPrimitive(from);
            boolean p2 = TypeUtils.isPrimitive(to);
            if (p1 != p2) {
                throw new IllegalStateException(from + " to " + to);
            }
            if (!p1 && !p2) {
                return null;
            }
            EvaluationFunctor<Number> b = factory.cast(from, to);
            return new ConstantExpr(b.eval(ce.getConstant()), to);
        }
    } else if (e.getOpcode() == COMPARE) {
        ComparisonExpr comp = (ComparisonExpr) e;
        Expr l = comp.getLeft();
        Expr r = comp.getRight();
        Expr le = eval(pool, l);
        Expr re = eval(pool, r);
        if (le != null && re != null) {
            ConstantExpr lc = (ConstantExpr) le;
            ConstantExpr rc = (ConstantExpr) re;
            EvaluationFunctor<Number> b = factory.compare(lc.getType(), rc.getType(), comp.getComparisonType());
            return new ConstantExpr(b.eval(lc.getConstant(), rc.getConstant()), Type.INT_TYPE);
        }
    }
    return null;
}
Also used : ComparisonExpr(org.mapleir.ir.code.expr.ComparisonExpr) ConstantExpr(org.mapleir.ir.code.expr.ConstantExpr) Local(org.mapleir.ir.locals.Local) Type(org.objectweb.asm.Type) ArithmeticExpr(org.mapleir.ir.code.expr.ArithmeticExpr) VarExpr(org.mapleir.ir.code.expr.VarExpr) Expr(org.mapleir.ir.code.Expr) ConstantExpr(org.mapleir.ir.code.expr.ConstantExpr) CastExpr(org.mapleir.ir.code.expr.CastExpr) ComparisonExpr(org.mapleir.ir.code.expr.ComparisonExpr) NegationExpr(org.mapleir.ir.code.expr.NegationExpr) ArithmeticExpr(org.mapleir.ir.code.expr.ArithmeticExpr) CastExpr(org.mapleir.ir.code.expr.CastExpr) VarExpr(org.mapleir.ir.code.expr.VarExpr) AbstractCopyStmt(org.mapleir.ir.code.stmt.copy.AbstractCopyStmt) NegationExpr(org.mapleir.ir.code.expr.NegationExpr)

Example 15 with AbstractCopyStmt

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

the class PoolLocalValueResolver method checkRecursive.

private void checkRecursive(Local l) {
    Set<Local> visited = new HashSet<>();
    Queue<Local> worklist = new LinkedList<>();
    worklist.add(l);
    while (!worklist.isEmpty()) {
        l = worklist.poll();
        AbstractCopyStmt copy = pool.defs.get(l);
        Set<Local> set = new HashSet<>();
        Expr rhs = copy.getExpression();
        if (rhs.getOpcode() == Opcode.LOCAL_LOAD) {
            set.add(((VarExpr) rhs).getLocal());
        } else if (rhs.getOpcode() == Opcode.PHI) {
            for (Expr e : ((PhiExpr) rhs).getArguments().values()) {
                set.add(((VarExpr) e).getLocal());
            }
        }
        for (Local v : set) {
            if (visited.contains(v)) {
                System.err.println(copy.getBlock().getGraph());
                System.err.printf("visited: %s%n", visited);
                System.err.printf(" copy: %s%n", copy);
                System.err.printf("  dup: %s%n", v);
                throw new RuntimeException();
            }
        }
        worklist.addAll(set);
        visited.addAll(set);
    }
}
Also used : VarExpr(org.mapleir.ir.code.expr.VarExpr) Expr(org.mapleir.ir.code.Expr) PhiExpr(org.mapleir.ir.code.expr.PhiExpr) PhiExpr(org.mapleir.ir.code.expr.PhiExpr) Local(org.mapleir.ir.locals.Local) AbstractCopyStmt(org.mapleir.ir.code.stmt.copy.AbstractCopyStmt) VarExpr(org.mapleir.ir.code.expr.VarExpr) LinkedList(java.util.LinkedList) HashSet(java.util.HashSet)

Aggregations

AbstractCopyStmt (org.mapleir.ir.code.stmt.copy.AbstractCopyStmt)20 VarExpr (org.mapleir.ir.code.expr.VarExpr)17 Expr (org.mapleir.ir.code.Expr)15 VersionedLocal (org.mapleir.ir.locals.impl.VersionedLocal)12 PhiExpr (org.mapleir.ir.code.expr.PhiExpr)11 Local (org.mapleir.ir.locals.Local)11 BasicBlock (org.mapleir.ir.cfg.BasicBlock)9 Stmt (org.mapleir.ir.code.Stmt)8 ConstantExpr (org.mapleir.ir.code.expr.ConstantExpr)8 InitialisedObjectExpr (org.mapleir.ir.code.expr.invoke.InitialisedObjectExpr)7 InvocationExpr (org.mapleir.ir.code.expr.invoke.InvocationExpr)7 CopyPhiStmt (org.mapleir.ir.code.stmt.copy.CopyPhiStmt)6 CopyVarStmt (org.mapleir.ir.code.stmt.copy.CopyVarStmt)5 HashSet (java.util.HashSet)4 CodeUnit (org.mapleir.ir.code.CodeUnit)4 LocalsPool (org.mapleir.ir.locals.LocalsPool)4 Constraint (org.mapleir.ir.cfg.builder.ssaopt.Constraint)3 LatestValue (org.mapleir.ir.cfg.builder.ssaopt.LatestValue)3 ConditionalJumpStmt (org.mapleir.ir.code.stmt.ConditionalJumpStmt)3 PopStmt (org.mapleir.ir.code.stmt.PopStmt)3