All Downloads are FREE. Search and download functionalities are using the official Maven repository.

soot.jimple.toolkits.typing.ConstraintCollector Maven / Gradle / Ivy

There is a newer version: 2.5.0-9
Show newest version
/* 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());
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy