Search in sources :

Example 21 with VarExpr

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

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

the class SSAGenPass method splitRanges.

private void splitRanges() {
    // produce cleaner cfg
    List<BasicBlock> order = new ArrayList<>(builder.graph.vertices());
    NullPermeableHashMap<BasicBlock, Set<Local>> splits = new NullPermeableHashMap<>(SetCreator.getInstance());
    for (ExceptionRange<BasicBlock> er : builder.graph.getRanges()) {
        BasicBlock h = er.getHandler();
        handlers.add(h);
        Set<Local> ls = new HashSet<>(liveness.in(h));
        for (BasicBlock b : er.get()) {
            splits.getNonNull(b).addAll(ls);
        }
    }
    for (Entry<BasicBlock, Set<Local>> e : splits.entrySet()) {
        BasicBlock b = e.getKey();
        Set<Local> ls = e.getValue();
        ArrayList<Stmt> stmtsCopy = new ArrayList<>(b);
        int i = 0;
        boolean checkSplit = false;
        for (int i1 = 0; i1 < stmtsCopy.size(); i1++) {
            Stmt stmt = stmtsCopy.get(i1);
            if (b.size() == i)
                throw new IllegalStateException("s");
            if (checkSplit && stmt.getOpcode() == Opcode.LOCAL_STORE) {
                CopyVarStmt copy = (CopyVarStmt) stmt;
                VarExpr v = copy.getVariable();
                if (ls.contains(v.getLocal())) {
                    BasicBlock n = splitBlock(b, i);
                    order.add(order.indexOf(b), n);
                    i = 0;
                    checkSplit = false;
                }
            } else {
                // do not split if we have only seen simple or synthetic copies (catch copy is synthetic)
                if (stmt instanceof CopyVarStmt) {
                    CopyVarStmt copy = (CopyVarStmt) stmt;
                    int opc = copy.getExpression().getOpcode();
                    if (!copy.isSynthetic() && opc != Opcode.LOCAL_LOAD && opc != Opcode.CATCH) {
                        checkSplit = true;
                    }
                } else {
                    checkSplit = true;
                }
            }
            i++;
        }
    }
    builder.graph.naturalise(order);
    int po = 0;
    for (BasicBlock b : SimpleDfs.preorder(builder.graph, builder.graph.getEntries().iterator().next())) {
        insertion.put(b, 0);
        process.put(b, 0);
        preorder.put(b, po++);
    }
}
Also used : 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) 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) NullPermeableHashMap(org.mapleir.stdlib.collections.map.NullPermeableHashMap) VarExpr(org.mapleir.ir.code.expr.VarExpr)

Example 23 with VarExpr

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

the class SSAGenPass method translateStmt.

