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);
}
}
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));
}
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);
}
}
}
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);
}
}
}
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);
}
Aggregations