use of soot.jimple.NullConstant in project soot by Sable.
the class ConstraintChecker method caseAssignStmt.
public void caseAssignStmt(AssignStmt stmt) {
Value l = stmt.getLeftOp();
Value r = stmt.getRightOp();
TypeNode left = null;
TypeNode right = null;
if (l instanceof ArrayRef) {
ArrayRef ref = (ArrayRef) l;
Type baset = ((Local) ref.getBase()).getType();
if (baset instanceof ArrayType) {
ArrayType base = (ArrayType) baset;
Value index = ref.getIndex();
if ((base.numDimensions == 1) && (base.baseType instanceof IntegerType)) {
left = ClassHierarchy.v().typeNode(base.baseType);
}
if (index instanceof Local) {
if (!ClassHierarchy.v().typeNode(((Local) index).getType()).hasAncestor_1(ClassHierarchy.v().INT)) {
if (fix) {
ref.setIndex(insertCast((Local) index, IntType.v(), stmt));
} else {
error("Type Error(5)");
}
}
}
}
} else if (l instanceof Local) {
if (((Local) l).getType() instanceof IntegerType) {
left = ClassHierarchy.v().typeNode(((Local) l).getType());
}
} else if (l instanceof InstanceFieldRef) {
InstanceFieldRef ref = (InstanceFieldRef) l;
if (ref.getFieldRef().type() instanceof IntegerType) {
left = ClassHierarchy.v().typeNode(ref.getFieldRef().type());
}
} else if (l instanceof StaticFieldRef) {
StaticFieldRef ref = (StaticFieldRef) l;
if (ref.getFieldRef().type() instanceof IntegerType) {
left = ClassHierarchy.v().typeNode(ref.getFieldRef().type());
}
} else {
throw new RuntimeException("Unhandled assignment left hand side type: " + l.getClass());
}
if (r instanceof ArrayRef) {
ArrayRef ref = (ArrayRef) r;
Type baset = ((Local) ref.getBase()).getType();
if (!(baset instanceof NullType)) {
ArrayType base = (ArrayType) baset;
Value index = ref.getIndex();
if ((base.numDimensions == 1) && (base.baseType instanceof IntegerType)) {
right = ClassHierarchy.v().typeNode(base.baseType);
}
if (index instanceof Local) {
if (!ClassHierarchy.v().typeNode(((Local) index).getType()).hasAncestor_1(ClassHierarchy.v().INT)) {
if (fix) {
ref.setIndex(insertCast((Local) index, IntType.v(), stmt));
} else {
error("Type Error(6)");
}
}
}
}
} else if (r instanceof DoubleConstant) {
} else if (r instanceof FloatConstant) {
} else if (r instanceof IntConstant) {
int value = ((IntConstant) r).value;
if (value < -32768) {
right = ClassHierarchy.v().INT;
} else if (value < -128) {
right = ClassHierarchy.v().SHORT;
} else if (value < 0) {
right = ClassHierarchy.v().BYTE;
} else if (value < 2) {
right = ClassHierarchy.v().R0_1;
} else if (value < 128) {
right = ClassHierarchy.v().R0_127;
} else if (value < 32768) {
right = ClassHierarchy.v().R0_32767;
} else if (value < 65536) {
right = ClassHierarchy.v().CHAR;
} else {
right = ClassHierarchy.v().INT;
}
} else if (r instanceof LongConstant) {
} else if (r instanceof NullConstant) {
} else if (r instanceof StringConstant) {
} else if (r instanceof ClassConstant) {
} else if (r instanceof BinopExpr) {
// ******** BINOP EXPR ********
BinopExpr be = (BinopExpr) r;
Value lv = be.getOp1();
Value rv = be.getOp2();
TypeNode lop = null;
TypeNode rop = null;
// ******** LEFT ********
if (lv instanceof Local) {
if (((Local) lv).getType() instanceof IntegerType) {
lop = ClassHierarchy.v().typeNode(((Local) lv).getType());
}
} else if (lv instanceof DoubleConstant) {
} else if (lv instanceof FloatConstant) {
} else if (lv instanceof IntConstant) {
int value = ((IntConstant) lv).value;
if (value < -32768) {
lop = ClassHierarchy.v().INT;
} else if (value < -128) {
lop = ClassHierarchy.v().SHORT;
} else if (value < 0) {
lop = ClassHierarchy.v().BYTE;
} else if (value < 2) {
lop = ClassHierarchy.v().R0_1;
} else if (value < 128) {
lop = ClassHierarchy.v().R0_127;
} else if (value < 32768) {
lop = ClassHierarchy.v().R0_32767;
} else if (value < 65536) {
lop = ClassHierarchy.v().CHAR;
} else {
lop = ClassHierarchy.v().INT;
}
} else if (lv instanceof LongConstant) {
} else if (lv instanceof NullConstant) {
} else if (lv instanceof StringConstant) {
} else if (lv instanceof ClassConstant) {
} else {
throw new RuntimeException("Unhandled binary expression left operand type: " + lv.getClass());
}
// ******** RIGHT ********
if (rv instanceof Local) {
if (((Local) rv).getType() instanceof IntegerType) {
rop = ClassHierarchy.v().typeNode(((Local) rv).getType());
}
} else if (rv instanceof DoubleConstant) {
} else if (rv instanceof FloatConstant) {
} else if (rv instanceof IntConstant) {
int value = ((IntConstant) rv).value;
if (value < -32768) {
rop = ClassHierarchy.v().INT;
} else if (value < -128) {
rop = ClassHierarchy.v().SHORT;
} else if (value < 0) {
rop = ClassHierarchy.v().BYTE;
} else if (value < 2) {
rop = ClassHierarchy.v().R0_1;
} else if (value < 128) {
rop = ClassHierarchy.v().R0_127;
} else if (value < 32768) {
rop = ClassHierarchy.v().R0_32767;
} else if (value < 65536) {
rop = ClassHierarchy.v().CHAR;
} else {
rop = ClassHierarchy.v().INT;
}
} else if (rv instanceof LongConstant) {
} else if (rv instanceof NullConstant) {
} else if (rv instanceof StringConstant) {
} else if (rv instanceof ClassConstant) {
} else {
throw new RuntimeException("Unhandled binary expression right operand type: " + rv.getClass());
}
if ((be instanceof AddExpr) || (be instanceof SubExpr) || (be instanceof MulExpr) || (be instanceof DivExpr) || (be instanceof RemExpr)) {
if (lop != null && rop != null) {
if (!lop.hasAncestor_1(ClassHierarchy.v().INT)) {
if (fix) {
be.setOp1(insertCast(be.getOp1(), getTypeForCast(lop), IntType.v(), stmt));
} else {
error("Type Error(7)");
}
}
if (!rop.hasAncestor_1(ClassHierarchy.v().INT)) {
if (fix) {
be.setOp2(insertCast(be.getOp2(), getTypeForCast(rop), IntType.v(), stmt));
} else {
error("Type Error(8)");
}
}
}
right = ClassHierarchy.v().INT;
} else if ((be instanceof AndExpr) || (be instanceof OrExpr) || (be instanceof XorExpr)) {
if (lop != null && rop != null) {
TypeNode lca = lop.lca_1(rop);
if (lca == ClassHierarchy.v().TOP) {
if (fix) {
if (!lop.hasAncestor_1(ClassHierarchy.v().INT)) {
be.setOp1(insertCast(be.getOp1(), getTypeForCast(lop), getTypeForCast(rop), stmt));
lca = rop;
}
if (!rop.hasAncestor_1(ClassHierarchy.v().INT)) {
be.setOp2(insertCast(be.getOp2(), getTypeForCast(rop), getTypeForCast(lop), stmt));
lca = lop;
}
} else {
error("Type Error(11)");
}
}
right = lca;
}
} else if (be instanceof ShlExpr) {
if (lop != null) {
if (!lop.hasAncestor_1(ClassHierarchy.v().INT)) {
if (fix) {
be.setOp1(insertCast(be.getOp1(), getTypeForCast(lop), IntType.v(), stmt));
} else {
error("Type Error(9)");
}
}
}
if (!rop.hasAncestor_1(ClassHierarchy.v().INT)) {
if (fix) {
be.setOp2(insertCast(be.getOp2(), getTypeForCast(rop), IntType.v(), stmt));
} else {
error("Type Error(10)");
}
}
right = (lop == null) ? null : ClassHierarchy.v().INT;
} else if ((be instanceof ShrExpr) || (be instanceof UshrExpr)) {
if (lop != null) {
if (!lop.hasAncestor_1(ClassHierarchy.v().INT)) {
if (fix) {
be.setOp1(insertCast(be.getOp1(), getTypeForCast(lop), ByteType.v(), stmt));
lop = ClassHierarchy.v().BYTE;
} else {
error("Type Error(9)");
}
}
}
if (!rop.hasAncestor_1(ClassHierarchy.v().INT)) {
if (fix) {
be.setOp2(insertCast(be.getOp2(), getTypeForCast(rop), IntType.v(), stmt));
} else {
error("Type Error(10)");
}
}
right = lop;
} else if ((be instanceof CmpExpr) || (be instanceof CmpgExpr) || (be instanceof CmplExpr)) {
right = ClassHierarchy.v().BYTE;
} else if ((be instanceof EqExpr) || (be instanceof GeExpr) || (be instanceof GtExpr) || (be instanceof LeExpr) || (be instanceof LtExpr) || (be instanceof NeExpr)) {
if (rop != null) {
TypeNode lca = lop.lca_1(rop);
if (lca == ClassHierarchy.v().TOP) {
if (fix) {
if (!lop.hasAncestor_1(ClassHierarchy.v().INT)) {
be.setOp1(insertCast(be.getOp1(), getTypeForCast(lop), getTypeForCast(rop), stmt));
}
if (!rop.hasAncestor_1(ClassHierarchy.v().INT)) {
be.setOp2(insertCast(be.getOp2(), getTypeForCast(rop), getTypeForCast(lop), stmt));
}
} else {
error("Type Error(11)");
}
}
}
right = ClassHierarchy.v().BOOLEAN;
} else {
throw new RuntimeException("Unhandled binary expression type: " + be.getClass());
}
} else if (r instanceof CastExpr) {
CastExpr ce = (CastExpr) r;
if (ce.getCastType() instanceof IntegerType) {
right = ClassHierarchy.v().typeNode(ce.getCastType());
}
} else if (r instanceof InstanceOfExpr) {
right = ClassHierarchy.v().BOOLEAN;
} else if (r instanceof InvokeExpr) {
InvokeExpr ie = (InvokeExpr) r;
handleInvokeExpr(ie, stmt);
if (ie.getMethodRef().returnType() instanceof IntegerType) {
right = ClassHierarchy.v().typeNode(ie.getMethodRef().returnType());
}
} else if (r instanceof NewArrayExpr) {
NewArrayExpr nae = (NewArrayExpr) r;
Value size = nae.getSize();
if (size instanceof Local) {
if (!ClassHierarchy.v().typeNode(((Local) size).getType()).hasAncestor_1(ClassHierarchy.v().INT)) {
if (fix) {
nae.setSize(insertCast((Local) size, IntType.v(), stmt));
} else {
error("Type Error(12)");
}
}
}
} else if (r instanceof NewExpr) {
} else if (r instanceof NewMultiArrayExpr) {
NewMultiArrayExpr nmae = (NewMultiArrayExpr) r;
for (int i = 0; i < nmae.getSizeCount(); i++) {
Value size = nmae.getSize(i);
if (size instanceof Local) {
if (!ClassHierarchy.v().typeNode(((Local) size).getType()).hasAncestor_1(ClassHierarchy.v().INT)) {
if (fix) {
nmae.setSize(i, insertCast((Local) size, IntType.v(), stmt));
} else {
error("Type Error(13)");
}
}
}
}
} else if (r instanceof LengthExpr) {
right = ClassHierarchy.v().INT;
} else if (r instanceof NegExpr) {
NegExpr ne = (NegExpr) r;
if (ne.getOp() instanceof Local) {
Local local = (Local) ne.getOp();
if (local.getType() instanceof IntegerType) {
TypeNode ltype = ClassHierarchy.v().typeNode(local.getType());
if (!ltype.hasAncestor_1(ClassHierarchy.v().INT)) {
if (fix) {
ne.setOp(insertCast(local, IntType.v(), stmt));
ltype = ClassHierarchy.v().BYTE;
} else {
error("Type Error(14)");
}
}
right = (ltype == ClassHierarchy.v().CHAR) ? ClassHierarchy.v().INT : ltype;
}
} else if (ne.getOp() instanceof DoubleConstant) {
} else if (ne.getOp() instanceof FloatConstant) {
} else if (ne.getOp() instanceof IntConstant) {
right = ClassHierarchy.v().INT;
} else if (ne.getOp() instanceof LongConstant) {
} else {
throw new RuntimeException("Unhandled neg expression operand type: " + ne.getOp().getClass());
}
} else if (r instanceof Local) {
Local local = (Local) r;
if (local.getType() instanceof IntegerType) {
right = ClassHierarchy.v().typeNode(local.getType());
}
} else if (r instanceof InstanceFieldRef) {
InstanceFieldRef ref = (InstanceFieldRef) r;
if (ref.getFieldRef().type() instanceof IntegerType) {
right = ClassHierarchy.v().typeNode(ref.getFieldRef().type());
}
} else if (r instanceof StaticFieldRef) {
StaticFieldRef ref = (StaticFieldRef) r;
if (ref.getFieldRef().type() instanceof IntegerType) {
right = ClassHierarchy.v().typeNode(ref.getFieldRef().type());
}
} else {
throw new RuntimeException("Unhandled assignment right hand side type: " + r.getClass());
}
if (left != null && right != null) {
if (!right.hasAncestor_1(left)) {
if (fix) {
stmt.setRightOp(insertCast(stmt.getRightOp(), getTypeForCast(right), getTypeForCast(left), stmt));
} else {
error("Type Error(15)");
}
}
}
}
use of soot.jimple.NullConstant in project soot by Sable.
the class ConstraintCollector method caseIfStmt.
public void caseIfStmt(IfStmt stmt) {
if (uses) {
ConditionExpr cond = (ConditionExpr) stmt.getCondition();
BinopExpr expr = cond;
Value lv = expr.getOp1();
Value rv = expr.getOp2();
TypeVariable lop = null;
TypeVariable rop = null;
// ******** LEFT ********
if (lv instanceof Local) {
if (((Local) lv).getType() instanceof IntegerType) {
lop = resolver.typeVariable((Local) lv);
}
} else if (lv instanceof DoubleConstant) {
} else if (lv instanceof FloatConstant) {
} else if (lv instanceof IntConstant) {
int value = ((IntConstant) lv).value;
if (value < -32768) {
lop = resolver.INT;
} else if (value < -128) {
lop = resolver.SHORT;
} else if (value < 0) {
lop = resolver.BYTE;
} else if (value < 2) {
lop = resolver.R0_1;
} else if (value < 128) {
lop = resolver.R0_127;
} else if (value < 32768) {
lop = resolver.R0_32767;
} else if (value < 65536) {
lop = resolver.CHAR;
} else {
lop = resolver.INT;
}
} else if (lv instanceof LongConstant) {
} else if (lv instanceof NullConstant) {
} else if (lv instanceof StringConstant) {
} else if (lv instanceof ClassConstant) {
} else {
throw new RuntimeException("Unhandled binary expression left operand type: " + lv.getClass());
}
// ******** RIGHT ********
if (rv instanceof Local) {
if (((Local) rv).getType() instanceof IntegerType) {
rop = resolver.typeVariable((Local) rv);
}
} else if (rv instanceof DoubleConstant) {
} else if (rv instanceof FloatConstant) {
} else if (rv instanceof IntConstant) {
int value = ((IntConstant) rv).value;
if (value < -32768) {
rop = resolver.INT;
} else if (value < -128) {
rop = resolver.SHORT;
} else if (value < 0) {
rop = resolver.BYTE;
} else if (value < 2) {
rop = resolver.R0_1;
} else if (value < 128) {
rop = resolver.R0_127;
} else if (value < 32768) {
rop = resolver.R0_32767;
} else if (value < 65536) {
rop = resolver.CHAR;
} else {
rop = resolver.INT;
}
} else if (rv instanceof LongConstant) {
} else if (rv instanceof NullConstant) {
} else if (rv instanceof StringConstant) {
} else if (rv instanceof ClassConstant) {
} else {
throw new RuntimeException("Unhandled binary expression right operand type: " + rv.getClass());
}
if (rop != null && lop != null) {
TypeVariable common = resolver.typeVariable();
if (rop != null)
rop.addParent(common);
if (lop != null)
lop.addParent(common);
}
}
}
use of soot.jimple.NullConstant in project soot by Sable.
the class RegisterAllocator method asConstant.
private Register asConstant(Constant c, ConstantVisitor constantV) {
Register constantRegister = null;
List<Register> rArray = null;
AtomicInteger iI = null;
if (c instanceof ClassConstant) {
rArray = classConstantReg;
iI = classI;
} else if (c instanceof NullConstant) {
rArray = nullConstantReg;
iI = nullI;
} else if (c instanceof FloatConstant) {
rArray = floatConstantReg;
iI = floatI;
} else if (c instanceof IntConstant) {
rArray = intConstantReg;
iI = intI;
} else if (c instanceof LongConstant) {
rArray = longConstantReg;
iI = longI;
} else if (c instanceof DoubleConstant) {
rArray = doubleConstantReg;
iI = doubleI;
} else if (c instanceof StringConstant) {
rArray = stringConstantReg;
iI = stringI;
} else {
throw new RuntimeException("Error. Unknown constant type: '" + c.getType() + "'");
}
boolean inConflict = true;
while (inConflict) {
if (rArray.size() == 0 || iI.intValue() >= rArray.size()) {
rArray.add(new Register(c.getType(), nextRegNum));
nextRegNum += SootToDexUtils.getDexWords(c.getType());
}
constantRegister = rArray.get(iI.getAndIncrement()).clone();
inConflict = lockedRegisters.contains(constantRegister);
}
// "load" constant into the register...
constantV.setDestination(constantRegister);
c.apply(constantV);
// get an independent clone in case we got a cached reguster
return constantRegister.clone();
}
use of soot.jimple.NullConstant 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);
}
});
}
use of soot.jimple.NullConstant in project soot by Sable.
the class DexBody method jimplify.
/**
* Return the jimple equivalent of this body.
*
* @param m
* the SootMethod that contains this body
*/
public Body jimplify(Body b, SootMethod m) {
final Jimple jimple = Jimple.v();
final UnknownType unknownType = UnknownType.v();
final NullConstant nullConstant = NullConstant.v();
final Options options = Options.v();
/*
* Timer t_whole_jimplification = new Timer(); Timer t_num = new
* Timer(); Timer t_null = new Timer();
*
* t_whole_jimplification.start();
*/
jBody = (JimpleBody) b;
deferredInstructions = new ArrayList<DeferableInstruction>();
instructionsToRetype = new HashSet<RetypeableInstruction>();
if (IDalvikTyper.ENABLE_DVKTYPER) {
DalvikTyper.v().clear();
}
// process method parameters and generate Jimple locals from Dalvik
// registers
List<Local> paramLocals = new LinkedList<Local>();
if (!isStatic) {
int thisRegister = numRegisters - numParameterRegisters - 1;
// generateLocal(UnknownType.v());
Local thisLocal = jimple.newLocal("$u" + thisRegister, unknownType);
jBody.getLocals().add(thisLocal);
registerLocals[thisRegister] = thisLocal;
JIdentityStmt idStmt = (JIdentityStmt) jimple.newIdentityStmt(thisLocal, jimple.newThisRef(declaringClassType));
add(idStmt);
paramLocals.add(thisLocal);
if (IDalvikTyper.ENABLE_DVKTYPER) {
DalvikTyper.v().setType(idStmt.leftBox, jBody.getMethod().getDeclaringClass().getType(), false);
}
}
{
// index of parameter type
int i = 0;
// index
int parameterRegister = numRegisters - numParameterRegisters;
// register
for (Type t : parameterTypes) {
// may
Local gen = jimple.newLocal("$u" + parameterRegister, unknownType);
// only
// use
// UnknownType
// here
// because
// the
// local
// may
// be
// reused
// with
// a
// different
// type
// later
// (before
// splitting)
jBody.getLocals().add(gen);
registerLocals[parameterRegister] = gen;
JIdentityStmt idStmt = (JIdentityStmt) jimple.newIdentityStmt(gen, jimple.newParameterRef(t, i++));
add(idStmt);
paramLocals.add(gen);
if (IDalvikTyper.ENABLE_DVKTYPER) {
DalvikTyper.v().setType(idStmt.leftBox, t, false);
}
// used later in the Dalvik bytecode
if (t instanceof LongType || t instanceof DoubleType) {
parameterRegister++;
// may
Local g = jimple.newLocal("$u" + parameterRegister, unknownType);
// only
// use
// UnknownType
// here
// because
// the
// local
// may
// be
// reused
// with
// a
// different
// type
// later
// (before
// splitting)
jBody.getLocals().add(g);
registerLocals[parameterRegister] = g;
}
parameterRegister++;
}
}
for (int i = 0; i < (numRegisters - numParameterRegisters - (isStatic ? 0 : 1)); i++) {
registerLocals[i] = jimple.newLocal("$u" + i, unknownType);
jBody.getLocals().add(registerLocals[i]);
}
// add local to store intermediate results
storeResultLocal = jimple.newLocal("$u-1", unknownType);
jBody.getLocals().add(storeResultLocal);
// process bytecode instructions
final boolean isOdex = dexFile instanceof DexBackedDexFile ? ((DexBackedDexFile) dexFile).isOdexFile() : false;
ClassPath cp = null;
if (isOdex) {
String[] sootClasspath = options.soot_classpath().split(File.pathSeparator);
List<String> classpathList = new ArrayList<String>();
for (String str : sootClasspath) classpathList.add(str);
try {
ClassPathResolver resolver = new ClassPathResolver(classpathList, classpathList, classpathList, dexFile);
cp = new ClassPath(resolver.getResolvedClassProviders().toArray(new ClassProvider[0]));
} catch (IOException e) {
throw new RuntimeException(e);
}
}
int prevLineNumber = -1;
for (DexlibAbstractInstruction instruction : instructions) {
if (isOdex && instruction instanceof OdexInstruction)
((OdexInstruction) instruction).deOdex(dexFile, method, cp);
if (dangling != null) {
dangling.finalize(this, instruction);
dangling = null;
}
instruction.jimplify(this);
if (instruction.getLineNumber() > 0)
prevLineNumber = instruction.getLineNumber();
else {
instruction.setLineNumber(prevLineNumber);
}
}
for (DeferableInstruction instruction : deferredInstructions) {
instruction.deferredJimplify(this);
}
if (tries != null)
addTraps();
int prevLn = -1;
final boolean keepLineNumber = options.keep_line_number();
for (DexlibAbstractInstruction instruction : instructions) {
Unit unit = instruction.getUnit();
int lineNumber = unit.getJavaSourceStartLineNumber();
if (keepLineNumber && lineNumber < 0) {
if (prevLn >= 0) {
unit.addTag(new LineNumberTag(prevLn));
unit.addTag(new SourceLineNumberTag(prevLn));
}
} else {
prevLn = lineNumber;
}
}
// At this point Jimple code is generated
// Cleaning...
instructions = null;
// registerLocals = null;
// storeResultLocal = null;
instructionAtAddress.clear();
// localGenerator = null;
deferredInstructions = null;
// instructionsToRetype = null;
dangling = null;
tries = null;
/*
* We eliminate dead code. Dead code has been shown to occur under the
* following circumstances.
*
* 0006ec: 0d00 |00a2: move-exception v0 ... 0006f2: 0d00 |00a5:
* move-exception v0 ... 0x0041 - 0x008a Ljava/lang/Throwable; -> 0x00a5
* <any> -> 0x00a2
*
* Here there are two traps both over the same region. But the same
* always fires, hence rendering the code at a2 unreachable. Dead code
* yields problems during local splitting because locals within dead
* code will not be split. Hence we remove all dead code here.
*/
// Fix traps that do not catch exceptions
DexTrapStackFixer.v().transform(jBody);
// Sort out jump chains
DexJumpChainShortener.v().transform(jBody);
// Make sure that we don't have any overlapping uses due to returns
DexReturnInliner.v().transform(jBody);
// Shortcut: Reduce array initializations
DexArrayInitReducer.v().transform(jBody);
// split first to find undefined uses
getLocalSplitter().transform(jBody);
// Remove dead code and the corresponding locals before assigning types
getUnreachableCodeEliminator().transform(jBody);
DeadAssignmentEliminator.v().transform(jBody);
UnusedLocalEliminator.v().transform(jBody);
for (RetypeableInstruction i : instructionsToRetype) i.retype(jBody);
if (IDalvikTyper.ENABLE_DVKTYPER) {
DexReturnValuePropagator.v().transform(jBody);
getCopyPopagator().transform(jBody);
DexNullThrowTransformer.v().transform(jBody);
DalvikTyper.v().typeUntypedConstrantInDiv(jBody);
DeadAssignmentEliminator.v().transform(jBody);
UnusedLocalEliminator.v().transform(jBody);
DalvikTyper.v().assignType(jBody);
// jBody.validate();
jBody.validateUses();
jBody.validateValueBoxes();
// jBody.checkInit();
// Validate.validateArrays(jBody);
// jBody.checkTypes();
// jBody.checkLocals();
} else {
// t_num.start();
DexNumTransformer.v().transform(jBody);
// t_num.end();
DexReturnValuePropagator.v().transform(jBody);
getCopyPopagator().transform(jBody);
DexNullThrowTransformer.v().transform(jBody);
// t_null.start();
DexNullTransformer.v().transform(jBody);
// t_null.end();
DexIfTransformer.v().transform(jBody);
DeadAssignmentEliminator.v().transform(jBody);
UnusedLocalEliminator.v().transform(jBody);
// DexRefsChecker.v().transform(jBody);
DexNullArrayRefTransformer.v().transform(jBody);
}
if (IDalvikTyper.ENABLE_DVKTYPER) {
for (Local l : jBody.getLocals()) {
l.setType(unknownType);
}
}
// Remove "instanceof" checks on the null constant
DexNullInstanceofTransformer.v().transform(jBody);
TypeAssigner.v().transform(jBody);
final RefType objectType = RefType.v("java.lang.Object");
if (IDalvikTyper.ENABLE_DVKTYPER) {
for (Unit u : jBody.getUnits()) {
if (u instanceof IfStmt) {
ConditionExpr expr = (ConditionExpr) ((IfStmt) u).getCondition();
if (((expr instanceof EqExpr) || (expr instanceof NeExpr))) {
Value op1 = expr.getOp1();
Value op2 = expr.getOp2();
if (op1 instanceof Constant && op2 instanceof Local) {
Local l = (Local) op2;
Type ltype = l.getType();
if (ltype instanceof PrimType)
continue;
if (// by default
!(op1 instanceof IntConstant))
// in Dalvik
continue;
IntConstant icst = (IntConstant) op1;
int val = icst.value;
if (val != 0)
continue;
expr.setOp1(nullConstant);
} else if (op1 instanceof Local && op2 instanceof Constant) {
Local l = (Local) op1;
Type ltype = l.getType();
if (ltype instanceof PrimType)
continue;
if (// by default
!(op2 instanceof IntConstant))
// in Dalvik
continue;
IntConstant icst = (IntConstant) op2;
int val = icst.value;
if (val != 0)
continue;
expr.setOp2(nullConstant);
} else if (op1 instanceof Local && op2 instanceof Local) {
// nothing to do
} else if (op1 instanceof Constant && op2 instanceof Constant) {
if (op1 instanceof NullConstant && op2 instanceof NumericConstant) {
IntConstant nc = (IntConstant) op2;
if (nc.value != 0)
throw new RuntimeException("expected value 0 for int constant. Got " + expr);
expr.setOp2(NullConstant.v());
} else if (op2 instanceof NullConstant && op1 instanceof NumericConstant) {
IntConstant nc = (IntConstant) op1;
if (nc.value != 0)
throw new RuntimeException("expected value 0 for int constant. Got " + expr);
expr.setOp1(nullConstant);
}
} else {
throw new RuntimeException("error: do not handle if: " + u);
}
}
}
}
// For null_type locals: replace their use by NullConstant()
List<ValueBox> uses = jBody.getUseBoxes();
// List<ValueBox> defs = jBody.getDefBoxes();
List<ValueBox> toNullConstantify = new ArrayList<ValueBox>();
List<Local> toRemove = new ArrayList<Local>();
for (Local l : jBody.getLocals()) {
if (l.getType() instanceof NullType) {
toRemove.add(l);
for (ValueBox vb : uses) {
Value v = vb.getValue();
if (v == l)
toNullConstantify.add(vb);
}
}
}
for (ValueBox vb : toNullConstantify) {
System.out.println("replace valuebox '" + vb + " with null constant");
vb.setValue(nullConstant);
}
for (Local l : toRemove) {
System.out.println("removing null_type local " + l);
l.setType(objectType);
}
}
// We pack locals that are not used in overlapping regions. This may
// again lead to unused locals which we have to remove.
LocalPacker.v().transform(jBody);
UnusedLocalEliminator.v().transform(jBody);
LocalNameStandardizer.v().transform(jBody);
// on the fly.
if (options.wrong_staticness() == Options.wrong_staticness_fix) {
FieldStaticnessCorrector.v().transform(jBody);
MethodStaticnessCorrector.v().transform(jBody);
}
// Inline PackManager.v().getPack("jb").apply(jBody);
// Keep only transformations that have not been done
// at this point.
TrapTightener.v().transform(jBody);
TrapMinimizer.v().transform(jBody);
// LocalSplitter.v().transform(jBody);
Aggregator.v().transform(jBody);
// UnusedLocalEliminator.v().transform(jBody);
// TypeAssigner.v().transform(jBody);
// LocalPacker.v().transform(jBody);
// LocalNameStandardizer.v().transform(jBody);
// Remove if (null == null) goto x else <madness>. We can only do this
// after we have run the constant propagation as we might not be able
// to statically decide the conditions earlier.
ConditionalBranchFolder.v().transform(jBody);
// Remove unnecessary typecasts
ConstantCastEliminator.v().transform(jBody);
IdentityCastEliminator.v().transform(jBody);
// Remove unnecessary logic operations
IdentityOperationEliminator.v().transform(jBody);
// We need to run this transformer since the conditional branch folder
// might have rendered some code unreachable (well, it was unreachable
// before as well, but we didn't know).
UnreachableCodeEliminator.v().transform(jBody);
// Not sure whether we need this even though we do it earlier on as
// the earlier pass does not have type information
// CopyPropagator.v().transform(jBody);
// we might have gotten new dead assignments and unused locals through
// copy propagation and unreachable code elimination, so we have to do
// this again
DeadAssignmentEliminator.v().transform(jBody);
UnusedLocalEliminator.v().transform(jBody);
NopEliminator.v().transform(jBody);
// Remove unnecessary chains of return statements
DexReturnPacker.v().transform(jBody);
for (Unit u : jBody.getUnits()) {
if (u instanceof AssignStmt) {
AssignStmt ass = (AssignStmt) u;
if (ass.getRightOp() instanceof CastExpr) {
CastExpr c = (CastExpr) ass.getRightOp();
if (c.getType() instanceof NullType) {
ass.setRightOp(nullConstant);
}
}
}
if (u instanceof DefinitionStmt) {
DefinitionStmt def = (DefinitionStmt) u;
// we must manually fix the hierarchy
if (def.getLeftOp() instanceof Local && def.getRightOp() instanceof CaughtExceptionRef) {
Type t = def.getLeftOp().getType();
if (t instanceof RefType) {
RefType rt = (RefType) t;
if (rt.getSootClass().isPhantom() && !rt.getSootClass().hasSuperclass() && !rt.getSootClass().getName().equals("java.lang.Throwable"))
rt.getSootClass().setSuperclass(Scene.v().getSootClass("java.lang.Throwable"));
}
}
}
}
//
for (Local l : jBody.getLocals()) {
Type t = l.getType();
if (t instanceof NullType) {
l.setType(objectType);
}
}
return jBody;
}
Aggregations