soot.jimple.toolkits.typing.ConstraintCollector Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of robovm-soot Show documentation
Show all versions of robovm-soot Show documentation
RoboVM fork of Soot - A Java optimization framework
/* Soot - a J*va Optimization Framework
* Copyright (C) 1997-2000 Etienne Gagnon. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
/*
* Modified by the Sable Research Group and others 1997-1999.
* See the 'credits' file distributed with Soot for the complete list of
* contributors. (Soot is distributed at http://www.sable.mcgill.ca/soot)
*/
package soot.jimple.toolkits.typing;
import soot.*;
import soot.jimple.*;
import java.util.*;
class ConstraintCollector extends AbstractStmtSwitch
{
private TypeResolver resolver;
private boolean uses; // if true, include use contraints
private JimpleBody stmtBody;
public ConstraintCollector(TypeResolver resolver, boolean uses)
{
this.resolver = resolver;
this.uses = uses;
}
public void collect(Stmt stmt, JimpleBody stmtBody)
{
this.stmtBody = stmtBody;
stmt.apply(this);
}
private void handleInvokeExpr(InvokeExpr ie)
{
if(!uses)
return;
if(ie instanceof InterfaceInvokeExpr)
{
InterfaceInvokeExpr invoke = (InterfaceInvokeExpr) ie;
SootMethodRef method = invoke.getMethodRef();
Value base = invoke.getBase();
if(base instanceof Local)
{
Local local = (Local) base;
TypeVariable localType = resolver.typeVariable(local);
localType.addParent(resolver.typeVariable(method.declaringClass()));
}
int count = invoke.getArgCount();
for(int i = 0; i < count; i++)
{
if(invoke.getArg(i) instanceof Local)
{
Local local = (Local) invoke.getArg(i);
TypeVariable localType = resolver.typeVariable(local);
localType.addParent(resolver.typeVariable(method.parameterType(i)));
}
}
}
else if(ie instanceof SpecialInvokeExpr)
{
SpecialInvokeExpr invoke = (SpecialInvokeExpr) ie;
SootMethodRef method = invoke.getMethodRef();
Value base = invoke.getBase();
if(base instanceof Local)
{
Local local = (Local) base;
TypeVariable localType = resolver.typeVariable(local);
localType.addParent(resolver.typeVariable(method.declaringClass()));
}
int count = invoke.getArgCount();
for(int i = 0; i < count; i++)
{
if(invoke.getArg(i) instanceof Local)
{
Local local = (Local) invoke.getArg(i);
TypeVariable localType = resolver.typeVariable(local);
localType.addParent(resolver.typeVariable(method.parameterType(i)));
}
}
}
else if(ie instanceof VirtualInvokeExpr)
{
VirtualInvokeExpr invoke = (VirtualInvokeExpr) ie;
SootMethodRef method = invoke.getMethodRef();
Value base = invoke.getBase();
if(base instanceof Local)
{
Local local = (Local) base;
TypeVariable localType = resolver.typeVariable(local);
localType.addParent(resolver.typeVariable(method.declaringClass()));
}
int count = invoke.getArgCount();
for(int i = 0; i < count; i++)
{
if(invoke.getArg(i) instanceof Local)
{
Local local = (Local) invoke.getArg(i);
TypeVariable localType = resolver.typeVariable(local);
localType.addParent(resolver.typeVariable(method.parameterType(i)));
}
}
}
else if(ie instanceof StaticInvokeExpr)
{
StaticInvokeExpr invoke = (StaticInvokeExpr) ie;
SootMethodRef method = invoke.getMethodRef();
int count = invoke.getArgCount();
for(int i = 0; i < count; i++)
{
if(invoke.getArg(i) instanceof Local)
{
Local local = (Local) invoke.getArg(i);
TypeVariable localType = resolver.typeVariable(local);
localType.addParent(resolver.typeVariable(method.parameterType(i)));
}
}
}
else
{
throw new RuntimeException("Unhandled invoke expression type: " + ie.getClass());
}
}
public void caseBreakpointStmt(BreakpointStmt stmt)
{
// Do nothing
}
public void caseInvokeStmt(InvokeStmt stmt)
{
handleInvokeExpr(stmt.getInvokeExpr());
}
public void caseAssignStmt(AssignStmt stmt)
{
Value l = stmt.getLeftOp();
Value r = stmt.getRightOp();
TypeVariable left = null;
TypeVariable right = null;
//******** LEFT ********
if(l instanceof ArrayRef)
{
ArrayRef ref = (ArrayRef) l;
Value base = ref.getBase();
Value index = ref.getIndex();
TypeVariable baseType = resolver.typeVariable((Local) base);
baseType.makeElement();
left = baseType.element();
if(index instanceof Local)
{
if(uses)
{
resolver.typeVariable((Local) index).addParent(resolver.typeVariable(IntType.v()));
}
}
}
else if(l instanceof Local)
{
left = resolver.typeVariable((Local) l);
}
else if(l instanceof InstanceFieldRef)
{
InstanceFieldRef ref = (InstanceFieldRef) l;
if(uses)
{
TypeVariable baseType = resolver.typeVariable((Local) ref.getBase());
baseType.addParent(resolver.typeVariable(ref.getField().getDeclaringClass()));
left = resolver.typeVariable(ref.getField().getType());
}
}
else if(l instanceof StaticFieldRef)
{
if(uses)
{
StaticFieldRef ref = (StaticFieldRef) l;
left = resolver.typeVariable(ref.getField().getType());
}
}
else
{
throw new RuntimeException("Unhandled assignment left hand side type: " + l.getClass());
}
//******** RIGHT ********
if(r instanceof ArrayRef)
{
ArrayRef ref = (ArrayRef) r;
Value base = ref.getBase();
Value index = ref.getIndex();
TypeVariable baseType = resolver.typeVariable((Local) base);
baseType.makeElement();
right = baseType.element();
if(index instanceof Local)
{
if(uses)
{
resolver.typeVariable((Local) index).addParent(resolver.typeVariable(IntType.v()));
}
}
}
else if(r instanceof DoubleConstant)
{
right = resolver.typeVariable(DoubleType.v());
}
else if(r instanceof FloatConstant)
{
right = resolver.typeVariable(FloatType.v());
}
else if(r instanceof IntConstant)
{
right = resolver.typeVariable(IntType.v());
}
else if(r instanceof LongConstant)
{
right = resolver.typeVariable(LongType.v());
}
else if(r instanceof NullConstant)
{
right = resolver.typeVariable(NullType.v());
}
else if(r instanceof StringConstant)
{
right = resolver.typeVariable(RefType.v("java.lang.String"));
}
else if(r instanceof ClassConstant)
{
right = resolver.typeVariable(RefType.v("java.lang.Class"));
}
else if(r instanceof BinopExpr)
{
//******** BINOP EXPR ********
BinopExpr be = (BinopExpr) r;
Value lv = be.getOp1();
Value rv = be.getOp2();
TypeVariable lop;
TypeVariable rop;
//******** LEFT ********
if(lv instanceof Local)
{
lop = resolver.typeVariable((Local) lv);
}
else if(lv instanceof DoubleConstant)
{
lop = resolver.typeVariable(DoubleType.v());
}
else if(lv instanceof FloatConstant)
{
lop = resolver.typeVariable(FloatType.v());
}
else if(lv instanceof IntConstant)
{
lop = resolver.typeVariable(IntType.v());
}
else if(lv instanceof LongConstant)
{
lop = resolver.typeVariable(LongType.v());
}
else if(lv instanceof NullConstant)
{
lop = resolver.typeVariable(NullType.v());
}
else if(lv instanceof StringConstant)
{
lop = resolver.typeVariable(RefType.v("java.lang.String"));
}
else if(lv instanceof ClassConstant)
{
lop = resolver.typeVariable(RefType.v("java.lang.Class"));
}
else
{
throw new RuntimeException("Unhandled binary expression left operand type: " + lv.getClass());
}
//******** RIGHT ********
if(rv instanceof Local)
{
rop = resolver.typeVariable((Local) rv);
}
else if(rv instanceof DoubleConstant)
{
rop = resolver.typeVariable(DoubleType.v());
}
else if(rv instanceof FloatConstant)
{
rop = resolver.typeVariable(FloatType.v());
}
else if(rv instanceof IntConstant)
{
rop = resolver.typeVariable(IntType.v());
}
else if(rv instanceof LongConstant)
{
rop = resolver.typeVariable(LongType.v());
}
else if(rv instanceof NullConstant)
{
rop = resolver.typeVariable(NullType.v());
}
else if(rv instanceof StringConstant)
{
rop = resolver.typeVariable(RefType.v("java.lang.String"));
}
else if(rv instanceof ClassConstant)
{
rop = resolver.typeVariable(RefType.v("java.lang.Class"));
}
else
{
throw new RuntimeException("Unhandled binary expression right operand type: " + rv.getClass());
}
if((be instanceof AddExpr) ||
(be instanceof SubExpr) ||
(be instanceof MulExpr) ||
(be instanceof DivExpr) ||
(be instanceof RemExpr) ||
(be instanceof AndExpr) ||
(be instanceof OrExpr) ||
(be instanceof XorExpr))
{
if(uses)
{
TypeVariable common = resolver.typeVariable();
rop.addParent(common);
lop.addParent(common);
}
if(left != null)
{
rop.addParent(left);
lop.addParent(left);
}
}
else if((be instanceof ShlExpr) ||
(be instanceof ShrExpr) ||
(be instanceof UshrExpr))
{
if(uses)
{
rop.addParent(resolver.typeVariable(IntType.v()));
}
right = lop;
}
else if((be instanceof CmpExpr) ||
(be instanceof CmpgExpr) ||
(be instanceof CmplExpr) ||
(be instanceof EqExpr) ||
(be instanceof GeExpr) ||
(be instanceof GtExpr) ||
(be instanceof LeExpr) ||
(be instanceof LtExpr) ||
(be instanceof NeExpr))
{
if(uses)
{
TypeVariable common = resolver.typeVariable();
rop.addParent(common);
lop.addParent(common);
}
right = resolver.typeVariable(IntType.v());
}
else
{
throw new RuntimeException("Unhandled binary expression type: " + be.getClass());
}
}
else if(r instanceof CastExpr)
{
CastExpr ce = (CastExpr) r;
right = resolver.typeVariable(ce.getCastType());
}
else if(r instanceof InstanceOfExpr)
{
right = resolver.typeVariable(IntType.v());
}
else if(r instanceof InvokeExpr)
{
InvokeExpr ie = (InvokeExpr) r;
handleInvokeExpr(ie);
right = resolver.typeVariable(ie.getMethodRef().returnType());
}
else if(r instanceof NewArrayExpr)
{
NewArrayExpr nae = (NewArrayExpr) r;
Type baseType = nae.getBaseType();
if(baseType instanceof ArrayType)
{
right = resolver.typeVariable(ArrayType.v(((ArrayType) baseType).baseType,
((ArrayType) baseType).numDimensions + 1));
}
else
{
right = resolver.typeVariable(ArrayType.v(baseType, 1));
}
if(uses)
{
Value size = nae.getSize();
if(size instanceof Local)
{
TypeVariable var = resolver.typeVariable((Local) size);
var.addParent(resolver.typeVariable(IntType.v()));
}
}
}
else if(r instanceof NewExpr)
{
NewExpr na = (NewExpr) r;
right = resolver.typeVariable(na.getBaseType());
}
else if(r instanceof NewMultiArrayExpr)
{
NewMultiArrayExpr nmae = (NewMultiArrayExpr) r;
right = resolver.typeVariable(nmae.getBaseType());
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.typeVariable(IntType.v()));
}
}
}
}
else if(r instanceof LengthExpr)
{
LengthExpr le = (LengthExpr) r;
if(uses)
{
if(le.getOp() instanceof Local)
{
resolver.typeVariable((Local) le.getOp()).makeElement();
}
}
right = resolver.typeVariable(IntType.v());
}
else if(r instanceof NegExpr)
{
NegExpr ne = (NegExpr) r;
if(ne.getOp() instanceof Local)
{
right = resolver.typeVariable((Local) ne.getOp());
}
else if(ne.getOp() instanceof DoubleConstant)
{
right = resolver.typeVariable(DoubleType.v());
}
else if(ne.getOp() instanceof FloatConstant)
{
right = resolver.typeVariable(FloatType.v());
}
else if(ne.getOp() instanceof IntConstant)
{
right = resolver.typeVariable(IntType.v());
}
else if(ne.getOp() instanceof LongConstant)
{
right = resolver.typeVariable(LongType.v());
}
else
{
throw new RuntimeException("Unhandled neg expression operand type: " + ne.getOp().getClass());
}
}
else if(r instanceof Local)
{
right = resolver.typeVariable((Local) r);
}
else if(r instanceof InstanceFieldRef)
{
InstanceFieldRef ref = (InstanceFieldRef) r;
if(uses)
{
TypeVariable baseType = resolver.typeVariable((Local) ref.getBase());
baseType.addParent(resolver.typeVariable(ref.getField().getDeclaringClass()));
}
right = resolver.typeVariable(ref.getField().getType());
}
else if(r instanceof StaticFieldRef)
{
StaticFieldRef ref = (StaticFieldRef) r;
right = resolver.typeVariable(ref.getField().getType());
}
else
{
throw new RuntimeException("Unhandled assignment right hand side type: " + r.getClass());
}
if(left != null && right != null)
{
right.addParent(left);
}
}
public void caseIdentityStmt(IdentityStmt stmt)
{
Value l = stmt.getLeftOp();
Value r = stmt.getRightOp();
if(l instanceof Local)
{
TypeVariable left = resolver.typeVariable((Local) l);
if(!(r instanceof CaughtExceptionRef))
{
TypeVariable right = resolver.typeVariable(r.getType());
right.addParent(left);
}
else
{
List exceptionTypes = TrapManager.getExceptionTypesOf(stmt, stmtBody);
Iterator typeIt = exceptionTypes.iterator();
while(typeIt.hasNext())
{
Type t = (Type) typeIt.next();
resolver.typeVariable(t).addParent(left);
}
if(uses)
{
left.addParent(resolver.typeVariable(RefType.v("java.lang.Throwable")));
}
}
}
}
public void caseEnterMonitorStmt(EnterMonitorStmt stmt)
{
if(uses)
{
if(stmt.getOp() instanceof Local)
{
TypeVariable op = resolver.typeVariable((Local) stmt.getOp());
op.addParent(resolver.typeVariable(RefType.v("java.lang.Object")));
}
}
}
public void caseExitMonitorStmt(ExitMonitorStmt stmt)
{
if(uses)
{
if(stmt.getOp() instanceof Local)
{
TypeVariable op = resolver.typeVariable((Local) stmt.getOp());
op.addParent(resolver.typeVariable(RefType.v("java.lang.Object")));
}
}
}
public void caseGotoStmt(GotoStmt stmt)
{
}
public void caseIfStmt(IfStmt stmt)
{
if(uses)
{
ConditionExpr cond = (ConditionExpr) stmt.getCondition();
BinopExpr expr = cond;
Value lv = expr.getOp1();
Value rv = expr.getOp2();
TypeVariable lop;
TypeVariable rop;
//******** LEFT ********
if(lv instanceof Local)
{
lop = resolver.typeVariable((Local) lv);
}
else if(lv instanceof DoubleConstant)
{
lop = resolver.typeVariable(DoubleType.v());
}
else if(lv instanceof FloatConstant)
{
lop = resolver.typeVariable(FloatType.v());
}
else if(lv instanceof IntConstant)
{
lop = resolver.typeVariable(IntType.v());
}
else if(lv instanceof LongConstant)
{
lop = resolver.typeVariable(LongType.v());
}
else if(lv instanceof NullConstant)
{
lop = resolver.typeVariable(NullType.v());
}
else if(lv instanceof StringConstant)
{
lop = resolver.typeVariable(RefType.v("java.lang.String"));
}
else if(lv instanceof ClassConstant)
{
lop = resolver.typeVariable(RefType.v("java.lang.Class"));
}
else
{
throw new RuntimeException("Unhandled binary expression left operand type: " + lv.getClass());
}
//******** RIGHT ********
if(rv instanceof Local)
{
rop = resolver.typeVariable((Local) rv);
}
else if(rv instanceof DoubleConstant)
{
rop = resolver.typeVariable(DoubleType.v());
}
else if(rv instanceof FloatConstant)
{
rop = resolver.typeVariable(FloatType.v());
}
else if(rv instanceof IntConstant)
{
rop = resolver.typeVariable(IntType.v());
}
else if(rv instanceof LongConstant)
{
rop = resolver.typeVariable(LongType.v());
}
else if(rv instanceof NullConstant)
{
rop = resolver.typeVariable(NullType.v());
}
else if(rv instanceof StringConstant)
{
rop = resolver.typeVariable(RefType.v("java.lang.String"));
}
else if(rv instanceof ClassConstant)
{
rop = resolver.typeVariable(RefType.v("java.lang.Class"));
}
else
{
throw new RuntimeException("Unhandled binary expression right operand type: " + rv.getClass());
}
TypeVariable common = resolver.typeVariable();
rop.addParent(common);
lop.addParent(common);
}
}
public void caseLookupSwitchStmt(LookupSwitchStmt stmt)
{
if(uses)
{
Value key = stmt.getKey();
if(key instanceof Local)
{
resolver.typeVariable((Local) key).addParent(resolver.typeVariable(IntType.v()));
}
}
}
public void caseNopStmt(NopStmt stmt)
{
}
public void caseReturnStmt(ReturnStmt stmt)
{
if(uses)
{
if(stmt.getOp() instanceof Local)
{
resolver.typeVariable((Local) stmt.getOp()).
addParent(resolver.typeVariable(stmtBody.getMethod().getReturnType()));
}
}
}
public void caseReturnVoidStmt(ReturnVoidStmt stmt)
{
}
public void caseTableSwitchStmt(TableSwitchStmt stmt)
{
if(uses)
{
Value key = stmt.getKey();
if(key instanceof Local)
{
resolver.typeVariable((Local) key).addParent(resolver.typeVariable(IntType.v()));
}
}
}
public void caseThrowStmt(ThrowStmt stmt)
{
if(uses)
{
if(stmt.getOp() instanceof Local)
{
TypeVariable op = resolver.typeVariable((Local) stmt.getOp());
op.addParent(resolver.typeVariable(RefType.v("java.lang.Throwable")));
}
}
}
public void defaultCase(Stmt stmt)
{
throw new RuntimeException("Unhandled statement type: " + stmt.getClass());
}
}