use of com.googlecode.dex2jar.ir.expr.Local in project dex2jar by pxb1988.
the class AggTransformerTest method t001.
@Test
public void t001() {
Local a = addLocal("a");
addStmt(nAssign(a, nNewIntArray(nInt(5))));
addStmt(nReturn(a));
transform();
Assert.assertEquals("only `return new int[5]` should left.", 1, stmts.getSize());
Assert.assertEquals("no local should left", 0, locals.size());
}
use of com.googlecode.dex2jar.ir.expr.Local in project dex2jar by pxb1988.
the class ConstTransformerTest method test02.
@Test
public void test02() {
// test local loop
IrMethod jm = new IrMethod();
Local a = nLocal("a");
Local p = nLocal("p");
Local q = nLocal("q");
jm.locals.add(a);
jm.locals.add(p);
jm.locals.add(q);
jm.stmts.add(nAssign(a, nString("a String")));
jm.stmts.add(nAssign(p, Exprs.nPhi(a, q)));
jm.stmts.add(nAssign(q, Exprs.nPhi(p)));
UnopStmt retStmt = nReturn(q);
jm.stmts.add(retStmt);
new ConstTransformer().transform(jm);
Assert.assertTrue(jm.locals.size() == 3);
Assert.assertTrue(jm.stmts.getSize() == 4);
Assert.assertEquals("a String", ((Constant) retStmt.op.trim()).value);
}
use of com.googlecode.dex2jar.ir.expr.Local in project dex2jar by pxb1988.
the class UnSSATransformer method insertAssignPath.
private void insertAssignPath(StmtList stmts, Stmt from, LabelStmt labelStmt, List<AssignStmt> buff) {
boolean insertBeforeFromStmt;
if (from.exceptionHandlers != null && from.exceptionHandlers.contains(labelStmt)) {
insertBeforeFromStmt = true;
} else {
switch(from.st) {
case GOTO:
case IF:
JumpStmt jumpStmt = (JumpStmt) from;
//
insertBeforeFromStmt = jumpStmt.getTarget().equals(labelStmt);
break;
case TABLE_SWITCH:
case LOOKUP_SWITCH:
insertBeforeFromStmt = true;
break;
default:
insertBeforeFromStmt = false;
break;
}
}
if (insertBeforeFromStmt) {
for (AssignStmt as : buff) {
stmts.insertBefore(from, as);
}
} else {
for (AssignStmt as : buff) {
stmts.insertAfter(from, as);
}
}
LiveV[] frame = (LiveV[]) from.frame;
List<LiveV> newLiveVs = new ArrayList<>(buff.size());
for (AssignStmt as : buff) {
Local left = (Local) as.getOp1();
{
LiveV liveV = new LiveV();
liveV.local = left;
liveV.used = true;
newLiveVs.add(liveV);
}
RegAssign leftRegAssign = (RegAssign) left.tag;
Local right = (Local) as.getOp2();
int toSkip = right._ls_index;
for (int i = 0; i < frame.length; i++) {
if (i == toSkip) {
continue;
}
LiveV v = frame[i];
if (v != null && v.used) {
RegAssign assign = (RegAssign) v.local.tag;
assign.excludes.add(leftRegAssign);
leftRegAssign.excludes.add(assign);
}
}
for (AssignStmt as2 : buff) {
RegAssign assign = (RegAssign) ((Local) as2.getOp1()).tag;
assign.excludes.add(leftRegAssign);
leftRegAssign.excludes.add(assign);
}
}
LiveV[] newFrame = new LiveV[frame.length + newLiveVs.size()];
System.arraycopy(frame, 0, newFrame, 0, frame.length);
for (int i = 0; i < newLiveVs.size(); i++) {
newFrame[i + frame.length] = newLiveVs.get(i);
}
}
use of com.googlecode.dex2jar.ir.expr.Local in project dex2jar by pxb1988.
the class UnSSATransformer method transform.
@Override
public void transform(IrMethod method) {
if (method.phiLabels == null || method.phiLabels.size() == 0) {
return;
}
// 1. Live analyze the method,
// a. remove Phi,
// b. record parameter reference
LiveA liveA = new LiveA(method);
liveA.analyze();
genRegGraph(method, liveA);
// 2. insert x=y
fixPhi(method, method.phiLabels);
insertAssignPath(method, method.phiLabels);
// 4. clean up
for (Local local : method.locals) {
local.tag = null;
}
for (Stmt stmt : method.stmts) {
stmt.frame = null;
}
for (LabelStmt labelStmt : method.phiLabels) {
labelStmt.phis = null;
}
method.phiLabels = null;
}
use of com.googlecode.dex2jar.ir.expr.Local in project dex2jar by pxb1988.
the class UnSSATransformer method fixPhi.
/**
* there is somewhere both a and its possible x is both live, insert a=x, will change the meaning for example
*
* <pre>
* L0:
* a = phi(b, ... )
* b = 234;
* if a>0 goto L0: // a, b both live here
* ...
* </pre>
*
* after insert a=b before the if stmt, the programe change to
*
* <pre>
* L0:
* // a = phi(b, ... )
* b = 234;
* a = b
* if a>0 goto L0:
* ...
* </pre>
*
* the solution is by introduce a new local x
*
* <pre>
* L0:
* x = phi(b, ... )
* a = x
* b = 234;
* if a>0 goto L0: // a, b both live here
* ...
* </pre>
*
* insert x = b is ok now
*
* <pre>
* L0:
* // x = phi(b, ... )
* a = x
* b = 234;
* x = b
* if a>0 goto L0: // a, b both live here
* ...
* </pre>
*
* @param phiLabels
*/
private void fixPhi(IrMethod method, Collection<LabelStmt> phiLabels) {
for (LabelStmt labelStmt : phiLabels) {
List<AssignStmt> phis = (List<AssignStmt>) labelStmt.phis;
for (AssignStmt phi : phis) {
Local a = (Local) phi.getOp1();
PhiExpr b = (PhiExpr) phi.getOp2();
boolean introduceNewLocal = false;
RegAssign aReg = (RegAssign) a.tag;
for (Value op : b.getOps()) {
RegAssign bReg = (RegAssign) ((Local) op).tag;
if (aReg.excludes.contains(bReg)) {
introduceNewLocal = true;
break;
}
}
if (introduceNewLocal) {
Local newLocal = (Local) a.clone();
if (DEBUG) {
newLocal.debugName = "x" + method.locals.size();
}
phi.op1 = newLocal;
RegAssign newRegAssign = new RegAssign();
newLocal.tag = newRegAssign;
method.locals.add(newLocal);
Stmt newAssigStmt = Stmts.nAssign(a, newLocal);
Stmt next = labelStmt.getNext();
if (next != null && next.st == ST.IDENTITY && next.getOp2().vt == VT.EXCEPTION_REF) {
// it's a handler, insert after the exception ref
method.stmts.insertAfter(next, newAssigStmt);
} else {
method.stmts.insertAfter(labelStmt, newAssigStmt);
}
LiveV[] frame = (LiveV[]) labelStmt.frame;
if (DEBUG) {
LiveV[] copy = frame.clone();
LiveV n = new LiveV();
n.local = a;
n.used = true;
copy[a._ls_index] = new LiveV();
newAssigStmt.frame = copy;
}
LiveV thePhi = frame[a._ls_index];
thePhi.local = newLocal;
for (LiveV v : frame) {
if (v != null && v.used) {
RegAssign s = (RegAssign) v.local.tag;
s.excludes.add(newRegAssign);
newRegAssign.excludes.add(s);
}
}
}
}
}
}
Aggregations