use of soot.StmtAddressType in project soot by Sable.
the class GroupIntPair method emitInst.
void emitInst(Inst inst) {
LineNumberTag lnTag = (LineNumberTag) inst.getTag("LineNumberTag");
if (lnTag != null)
emit(".line " + lnTag.getLineNumber());
inst.apply(new InstSwitch() {
@Override
public void caseReturnVoidInst(ReturnVoidInst i) {
emit("return");
}
@Override
public void caseReturnInst(ReturnInst i) {
i.getOpType().apply(new TypeSwitch() {
@Override
public void defaultCase(Type t) {
throw new RuntimeException("invalid return type " + t.toString());
}
@Override
public void caseDoubleType(DoubleType t) {
emit("dreturn");
}
@Override
public void caseFloatType(FloatType t) {
emit("freturn");
}
@Override
public void caseIntType(IntType t) {
emit("ireturn");
}
@Override
public void caseByteType(ByteType t) {
emit("ireturn");
}
@Override
public void caseShortType(ShortType t) {
emit("ireturn");
}
@Override
public void caseCharType(CharType t) {
emit("ireturn");
}
@Override
public void caseBooleanType(BooleanType t) {
emit("ireturn");
}
@Override
public void caseLongType(LongType t) {
emit("lreturn");
}
@Override
public void caseArrayType(ArrayType t) {
emit("areturn");
}
@Override
public void caseRefType(RefType t) {
emit("areturn");
}
@Override
public void caseNullType(NullType t) {
emit("areturn");
}
});
}
@Override
public void caseNopInst(NopInst i) {
emit("nop");
}
@Override
public void caseEnterMonitorInst(EnterMonitorInst i) {
emit("monitorenter");
}
@Override
public void casePopInst(PopInst i) {
if (i.getWordCount() == 2) {
emit("pop2");
} else
emit("pop");
}
@Override
public void caseExitMonitorInst(ExitMonitorInst i) {
emit("monitorexit");
}
@Override
public void caseGotoInst(GotoInst i) {
emit("goto " + unitToLabel.get(i.getTarget()));
}
@Override
public void caseJSRInst(JSRInst i) {
emit("jsr " + unitToLabel.get(i.getTarget()));
}
@Override
public void casePushInst(PushInst i) {
if (i.getConstant() instanceof IntConstant) {
IntConstant v = (IntConstant) (i.getConstant());
if (v.value == -1)
emit("iconst_m1");
else if (v.value >= 0 && v.value <= 5)
emit("iconst_" + v.value);
else if (v.value >= Byte.MIN_VALUE && v.value <= Byte.MAX_VALUE)
emit("bipush " + v.value);
else if (v.value >= Short.MIN_VALUE && v.value <= Short.MAX_VALUE)
emit("sipush " + v.value);
else
emit("ldc " + v.toString());
} else if (i.getConstant() instanceof StringConstant) {
emit("ldc " + i.getConstant().toString());
} else if (i.getConstant() instanceof ClassConstant) {
emit("ldc_w " + ((ClassConstant) i.getConstant()).getValue());
} else if (i.getConstant() instanceof DoubleConstant) {
DoubleConstant v = (DoubleConstant) (i.getConstant());
if ((v.value == 0) && ((1.0 / v.value) > 0.0))
emit("dconst_0");
else if (v.value == 1)
emit("dconst_1");
else {
String s = doubleToString(v);
emit("ldc2_w " + s);
}
} else if (i.getConstant() instanceof FloatConstant) {
FloatConstant v = (FloatConstant) (i.getConstant());
if ((v.value == 0) && ((1.0f / v.value) > 1.0f))
emit("fconst_0");
else if (v.value == 1)
emit("fconst_1");
else if (v.value == 2)
emit("fconst_2");
else {
String s = floatToString(v);
emit("ldc " + s);
}
} else if (i.getConstant() instanceof LongConstant) {
LongConstant v = (LongConstant) (i.getConstant());
if (v.value == 0)
emit("lconst_0");
else if (v.value == 1)
emit("lconst_1");
else
emit("ldc2_w " + v.toString());
} else if (i.getConstant() instanceof NullConstant) {
emit("aconst_null");
} else if (i.getConstant() instanceof MethodHandle) {
throw new RuntimeException("MethodHandle constants not supported by Jasmin. Please use -asm-backend.");
} else
throw new RuntimeException("unsupported opcode");
}
@Override
public void caseIdentityInst(IdentityInst i) {
if (i.getRightOp() instanceof CaughtExceptionRef && i.getLeftOp() instanceof Local) {
int slot = localToSlot.get(i.getLeftOp()).intValue();
if (slot >= 0 && slot <= 3)
emit("astore_" + slot);
else
emit("astore " + slot);
}
}
@Override
public void caseStoreInst(StoreInst i) {
final int slot = localToSlot.get(i.getLocal()).intValue();
i.getOpType().apply(new TypeSwitch() {
@Override
public void caseArrayType(ArrayType t) {
if (slot >= 0 && slot <= 3)
emit("astore_" + slot);
else
emit("astore " + slot);
}
@Override
public void caseDoubleType(DoubleType t) {
if (slot >= 0 && slot <= 3)
emit("dstore_" + slot);
else
emit("dstore " + slot);
}
@Override
public void caseFloatType(FloatType t) {
if (slot >= 0 && slot <= 3)
emit("fstore_" + slot);
else
emit("fstore " + slot);
}
@Override
public void caseIntType(IntType t) {
if (slot >= 0 && slot <= 3)
emit("istore_" + slot);
else
emit("istore " + slot);
}
@Override
public void caseByteType(ByteType t) {
if (slot >= 0 && slot <= 3)
emit("istore_" + slot);
else
emit("istore " + slot);
}
@Override
public void caseShortType(ShortType t) {
if (slot >= 0 && slot <= 3)
emit("istore_" + slot);
else
emit("istore " + slot);
}
@Override
public void caseCharType(CharType t) {
if (slot >= 0 && slot <= 3)
emit("istore_" + slot);
else
emit("istore " + slot);
}
@Override
public void caseBooleanType(BooleanType t) {
if (slot >= 0 && slot <= 3)
emit("istore_" + slot);
else
emit("istore " + slot);
}
@Override
public void caseLongType(LongType t) {
if (slot >= 0 && slot <= 3)
emit("lstore_" + slot);
else
emit("lstore " + slot);
}
@Override
public void caseRefType(RefType t) {
if (slot >= 0 && slot <= 3)
emit("astore_" + slot);
else
emit("astore " + slot);
}
@Override
public void caseStmtAddressType(StmtAddressType t) {
isNextGotoAJsr = true;
returnAddressSlot = slot;
/*
* if ( slot >= 0 && slot <= 3) emit("astore_" + slot,
* ); else emit("astore " + slot, );
*/
}
@Override
public void caseNullType(NullType t) {
if (slot >= 0 && slot <= 3)
emit("astore_" + slot);
else
emit("astore " + slot);
}
@Override
public void defaultCase(Type t) {
throw new RuntimeException("Invalid local type:" + t);
}
});
}
@Override
public void caseLoadInst(LoadInst i) {
final int slot = localToSlot.get(i.getLocal()).intValue();
i.getOpType().apply(new TypeSwitch() {
@Override
public void caseArrayType(ArrayType t) {
if (slot >= 0 && slot <= 3)
emit("aload_" + slot);
else
emit("aload " + slot);
}
@Override
public void defaultCase(Type t) {
throw new RuntimeException("invalid local type to load" + t);
}
@Override
public void caseDoubleType(DoubleType t) {
if (slot >= 0 && slot <= 3)
emit("dload_" + slot);
else
emit("dload " + slot);
}
@Override
public void caseFloatType(FloatType t) {
if (slot >= 0 && slot <= 3)
emit("fload_" + slot);
else
emit("fload " + slot);
}
@Override
public void caseIntType(IntType t) {
if (slot >= 0 && slot <= 3)
emit("iload_" + slot);
else
emit("iload " + slot);
}
@Override
public void caseByteType(ByteType t) {
if (slot >= 0 && slot <= 3)
emit("iload_" + slot);
else
emit("iload " + slot);
}
@Override
public void caseShortType(ShortType t) {
if (slot >= 0 && slot <= 3)
emit("iload_" + slot);
else
emit("iload " + slot);
}
@Override
public void caseCharType(CharType t) {
if (slot >= 0 && slot <= 3)
emit("iload_" + slot);
else
emit("iload " + slot);
}
@Override
public void caseBooleanType(BooleanType t) {
if (slot >= 0 && slot <= 3)
emit("iload_" + slot);
else
emit("iload " + slot);
}
@Override
public void caseLongType(LongType t) {
if (slot >= 0 && slot <= 3)
emit("lload_" + slot);
else
emit("lload " + slot);
}
@Override
public void caseRefType(RefType t) {
if (slot >= 0 && slot <= 3)
emit("aload_" + slot);
else
emit("aload " + slot);
}
@Override
public void caseNullType(NullType t) {
if (slot >= 0 && slot <= 3)
emit("aload_" + slot);
else
emit("aload " + slot);
}
});
}
@Override
public void caseArrayWriteInst(ArrayWriteInst i) {
i.getOpType().apply(new TypeSwitch() {
@Override
public void caseArrayType(ArrayType t) {
emit("aastore");
}
@Override
public void caseDoubleType(DoubleType t) {
emit("dastore");
}
@Override
public void caseFloatType(FloatType t) {
emit("fastore");
}
@Override
public void caseIntType(IntType t) {
emit("iastore");
}
@Override
public void caseLongType(LongType t) {
emit("lastore");
}
@Override
public void caseRefType(RefType t) {
emit("aastore");
}
@Override
public void caseByteType(ByteType t) {
emit("bastore");
}
@Override
public void caseBooleanType(BooleanType t) {
emit("bastore");
}
@Override
public void caseCharType(CharType t) {
emit("castore");
}
@Override
public void caseShortType(ShortType t) {
emit("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 ty) {
emit("aaload");
}
@Override
public void caseBooleanType(BooleanType ty) {
emit("baload");
}
@Override
public void caseByteType(ByteType ty) {
emit("baload");
}
@Override
public void caseCharType(CharType ty) {
emit("caload");
}
@Override
public void defaultCase(Type ty) {
throw new RuntimeException("invalid base type");
}
@Override
public void caseDoubleType(DoubleType ty) {
emit("daload");
}
@Override
public void caseFloatType(FloatType ty) {
emit("faload");
}
@Override
public void caseIntType(IntType ty) {
emit("iaload");
}
@Override
public void caseLongType(LongType ty) {
emit("laload");
}
@Override
public void caseNullType(NullType ty) {
emit("aaload");
}
@Override
public void caseRefType(RefType ty) {
emit("aaload");
}
@Override
public void caseShortType(ShortType ty) {
emit("saload");
}
});
}
@Override
public void caseIfNullInst(IfNullInst i) {
emit("ifnull " + unitToLabel.get(i.getTarget()));
}
@Override
public void caseIfNonNullInst(IfNonNullInst i) {
emit("ifnonnull " + unitToLabel.get(i.getTarget()));
}
@Override
public void caseIfEqInst(IfEqInst i) {
emit("ifeq " + unitToLabel.get(i.getTarget()));
}
@Override
public void caseIfNeInst(IfNeInst i) {
emit("ifne " + unitToLabel.get(i.getTarget()));
}
@Override
public void caseIfGtInst(IfGtInst i) {
emit("ifgt " + unitToLabel.get(i.getTarget()));
}
@Override
public void caseIfGeInst(IfGeInst i) {
emit("ifge " + unitToLabel.get(i.getTarget()));
}
@Override
public void caseIfLtInst(IfLtInst i) {
emit("iflt " + unitToLabel.get(i.getTarget()));
}
@Override
public void caseIfLeInst(IfLeInst i) {
emit("ifle " + unitToLabel.get(i.getTarget()));
}
@Override
public void caseIfCmpEqInst(final IfCmpEqInst i) {
i.getOpType().apply(new TypeSwitch() {
@Override
public void caseIntType(IntType t) {
emit("if_icmpeq " + unitToLabel.get(i.getTarget()));
}
@Override
public void caseBooleanType(BooleanType t) {
emit("if_icmpeq " + unitToLabel.get(i.getTarget()));
}
@Override
public void caseShortType(ShortType t) {
emit("if_icmpeq " + unitToLabel.get(i.getTarget()));
}
@Override
public void caseCharType(CharType t) {
emit("if_icmpeq " + unitToLabel.get(i.getTarget()));
}
@Override
public void caseByteType(ByteType t) {
emit("if_icmpeq " + unitToLabel.get(i.getTarget()));
}
@Override
public void caseDoubleType(DoubleType t) {
emit("dcmpg");
emit("ifeq " + unitToLabel.get(i.getTarget()));
}
@Override
public void caseLongType(LongType t) {
emit("lcmp");
emit("ifeq " + unitToLabel.get(i.getTarget()));
}
@Override
public void caseFloatType(FloatType t) {
emit("fcmpg");
emit("ifeq " + unitToLabel.get(i.getTarget()));
}
@Override
public void caseArrayType(ArrayType t) {
emit("if_acmpeq " + unitToLabel.get(i.getTarget()));
}
@Override
public void caseRefType(RefType t) {
emit("if_acmpeq " + unitToLabel.get(i.getTarget()));
}
@Override
public void caseNullType(NullType t) {
emit("if_acmpeq " + unitToLabel.get(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 caseIntType(IntType t) {
emit("if_icmpne " + unitToLabel.get(i.getTarget()));
}
@Override
public void caseBooleanType(BooleanType t) {
emit("if_icmpne " + unitToLabel.get(i.getTarget()));
}
@Override
public void caseShortType(ShortType t) {
emit("if_icmpne " + unitToLabel.get(i.getTarget()));
}
@Override
public void caseCharType(CharType t) {
emit("if_icmpne " + unitToLabel.get(i.getTarget()));
}
@Override
public void caseByteType(ByteType t) {
emit("if_icmpne " + unitToLabel.get(i.getTarget()));
}
@Override
public void caseDoubleType(DoubleType t) {
emit("dcmpg");
emit("ifne " + unitToLabel.get(i.getTarget()));
}
@Override
public void caseLongType(LongType t) {
emit("lcmp");
emit("ifne " + unitToLabel.get(i.getTarget()));
}
@Override
public void caseFloatType(FloatType t) {
emit("fcmpg");
emit("ifne " + unitToLabel.get(i.getTarget()));
}
@Override
public void caseArrayType(ArrayType t) {
emit("if_acmpne " + unitToLabel.get(i.getTarget()));
}
@Override
public void caseRefType(RefType t) {
emit("if_acmpne " + unitToLabel.get(i.getTarget()));
}
@Override
public void caseNullType(NullType t) {
emit("if_acmpne " + unitToLabel.get(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 caseIntType(IntType t) {
emit("if_icmpgt " + unitToLabel.get(i.getTarget()));
}
@Override
public void caseBooleanType(BooleanType t) {
emit("if_icmpgt " + unitToLabel.get(i.getTarget()));
}
@Override
public void caseShortType(ShortType t) {
emit("if_icmpgt " + unitToLabel.get(i.getTarget()));
}
@Override
public void caseCharType(CharType t) {
emit("if_icmpgt " + unitToLabel.get(i.getTarget()));
}
@Override
public void caseByteType(ByteType t) {
emit("if_icmpgt " + unitToLabel.get(i.getTarget()));
}
@Override
public void caseDoubleType(DoubleType t) {
emit("dcmpg");
emit("ifgt " + unitToLabel.get(i.getTarget()));
}
@Override
public void caseLongType(LongType t) {
emit("lcmp");
emit("ifgt " + unitToLabel.get(i.getTarget()));
}
@Override
public void caseFloatType(FloatType t) {
emit("fcmpg");
emit("ifgt " + unitToLabel.get(i.getTarget()));
}
@Override
public void caseArrayType(ArrayType t) {
emit("if_acmpgt " + unitToLabel.get(i.getTarget()));
}
@Override
public void caseRefType(RefType t) {
emit("if_acmpgt " + unitToLabel.get(i.getTarget()));
}
@Override
public void caseNullType(NullType t) {
emit("if_acmpgt " + unitToLabel.get(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 caseIntType(IntType t) {
emit("if_icmpge " + unitToLabel.get(i.getTarget()));
}
@Override
public void caseBooleanType(BooleanType t) {
emit("if_icmpge " + unitToLabel.get(i.getTarget()));
}
@Override
public void caseShortType(ShortType t) {
emit("if_icmpge " + unitToLabel.get(i.getTarget()));
}
@Override
public void caseCharType(CharType t) {
emit("if_icmpge " + unitToLabel.get(i.getTarget()));
}
@Override
public void caseByteType(ByteType t) {
emit("if_icmpge " + unitToLabel.get(i.getTarget()));
}
@Override
public void caseDoubleType(DoubleType t) {
emit("dcmpg");
emit("ifge " + unitToLabel.get(i.getTarget()));
}
@Override
public void caseLongType(LongType t) {
emit("lcmp");
emit("ifge " + unitToLabel.get(i.getTarget()));
}
@Override
public void caseFloatType(FloatType t) {
emit("fcmpg");
emit("ifge " + unitToLabel.get(i.getTarget()));
}
@Override
public void caseArrayType(ArrayType t) {
emit("if_acmpge " + unitToLabel.get(i.getTarget()));
}
@Override
public void caseRefType(RefType t) {
emit("if_acmpge " + unitToLabel.get(i.getTarget()));
}
@Override
public void caseNullType(NullType t) {
emit("if_acmpge " + unitToLabel.get(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 caseIntType(IntType t) {
emit("if_icmplt " + unitToLabel.get(i.getTarget()));
}
@Override
public void caseBooleanType(BooleanType t) {
emit("if_icmplt " + unitToLabel.get(i.getTarget()));
}
@Override
public void caseShortType(ShortType t) {
emit("if_icmplt " + unitToLabel.get(i.getTarget()));
}
@Override
public void caseCharType(CharType t) {
emit("if_icmplt " + unitToLabel.get(i.getTarget()));
}
@Override
public void caseByteType(ByteType t) {
emit("if_icmplt " + unitToLabel.get(i.getTarget()));
}
@Override
public void caseDoubleType(DoubleType t) {
emit("dcmpg");
emit("iflt " + unitToLabel.get(i.getTarget()));
}
@Override
public void caseLongType(LongType t) {
emit("lcmp");
emit("iflt " + unitToLabel.get(i.getTarget()));
}
@Override
public void caseFloatType(FloatType t) {
emit("fcmpg");
emit("iflt " + unitToLabel.get(i.getTarget()));
}
@Override
public void caseArrayType(ArrayType t) {
emit("if_acmplt " + unitToLabel.get(i.getTarget()));
}
@Override
public void caseRefType(RefType t) {
emit("if_acmplt " + unitToLabel.get(i.getTarget()));
}
@Override
public void caseNullType(NullType t) {
emit("if_acmplt " + unitToLabel.get(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 caseIntType(IntType t) {
emit("if_icmple " + unitToLabel.get(i.getTarget()));
}
@Override
public void caseBooleanType(BooleanType t) {
emit("if_icmple " + unitToLabel.get(i.getTarget()));
}
@Override
public void caseShortType(ShortType t) {
emit("if_icmple " + unitToLabel.get(i.getTarget()));
}
@Override
public void caseCharType(CharType t) {
emit("if_icmple " + unitToLabel.get(i.getTarget()));
}
@Override
public void caseByteType(ByteType t) {
emit("if_icmple " + unitToLabel.get(i.getTarget()));
}
@Override
public void caseDoubleType(DoubleType t) {
emit("dcmpg");
emit("ifle " + unitToLabel.get(i.getTarget()));
}
@Override
public void caseLongType(LongType t) {
emit("lcmp");
emit("ifle " + unitToLabel.get(i.getTarget()));
}
@Override
public void caseFloatType(FloatType t) {
emit("fcmpg");
emit("ifle " + unitToLabel.get(i.getTarget()));
}
@Override
public void caseArrayType(ArrayType t) {
emit("if_acmple " + unitToLabel.get(i.getTarget()));
}
@Override
public void caseRefType(RefType t) {
emit("if_acmple " + unitToLabel.get(i.getTarget()));
}
@Override
public void caseNullType(NullType t) {
emit("if_acmple " + unitToLabel.get(i.getTarget()));
}
@Override
public void defaultCase(Type t) {
throw new RuntimeException("invalid type");
}
});
}
@Override
public void caseStaticGetInst(StaticGetInst i) {
SootFieldRef field = i.getFieldRef();
emit("getstatic " + slashify(field.declaringClass().getName()) + "/" + field.name() + " " + jasminDescriptorOf(field.type()));
}
@Override
public void caseStaticPutInst(StaticPutInst i) {
emit("putstatic " + slashify(i.getFieldRef().declaringClass().getName()) + "/" + i.getFieldRef().name() + " " + jasminDescriptorOf(i.getFieldRef().type()));
}
@Override
public void caseFieldGetInst(FieldGetInst i) {
emit("getfield " + slashify(i.getFieldRef().declaringClass().getName()) + "/" + i.getFieldRef().name() + " " + jasminDescriptorOf(i.getFieldRef().type()));
}
@Override
public void caseFieldPutInst(FieldPutInst i) {
emit("putfield " + slashify(i.getFieldRef().declaringClass().getName()) + "/" + i.getFieldRef().name() + " " + jasminDescriptorOf(i.getFieldRef().type()));
}
@Override
public void caseInstanceCastInst(InstanceCastInst i) {
Type castType = i.getCastType();
if (castType instanceof RefType)
emit("checkcast " + slashify(((RefType) castType).getClassName()));
else if (castType instanceof ArrayType)
emit("checkcast " + jasminDescriptorOf(castType));
}
@Override
public void caseInstanceOfInst(InstanceOfInst i) {
Type checkType = i.getCheckType();
if (checkType instanceof RefType)
emit("instanceof " + slashify(checkType.toString()));
else if (checkType instanceof ArrayType)
emit("instanceof " + jasminDescriptorOf(checkType));
}
@Override
public void caseNewInst(NewInst i) {
emit("new " + slashify(i.getBaseType().getClassName()));
}
@Override
public void casePrimitiveCastInst(PrimitiveCastInst i) {
emit(i.toString());
}
@Override
public void caseDynamicInvokeInst(DynamicInvokeInst i) {
SootMethodRef m = i.getMethodRef();
SootMethodRef bsm = i.getBootstrapMethodRef();
String bsmArgString = "";
for (Iterator<Value> iterator = i.getBootstrapArgs().iterator(); iterator.hasNext(); ) {
Value val = iterator.next();
bsmArgString += "(" + jasminDescriptorOf(val.getType()) + ")";
bsmArgString += escape(val.toString());
if (iterator.hasNext())
bsmArgString += ",";
}
emit("invokedynamic \"" + m.name() + "\" " + jasminDescriptorOf(m) + " " + slashify(bsm.declaringClass().getName()) + "/" + bsm.name() + jasminDescriptorOf(bsm) + "(" + bsmArgString + ")");
}
private String escape(String bsmArgString) {
return bsmArgString.replace(",", "\\comma").replace(" ", "\\blank").replace("\t", "\\tab").replace("\n", "\\newline");
}
@Override
public void caseStaticInvokeInst(StaticInvokeInst i) {
SootMethodRef m = i.getMethodRef();
emit("invokestatic " + slashify(m.declaringClass().getName()) + "/" + m.name() + jasminDescriptorOf(m));
}
@Override
public void caseVirtualInvokeInst(VirtualInvokeInst i) {
SootMethodRef m = i.getMethodRef();
emit("invokevirtual " + slashify(m.declaringClass().getName()) + "/" + m.name() + jasminDescriptorOf(m));
}
@Override
public void caseInterfaceInvokeInst(InterfaceInvokeInst i) {
SootMethodRef m = i.getMethodRef();
emit("invokeinterface " + slashify(m.declaringClass().getName()) + "/" + m.name() + jasminDescriptorOf(m) + " " + (argCountOf(m) + 1));
}
@Override
public void caseSpecialInvokeInst(SpecialInvokeInst i) {
SootMethodRef m = i.getMethodRef();
emit("invokespecial " + slashify(m.declaringClass().getName()) + "/" + m.name() + jasminDescriptorOf(m));
}
@Override
public void caseThrowInst(ThrowInst i) {
emit("athrow");
}
@Override
public void caseCmpInst(CmpInst i) {
emit("lcmp");
}
@Override
public void caseCmplInst(CmplInst i) {
if (i.getOpType().equals(FloatType.v()))
emit("fcmpl");
else
emit("dcmpl");
}
@Override
public void caseCmpgInst(CmpgInst i) {
if (i.getOpType().equals(FloatType.v()))
emit("fcmpg");
else
emit("dcmpg");
}
private void emitOpTypeInst(final String s, final OpTypeArgInst i) {
i.getOpType().apply(new TypeSwitch() {
private void handleIntCase() {
emit("i" + s);
}
@Override
public void caseIntType(IntType t) {
handleIntCase();
}
@Override
public void caseBooleanType(BooleanType t) {
handleIntCase();
}
@Override
public void caseShortType(ShortType t) {
handleIntCase();
}
@Override
public void caseCharType(CharType t) {
handleIntCase();
}
@Override
public void caseByteType(ByteType t) {
handleIntCase();
}
@Override
public void caseLongType(LongType t) {
emit("l" + s);
}
@Override
public void caseDoubleType(DoubleType t) {
emit("d" + s);
}
@Override
public void caseFloatType(FloatType t) {
emit("f" + s);
}
@Override
public void defaultCase(Type t) {
throw new RuntimeException("Invalid argument type for div");
}
});
}
@Override
public void caseAddInst(AddInst i) {
emitOpTypeInst("add", i);
}
@Override
public void caseDivInst(DivInst i) {
emitOpTypeInst("div", i);
}
@Override
public void caseSubInst(SubInst i) {
emitOpTypeInst("sub", i);
}
@Override
public void caseMulInst(MulInst i) {
emitOpTypeInst("mul", i);
}
@Override
public void caseRemInst(RemInst i) {
emitOpTypeInst("rem", i);
}
@Override
public void caseShlInst(ShlInst i) {
emitOpTypeInst("shl", i);
}
@Override
public void caseAndInst(AndInst i) {
emitOpTypeInst("and", i);
}
@Override
public void caseOrInst(OrInst i) {
emitOpTypeInst("or", i);
}
@Override
public void caseXorInst(XorInst i) {
emitOpTypeInst("xor", i);
}
@Override
public void caseShrInst(ShrInst i) {
emitOpTypeInst("shr", i);
}
@Override
public void caseUshrInst(UshrInst i) {
emitOpTypeInst("ushr", i);
}
@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");
emit("iinc " + localToSlot.get(i.getLocal()) + " " + i.getConstant());
}
@Override
public void caseArrayLengthInst(ArrayLengthInst i) {
emit("arraylength");
}
@Override
public void caseNegInst(NegInst i) {
emitOpTypeInst("neg", i);
}
@Override
public void caseNewArrayInst(NewArrayInst i) {
if (i.getBaseType() instanceof RefType)
emit("anewarray " + slashify(((RefType) i.getBaseType()).getClassName()));
else if (i.getBaseType() instanceof ArrayType)
emit("anewarray " + jasminDescriptorOf(i.getBaseType()));
else
emit("newarray " + i.getBaseType().toString());
}
@Override
public void caseNewMultiArrayInst(NewMultiArrayInst i) {
emit("multianewarray " + jasminDescriptorOf(i.getBaseType()) + " " + i.getDimensionCount());
}
@Override
public void caseLookupSwitchInst(LookupSwitchInst i) {
emit("lookupswitch");
List<IntConstant> lookupValues = i.getLookupValues();
List<Unit> targets = i.getTargets();
for (int j = 0; j < lookupValues.size(); j++) emit(" " + lookupValues.get(j) + " : " + unitToLabel.get(targets.get(j)));
emit(" default : " + unitToLabel.get(i.getDefaultTarget()));
}
@Override
public void caseTableSwitchInst(TableSwitchInst i) {
emit("tableswitch " + i.getLowIndex() + " ; high = " + i.getHighIndex());
List<Unit> targets = i.getTargets();
for (int j = 0; j < targets.size(); j++) emit(" " + unitToLabel.get(targets.get(j)));
emit("default : " + unitToLabel.get(i.getDefaultTarget()));
}
private boolean isDwordType(Type t) {
return t instanceof LongType || t instanceof DoubleType || t instanceof DoubleWordType;
}
@Override
public void caseDup1Inst(Dup1Inst i) {
Type firstOpType = i.getOp1Type();
if (isDwordType(firstOpType))
// (form 2)
emit("dup2");
else
emit("dup");
}
@Override
public void caseDup2Inst(Dup2Inst i) {
Type firstOpType = i.getOp1Type();
Type secondOpType = i.getOp2Type();
// Use a pair of insts to simulate them.
if (isDwordType(firstOpType)) {
// (form 2)
emit("dup2");
if (isDwordType(secondOpType)) {
// (form 2 -- by simulation)
emit("dup2");
} else
// also a simulation
emit("dup");
} else if (isDwordType(secondOpType)) {
if (isDwordType(firstOpType)) {
// (form 2)
emit("dup2");
} else
emit("dup");
// (form 2 -- complete the simulation)
emit("dup2");
} else {
// form 1
emit("dup2");
}
}
@Override
public void caseDup1_x1Inst(Dup1_x1Inst i) {
Type opType = i.getOp1Type();
Type underType = i.getUnder1Type();
if (isDwordType(opType)) {
if (isDwordType(underType)) {
// (form 4)
emit("dup2_x2");
} else
// (form 2)
emit("dup2_x1");
} else {
if (isDwordType(underType))
// (form 2)
emit("dup_x2");
else
// (only one form)
emit("dup_x1");
}
}
@Override
public void caseDup1_x2Inst(Dup1_x2Inst i) {
Type opType = i.getOp1Type();
Type under1Type = i.getUnder1Type();
Type under2Type = i.getUnder2Type();
if (isDwordType(opType)) {
if (!isDwordType(under1Type) && !isDwordType(under2Type))
// (form 2)
emit("dup2_x2");
else
throw new RuntimeException("magic not implemented yet");
} else {
if (isDwordType(under1Type) || isDwordType(under2Type))
throw new RuntimeException("magic not implemented yet");
}
// (form 1)
emit("dup_x2");
}
@Override
public void caseDup2_x1Inst(Dup2_x1Inst i) {
Type op1Type = i.getOp1Type();
Type op2Type = i.getOp2Type();
Type under1Type = i.getUnder1Type();
/*
* From VM Spec: cat1 = category 1 (word type) cat2 = category 2
* (doubleword)
*
* Form 1: [..., cat1_value3, cat1_value2, cat1_value1]->[...,
* cat1_value2, cat1_value1, cat1_value3, cat1_value2,
* cat1_value1] Form 2: [..., cat1_value2, cat2_value1]->[...,
* cat2_value1, cat1_value2, cat2_value1]
*/
if (isDwordType(under1Type)) {
if (!isDwordType(op1Type) && !isDwordType(op2Type))
throw new RuntimeException("magic not implemented yet");
else
// (form 3)
emit("dup2_x2");
} else {
if ((isDwordType(op1Type) && op2Type != null) || isDwordType(op2Type))
throw new RuntimeException("magic not implemented yet");
}
// (form 1)
emit("dup2_x1");
}
@Override
public void caseDup2_x2Inst(Dup2_x2Inst i) {
Type op1Type = i.getOp1Type();
Type op2Type = i.getOp2Type();
Type under1Type = i.getUnder1Type();
Type under2Type = i.getUnder2Type();
// 07-20-2006 Michael Batchelder
// NOW handling all types of dup2_x2
/*
* From VM Spec: cat1 = category 1 (word type) cat2 = category 2
* (doubleword) Form 1: [..., cat1_value4, cat1_value3,
* cat1_value2, cat1_value1]->[..., cat1_value2, cat1_value1,
* cat1_value4, cat1_value3, cat1_value2, cat1_value1] Form 2:
* [..., cat1_value3, cat1_value2, cat2_value1]->[ ...,
* cat2_value1, cat1_value3, cat1_value2, cat2_value1] Form 3:
* [..., cat2_value3, cat1_value2, cat1_value1]->[...,
* cat1_value2, cat1_value1, cat2_value3, cat1_value2,
* cat1_value1] Form 4: [..., cat2_value2, cat2_value1]->[...,
* cat2_value1, cat2_value2, cat2_value1]
*/
boolean malformed = true;
if (isDwordType(op1Type)) {
if (op2Type == null && under1Type != null)
if ((under2Type == null && isDwordType(under1Type)) || (!isDwordType(under1Type) && under2Type != null && !isDwordType(under2Type)))
malformed = false;
} else if (op1Type != null && op2Type != null && !isDwordType(op2Type)) {
if ((under2Type == null && isDwordType(under1Type)) || (under1Type != null && !isDwordType(under1Type) && under2Type != null && !isDwordType(under2Type)))
malformed = false;
}
if (malformed)
throw new RuntimeException("magic not implemented yet");
// (form 1)
emit("dup2_x2");
}
@Override
public void caseSwapInst(SwapInst i) {
emit("swap");
}
});
}
use of soot.StmtAddressType in project soot by Sable.
the class LocalNameStandardizer method internalTransform.
@Override
protected void internalTransform(Body body, String phaseName, Map<String, String> options) {
boolean onlyStackName = PhaseOptions.getBoolean(options, "only-stack-locals");
boolean sortLocals = PhaseOptions.getBoolean(options, "sort-locals");
final BooleanType booleanType = BooleanType.v();
final ByteType byteType = ByteType.v();
final ShortType shortType = ShortType.v();
final CharType charType = CharType.v();
final IntType intType = IntType.v();
final LongType longType = LongType.v();
final DoubleType doubleType = DoubleType.v();
final FloatType floatType = FloatType.v();
final ErroneousType erroneousType = ErroneousType.v();
final UnknownType unknownType = UnknownType.v();
final StmtAddressType stmtAddressType = StmtAddressType.v();
final NullType nullType = NullType.v();
// Change the names to the standard forms now.
{
int objectCount = 0;
int intCount = 0;
int longCount = 0;
int floatCount = 0;
int doubleCount = 0;
int addressCount = 0;
int errorCount = 0;
int nullCount = 0;
/* The goal of this option is to ensure that local ordering remains
* consistent between different iterations of soot. This helps to ensure
* things like stable string representations of instructions and stable
* jimple representations of a methods body when soot is used to load
* the same code in different iterations.
*
* First sorts the locals alphabetically by the string representation of
* their type. Then if there are two locals with the same type, it uses
* the only other source of structurally stable information (i.e. the
* instructions themselves) to produce an ordering for the locals
* that remains consistent between different soot instances. It achieves
* this by determining the position of a local's first occurrence in the
* instruction's list of definition statements. This position is then used
* to sort the locals with the same type in an ascending order.
*
* The only times that this may not produce a consistent ordering for the
* locals between different soot instances is if a local is never defined in
* the instructions or if the instructions themselves are changed in some way
* that effects the ordering of the locals. In the first case, if a local is
* never defined, the other jimple body phases will remove this local as it is
* unused. As such, all we have to do is rerun this LocalNameStandardizer after
* all other jimple body phases to eliminate any ambiguity introduced by these
* phases and by the removed unused locals. In the second case, if the instructions
* themselves changed then the user would have had to intentionally told soot to
* modify the instructions of the code. Otherwise, the instructions would not have
* changed because we assume the instructions to always be structurally stable
* between different instances of soot. As such, in this instance, the user should
* not be expecting soot to produce the same output as the input and thus the
* ordering of the locals does not matter.
*/
if (sortLocals) {
Chain<Local> locals = body.getLocals();
final List<ValueBox> defs = body.getDefBoxes();
ArrayList<Local> sortedLocals = new ArrayList<Local>(locals);
Collections.sort(sortedLocals, new Comparator<Local>() {
private Map<Local, Integer> firstOccuranceCache = new HashMap<Local, Integer>();
@Override
public int compare(Local arg0, Local arg1) {
int ret = arg0.getType().toString().compareTo(arg1.getType().toString());
if (ret == 0) {
ret = Integer.compare(getFirstOccurance(arg0), getFirstOccurance(arg1));
}
return ret;
}
private int getFirstOccurance(Local l) {
Integer cur = firstOccuranceCache.get(l);
if (cur != null) {
return cur;
} else {
int count = 0;
int first = -1;
for (ValueBox vb : defs) {
Value v = vb.getValue();
if (v instanceof Local && v.equals(l)) {
first = count;
break;
}
count++;
}
firstOccuranceCache.put(l, first);
return first;
}
}
});
locals.clear();
locals.addAll(sortedLocals);
}
for (Local l : body.getLocals()) {
String prefix = "";
if (l.getName().startsWith("$"))
prefix = "$";
else {
if (onlyStackName)
continue;
}
final Type type = l.getType();
if (type.equals(booleanType))
l.setName(prefix + "z" + intCount++);
else if (type.equals(byteType))
l.setName(prefix + "b" + longCount++);
else if (type.equals(shortType))
l.setName(prefix + "s" + longCount++);
else if (type.equals(charType))
l.setName(prefix + "c" + longCount++);
else if (type.equals(intType))
l.setName(prefix + "i" + longCount++);
else if (type.equals(longType))
l.setName(prefix + "l" + longCount++);
else if (type.equals(doubleType))
l.setName(prefix + "d" + doubleCount++);
else if (type.equals(floatType))
l.setName(prefix + "f" + floatCount++);
else if (type.equals(stmtAddressType))
l.setName(prefix + "a" + addressCount++);
else if (type.equals(erroneousType) || type.equals(unknownType)) {
l.setName(prefix + "e" + errorCount++);
} else if (type.equals(nullType))
l.setName(prefix + "n" + nullCount++);
else
l.setName(prefix + "r" + objectCount++);
}
}
}
use of soot.StmtAddressType 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