修改IR结构

--HG--
branch : 0.0.9.x
This commit is contained in:
Panxiaobo 2011-07-03 17:57:54 +08:00
parent 627987347a
commit 346e1254b0
31 changed files with 297 additions and 384 deletions

View File

@ -2,7 +2,9 @@ package com.googlecode.dex2jar.ir;
import org.objectweb.asm.Type;
public class Constant extends Value {
import com.googlecode.dex2jar.ir.Value.E0Expr;
public class Constant extends E0Expr {
public static Object Null = new Object();
public static Type STRING = Type.getType(String.class);

View File

@ -0,0 +1,5 @@
package com.googlecode.dex2jar.ir;
public enum ET {
E0, E1, E2, En
}

View File

@ -2,7 +2,9 @@ package com.googlecode.dex2jar.ir;
import org.objectweb.asm.Type;
public class Local extends Value {
import com.googlecode.dex2jar.ir.Value.E0Expr;
public class Local extends E0Expr {
public Type type;
public String name;

View File

@ -2,18 +2,58 @@ package com.googlecode.dex2jar.ir;
public abstract class Value {
public static enum VT {
ADD, AND, ARRAY, CAST, CMP, CMPG, CMPL, DIV, EQ, FIELD, GE, GT, INSTANCEOF, INVOKE_INTERFACE, LE, LENGTH, LT, MUL, NE, NEG, NEW_ARRAY, NEW_MUTI_ARRAY, OR, REM, SHL, SHR, INVOKE_SPECIAL, //
INVOKE_STATIC, SUB, USHR, INVOKE_VIRTUAL, INVOKE_NEW, XOR, LOCAL, CONSTANT, THIS_REF, PARAMETER_REF, EXCEPTION_REF, NOT
}
final public VT vt;
final public ET et;
/**
* @param vt
*/
public Value(VT vt) {
public Value(VT vt, ET et) {
super();
this.vt = vt;
this.et = et;
}
public static abstract class E0Expr extends Value {
public E0Expr(VT vt) {
super(vt, ET.E0);
}
}
public static abstract class E1Expr extends Value {
public ValueBox op;
public E1Expr(VT vt, ValueBox op) {
super(vt, ET.E1);
this.op = op;
}
}
public static abstract class E2Expr extends Value {
public ValueBox op1;
public ValueBox op2;
public E2Expr(VT vt, ValueBox op1, ValueBox op2) {
super(vt, ET.E2);
this.op1 = op1;
this.op2 = op2;
}
}
public static abstract class EnExpr extends Value {
public ValueBox[] ops;
public EnExpr(VT vt, ValueBox[] ops) {
super(vt, ET.En);
this.ops = ops;
}
}
}

View File

@ -1,24 +1,20 @@
package com.googlecode.dex2jar.ir.expr;
import com.googlecode.dex2jar.ir.Value;
import com.googlecode.dex2jar.ir.Value.E2Expr;
import com.googlecode.dex2jar.ir.ValueBox;
public class ArrayExpr extends Value {
public ValueBox base;
public ValueBox index;
public class ArrayExpr extends E2Expr {
public ArrayExpr() {
super(VT.ARRAY);
super(VT.ARRAY, null, null);
}
public ArrayExpr(Value base, Value index) {
super(VT.ARRAY);
this.base = new ValueBox(base);
this.index = new ValueBox(index);
super(VT.ARRAY, new ValueBox(base), new ValueBox(index));
}
public String toString() {
return base + "[" + index + "]";
return op1 + "[" + op2 + "]";
}
}

View File

@ -1,17 +1,13 @@
package com.googlecode.dex2jar.ir.expr;
import com.googlecode.dex2jar.ir.Value;
import com.googlecode.dex2jar.ir.Value.E2Expr;
import com.googlecode.dex2jar.ir.ValueBox;
public class BinopExpr extends Value {
public ValueBox op1;
public ValueBox op2;
public class BinopExpr extends E2Expr {
public BinopExpr(VT type, Value op1, Value op2) {
super(type);
this.op1 = new ValueBox(op1);
this.op2 = new ValueBox(op2);
super(type, new ValueBox(op1), new ValueBox(op2));
}
public String toString() {

View File

@ -1,24 +0,0 @@
package com.googlecode.dex2jar.ir.expr;
import org.objectweb.asm.Type;
import com.googlecode.dex2jar.ir.Value;
import com.googlecode.dex2jar.ir.ValueBox;
public class CastExpr extends Value {
public Type castType;
public ValueBox op;
public CastExpr(Value value, Type type) {
super(VT.CAST);
this.castType = type;
this.op = new ValueBox(value);
}
public String toString() {
return "((" + castType.getClassName() + ")" + op + ")";
}
}

View File

@ -9,7 +9,11 @@ import com.googlecode.dex2jar.ir.ValueBox;
public final class Exprs {
private static ValueBox[] box(Value[] v) {
public static ValueBox box(Value value) {
return new ValueBox(value);
}
public static ValueBox[] box(Value[] v) {
if (v == null) {
return new ValueBox[0];
}
@ -32,8 +36,8 @@ public final class Exprs {
return new ArrayExpr(base, index);
}
public static CastExpr nCast(Value obj, Type type) {
return new CastExpr(obj, type);
public static TypeExpr nCast(Value obj, Type type) {
return new TypeExpr(obj, type);
}
public static BinopExpr nCmp(Value a, Value b) {
@ -56,8 +60,8 @@ public final class Exprs {
return new BinopExpr(VT.EQ, a, b);
}
public static TypeRefExpr nExceptionRef(Type type) {
return new TypeRefExpr(VT.EXCEPTION_REF, type, -1);
public static RefExpr nExceptionRef(Type type) {
return new RefExpr(VT.EXCEPTION_REF, type, -1);
}
public static FieldExpr nField(Value object, Type ownerType, String fieldName, Type fieldType) {
@ -72,8 +76,8 @@ public final class Exprs {
return new BinopExpr(VT.GT, a, b);
}
public static InstanceOfExpr nInstanceOf(Value value, Type type) {
return new InstanceOfExpr(value, type);
public static TypeExpr nInstanceOf(Value value, Type type) {
return new TypeExpr(value, type);
}
public static InvokeExpr nInvokeInterface(Value[] regs, Type owner, String name, Type[] argmentTypes,
@ -137,20 +141,20 @@ public final class Exprs {
// return new NewExpr(type);
// }
public static NewArrayExpr nNewArray(Type elementType, Value size) {
return new NewArrayExpr(elementType, size);
public static TypeExpr nNewArray(Type elementType, Value size) {
return new TypeExpr(size, elementType);
}
public static NewMutiArrayExpr nNewMutiArray(Type base, int dim, Value[] sizes) {
return new NewMutiArrayExpr(base, dim, sizes);
return new NewMutiArrayExpr(base, dim, box(sizes));
}
public static BinopExpr nOr(Value a, Value b) {
return new BinopExpr(VT.OR, a, b);
}
public static TypeRefExpr nParameterRef(Type type, int index) {
return new TypeRefExpr(VT.PARAMETER_REF, type, index);
public static RefExpr nParameterRef(Type type, int index) {
return new RefExpr(VT.PARAMETER_REF, type, index);
}
public static BinopExpr nRem(Value a, Value b) {
@ -173,8 +177,8 @@ public final class Exprs {
return new BinopExpr(VT.SUB, a, b);
}
public static TypeRefExpr nThisRef(Type type) {
return new TypeRefExpr(VT.THIS_REF, type, -1);
public static RefExpr nThisRef(Type type) {
return new RefExpr(VT.THIS_REF, type, -1);
}
public static BinopExpr nUshr(Value a, Value b) {

View File

@ -2,26 +2,25 @@ package com.googlecode.dex2jar.ir.expr;
import org.objectweb.asm.Type;
import com.googlecode.dex2jar.ir.Value;
import com.googlecode.dex2jar.ir.Value.E1Expr;
import com.googlecode.dex2jar.ir.ValueBox;
public class FieldExpr extends Value {
public class FieldExpr extends E1Expr {
public String fieldName;
public Type fieldType;
public Type fieldOwnerType;
public ValueBox object;
public ValueBox op;
public FieldExpr(ValueBox object, Type ownerType, String fieldName, Type fieldType) {
super(VT.FIELD);
this.object = object;
super(VT.FIELD,object);
this.fieldType = fieldType;
this.fieldName = fieldName;
this.fieldOwnerType = ownerType;
}
public String toString() {
return (object == null ? fieldOwnerType.getClassName() : object) + "." + fieldName;
return (op == null ? fieldOwnerType.getClassName() : op) + "." + fieldName;
}
}

View File

@ -1,23 +0,0 @@
package com.googlecode.dex2jar.ir.expr;
import org.objectweb.asm.Type;
import com.googlecode.dex2jar.ir.Value;
import com.googlecode.dex2jar.ir.ValueBox;
public class InstanceOfExpr extends Value {
public ValueBox op;
public Type instanceType;
public InstanceOfExpr(Value op, Type type2) {
super(VT.INSTANCEOF);
this.op = new ValueBox(op);
instanceType = type2;
}
public String toString() {
return "(" + op + " instanceof " + instanceType.getClassName() + ")";
}
}

View File

@ -2,25 +2,22 @@ package com.googlecode.dex2jar.ir.expr;
import org.objectweb.asm.Type;
import com.googlecode.dex2jar.ir.Value;
import com.googlecode.dex2jar.ir.Value.EnExpr;
import com.googlecode.dex2jar.ir.ValueBox;
public class InvokeExpr extends Value {
public class InvokeExpr extends EnExpr {
public Type[] argmentTypes;
public ValueBox args[];
public String methodName;
public Type methodOwnerType;
public Type methodReturnType;
public InvokeExpr(VT type, ValueBox[] args, Type ownerType, String methodName, Type[] argmentTypes, Type returnType) {
super(type);
super(type, args);
this.methodReturnType = returnType;
this.methodName = methodName;
this.methodOwnerType = ownerType;
this.argmentTypes = argmentTypes;
this.args = args;
}
public String toString() {
@ -29,18 +26,18 @@ public class InvokeExpr extends Value {
if (super.vt == VT.INVOKE_NEW) {
sb.append("new ").append(methodOwnerType.getClassName()).append('(');
} else {
sb.append(super.vt == VT.INVOKE_STATIC ? methodOwnerType.getClassName() : args[i]).append('.')
sb.append(super.vt == VT.INVOKE_STATIC ? methodOwnerType.getClassName() : ops[i]).append('.')
.append(this.methodName).append('(');
i++;
}
boolean first = true;
for (; i < args.length; i++) {
for (; i < ops.length; i++) {
if (first) {
first = false;
} else {
sb.append(',');
}
sb.append(args[i]);
sb.append(ops[i]);
}
sb.append(')');
return sb.toString();

View File

@ -1,23 +0,0 @@
package com.googlecode.dex2jar.ir.expr;
import org.objectweb.asm.Type;
import com.googlecode.dex2jar.ir.Value;
import com.googlecode.dex2jar.ir.ValueBox;
public class NewArrayExpr extends Value {
public ValueBox size;
public Type baseType;
public NewArrayExpr(Type type, Value size) {
super(VT.NEW_ARRAY);
this.size = new ValueBox(size);
this.baseType = type;
}
public String toString() {
return "new " + baseType.getClassName() + "[" + size + "]";
}
}

View File

@ -2,31 +2,26 @@ package com.googlecode.dex2jar.ir.expr;
import org.objectweb.asm.Type;
import com.googlecode.dex2jar.ir.Value;
import com.googlecode.dex2jar.ir.Value.EnExpr;
import com.googlecode.dex2jar.ir.ValueBox;
public class NewMutiArrayExpr extends Value {
public class NewMutiArrayExpr extends EnExpr {
public Type baseType;
public int dimension;
public ValueBox[] sizes;
public NewMutiArrayExpr(Type base, int dimension, Value[] sizes) {
super(VT.NEW_MUTI_ARRAY);
public NewMutiArrayExpr(Type base, int dimension, ValueBox[] sizes) {
super(VT.NEW_MUTI_ARRAY, sizes);
this.baseType = base;
this.dimension = dimension;
this.sizes = new ValueBox[sizes.length];
for (int i = 0; i < sizes.length; i++) {
this.sizes[i] = new ValueBox(sizes[i]);
}
this.ops = new ValueBox[sizes.length];
}
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("new ").append(baseType);
for (int i = 0; i < dimension; i++) {
sb.append('[').append(sizes[i]).append(']');
sb.append('[').append(ops[i]).append(']');
}
return sb.toString();
}

View File

@ -2,12 +2,12 @@ package com.googlecode.dex2jar.ir.expr;
import org.objectweb.asm.Type;
import com.googlecode.dex2jar.ir.Value;
import com.googlecode.dex2jar.ir.Value.E0Expr;
public class TypeRefExpr extends Value {
public class RefExpr extends E0Expr {
public TypeRefExpr(VT vt, Type refType, int index) {
public RefExpr(VT vt, Type refType, int index) {
super(vt);
this.parameterIndex = index;
}

View File

@ -0,0 +1,31 @@
package com.googlecode.dex2jar.ir.expr;
import org.objectweb.asm.Type;
import com.googlecode.dex2jar.ir.Value;
import com.googlecode.dex2jar.ir.Value.E1Expr;
import com.googlecode.dex2jar.ir.ValueBox;
public class TypeExpr extends E1Expr {
public Type type;
public TypeExpr(Value value, Type type) {
super(VT.CAST, new ValueBox(value));
this.type = type;
}
public String toString() {
switch (super.vt) {
case CAST:
return "((" + type.getClassName() + ")" + op + ")";
case INSTANCEOF:
return "(" + op + " instanceof " + type.getClassName() + ")";
case NEW_ARRAY:
return "new " + type.getClassName() + "[" + op + "]";
}
return "UNKNOW";
}
}

View File

@ -1,19 +1,17 @@
package com.googlecode.dex2jar.ir.expr;
import com.googlecode.dex2jar.ir.Value;
import com.googlecode.dex2jar.ir.Value.E1Expr;
import com.googlecode.dex2jar.ir.ValueBox;
public class UnopExpr extends Value {
public ValueBox op;
public class UnopExpr extends E1Expr {
/**
* @param type
* @param value
*/
public UnopExpr(VT type, Value value) {
super(type);
this.op = new ValueBox(value);
super(type, new ValueBox(value));
}
public String toString() {

View File

@ -1,38 +1,20 @@
package com.googlecode.dex2jar.ir.stmt;
import java.util.Map;
import com.googlecode.dex2jar.ir.Value;
import com.googlecode.dex2jar.ir.ValueBox;
import com.googlecode.dex2jar.ir.stmt.Stmt.E2Stmt;
public class AssignStmt extends Stmt {
public ValueBox left;
public ValueBox right;
public class AssignStmt extends E2Stmt {
public AssignStmt(ST type, ValueBox left, ValueBox right) {
super(type);
this.left = left;
this.right = right;
}
public AssignStmt(ST type, Value left, Value right) {
super(type);
this.left = new ValueBox(left);
this.right = new ValueBox(right);
}
@Override
public Stmt clone(Map<LabelStmt, LabelStmt> map) {
return new AssignStmt(st, left.value, right.value);
super(type, left, right);
}
public String toString() {
switch (st) {
case ASSIGN:
return left + " = " + right;
return op1 + " = " + op2;
case IDENTITY:
return left + " := " + right;
return op1 + " := " + op2;
}
return super.toString();
}

View File

@ -1,20 +1,12 @@
package com.googlecode.dex2jar.ir.stmt;
import java.util.Map;
import com.googlecode.dex2jar.ir.Value;
import com.googlecode.dex2jar.ir.ValueBox;
import com.googlecode.dex2jar.ir.stmt.Stmt.E1Stmt;
public class JumpStmt extends E1Stmt {
public class JumpStmt extends Stmt {
public ValueBox condition;
public LabelStmt target;
private JumpStmt(ST type) {
super(type);
}
/**
* GOTO
*
@ -22,8 +14,7 @@ public class JumpStmt extends Stmt {
* @param target
*/
public JumpStmt(ST type, LabelStmt target) {
this(type);
this.target = target;
this(type, null, target);
}
/**
@ -33,14 +24,9 @@ public class JumpStmt extends Stmt {
* @param condition
* @param target
*/
public JumpStmt(ST type, Value condition, LabelStmt target) {
this(type, target);
this.condition = new ValueBox(condition);
}
@Override
public Stmt clone(Map<LabelStmt, LabelStmt> map) {
return new JumpStmt(st, condition.value, (LabelStmt) target.clone(map));
public JumpStmt(ST type, ValueBox condition, LabelStmt target) {
super(type, condition);
this.target = target;
}
public String toString() {
@ -48,7 +34,7 @@ public class JumpStmt extends Stmt {
case GOTO:
return "GOTO " + target;
case IF:
return "if " + condition + " GOTO " + target;
return "if " + op + " GOTO " + target;
}
return super.toString();
}

View File

@ -1,10 +1,10 @@
package com.googlecode.dex2jar.ir.stmt;
import java.util.Map;
import org.objectweb.asm.Label;
public class LabelStmt extends Stmt {
import com.googlecode.dex2jar.ir.stmt.Stmt.E0Stmt;
public class LabelStmt extends E0Stmt {
public LabelStmt(Label label) {
super(ST.LABEL);
@ -13,16 +13,6 @@ public class LabelStmt extends Stmt {
public Label label;
@Override
public Stmt clone(Map<LabelStmt, LabelStmt> map) {
LabelStmt clone = map.get(this);
if (clone == null) {
clone = new LabelStmt(new Label());
map.put(this, clone);
}
return clone;
}
public String toString() {
return label + ":";
}

View File

@ -1,50 +1,23 @@
package com.googlecode.dex2jar.ir.stmt;
import java.util.Map;
import com.googlecode.dex2jar.ir.Value;
import com.googlecode.dex2jar.ir.ValueBox;
import com.googlecode.dex2jar.ir.stmt.Stmt.E1Stmt;
public class LookupSwitchStmt extends Stmt {
public class LookupSwitchStmt extends E1Stmt {
public LabelStmt defaultTarget;
public ValueBox key;
public Value[] lookupValues;
public int[] lookupValues;
public LabelStmt[] targets;
public LookupSwitchStmt() {
super(ST.LOOKUP_SWITCH);
}
public LookupSwitchStmt(Value key, Value[] lookupValues, LabelStmt[] targets, LabelStmt defaultTarget) {
super(ST.LOOKUP_SWITCH);
this.key = new ValueBox(key);
public LookupSwitchStmt(ValueBox key, int[] lookupValues, LabelStmt[] targets, LabelStmt defaultTarget) {
super(ST.LOOKUP_SWITCH, key);
this.lookupValues = lookupValues;
this.targets = targets;
this.defaultTarget = defaultTarget;
}
@Override
public Stmt clone(Map<LabelStmt, LabelStmt> map) {
LabelStmt[] cloneTargets;
Value[] cloneValue;
if (targets != null) {
cloneValue = new Value[lookupValues.length];
cloneTargets = new LabelStmt[targets.length];
for (int i = 0; i < targets.length; i++) {
cloneTargets[i] = (LabelStmt) targets[i].clone(map);
cloneValue[i] = lookupValues[i];
}
} else {
cloneTargets = null;
cloneValue = null;
}
return new LookupSwitchStmt(key.value, cloneValue, cloneTargets, (LabelStmt) defaultTarget.clone(map));
}
public String toString() {
StringBuilder sb = new StringBuilder("switch(").append(key).append(") {");
StringBuilder sb = new StringBuilder("switch(").append(op).append(") {");
for (int i = 0; i < lookupValues.length; i++) {
sb.append("case ").append(lookupValues[i]).append(": GOTO ").append(targets[i].label).append(";");

View File

@ -1,18 +1,13 @@
package com.googlecode.dex2jar.ir.stmt;
import java.util.Map;
import com.googlecode.dex2jar.ir.stmt.Stmt.E0Stmt;
public class NopStmt extends Stmt {
public class NopStmt extends E0Stmt {
public NopStmt() {
super(ST.NOP);
}
@Override
public Stmt clone(Map<LabelStmt, LabelStmt> map) {
return new NopStmt();
}
public String toString() {
return "NOP";
}

View File

@ -1,18 +1,13 @@
package com.googlecode.dex2jar.ir.stmt;
import java.util.Map;
import com.googlecode.dex2jar.ir.stmt.Stmt.E0Stmt;
public class ReturnVoidStmt extends Stmt {
public class ReturnVoidStmt extends E0Stmt {
public ReturnVoidStmt() {
super(ST.RETURN_VOID);
}
@Override
public Stmt clone(Map<LabelStmt, LabelStmt> map) {
return new ReturnVoidStmt();
}
@Override
public String toString() {
return "return";

View File

@ -1,9 +1,9 @@
package com.googlecode.dex2jar.ir.stmt;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import com.googlecode.dex2jar.ir.ET;
import com.googlecode.dex2jar.ir.ValueBox;
public abstract class Stmt {
@ -23,13 +23,13 @@ public abstract class Stmt {
/* default */Stmt pre;
public final ST st;
public final ET et;
public Stmt(ST type) {
public Stmt(ST type, ET et) {
this.st = type;
this.et = et;
}
public abstract Stmt clone(Map<LabelStmt, LabelStmt> map);
public final Stmt getNext() {
return next;
}
@ -38,4 +38,39 @@ public abstract class Stmt {
return pre;
}
public static abstract class E0Stmt extends Stmt {
public E0Stmt(ST type) {
super(type, ET.E0);
}
}
public static abstract class E1Stmt extends Stmt {
public ValueBox op;
public E1Stmt(ST type, ValueBox op) {
super(type, ET.E1);
this.op = op;
}
}
public static abstract class E2Stmt extends Stmt {
public ValueBox op1;
public ValueBox op2;
public E2Stmt(ST type, ValueBox op1, ValueBox op2) {
super(type, ET.E2);
this.op1 = op1;
this.op2 = op2;
}
}
public static abstract class EnStmt extends Stmt {
public ValueBox[] ops;
public EnStmt(ST type, ValueBox[] ops) {
super(type, ET.E1);
this.ops = ops;
}
}
}

View File

@ -1,5 +1,7 @@
package com.googlecode.dex2jar.ir.stmt;
import static com.googlecode.dex2jar.ir.expr.Exprs.box;
import org.objectweb.asm.Label;
import com.googlecode.dex2jar.ir.Value;
@ -11,9 +13,9 @@ public final class Stmts {
public static AssignStmt nAssign(ValueBox left, ValueBox right) {
return new AssignStmt(ST.ASSIGN, left, right);
}
public static AssignStmt nAssign(Value left, Value right) {
return new AssignStmt(ST.ASSIGN, left, right);
return new AssignStmt(ST.ASSIGN, box(left), box(right));
}
public static JumpStmt nGoto(LabelStmt target) {
@ -21,25 +23,27 @@ public final class Stmts {
}
public static AssignStmt nIdentity(Value local, Value identityRef) {
return new AssignStmt(ST.IDENTITY, local, identityRef);
return new AssignStmt(ST.IDENTITY, box(local), box(identityRef));
}
public static JumpStmt nIf(Value a, LabelStmt target) {
return new JumpStmt(ST.IF, a, target);
return new JumpStmt(ST.IF, box(a), target);
}
public static LabelStmt nLabel() {
return new LabelStmt(new Label());
}
public static LabelStmt nLabel(Label label) {
return new LabelStmt(label);
}
public static UnopStmt nLock(Value op) {
return new UnopStmt(ST.LOCK, op);
return new UnopStmt(ST.LOCK, box(op));
}
public static LookupSwitchStmt nLookupSwitch(Value key, Value[] lookupValues, LabelStmt[] targets, LabelStmt target) {
return new LookupSwitchStmt(key, lookupValues, targets, target);
public static LookupSwitchStmt nLookupSwitch(Value key, int[] lookupValues, LabelStmt[] targets, LabelStmt target) {
return new LookupSwitchStmt(box(key), lookupValues, targets, target);
}
public static NopStmt nNop() {
@ -47,7 +51,7 @@ public final class Stmts {
}
public static UnopStmt nReturn(Value op) {
return new UnopStmt(ST.RETURN, op);
return new UnopStmt(ST.RETURN, box(op));
}
public static ReturnVoidStmt nReturnVoid() {
@ -60,11 +64,11 @@ public final class Stmts {
}
public static UnopStmt nThrow(Value op) {
return new UnopStmt(ST.THROW, op);
return new UnopStmt(ST.THROW, box(op));
}
public static UnopStmt nUnLock(Value op) {
return new UnopStmt(ST.UNLOCK, op);
return new UnopStmt(ST.UNLOCK, box(op));
}
private Stmts() {

View File

@ -1,49 +1,29 @@
package com.googlecode.dex2jar.ir.stmt;
import java.util.Map;
import com.googlecode.dex2jar.ir.Value;
import com.googlecode.dex2jar.ir.ValueBox;
import com.googlecode.dex2jar.ir.stmt.Stmt.E1Stmt;
public class TableSwitchStmt extends Stmt {
public class TableSwitchStmt extends E1Stmt {
public LabelStmt defaultTarget;
public ValueBox key;
public int lowIndex, highIndex;
public LabelStmt[] targets;
public TableSwitchStmt() {
super(ST.TABLE_SWITCH);
super(ST.TABLE_SWITCH, null);
}
public TableSwitchStmt(Value key, int lowIndex, int highIndex, LabelStmt[] targets, LabelStmt defaultTarget) {
super(ST.TABLE_SWITCH);
this.key = new ValueBox(key);
super(ST.TABLE_SWITCH, new ValueBox(key));
this.lowIndex = lowIndex;
this.highIndex = highIndex;
this.targets = targets;
this.defaultTarget = defaultTarget;
}
@Override
public Stmt clone(Map<LabelStmt, LabelStmt> map) {
LabelStmt[] cloneTargets;
if (targets != null) {
cloneTargets = new LabelStmt[targets.length];
for (int i = 0; i < targets.length; i++) {
cloneTargets[i] = (LabelStmt) targets[i].clone(map);
}
} else {
cloneTargets = null;
}
return new TableSwitchStmt(key.value, lowIndex, highIndex, cloneTargets, (LabelStmt) defaultTarget.clone(map));
}
public String toString() {
StringBuilder sb = new StringBuilder("switch(").append(key).append(") {");
StringBuilder sb = new StringBuilder("switch(").append(op).append(") {");
for (int i = 0; i < targets.length; i++) {
sb.append("case ").append(lowIndex + i).append(": GOTO ").append(targets[i].label).append(";");

View File

@ -1,23 +1,12 @@
package com.googlecode.dex2jar.ir.stmt;
import java.util.Map;
import com.googlecode.dex2jar.ir.Value;
import com.googlecode.dex2jar.ir.ValueBox;
import com.googlecode.dex2jar.ir.stmt.Stmt.E1Stmt;
public class UnopStmt extends E1Stmt {
public class UnopStmt extends Stmt {
public ValueBox op;
public UnopStmt(ST type, Value op) {
super(type);
this.op = new ValueBox(op);
}
@Override
public Stmt clone(Map<LabelStmt, LabelStmt> map) {
return new UnopStmt(st, op.value);
public UnopStmt(ST type, ValueBox op) {
super(type, op);
}
public String toString() {

View File

@ -15,13 +15,11 @@ import com.googlecode.dex2jar.ir.Value.VT;
import com.googlecode.dex2jar.ir.ValueBox;
import com.googlecode.dex2jar.ir.expr.ArrayExpr;
import com.googlecode.dex2jar.ir.expr.BinopExpr;
import com.googlecode.dex2jar.ir.expr.CastExpr;
import com.googlecode.dex2jar.ir.expr.Exprs;
import com.googlecode.dex2jar.ir.expr.FieldExpr;
import com.googlecode.dex2jar.ir.expr.InstanceOfExpr;
import com.googlecode.dex2jar.ir.expr.InvokeExpr;
import com.googlecode.dex2jar.ir.expr.NewArrayExpr;
import com.googlecode.dex2jar.ir.expr.NewMutiArrayExpr;
import com.googlecode.dex2jar.ir.expr.TypeExpr;
import com.googlecode.dex2jar.ir.expr.UnopExpr;
import com.googlecode.dex2jar.ir.stmt.AssignStmt;
import com.googlecode.dex2jar.ir.stmt.JumpStmt;
@ -48,34 +46,35 @@ public class LocalRemover implements Transformer {
}
switch (st.st) {
case ASSIGN:
case IDENTITY:
AssignStmt as = (AssignStmt) st;
if (as.left.value.vt == VT.LOCAL) {
Local aLeft = (Local) as.left.value;
if (as.right.value.vt == VT.CONSTANT) {// remove new
Constant c = (Constant) as.right.value;
if (as.op1.value.vt == VT.LOCAL) {
Local aLeft = (Local) as.op1.value;
if (as.op2.value.vt == VT.CONSTANT) {// remove new
Constant c = (Constant) as.op2.value;
if (NEW_TYPE.equals(c.type)) {
list.remove(st);
for (Iterator<AssignStmt> it = je._ls_inits.iterator(); it.hasNext();) {
AssignStmt stmt = it.next();
InvokeExpr ie = (InvokeExpr) stmt.right.value;
if (ie.args[0].value == aLeft) {
InvokeExpr ie = (InvokeExpr) stmt.op2.value;
if (ie.ops[0].value == aLeft) {
it.remove();
ValueBox[] vb = new ValueBox[ie.args.length - 1];
System.arraycopy(ie.args, 1, vb, 0, vb.length);
AssignStmt nas = Stmts.nAssign(as.left,
ValueBox[] vb = new ValueBox[ie.ops.length - 1];
System.arraycopy(ie.ops, 1, vb, 0, vb.length);
AssignStmt nas = Stmts.nAssign(as.op1,
new ValueBox(Exprs.nInvokeNew(vb, ie.argmentTypes, ie.methodOwnerType)));
list.replace(stmt, nas);
aLeft._ls_read_count--;
orderList.set(orderList.indexOf(stmt), nas);
}
}
continue;
}
continue;
}
if (aLeft._ls_write_count == 1) {
switch (as.right.value.vt) {
switch (as.op2.value.vt) {
case LOCAL: {
Local b = (Local) as.right.value;
Local b = (Local) as.op2.value;
b._ls_read_count += aLeft._ls_read_count - 1;
je.locals.remove(aLeft);
aLeft._ls_vb.value = b;
@ -84,7 +83,7 @@ public class LocalRemover implements Transformer {
continue;
}
case CONSTANT: {
as.left.value = as.right.value;
as.op1.value = as.op2.value;
je.locals.remove(aLeft);
list.remove(st);
orderList.set(p, null);
@ -127,7 +126,7 @@ public class LocalRemover implements Transformer {
vbs.clear();
tmp.clear();
AssignStmt as = (AssignStmt) pre;
Local preLocal = (Local) as.left.value;
Local preLocal = (Local) as.op1.value;
execStmt(vbs, st, preLocal);
for (ValueBox vb : vbs) {
switch (vb.value.vt) {
@ -142,13 +141,13 @@ public class LocalRemover implements Transformer {
while (!tmp.isEmpty()) {
ValueBox vb = tmp.pop();
if (vb.value == preLocal) {
vb.value = as.right.value;
vb.value = as.op2.value;
list.remove(as);
je.locals.remove(preLocal);
pre = st.getPre();
if (pre != null && canRemove(pre)) {
as = (AssignStmt) pre;
preLocal = (Local) as.left.value;
preLocal = (Local) as.op1.value;
} else {
break;
}
@ -163,11 +162,12 @@ public class LocalRemover implements Transformer {
private static boolean canRemove(Stmt pre) {
switch (pre.st) {
case ASSIGN:
case IDENTITY:
AssignStmt as = (AssignStmt) pre;
if (as.left.value.vt == VT.LOCAL) {
Local aLeft = (Local) as.left.value;
if (as.op1.value.vt == VT.LOCAL) {
Local aLeft = (Local) as.op1.value;
if (aLeft._ls_write_count == 1 && aLeft._ls_read_count == 1) {
switch (as.right.value.vt) {
switch (as.op2.value.vt) {
case THIS_REF:
case PARAMETER_REF:
case EXCEPTION_REF:
@ -192,23 +192,24 @@ public class LocalRemover implements Transformer {
switch (st.st) {
case ASSIGN:
case IDENTITY:
AssignStmt as = (AssignStmt) st;
if (as.left.value.vt != VT.LOCAL) {
execValue(stack, as.left, local);
if (as.op1.value.vt != VT.LOCAL) {
execValue(stack, as.op1, local);
}
execValue(stack, as.right, local);
execValue(stack, as.op2, local);
break;
case IF:
JumpStmt js = (JumpStmt) st;
execValue(stack, js.condition, local);
execValue(stack, js.op, local);
break;
case LOOKUP_SWITCH:
LookupSwitchStmt lss = (LookupSwitchStmt) st;
execValue(stack, lss.key, local);
execValue(stack, lss.op, local);
break;
case TABLE_SWITCH:
TableSwitchStmt tss = (TableSwitchStmt) st;
execValue(stack, tss.key, local);
execValue(stack, tss.op, local);
break;
case RETURN:
case LOCK:
@ -261,17 +262,17 @@ public class LocalRemover implements Transformer {
}
case ARRAY:
ArrayExpr ae = (ArrayExpr) toReplace;
stack.add(ae.base);
stack.add(ae.index);
stack.add(ae.op1);
stack.add(ae.op2);
break;
case FIELD:
FieldExpr fe = (FieldExpr) toReplace;
if (fe.object != null) {// not a static field
stack.add(fe.object);
if (fe.op != null) {// not a static field
stack.add(fe.op);
}
break;
case CAST:
CastExpr ce = (CastExpr) toReplace;
TypeExpr ce = (TypeExpr) toReplace;
stack.add(ce.op);
break;
case CMP:
@ -288,8 +289,9 @@ public class LocalRemover implements Transformer {
stack.add(be.op2);
break;
}
case NEW_ARRAY:
case INSTANCEOF:
InstanceOfExpr iof = (InstanceOfExpr) toReplace;
TypeExpr iof = (TypeExpr) toReplace;
stack.add(iof.op);
break;
case INVOKE_INTERFACE:
@ -298,7 +300,7 @@ public class LocalRemover implements Transformer {
case INVOKE_NEW:
case INVOKE_STATIC:
InvokeExpr ie = (InvokeExpr) toReplace;
for (ValueBox vb : ie.args) {
for (ValueBox vb : ie.ops) {
stack.add(vb);
}
break;
@ -308,13 +310,10 @@ public class LocalRemover implements Transformer {
UnopExpr ue = (UnopExpr) toReplace;
stack.add(ue.op);
break;
case NEW_ARRAY:
NewArrayExpr nae = (NewArrayExpr) toReplace;
stack.add(nae.size);
break;
case NEW_MUTI_ARRAY:
NewMutiArrayExpr nmae = (NewMutiArrayExpr) toReplace;
for (ValueBox vb : nmae.sizes) {
for (ValueBox vb : nmae.ops) {
stack.add(vb);
}
break;

View File

@ -12,13 +12,11 @@ import com.googlecode.dex2jar.ir.Value.VT;
import com.googlecode.dex2jar.ir.ValueBox;
import com.googlecode.dex2jar.ir.expr.ArrayExpr;
import com.googlecode.dex2jar.ir.expr.BinopExpr;
import com.googlecode.dex2jar.ir.expr.CastExpr;
import com.googlecode.dex2jar.ir.expr.Exprs;
import com.googlecode.dex2jar.ir.expr.FieldExpr;
import com.googlecode.dex2jar.ir.expr.InstanceOfExpr;
import com.googlecode.dex2jar.ir.expr.InvokeExpr;
import com.googlecode.dex2jar.ir.expr.NewArrayExpr;
import com.googlecode.dex2jar.ir.expr.NewMutiArrayExpr;
import com.googlecode.dex2jar.ir.expr.TypeExpr;
import com.googlecode.dex2jar.ir.expr.UnopExpr;
import com.googlecode.dex2jar.ir.stmt.AssignStmt;
import com.googlecode.dex2jar.ir.stmt.JumpStmt;
@ -104,11 +102,12 @@ public class LocalSpliter implements Transformer {
toVisitStack.push(lss.defaultTarget);
break;
case ASSIGN:
case IDENTITY:
AssignStmt assignStmt = (AssignStmt) currentStmt;
if (assignStmt.left.value.vt == VT.LOCAL) {
if (assignStmt.op1.value.vt == VT.LOCAL) {
System.arraycopy(currentFrame, 0, tmp, 0, tmp.length);
Local local = (Local) assignStmt.left.value;
Local local = (Local) assignStmt.op1.value;
int reg = local._ls_index;
Stmt next = currentStmt.getNext();
ValueBox vb;
@ -128,13 +127,12 @@ public class LocalSpliter implements Transformer {
tmp[reg] = vb;
currentFrame = tmp;
mergeFrame2Stmt(currentFrame, currentStmt.getNext(), locals);
assignStmt.left = ((Local) vb.value)._ls_vb;
assignStmt.op1 = ((Local) vb.value)._ls_vb;
} else {
mergeFrame2Stmt(currentFrame, currentStmt.getNext(), locals);
}
toVisitStack.push(currentStmt.getNext());
break;
case IDENTITY:
case NOP:
case LABEL:
case LOCK:
@ -166,12 +164,13 @@ public class LocalSpliter implements Transformer {
exec(st);
switch (st.st) {
case ASSIGN:
case IDENTITY:
AssignStmt as = (AssignStmt) st;
if (as.left.value.vt == VT.LOCAL) {
as.left = ((Local) as.left.value)._ls_vb;
if (as.op1.value.vt == VT.LOCAL) {
as.op1 = ((Local) as.op1.value)._ls_vb;
}
if (as.right.value.vt == VT.INVOKE_SPECIAL) {
InvokeExpr ie = (InvokeExpr) as.right.value;
if (as.op2.value.vt == VT.INVOKE_SPECIAL) {
InvokeExpr ie = (InvokeExpr) as.op2.value;
if (ie.methodName.equals("<init>")) {
jm._ls_inits.add(as);
}
@ -191,28 +190,26 @@ public class LocalSpliter implements Transformer {
ValueBox[] frame = st._ls_frame;
switch (st.st) {
case ASSIGN:
case IDENTITY:
AssignStmt assignStmt = (AssignStmt) st;
if (assignStmt.left.value.vt != VT.LOCAL) {
assignStmt.left = execValue(assignStmt.left, frame);
if (assignStmt.op1.value.vt != VT.LOCAL) {
assignStmt.op1 = execValue(assignStmt.op1, frame);
}
assignStmt.right = execValue(assignStmt.right, frame);
assignStmt.op2 = execValue(assignStmt.op2, frame);
break;
case GOTO:
case NOP:
case LABEL:
case RETURN_VOID:
break;
case IDENTITY:
break;
case IF:
((JumpStmt) st).condition = execValue(((JumpStmt) st).condition, frame);
((JumpStmt) st).op = execValue(((JumpStmt) st).op, frame);
break;
case LOOKUP_SWITCH:
((LookupSwitchStmt) st).key = execValue(((LookupSwitchStmt) st).key, frame);
((LookupSwitchStmt) st).op = execValue(((LookupSwitchStmt) st).op, frame);
break;
case TABLE_SWITCH:
((TableSwitchStmt) st).key = execValue(((TableSwitchStmt) st).key, frame);
((TableSwitchStmt) st).op = execValue(((TableSwitchStmt) st).op, frame);
break;
case LOCK:
case THROW:
@ -229,18 +226,16 @@ public class LocalSpliter implements Transformer {
Local local = (Local) frame[((Local) vb.value)._ls_index].value;
local._ls_read_count++;
return ((Local) frame[((Local) vb.value)._ls_index].value)._ls_vb;
case CAST:
CastExpr ce = (CastExpr) vb.value;
ce.op = execValue(ce.op, frame);
break;
case FIELD:
FieldExpr fe = (FieldExpr) vb.value;
if (null != fe.object) {
fe.object = execValue(fe.object, frame);
if (null != fe.op) {
fe.op = execValue(fe.op, frame);
}
break;
case INSTANCEOF:
InstanceOfExpr ioe = (InstanceOfExpr) vb.value;
case NEW_ARRAY:
case CAST:
TypeExpr ioe = (TypeExpr) vb.value;
ioe.op = execValue(ioe.op, frame);
break;
case LENGTH:
@ -249,22 +244,16 @@ public class LocalSpliter implements Transformer {
UnopExpr ue = (UnopExpr) vb.value;
ue.op = execValue(ue.op, frame);
break;
case NEW_ARRAY:
NewArrayExpr nae = (NewArrayExpr) vb.value;
execValue(nae.size, frame);
break;
case NEW_MUTI_ARRAY:
NewMutiArrayExpr nmae = (NewMutiArrayExpr) vb.value;
for (int i = 0; i < nmae.sizes.length; i++) {
nmae.sizes[i] = execValue(nmae.sizes[i], frame);
for (int i = 0; i < nmae.ops.length; i++) {
nmae.ops[i] = execValue(nmae.ops[i], frame);
}
break;
case ARRAY:
ArrayExpr ae = (ArrayExpr) vb.value;
ae.base = execValue(ae.base, frame);
ae.index = execValue(ae.index, frame);
ae.op1 = execValue(ae.op1, frame);
ae.op2 = execValue(ae.op2, frame);
break;
case CMP:
case CMPG:
@ -296,8 +285,8 @@ public class LocalSpliter implements Transformer {
case INVOKE_INTERFACE:
case INVOKE_NEW:
InvokeExpr methodExpr = (InvokeExpr) vb.value;
for (int i = 0; i < methodExpr.args.length; i++) {
methodExpr.args[i] = execValue(methodExpr.args[i], frame);
for (int i = 0; i < methodExpr.ops.length; i++) {
methodExpr.ops[i] = execValue(methodExpr.ops[i], frame);
}
break;
case EXCEPTION_REF:

View File

@ -13,6 +13,7 @@ import static com.googlecode.dex2jar.ir.expr.Exprs.nLocal;
import static com.googlecode.dex2jar.ir.expr.Exprs.nNewArray;
import static com.googlecode.dex2jar.ir.stmt.Stmts.nAssign;
import static com.googlecode.dex2jar.ir.stmt.Stmts.nGoto;
import static com.googlecode.dex2jar.ir.stmt.Stmts.nIdentity;
import static com.googlecode.dex2jar.ir.stmt.Stmts.nIf;
import static com.googlecode.dex2jar.ir.stmt.Stmts.nLabel;
import static com.googlecode.dex2jar.ir.stmt.Stmts.nReturn;
@ -207,7 +208,7 @@ public class LocalRemoverTest {
list.add(L2);
list.add(nGoto(L4));
list.add(L3);
list.add(nAssign(ex, nExceptionRef(exType)));
list.add(nIdentity(ex, nExceptionRef(exType)));
list.add(nAssign(ex,
nInvokeVirtual(new Value[] { ex }, exType, "toString", new Type[0], Type.getType(String.class))));
list.add(nAssign(b, nNull()));

View File

@ -13,6 +13,7 @@ import static com.googlecode.dex2jar.ir.expr.Exprs.nLocal;
import static com.googlecode.dex2jar.ir.expr.Exprs.nNewArray;
import static com.googlecode.dex2jar.ir.stmt.Stmts.nAssign;
import static com.googlecode.dex2jar.ir.stmt.Stmts.nGoto;
import static com.googlecode.dex2jar.ir.stmt.Stmts.nIdentity;
import static com.googlecode.dex2jar.ir.stmt.Stmts.nIf;
import static com.googlecode.dex2jar.ir.stmt.Stmts.nLabel;
import static com.googlecode.dex2jar.ir.stmt.Stmts.nReturn;
@ -54,7 +55,7 @@ public class LocalSplitTest {
new LocalSpliter().transform(jm);
Assert.assertTrue(jm.locals.size() == 2);
Assert.assertEquals(st2.left.value, st3.op.value);
Assert.assertEquals(st2.op1.value, st3.op.value);
}
@Test
@ -106,7 +107,7 @@ public class LocalSplitTest {
list.add(L2);
list.add(nGoto(L4));
list.add(L3);
list.add(nAssign(ex, nExceptionRef(exType)));
list.add(nIdentity(ex, nExceptionRef(exType)));
list.add(nAssign(ex,
nInvokeVirtual(new Value[] { ex }, exType, "toString", new Type[0], Type.getType(String.class))));
list.add(nAssign(b, nNull()));

View File

@ -59,6 +59,7 @@ import static com.googlecode.dex2jar.ir.expr.Exprs.nUshr;
import static com.googlecode.dex2jar.ir.expr.Exprs.nXor;
import static com.googlecode.dex2jar.ir.stmt.Stmts.nAssign;
import static com.googlecode.dex2jar.ir.stmt.Stmts.nGoto;
import static com.googlecode.dex2jar.ir.stmt.Stmts.nIdentity;
import static com.googlecode.dex2jar.ir.stmt.Stmts.nIf;
import static com.googlecode.dex2jar.ir.stmt.Stmts.nLabel;
import static com.googlecode.dex2jar.ir.stmt.Stmts.nLock;
@ -137,14 +138,14 @@ public class V3CodeAdapter implements DexCodeVisitor, Opcodes, DexOpcodes {
int i = 0;
if ((irMethod.access & ACC_STATIC) == 0) {
Local _this = nLocal("this", this.irMethod.owner);
list.add(nAssign(_this, nThisRef(this.irMethod.owner)));
list.add(nIdentity(_this, nThisRef(this.irMethod.owner)));
locals[args[i]] = _this;
i++;
}
int j = 0;
for (; i < args.length; i++, j++) {
Local _arg = nLocal("arg_" + args[i], this.irMethod.args[j]);
list.add(nAssign(_arg, nParameterRef(this.irMethod.args[j], j)));
list.add(nIdentity(_arg, nParameterRef(this.irMethod.args[j], j)));
locals[args[i]] = _arg;
}
}
@ -480,13 +481,11 @@ public class V3CodeAdapter implements DexCodeVisitor, Opcodes, DexOpcodes {
@Override
public void visitLookupSwitchStmt(int opcode, int aA, Label label, int[] cases, Label[] labels) {
Value vs[] = new Value[cases.length];
LabelStmt[] lss = new LabelStmt[cases.length];
for (int i = 0; i < cases.length; i++) {
vs[i] = nInt(cases[i]);
lss[i] = toLabelStmt(labels[i]);
}
list.add(nLookupSwitch(locals[aA], vs, lss, toLabelStmt(label)));
list.add(nLookupSwitch(locals[aA], cases, lss, toLabelStmt(label)));
}
@Override
@ -540,7 +539,7 @@ public class V3CodeAdapter implements DexCodeVisitor, Opcodes, DexOpcodes {
list.add(nAssign(locals[toReg], locals[tmp_reg]));
break;
case OP_MOVE_EXCEPTION:
list.add(nAssign(locals[toReg], nExceptionRef(Type.getType(Throwable.class))));
list.add(nIdentity(locals[toReg], nExceptionRef(Type.getType(Throwable.class))));
break;
}
}