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

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

/* 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.integer;

import soot.*;
import soot.jimple.*;

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();
	int count = invoke.getArgCount();
	
	for(int i = 0; i < count; i++)
	  {
	    if(invoke.getArg(i) instanceof Local)
	      {
		Local local = (Local) invoke.getArg(i);
		
		if(local.getType() instanceof IntegerType)
		  {
		    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();
	int count = invoke.getArgCount();
	
	for(int i = 0; i < count; i++)
	  {
	    if(invoke.getArg(i) instanceof Local)
	      {
		Local local = (Local) invoke.getArg(i);
		
		if(local.getType() instanceof IntegerType)
		  {
		    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();
	int count = invoke.getArgCount();
	
	for(int i = 0; i < count; i++)
	  {
	    if(invoke.getArg(i) instanceof Local)
	      {
		Local local = (Local) invoke.getArg(i);
		
		if(local.getType() instanceof IntegerType)
		  {
		    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);
		
		if(local.getType() instanceof IntegerType)
		  {
		    TypeVariable localType = resolver.typeVariable(local);
		    
		    localType.addParent(resolver.typeVariable(method.parameterType(i)));
		  }
	      }
	  }
      }
    else if(ie instanceof DynamicInvokeExpr)
    {  // RoboVM note: Added support for DynamicInvokeExpr
        DynamicInvokeExpr invoke = (DynamicInvokeExpr) 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);
              
              if(local.getType() instanceof IntegerType)
                {
                  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;
	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.getField().getType();
	    
	    if(fieldType instanceof IntegerType)
	      {
		left = resolver.typeVariable(ref.getField().getType());
	      }
	  }
      }
    else if(l instanceof StaticFieldRef)
      {
	if(uses)
	  {
	    StaticFieldRef ref = (StaticFieldRef) l;
	    
	    Type fieldType = ref.getField().getType();
	    
	    if(fieldType instanceof IntegerType)
	      {
		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;
	Type baset = ((Local) ref.getBase()).getType();
	if(!(baset instanceof NullType))
	{
	  ArrayType base = (ArrayType) baset;
	  Value index = ref.getIndex();
	
	  if((base.numDimensions == 1) &&
	     (base.baseType instanceof IntegerType))
	    {
	      right = resolver.typeVariable(base.baseType);
	    }
	
	  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();
		rop.addParent(common);
		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();
		rop.addParent(common);
		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.getField().getType() instanceof IntegerType)
	  {
	    right = resolver.typeVariable(ref.getField().getType());
	  }
      }
    else if(r instanceof StaticFieldRef)
      {
	StaticFieldRef ref = (StaticFieldRef) r;

	if(ref.getField().getType() instanceof IntegerType)
	  {
	    right = resolver.typeVariable(ref.getField().getType());
	  }
      }
    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);
      }
  }

  public void caseIdentityStmt(IdentityStmt stmt)
  {
    Value l = stmt.getLeftOp();
    Value r = stmt.getRightOp();

    if(l instanceof Local)
      {
	if(((Local) l).getType() instanceof IntegerType)
	  {
	    TypeVariable left = resolver.typeVariable((Local) l);
	    
	    TypeVariable right = resolver.typeVariable(r.getType());
	    right.addParent(left);
	  }
      }
  }

  public void caseEnterMonitorStmt(EnterMonitorStmt stmt)
  {
  }

  public void caseExitMonitorStmt(ExitMonitorStmt stmt)
  {
  }

  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 = 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(rop != null && lop != null)
	  {
	    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.INT);
	  }
      }
  }

  public void caseNopStmt(NopStmt stmt)
  {
  }

  public void caseReturnStmt(ReturnStmt stmt)
  {
    if(uses)
      {
	if(stmt.getOp() instanceof Local)
	  {
	    if(((Local) stmt.getOp()).getType() instanceof IntegerType)
	      {
		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.INT);
	  }
      }
  }

  public void caseThrowStmt(ThrowStmt stmt)
  {
  }

  public void defaultCase(Stmt stmt)
  {
    throw new RuntimeException("Unhandled statement type: " + stmt.getClass());
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy