use of soot.jimple.Constant in project soot by Sable.
the class StmtVisitor method buildMonitorInsn.
private Insn buildMonitorInsn(MonitorStmt stmt, Opcode opc) {
Value lockValue = stmt.getOp();
constantV.setOrigStmt(stmt);
// When leaving a monitor, we must make sure to re-use the old
// register. If we assign the same class constant to a new register
// before leaving the monitor, Android's bytecode verifier will assume
// that this constant assignment can throw an exception, leaving us
// with a dangling monitor. Imprecise static analyzers ftw.
Register lockReg = null;
if (lockValue instanceof Constant)
if ((lockReg = monitorRegs.get(lockValue)) != null)
lockReg = lockReg.clone();
if (lockReg == null) {
lockReg = regAlloc.asImmediate(lockValue, constantV);
regAlloc.lockRegister(lockReg);
if (lockValue instanceof Constant) {
monitorRegs.put((Constant) lockValue, lockReg);
regAlloc.lockRegister(lockReg);
}
}
return new Insn11x(opc, lockReg);
}
use of soot.jimple.Constant in project soot by Sable.
the class StmtVisitor method caseAssignStmt.
@Override
public void caseAssignStmt(AssignStmt stmt) {
// If this is the beginning of an array initialization, we shortcut the
// normal translation process
List<Value> arrayValues = arrayInitDetector.getValuesForArrayInit(stmt);
if (arrayValues != null) {
Insn insn = buildArrayFillInsn((ArrayRef) stmt.getLeftOp(), arrayValues);
if (insn != null) {
addInsn(insn, stmt);
return;
}
}
if (arrayInitDetector.getIgnoreUnits().contains(stmt)) {
return;
}
constantV.setOrigStmt(stmt);
exprV.setOrigStmt(stmt);
Value lhs = stmt.getLeftOp();
if (lhs instanceof ConcreteRef) {
// special cases that lead to *put* opcodes
Value source = stmt.getRightOp();
addInsn(buildPutInsn((ConcreteRef) lhs, source), stmt);
return;
}
// other cases, where lhs is a local
if (!(lhs instanceof Local)) {
throw new Error("left-hand side of AssignStmt is not a Local: " + lhs.getClass());
}
Local lhsLocal = (Local) lhs;
final Insn newInsn;
Register lhsReg = regAlloc.asLocal(lhsLocal);
Value rhs = stmt.getRightOp();
if (rhs instanceof Local) {
// move rhs local to lhs local, if different
Local rhsLocal = (Local) rhs;
if (lhsLocal == rhsLocal) {
return;
}
Register sourceReg = regAlloc.asLocal(rhsLocal);
newInsn = buildMoveInsn(lhsReg, sourceReg);
addInsn(newInsn, stmt);
} else if (rhs instanceof Constant) {
// move rhs constant into the lhs local
constantV.setDestination(lhsReg);
rhs.apply(constantV);
newInsn = insns.get(insns.size() - 1);
} else if (rhs instanceof ConcreteRef) {
newInsn = buildGetInsn((ConcreteRef) rhs, lhsReg);
addInsn(newInsn, stmt);
} else {
// evaluate rhs expression, saving the result in the lhs local
exprV.setDestinationReg(lhsReg);
rhs.apply(exprV);
if (rhs instanceof InvokeExpr) {
// do the actual "assignment" for an invocation: move its result
// to the lhs reg (it was not used yet)
Insn moveResultInsn = buildMoveResultInsn(lhsReg);
int invokeInsnIndex = exprV.getLastInvokeInstructionPosition();
insns.add(invokeInsnIndex + 1, moveResultInsn);
}
newInsn = insns.get(insns.size() - 1);
}
this.insnRegisterMap.put(newInsn, LocalRegisterAssignmentInformation.v(lhsReg, lhsLocal));
}
use of soot.jimple.Constant in project soot by Sable.
the class ConstantInitializerToTagTransformer method transformClass.
/**
* Transforms the given class, i.e. scans for a <clinit> method and
* generates new constant value tags for all constant assignments to static
* final fields.
*
* @param sc
* The class to transform
* @param removeAssignments
* True if the assignments inside the <clinit> method shall be
* removed, otherwise false
*/
public void transformClass(SootClass sc, boolean removeAssignments) {
// If this class has no <clinit> method, we're done
SootMethod smInit = sc.getMethodByNameUnsafe("<clinit>");
if (smInit == null || !smInit.isConcrete())
return;
Set<SootField> nonConstantFields = new HashSet<SootField>();
Map<SootField, ConstantValueTag> newTags = new HashMap<SootField, ConstantValueTag>();
// in case of
Set<SootField> removeTagList = new HashSet<SootField>();
for (Iterator<Unit> itU = smInit.getActiveBody().getUnits().snapshotIterator(); itU.hasNext(); ) {
Unit u = itU.next();
if (u instanceof AssignStmt) {
AssignStmt assign = (AssignStmt) u;
if (assign.getLeftOp() instanceof StaticFieldRef && assign.getRightOp() instanceof Constant) {
SootField field = null;
try {
field = ((StaticFieldRef) assign.getLeftOp()).getField();
if (field == null || nonConstantFields.contains(field))
continue;
} catch (ConflictingFieldRefException ex) {
// Ignore this statement
continue;
}
if (field.getDeclaringClass().equals(sc) && field.isStatic() && field.isFinal()) {
// Do we already have a constant value for this field?
boolean found = false;
for (Tag t : field.getTags()) {
if (t instanceof ConstantValueTag) {
if (checkConstantValue((ConstantValueTag) t, (Constant) assign.getRightOp())) {
// the assignment.
if (removeAssignments)
itU.remove();
} else {
logger.debug("" + "WARNING: Constant value for field '" + field + "' mismatch between code (" + assign.getRightOp() + ") and constant table (" + t + ")");
removeTagList.add(field);
}
found = true;
break;
}
}
if (!found) {
// tags.
if (!checkConstantValue(newTags.get(field), (Constant) assign.getRightOp())) {
nonConstantFields.add(field);
newTags.remove(field);
removeTagList.add(field);
continue;
}
ConstantValueTag newTag = createConstantTagFromValue((Constant) assign.getRightOp());
if (newTag != null)
newTags.put(field, newTag);
}
}
} else if (assign.getLeftOp() instanceof StaticFieldRef) {
// a non-constant is assigned to the field
try {
SootField sf = ((StaticFieldRef) assign.getLeftOp()).getField();
if (sf != null)
removeTagList.add(sf);
} catch (ConflictingFieldRefException ex) {
// let's assume that a broken field doesn't cause any
// harm
}
}
}
}
// Do the actual assignment
for (Entry<SootField, ConstantValueTag> entry : newTags.entrySet()) {
SootField field = entry.getKey();
if (removeTagList.contains(field))
continue;
field.addTag(entry.getValue());
}
if (removeAssignments && !newTags.isEmpty())
for (Iterator<Unit> itU = smInit.getActiveBody().getUnits().snapshotIterator(); itU.hasNext(); ) {
Unit u = itU.next();
if (u instanceof AssignStmt) {
AssignStmt assign = (AssignStmt) u;
if (assign.getLeftOp() instanceof FieldRef)
try {
SootField fld = ((FieldRef) assign.getLeftOp()).getField();
if (fld != null && newTags.containsKey(fld))
itU.remove();
} catch (ConflictingFieldRefException ex) {
// Ignore broken code
}
}
}
// remove constant tags
for (SootField sf : removeTagList) {
if (removeTagList.contains(sf)) {
List<Tag> toRemoveTagList = new ArrayList<Tag>();
for (Tag t : sf.getTags()) {
if (t instanceof ConstantValueTag) {
toRemoveTagList.add(t);
}
}
for (Tag t : toRemoveTagList) {
sf.getTags().remove(t);
}
}
}
}
use of soot.jimple.Constant in project soot by Sable.
the class AsmMethodSource method popImmediate.
private Operand popImmediate(Operand o) {
Value v = o.value;
Local l = o.stack;
if (l == null && !(v instanceof Local) && !(v instanceof Constant)) {
l = o.stack = newStackLocal();
setUnit(o.insn, Jimple.v().newAssignStmt(l, v));
o.updateBoxes();
}
return o;
}
use of soot.jimple.Constant 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