Search in sources :

Example 16 with VersionedLocal

use of org.mapleir.ir.locals.impl.VersionedLocal 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 17 with VersionedLocal

use of org.mapleir.ir.locals.impl.VersionedLocal 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 18 with VersionedLocal

use of org.mapleir.ir.locals.impl.VersionedLocal 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 19 with VersionedLocal

use of org.mapleir.ir.locals.impl.VersionedLocal in project maple-ir by LLVM-but-worse.

the class ConstantParameterPass method demoteDeadParamters.

private void demoteDeadParamters(IPAnalysis constAnalysis, ControlFlowGraph cfg, MethodNode n, boolean[] dead) {
    LocalsPool pool = cfg.getLocals();
    BasicBlock entry = cfg.getEntries().iterator().next();
    for (int i = 0; i < dead.length; i++) {
        if (dead[i]) {
            int localIndex = constAnalysis.getLocalIndex(n, i);
            VersionedLocal local = pool.get(localIndex, 0, false);
            AbstractCopyStmt copy = pool.defs.get(local);
            if (copy.getBlock() != entry) {
                System.err.printf("entry:%n%s%n", ControlFlowGraph.printBlock(entry));
                System.err.printf("block:%n%s%n", ControlFlowGraph.printBlock(copy.getBlock()));
                throw new IllegalStateException(String.format("See debug trace (entry vs block) in %s", n));
            }
            copy.delete();
            if (pool.uses.get(local).size() != 0) {
                throw new IllegalStateException(String.format("m: %s, l:%s, uses:%s", n, local, pool.uses.get(local)));
            }
            pool.defs.remove(local);
            pool.uses.remove(local);
        }
    }
}
Also used : VersionedLocal(org.mapleir.ir.locals.impl.VersionedLocal) LocalsPool(org.mapleir.ir.locals.LocalsPool) BasicBlock(org.mapleir.ir.cfg.BasicBlock) AbstractCopyStmt(org.mapleir.ir.code.stmt.copy.AbstractCopyStmt)

Example 20 with VersionedLocal

use of org.mapleir.ir.locals.impl.VersionedLocal in project maple-ir by LLVM-but-worse.

the class ControlFlowGraph method exciseStmt.

/**
 * Excises uses of a removed statement.
 * @param c Removed statement to update def/use information with respect to.
 */
public void exciseStmt(Stmt c) {
    // delete uses
    for (Expr e : c.enumerateOnlyChildren()) {
        if (e.getOpcode() == Opcode.LOCAL_LOAD) {
            VarExpr v = (VarExpr) e;
            VersionedLocal l = (VersionedLocal) v.getLocal();
            locals.uses.get(l).remove(v);
        }
    }
    c.getBlock().remove(c);
}
Also used : VersionedLocal(org.mapleir.ir.locals.impl.VersionedLocal) 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)

Aggregations

VersionedLocal (org.mapleir.ir.locals.impl.VersionedLocal)21 VarExpr (org.mapleir.ir.code.expr.VarExpr)18 Expr (org.mapleir.ir.code.Expr)12 PhiExpr (org.mapleir.ir.code.expr.PhiExpr)12 AbstractCopyStmt (org.mapleir.ir.code.stmt.copy.AbstractCopyStmt)11 ConstantExpr (org.mapleir.ir.code.expr.ConstantExpr)9 InitialisedObjectExpr (org.mapleir.ir.code.expr.invoke.InitialisedObjectExpr)8 InvocationExpr (org.mapleir.ir.code.expr.invoke.InvocationExpr)8 Stmt (org.mapleir.ir.code.Stmt)6 CopyPhiStmt (org.mapleir.ir.code.stmt.copy.CopyPhiStmt)6 BasicBlock (org.mapleir.ir.cfg.BasicBlock)5 Constraint (org.mapleir.ir.cfg.builder.ssaopt.Constraint)5 CopyVarStmt (org.mapleir.ir.code.stmt.copy.CopyVarStmt)5 Local (org.mapleir.ir.locals.Local)5 LocalsPool (org.mapleir.ir.locals.LocalsPool)5 LatestValue (org.mapleir.ir.cfg.builder.ssaopt.LatestValue)4 CodeUnit (org.mapleir.ir.code.CodeUnit)3 BasicLocal (org.mapleir.ir.locals.impl.BasicLocal)3 HashSet (java.util.HashSet)2 Entry (java.util.Map.Entry)2