Search in sources :

Example 1 with CodeUnit

use of org.mapleir.ir.code.CodeUnit 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 2 with CodeUnit

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

the class SSAGenPass method processDeferredTranslations.

private int processDeferredTranslations() {
    int i = 0;
    Iterator<Entry<VersionedLocal, Set<VarExpr>>> it = pool.uses.entrySet().iterator();
    while (it.hasNext()) {
        Entry<VersionedLocal, Set<VarExpr>> e = it.next();
        VersionedLocal vl = e.getKey();
        if (deferred.contains(vl) || vl.isStack()) {
            Set<VarExpr> useSet = e.getValue();
            AbstractCopyStmt def = pool.defs.get(vl);
            if (def != null && useSet.size() == 1) {
                /* In this case, the only place that the value
					 * of this assignment will be used is at the use site.
					 * Since that value can not be spread until this one
					 * is, we can propagate it.*/
                if (def.getOpcode() != Opcode.PHI_STORE) {
                    VarExpr use = useSet.iterator().next();
                    LatestValue val = latest.get(vl);
                    // System.out.println();
                    // System.out.println();
                    // System.out.println(def);
                    // System.out.println(use);
                    /* phi var*/
                    Expr rhs = def.getExpression();
                    if (use.getParent() != null) {
                        if (canTransferHandlers(def.getBlock(), use.getBlock()) && val.canPropagate(def, use.getRootParent(), use, false)) {
                            CodeUnit parent = use.getParent();
                            if (rhs.getOpcode() == Opcode.CATCH) {
                                // CodeUnit rp = use.getRootParent();
                                // System.out.println("DENIED NIGGA");
                                // System.out.println("replace " + vl + " with " + rhs);
                                // System.out.println(" in " + parent);
                                // System.out.println(" kill def: " + def);
                                // System.out.println();
                                deferred.remove(vl);
                                continue;
                            // check to see if we're moving it to the
                            // first expression in the block, if we aren't
                            // then deny, otherwise we can get rid of the local.
                            // if(rp.getBlock().indexOf(rp) != 1 || rp.enumerateExecutionOrder().indexOf(use) != 0) {
                            // 
                            // }
                            }
                            rhs.unlink();
                            def.delete();
                            pool.defs.remove(vl);
                            useSet.clear();
                            parent.overwrite(rhs, parent.indexOf(use));
                            i++;
                            it.remove();
                        }
                    }
                }
            }
        }
    }
    return i;
}
Also used : VersionedLocal(org.mapleir.ir.locals.impl.VersionedLocal) LatestValue(org.mapleir.ir.cfg.builder.ssaopt.LatestValue) Entry(java.util.Map.Entry) 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) AbstractCopyStmt(org.mapleir.ir.code.stmt.copy.AbstractCopyStmt) Constraint(org.mapleir.ir.cfg.builder.ssaopt.Constraint) CodeUnit(org.mapleir.ir.code.CodeUnit)

Example 3 with CodeUnit

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

the class LatestValue method canPropagate.

public boolean canPropagate(AbstractCopyStmt def, Stmt use, Expr tail, boolean debug) {
    Local local = def.getVariable().getLocal();
    Set<Stmt> path = findReachable(def, use);
    path.remove(def);
    path.add(use);
    if (debug) {
        System.out.println();
        System.out.println("from " + def);
        System.out.println("to " + use);
        System.out.println(this);
        System.out.println("constraints: " + constraints.size());
        for (Constraint c : constraints) {
            System.out.println(" " + c);
        }
        System.out.println(" path:");
        for (Stmt s : path) {
            System.out.println("  " + s);
        }
    }
    for (Stmt stmt : path) {
        if (stmt != use) {
            for (CodeUnit s : stmt.enumerateWithSelf()) {
                for (Constraint c : constraints) {
                    if (c.fails(s)) {
                        if (debug) {
                            System.out.println("  Fail: " + c);
                            System.out.println("  stmt: " + stmt);
                            System.out.println("     c: " + s);
                        }
                        return false;
                    }
                }
            }
        } else {
            if (constraints.size() > 0) {
                for (CodeUnit s : stmt.enumerateExecutionOrder()) {
                    if (s == tail && (s.getOpcode() == Opcode.LOCAL_LOAD && ((VarExpr) s).getLocal() == local)) {
                        break;
                    } else {
                        for (Constraint c : constraints) {
                            if (c.fails(s)) {
                                if (debug) {
                                    System.out.println("  Fail: " + c);
                                    System.out.println("  stmt: " + stmt);
                                    System.out.println("     c: " + s);
                                }
                                return false;
                            }
                        }
                    }
                }
            }
        }
    }
    return true;
}
Also used : Local(org.mapleir.ir.locals.Local) VersionedLocal(org.mapleir.ir.locals.impl.VersionedLocal) VarExpr(org.mapleir.ir.code.expr.VarExpr) Stmt(org.mapleir.ir.code.Stmt) AbstractCopyStmt(org.mapleir.ir.code.stmt.copy.AbstractCopyStmt) CodeUnit(org.mapleir.ir.code.CodeUnit)

Example 4 with CodeUnit

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

the class ConstantParameterPass method inlineConstant.

