com.googlecode.d2j.dex.Dex2IrAdapter Maven / Gradle / Ivy
The newest version!
/*
* 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;
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy