use of soot.ArrayType in project soot by Sable.
the class ExprVisitor method caseNewArrayExpr.
@Override
public void caseNewArrayExpr(NewArrayExpr nae) {
Value size = nae.getSize();
constantV.setOrigStmt(origStmt);
Register sizeReg = regAlloc.asImmediate(size, constantV);
ArrayType arrayType = nae.getBaseType().getArrayType();
TypeReference arrayTypeItem = DexPrinter.toTypeReference(arrayType);
stmtV.addInsn(new Insn22c(Opcode.NEW_ARRAY, destinationReg, sizeReg, arrayTypeItem), origStmt);
}
use of soot.ArrayType in project soot by Sable.
the class ExprVisitor method caseNewMultiArrayExpr.
@Override
public void caseNewMultiArrayExpr(NewMultiArrayExpr nmae) {
constantV.setOrigStmt(origStmt);
// get array dimensions
if (nmae.getSizeCount() > 255) {
throw new RuntimeException("number of dimensions is too high (> 255) for the filled-new-array* opcodes: " + nmae.getSizeCount());
}
short dimensions = (short) nmae.getSizeCount();
// get array base type
ArrayType arrayType = ArrayType.v(nmae.getBaseType().baseType, dimensions);
TypeReference arrayTypeItem = DexPrinter.toTypeReference(arrayType);
// get the dimension size registers
List<Register> dimensionSizeRegs = new ArrayList<Register>();
for (int i = 0; i < dimensions; i++) {
Value currentDimensionSize = nmae.getSize(i);
Register currentReg = regAlloc.asImmediate(currentDimensionSize, constantV);
dimensionSizeRegs.add(currentReg);
}
// create filled-new-array instruction, depending on the dimension sizes
if (dimensions <= 5) {
Register[] paddedRegs = pad35cRegs(dimensionSizeRegs);
stmtV.addInsn(new Insn35c(Opcode.FILLED_NEW_ARRAY, dimensions, paddedRegs[0], paddedRegs[1], paddedRegs[2], paddedRegs[3], paddedRegs[4], arrayTypeItem), null);
} else {
stmtV.addInsn(new Insn3rc(Opcode.FILLED_NEW_ARRAY_RANGE, dimensionSizeRegs, dimensions, arrayTypeItem), null);
}
// check for > 255 is done already
// move the resulting array into the destination register
stmtV.addInsn(new Insn11x(Opcode.MOVE_RESULT_OBJECT, destinationReg), origStmt);
}
use of soot.ArrayType in project soot by Sable.
the class ASMBackendUtils method toTypeDesc.
/**
* Convert type to JVM style type description
* @param type Type to convert
* @return JVM style type description
*/
public static String toTypeDesc(Type type) {
final StringBuilder sb = new StringBuilder(1);
type.apply(new TypeSwitch() {
public void defaultCase(Type t) {
throw new RuntimeException("Invalid type " + t.toString());
}
public void caseDoubleType(DoubleType t) {
sb.append('D');
}
public void caseFloatType(FloatType t) {
sb.append('F');
}
public void caseIntType(IntType t) {
sb.append('I');
}
public void caseByteType(ByteType t) {
sb.append('B');
}
public void caseShortType(ShortType t) {
sb.append('S');
}
public void caseCharType(CharType t) {
sb.append('C');
}
public void caseBooleanType(BooleanType t) {
sb.append('Z');
}
public void caseLongType(LongType t) {
sb.append('J');
}
public void caseArrayType(ArrayType t) {
sb.append('[');
t.getElementType().apply(this);
}
public void caseRefType(RefType t) {
sb.append('L');
sb.append(slashify(t.getClassName()));
sb.append(';');
}
public void caseVoidType(VoidType t) {
sb.append('V');
}
});
return sb.toString();
}
use of soot.ArrayType in project soot by Sable.
the class OutFlow method generateJimple.
void generateJimple(Instruction ins, TypeStack typeStack, TypeStack postTypeStack, cp_info[] constant_pool, List<Stmt> statements, BasicBlock basicBlock) {
Value[] params;
Local l1 = null, l2 = null, l3 = null, l4 = null;
Expr rhs = null;
ConditionExpr co = null;
ArrayRef a = null;
int args;
Value rvalue;
// int localIndex;
Stmt stmt = null;
int x = ((ins.code)) & 0xff;
switch(x) {
case ByteCode.BIPUSH:
rvalue = IntConstant.v(((Instruction_Bipush) ins).arg_b);
stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack, postTypeStack.topIndex()), rvalue);
break;
case ByteCode.SIPUSH:
rvalue = IntConstant.v(((Instruction_Sipush) ins).arg_i);
stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack, postTypeStack.topIndex()), rvalue);
break;
case ByteCode.LDC1:
generateJimpleForCPEntry(constant_pool, ((Instruction_Ldc1) ins).arg_b, typeStack, postTypeStack, jmethod, statements);
break;
case ByteCode.LDC2:
case ByteCode.LDC2W:
generateJimpleForCPEntry(constant_pool, ((Instruction_intindex) ins).arg_i, typeStack, postTypeStack, jmethod, statements);
break;
case ByteCode.ACONST_NULL:
rvalue = NullConstant.v();
stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack, postTypeStack.topIndex()), rvalue);
break;
case ByteCode.ICONST_M1:
case ByteCode.ICONST_0:
case ByteCode.ICONST_1:
case ByteCode.ICONST_2:
case ByteCode.ICONST_3:
case ByteCode.ICONST_4:
case ByteCode.ICONST_5:
rvalue = IntConstant.v(x - ByteCode.ICONST_0);
stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack, postTypeStack.topIndex()), rvalue);
break;
case ByteCode.LCONST_0:
case ByteCode.LCONST_1:
rvalue = LongConstant.v(x - ByteCode.LCONST_0);
stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack, postTypeStack.topIndex()), rvalue);
break;
case ByteCode.FCONST_0:
case ByteCode.FCONST_1:
case ByteCode.FCONST_2:
rvalue = FloatConstant.v((x - ByteCode.FCONST_0));
stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack, postTypeStack.topIndex()), rvalue);
break;
case ByteCode.DCONST_0:
case ByteCode.DCONST_1:
rvalue = DoubleConstant.v((x - ByteCode.DCONST_0));
stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack, postTypeStack.topIndex()), rvalue);
break;
case ByteCode.ILOAD:
{
Local local = Util.v().getLocalForIndex(listBody, ((Instruction_bytevar) ins).arg_b, ins);
stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack, postTypeStack.topIndex()), local);
break;
}
case ByteCode.FLOAD:
{
Local local = Util.v().getLocalForIndex(listBody, ((Instruction_bytevar) ins).arg_b, ins);
stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack, postTypeStack.topIndex()), local);
break;
}
case ByteCode.ALOAD:
{
Local local = Util.v().getLocalForIndex(listBody, ((Instruction_bytevar) ins).arg_b, ins);
stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack, postTypeStack.topIndex()), local);
break;
}
case ByteCode.DLOAD:
{
Local local = Util.v().getLocalForIndex(listBody, ((Instruction_bytevar) ins).arg_b, ins);
stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack, postTypeStack.topIndex()), local);
break;
}
case ByteCode.LLOAD:
{
Local local = Util.v().getLocalForIndex(listBody, ((Instruction_bytevar) ins).arg_b, ins);
stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack, postTypeStack.topIndex()), local);
break;
}
case ByteCode.ILOAD_0:
case ByteCode.ILOAD_1:
case ByteCode.ILOAD_2:
case ByteCode.ILOAD_3:
{
Local local = Util.v().getLocalForIndex(listBody, (x - ByteCode.ILOAD_0), ins);
stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack, postTypeStack.topIndex()), local);
break;
}
case ByteCode.FLOAD_0:
case ByteCode.FLOAD_1:
case ByteCode.FLOAD_2:
case ByteCode.FLOAD_3:
{
Local local = Util.v().getLocalForIndex(listBody, (x - ByteCode.FLOAD_0), ins);
stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack, postTypeStack.topIndex()), local);
break;
}
case ByteCode.ALOAD_0:
case ByteCode.ALOAD_1:
case ByteCode.ALOAD_2:
case ByteCode.ALOAD_3:
{
Local local = Util.v().getLocalForIndex(listBody, (x - ByteCode.ALOAD_0), ins);
stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack, postTypeStack.topIndex()), local);
break;
}
case ByteCode.LLOAD_0:
case ByteCode.LLOAD_1:
case ByteCode.LLOAD_2:
case ByteCode.LLOAD_3:
{
Local local = Util.v().getLocalForIndex(listBody, (x - ByteCode.LLOAD_0), ins);
stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack, postTypeStack.topIndex()), local);
break;
}
case ByteCode.DLOAD_0:
case ByteCode.DLOAD_1:
case ByteCode.DLOAD_2:
case ByteCode.DLOAD_3:
{
Local local = Util.v().getLocalForIndex(listBody, (x - ByteCode.DLOAD_0), ins);
stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack, postTypeStack.topIndex()), local);
break;
}
case ByteCode.ISTORE:
{
Local local = Util.v().getLocalForIndex(listBody, ((Instruction_bytevar) ins).arg_b, ins);
stmt = Jimple.v().newAssignStmt(local, Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()));
break;
}
case ByteCode.FSTORE:
{
Local local = Util.v().getLocalForIndex(listBody, ((Instruction_bytevar) ins).arg_b, ins);
stmt = Jimple.v().newAssignStmt(local, Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()));
break;
}
case ByteCode.ASTORE:
{
Local local = Util.v().getLocalForIndex(listBody, ((Instruction_bytevar) ins).arg_b, ins);
stmt = Jimple.v().newAssignStmt(local, Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()));
break;
}
case ByteCode.LSTORE:
{
Local local = Util.v().getLocalForIndex(listBody, ((Instruction_bytevar) ins).arg_b, ins);
stmt = Jimple.v().newAssignStmt(local, Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()));
break;
}
case ByteCode.DSTORE:
{
Local local = Util.v().getLocalForIndex(listBody, ((Instruction_bytevar) ins).arg_b, ins);
stmt = Jimple.v().newAssignStmt(local, Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()));
break;
}
case ByteCode.ISTORE_0:
case ByteCode.ISTORE_1:
case ByteCode.ISTORE_2:
case ByteCode.ISTORE_3:
{
Local local = Util.v().getLocalForIndex(listBody, (x - ByteCode.ISTORE_0), ins);
stmt = Jimple.v().newAssignStmt(local, Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()));
break;
}
case ByteCode.FSTORE_0:
case ByteCode.FSTORE_1:
case ByteCode.FSTORE_2:
case ByteCode.FSTORE_3:
{
Local local = Util.v().getLocalForIndex(listBody, (x - ByteCode.FSTORE_0), ins);
stmt = Jimple.v().newAssignStmt(local, Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()));
break;
}
case ByteCode.ASTORE_0:
case ByteCode.ASTORE_1:
case ByteCode.ASTORE_2:
case ByteCode.ASTORE_3:
{
Local local = Util.v().getLocalForIndex(listBody, (x - ByteCode.ASTORE_0), ins);
stmt = Jimple.v().newAssignStmt(local, Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()));
break;
}
case ByteCode.LSTORE_0:
case ByteCode.LSTORE_1:
case ByteCode.LSTORE_2:
case ByteCode.LSTORE_3:
{
Local local = Util.v().getLocalForIndex(listBody, (x - ByteCode.LSTORE_0), ins);
stmt = Jimple.v().newAssignStmt(local, Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()));
break;
}
case ByteCode.DSTORE_0:
case ByteCode.DSTORE_1:
case ByteCode.DSTORE_2:
case ByteCode.DSTORE_3:
{
Local local = Util.v().getLocalForIndex(listBody, (x - ByteCode.DSTORE_0), ins);
stmt = Jimple.v().newAssignStmt(local, Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()));
break;
}
case ByteCode.IINC:
{
Local local = Util.v().getLocalForIndex(listBody, ((Instruction_Iinc) ins).arg_b, ins);
int amt = (((Instruction_Iinc) ins).arg_c);
rhs = Jimple.v().newAddExpr(local, IntConstant.v(amt));
stmt = Jimple.v().newAssignStmt(local, rhs);
break;
}
case ByteCode.WIDE:
throw new RuntimeException("WIDE instruction should not be encountered anymore");
case ByteCode.NEWARRAY:
{
Type baseType = jimpleTypeOfAtype(((Instruction_Newarray) ins).atype);
rhs = Jimple.v().newNewArrayExpr(baseType, Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()));
stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack, postTypeStack.topIndex()), rhs);
break;
}
case ByteCode.ANEWARRAY:
{
String baseName = getClassName(constant_pool, ((Instruction_Anewarray) ins).arg_i);
Type baseType;
if (baseName.startsWith("["))
baseType = Util.v().jimpleTypeOfFieldDescriptor(getClassName(constant_pool, ((Instruction_Anewarray) ins).arg_i));
else
baseType = RefType.v(baseName);
rhs = Jimple.v().newNewArrayExpr(baseType, Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()));
stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack, postTypeStack.topIndex()), rhs);
break;
}
case ByteCode.MULTIANEWARRAY:
{
int bdims = (((Instruction_Multianewarray) ins).dims);
List<Value> dims = new ArrayList<Value>();
for (int j = 0; j < bdims; j++) dims.add(Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex() - bdims + j + 1));
String mstype = constant_pool[((Instruction_Multianewarray) ins).arg_i].toString(constant_pool);
ArrayType jimpleType = (ArrayType) Util.v().jimpleTypeOfFieldDescriptor(mstype);
rhs = Jimple.v().newNewMultiArrayExpr(jimpleType, dims);
stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack, postTypeStack.topIndex()), rhs);
break;
}
case ByteCode.ARRAYLENGTH:
rhs = Jimple.v().newLengthExpr(Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()));
stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack, postTypeStack.topIndex()), rhs);
break;
case ByteCode.IALOAD:
case ByteCode.BALOAD:
case ByteCode.CALOAD:
case ByteCode.SALOAD:
case ByteCode.FALOAD:
case ByteCode.LALOAD:
case ByteCode.DALOAD:
case ByteCode.AALOAD:
a = Jimple.v().newArrayRef(Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex() - 1), Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()));
stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack, postTypeStack.topIndex()), a);
break;
case ByteCode.IASTORE:
case ByteCode.FASTORE:
case ByteCode.AASTORE:
case ByteCode.BASTORE:
case ByteCode.CASTORE:
case ByteCode.SASTORE:
a = Jimple.v().newArrayRef(Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex() - 2), Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex() - 1));
stmt = Jimple.v().newAssignStmt(a, Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()));
break;
case ByteCode.LASTORE:
case ByteCode.DASTORE:
a = Jimple.v().newArrayRef(Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex() - 3), Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex() - 2));
stmt = Jimple.v().newAssignStmt(a, Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()));
break;
case ByteCode.NOP:
stmt = Jimple.v().newNopStmt();
break;
case ByteCode.POP:
case ByteCode.POP2:
stmt = Jimple.v().newNopStmt();
break;
case ByteCode.DUP:
stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack, postTypeStack.topIndex()), Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()));
break;
case ByteCode.DUP2:
if (typeSize(typeStack.top()) == 2) {
stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack, postTypeStack.topIndex() - 1), Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex() - 1));
} else {
stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack, postTypeStack.topIndex() - 1), Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex() - 1));
statements.add(stmt);
stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack, postTypeStack.topIndex()), Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()));
statements.add(stmt);
stmt = null;
}
break;
case ByteCode.DUP_X1:
l1 = Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex());
l2 = Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex() - 1);
stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack, postTypeStack.topIndex()), l1);
statements.add(stmt);
stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack, postTypeStack.topIndex() - 1), l2);
statements.add(stmt);
stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack, postTypeStack.topIndex() - 2), Util.v().getLocalForStackOp(listBody, postTypeStack, postTypeStack.topIndex()));
statements.add(stmt);
stmt = null;
break;
case ByteCode.DUP_X2:
if (typeSize(typeStack.get(typeStack.topIndex() - 2)) == 2) {
l3 = Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex() - 2);
l1 = Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex());
stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack, postTypeStack.topIndex() - 2), l3);
statements.add(stmt);
stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack, postTypeStack.topIndex() - 3), l1);
statements.add(stmt);
stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack, postTypeStack.topIndex()), l1);
statements.add(stmt);
stmt = null;
} else {
l3 = Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex() - 2);
l2 = Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex() - 1);
l1 = Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex());
stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack, postTypeStack.topIndex()), l1);
statements.add(stmt);
stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack, postTypeStack.topIndex() - 1), l2);
statements.add(stmt);
stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack, postTypeStack.topIndex() - 2), l3);
statements.add(stmt);
stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack, postTypeStack.topIndex() - 3), Util.v().getLocalForStackOp(listBody, postTypeStack, postTypeStack.topIndex()));
statements.add(stmt);
stmt = null;
}
break;
case ByteCode.DUP2_X1:
if (typeSize(typeStack.get(typeStack.topIndex() - 1)) == 2) {
l2 = Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex() - 1);
l3 = Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex() - 2);
stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack, postTypeStack.topIndex() - 1), l2);
statements.add(stmt);
stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack, postTypeStack.topIndex() - 2), l3);
statements.add(stmt);
stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack, postTypeStack.topIndex() - 4), Util.v().getLocalForStackOp(listBody, postTypeStack, postTypeStack.topIndex() - 1));
statements.add(stmt);
stmt = null;
} else {
l3 = Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex() - 2);
l2 = Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex() - 1);
l1 = Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex());
stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack, postTypeStack.topIndex()), l1);
statements.add(stmt);
stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack, postTypeStack.topIndex() - 1), l2);
statements.add(stmt);
stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack, postTypeStack.topIndex() - 2), l3);
statements.add(stmt);
stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack, postTypeStack.topIndex() - 3), Util.v().getLocalForStackOp(listBody, postTypeStack, postTypeStack.topIndex()));
statements.add(stmt);
stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack, postTypeStack.topIndex() - 4), Util.v().getLocalForStackOp(listBody, postTypeStack, postTypeStack.topIndex() - 1));
statements.add(stmt);
stmt = null;
}
break;
case ByteCode.DUP2_X2:
if (typeSize(typeStack.get(typeStack.topIndex() - 1)) == 2) {
l2 = Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex() - 1);
stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack, postTypeStack.topIndex() - 1), l2);
statements.add(stmt);
} else {
l1 = Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex());
l2 = Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex() - 1);
stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack, postTypeStack.topIndex() - 1), l2);
statements.add(stmt);
stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack, postTypeStack.topIndex()), l1);
statements.add(stmt);
}
if (typeSize(typeStack.get(typeStack.topIndex() - 3)) == 2) {
l4 = Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex() - 3);
stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack, postTypeStack.topIndex() - 3), l4);
statements.add(stmt);
} else {
l4 = Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex() - 3);
l3 = Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex() - 2);
stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack, postTypeStack.topIndex() - 3), l4);
statements.add(stmt);
stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack, postTypeStack.topIndex() - 2), l3);
statements.add(stmt);
}
if (typeSize(typeStack.get(typeStack.topIndex() - 1)) == 2) {
stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack, postTypeStack.topIndex() - 5), Util.v().getLocalForStackOp(listBody, postTypeStack, postTypeStack.topIndex() - 1));
statements.add(stmt);
} else {
stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack, postTypeStack.topIndex() - 5), Util.v().getLocalForStackOp(listBody, postTypeStack, postTypeStack.topIndex() - 1));
statements.add(stmt);
stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack, postTypeStack.topIndex() - 4), Util.v().getLocalForStackOp(listBody, postTypeStack, postTypeStack.topIndex()));
statements.add(stmt);
}
stmt = null;
break;
case ByteCode.SWAP:
{
Local first;
typeStack = typeStack.push(typeStack.top());
first = Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex());
typeStack = typeStack.pop();
// generation of a free temporary
Local second = Util.v().getLocalForStackOp(listBody, postTypeStack, postTypeStack.topIndex());
Local third = Util.v().getLocalForStackOp(listBody, postTypeStack, postTypeStack.topIndex() - 1);
stmt = Jimple.v().newAssignStmt(first, second);
statements.add(stmt);
stmt = Jimple.v().newAssignStmt(second, third);
statements.add(stmt);
stmt = Jimple.v().newAssignStmt(third, first);
statements.add(stmt);
stmt = null;
break;
}
case ByteCode.FADD:
case ByteCode.IADD:
rhs = Jimple.v().newAddExpr(Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex() - 1), Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()));
stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack, postTypeStack.topIndex()), rhs);
break;
case ByteCode.DADD:
case ByteCode.LADD:
rhs = Jimple.v().newAddExpr(Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex() - 3), Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex() - 1));
stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack, postTypeStack.topIndex()), rhs);
break;
case ByteCode.FSUB:
case ByteCode.ISUB:
rhs = Jimple.v().newSubExpr(Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex() - 1), Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()));
stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack, postTypeStack.topIndex()), rhs);
break;
case ByteCode.DSUB:
case ByteCode.LSUB:
rhs = Jimple.v().newSubExpr(Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex() - 3), Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex() - 1));
stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack, postTypeStack.topIndex()), rhs);
break;
case ByteCode.FMUL:
case ByteCode.IMUL:
rhs = Jimple.v().newMulExpr(Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex() - 1), Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()));
stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack, postTypeStack.topIndex()), rhs);
break;
case ByteCode.DMUL:
case ByteCode.LMUL:
rhs = Jimple.v().newMulExpr(Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex() - 3), Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex() - 1));
stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack, postTypeStack.topIndex()), rhs);
break;
case ByteCode.FDIV:
case ByteCode.IDIV:
rhs = Jimple.v().newDivExpr(Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex() - 1), Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()));
stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack, postTypeStack.topIndex()), rhs);
break;
case ByteCode.DDIV:
case ByteCode.LDIV:
rhs = Jimple.v().newDivExpr(Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex() - 3), Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex() - 1));
stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack, postTypeStack.topIndex()), rhs);
break;
case ByteCode.FREM:
case ByteCode.IREM:
rhs = Jimple.v().newRemExpr(Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex() - 1), Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()));
stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack, postTypeStack.topIndex()), rhs);
break;
case ByteCode.DREM:
case ByteCode.LREM:
rhs = Jimple.v().newRemExpr(Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex() - 3), Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex() - 1));
stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack, postTypeStack.topIndex()), rhs);
break;
case ByteCode.INEG:
case ByteCode.LNEG:
case ByteCode.FNEG:
case ByteCode.DNEG:
rhs = Jimple.v().newNegExpr(Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()));
stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack, postTypeStack.topIndex()), rhs);
break;
case ByteCode.ISHL:
rhs = Jimple.v().newShlExpr(Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex() - 1), Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()));
stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack, postTypeStack.topIndex()), rhs);
break;
case ByteCode.ISHR:
rhs = Jimple.v().newShrExpr(Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex() - 1), Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()));
stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack, postTypeStack.topIndex()), rhs);
break;
case ByteCode.IUSHR:
rhs = Jimple.v().newUshrExpr(Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex() - 1), Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()));
stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack, postTypeStack.topIndex()), rhs);
break;
case ByteCode.LSHL:
rhs = Jimple.v().newShlExpr(Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex() - 2), Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()));
stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack, postTypeStack.topIndex()), rhs);
break;
case ByteCode.LSHR:
rhs = Jimple.v().newShrExpr(Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex() - 2), Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()));
stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack, postTypeStack.topIndex()), rhs);
break;
case ByteCode.LUSHR:
rhs = Jimple.v().newUshrExpr(Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex() - 2), Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()));
stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack, postTypeStack.topIndex()), rhs);
break;
case ByteCode.IAND:
rhs = Jimple.v().newAndExpr(Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex() - 1), Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()));
stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack, postTypeStack.topIndex()), rhs);
break;
case ByteCode.LAND:
rhs = Jimple.v().newAndExpr(Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex() - 3), Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex() - 1));
stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack, postTypeStack.topIndex()), rhs);
break;
case ByteCode.IOR:
rhs = Jimple.v().newOrExpr(Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex() - 1), Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()));
stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack, postTypeStack.topIndex()), rhs);
break;
case ByteCode.LOR:
rhs = Jimple.v().newOrExpr(Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex() - 3), Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex() - 1));
stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack, postTypeStack.topIndex()), rhs);
break;
case ByteCode.IXOR:
rhs = Jimple.v().newXorExpr(Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex() - 1), Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()));
stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack, postTypeStack.topIndex()), rhs);
break;
case ByteCode.LXOR:
rhs = Jimple.v().newXorExpr(Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex() - 3), Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex() - 1));
stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack, postTypeStack.topIndex()), rhs);
break;
case ByteCode.D2L:
case ByteCode.F2L:
case ByteCode.I2L:
rhs = Jimple.v().newCastExpr(Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()), LongType.v());
stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack, postTypeStack.topIndex()), rhs);
break;
case ByteCode.D2F:
case ByteCode.L2F:
case ByteCode.I2F:
rhs = Jimple.v().newCastExpr(Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()), FloatType.v());
stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack, postTypeStack.topIndex()), rhs);
break;
case ByteCode.I2D:
case ByteCode.L2D:
case ByteCode.F2D:
rhs = Jimple.v().newCastExpr(Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()), DoubleType.v());
stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack, postTypeStack.topIndex()), rhs);
break;
case ByteCode.L2I:
case ByteCode.F2I:
case ByteCode.D2I:
rhs = Jimple.v().newCastExpr(Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()), IntType.v());
stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack, postTypeStack.topIndex()), rhs);
break;
case ByteCode.INT2BYTE:
rhs = Jimple.v().newCastExpr(Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()), ByteType.v());
stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack, postTypeStack.topIndex()), rhs);
break;
case ByteCode.INT2CHAR:
rhs = Jimple.v().newCastExpr(Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()), CharType.v());
stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack, postTypeStack.topIndex()), rhs);
break;
case ByteCode.INT2SHORT:
rhs = Jimple.v().newCastExpr(Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()), ShortType.v());
stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack, postTypeStack.topIndex()), rhs);
break;
case ByteCode.IFEQ:
co = Jimple.v().newEqExpr(Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()), IntConstant.v(0));
stmt = Jimple.v().newIfStmt(co, new FutureStmt());
break;
case ByteCode.IFNULL:
co = Jimple.v().newEqExpr(Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()), NullConstant.v());
stmt = Jimple.v().newIfStmt(co, new FutureStmt());
break;
case ByteCode.IFLT:
co = Jimple.v().newLtExpr(Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()), IntConstant.v(0));
stmt = Jimple.v().newIfStmt(co, new FutureStmt());
break;
case ByteCode.IFLE:
co = Jimple.v().newLeExpr(Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()), IntConstant.v(0));
stmt = Jimple.v().newIfStmt(co, new FutureStmt());
break;
case ByteCode.IFNE:
co = Jimple.v().newNeExpr(Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()), IntConstant.v(0));
stmt = Jimple.v().newIfStmt(co, new FutureStmt());
break;
case ByteCode.IFNONNULL:
co = Jimple.v().newNeExpr(Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()), NullConstant.v());
stmt = Jimple.v().newIfStmt(co, new FutureStmt());
break;
case ByteCode.IFGT:
co = Jimple.v().newGtExpr(Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()), IntConstant.v(0));
stmt = Jimple.v().newIfStmt(co, new FutureStmt());
break;
case ByteCode.IFGE:
co = Jimple.v().newGeExpr(Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()), IntConstant.v(0));
stmt = Jimple.v().newIfStmt(co, new FutureStmt());
break;
case ByteCode.IF_ICMPEQ:
co = Jimple.v().newEqExpr(Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex() - 1), Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()));
stmt = Jimple.v().newIfStmt(co, new FutureStmt());
break;
case ByteCode.IF_ICMPLT:
co = Jimple.v().newLtExpr(Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex() - 1), Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()));
stmt = Jimple.v().newIfStmt(co, new FutureStmt());
break;
case ByteCode.IF_ICMPLE:
co = Jimple.v().newLeExpr(Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex() - 1), Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()));
stmt = Jimple.v().newIfStmt(co, new FutureStmt());
break;
case ByteCode.IF_ICMPNE:
co = Jimple.v().newNeExpr(Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex() - 1), Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()));
stmt = Jimple.v().newIfStmt(co, new FutureStmt());
break;
case ByteCode.IF_ICMPGT:
co = Jimple.v().newGtExpr(Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex() - 1), Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()));
stmt = Jimple.v().newIfStmt(co, new FutureStmt());
break;
case ByteCode.IF_ICMPGE:
co = Jimple.v().newGeExpr(Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex() - 1), Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()));
stmt = Jimple.v().newIfStmt(co, new FutureStmt());
break;
case ByteCode.LCMP:
rhs = Jimple.v().newCmpExpr(Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex() - 3), Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex() - 1));
stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack, postTypeStack.topIndex()), rhs);
break;
case ByteCode.FCMPL:
rhs = Jimple.v().newCmplExpr(Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex() - 1), Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()));
stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack, postTypeStack.topIndex()), rhs);
break;
case ByteCode.FCMPG:
rhs = Jimple.v().newCmpgExpr(Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex() - 1), Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()));
stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack, postTypeStack.topIndex()), rhs);
break;
case ByteCode.DCMPL:
rhs = Jimple.v().newCmplExpr(Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex() - 3), Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex() - 1));
stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack, postTypeStack.topIndex()), rhs);
break;
case ByteCode.DCMPG:
rhs = Jimple.v().newCmpgExpr(Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex() - 3), Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex() - 1));
stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack, postTypeStack.topIndex()), rhs);
break;
case ByteCode.IF_ACMPEQ:
co = Jimple.v().newEqExpr(Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex() - 1), Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()));
stmt = Jimple.v().newIfStmt(co, new FutureStmt());
break;
case ByteCode.IF_ACMPNE:
co = Jimple.v().newNeExpr(Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex() - 1), Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()));
stmt = Jimple.v().newIfStmt(co, new FutureStmt());
break;
case ByteCode.GOTO:
stmt = Jimple.v().newGotoStmt(new FutureStmt());
break;
case ByteCode.GOTO_W:
stmt = Jimple.v().newGotoStmt(new FutureStmt());
break;
case ByteCode.RET:
{
Local local = Util.v().getLocalForIndex(listBody, ((Instruction_Ret) ins).arg_b, ins);
stmt = Jimple.v().newRetStmt(local);
break;
}
case ByteCode.RET_W:
{
Local local = Util.v().getLocalForIndex(listBody, ((Instruction_Ret_w) ins).arg_i, ins);
stmt = Jimple.v().newRetStmt(local);
break;
}
case ByteCode.RETURN:
stmt = Jimple.v().newReturnVoidStmt();
break;
case ByteCode.LRETURN:
case ByteCode.DRETURN:
case ByteCode.IRETURN:
case ByteCode.FRETURN:
case ByteCode.ARETURN:
stmt = Jimple.v().newReturnStmt(Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()));
break;
case ByteCode.BREAKPOINT:
stmt = Jimple.v().newBreakpointStmt();
break;
case ByteCode.TABLESWITCH:
{
int lowIndex = ((Instruction_Tableswitch) ins).low, highIndex = ((Instruction_Tableswitch) ins).high;
int npairs = highIndex - lowIndex + 1;
stmt = Jimple.v().newTableSwitchStmt(Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()), lowIndex, highIndex, Arrays.asList(new FutureStmt[npairs]), new FutureStmt());
break;
}
case ByteCode.LOOKUPSWITCH:
{
List<IntConstant> matches = new ArrayList<IntConstant>();
int npairs = ((Instruction_Lookupswitch) ins).npairs;
for (int j = 0; j < npairs; j++) matches.add(IntConstant.v(((Instruction_Lookupswitch) ins).match_offsets[j * 2]));
stmt = Jimple.v().newLookupSwitchStmt(Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()), matches, Arrays.asList(new FutureStmt[npairs]), new FutureStmt());
break;
}
case ByteCode.PUTFIELD:
{
CONSTANT_Fieldref_info fieldInfo = (CONSTANT_Fieldref_info) constant_pool[((Instruction_Putfield) ins).arg_i];
CONSTANT_Class_info c = (CONSTANT_Class_info) constant_pool[fieldInfo.class_index];
String className = ((CONSTANT_Utf8_info) (constant_pool[c.name_index])).convert();
className = className.replace('/', '.');
CONSTANT_NameAndType_info i = (CONSTANT_NameAndType_info) constant_pool[fieldInfo.name_and_type_index];
String fieldName = ((CONSTANT_Utf8_info) (constant_pool[i.name_index])).convert();
String fieldDescriptor = ((CONSTANT_Utf8_info) (constant_pool[i.descriptor_index])).convert();
Type fieldType = Util.v().jimpleTypeOfFieldDescriptor(fieldDescriptor);
SootClass bclass = cm.getSootClass(className);
SootFieldRef fieldRef = Scene.v().makeFieldRef(bclass, fieldName, fieldType, false);
InstanceFieldRef fr = Jimple.v().newInstanceFieldRef(Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex() - typeSize(typeStack.top())), fieldRef);
rvalue = Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex());
stmt = Jimple.v().newAssignStmt(fr, rvalue);
break;
}
case ByteCode.GETFIELD:
{
InstanceFieldRef fr = null;
CONSTANT_Fieldref_info fieldInfo = (CONSTANT_Fieldref_info) constant_pool[((Instruction_Getfield) ins).arg_i];
CONSTANT_Class_info c = (CONSTANT_Class_info) constant_pool[fieldInfo.class_index];
String className = ((CONSTANT_Utf8_info) (constant_pool[c.name_index])).convert();
className = className.replace('/', '.');
CONSTANT_NameAndType_info i = (CONSTANT_NameAndType_info) constant_pool[fieldInfo.name_and_type_index];
String fieldName = ((CONSTANT_Utf8_info) (constant_pool[i.name_index])).convert();
String fieldDescriptor = ((CONSTANT_Utf8_info) (constant_pool[i.descriptor_index])).convert();
if (className.charAt(0) == '[')
className = "java.lang.Object";
SootClass bclass = cm.getSootClass(className);
Type fieldType = Util.v().jimpleTypeOfFieldDescriptor(fieldDescriptor);
SootFieldRef fieldRef = Scene.v().makeFieldRef(bclass, fieldName, fieldType, false);
fr = Jimple.v().newInstanceFieldRef(Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()), fieldRef);
stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack, postTypeStack.topIndex()), fr);
break;
}
case ByteCode.PUTSTATIC:
{
StaticFieldRef fr = null;
CONSTANT_Fieldref_info fieldInfo = (CONSTANT_Fieldref_info) constant_pool[((Instruction_Putstatic) ins).arg_i];
CONSTANT_Class_info c = (CONSTANT_Class_info) constant_pool[fieldInfo.class_index];
String className = ((CONSTANT_Utf8_info) (constant_pool[c.name_index])).convert();
className = className.replace('/', '.');
CONSTANT_NameAndType_info i = (CONSTANT_NameAndType_info) constant_pool[fieldInfo.name_and_type_index];
String fieldName = ((CONSTANT_Utf8_info) (constant_pool[i.name_index])).convert();
String fieldDescriptor = ((CONSTANT_Utf8_info) (constant_pool[i.descriptor_index])).convert();
Type fieldType = Util.v().jimpleTypeOfFieldDescriptor(fieldDescriptor);
SootClass bclass = cm.getSootClass(className);
SootFieldRef fieldRef = Scene.v().makeFieldRef(bclass, fieldName, fieldType, true);
fr = Jimple.v().newStaticFieldRef(fieldRef);
stmt = Jimple.v().newAssignStmt(fr, Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()));
break;
}
case ByteCode.GETSTATIC:
{
StaticFieldRef fr = null;
CONSTANT_Fieldref_info fieldInfo = (CONSTANT_Fieldref_info) constant_pool[((Instruction_Getstatic) ins).arg_i];
CONSTANT_Class_info c = (CONSTANT_Class_info) constant_pool[fieldInfo.class_index];
String className = ((CONSTANT_Utf8_info) (constant_pool[c.name_index])).convert();
className = className.replace('/', '.');
CONSTANT_NameAndType_info i = (CONSTANT_NameAndType_info) constant_pool[fieldInfo.name_and_type_index];
String fieldName = ((CONSTANT_Utf8_info) (constant_pool[i.name_index])).convert();
String fieldDescriptor = ((CONSTANT_Utf8_info) (constant_pool[i.descriptor_index])).convert();
Type fieldType = Util.v().jimpleTypeOfFieldDescriptor(fieldDescriptor);
SootClass bclass = cm.getSootClass(className);
SootFieldRef fieldRef = Scene.v().makeFieldRef(bclass, fieldName, fieldType, true);
fr = Jimple.v().newStaticFieldRef(fieldRef);
stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack, postTypeStack.topIndex()), fr);
break;
}
case ByteCode.INVOKEDYNAMIC:
{
Instruction_Invokedynamic iv = (Instruction_Invokedynamic) ins;
CONSTANT_InvokeDynamic_info iv_info = (CONSTANT_InvokeDynamic_info) constant_pool[iv.invoke_dynamic_index];
args = cp_info.countParams(constant_pool, iv_info.name_and_type_index);
SootMethodRef bootstrapMethodRef;
List<Value> bootstrapArgs = new LinkedList<Value>();
{
short[] bootstrapMethodTable = bootstrap_methods_attribute.method_handles;
short methodSigIndex = bootstrapMethodTable[iv_info.bootstrap_method_index];
CONSTANT_MethodHandle_info mhInfo = (CONSTANT_MethodHandle_info) constant_pool[methodSigIndex];
CONSTANT_Methodref_info bsmInfo = (CONSTANT_Methodref_info) constant_pool[mhInfo.target_index];
bootstrapMethodRef = createMethodRef(constant_pool, bsmInfo, false);
short[] bsmArgIndices = bootstrap_methods_attribute.arg_indices[iv_info.bootstrap_method_index];
if (bsmArgIndices.length > 0) {
// logger.debug("Soot does not currently support static arguments to bootstrap methods. They will be stripped.");
for (short bsmArgIndex : bsmArgIndices) {
cp_info cpEntry = constant_pool[bsmArgIndex];
Value val = cpEntry.createJimpleConstantValue(constant_pool);
bootstrapArgs.add(val);
}
}
}
SootMethodRef methodRef = null;
CONSTANT_NameAndType_info nameAndTypeInfo = (CONSTANT_NameAndType_info) constant_pool[iv_info.name_and_type_index];
String methodName = ((CONSTANT_Utf8_info) (constant_pool[nameAndTypeInfo.name_index])).convert();
String methodDescriptor = ((CONSTANT_Utf8_info) (constant_pool[nameAndTypeInfo.descriptor_index])).convert();
SootClass bclass = cm.getSootClass(SootClass.INVOKEDYNAMIC_DUMMY_CLASS_NAME);
List<Type> parameterTypes;
Type returnType;
// Generate parameters & returnType & parameterTypes
{
Type[] types = Util.v().jimpleTypesOfFieldOrMethodDescriptor(methodDescriptor);
parameterTypes = new ArrayList<Type>();
for (int k = 0; k < types.length - 1; k++) {
parameterTypes.add(types[k]);
}
returnType = types[types.length - 1];
}
// we always model invokeDynamic method refs as static method references of methods on the type SootClass.INVOKEDYNAMIC_DUMMY_CLASS_NAME
methodRef = Scene.v().makeMethodRef(bclass, methodName, parameterTypes, returnType, true);
// build Vector of parameters
params = new Value[args];
for (int j = args - 1; j >= 0; j--) {
params[j] = Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex());
if (typeSize(typeStack.top()) == 2) {
typeStack = typeStack.pop();
typeStack = typeStack.pop();
} else
typeStack = typeStack.pop();
}
rvalue = Jimple.v().newDynamicInvokeExpr(bootstrapMethodRef, bootstrapArgs, methodRef, Arrays.asList(params));
if (!returnType.equals(VoidType.v())) {
stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack, postTypeStack.topIndex()), rvalue);
} else
stmt = Jimple.v().newInvokeStmt(rvalue);
break;
}
case ByteCode.INVOKEVIRTUAL:
{
Instruction_Invokevirtual iv = (Instruction_Invokevirtual) ins;
args = cp_info.countParams(constant_pool, iv.arg_i);
CONSTANT_Methodref_info methodInfo = (CONSTANT_Methodref_info) constant_pool[iv.arg_i];
SootMethodRef methodRef = createMethodRef(constant_pool, methodInfo, false);
Type returnType = methodRef.returnType();
// build array of parameters
params = new Value[args];
for (int j = args - 1; j >= 0; j--) {
params[j] = Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex());
if (typeSize(typeStack.top()) == 2) {
typeStack = typeStack.pop();
typeStack = typeStack.pop();
} else
typeStack = typeStack.pop();
}
rvalue = Jimple.v().newVirtualInvokeExpr(Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()), methodRef, Arrays.asList(params));
if (!returnType.equals(VoidType.v())) {
stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack, postTypeStack.topIndex()), rvalue);
} else
stmt = Jimple.v().newInvokeStmt(rvalue);
break;
}
case ByteCode.INVOKENONVIRTUAL:
{
Instruction_Invokenonvirtual iv = (Instruction_Invokenonvirtual) ins;
args = cp_info.countParams(constant_pool, iv.arg_i);
CONSTANT_Methodref_info methodInfo = (CONSTANT_Methodref_info) constant_pool[iv.arg_i];
SootMethodRef methodRef = createMethodRef(constant_pool, methodInfo, false);
Type returnType = methodRef.returnType();
// build array of parameters
params = new Value[args];
for (int j = args - 1; j >= 0; j--) {
params[j] = Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex());
if (typeSize(typeStack.top()) == 2) {
typeStack = typeStack.pop();
typeStack = typeStack.pop();
} else
typeStack = typeStack.pop();
}
rvalue = Jimple.v().newSpecialInvokeExpr(Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()), methodRef, Arrays.asList(params));
if (!returnType.equals(VoidType.v())) {
stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack, postTypeStack.topIndex()), rvalue);
} else
stmt = Jimple.v().newInvokeStmt(rvalue);
break;
}
case ByteCode.INVOKESTATIC:
{
Instruction_Invokestatic is = (Instruction_Invokestatic) ins;
args = cp_info.countParams(constant_pool, is.arg_i);
CONSTANT_Methodref_info methodInfo = (CONSTANT_Methodref_info) constant_pool[is.arg_i];
SootMethodRef methodRef = createMethodRef(constant_pool, methodInfo, true);
Type returnType = methodRef.returnType();
// build Vector of parameters
params = new Value[args];
for (int j = args - 1; j >= 0; j--) {
/* logger.debug("BeforeTypeStack");
typeStack.print(G.v().out);
logger.debug("AfterTypeStack");
postTypeStack.print(G.v().out);
*/
params[j] = Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex());
if (typeSize(typeStack.top()) == 2) {
typeStack = typeStack.pop();
typeStack = typeStack.pop();
} else
typeStack = typeStack.pop();
}
rvalue = Jimple.v().newStaticInvokeExpr(methodRef, Arrays.asList(params));
if (!returnType.equals(VoidType.v())) {
stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack, postTypeStack.topIndex()), rvalue);
} else
stmt = Jimple.v().newInvokeStmt(rvalue);
break;
}
case ByteCode.INVOKEINTERFACE:
{
Instruction_Invokeinterface ii = (Instruction_Invokeinterface) ins;
args = cp_info.countParams(constant_pool, ii.arg_i);
CONSTANT_InterfaceMethodref_info methodInfo = (CONSTANT_InterfaceMethodref_info) constant_pool[ii.arg_i];
SootMethodRef methodRef = createMethodRef(constant_pool, methodInfo, false);
Type returnType = methodRef.returnType();
// build Vector of parameters
params = new Value[args];
for (int j = args - 1; j >= 0; j--) {
params[j] = Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex());
if (typeSize(typeStack.top()) == 2) {
typeStack = typeStack.pop();
typeStack = typeStack.pop();
} else
typeStack = typeStack.pop();
}
rvalue = Jimple.v().newInterfaceInvokeExpr(Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()), methodRef, Arrays.asList(params));
if (!returnType.equals(VoidType.v())) {
stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack, postTypeStack.topIndex()), rvalue);
} else
stmt = Jimple.v().newInvokeStmt(rvalue);
break;
}
case ByteCode.ATHROW:
stmt = Jimple.v().newThrowStmt(Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()));
break;
case ByteCode.NEW:
{
SootClass bclass = cm.getSootClass(getClassName(constant_pool, ((Instruction_New) ins).arg_i));
stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack, postTypeStack.topIndex()), Jimple.v().newNewExpr(RefType.v(bclass.getName())));
break;
}
case ByteCode.CHECKCAST:
{
String className = getClassName(constant_pool, ((Instruction_Checkcast) ins).arg_i);
Type castType;
if (className.startsWith("["))
castType = Util.v().jimpleTypeOfFieldDescriptor(getClassName(constant_pool, ((Instruction_Checkcast) ins).arg_i));
else
castType = RefType.v(className);
rhs = Jimple.v().newCastExpr(Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()), castType);
stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack, postTypeStack.topIndex()), rhs);
break;
}
case ByteCode.INSTANCEOF:
{
Type checkType;
String className = getClassName(constant_pool, ((Instruction_Instanceof) ins).arg_i);
if (className.startsWith("["))
checkType = Util.v().jimpleTypeOfFieldDescriptor(getClassName(constant_pool, ((Instruction_Instanceof) ins).arg_i));
else
checkType = RefType.v(className);
rhs = Jimple.v().newInstanceOfExpr(Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()), checkType);
stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack, postTypeStack.topIndex()), rhs);
break;
}
case ByteCode.MONITORENTER:
stmt = Jimple.v().newEnterMonitorStmt(Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()));
break;
case ByteCode.MONITOREXIT:
stmt = Jimple.v().newExitMonitorStmt(Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()));
break;
default:
throw new RuntimeException("Unrecognized bytecode instruction: " + x);
}
if (stmt != null) {
if (Options.v().keep_offset()) {
stmt.addTag(new BytecodeOffsetTag(ins.label));
}
statements.add(stmt);
}
}
use of soot.ArrayType in project soot by Sable.
the class BafASMBackend method generateInstruction.
/**
* Emits the bytecode for a single Baf instruction
*
* @param mv
* The ASM MethodVisitor the bytecode is to be emitted to
* @param inst
* The Baf instruction to be converted into bytecode
*/
protected void generateInstruction(final MethodVisitor mv, Inst inst) {
inst.apply(new InstSwitch() {
@Override
public void caseReturnVoidInst(ReturnVoidInst i) {
mv.visitInsn(Opcodes.RETURN);
}
@Override
public void caseReturnInst(ReturnInst i) {
i.getOpType().apply(new TypeSwitch() {
@Override
public void caseArrayType(ArrayType t) {
mv.visitInsn(Opcodes.ARETURN);
}
@Override
public void caseBooleanType(BooleanType t) {
mv.visitInsn(Opcodes.IRETURN);
}
@Override
public void caseByteType(ByteType t) {
mv.visitInsn(Opcodes.IRETURN);
}
@Override
public void caseCharType(CharType t) {
mv.visitInsn(Opcodes.IRETURN);
}
@Override
public void caseDoubleType(DoubleType t) {
mv.visitInsn(Opcodes.DRETURN);
}
@Override
public void caseFloatType(FloatType t) {
mv.visitInsn(Opcodes.FRETURN);
}
@Override
public void caseIntType(IntType t) {
mv.visitInsn(Opcodes.IRETURN);
}
@Override
public void caseLongType(LongType t) {
mv.visitInsn(Opcodes.LRETURN);
}
@Override
public void caseRefType(RefType t) {
mv.visitInsn(Opcodes.ARETURN);
}
@Override
public void caseShortType(ShortType t) {
mv.visitInsn(Opcodes.IRETURN);
}
@Override
public void caseNullType(NullType t) {
mv.visitInsn(Opcodes.ARETURN);
}
@Override
public void defaultCase(Type t) {
throw new RuntimeException("Invalid return type " + t.toString());
}
});
}
@Override
public void caseNopInst(NopInst i) {
mv.visitInsn(Opcodes.NOP);
}
@Override
public void caseJSRInst(JSRInst i) {
mv.visitJumpInsn(Opcodes.JSR, getBranchTargetLabel(i.getTarget()));
}
@Override
public void casePushInst(PushInst i) {
Constant c = i.getConstant();
if (c instanceof IntConstant) {
int v = ((IntConstant) c).value;
switch(v) {
case -1:
mv.visitInsn(Opcodes.ICONST_M1);
break;
case 0:
mv.visitInsn(Opcodes.ICONST_0);
break;
case 1:
mv.visitInsn(Opcodes.ICONST_1);
break;
case 2:
mv.visitInsn(Opcodes.ICONST_2);
break;
case 3:
mv.visitInsn(Opcodes.ICONST_3);
break;
case 4:
mv.visitInsn(Opcodes.ICONST_4);
break;
case 5:
mv.visitInsn(Opcodes.ICONST_5);
break;
default:
if (v >= Byte.MIN_VALUE && v <= Byte.MAX_VALUE) {
mv.visitIntInsn(Opcodes.BIPUSH, v);
} else if (v >= Short.MIN_VALUE && v <= Short.MAX_VALUE) {
mv.visitIntInsn(Opcodes.SIPUSH, v);
} else {
mv.visitLdcInsn(v);
}
}
} else if (c instanceof StringConstant) {
mv.visitLdcInsn(((StringConstant) c).value);
} else if (c instanceof ClassConstant) {
mv.visitLdcInsn(org.objectweb.asm.Type.getType(((ClassConstant) c).getValue()));
} else if (c instanceof DoubleConstant) {
double v = ((DoubleConstant) c).value;
/*
* Do not emit a DCONST_0 for negative zero, therefore we
* need the following check.
*/
if (new Double(v).equals(0.0)) {
mv.visitInsn(Opcodes.DCONST_0);
} else if (v == 1) {
mv.visitInsn(Opcodes.DCONST_1);
} else {
mv.visitLdcInsn(v);
}
} else if (c instanceof FloatConstant) {
float v = ((FloatConstant) c).value;
/*
* Do not emit a FCONST_0 for negative zero, therefore we
* need the following check.
*/
if (new Float(v).equals(0.0f)) {
mv.visitInsn(Opcodes.FCONST_0);
} else if (v == 1) {
mv.visitInsn(Opcodes.FCONST_1);
} else if (v == 2) {
mv.visitInsn(Opcodes.FCONST_2);
} else {
mv.visitLdcInsn(v);
}
} else if (c instanceof LongConstant) {
long v = ((LongConstant) c).value;
if (v == 0) {
mv.visitInsn(Opcodes.LCONST_0);
} else if (v == 1) {
mv.visitInsn(Opcodes.LCONST_1);
} else {
mv.visitLdcInsn(v);
}
} else if (c instanceof NullConstant) {
mv.visitInsn(Opcodes.ACONST_NULL);
} else if (c instanceof MethodHandle) {
SootMethodRef ref = ((MethodHandle) c).getMethodRef();
int tag;
if (ref.isStatic()) {
tag = Opcodes.H_INVOKESTATIC;
} else if (ref.declaringClass().isInterface()) {
tag = Opcodes.H_INVOKEINTERFACE;
} else {
tag = Opcodes.H_INVOKEVIRTUAL;
}
Handle handle = new Handle(tag, ref.declaringClass().getName(), ref.name(), ref.getSignature(), ref.declaringClass().isInnerClass());
mv.visitLdcInsn(handle);
} else {
throw new RuntimeException("unsupported opcode");
}
}
@Override
public void casePopInst(PopInst i) {
if (i.getWordCount() == 2) {
mv.visitInsn(Opcodes.POP2);
} else {
mv.visitInsn(Opcodes.POP);
}
}
@Override
public void caseIdentityInst(IdentityInst i) {
Value l = i.getLeftOp();
Value r = i.getRightOp();
if (r instanceof CaughtExceptionRef && l instanceof Local) {
mv.visitVarInsn(Opcodes.ASTORE, localToSlot.get(l));
// asm handles constant opcodes automatically here
}
}
@Override
public void caseStoreInst(StoreInst i) {
final int slot = localToSlot.get(i.getLocal());
i.getOpType().apply(new TypeSwitch() {
@Override
public void caseArrayType(ArrayType t) {
mv.visitVarInsn(Opcodes.ASTORE, slot);
}
@Override
public void caseBooleanType(BooleanType t) {
mv.visitVarInsn(Opcodes.ISTORE, slot);
}
@Override
public void caseByteType(ByteType t) {
mv.visitVarInsn(Opcodes.ISTORE, slot);
}
@Override
public void caseCharType(CharType t) {
mv.visitVarInsn(Opcodes.ISTORE, slot);
}
@Override
public void caseDoubleType(DoubleType t) {
mv.visitVarInsn(Opcodes.DSTORE, slot);
}
@Override
public void caseFloatType(FloatType t) {
mv.visitVarInsn(Opcodes.FSTORE, slot);
}
@Override
public void caseIntType(IntType t) {
mv.visitVarInsn(Opcodes.ISTORE, slot);
}
@Override
public void caseLongType(LongType t) {
mv.visitVarInsn(Opcodes.LSTORE, slot);
}
@Override
public void caseRefType(RefType t) {
mv.visitVarInsn(Opcodes.ASTORE, slot);
}
@Override
public void caseShortType(ShortType t) {
mv.visitVarInsn(Opcodes.ISTORE, slot);
}
@Override
public void caseStmtAddressType(StmtAddressType t) {
throw new RuntimeException("JSR not supported, use recent Java compiler!");
}
@Override
public void caseNullType(NullType t) {
mv.visitVarInsn(Opcodes.ASTORE, slot);
}
@Override
public void defaultCase(Type t) {
throw new RuntimeException("Invalid local type: " + t);
}
});
}
@Override
public void caseGotoInst(GotoInst i) {
mv.visitJumpInsn(Opcodes.GOTO, getBranchTargetLabel(i.getTarget()));
}
@Override
public void caseLoadInst(LoadInst i) {
final int slot = localToSlot.get(i.getLocal());
i.getOpType().apply(new TypeSwitch() {
@Override
public void caseArrayType(ArrayType t) {
mv.visitVarInsn(Opcodes.ALOAD, slot);
}
@Override
public void caseBooleanType(BooleanType t) {
mv.visitVarInsn(Opcodes.ILOAD, slot);
}
@Override
public void caseByteType(ByteType t) {
mv.visitVarInsn(Opcodes.ILOAD, slot);
}
@Override
public void caseCharType(CharType t) {
mv.visitVarInsn(Opcodes.ILOAD, slot);
}
@Override
public void caseDoubleType(DoubleType t) {
mv.visitVarInsn(Opcodes.DLOAD, slot);
}
@Override
public void caseFloatType(FloatType t) {
mv.visitVarInsn(Opcodes.FLOAD, slot);
}
@Override
public void caseIntType(IntType t) {
mv.visitVarInsn(Opcodes.ILOAD, slot);
}
@Override
public void caseLongType(LongType t) {
mv.visitVarInsn(Opcodes.LLOAD, slot);
}
@Override
public void caseRefType(RefType t) {
mv.visitVarInsn(Opcodes.ALOAD, slot);
}
@Override
public void caseShortType(ShortType t) {
mv.visitVarInsn(Opcodes.ILOAD, slot);
}
@Override
public void caseNullType(NullType t) {
mv.visitVarInsn(Opcodes.ALOAD, slot);
}
@Override
public void defaultCase(Type t) {
throw new RuntimeException("Invalid local type: " + t);
}
});
}
@Override
public void caseArrayWriteInst(ArrayWriteInst i) {
i.getOpType().apply(new TypeSwitch() {
@Override
public void caseArrayType(ArrayType t) {
mv.visitInsn(Opcodes.AASTORE);
}
@Override
public void caseBooleanType(BooleanType t) {
mv.visitInsn(Opcodes.BASTORE);
}
@Override
public void caseByteType(ByteType t) {
mv.visitInsn(Opcodes.BASTORE);
}
@Override
public void caseCharType(CharType t) {
mv.visitInsn(Opcodes.CASTORE);
}
@Override
public void caseDoubleType(DoubleType t) {
mv.visitInsn(Opcodes.DASTORE);
}
@Override
public void caseFloatType(FloatType t) {
mv.visitInsn(Opcodes.FASTORE);
}
@Override
public void caseIntType(IntType t) {
mv.visitInsn(Opcodes.IASTORE);
}
@Override
public void caseLongType(LongType t) {
mv.visitInsn(Opcodes.LASTORE);
}
@Override
public void caseRefType(RefType t) {
mv.visitInsn(Opcodes.AASTORE);
}
@Override
public void caseShortType(ShortType t) {
mv.visitInsn(Opcodes.SASTORE);
}
@Override
public void defaultCase(Type t) {
throw new RuntimeException("Invalid type: " + t);
}
});
}
@Override
public void caseArrayReadInst(ArrayReadInst i) {
i.getOpType().apply(new TypeSwitch() {
@Override
public void caseArrayType(ArrayType t) {
mv.visitInsn(Opcodes.AALOAD);
}
@Override
public void caseBooleanType(BooleanType t) {
mv.visitInsn(Opcodes.BALOAD);
}
@Override
public void caseByteType(ByteType t) {
mv.visitInsn(Opcodes.BALOAD);
}
@Override
public void caseCharType(CharType t) {
mv.visitInsn(Opcodes.CALOAD);
}
@Override
public void caseDoubleType(DoubleType t) {
mv.visitInsn(Opcodes.DALOAD);
}
@Override
public void caseFloatType(FloatType t) {
mv.visitInsn(Opcodes.FALOAD);
}
@Override
public void caseIntType(IntType t) {
mv.visitInsn(Opcodes.IALOAD);
}
@Override
public void caseLongType(LongType t) {
mv.visitInsn(Opcodes.LALOAD);
}
@Override
public void caseRefType(RefType t) {
mv.visitInsn(Opcodes.AALOAD);
}
@Override
public void caseShortType(ShortType t) {
mv.visitInsn(Opcodes.SALOAD);
}
@Override
public void caseNullType(NullType t) {
mv.visitInsn(Opcodes.AALOAD);
}
@Override
public void defaultCase(Type t) {
throw new RuntimeException("Invalid type: " + t);
}
});
}
@Override
public void caseIfNullInst(IfNullInst i) {
mv.visitJumpInsn(Opcodes.IFNULL, getBranchTargetLabel(i.getTarget()));
}
@Override
public void caseIfNonNullInst(IfNonNullInst i) {
mv.visitJumpInsn(Opcodes.IFNONNULL, getBranchTargetLabel(i.getTarget()));
}
@Override
public void caseIfEqInst(IfEqInst i) {
mv.visitJumpInsn(Opcodes.IFEQ, getBranchTargetLabel(i.getTarget()));
}
@Override
public void caseIfNeInst(IfNeInst i) {
mv.visitJumpInsn(Opcodes.IFNE, getBranchTargetLabel(i.getTarget()));
}
@Override
public void caseIfGtInst(IfGtInst i) {
mv.visitJumpInsn(Opcodes.IFGT, getBranchTargetLabel(i.getTarget()));
}
@Override
public void caseIfGeInst(IfGeInst i) {
mv.visitJumpInsn(Opcodes.IFGE, getBranchTargetLabel(i.getTarget()));
}
@Override
public void caseIfLtInst(IfLtInst i) {
mv.visitJumpInsn(Opcodes.IFLT, getBranchTargetLabel(i.getTarget()));
}
@Override
public void caseIfLeInst(IfLeInst i) {
mv.visitJumpInsn(Opcodes.IFLE, getBranchTargetLabel(i.getTarget()));
}
@Override
public void caseIfCmpEqInst(final IfCmpEqInst i) {
i.getOpType().apply(new TypeSwitch() {
@Override
public void caseArrayType(ArrayType t) {
mv.visitJumpInsn(Opcodes.IF_ACMPEQ, getBranchTargetLabel(i.getTarget()));
}
@Override
public void caseBooleanType(BooleanType t) {
mv.visitJumpInsn(Opcodes.IF_ICMPEQ, getBranchTargetLabel(i.getTarget()));
}
@Override
public void caseByteType(ByteType t) {
mv.visitJumpInsn(Opcodes.IF_ICMPEQ, getBranchTargetLabel(i.getTarget()));
}
@Override
public void caseCharType(CharType t) {
mv.visitJumpInsn(Opcodes.IF_ICMPEQ, getBranchTargetLabel(i.getTarget()));
}
@Override
public void caseDoubleType(DoubleType t) {
mv.visitInsn(Opcodes.DCMPG);
mv.visitJumpInsn(Opcodes.IFEQ, getBranchTargetLabel(i.getTarget()));
}
@Override
public void caseFloatType(FloatType t) {
mv.visitInsn(Opcodes.FCMPG);
mv.visitJumpInsn(Opcodes.IFEQ, getBranchTargetLabel(i.getTarget()));
}
@Override
public void caseIntType(IntType t) {
mv.visitJumpInsn(Opcodes.IF_ICMPEQ, getBranchTargetLabel(i.getTarget()));
}
@Override
public void caseLongType(LongType t) {
mv.visitInsn(Opcodes.LCMP);
mv.visitJumpInsn(Opcodes.IFEQ, getBranchTargetLabel(i.getTarget()));
}
@Override
public void caseRefType(RefType t) {
mv.visitJumpInsn(Opcodes.IF_ACMPEQ, getBranchTargetLabel(i.getTarget()));
}
@Override
public void caseShortType(ShortType t) {
mv.visitJumpInsn(Opcodes.IF_ICMPEQ, getBranchTargetLabel(i.getTarget()));
}
@Override
public void caseNullType(NullType t) {
mv.visitJumpInsn(Opcodes.IF_ACMPEQ, getBranchTargetLabel(i.getTarget()));
}
@Override
public void defaultCase(Type t) {
throw new RuntimeException("invalid type");
}
});
}
@Override
public void caseIfCmpNeInst(final IfCmpNeInst i) {
i.getOpType().apply(new TypeSwitch() {
@Override
public void caseArrayType(ArrayType t) {
mv.visitJumpInsn(Opcodes.IF_ACMPNE, getBranchTargetLabel(i.getTarget()));
}
@Override
public void caseBooleanType(BooleanType t) {
mv.visitJumpInsn(Opcodes.IF_ICMPNE, getBranchTargetLabel(i.getTarget()));
}
@Override
public void caseByteType(ByteType t) {
mv.visitJumpInsn(Opcodes.IF_ICMPNE, getBranchTargetLabel(i.getTarget()));
}
@Override
public void caseCharType(CharType t) {
mv.visitJumpInsn(Opcodes.IF_ICMPNE, getBranchTargetLabel(i.getTarget()));
}
@Override
public void caseDoubleType(DoubleType t) {
mv.visitInsn(Opcodes.DCMPG);
mv.visitJumpInsn(Opcodes.IFNE, getBranchTargetLabel(i.getTarget()));
}
@Override
public void caseFloatType(FloatType t) {
mv.visitInsn(Opcodes.FCMPG);
mv.visitJumpInsn(Opcodes.IFNE, getBranchTargetLabel(i.getTarget()));
}
@Override
public void caseIntType(IntType t) {
mv.visitJumpInsn(Opcodes.IF_ICMPNE, getBranchTargetLabel(i.getTarget()));
}
@Override
public void caseLongType(LongType t) {
mv.visitInsn(Opcodes.LCMP);
mv.visitJumpInsn(Opcodes.IFNE, getBranchTargetLabel(i.getTarget()));
}
@Override
public void caseRefType(RefType t) {
mv.visitJumpInsn(Opcodes.IF_ACMPNE, getBranchTargetLabel(i.getTarget()));
}
@Override
public void caseShortType(ShortType t) {
mv.visitJumpInsn(Opcodes.IF_ICMPNE, getBranchTargetLabel(i.getTarget()));
}
@Override
public void caseNullType(NullType t) {
mv.visitJumpInsn(Opcodes.IF_ACMPNE, getBranchTargetLabel(i.getTarget()));
}
@Override
public void defaultCase(Type t) {
throw new RuntimeException("invalid type");
}
});
}
@Override
public void caseIfCmpGtInst(final IfCmpGtInst i) {
i.getOpType().apply(new TypeSwitch() {
@Override
public void caseBooleanType(BooleanType t) {
mv.visitJumpInsn(Opcodes.IF_ICMPGT, getBranchTargetLabel(i.getTarget()));
}
@Override
public void caseByteType(ByteType t) {
mv.visitJumpInsn(Opcodes.IF_ICMPGT, getBranchTargetLabel(i.getTarget()));
}
@Override
public void caseCharType(CharType t) {
mv.visitJumpInsn(Opcodes.IF_ICMPGT, getBranchTargetLabel(i.getTarget()));
}
@Override
public void caseDoubleType(DoubleType t) {
mv.visitInsn(Opcodes.DCMPG);
mv.visitJumpInsn(Opcodes.IFGT, getBranchTargetLabel(i.getTarget()));
}
@Override
public void caseFloatType(FloatType t) {
mv.visitInsn(Opcodes.FCMPG);
mv.visitJumpInsn(Opcodes.IFGT, getBranchTargetLabel(i.getTarget()));
}
@Override
public void caseIntType(IntType t) {
mv.visitJumpInsn(Opcodes.IF_ICMPGT, getBranchTargetLabel(i.getTarget()));
}
@Override
public void caseLongType(LongType t) {
mv.visitInsn(Opcodes.LCMP);
mv.visitJumpInsn(Opcodes.IFGT, getBranchTargetLabel(i.getTarget()));
}
@Override
public void caseShortType(ShortType t) {
mv.visitJumpInsn(Opcodes.IF_ICMPGT, getBranchTargetLabel(i.getTarget()));
}
@Override
public void defaultCase(Type t) {
throw new RuntimeException("invalid type");
}
});
}
@Override
public void caseIfCmpGeInst(final IfCmpGeInst i) {
i.getOpType().apply(new TypeSwitch() {
@Override
public void caseBooleanType(BooleanType t) {
mv.visitJumpInsn(Opcodes.IF_ICMPGE, getBranchTargetLabel(i.getTarget()));
}
@Override
public void caseByteType(ByteType t) {
mv.visitJumpInsn(Opcodes.IF_ICMPGE, getBranchTargetLabel(i.getTarget()));
}
@Override
public void caseCharType(CharType t) {
mv.visitJumpInsn(Opcodes.IF_ICMPGE, getBranchTargetLabel(i.getTarget()));
}
@Override
public void caseDoubleType(DoubleType t) {
mv.visitInsn(Opcodes.DCMPG);
mv.visitJumpInsn(Opcodes.IFGE, getBranchTargetLabel(i.getTarget()));
}
@Override
public void caseFloatType(FloatType t) {
mv.visitInsn(Opcodes.FCMPG);
mv.visitJumpInsn(Opcodes.IFGE, getBranchTargetLabel(i.getTarget()));
}
@Override
public void caseIntType(IntType t) {
mv.visitJumpInsn(Opcodes.IF_ICMPGE, getBranchTargetLabel(i.getTarget()));
}
@Override
public void caseLongType(LongType t) {
mv.visitInsn(Opcodes.LCMP);
mv.visitJumpInsn(Opcodes.IFGE, getBranchTargetLabel(i.getTarget()));
}
@Override
public void caseShortType(ShortType t) {
mv.visitJumpInsn(Opcodes.IF_ICMPGE, getBranchTargetLabel(i.getTarget()));
}
@Override
public void defaultCase(Type t) {
throw new RuntimeException("invalid type");
}
});
}
@Override
public void caseIfCmpLtInst(final IfCmpLtInst i) {
i.getOpType().apply(new TypeSwitch() {
@Override
public void caseBooleanType(BooleanType t) {
mv.visitJumpInsn(Opcodes.IF_ICMPLT, getBranchTargetLabel(i.getTarget()));
}
@Override
public void caseByteType(ByteType t) {
mv.visitJumpInsn(Opcodes.IF_ICMPLT, getBranchTargetLabel(i.getTarget()));
}
@Override
public void caseCharType(CharType t) {
mv.visitJumpInsn(Opcodes.IF_ICMPLT, getBranchTargetLabel(i.getTarget()));
}
@Override
public void caseDoubleType(DoubleType t) {
mv.visitInsn(Opcodes.DCMPG);
mv.visitJumpInsn(Opcodes.IFLT, getBranchTargetLabel(i.getTarget()));
}
@Override
public void caseFloatType(FloatType t) {
mv.visitInsn(Opcodes.FCMPG);
mv.visitJumpInsn(Opcodes.IFLT, getBranchTargetLabel(i.getTarget()));
}
@Override
public void caseIntType(IntType t) {
mv.visitJumpInsn(Opcodes.IF_ICMPLT, getBranchTargetLabel(i.getTarget()));
}
@Override
public void caseLongType(LongType t) {
mv.visitInsn(Opcodes.LCMP);
mv.visitJumpInsn(Opcodes.IFLT, getBranchTargetLabel(i.getTarget()));
}
@Override
public void caseShortType(ShortType t) {
mv.visitJumpInsn(Opcodes.IF_ICMPLT, getBranchTargetLabel(i.getTarget()));
}
@Override
public void defaultCase(Type t) {
throw new RuntimeException("invalid type");
}
});
}
@Override
public void caseIfCmpLeInst(final IfCmpLeInst i) {
i.getOpType().apply(new TypeSwitch() {
@Override
public void caseBooleanType(BooleanType t) {
mv.visitJumpInsn(Opcodes.IF_ICMPLE, getBranchTargetLabel(i.getTarget()));
}
@Override
public void caseByteType(ByteType t) {
mv.visitJumpInsn(Opcodes.IF_ICMPLE, getBranchTargetLabel(i.getTarget()));
}
@Override
public void caseCharType(CharType t) {
mv.visitJumpInsn(Opcodes.IF_ICMPLE, getBranchTargetLabel(i.getTarget()));
}
@Override
public void caseDoubleType(DoubleType t) {
mv.visitInsn(Opcodes.DCMPG);
mv.visitJumpInsn(Opcodes.IFLE, getBranchTargetLabel(i.getTarget()));
}
@Override
public void caseFloatType(FloatType t) {
mv.visitInsn(Opcodes.FCMPG);
mv.visitJumpInsn(Opcodes.IFLE, getBranchTargetLabel(i.getTarget()));
}
@Override
public void caseIntType(IntType t) {
mv.visitJumpInsn(Opcodes.IF_ICMPLE, getBranchTargetLabel(i.getTarget()));
}
@Override
public void caseLongType(LongType t) {
mv.visitInsn(Opcodes.LCMP);
mv.visitJumpInsn(Opcodes.IFLE, getBranchTargetLabel(i.getTarget()));
}
@Override
public void caseShortType(ShortType t) {
mv.visitJumpInsn(Opcodes.IF_ICMPLE, getBranchTargetLabel(i.getTarget()));
}
@Override
public void defaultCase(Type t) {
throw new RuntimeException("invalid type");
}
});
}
@Override
public void caseStaticGetInst(StaticGetInst i) {
SootFieldRef field = i.getFieldRef();
mv.visitFieldInsn(Opcodes.GETSTATIC, slashify(field.declaringClass().getName()), field.name(), toTypeDesc(field.type()));
}
@Override
public void caseStaticPutInst(StaticPutInst i) {
SootFieldRef field = i.getFieldRef();
mv.visitFieldInsn(Opcodes.PUTSTATIC, slashify(field.declaringClass().getName()), field.name(), toTypeDesc(field.type()));
}
@Override
public void caseFieldGetInst(FieldGetInst i) {
SootFieldRef field = i.getFieldRef();
mv.visitFieldInsn(Opcodes.GETFIELD, slashify(field.declaringClass().getName()), field.name(), toTypeDesc(field.type()));
}
@Override
public void caseFieldPutInst(FieldPutInst i) {
SootFieldRef field = i.getFieldRef();
mv.visitFieldInsn(Opcodes.PUTFIELD, slashify(field.declaringClass().getName()), field.name(), toTypeDesc(field.type()));
}
@Override
public void caseInstanceCastInst(InstanceCastInst i) {
Type castType = i.getCastType();
if (castType instanceof RefType) {
mv.visitTypeInsn(Opcodes.CHECKCAST, slashify(((RefType) castType).getClassName()));
} else if (castType instanceof ArrayType) {
mv.visitTypeInsn(Opcodes.CHECKCAST, toTypeDesc(castType));
}
}
@Override
public void caseInstanceOfInst(InstanceOfInst i) {
Type checkType = i.getCheckType();
if (checkType instanceof RefType) {
mv.visitTypeInsn(Opcodes.INSTANCEOF, slashify(((RefType) checkType).getClassName()));
} else if (checkType instanceof ArrayType) {
mv.visitTypeInsn(Opcodes.INSTANCEOF, toTypeDesc(checkType));
}
}
@Override
public void casePrimitiveCastInst(PrimitiveCastInst i) {
Type from = i.getFromType();
final Type to = i.getToType();
from.apply(new TypeSwitch() {
@Override
public void caseBooleanType(BooleanType t) {
emitIntToTypeCast();
}
@Override
public void caseByteType(ByteType t) {
emitIntToTypeCast();
}
@Override
public void caseCharType(CharType t) {
emitIntToTypeCast();
}
@Override
public void caseDoubleType(DoubleType t) {
if (to.equals(IntType.v())) {
mv.visitInsn(Opcodes.D2I);
} else if (to.equals(LongType.v())) {
mv.visitInsn(Opcodes.D2L);
} else if (to.equals(FloatType.v())) {
mv.visitInsn(Opcodes.D2F);
} else {
throw new RuntimeException("invalid to-type from double");
}
}
@Override
public void caseFloatType(FloatType t) {
if (to.equals(IntType.v())) {
mv.visitInsn(Opcodes.F2I);
} else if (to.equals(LongType.v())) {
mv.visitInsn(Opcodes.F2L);
} else if (to.equals(DoubleType.v())) {
mv.visitInsn(Opcodes.F2D);
} else {
throw new RuntimeException("invalid to-type from float");
}
}
@Override
public void caseIntType(IntType t) {
emitIntToTypeCast();
}
@Override
public void caseLongType(LongType t) {
if (to.equals(IntType.v())) {
mv.visitInsn(Opcodes.L2I);
} else if (to.equals(FloatType.v())) {
mv.visitInsn(Opcodes.L2F);
} else if (to.equals(DoubleType.v())) {
mv.visitInsn(Opcodes.L2D);
} else {
throw new RuntimeException("invalid to-type from long");
}
}
@Override
public void caseShortType(ShortType t) {
emitIntToTypeCast();
}
@Override
public void defaultCase(Type t) {
throw new RuntimeException("invalid from-type: " + t);
}
private void emitIntToTypeCast() {
if (to.equals(ByteType.v())) {
mv.visitInsn(Opcodes.I2B);
} else if (to.equals(CharType.v())) {
mv.visitInsn(Opcodes.I2C);
} else if (to.equals(ShortType.v())) {
mv.visitInsn(Opcodes.I2S);
} else if (to.equals(FloatType.v())) {
mv.visitInsn(Opcodes.I2F);
} else if (to.equals(LongType.v())) {
mv.visitInsn(Opcodes.I2L);
} else if (to.equals(DoubleType.v())) {
mv.visitInsn(Opcodes.I2D);
} else if (to.equals(IntType.v())) {
} else if (to.equals(BooleanType.v())) {
} else {
throw new RuntimeException("invalid to-type from int");
}
}
});
}
@Override
public void caseDynamicInvokeInst(DynamicInvokeInst i) {
SootMethodRef m = i.getMethodRef();
SootMethodRef bsm = i.getBootstrapMethodRef();
List<Value> args = i.getBootstrapArgs();
final Object[] argsArray = new Object[args.size()];
int index = 0;
for (Value v : args) {
final int j = index;
v.apply(new ConstantSwitch() {
@Override
public void defaultCase(Object object) {
throw new RuntimeException("Unexpected constant type!");
}
@Override
public void caseStringConstant(StringConstant v) {
argsArray[j] = v.value;
}
@Override
public void caseNullConstant(NullConstant v) {
/*
* The Jasmin-backend throws an exception for the
* null-type.
*/
throw new RuntimeException("Unexpected NullType as argument-type in invokedynamic!");
}
@Override
public void caseMethodHandle(MethodHandle handle) {
SootMethodRef methodRef = handle.getMethodRef();
argsArray[j] = new Handle(handle.tag, slashify(methodRef.declaringClass().getName()), methodRef.name(), toTypeDesc(methodRef));
}
@Override
public void caseLongConstant(LongConstant v) {
argsArray[j] = v.value;
}
@Override
public void caseIntConstant(IntConstant v) {
argsArray[j] = v.value;
}
@Override
public void caseFloatConstant(FloatConstant v) {
argsArray[j] = v.value;
}
@Override
public void caseDoubleConstant(DoubleConstant v) {
argsArray[j] = v.value;
}
@Override
public void caseClassConstant(ClassConstant v) {
argsArray[j] = org.objectweb.asm.Type.getType(v.getValue());
}
});
++index;
}
mv.visitInvokeDynamicInsn(m.name(), toTypeDesc(m), new Handle(i.getHandleTag(), slashify(bsm.declaringClass().getName()), bsm.name(), toTypeDesc(bsm)), argsArray);
}
@Override
public void caseStaticInvokeInst(StaticInvokeInst i) {
SootMethodRef m = i.getMethodRef();
mv.visitMethodInsn(Opcodes.INVOKESTATIC, slashify(m.declaringClass().getName()), m.name(), toTypeDesc(m), m.declaringClass().isInterface() && !m.isStatic());
}
@Override
public void caseVirtualInvokeInst(VirtualInvokeInst i) {
SootMethodRef m = i.getMethodRef();
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, slashify(m.declaringClass().getName()), m.name(), toTypeDesc(m), m.declaringClass().isInterface());
}
@Override
public void caseInterfaceInvokeInst(InterfaceInvokeInst i) {
SootMethodRef m = i.getMethodRef();
SootClass declaration = m.declaringClass();
boolean isInterface = true;
if (!declaration.isPhantom() && !declaration.isInterface()) {
/*
* If the declaring class of a method called via
* invokeinterface is a phantom class we assume the
* declaring class to be an interface. This might not be
* true in general, but as of today Soot can not evaluate
* isInterface() for phantom classes correctly.
*/
isInterface = false;
}
mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, slashify(declaration.getName()), m.name(), toTypeDesc(m), isInterface);
}
@Override
public void caseSpecialInvokeInst(SpecialInvokeInst i) {
SootMethodRef m = i.getMethodRef();
mv.visitMethodInsn(Opcodes.INVOKESPECIAL, slashify(m.declaringClass().getName()), m.name(), toTypeDesc(m), m.declaringClass().isInterface());
}
@Override
public void caseThrowInst(ThrowInst i) {
mv.visitInsn(Opcodes.ATHROW);
}
@Override
public void caseAddInst(AddInst i) {
i.getOpType().apply(new TypeSwitch() {
@Override
public void caseBooleanType(BooleanType t) {
mv.visitInsn(Opcodes.IADD);
}
@Override
public void caseByteType(ByteType t) {
mv.visitInsn(Opcodes.IADD);
}
@Override
public void caseCharType(CharType t) {
mv.visitInsn(Opcodes.IADD);
}
@Override
public void caseDoubleType(DoubleType t) {
mv.visitInsn(Opcodes.DADD);
}
@Override
public void caseFloatType(FloatType t) {
mv.visitInsn(Opcodes.FADD);
}
@Override
public void caseIntType(IntType t) {
mv.visitInsn(Opcodes.IADD);
}
@Override
public void caseLongType(LongType t) {
mv.visitInsn(Opcodes.LADD);
}
@Override
public void caseShortType(ShortType t) {
mv.visitInsn(Opcodes.IADD);
}
@Override
public void defaultCase(Type t) {
throw new RuntimeException("invalid type");
}
});
}
@Override
public void caseAndInst(AndInst i) {
if (i.getOpType().equals(LongType.v())) {
mv.visitInsn(Opcodes.LAND);
} else {
mv.visitInsn(Opcodes.IAND);
}
}
@Override
public void caseOrInst(OrInst i) {
if (i.getOpType().equals(LongType.v())) {
mv.visitInsn(Opcodes.LOR);
} else {
mv.visitInsn(Opcodes.IOR);
}
}
@Override
public void caseXorInst(XorInst i) {
if (i.getOpType().equals(LongType.v())) {
mv.visitInsn(Opcodes.LXOR);
} else {
mv.visitInsn(Opcodes.IXOR);
}
}
@Override
public void caseArrayLengthInst(ArrayLengthInst i) {
mv.visitInsn(Opcodes.ARRAYLENGTH);
}
@Override
public void caseCmpInst(CmpInst i) {
mv.visitInsn(Opcodes.LCMP);
}
@Override
public void caseCmpgInst(CmpgInst i) {
if (i.getOpType().equals(FloatType.v())) {
mv.visitInsn(Opcodes.FCMPG);
} else {
mv.visitInsn(Opcodes.DCMPG);
}
}
@Override
public void caseCmplInst(CmplInst i) {
if (i.getOpType().equals(FloatType.v())) {
mv.visitInsn(Opcodes.FCMPL);
} else {
mv.visitInsn(Opcodes.DCMPL);
}
}
@Override
public void caseDivInst(DivInst i) {
i.getOpType().apply(new TypeSwitch() {
@Override
public void caseBooleanType(BooleanType t) {
mv.visitInsn(Opcodes.IDIV);
}
@Override
public void caseByteType(ByteType t) {
mv.visitInsn(Opcodes.IDIV);
}
@Override
public void caseCharType(CharType t) {
mv.visitInsn(Opcodes.IDIV);
}
@Override
public void caseDoubleType(DoubleType t) {
mv.visitInsn(Opcodes.DDIV);
}
@Override
public void caseFloatType(FloatType t) {
mv.visitInsn(Opcodes.FDIV);
}
@Override
public void caseIntType(IntType t) {
mv.visitInsn(Opcodes.IDIV);
}
@Override
public void caseLongType(LongType t) {
mv.visitInsn(Opcodes.LDIV);
}
@Override
public void caseShortType(ShortType t) {
mv.visitInsn(Opcodes.IDIV);
}
@Override
public void defaultCase(Type t) {
throw new RuntimeException("invalid type");
}
});
}
@Override
public void caseIncInst(IncInst i) {
if (i.getUseBoxes().get(0).getValue() != i.getDefBoxes().get(0).getValue()) {
throw new RuntimeException("iinc def and use boxes don't match");
}
if (i.getConstant() instanceof IntConstant) {
mv.visitIincInsn(localToSlot.get(i.getLocal()), ((IntConstant) i.getConstant()).value);
} else {
throw new RuntimeException("Wrong constant type for increment!");
}
}
@Override
public void caseMulInst(MulInst i) {
i.getOpType().apply(new TypeSwitch() {
@Override
public void caseBooleanType(BooleanType t) {
mv.visitInsn(Opcodes.IMUL);
}
@Override
public void caseByteType(ByteType t) {
mv.visitInsn(Opcodes.IMUL);
}
@Override
public void caseCharType(CharType t) {
mv.visitInsn(Opcodes.IMUL);
}
@Override
public void caseDoubleType(DoubleType t) {
mv.visitInsn(Opcodes.DMUL);
}
@Override
public void caseFloatType(FloatType t) {
mv.visitInsn(Opcodes.FMUL);
}
@Override
public void caseIntType(IntType t) {
mv.visitInsn(Opcodes.IMUL);
}
@Override
public void caseLongType(LongType t) {
mv.visitInsn(Opcodes.LMUL);
}
@Override
public void caseShortType(ShortType t) {
mv.visitInsn(Opcodes.IMUL);
}
@Override
public void defaultCase(Type t) {
throw new RuntimeException("invalid type");
}
});
}
@Override
public void caseRemInst(RemInst i) {
i.getOpType().apply(new TypeSwitch() {
@Override
public void caseBooleanType(BooleanType t) {
mv.visitInsn(Opcodes.IREM);
}
@Override
public void caseByteType(ByteType t) {
mv.visitInsn(Opcodes.IREM);
}
@Override
public void caseCharType(CharType t) {
mv.visitInsn(Opcodes.IREM);
}
@Override
public void caseDoubleType(DoubleType t) {
mv.visitInsn(Opcodes.DREM);
}
@Override
public void caseFloatType(FloatType t) {
mv.visitInsn(Opcodes.FREM);
}
@Override
public void caseIntType(IntType t) {
mv.visitInsn(Opcodes.IREM);
}
@Override
public void caseLongType(LongType t) {
mv.visitInsn(Opcodes.LREM);
}
@Override
public void caseShortType(ShortType t) {
mv.visitInsn(Opcodes.IREM);
}
@Override
public void defaultCase(Type t) {
throw new RuntimeException("invalid type");
}
});
}
@Override
public void caseSubInst(SubInst i) {
i.getOpType().apply(new TypeSwitch() {
@Override
public void caseBooleanType(BooleanType t) {
mv.visitInsn(Opcodes.ISUB);
}
@Override
public void caseByteType(ByteType t) {
mv.visitInsn(Opcodes.ISUB);
}
@Override
public void caseCharType(CharType t) {
mv.visitInsn(Opcodes.ISUB);
}
@Override
public void caseDoubleType(DoubleType t) {
mv.visitInsn(Opcodes.DSUB);
}
@Override
public void caseFloatType(FloatType t) {
mv.visitInsn(Opcodes.FSUB);
}
@Override
public void caseIntType(IntType t) {
mv.visitInsn(Opcodes.ISUB);
}
@Override
public void caseLongType(LongType t) {
mv.visitInsn(Opcodes.LSUB);
}
@Override
public void caseShortType(ShortType t) {
mv.visitInsn(Opcodes.ISUB);
}
@Override
public void defaultCase(Type t) {
throw new RuntimeException("invalid type");
}
});
}
@Override
public void caseShlInst(ShlInst i) {
if (i.getOpType().equals(LongType.v())) {
mv.visitInsn(Opcodes.LSHL);
} else {
mv.visitInsn(Opcodes.ISHL);
}
}
@Override
public void caseShrInst(ShrInst i) {
if (i.getOpType().equals(LongType.v())) {
mv.visitInsn(Opcodes.LSHR);
} else {
mv.visitInsn(Opcodes.ISHR);
}
}
@Override
public void caseUshrInst(UshrInst i) {
if (i.getOpType().equals(LongType.v())) {
mv.visitInsn(Opcodes.LUSHR);
} else {
mv.visitInsn(Opcodes.IUSHR);
}
}
@Override
public void caseNewInst(NewInst i) {
mv.visitTypeInsn(Opcodes.NEW, slashify(i.getBaseType().getClassName()));
}
@Override
public void caseNegInst(NegInst i) {
i.getOpType().apply(new TypeSwitch() {
@Override
public void caseBooleanType(BooleanType t) {
mv.visitInsn(Opcodes.INEG);
}
@Override
public void caseByteType(ByteType t) {
mv.visitInsn(Opcodes.INEG);
}
@Override
public void caseCharType(CharType t) {
mv.visitInsn(Opcodes.INEG);
}
@Override
public void caseDoubleType(DoubleType t) {
mv.visitInsn(Opcodes.DNEG);
}
@Override
public void caseFloatType(FloatType t) {
mv.visitInsn(Opcodes.FNEG);
}
@Override
public void caseIntType(IntType t) {
mv.visitInsn(Opcodes.INEG);
}
@Override
public void caseLongType(LongType t) {
mv.visitInsn(Opcodes.LNEG);
}
@Override
public void caseShortType(ShortType t) {
mv.visitInsn(Opcodes.INEG);
}
@Override
public void defaultCase(Type t) {
throw new RuntimeException("invalid type");
}
});
}
@Override
public void caseSwapInst(SwapInst i) {
mv.visitInsn(Opcodes.SWAP);
}
@Override
public void caseDup1Inst(Dup1Inst i) {
if (sizeOfType(i.getOp1Type()) == 2) {
mv.visitInsn(Opcodes.DUP2);
} else {
mv.visitInsn(Opcodes.DUP);
}
}
@Override
public void caseDup2Inst(Dup2Inst i) {
Type firstOpType = i.getOp1Type();
Type secondOpType = i.getOp2Type();
// Use a pair of instructions to simulate them.
if (sizeOfType(firstOpType) == 2) {
mv.visitInsn(Opcodes.DUP2);
if (sizeOfType(secondOpType) == 2) {
mv.visitInsn(Opcodes.DUP2);
} else {
mv.visitInsn(Opcodes.DUP);
}
} else if (sizeOfType(secondOpType) == 2) {
mv.visitInsn(Opcodes.DUP);
mv.visitInsn(Opcodes.DUP2);
} else {
mv.visitInsn(Opcodes.DUP2);
}
}
@Override
public void caseDup1_x1Inst(Dup1_x1Inst i) {
Type opType = i.getOp1Type();
Type underType = i.getUnder1Type();
if (sizeOfType(opType) == 2) {
if (sizeOfType(underType) == 2) {
mv.visitInsn(Opcodes.DUP2_X2);
} else {
mv.visitInsn(Opcodes.DUP2_X1);
}
} else {
if (sizeOfType(underType) == 2) {
mv.visitInsn(Opcodes.DUP_X2);
} else {
mv.visitInsn(Opcodes.DUP_X1);
}
}
}
@Override
public void caseDup1_x2Inst(Dup1_x2Inst i) {
int toSkip = sizeOfType(i.getUnder1Type()) + sizeOfType(i.getUnder2Type());
if (sizeOfType(i.getOp1Type()) == 2) {
if (toSkip == 2) {
mv.visitInsn(Opcodes.DUP2_X2);
} else {
throw new RuntimeException("magic not implemented yet");
}
} else {
if (toSkip == 2) {
mv.visitInsn(Opcodes.DUP_X2);
} else {
throw new RuntimeException("magic not implemented yet");
}
}
}
@Override
public void caseDup2_x1Inst(Dup2_x1Inst i) {
int toDup = sizeOfType(i.getOp1Type()) + sizeOfType(i.getOp2Type());
if (toDup == 2) {
if (sizeOfType(i.getUnder1Type()) == 2) {
mv.visitInsn(Opcodes.DUP2_X2);
} else {
mv.visitInsn(Opcodes.DUP2_X1);
}
} else {
throw new RuntimeException("magic not implemented yet");
}
}
@Override
public void caseDup2_x2Inst(Dup2_x2Inst i) {
int toDup = sizeOfType(i.getOp1Type()) + sizeOfType(i.getOp2Type());
int toSkip = sizeOfType(i.getUnder1Type()) + sizeOfType(i.getUnder2Type());
if (toDup > 2 || toSkip > 2) {
throw new RuntimeException("magic not implemented yet");
}
if (toDup == 2 && toSkip == 2) {
mv.visitInsn(Opcodes.DUP2_X2);
} else {
throw new RuntimeException("VoidType not allowed in Dup2_x2 Instruction");
}
}
@Override
public void caseNewArrayInst(NewArrayInst i) {
Type t = i.getBaseType();
if (t instanceof RefType) {
mv.visitTypeInsn(Opcodes.ANEWARRAY, slashify(((RefType) t).getClassName()));
} else if (t instanceof ArrayType) {
mv.visitTypeInsn(Opcodes.ANEWARRAY, toTypeDesc(t));
} else {
int type;
if (t.equals(BooleanType.v())) {
type = Opcodes.T_BOOLEAN;
} else if (t.equals(CharType.v())) {
type = Opcodes.T_CHAR;
} else if (t.equals(FloatType.v())) {
type = Opcodes.T_FLOAT;
} else if (t.equals(DoubleType.v())) {
type = Opcodes.T_DOUBLE;
} else if (t.equals(ByteType.v())) {
type = Opcodes.T_BYTE;
} else if (t.equals(ShortType.v())) {
type = Opcodes.T_SHORT;
} else if (t.equals(IntType.v())) {
type = Opcodes.T_INT;
} else if (t.equals(LongType.v())) {
type = Opcodes.T_LONG;
} else {
throw new RuntimeException("invalid type");
}
mv.visitIntInsn(Opcodes.NEWARRAY, type);
}
}
@Override
public void caseNewMultiArrayInst(NewMultiArrayInst i) {
mv.visitMultiANewArrayInsn(toTypeDesc(i.getBaseType()), i.getDimensionCount());
}
@Override
public void caseLookupSwitchInst(LookupSwitchInst i) {
List<IntConstant> values = i.getLookupValues();
List<Unit> targets = i.getTargets();
int[] keys = new int[values.size()];
Label[] labels = new Label[values.size()];
for (int j = 0; j < values.size(); j++) {
keys[j] = values.get(j).value;
labels[j] = branchTargetLabels.get(targets.get(j));
}
mv.visitLookupSwitchInsn(branchTargetLabels.get(i.getDefaultTarget()), keys, labels);
}
@Override
public void caseTableSwitchInst(TableSwitchInst i) {
List<Unit> targets = i.getTargets();
Label[] labels = new Label[targets.size()];
for (int j = 0; j < targets.size(); j++) {
labels[j] = branchTargetLabels.get(targets.get(j));
}
mv.visitTableSwitchInsn(i.getLowIndex(), i.getHighIndex(), branchTargetLabels.get(i.getDefaultTarget()), labels);
}
@Override
public void caseEnterMonitorInst(EnterMonitorInst i) {
mv.visitInsn(Opcodes.MONITORENTER);
}
@Override
public void caseExitMonitorInst(ExitMonitorInst i) {
mv.visitInsn(Opcodes.MONITOREXIT);
}
});
}
Aggregations