private void inlineConstant(ControlFlowGraph cfg, int argLocalIndex, Object o) {
    /* we don't actually demote the synthetic copy
		 * here as we would also need to change the
		 * method desc and we can't do that until
		 * later so we defer it. */
    LocalsPool pool = cfg.getLocals();
    /* create the spill variable but not the
		 * actual definition yet. */
    VersionedLocal argLocal = pool.get(argLocalIndex, 0, false);
    VersionedLocal spill = pool.makeLatestVersion(argLocal);
    AbstractCopyStmt synthParamCopy = pool.defs.get(argLocal);
    ConstantExpr rhsVal = new ConstantExpr(o, synthParamCopy.getType() == Type.BOOLEAN_TYPE ? Type.BYTE_TYPE : synthParamCopy.getType());
    /* we have to maintain local references in
		 * phis as opposed to direct constant refs,
		 * so we go through every use of the argLocal
		 * and either replace it with the constant or
		 * a reference to the spill local if it is in
		 * a phi. */
    Set<VarExpr> spillUses = new HashSet<>();
    boolean requireSpill = false;
    Iterator<VarExpr> it = pool.uses.get(argLocal).iterator();
    while (it.hasNext()) {
        VarExpr v = it.next();
        if (v.getParent() == null) {
            /* the use is in a phi, we can't
				 * remove the def. 
				 * 
				 * we also replace the old var
				 * with the new spill one so we
				 * have to add this as a use of
				 * the new spill local. */
            spillUses.add(v);
            v.setLocal(spill);
            requireSpill = true;
        } else {
            CodeUnit par = v.getParent();
            par.overwrite(rhsVal.copy(), par.indexOf(v));
        }
        /* this use is no longer associated
			 * with the old argLocal. */
        it.remove();
    }
    if (pool.uses.get(argLocal).size() != 0) {
        throw new IllegalStateException(String.format("l:%s, uses:%s", argLocal, pool.uses.get(argLocal)));
    }
    if (requireSpill) {
        /* generate the copy for the spill (v = const) */
        CopyVarStmt spillCopy = new CopyVarStmt(new VarExpr(spill, synthParamCopy.getVariable().getType()), rhsVal);
        synthParamCopy.getBlock().add(spillCopy);
        /* initialise data entries for the new spill
			 * variable. */
        pool.defs.put(spill, spillCopy);
        pool.uses.put(spill, spillUses);
    }
}
Also used : VersionedLocal(org.mapleir.ir.locals.impl.VersionedLocal) LocalsPool(org.mapleir.ir.locals.LocalsPool) CopyVarStmt(org.mapleir.ir.code.stmt.copy.CopyVarStmt) ConstantExpr(org.mapleir.ir.code.expr.ConstantExpr) AbstractCopyStmt(org.mapleir.ir.code.stmt.copy.AbstractCopyStmt) VarExpr(org.mapleir.ir.code.expr.VarExpr) HashSet(java.util.HashSet) CodeUnit(org.mapleir.ir.code.CodeUnit)

Example 5 with CodeUnit

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

the class ConstantParameterPass method patchCall.

private void patchCall(String newDesc, Expr call, boolean[] dead) {
    if (call.getOpcode() == Opcode.INIT_OBJ) {
        InitialisedObjectExpr init = (InitialisedObjectExpr) call;
        CodeUnit parent = init.getParent();
        Expr[] newArgs = buildArgs(init.getArgumentExprs(), false, dead);
        InitialisedObjectExpr init2 = new InitialisedObjectExpr(init.getOwner(), newDesc, newArgs);
        parent.overwrite(init2, parent.indexOf(init));
    } else if (call.getOpcode() == Opcode.INVOKE) {
        InvocationExpr invoke = (InvocationExpr) call;
        CodeUnit parent = invoke.getParent();
        Expr[] newArgs = buildArgs(invoke.getArgumentExprs(), invoke.getCallType() != InvocationExpr.CallType.STATIC, dead);
        InvocationExpr invoke2 = new InvocationExpr(invoke.getCallType(), newArgs, invoke.getOwner(), invoke.getName(), newDesc);
        parent.overwrite(invoke2, parent.indexOf(invoke));
    } else {
        throw new UnsupportedOperationException(call.toString());
    }
}
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) InitialisedObjectExpr(org.mapleir.ir.code.expr.invoke.InitialisedObjectExpr) InvocationExpr(org.mapleir.ir.code.expr.invoke.InvocationExpr) CodeUnit(org.mapleir.ir.code.CodeUnit)

Aggregations

CodeUnit (org.mapleir.ir.code.CodeUnit)10 ConstantExpr (org.mapleir.ir.code.expr.ConstantExpr)9 Expr (org.mapleir.ir.code.Expr)6 VarExpr (org.mapleir.ir.code.expr.VarExpr)6 AbstractCopyStmt (org.mapleir.ir.code.stmt.copy.AbstractCopyStmt)5 VersionedLocal (org.mapleir.ir.locals.impl.VersionedLocal)4 Stmt (org.mapleir.ir.code.Stmt)3 ArithmeticExpr (org.mapleir.ir.code.expr.ArithmeticExpr)3 InitialisedObjectExpr (org.mapleir.ir.code.expr.invoke.InitialisedObjectExpr)3 InvocationExpr (org.mapleir.ir.code.expr.invoke.InvocationExpr)3 BigInteger (java.math.BigInteger)2 HashSet (java.util.HashSet)2 BasicBlock (org.mapleir.ir.cfg.BasicBlock)2 LatestValue (org.mapleir.ir.cfg.builder.ssaopt.LatestValue)2 FieldLoadExpr (org.mapleir.ir.code.expr.FieldLoadExpr)2 PhiExpr (org.mapleir.ir.code.expr.PhiExpr)2 Local (org.mapleir.ir.locals.Local)2 ArrayList (java.util.ArrayList)1 Entry (java.util.Map.Entry)1 ControlFlowGraph (org.mapleir.ir.cfg.ControlFlowGraph)1