com.googlecode.d2j.dex.Dex2IrAdapter Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of gradle Show documentation
Show all versions of gradle Show documentation
fakeradnroid gradle builder
/*
* Copyright (c) 2009-2012 Panxiaobo
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.googlecode.d2j.dex;
import static com.googlecode.dex2jar.ir.expr.Exprs.nAdd;
import static com.googlecode.dex2jar.ir.expr.Exprs.nAnd;
import static com.googlecode.dex2jar.ir.expr.Exprs.nArray;
import static com.googlecode.dex2jar.ir.expr.Exprs.nArrayValue;
import static com.googlecode.dex2jar.ir.expr.Exprs.nCast;
import static com.googlecode.dex2jar.ir.expr.Exprs.nCheckCast;
import static com.googlecode.dex2jar.ir.expr.Exprs.nDCmpg;
import static com.googlecode.dex2jar.ir.expr.Exprs.nDCmpl;
import static com.googlecode.dex2jar.ir.expr.Exprs.nDiv;
import static com.googlecode.dex2jar.ir.expr.Exprs.nExceptionRef;
import static com.googlecode.dex2jar.ir.expr.Exprs.nFCmpg;
import static com.googlecode.dex2jar.ir.expr.Exprs.nFCmpl;
import static com.googlecode.dex2jar.ir.expr.Exprs.nField;
import static com.googlecode.dex2jar.ir.expr.Exprs.nInstanceOf;
import static com.googlecode.dex2jar.ir.expr.Exprs.nInt;
import static com.googlecode.dex2jar.ir.expr.Exprs.nInvokeInterface;
import static com.googlecode.dex2jar.ir.expr.Exprs.nInvokeNew;
import static com.googlecode.dex2jar.ir.expr.Exprs.nInvokeSpecial;
import static com.googlecode.dex2jar.ir.expr.Exprs.nInvokeStatic;
import static com.googlecode.dex2jar.ir.expr.Exprs.nInvokeVirtual;
import static com.googlecode.dex2jar.ir.expr.Exprs.nLCmp;
import static com.googlecode.dex2jar.ir.expr.Exprs.nLength;
import static com.googlecode.dex2jar.ir.expr.Exprs.nLong;
import static com.googlecode.dex2jar.ir.expr.Exprs.nMul;
import static com.googlecode.dex2jar.ir.expr.Exprs.nNeg;
import static com.googlecode.dex2jar.ir.expr.Exprs.nNew;
import static com.googlecode.dex2jar.ir.expr.Exprs.nNewArray;
import static com.googlecode.dex2jar.ir.expr.Exprs.nNot;
import static com.googlecode.dex2jar.ir.expr.Exprs.nOr;
import static com.googlecode.dex2jar.ir.expr.Exprs.nRem;
import static com.googlecode.dex2jar.ir.expr.Exprs.nShl;
import static com.googlecode.dex2jar.ir.expr.Exprs.nShr;
import static com.googlecode.dex2jar.ir.expr.Exprs.nStaticField;
import static com.googlecode.dex2jar.ir.expr.Exprs.nString;
import static com.googlecode.dex2jar.ir.expr.Exprs.nSub;
import static com.googlecode.dex2jar.ir.expr.Exprs.nType;
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.*;
import java.util.*;
import com.googlecode.d2j.node.DexCodeNode;
import com.googlecode.d2j.node.TryCatchNode;
import com.googlecode.d2j.node.insn.DexLabelStmtNode;
import com.googlecode.d2j.node.insn.FilledNewArrayStmtNode;
import com.googlecode.d2j.node.insn.DexStmtNode;
import com.googlecode.d2j.node.insn.MethodStmtNode;
import com.googlecode.d2j.visitors.DexDebugVisitor;
import com.googlecode.dex2jar.ir.TypeClass;
import org.objectweb.asm.Opcodes;
import com.googlecode.d2j.DexLabel;
import com.googlecode.d2j.DexConstants;
import com.googlecode.d2j.DexType;
import com.googlecode.d2j.Field;
import com.googlecode.d2j.Method;
import com.googlecode.d2j.reader.Op;
import com.googlecode.d2j.visitors.DexCodeVisitor;
import com.googlecode.dex2jar.ir.IrMethod;
import com.googlecode.dex2jar.ir.Trap;
import com.googlecode.dex2jar.ir.expr.Exprs;
import com.googlecode.dex2jar.ir.expr.Local;
import com.googlecode.dex2jar.ir.expr.Value;
import com.googlecode.dex2jar.ir.stmt.LabelStmt;
import com.googlecode.dex2jar.ir.stmt.Stmt;
import com.googlecode.dex2jar.ir.stmt.StmtList;
import com.googlecode.dex2jar.ir.stmt.Stmts;
/**
* @author Panxiaobo
* @version $Rev$
*/
public class Dex2IrAdapter extends DexCodeVisitor implements Opcodes, DexConstants {
protected IrMethod irMethod;
private Method method;
private boolean isStatic;
private StmtList list;
private Local[] locals;
Map labelStmtMap = new HashMap<>();
private Local tmpLocal;
/**
* @param isStatic
* @param method
*/
public Dex2IrAdapter(boolean isStatic, Method method) {
super();
IrMethod irMethod = new IrMethod();
irMethod.args = method.getParameterTypes();
irMethod.ret = method.getReturnType();
irMethod.owner = method.getOwner();
irMethod.name = method.getName();
irMethod.isStatic = isStatic;
this.irMethod = irMethod;
this.list = irMethod.stmts;
this.irMethod = irMethod;
this.method = method;
this.isStatic = isStatic;
}
private LabelStmt toLabelStmt(DexLabel label) {
LabelStmt ls = labelStmtMap.get(label);
if (ls == null) {
ls = new LabelStmt();
labelStmtMap.put(label, ls);
}
return ls;
}
static int countParameterRegisters(Method m, boolean isStatic) {
int a = isStatic ? 0 : 1;
for (String t : m.getParameterTypes()) {
switch (t.charAt(0)) {
case 'J':
case 'D':
a += 2;
break;
default:
a += 1;
break;
}
}
return a;
}
void x(Stmt stmt) {
list.add(stmt);
}
@Override
public void visitRegister(int total) {
Local[] locals = new Local[total];
this.locals = locals;
this.tmpLocal = new Local(total);
for (int i = 0; i < locals.length; i++) {
locals[i] = new Local(i);
}
int nextReg = total - countParameterRegisters(method, isStatic);
int nextReg0 = nextReg;
if (!isStatic) {// is not static
x(Stmts.nIdentity(locals[nextReg], Exprs.nThisRef(method.getOwner())));
nextReg++;
}
String[] args = method.getParameterTypes();
for (int i = 0; i < args.length; i++) {
String t = args[i];
x(Stmts.nIdentity(locals[nextReg], Exprs.nParameterRef(t, i)));
nextReg++;
if (t.equals("J") || t.equals("D")) {
nextReg++;
}
}
// simple fix for issue 219, init all tmp register to 0 at the start of insn.
for (int i = 0; i < nextReg0; i++) {
x(Stmts.nAssign(locals[i], nInt(0)));
}
x(Stmts.nAssign(tmpLocal, nInt(0)));
}
@Override
public void visitStmt2R1N(Op op, int a, int b, int content) {
Local va = locals[a];
Local vb = locals[b];
Value to;
switch (op) {
case ADD_INT_LIT16:
case ADD_INT_LIT8:
to = nAdd(vb, nInt(content), "I");
break;
case RSUB_INT_LIT8:
case RSUB_INT://
to = nSub(nInt(content), vb, "I");
break;
case MUL_INT_LIT8:
case MUL_INT_LIT16:
to = nMul(vb, nInt(content), "I");
break;
case DIV_INT_LIT16:
case DIV_INT_LIT8:
to = nDiv(vb, nInt(content), "I");
break;
case REM_INT_LIT16:
case REM_INT_LIT8:
to = nRem(vb, nInt(content), "I");
break;
case AND_INT_LIT16:
case AND_INT_LIT8:
to = nAnd(vb, nInt(content), content < 0 || content > 1 ? "I" : TypeClass.ZI.name);
break;
case OR_INT_LIT16:
case OR_INT_LIT8:
to = nOr(vb, nInt(content), content < 0 || content > 1 ? "I" : TypeClass.ZI.name);
break;
case XOR_INT_LIT16:
case XOR_INT_LIT8:
to = nXor(vb, nInt(content), content < 0 || content > 1 ? "I" : TypeClass.ZI.name);
break;
case SHL_INT_LIT8:
to = nShl(vb, nInt(content), "I");
break;
case SHR_INT_LIT8:
to = nShr(vb, nInt(content), "I");
break;
case USHR_INT_LIT8:
to = nUshr(vb, nInt(content), "I");
break;
default:
throw new RuntimeException();
}
x(nAssign(va, to));
}
@Override
public void visitStmt3R(Op op, int a, int b, int c) {
Value va = locals[a];
Value vb = locals[b];
Value vc = locals[c];
switch (op) {
case APUT:
x(nAssign(nArray(vb, vc, TypeClass.IF.name), va));
break;
case APUT_BOOLEAN:
x(nAssign(nArray(vb, vc, "Z"), va));
break;
case APUT_BYTE:
x(nAssign(nArray(vb, vc, "B"), va));
break;
case APUT_CHAR:
x(nAssign(nArray(vb, vc, "C"), va));
break;
case APUT_OBJECT:
x(nAssign(nArray(vb, vc, "L"), va));
break;
case APUT_SHORT:
x(nAssign(nArray(vb, vc, "S"), va));
break;
case APUT_WIDE:
x(nAssign(nArray(vb, vc, TypeClass.JD.name), va));
break;
case AGET:
x(nAssign(va, nArray(vb, vc, TypeClass.IF.name)));
break;
case AGET_BOOLEAN:
x(nAssign(va, nArray(vb, vc, "Z")));
break;
case AGET_BYTE:
x(nAssign(va, nArray(vb, vc, "B")));
break;
case AGET_CHAR:
x(nAssign(va, nArray(vb, vc, "C")));
break;
case AGET_OBJECT:
x(nAssign(va, nArray(vb, vc, "L")));
break;
case AGET_SHORT:
x(nAssign(va, nArray(vb, vc, "S")));
break;
case AGET_WIDE:
x(nAssign(va, nArray(vb, vc, TypeClass.JD.name)));
break;
case CMP_LONG:
x(nAssign(va, nLCmp(vb, vc)));
break;
case CMPG_DOUBLE:
x(nAssign(va, nDCmpg(vb, vc)));
break;
case CMPG_FLOAT:
x(nAssign(va, nFCmpg(vb, vc)));
break;
case CMPL_DOUBLE:
x(nAssign(va, nDCmpl(vb, vc)));
break;
case CMPL_FLOAT:
x(nAssign(va, nFCmpl(vb, vc)));
break;
case ADD_DOUBLE:
x(nAssign(va, nAdd(vb, vc, "D")));
break;
case ADD_FLOAT:
x(nAssign(va, nAdd(vb, vc, "F")));
break;
case ADD_INT:
x(nAssign(va, nAdd(vb, vc, "I")));
break;
case ADD_LONG:
x(nAssign(va, nAdd(vb, vc, "J")));
break;
case SUB_DOUBLE:
x(nAssign(va, nSub(vb, vc, "D")));
break;
case SUB_FLOAT:
x(nAssign(va, nSub(vb, vc, "F")));
break;
// case RSUB_INT:
// x(nAssign(va, nSub(vc, vb, "I")));
// break;
case SUB_INT:
x(nAssign(va, nSub(vb, vc, "I")));
break;
case SUB_LONG:
x(nAssign(va, nSub(vb, vc, "J")));
break;
case MUL_DOUBLE:
x(nAssign(va, nMul(vb, vc, "D")));
break;
case MUL_FLOAT:
x(nAssign(va, nMul(vb, vc, "F")));
break;
case MUL_INT:
x(nAssign(va, nMul(vb, vc, "I")));
break;
case MUL_LONG:
x(nAssign(va, nMul(vb, vc, "J")));
break;
case DIV_DOUBLE:
x(nAssign(va, nDiv(vb, vc, "D")));
break;
case DIV_FLOAT:
x(nAssign(va, nDiv(vb, vc, "F")));
break;
case DIV_INT:
x(nAssign(va, nDiv(vb, vc, "I")));
break;
case DIV_LONG:
x(nAssign(va, nDiv(vb, vc, "J")));
break;
case REM_DOUBLE:
x(nAssign(va, nRem(vb, vc, "D")));
break;
case REM_FLOAT:
x(nAssign(va, nRem(vb, vc, "F")));
break;
case REM_INT:
x(nAssign(va, nRem(vb, vc, "I")));
break;
case REM_LONG:
x(nAssign(va, nRem(vb, vc, "J")));
break;
case AND_INT:
x(nAssign(va, nAnd(vb, vc, TypeClass.ZI.name)));
break;
case AND_LONG:
x(nAssign(va, nAnd(vb, vc, "J")));
break;
case OR_INT:
x(nAssign(va, nOr(vb, vc, TypeClass.ZI.name)));
break;
case OR_LONG:
x(nAssign(va, nOr(vb, vc, "J")));
break;
case XOR_INT:
x(nAssign(va, nXor(vb, vc, TypeClass.ZI.name)));
break;
case XOR_LONG:
x(nAssign(va, nXor(vb, vc, "J")));
break;
case SHL_INT:
x(nAssign(va, nShl(vb, vc, "I")));
break;
case SHL_LONG:
x(nAssign(va, nShl(vb, vc, "J")));
break;
case SHR_INT:
x(nAssign(va, nShr(vb, vc, "I")));
break;
case SHR_LONG:
x(nAssign(va, nShr(vb, vc, "J")));
break;
case USHR_INT:
x(nAssign(va, nUshr(vb, vc, "I")));
break;
case USHR_LONG:
x(nAssign(va, nUshr(vb, vc, "J")));
break;
default:
throw new RuntimeException();
}
}
@Override
public void visitTypeStmt(Op op, int a, int b, String type) {
switch (op) {
case INSTANCE_OF:
list.add(nAssign(locals[a], nInstanceOf(locals[b], type)));
break;
case NEW_ARRAY:
list.add(nAssign(locals[a], nNewArray(type.substring(1), locals[b])));
break;
case CHECK_CAST:
list.add(nAssign(locals[a], nCheckCast(locals[a], type)));
break;
case NEW_INSTANCE:
list.add(nAssign(locals[a], nNew(type)));
break;
default:
throw new RuntimeException();
}
}
@Override
public void visitFillArrayDataStmt(Op op, int ra, Object array) {
x(nFillArrayData(locals[ra], nArrayValue(array)));
}
@Override
public void visitConstStmt(Op op, int toReg, Object value) {
switch (op) {
case CONST:
case CONST_16:
case CONST_4:
case CONST_HIGH16:
x(nAssign(locals[toReg], nInt((Integer) value)));
break;
case CONST_WIDE:
case CONST_WIDE_16:
case CONST_WIDE_32:
case CONST_WIDE_HIGH16:
x(nAssign(locals[toReg], nLong((Long) value)));
break;
case CONST_CLASS:
x(nAssign(locals[toReg], nType((DexType) value)));
break;
case CONST_STRING:
case CONST_STRING_JUMBO:
x(nAssign(locals[toReg], nString((String) value)));
break;
default:
throw new RuntimeException();
}
}
/*
* (non-Javadoc)
*
* @see com.googlecode.dex2jar.visitors.DexCodeVisitor#visitEnd()
*/
@Override
public void visitEnd() {
irMethod.locals.addAll(Arrays.asList(this.locals));
irMethod.locals.add(tmpLocal);
this.locals = null;
}
@Override
public void visitFieldStmt(Op op, int a, int b, Field field) {
switch (op) {
case IGET:
case IGET_BOOLEAN:
case IGET_BYTE:
case IGET_CHAR:
case IGET_OBJECT:
case IGET_SHORT:
case IGET_WIDE:
list.add(nAssign(locals[a], nField(locals[b], field.getOwner(), field.getName(), field.getType())));
break;
case IPUT:
case IPUT_BOOLEAN:
case IPUT_BYTE:
case IPUT_CHAR:
case IPUT_OBJECT:
case IPUT_SHORT:
case IPUT_WIDE:
list.add(nAssign(nField(locals[b], field.getOwner(), field.getName(), field.getType()), locals[a]));
break;
case SGET:
case SGET_BOOLEAN:
case SGET_BYTE:
case SGET_CHAR:
case SGET_OBJECT:
case SGET_SHORT:
case SGET_WIDE:
list.add(nAssign(locals[a], nStaticField(field.getOwner(), field.getName(), field.getType())));
break;
case SPUT:
case SPUT_BOOLEAN:
case SPUT_BYTE:
case SPUT_CHAR:
case SPUT_OBJECT:
case SPUT_SHORT:
case SPUT_WIDE:
list.add(nAssign(nStaticField(field.getOwner(), field.getName(), field.getType()), locals[a]));
break;
default:
throw new RuntimeException();
}
}
@Override
public void visitFilledNewArrayStmt(Op opc, int[] args, String type) {
Local array = tmpLocal;
String elem = type.substring(1);
list.add(nAssign(array, nNewArray(elem, nInt(args.length))));
for (int i = 0; i < args.length; i++) {
list.add(nAssign(nArray(array, nInt(i), elem), locals[args[i]]));
}
}
@Override
public void visitJumpStmt(Op op, int a, int b, DexLabel label) {
switch (op) {
case GOTO:
case GOTO_16:
case GOTO_32:
x(nGoto(toLabelStmt(label)));
break;
case IF_EQ:
x(nIf(Exprs.nEq(locals[a], locals[b], TypeClass.ZIL.name), toLabelStmt(label)));
break;
case IF_GE:
x(nIf(Exprs.nGe(locals[a], locals[b], "I"), toLabelStmt(label)));
break;
case IF_GT:
x(nIf(Exprs.nGt(locals[a], locals[b], "I"), toLabelStmt(label)));
break;
case IF_LE:
x(nIf(Exprs.nLe(locals[a], locals[b], "I"), toLabelStmt(label)));
break;
case IF_LT:
x(nIf(Exprs.nLt(locals[a], locals[b], "I"), toLabelStmt(label)));
break;
case IF_NE:
x(nIf(Exprs.nNe(locals[a], locals[b], TypeClass.ZIL.name), toLabelStmt(label)));
break;
case IF_EQZ:
x(nIf(Exprs.nEq(locals[a], nInt(0), TypeClass.ZIL.name), toLabelStmt(label)));
break;
case IF_GEZ:
x(nIf(Exprs.nGe(locals[a], nInt(0), "I"), toLabelStmt(label)));
break;
case IF_GTZ:
x(nIf(Exprs.nGt(locals[a], nInt(0), "I"), toLabelStmt(label)));
break;
case IF_LEZ:
x(nIf(Exprs.nLe(locals[a], nInt(0), "I"), toLabelStmt(label)));
break;
case IF_LTZ:
x(nIf(Exprs.nLt(locals[a], nInt(0), "I"), toLabelStmt(label)));
break;
case IF_NEZ:
x(nIf(Exprs.nNe(locals[a], nInt(0), TypeClass.ZIL.name), toLabelStmt(label)));
break;
default:
throw new RuntimeException();
}
}
@Override
public void visitLabel(DexLabel label) {
list.add(toLabelStmt(label));
}
@Override
public void visitSparseSwitchStmt(Op op, int aA, int[] cases, DexLabel[] labels) {
LabelStmt[] lss = new LabelStmt[cases.length];
for (int i = 0; i < cases.length; i++) {
lss[i] = toLabelStmt(labels[i]);
}
LabelStmt d = new LabelStmt();
x(nLookupSwitch(locals[aA], cases, lss, d));
x(d);
}
@Override
public void visitMethodStmt(Op op, int[] args, Method method) {
Value[] vs;
if (args.length > 0) {
int i = 0;
List ps = new ArrayList(args.length);
if (op == Op.INVOKE_STATIC || op == Op.INVOKE_STATIC_RANGE) {
;
} else {
ps.add(locals[args[i]]);
i++;
}
for (String t : method.getParameterTypes()) {
ps.add(locals[args[i]]);
if (t.equals("J") || t.equals("D")) {
i += 2;
} else {
i++;
}
}
vs = ps.toArray(new Value[ps.size()]);
} else {
vs = new Value[0];
}
Value invoke = null;
switch (op) {
case INVOKE_VIRTUAL_RANGE:
case INVOKE_VIRTUAL:
invoke = nInvokeVirtual(vs, method.getOwner(), method.getName(), method.getParameterTypes(),
method.getReturnType());
break;
case INVOKE_SUPER_RANGE:
case INVOKE_DIRECT_RANGE:
case INVOKE_SUPER:
case INVOKE_DIRECT:
invoke = nInvokeSpecial(vs, method.getOwner(), method.getName(), method.getParameterTypes(),
method.getReturnType());
break;
case INVOKE_STATIC_RANGE:
case INVOKE_STATIC:
invoke = nInvokeStatic(vs, method.getOwner(), method.getName(), method.getParameterTypes(),
method.getReturnType());
break;
case INVOKE_INTERFACE_RANGE:
case INVOKE_INTERFACE:
invoke = nInvokeInterface(vs, method.getOwner(), method.getName(), method.getParameterTypes(),
method.getReturnType());
break;
default:
throw new RuntimeException();
}
if ("V".equals(method.getReturnType())) {
x(nVoidInvoke(invoke));
} else {
x(nAssign(tmpLocal, invoke));
}
}
@Override
public void visitStmt1R(Op op, int reg) {
Local va = locals[reg];
switch (op) {
case MONITOR_ENTER:
x(nLock(va));
break;
case MONITOR_EXIT:
x(nUnLock(va));
break;
case RETURN:
case RETURN_WIDE:
case RETURN_OBJECT:
x(nReturn(va));
break;
case THROW:
x(nThrow(va));
break;
case MOVE_RESULT:
case MOVE_RESULT_WIDE:
case MOVE_RESULT_OBJECT:
if (lastIsInvokeOrFilledNewArray) { // right position
x(nAssign(va, tmpLocal));
} else { // wrong position, replace with throw new RuntimeExceptoin("...");
System.err.println("WARN: find wrong position of " + op + " in method " + method);
x(nThrow(nInvokeNew(new Value[] { nString("d2j: wrong position of " + op) },
new String[] { "Ljava/lang/String;" }, "Ljava/lang/RuntimeException;")));
}
break;
case MOVE_EXCEPTION:
x(nIdentity(va, nExceptionRef("Ljava/lang/Throwable;")));
break;
default:
throw new RuntimeException();
}
}
@Override
public void visitStmt2R(Op op, int a, int b) {
Local va = locals[a];
Local vb = locals[b];
Value to = null;
switch (op) {
case MOVE:
case MOVE_16:
case MOVE_FROM16:
case MOVE_OBJECT:
case MOVE_OBJECT_16:
case MOVE_OBJECT_FROM16:
case MOVE_WIDE:
case MOVE_WIDE_FROM16:
case MOVE_WIDE_16:
to = vb;
break;
case ARRAY_LENGTH:
to = nLength(vb);
break;
case ADD_DOUBLE_2ADDR:
to = nAdd(va, vb, "D");
break;
case ADD_FLOAT_2ADDR:
to = nAdd(va, vb, "F");
break;
case ADD_INT_2ADDR:
to = nAdd(va, vb, "I");
break;
case ADD_LONG_2ADDR:
to = nAdd(va, vb, "J");
break;
case SUB_DOUBLE_2ADDR:
to = nSub(va, vb, "D");
break;
case SUB_FLOAT_2ADDR:
to = nSub(va, vb, "F");
break;
case SUB_INT_2ADDR:
to = nSub(va, vb, "I");
break;
case SUB_LONG_2ADDR:
to = nSub(va, vb, "J");
break;
case MUL_DOUBLE_2ADDR:
to = nMul(va, vb, "D");
break;
case MUL_FLOAT_2ADDR:
to = nMul(va, vb, "F");
break;
case MUL_INT_2ADDR:
to = nMul(va, vb, "I");
break;
case MUL_LONG_2ADDR:
to = nMul(va, vb, "J");
break;
case DIV_DOUBLE_2ADDR:
to = nDiv(va, vb, "D");
break;
case DIV_FLOAT_2ADDR:
to = nDiv(va, vb, "F");
break;
case DIV_INT_2ADDR:
to = nDiv(va, vb, "I");
break;
case DIV_LONG_2ADDR:
to = nDiv(va, vb, "J");
break;
case REM_DOUBLE_2ADDR:
to = nRem(va, vb, "D");
break;
case REM_FLOAT_2ADDR:
to = nRem(va, vb, "F");
break;
case REM_INT_2ADDR:
to = nRem(va, vb, "I");
break;
case REM_LONG_2ADDR:
to = nRem(va, vb, "J");
break;
case AND_INT_2ADDR:
to = nAnd(va, vb, TypeClass.ZI.name);
break;
case AND_LONG_2ADDR:
to = nAnd(va, vb, "J");
break;
case OR_INT_2ADDR:
to = nOr(va, vb, TypeClass.ZI.name);
break;
case OR_LONG_2ADDR:
to = nOr(va, vb, "J");
break;
case XOR_INT_2ADDR:
to = nXor(va, vb, TypeClass.ZI.name);
break;
case XOR_LONG_2ADDR:
to = nXor(va, vb, "J");
break;
case SHL_INT_2ADDR:
to = nShl(va, vb, "I");
break;
case SHL_LONG_2ADDR:
to = nShl(va, vb, "J");
break;
case SHR_INT_2ADDR:
to = nShr(va, vb, "I");
break;
case SHR_LONG_2ADDR:
to = nShr(va, vb, "J");
break;
case USHR_INT_2ADDR:
to = nUshr(va, vb, "I");
break;
case USHR_LONG_2ADDR:
to = nUshr(va, vb, "J");
break;
case NOT_INT:
to = nNot(vb, "I");
break;
case NOT_LONG:
to = nNot(vb, "J");
break;
case NEG_DOUBLE:
to = nNeg(vb, "D");
break;
case NEG_FLOAT:
to = nNeg(vb, "F");
break;
case NEG_INT:
to = nNeg(vb, "I");
break;
case NEG_LONG:
to = nNeg(vb, "J");
break;
case INT_TO_BYTE:
to = nCast(vb, "I", "B");
break;
case INT_TO_CHAR:
to = nCast(vb, "I", "C");
break;
case INT_TO_DOUBLE:
to = nCast(vb, "I", "D");
break;
case INT_TO_FLOAT:
to = nCast(vb, "I", "F");
break;
case INT_TO_LONG:
to = nCast(vb, "I", "J");
break;
case INT_TO_SHORT:
to = nCast(vb, "I", "S");
break;
case FLOAT_TO_DOUBLE:
to = nCast(vb, "F", "D");
break;
case FLOAT_TO_INT:
to = nCast(vb, "F", "I");
break;
case FLOAT_TO_LONG:
to = nCast(vb, "F", "J");
break;
case DOUBLE_TO_FLOAT:
to = nCast(vb, "D", "F");
break;
case DOUBLE_TO_INT:
to = nCast(vb, "D", "I");
break;
case DOUBLE_TO_LONG:
to = nCast(vb, "D", "J");
break;
case LONG_TO_DOUBLE:
to = nCast(vb, "J", "D");
break;
case LONG_TO_FLOAT:
to = nCast(vb, "J", "F");
break;
case LONG_TO_INT:
to = nCast(vb, "J", "I");
break;
default:
throw new RuntimeException();
}
x(nAssign(va, to));
}
@Override
public void visitStmt0R(Op op) {
switch (op) {
case RETURN_VOID:
x(nReturnVoid());
break;
case NOP:
// ignore
break;
case BAD_OP:
x(nThrow(nInvokeNew(new Value[] { nString("bad dex opcode") }, new String[] { "Ljava/lang/String;" },
"Ljava/lang/VerifyError;")));
break;
default:
throw new RuntimeException();
}
}
@Override
public void visitPackedSwitchStmt(Op op, int aA, int first_case, DexLabel[] labels) {
LabelStmt[] lss = new LabelStmt[labels.length];
for (int i = 0; i < labels.length; i++) {
lss[i] = toLabelStmt(labels[i]);
}
LabelStmt d = new LabelStmt();
x(nTableSwitch(locals[aA], first_case, lss, d));
x(d);
}
@Override
public void visitTryCatch(DexLabel start, DexLabel end, DexLabel[] handlers, String[] types) {
LabelStmt xlabelStmts[] = new LabelStmt[types.length];
for (int i = 0; i < types.length; i++) {
xlabelStmts[i] = toLabelStmt(handlers[i]);
}
irMethod.traps.add(new Trap(toLabelStmt(start), toLabelStmt(end), xlabelStmts, types));
}
boolean lastIsInvokeOrFilledNewArray = false;
public IrMethod convert(DexCodeNode codeNode) {
if (codeNode.tryStmts != null) {
for (TryCatchNode n : codeNode.tryStmts) {
n.accept(this);
}
}
if (codeNode.debugNode != null) {
DexDebugVisitor ddv = this.visitDebug();
if (ddv != null) {
codeNode.debugNode.accept(ddv);
ddv.visitEnd();
}
}
lastIsInvokeOrFilledNewArray = false;
if (codeNode.totalRegister >= 0) {
this.visitRegister(codeNode.totalRegister);
}
for (DexStmtNode n : codeNode.stmts) {
n.accept(this);
if (n instanceof FilledNewArrayStmtNode) {
lastIsInvokeOrFilledNewArray = true;
} else if (n instanceof MethodStmtNode) {
lastIsInvokeOrFilledNewArray = !((MethodStmtNode) n).method.getReturnType().equals("V");
} else if (!(n instanceof DexLabelStmtNode)) {
lastIsInvokeOrFilledNewArray = false;
}
}
visitEnd();
return irMethod;
}
}