private void translateStmt(VarExpr var, boolean resolve, boolean isPhi) {
    /* Here we only remap local variable loads
		 * on the right hand side of a statement or
		 * expression. This means that if we are able
		 * to simply replace a local load which has
		 * a constant or deferred local value.
		 * 
		 * However, if the value of the local is
		 * a complex expression we need to check that
		 * we can propagate it before we do.
		 * 
		 * Since we will only replace a single
		 * local load in the original expression,
		 * only 1 variable is killed. However, there
		 * may be local load expressions in the
		 * propagated expression. To account for this,
		 * these local loads must be counted as new
		 * uses (except for when an expression is
		 * moved instead of copied to a use site).*/
    Local l = var.getLocal();
    VersionedLocal ssaL;
    if (resolve) {
        ssaL = latest(l.getIndex(), l.isStack());
    } else {
        ssaL = (VersionedLocal) l;
    }
    pool.uses.get(ssaL).add(var);
    VersionedLocal newL = ssaL;
    boolean exists = true;
    if (OPTIMISE) {
        if (latest.containsKey(ssaL)) {
            /* Try to propagate a simple copy local
				 * to its use site. It is possible that
				 * a non simple copy (including phis)
				 * will not have a mapping. In this case
				 * they will not have an updated target.*/
            LatestValue value = latest.get(ssaL);
            boolean unpredictable = value.getType() == LatestValue.PARAM || value.getType() == LatestValue.PHI;
            if (unpredictable && ssaL != value.getSuggestedValue()) {
                VersionedLocal vl = (VersionedLocal) value.getSuggestedValue();
                if (shouldPropagate(ssaL, vl)) {
                    newL = vl;
                }
            } else if (!isPhi && !unpredictable) {
                Expr e = null;
                AbstractCopyStmt def = pool.defs.get(ssaL);
                Expr rval = (Expr) value.getSuggestedValue();
                if (ConstraintUtil.isUncopyable(rval)) {
                    /* A variable might have a value
						 * that is uncopyable such as an
						 * invoke or allocation call.
						 * 
						 * There are two ways this may happen:
						 *   x = call();
						 *  or
						 *   x = call();
						 *   y = x;
						 *   
						 * we defer optimising the first
						 * case till the end.
						 * 
						 * in the second case, we can
						 * propagate the source var (x)
						 * in place of the target (y). */
                    newL = tryDefer(value, ssaL);
                } else {
                    AbstractCopyStmt from = def;
                    if (value.getSource() != null) {
                        from = pool.defs.get(value.getSource());
                    }
                    if (!value.hasConstraints() || (canTransferHandlers(def.getBlock(), var.getBlock()) && value.canPropagate(from, var.getRootParent(), var, false))) {
                        if (shouldCopy(rval)) {
                            e = rval;
                        } else {
                            newL = tryDefer(value, ssaL);
                        }
                    } else if (value.getRealValue() instanceof VersionedLocal) {
                        VersionedLocal realVal = (VersionedLocal) value.getRealValue();
                        if (shouldPropagate(ssaL, realVal)) {
                            newL = realVal;
                        } else {
                            shadowed.getNonNull(ssaL).add(realVal);
                            shadowed.getNonNull(realVal).add(ssaL);
                        }
                    }
                }
                if (e != null) {
                    // System.out.println("=====");
                    // System.out.println("   ssaL: " + ssaL);
                    // System.out.println("   bpar: " + var.getParent());
                    CodeUnit parent = var.getParent();
                    int idx = parent.indexOf(var);
                    parent.overwrite(e = e.copy(), idx);
                    // System.out.println("    def: " + def);
                    // System.out.println("    idx: " + idx);
                    // System.out.println("    val: " + value);
                    // System.out.println("   apar: " + parent);
                    // System.out.println("      e: " + e);
                    /* Remove the use of the var before
						 * we translate the children of the 
						 * newly propagated expression.*/
                    pool.uses.get(ssaL).remove(var);
                    // System.out.println("   uses: " + pool.uses.get(ssaL));
                    /* Account for the new pool.uses.*/
                    collectUses(e);
                    /* Finally see if we can reduce
						 * this statement further.*/
                    translate(e, false, isPhi);
                    exists = false;
                }
            } else {
                newL = ssaL;
            }
        } else {
            throw new IllegalStateException("No (self) ancestors: " + l + " -> " + ssaL);
        }
    }
    if (exists) {
        if (OPTIMISE) {
            // System.out.println("replace: " + ssaL + " with " + newL);
            if (ssaL != newL) {
                // System.out.println(ssaL + "  -->  " + newL);
                pool.uses.get(ssaL).remove(var);
                pool.uses.get(newL).add(var);
            }
        }
        /* If the expression still exists, update
			 * or set both variable and type information.*/
        var.setLocal(newL);
        Type type = types.get(ssaL);
        if (type == null) {
            throw new IllegalStateException(var + ", " + ssaL + ", t=null");
        } else {
            var.setType(type);
        }
    }
}
Also used : VersionedLocal(org.mapleir.ir.locals.impl.VersionedLocal) LatestValue(org.mapleir.ir.cfg.builder.ssaopt.LatestValue) 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) 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) CodeUnit(org.mapleir.ir.code.CodeUnit)

Example 24 with VarExpr

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

the class SSAGenPass method generate.

private VersionedLocal generate(AbstractCopyStmt copy) {
    VarExpr v = copy.getVariable();
    Local oldLocal = v.getLocal();
    int index = oldLocal.getIndex();
    boolean isStack = oldLocal.isStack();
    LocalsPool handler = builder.graph.getLocals();
    Local l = handler.get(index, isStack);
    int subscript = counters.get(l);
    stacks.get(l).push(subscript);
    counters.put(l, subscript + 1);
    VersionedLocal ssaL = handler.get(index, subscript, isStack);
    if (OPTIMISE) {
        makeValue(copy, ssaL);
    }
    v.setLocal(ssaL);
    pool.defs.put(ssaL, copy);
    types.put(ssaL, copy.getExpression().getType());
    pool.uses.put(ssaL, new HashSet<>());
    return ssaL;
}
Also used : VersionedLocal(org.mapleir.ir.locals.impl.VersionedLocal) LocalsPool(org.mapleir.ir.locals.LocalsPool) 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) Constraint(org.mapleir.ir.cfg.builder.ssaopt.Constraint)

Example 25 with VarExpr

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

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