Search in sources :

Example 11 with CopyPhiStmt

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

the class SSAGenPass method reduceClass.

private void reduceClass(Set<CopyPhiStmt> cc, CopyPhiStmt preferred) {
    Set<CopyPhiStmt> useless = new HashSet<>(cc);
    useless.remove(preferred);
    VersionedLocal phiLocal = (VersionedLocal) preferred.getVariable().getLocal();
    /* all the *dead* phi class locals */
    Set<VersionedLocal> deadLocals = new HashSet<>();
    for (CopyPhiStmt def : useless) {
        VersionedLocal local = (VersionedLocal) def.getVariable().getLocal();
        deadLocals.add(local);
        for (Expr e : def.enumerateOnlyChildren()) {
            if (e.getOpcode() == Opcode.LOCAL_LOAD) {
                VarExpr v = (VarExpr) e;
                VersionedLocal vl = (VersionedLocal) v.getLocal();
                pool.uses.get(vl).remove(v);
            }
        }
        // System.out.println(" killing " + def);
        def.delete();
    }
    for (VersionedLocal vl : deadLocals) {
        Set<VarExpr> deadVExprs = pool.uses.get(vl);
        for (VarExpr v : deadVExprs) {
            /* v.getLocal() == vl, i.e. dead phi local.
				 * Replace each dead var with the real one. */
            v.setLocal(phiLocal);
            pool.uses.get(phiLocal).add(v);
        }
        /* all dead. */
        /*pool.uses.get(vl)*/
        deadVExprs.clear();
        pool.defs.remove(vl);
    }
}
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) VarExpr(org.mapleir.ir.code.expr.VarExpr) CopyPhiStmt(org.mapleir.ir.code.stmt.copy.CopyPhiStmt)

Example 12 with CopyPhiStmt

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

the class SSAGenPass method searchImpl.

private void searchImpl(BasicBlock b) {
    Iterator<Stmt> it = b.iterator();
    while (it.hasNext()) {
        Stmt stmt = it.next();
        int opcode = stmt.getOpcode();
        if (opcode == Opcode.POP) {
            PopStmt pop = (PopStmt) stmt;
            if (!ConstraintUtil.isUncopyable(pop.getExpression())) {
                it.remove();
                continue;
            }
        }
        if (opcode == Opcode.PHI_STORE) {
            /* We can rename these any time as these
				 * are visited before all other statements
				 * in a block (since they are always
				 * the starting statements of a block, if
				 * that block contains phi statements).
				 */
            CopyPhiStmt copy = (CopyPhiStmt) stmt;
            generate(copy);
        } else {
            /* Translates locals into their latest SSA
				 * versioned locals.
				 * 
				 * Do this before a LOCAL_STORE (x = ...)
				 * so that the target local isn't defined
				 * before the use so that copies in the
				 * form x = x; do not get mangled into
				 * x0 = x0 after SSA renaming.
				 * 
				 * We rename phi args later as the source
				 * local can originate from exotic blocks.
				 */
            translate(stmt, true, false);
        }
        if (opcode == Opcode.LOCAL_STORE) {
            /* Generate the target local after
				 * renaming the source pool.uses. 
				 */
            CopyVarStmt copy = (CopyVarStmt) stmt;
            generate(copy);
        }
    }
}
Also used : PopStmt(org.mapleir.ir.code.stmt.PopStmt) CopyVarStmt(org.mapleir.ir.code.stmt.copy.CopyVarStmt) Constraint(org.mapleir.ir.cfg.builder.ssaopt.Constraint) 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 CopyPhiStmt

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

the class SSAGenPass method fixPhiArgs.

private void fixPhiArgs(BasicBlock b, BasicBlock succ) {
    for (Stmt stmt : succ) {
        if (stmt.getOpcode() == Opcode.PHI_STORE) {
            CopyPhiStmt copy = (CopyPhiStmt) stmt;
            PhiExpr phi = copy.getExpression();
            Expr e = phi.getArgument(b);
            if (e.getOpcode() == Opcode.LOCAL_LOAD) {
                VarExpr v = (VarExpr) e;
                translate(v, true, true);
                VersionedLocal ssaL = (VersionedLocal) v.getLocal();
                Type t = types.get(ssaL);
                copy.getVariable().setType(t);
                phi.setType(t);
            } else {
                throw new IllegalArgumentException(phi + ", " + e);
            }
        } else {
            /* No need to search the rest of the block
				 * after we have visited the phis as they
				 * precede all other statements.
				 */
            break;
        }
    }
}
Also used : VersionedLocal(org.mapleir.ir.locals.impl.VersionedLocal) Type(org.objectweb.asm.Type) 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) PhiExpr(org.mapleir.ir.code.expr.PhiExpr) VarExpr(org.mapleir.ir.code.expr.VarExpr) 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 14 with CopyPhiStmt

use of org.mapleir.ir.code.stmt.copy.CopyPhiStmt 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 15 with CopyPhiStmt

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

the class SSAGenPass method insertPhis.

