use of soot.NullType in project robovm by robovm.
the class MethodCompiler method assign.
private void assign(DefinitionStmt stmt) {
/*
* leftOp is either a Local, an ArrayRef or a FieldRef
* rightOp is either a Local, a Ref, or an Expr
*/
soot.Value rightOp = stmt.getRightOp();
Value result;
if (rightOp instanceof Immediate) {
Immediate immediate = (Immediate) rightOp;
result = immediate(stmt, immediate);
} else if (rightOp instanceof ThisRef) {
result = function.getParameterRef(1);
} else if (rightOp instanceof ParameterRef) {
ParameterRef ref = (ParameterRef) rightOp;
int index = (sootMethod.isStatic() ? 1 : 2) + ref.getIndex();
Value p = new VariableRef("p" + index, getType(ref.getType()));
result = widenToI32Value(stmt, p, isUnsigned(ref.getType()));
} else if (rightOp instanceof CaughtExceptionRef) {
result = call(stmt, BC_EXCEPTION_CLEAR, env);
} else if (rightOp instanceof ArrayRef) {
ArrayRef ref = (ArrayRef) rightOp;
VariableRef base = (VariableRef) immediate(stmt, (Immediate) ref.getBase());
if (ref.getType() instanceof NullType) {
// The base value is always null. Do a null check which will
// always throw NPE.
checkNull(stmt, base);
return;
} else {
Value index = immediate(stmt, (Immediate) ref.getIndex());
checkNull(stmt, base);
checkBounds(stmt, base, index);
result = call(stmt, getArrayLoad(ref.getType()), base, index);
result = widenToI32Value(stmt, result, isUnsigned(ref.getType()));
}
} else if (rightOp instanceof InstanceFieldRef) {
InstanceFieldRef ref = (InstanceFieldRef) rightOp;
Value base = immediate(stmt, (Immediate) ref.getBase());
checkNull(stmt, base);
FunctionRef fn = null;
if (canAccessDirectly(ref)) {
fn = new FunctionRef(Symbols.getterSymbol(ref.getFieldRef()), new FunctionType(getType(ref.getType()), ENV_PTR, OBJECT_PTR));
} else {
soot.Type runtimeType = ref.getBase().getType();
String targetClassName = getInternalName(ref.getFieldRef().declaringClass());
String runtimeClassName = runtimeType == NullType.v() ? targetClassName : getInternalName(runtimeType);
Trampoline trampoline = new GetField(this.className, targetClassName, ref.getFieldRef().name(), getDescriptor(ref.getFieldRef().type()), runtimeClassName);
trampolines.add(trampoline);
fn = trampoline.getFunctionRef();
}
result = call(stmt, fn, env, base);
result = widenToI32Value(stmt, result, isUnsigned(ref.getType()));
} else if (rightOp instanceof StaticFieldRef) {
StaticFieldRef ref = (StaticFieldRef) rightOp;
FunctionRef fn = config.isDebug() ? null : Intrinsics.getIntrinsic(sootMethod, stmt);
if (fn == null) {
if (canAccessDirectly(ref)) {
fn = new FunctionRef(Symbols.getterSymbol(ref.getFieldRef()), new FunctionType(getType(ref.getType()), ENV_PTR));
} else {
String targetClassName = getInternalName(ref.getFieldRef().declaringClass());
Trampoline trampoline = new GetStatic(this.className, targetClassName, ref.getFieldRef().name(), getDescriptor(ref.getFieldRef().type()));
trampolines.add(trampoline);
fn = trampoline.getFunctionRef();
}
}
result = call(stmt, fn, env);
result = widenToI32Value(stmt, result, isUnsigned(ref.getType()));
} else if (rightOp instanceof Expr) {
if (rightOp instanceof BinopExpr) {
BinopExpr expr = (BinopExpr) rightOp;
Type rightType = getLocalType(expr.getType());
Variable resultVar = function.newVariable(rightType);
result = resultVar.ref();
Value op1 = immediate(stmt, (Immediate) expr.getOp1());
Value op2 = immediate(stmt, (Immediate) expr.getOp2());
if (rightOp instanceof AddExpr) {
if (rightType instanceof IntegerType) {
function.add(new Add(resultVar, op1, op2)).attach(stmt);
} else {
function.add(new Fadd(resultVar, op1, op2)).attach(stmt);
}
} else if (rightOp instanceof AndExpr) {
function.add(new And(resultVar, op1, op2)).attach(stmt);
} else if (rightOp instanceof CmpExpr) {
Variable t1 = function.newVariable(I1);
Variable t2 = function.newVariable(I1);
Variable t3 = function.newVariable(resultVar.getType());
Variable t4 = function.newVariable(resultVar.getType());
function.add(new Icmp(t1, Condition.slt, op1, op2)).attach(stmt);
function.add(new Icmp(t2, Condition.sgt, op1, op2)).attach(stmt);
function.add(new Zext(t3, new VariableRef(t1), resultVar.getType())).attach(stmt);
function.add(new Zext(t4, new VariableRef(t2), resultVar.getType())).attach(stmt);
function.add(new Sub(resultVar, new VariableRef(t4), new VariableRef(t3))).attach(stmt);
} else if (rightOp instanceof DivExpr) {
if (rightType instanceof IntegerType) {
FunctionRef f = rightType == I64 ? LDIV : IDIV;
result = call(stmt, f, env, op1, op2);
} else {
// float or double
function.add(new Fdiv(resultVar, op1, op2)).attach(stmt);
}
} else if (rightOp instanceof MulExpr) {
if (rightType instanceof IntegerType) {
function.add(new Mul(resultVar, op1, op2)).attach(stmt);
} else {
function.add(new Fmul(resultVar, op1, op2)).attach(stmt);
}
} else if (rightOp instanceof OrExpr) {
function.add(new Or(resultVar, op1, op2)).attach(stmt);
} else if (rightOp instanceof RemExpr) {
if (rightType instanceof IntegerType) {
FunctionRef f = rightType == I64 ? LREM : IREM;
result = call(stmt, f, env, op1, op2);
} else {
FunctionRef f = rightType == DOUBLE ? DREM : FREM;
result = call(stmt, f, env, op1, op2);
}
} else if (rightOp instanceof ShlExpr || rightOp instanceof ShrExpr || rightOp instanceof UshrExpr) {
IntegerType type = (IntegerType) op1.getType();
int bits = type.getBits();
Variable t = function.newVariable(op2.getType());
function.add(new And(t, op2, new IntegerConstant(bits - 1, (IntegerType) op2.getType()))).attach(stmt);
Value shift = t.ref();
if (((IntegerType) shift.getType()).getBits() < bits) {
Variable tmp = function.newVariable(type);
function.add(new Zext(tmp, shift, type)).attach(stmt);
shift = tmp.ref();
}
if (rightOp instanceof ShlExpr) {
function.add(new Shl(resultVar, op1, shift)).attach(stmt);
} else if (rightOp instanceof ShrExpr) {
function.add(new Ashr(resultVar, op1, shift)).attach(stmt);
} else {
function.add(new Lshr(resultVar, op1, shift)).attach(stmt);
}
} else if (rightOp instanceof SubExpr) {
if (rightType instanceof IntegerType) {
function.add(new Sub(resultVar, op1, op2)).attach(stmt);
} else {
function.add(new Fsub(resultVar, op1, op2)).attach(stmt);
}
} else if (rightOp instanceof XorExpr) {
function.add(new Xor(resultVar, op1, op2)).attach(stmt);
} else if (rightOp instanceof XorExpr) {
function.add(new Xor(resultVar, op1, op2)).attach(stmt);
} else if (rightOp instanceof CmplExpr) {
FunctionRef f = op1.getType() == FLOAT ? FCMPL : DCMPL;
function.add(new Call(resultVar, f, op1, op2)).attach(stmt);
} else if (rightOp instanceof CmpgExpr) {
FunctionRef f = op1.getType() == FLOAT ? FCMPG : DCMPG;
function.add(new Call(resultVar, f, op1, op2)).attach(stmt);
} else {
throw new IllegalArgumentException("Unknown type for rightOp: " + rightOp.getClass());
}
} else if (rightOp instanceof CastExpr) {
Value op = immediate(stmt, (Immediate) ((CastExpr) rightOp).getOp());
soot.Type sootTargetType = ((CastExpr) rightOp).getCastType();
soot.Type sootSourceType = ((CastExpr) rightOp).getOp().getType();
if (sootTargetType instanceof PrimType) {
Type targetType = getType(sootTargetType);
Type sourceType = getType(sootSourceType);
if (targetType instanceof IntegerType && sourceType instanceof IntegerType) {
// op is at least I32 and has already been widened if source type had fewer bits then I32
IntegerType toType = (IntegerType) targetType;
IntegerType fromType = (IntegerType) op.getType();
Variable v = function.newVariable(toType);
if (fromType.getBits() < toType.getBits()) {
// Widening
if (isUnsigned(sootSourceType)) {
function.add(new Zext(v, op, toType)).attach(stmt);
} else {
function.add(new Sext(v, op, toType)).attach(stmt);
}
} else if (fromType.getBits() == toType.getBits()) {
function.add(new Bitcast(v, op, toType)).attach(stmt);
} else {
// Narrow
function.add(new Trunc(v, op, toType)).attach(stmt);
}
result = widenToI32Value(stmt, v.ref(), isUnsigned(sootTargetType));
} else if (targetType instanceof FloatingPointType && sourceType instanceof IntegerType) {
// we always to a signed conversion since if op is char it has already been zero extended to I32
Variable v = function.newVariable(targetType);
function.add(new Sitofp(v, op, targetType)).attach(stmt);
result = v.ref();
} else if (targetType instanceof FloatingPointType && sourceType instanceof FloatingPointType) {
Variable v = function.newVariable(targetType);
if (targetType == FLOAT && sourceType == DOUBLE) {
function.add(new Fptrunc(v, op, targetType)).attach(stmt);
} else if (targetType == DOUBLE && sourceType == FLOAT) {
function.add(new Fpext(v, op, targetType)).attach(stmt);
} else {
function.add(new Bitcast(v, op, targetType)).attach(stmt);
}
result = v.ref();
} else {
// F2I, F2L, D2I, D2L
FunctionRef f = null;
if (targetType == I32 && sourceType == FLOAT) {
f = F2I;
} else if (targetType == I64 && sourceType == FLOAT) {
f = F2L;
} else if (targetType == I32 && sourceType == DOUBLE) {
f = D2I;
} else if (targetType == I64 && sourceType == DOUBLE) {
f = D2L;
} else {
throw new IllegalArgumentException();
}
Variable v = function.newVariable(targetType);
function.add(new Call(v, f, op)).attach(stmt);
result = v.ref();
}
} else {
if (sootTargetType instanceof soot.ArrayType && ((soot.ArrayType) sootTargetType).getElementType() instanceof PrimType) {
soot.Type primType = ((soot.ArrayType) sootTargetType).getElementType();
GlobalRef arrayClassPtr = new GlobalRef("array_" + getDescriptor(primType), CLASS_PTR);
Variable arrayClass = function.newVariable(CLASS_PTR);
function.add(new Load(arrayClass, arrayClassPtr)).attach(stmt);
result = call(stmt, CHECKCAST_PRIM_ARRAY, env, arrayClass.ref(), op);
} else {
String targetClassName = getInternalName(sootTargetType);
Trampoline trampoline = new Checkcast(this.className, targetClassName);
trampolines.add(trampoline);
result = call(stmt, trampoline.getFunctionRef(), env, op);
}
}
} else if (rightOp instanceof InstanceOfExpr) {
Value op = immediate(stmt, (Immediate) ((InstanceOfExpr) rightOp).getOp());
soot.Type checkType = ((InstanceOfExpr) rightOp).getCheckType();
if (checkType instanceof soot.ArrayType && ((soot.ArrayType) checkType).getElementType() instanceof PrimType) {
soot.Type primType = ((soot.ArrayType) checkType).getElementType();
GlobalRef arrayClassPtr = new GlobalRef("array_" + getDescriptor(primType), CLASS_PTR);
Variable arrayClass = function.newVariable(CLASS_PTR);
function.add(new Load(arrayClass, arrayClassPtr)).attach(stmt);
result = call(stmt, INSTANCEOF_PRIM_ARRAY, env, arrayClass.ref(), op);
} else {
String targetClassName = getInternalName(checkType);
Trampoline trampoline = new Instanceof(this.className, targetClassName);
trampolines.add(trampoline);
result = call(stmt, trampoline.getFunctionRef(), env, op);
}
} else if (rightOp instanceof NewExpr) {
String targetClassName = getInternalName(((NewExpr) rightOp).getBaseType());
FunctionRef fn = null;
if (targetClassName.equals(this.className)) {
fn = FunctionBuilder.allocator(sootMethod.getDeclaringClass()).ref();
} else {
Trampoline trampoline = new New(this.className, targetClassName);
trampolines.add(trampoline);
fn = trampoline.getFunctionRef();
}
result = call(stmt, fn, env);
} else if (rightOp instanceof NewArrayExpr) {
NewArrayExpr expr = (NewArrayExpr) rightOp;
Value size = immediate(stmt, (Immediate) expr.getSize());
if (expr.getBaseType() instanceof PrimType) {
result = call(stmt, getNewArray(expr.getBaseType()), env, size);
} else {
String targetClassName = getInternalName(expr.getType());
Trampoline trampoline = new Anewarray(this.className, targetClassName);
trampolines.add(trampoline);
result = call(stmt, trampoline.getFunctionRef(), env, size);
}
} else if (rightOp instanceof NewMultiArrayExpr) {
NewMultiArrayExpr expr = (NewMultiArrayExpr) rightOp;
if (expr.getBaseType().numDimensions == 1 && expr.getBaseType().getElementType() instanceof PrimType) {
Value size = immediate(stmt, (Immediate) expr.getSize(0));
result = call(stmt, getNewArray(expr.getBaseType().getElementType()), env, size);
} else {
for (int i = 0; i < expr.getSizeCount(); i++) {
Value size = immediate(stmt, (Immediate) expr.getSize(i));
Variable ptr = function.newVariable(new PointerType(I32));
function.add(new Getelementptr(ptr, dims.ref(), 0, i)).attach(stmt);
function.add(new Store(size, ptr.ref())).attach(stmt);
}
Variable dimsI32 = function.newVariable(new PointerType(I32));
function.add(new Bitcast(dimsI32, dims.ref(), dimsI32.getType())).attach(stmt);
String targetClassName = getInternalName(expr.getType());
Trampoline trampoline = new Multianewarray(this.className, targetClassName);
trampolines.add(trampoline);
result = call(stmt, trampoline.getFunctionRef(), env, new IntegerConstant(expr.getSizeCount()), dimsI32.ref());
}
} else if (rightOp instanceof InvokeExpr) {
result = invokeExpr(stmt, (InvokeExpr) rightOp);
} else if (rightOp instanceof LengthExpr) {
Value op = immediate(stmt, (Immediate) ((LengthExpr) rightOp).getOp());
checkNull(stmt, op);
Variable v = function.newVariable(I32);
function.add(new Call(v, ARRAY_LENGTH, op)).attach(stmt);
result = v.ref();
} else if (rightOp instanceof NegExpr) {
NegExpr expr = (NegExpr) rightOp;
Value op = immediate(stmt, (Immediate) expr.getOp());
Type rightType = op.getType();
Variable v = function.newVariable(op.getType());
if (rightType instanceof IntegerType) {
function.add(new Sub(v, new IntegerConstant(0, (IntegerType) rightType), op)).attach(stmt);
} else {
function.add(new Fmul(v, new FloatingPointConstant(-1.0, (FloatingPointType) rightType), op)).attach(stmt);
}
result = v.ref();
} else {
throw new IllegalArgumentException("Unknown type for rightOp: " + rightOp.getClass());
}
} else {
throw new IllegalArgumentException("Unknown type for rightOp: " + rightOp.getClass());
}
soot.Value leftOp = stmt.getLeftOp();
if (leftOp instanceof Local) {
Local local = (Local) leftOp;
VariableRef v = new VariableRef(local.getName(), new PointerType(getLocalType(leftOp.getType())));
function.add(new Store(result, v, !sootMethod.getActiveBody().getTraps().isEmpty())).attach(stmt);
} else {
Type leftType = getType(leftOp.getType());
Value narrowedResult = narrowFromI32Value(stmt, leftType, result);
if (leftOp instanceof ArrayRef) {
ArrayRef ref = (ArrayRef) leftOp;
VariableRef base = (VariableRef) immediate(stmt, (Immediate) ref.getBase());
Value index = immediate(stmt, (Immediate) ref.getIndex());
checkNull(stmt, base);
checkBounds(stmt, base, index);
if (leftOp.getType() instanceof RefLikeType) {
call(stmt, BC_SET_OBJECT_ARRAY_ELEMENT, env, base, index, narrowedResult);
} else {
call(stmt, getArrayStore(leftOp.getType()), base, index, narrowedResult);
}
} else if (leftOp instanceof InstanceFieldRef) {
InstanceFieldRef ref = (InstanceFieldRef) leftOp;
Value base = immediate(stmt, (Immediate) ref.getBase());
checkNull(stmt, base);
FunctionRef fn = null;
if (canAccessDirectly(ref)) {
fn = new FunctionRef(Symbols.setterSymbol(ref.getFieldRef()), new FunctionType(VOID, ENV_PTR, OBJECT_PTR, getType(ref.getType())));
} else {
soot.Type runtimeType = ref.getBase().getType();
String targetClassName = getInternalName(ref.getFieldRef().declaringClass());
String runtimeClassName = runtimeType == NullType.v() ? targetClassName : getInternalName(runtimeType);
Trampoline trampoline = new PutField(this.className, targetClassName, ref.getFieldRef().name(), getDescriptor(ref.getFieldRef().type()), runtimeClassName);
trampolines.add(trampoline);
fn = trampoline.getFunctionRef();
}
call(stmt, fn, env, base, narrowedResult);
} else if (leftOp instanceof StaticFieldRef) {
StaticFieldRef ref = (StaticFieldRef) leftOp;
FunctionRef fn = null;
if (canAccessDirectly(ref)) {
fn = new FunctionRef(Symbols.setterSymbol(ref.getFieldRef()), new FunctionType(VOID, ENV_PTR, getType(ref.getType())));
} else {
String targetClassName = getInternalName(ref.getFieldRef().declaringClass());
Trampoline trampoline = new PutStatic(this.className, targetClassName, ref.getFieldRef().name(), getDescriptor(ref.getFieldRef().type()));
trampolines.add(trampoline);
fn = trampoline.getFunctionRef();
}
call(stmt, fn, env, narrowedResult);
} else {
throw new IllegalArgumentException("Unknown type for leftOp: " + leftOp.getClass());
}
}
}
use of soot.NullType 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.NullType in project soot by Sable.
the class TypeAssigner method replaceNullType.
/**
* Replace statements using locals with null_type type and that would
* throw a NullPointerException at runtime by a set of instructions
* throwing a NullPointerException.
*
* This is done to remove locals with null_type type.
*
* @param b
*/
private void replaceNullType(Body b) {
List<Local> localsToRemove = new ArrayList<Local>();
boolean hasNullType = false;
// check if any local has null_type
for (Local l : b.getLocals()) {
if (l.getType() instanceof NullType) {
localsToRemove.add(l);
hasNullType = true;
}
}
// No local with null_type
if (!hasNullType)
return;
// force to propagate null constants
Map<String, String> opts = PhaseOptions.v().getPhaseOptions("jop.cpf");
if (!opts.containsKey("enabled") || !opts.get("enabled").equals("true")) {
logger.warn("Cannot run TypeAssigner.replaceNullType(Body). Try to enable jop.cfg.");
return;
}
ConstantPropagatorAndFolder.v().transform(b);
List<Unit> unitToReplaceByException = new ArrayList<Unit>();
for (Unit u : b.getUnits()) {
for (ValueBox vb : u.getUseBoxes()) {
if (vb.getValue() instanceof Local && ((Local) vb.getValue()).getType() instanceof NullType) {
Local l = (Local) vb.getValue();
Stmt s = (Stmt) u;
boolean replace = false;
if (s.containsArrayRef()) {
ArrayRef r = s.getArrayRef();
if (r.getBase() == l) {
replace = true;
}
} else if (s.containsFieldRef()) {
FieldRef r = s.getFieldRef();
if (r instanceof InstanceFieldRef) {
InstanceFieldRef ir = (InstanceFieldRef) r;
if (ir.getBase() == l) {
replace = true;
}
}
} else if (s.containsInvokeExpr()) {
InvokeExpr ie = s.getInvokeExpr();
if (ie instanceof InstanceInvokeExpr) {
InstanceInvokeExpr iie = (InstanceInvokeExpr) ie;
if (iie.getBase() == l) {
replace = true;
}
}
}
if (replace) {
unitToReplaceByException.add(u);
}
}
}
}
for (Unit u : unitToReplaceByException) {
soot.dexpler.Util.addExceptionAfterUnit(b, "java.lang.NullPointerException", u, "This statement would have triggered an Exception: " + u);
b.getUnits().remove(u);
}
// should be done on a separate phase
DeadAssignmentEliminator.v().transform(b);
UnusedLocalEliminator.v().transform(b);
}
use of soot.NullType in project soot by Sable.
the class TypeResolverBV method assign_types_1_2.
private void assign_types_1_2() throws TypeException {
for (Iterator<Local> localIt = stmtBody.getLocals().iterator(); localIt.hasNext(); ) {
final Local local = localIt.next();
TypeVariableBV var = typeVariable(local);
if (var == null) {
local.setType(RefType.v("java.lang.Object"));
} else if (var.depth() == 0) {
if (var.type() == null) {
TypeVariableBV.error("Type Error(5): Variable without type");
} else {
local.setType(var.type().type());
}
} else {
TypeVariableBV element = var.element();
for (int j = 1; j < var.depth(); j++) {
element = element.element();
}
if (element.type() == null) {
TypeVariableBV.error("Type Error(6): Array variable without base type");
} else if (element.type().type() instanceof NullType) {
local.setType(NullType.v());
} else {
Type t = element.type().type();
if (t instanceof IntType) {
local.setType(var.approx().type());
} else {
local.setType(ArrayType.v(t, var.depth()));
}
}
}
if (DEBUG) {
if ((var != null) && (var.approx() != null) && (var.approx().type() != null) && (local != null) && (local.getType() != null) && !local.getType().equals(var.approx().type())) {
logger.debug("local: " + local + ", type: " + local.getType() + ", approx: " + var.approx().type());
}
}
}
}
use of soot.NullType in project soot by Sable.
the class ConstraintCollector method caseAssignStmt.
public void caseAssignStmt(AssignStmt stmt) {
Value l = stmt.getLeftOp();
Value r = stmt.getRightOp();
TypeVariable left = null;
TypeVariable 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 (uses) {
if ((base.numDimensions == 1) && (base.baseType instanceof IntegerType)) {
left = resolver.typeVariable(base.baseType);
}
if (index instanceof Local) {
resolver.typeVariable((Local) index).addParent(resolver.INT);
}
}
}
} else if (l instanceof Local) {
if (((Local) l).getType() instanceof IntegerType) {
left = resolver.typeVariable((Local) l);
}
} else if (l instanceof InstanceFieldRef) {
if (uses) {
InstanceFieldRef ref = (InstanceFieldRef) l;
Type fieldType = ref.getFieldRef().type();
if (fieldType instanceof IntegerType) {
left = resolver.typeVariable(ref.getFieldRef().type());
}
}
} else if (l instanceof StaticFieldRef) {
if (uses) {
StaticFieldRef ref = (StaticFieldRef) l;
Type fieldType = ref.getFieldRef().type();
if (fieldType instanceof IntegerType) {
left = resolver.typeVariable(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)) {
Value index = ref.getIndex();
// Be careful, dex can do some weird object/array casting
if (baset instanceof ArrayType) {
ArrayType base = (ArrayType) baset;
if ((base.numDimensions == 1) && (base.baseType instanceof IntegerType)) {
right = resolver.typeVariable(base.baseType);
}
} else if (baset instanceof IntegerType)
right = resolver.typeVariable(baset);
if (uses)
if (index instanceof Local)
resolver.typeVariable((Local) index).addParent(resolver.INT);
}
} else if (r instanceof DoubleConstant) {
} else if (r instanceof FloatConstant) {
} else if (r instanceof IntConstant) {
int value = ((IntConstant) r).value;
if (value < -32768) {
right = resolver.INT;
} else if (value < -128) {
right = resolver.SHORT;
} else if (value < 0) {
right = resolver.BYTE;
} else if (value < 2) {
right = resolver.R0_1;
} else if (value < 128) {
right = resolver.R0_127;
} else if (value < 32768) {
right = resolver.R0_32767;
} else if (value < 65536) {
right = resolver.CHAR;
} else {
right = resolver.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();
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 ((be instanceof AddExpr) || (be instanceof SubExpr) || (be instanceof DivExpr) || (be instanceof RemExpr) || (be instanceof MulExpr)) {
if (lop != null && rop != null) {
if (uses) {
if (lop.type() == null) {
lop.addParent(resolver.INT);
}
if (rop.type() == null) {
rop.addParent(resolver.INT);
}
}
right = resolver.INT;
}
} else if ((be instanceof AndExpr) || (be instanceof OrExpr) || (be instanceof XorExpr)) {
if (lop != null && rop != null) {
TypeVariable common = resolver.typeVariable();
if (rop != null)
rop.addParent(common);
if (lop != null)
lop.addParent(common);
right = common;
}
} else if (be instanceof ShlExpr) {
if (uses) {
if (lop != null && lop.type() == null) {
lop.addParent(resolver.INT);
}
if (rop.type() == null) {
rop.addParent(resolver.INT);
}
}
right = (lop == null) ? null : resolver.INT;
} else if ((be instanceof ShrExpr) || (be instanceof UshrExpr)) {
if (uses) {
if (lop != null && lop.type() == null) {
lop.addParent(resolver.INT);
}
if (rop.type() == null) {
rop.addParent(resolver.INT);
}
}
right = lop;
} else if ((be instanceof CmpExpr) || (be instanceof CmpgExpr) || (be instanceof CmplExpr)) {
right = resolver.BYTE;
} else if ((be instanceof EqExpr) || (be instanceof GeExpr) || (be instanceof GtExpr) || (be instanceof LeExpr) || (be instanceof LtExpr) || (be instanceof NeExpr)) {
if (uses) {
TypeVariable common = resolver.typeVariable();
if (rop != null)
rop.addParent(common);
if (lop != null)
lop.addParent(common);
}
right = resolver.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 = resolver.typeVariable(ce.getCastType());
}
} else if (r instanceof InstanceOfExpr) {
right = resolver.BOOLEAN;
} else if (r instanceof InvokeExpr) {
InvokeExpr ie = (InvokeExpr) r;
handleInvokeExpr(ie);
if (ie.getMethodRef().returnType() instanceof IntegerType) {
right = resolver.typeVariable(ie.getMethodRef().returnType());
}
} else if (r instanceof NewArrayExpr) {
NewArrayExpr nae = (NewArrayExpr) r;
if (uses) {
Value size = nae.getSize();
if (size instanceof Local) {
TypeVariable var = resolver.typeVariable((Local) size);
var.addParent(resolver.INT);
}
}
} else if (r instanceof NewExpr) {
} else if (r instanceof NewMultiArrayExpr) {
NewMultiArrayExpr nmae = (NewMultiArrayExpr) r;
if (uses) {
for (int i = 0; i < nmae.getSizeCount(); i++) {
Value size = nmae.getSize(i);
if (size instanceof Local) {
TypeVariable var = resolver.typeVariable((Local) size);
var.addParent(resolver.INT);
}
}
}
} else if (r instanceof LengthExpr) {
right = resolver.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) {
if (uses) {
resolver.typeVariable(local).addParent(resolver.INT);
}
TypeVariable v = resolver.typeVariable();
v.addChild(resolver.BYTE);
v.addChild(resolver.typeVariable(local));
right = v;
}
} else if (ne.getOp() instanceof DoubleConstant) {
} else if (ne.getOp() instanceof FloatConstant) {
} else if (ne.getOp() instanceof IntConstant) {
int value = ((IntConstant) ne.getOp()).value;
if (value < -32768) {
right = resolver.INT;
} else if (value < -128) {
right = resolver.SHORT;
} else if (value < 0) {
right = resolver.BYTE;
} else if (value < 2) {
right = resolver.BYTE;
} else if (value < 128) {
right = resolver.BYTE;
} else if (value < 32768) {
right = resolver.SHORT;
} else if (value < 65536) {
right = resolver.INT;
} else {
right = resolver.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 = resolver.typeVariable(local);
}
} else if (r instanceof InstanceFieldRef) {
InstanceFieldRef ref = (InstanceFieldRef) r;
if (ref.getFieldRef().type() instanceof IntegerType) {
right = resolver.typeVariable(ref.getFieldRef().type());
}
} else if (r instanceof StaticFieldRef) {
StaticFieldRef ref = (StaticFieldRef) r;
if (ref.getFieldRef().type() instanceof IntegerType) {
right = resolver.typeVariable(ref.getFieldRef().type());
}
} else {
throw new RuntimeException("Unhandled assignment right hand side type: " + r.getClass());
}
if (left != null && right != null && (left.type() == null || right.type() == null)) {
right.addParent(left);
}
}
Aggregations