Search in sources :

Example 36 with VarExpr

use of org.mapleir.ir.code.expr.VarExpr 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 37 with VarExpr

use of org.mapleir.ir.code.expr.VarExpr 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)

Example 38 with VarExpr

use of org.mapleir.ir.code.expr.VarExpr in project maple-ir by LLVM-but-worse.

the class SSAGenPass method makeValue.

private void makeValue(AbstractCopyStmt copy, VersionedLocal ssaL) {
    /* Attempts to find the 'value' of a local.
		 * The value can be the following types:
		 *   param - assigned by caller method
		 *   phi - set by a phi node
		 *   const - compiletime constant
		 *   var - runtime computed
		 *   
		 * when a copy x = y, is visited,
		 * if y is a var, x inherits
		 * the value and value type.
		 * */
    Expr e = copy.getExpression();
    int opcode = e.getOpcode();
    if (opcode == Opcode.LOCAL_LOAD) {
        if (copy.isSynthetic()) {
            /* equals itself (pure value).*/
            LatestValue value = new LatestValue(builder.graph, LatestValue.PARAM, ssaL, null);
            latest.put(ssaL, value);
        } else {
            /* i.e. x = y, where x and y are both variables.
				 * 
				 * It is expected that the local uses of the copy 
				 * (rhs) are visited before the target is.
				 */
            VarExpr rhs = (VarExpr) e;
            VersionedLocal rhsL = (VersionedLocal) rhs.getLocal();
            /* the rhsL must have been visited already
				 * and the lhsL must not have been.*/
            if (!latest.containsKey(ssaL)) {
                if (latest.containsKey(rhsL)) {
                    LatestValue anc = latest.get(rhsL);
                    // TODO: maybe advance the src local if we
                    // can validate an expr propagation to the
                    // new copy dst.
                    LatestValue value = new LatestValue(builder.graph, anc.getType(), rhsL, anc.getSuggestedValue(), anc.getSource());
                    value.importConstraints(anc);
                    latest.put(ssaL, value);
                } else {
                    throw new IllegalStateException("Non anc parent: " + ssaL + " = " + rhsL + " (def: " + pool.defs.get(rhsL) + ")");
                }
            } else {
                throw new IllegalStateException("Revisit def " + ssaL + " ( = " + rhsL + ")");
            }
        }
    } else {
        LatestValue value;
        if (opcode == Opcode.CONST_LOAD) {
            ConstantExpr ce = (ConstantExpr) e;
            value = new LatestValue(builder.graph, LatestValue.CONST, ce, null);
        } else if ((opcode & Opcode.CLASS_PHI) == Opcode.CLASS_PHI) {
            value = new LatestValue(builder.graph, LatestValue.PHI, ssaL, null);
        } else {
            if (e.getOpcode() == Opcode.LOCAL_LOAD) {
                throw new RuntimeException(copy + "    " + e);
            }
            value = new LatestValue(builder.graph, LatestValue.VAR, e, ssaL);
            value.makeConstraints(e);
        }
        latest.put(ssaL, value);
    }
// System.out.println("made val " + ssaL + " -> " + latest.get(ssaL));
}
Also used : LatestValue(org.mapleir.ir.cfg.builder.ssaopt.LatestValue) 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) ConstantExpr(org.mapleir.ir.code.expr.ConstantExpr) VarExpr(org.mapleir.ir.code.expr.VarExpr) Constraint(org.mapleir.ir.cfg.builder.ssaopt.Constraint)

Example 39 with VarExpr

use of org.mapleir.ir.code.expr.VarExpr 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 40 with VarExpr

use of org.mapleir.ir.code.expr.VarExpr 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)

Aggregations

VarExpr (org.mapleir.ir.code.expr.VarExpr)51 Expr (org.mapleir.ir.code.Expr)37 Local (org.mapleir.ir.locals.Local)32 PhiExpr (org.mapleir.ir.code.expr.PhiExpr)31 AbstractCopyStmt (org.mapleir.ir.code.stmt.copy.AbstractCopyStmt)30 VersionedLocal (org.mapleir.ir.locals.impl.VersionedLocal)29 BasicBlock (org.mapleir.ir.cfg.BasicBlock)26 Stmt (org.mapleir.ir.code.Stmt)25 CopyPhiStmt (org.mapleir.ir.code.stmt.copy.CopyPhiStmt)25 CopyVarStmt (org.mapleir.ir.code.stmt.copy.CopyVarStmt)21 ConstantExpr (org.mapleir.ir.code.expr.ConstantExpr)15 InvocationExpr (org.mapleir.ir.code.expr.invoke.InvocationExpr)13 InitialisedObjectExpr (org.mapleir.ir.code.expr.invoke.InitialisedObjectExpr)12 BasicLocal (org.mapleir.ir.locals.impl.BasicLocal)7 NullPermeableHashMap (org.mapleir.stdlib.collections.map.NullPermeableHashMap)7 Type (org.objectweb.asm.Type)7 HashSet (java.util.HashSet)6 Constraint (org.mapleir.ir.cfg.builder.ssaopt.Constraint)6 ConditionalJumpStmt (org.mapleir.ir.code.stmt.ConditionalJumpStmt)5 PopStmt (org.mapleir.ir.code.stmt.PopStmt)5