private void insertPhis(BasicBlock b, Local l, int i, LinkedList<BasicBlock> queue) {
    if (b == null || b == builder.head) {
        // exit
        return;
    }
    Local newl = builder.graph.getLocals().get(l.getIndex(), 0, l.isStack());
    for (BasicBlock x : doms.iteratedFrontier(b)) {
        if (insertion.get(x) < i) {
            // pruned SSA
            if (liveness.in(x).contains(l)) {
                if ((l == svar0) && handlers.contains(x)) /* == faster than contains. */
                {
                    /* Note: this is quite subtle. Since there is a
						 * copy, (svar0 = catch()) at the start of each
						 * handler block, technically any natural flowing
						 * svar0 definition is killed upon entry to the
						 * block, so it is not considered live. One way to
						 * check if the variable is live-in, therefore, is
						 * by checking whether svar0 is live-out of the
						 * catch() definition. We handle it here, since
						 * the previous liveness check which is used for
						 * pruned SSA will fail in this case. */
                    /* Ok fuck that that, it's considered live-in
						 * even if there is a catch()::
						 *  #see SSaBlockLivenessAnalyser.precomputeBlock*/
                    boolean naturalFlow = false;
                    for (FlowEdge<BasicBlock> e : builder.graph.getReverseEdges(x)) {
                        if (e.getType() != FlowEdges.TRYCATCH) {
                            naturalFlow = true;
                            break;
                        }
                    }
                    if (naturalFlow) {
                        CopyVarStmt catcher = null;
                        for (Stmt stmt : x) {
                            if (stmt.getOpcode() == Opcode.LOCAL_STORE) {
                                CopyVarStmt copy = (CopyVarStmt) stmt;
                                Expr e = copy.getExpression();
                                if (e.getOpcode() == Opcode.CATCH) {
                                    catcher = copy;
                                    break;
                                }
                            }
                        }
                        if (catcher == null) {
                            /* Handler but no catch copy?
								 * This can't happen since svar0 is
								 * the only reserved register for
								 * catch copies, and this block cannot
								 * be visited twice to insert a phi or
								 * psi(ephi) node. */
                            throw new IllegalStateException(x.getDisplayName());
                        }
                        /* Map<BasicBlock, Expression> vls = new HashMap<>();
							for(FlowEdge<BasicBlock> fe : builder.graph.getReverseEdges(x)) {
								vls.put(fe.src, new VarExpr(newl, null));
							}
							vls.put(x, catcher.getExpression().copy());
							catcher.delete();
							
							PhiExpr phi = new PhiExceptionExpr(vls);
							CopyPhiStmt assign = new CopyPhiStmt(new VarExpr(l, null), phi);
							
							x.add(0, assign); */
                        throw new UnsupportedOperationException(builder.method.toString());
                    }
                }
                if (builder.graph.getReverseEdges(x).size() > 1) {
                    Map<BasicBlock, Expr> vls = new HashMap<>();
                    for (FlowEdge<BasicBlock> fe : builder.graph.getReverseEdges(x)) {
                        vls.put(fe.src(), new VarExpr(newl, null));
                    }
                    PhiExpr phi = new PhiExpr(vls);
                    CopyPhiStmt assign = new CopyPhiStmt(new VarExpr(l, null), phi);
                    x.add(0, assign);
                }
            }
            insertion.put(x, i);
            if (process.get(x) < i) {
                process.put(x, i);
                queue.add(x);
            }
        }
    }
}
Also used : NullPermeableHashMap(org.mapleir.stdlib.collections.map.NullPermeableHashMap) 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) 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) 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) PhiExpr(org.mapleir.ir.code.expr.PhiExpr) VarExpr(org.mapleir.ir.code.expr.VarExpr)

Aggregations

CopyPhiStmt (org.mapleir.ir.code.stmt.copy.CopyPhiStmt)20 VarExpr (org.mapleir.ir.code.expr.VarExpr)17 PhiExpr (org.mapleir.ir.code.expr.PhiExpr)16 BasicBlock (org.mapleir.ir.cfg.BasicBlock)15 Expr (org.mapleir.ir.code.Expr)15 Local (org.mapleir.ir.locals.Local)14 Stmt (org.mapleir.ir.code.Stmt)13 CopyVarStmt (org.mapleir.ir.code.stmt.copy.CopyVarStmt)13 AbstractCopyStmt (org.mapleir.ir.code.stmt.copy.AbstractCopyStmt)12 VersionedLocal (org.mapleir.ir.locals.impl.VersionedLocal)10 ConditionalJumpStmt (org.mapleir.ir.code.stmt.ConditionalJumpStmt)5 PopStmt (org.mapleir.ir.code.stmt.PopStmt)5 SwitchStmt (org.mapleir.ir.code.stmt.SwitchStmt)5 ThrowStmt (org.mapleir.ir.code.stmt.ThrowStmt)5 UnconditionalJumpStmt (org.mapleir.ir.code.stmt.UnconditionalJumpStmt)5 ConstantExpr (org.mapleir.ir.code.expr.ConstantExpr)4 InitialisedObjectExpr (org.mapleir.ir.code.expr.invoke.InitialisedObjectExpr)4 InvocationExpr (org.mapleir.ir.code.expr.invoke.InvocationExpr)4 NullPermeableHashMap (org.mapleir.stdlib.collections.map.NullPermeableHashMap)4 BasicLocal (org.mapleir.ir.locals.impl.BasicLocal)2