use of com.googlecode.dex2jar.ir.expr.Value in project dex2jar by pxb1988.
the class RemoveConstantFromSSA method transformReportChanged.
@Override
public boolean transformReportChanged(IrMethod method) {
boolean changed = false;
List<AssignStmt> assignStmtList = new ArrayList<>();
Map<Local, Object> cstMap = new HashMap<>();
for (Stmt p = method.stmts.getFirst(); p != null; p = p.getNext()) {
if (p.st == Stmt.ST.ASSIGN) {
AssignStmt as = (AssignStmt) p;
if (as.getOp1().vt == Value.VT.LOCAL) {
if (as.getOp2().vt == Value.VT.CONSTANT) {
assignStmtList.add(as);
cstMap.put((Local) as.getOp1(), ((Constant) as.getOp2()).value);
} else if (as.getOp2().vt == Value.VT.LOCAL) {
cstMap.put((Local) as.getOp1(), as.getOp2());
}
}
}
}
if (assignStmtList.size() == 0) {
return false;
}
RemoveLocalFromSSA.fixReplace(cstMap);
final Map<Local, Value> toReplace = new HashMap<>();
Set<Value> usedInPhi = new HashSet<>();
List<LabelStmt> phiLabels = method.phiLabels;
if (phiLabels != null) {
boolean loopAgain = true;
while (loopAgain) {
loopAgain = false;
usedInPhi.clear();
for (Iterator<LabelStmt> it = phiLabels.iterator(); it.hasNext(); ) {
LabelStmt labelStmt = it.next();
if (labelStmt.phis != null) {
for (Iterator<AssignStmt> it2 = labelStmt.phis.iterator(); it2.hasNext(); ) {
AssignStmt phi = it2.next();
Value[] vs = phi.getOp2().getOps();
Object sameCst = null;
boolean allEqual = true;
for (Value p : vs) {
Object cst = cstMap.get(p);
if (cst == null) {
allEqual = false;
break;
}
if (sameCst == null) {
sameCst = cst;
} else if (!sameCst.equals(cst)) {
allEqual = false;
break;
}
}
if (allEqual) {
// all are same constant
cstMap.put((Local) phi.getOp1(), sameCst);
if (sameCst instanceof Local) {
phi.setOp2((Value) sameCst);
} else {
phi.setOp2(Exprs.nConstant(sameCst));
assignStmtList.add(phi);
}
it2.remove();
method.stmts.insertAfter(labelStmt, phi);
changed = true;
// loop again
loopAgain = true;
} else {
usedInPhi.addAll(Arrays.asList(phi.getOp2().getOps()));
}
}
if (labelStmt.phis.size() == 0) {
it.remove();
}
}
}
}
}
for (Iterator<AssignStmt> it = assignStmtList.iterator(); it.hasNext(); ) {
AssignStmt as = it.next();
if (!usedInPhi.contains(as.getOp1())) {
it.remove();
method.stmts.remove(as);
method.locals.remove(as.getOp1());
changed = true;
}
toReplace.put((Local) as.getOp1(), as.getOp2());
}
Cfg.travelMod(method.stmts, new Cfg.TravelCallBack() {
@Override
public Value onAssign(Local v, AssignStmt as) {
return v;
}
@Override
public Value onUse(Local v) {
Value n = toReplace.get(v);
return n == null ? v : n.clone();
}
}, false);
return changed;
}
use of com.googlecode.dex2jar.ir.expr.Value in project dex2jar by pxb1988.
the class RemoveLocalFromSSA method collectPhiObjects.
private Map<Local, PhiObject> collectPhiObjects(List<LabelStmt> phiLabels) {
Map<Local, PhiObject> phis;
phis = new HashMap<>();
for (LabelStmt labelStmt : phiLabels) {
for (AssignStmt as : labelStmt.phis) {
Local local = (Local) as.getOp1();
PhiObject child = getOrCreate(phis, local);
child.isInitByPhi = true;
for (Value op : as.getOp2().getOps()) {
if (op == local) {
continue;
}
PhiObject parent = getOrCreate(phis, (Local) op);
linkPhiObject(parent, child);
}
}
}
return phis;
}
use of com.googlecode.dex2jar.ir.expr.Value in project dex2jar by pxb1988.
the class RemoveLocalFromSSA method transformReportChanged.
@Override
public boolean transformReportChanged(IrMethod method) {
boolean irChanged = false;
List<AssignStmt> assignStmtList = new ArrayList<>();
List<LabelStmt> phiLabels = method.phiLabels;
for (Stmt p = method.stmts.getFirst(); p != null; p = p.getNext()) {
if (p.st == Stmt.ST.ASSIGN) {
AssignStmt as = (AssignStmt) p;
if (as.getOp1().vt == Value.VT.LOCAL && as.getOp2().vt == Value.VT.LOCAL) {
assignStmtList.add(as);
}
}
}
final Map<Local, Local> toReplace = new HashMap<>();
Set<Value> set = new HashSet<>();
boolean changed = true;
while (changed) {
changed = false;
if (removeLoopFromPhi(phiLabels, toReplace)) {
fixReplace(toReplace);
replacePhi(phiLabels, toReplace, set);
}
while (simplePhi(phiLabels, toReplace, set)) {
// remove a = phi(b)
fixReplace(toReplace);
replacePhi(phiLabels, toReplace, set);
}
while (simpleAssign(phiLabels, assignStmtList, toReplace, method.stmts)) {
// remove a=b
fixReplace(toReplace);
replaceAssign(assignStmtList, toReplace);
changed = true;
irChanged = true;
}
replacePhi(phiLabels, toReplace, set);
}
for (Local local : toReplace.keySet()) {
method.locals.remove(local);
irChanged = true;
}
if (toReplace.size() > 0) {
Cfg.travelMod(method.stmts, new Cfg.TravelCallBack() {
@Override
public Value onAssign(Local v, AssignStmt as) {
return v;
}
@Override
public Value onUse(Local v) {
Local n = toReplace.get(v);
return n == null ? v : n;
}
}, true);
}
return irChanged;
}
use of com.googlecode.dex2jar.ir.expr.Value in project dex2jar by pxb1988.
the class RemoveLocalFromSSA method replaceAssign.
static <T extends Value> void replaceAssign(List<AssignStmt> assignStmtList, Map<Local, T> toReplace) {
for (AssignStmt as : assignStmtList) {
Value right = as.getOp2();
T to = toReplace.get(right);
if (to != null) {
as.setOp2(to);
}
}
}
use of com.googlecode.dex2jar.ir.expr.Value in project dex2jar by pxb1988.
the class SSATransformer method replaceLocalsWithSSA.
private void replaceLocalsWithSSA(final IrMethod method) {
final List<Local> locals = method.locals;
locals.clear();
StmtList stmts = method.stmts;
TravelCallBack tcb = new TravelCallBack() {
@Override
public Value onAssign(Local a, AssignStmt as) {
if (a._ls_index < 0) {
locals.add(a);
return a;
}
SSAValue lsv = (SSAValue) a.tag;
Local b = lsv.local;
locals.add(b);
return b;
}
@Override
public Value onUse(Local a) {
if (a._ls_index < 0) {
return a;
}
SSAValue lsv = (SSAValue) a.tag;
Local b = lsv.local;
return b;
}
};
Set<Value> froms = new HashSet<>();
List<LabelStmt> phiLabels = new ArrayList<>();
// 2. we are looking for Phis and insert Phi node to the code
for (Stmt p = stmts.getFirst(); p != null; p = p.getNext()) {
if (p.st == ST.LABEL) {
LabelStmt labelStmt = (LabelStmt) p;
List<AssignStmt> phis = null;
SSAValue[] frame = (SSAValue[]) p.frame;
if (frame != null) {
for (SSAValue v : frame) {
if (v == null || !v.used) {
continue;
}
if (v.parent != null) {
froms.add(v.parent.local);
}
if (v.otherParents != null) {
for (SSAValue parent : v.otherParents) {
froms.add(parent.local);
}
}
froms.remove(v.local);
if (phis == null) {
phis = new ArrayList<>();
}
locals.add(v.local);
phis.add(Stmts.nAssign(v.local, Exprs.nPhi(froms.toArray(new Value[froms.size()]))));
froms.clear();
}
}
labelStmt.phis = phis;
if (phis != null) {
phiLabels.add(labelStmt);
}
} else {
Cfg.travelMod(p, tcb, true);
}
p.frame = null;
}
if (phiLabels.size() > 0) {
method.phiLabels = phiLabels;
}
}
Aggregations