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

soot.jimple.toolkits.typing.integer.ConstraintChecker 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.*;
import java.io.*;

class ConstraintChecker extends AbstractStmtSwitch
{
  private final TypeResolver resolver;
  private final boolean fix;  // if true, fix constraint violations
  
  private JimpleBody stmtBody;

  public ConstraintChecker(TypeResolver resolver, boolean fix)
  {
    this.resolver = resolver;
    this.fix = fix;
  }

  public void check(Stmt stmt, JimpleBody stmtBody) throws TypeException
  {
    try
      {
	this.stmtBody = stmtBody;
	stmt.apply(this);
      }
    catch(RuntimeTypeException e)
      {
         StringWriter st = new StringWriter();
         PrintWriter pw = new PrintWriter(st);
	 e.printStackTrace(pw);
	 pw.close();
         throw new TypeException(st.toString());
      }
  }

  private static class RuntimeTypeException extends RuntimeException
  {
    RuntimeTypeException(String message)
    {
      super(message);
    }
  }

  static void error(String message)
  {
    throw new RuntimeTypeException(message);
  }

  private void handleInvokeExpr(InvokeExpr ie, Stmt invokestmt)
  {
    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)
		  {
		    if(!ClassHierarchy.v().typeNode(local.getType()).
		       hasAncestor_1(ClassHierarchy.v().typeNode(method.parameterType(i))))
		      {
			if(fix)
			  {
			    invoke.setArg(i, insertCast(local, method.parameterType(i), invokestmt));
			  }
			else
			  {
			    error("Type Error(1)");
			  }
		      }
		  }
	      }
	  }
      }
    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)
		  {
		    if(!ClassHierarchy.v().typeNode(local.getType()).
		       hasAncestor_1(ClassHierarchy.v().typeNode(method.parameterType(i))))
		      {
			if(fix)
			  {
			    invoke.setArg(i, insertCast(local, method.parameterType(i), invokestmt));
			  }
			else
			  {
			    error("Type Error(2)");
			  }
		      }
		  }
	      }
	  }
      }
    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)
		  {
		    if(!ClassHierarchy.v().typeNode(local.getType()).
		       hasAncestor_1(ClassHierarchy.v().typeNode(method.parameterType(i))))
		      {
			if(fix)
			  {
			    invoke.setArg(i, insertCast(local, method.parameterType(i), invokestmt));
			  }
			else
			  {
			    error("Type Error(3)");
			  }
		      }
		  }
	      }
	  }
      }
    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)
		  {
		    if(!ClassHierarchy.v().typeNode(local.getType()).
		       hasAncestor_1(ClassHierarchy.v().typeNode(method.parameterType(i))))
		      {
			if(fix)
			  {
			    invoke.setArg(i, insertCast(local, method.parameterType(i), invokestmt));
			  }
			else
			  {
			    error("Type Error(4)");
			  }
		      }
		  }
	      }
	  }
      }
    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)
                {
                  if(!ClassHierarchy.v().typeNode(local.getType()).
                     hasAncestor_1(ClassHierarchy.v().typeNode(method.parameterType(i))))
                    {
                      if(fix)
                        {
                          invoke.setArg(i, insertCast(local, method.parameterType(i), invokestmt));
                        }
                      else
                        {
                          error("Type Error(5)");
                        }
                    }
                }
            }
        }
    }
    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(), stmt);
  }

  public void caseAssignStmt(AssignStmt stmt)
  {
    Value l = stmt.getLeftOp();
    Value r = stmt.getRightOp();

    TypeNode left = null;
    TypeNode 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((base.numDimensions == 1) &&
	     (base.baseType instanceof IntegerType))
	    {
	      left = ClassHierarchy.v().typeNode(base.baseType);
	    }
	
	  if(index instanceof Local)
	    {
	      if(!ClassHierarchy.v().typeNode(((Local) index).getType()).hasAncestor_1(ClassHierarchy.v().INT))
	        {
		  if(fix)
		    {
		      ref.setIndex(insertCast((Local) index, IntType.v(), stmt));
		    }
		  else
		    {
		      error("Type Error(5)");
		    }
	        }
	    }
        }
      }
    else if(l instanceof Local)
      {
	if(((Local) l).getType() instanceof IntegerType)
	  {
	    left = ClassHierarchy.v().typeNode(((Local) l).getType());
	  }
      }
    else if(l instanceof InstanceFieldRef)
      {
	InstanceFieldRef ref = (InstanceFieldRef) l;
	
	if(ref.getField().getType() instanceof IntegerType)
	  {
	    left = ClassHierarchy.v().typeNode( ref.getField().getType());
	  }
      }
    else if(l instanceof StaticFieldRef)
      {
	StaticFieldRef ref = (StaticFieldRef) l;

	if(ref.getField().getType() instanceof IntegerType)
	  {
	    left = ClassHierarchy.v().typeNode(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 = ClassHierarchy.v().typeNode(base.baseType);
	    }
	
	  if(index instanceof Local)
	    {
	      if(!ClassHierarchy.v().typeNode(((Local) index).getType()).hasAncestor_1(ClassHierarchy.v().INT))
	        {
		  if(fix)
		    {
		      ref.setIndex(insertCast((Local) index, IntType.v(), stmt));
		    }
		  else
		    {
		      error("Type Error(6)");
		    }
	        }
	    }
	}
      }
    else if(r instanceof DoubleConstant)
      {
      }
    else if(r instanceof FloatConstant)
      {
      }
    else if(r instanceof IntConstant)
      {
	int value  = ((IntConstant) r).value;
	
	if(value < -32768)
	  {
	    right = ClassHierarchy.v().INT;
	  }
	else if(value < -128)
	  {
	    right = ClassHierarchy.v().SHORT;
	  }
	else if(value < 0)
	  {
	    right = ClassHierarchy.v().BYTE;
	  }
	else if(value < 2)
	  {
	    right = ClassHierarchy.v().R0_1;
	  }
	else if(value < 128)
	  {
	    right = ClassHierarchy.v().R0_127;
	  }
	else if(value < 32768)
	  {
	    right = ClassHierarchy.v().R0_32767;
	  }
	else if(value < 65536)
	  {
	    right = ClassHierarchy.v().CHAR;
	  }
	else
	  {
	    right = ClassHierarchy.v().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();
	
	TypeNode lop = null;
	TypeNode rop = null;

	//******** LEFT ********
	if(lv instanceof Local)
	  {
	    if(((Local) lv).getType() instanceof IntegerType)
	      {
		lop = ClassHierarchy.v().typeNode(((Local) lv).getType());
	      }
	  }
	else if(lv instanceof DoubleConstant)
	  {
	  }
	else if(lv instanceof FloatConstant)
	  {
	  }
	else if(lv instanceof IntConstant)
	  {
	    int value  = ((IntConstant) lv).value;
	    
	    if(value < -32768)
	      {
		lop = ClassHierarchy.v().INT;
	      }
	    else if(value < -128)
	      {
		lop = ClassHierarchy.v().SHORT;
	      }
	    else if(value < 0)
	      {
		lop = ClassHierarchy.v().BYTE;
	      }
	    else if(value < 2)
	      {
		lop = ClassHierarchy.v().R0_1;
	      }
	    else if(value < 128)
	      {
		lop = ClassHierarchy.v().R0_127;
	      }
	    else if(value < 32768)
	      {
		lop = ClassHierarchy.v().R0_32767;
	      }
	    else if(value < 65536)
	      {
		lop = ClassHierarchy.v().CHAR;
	      }
	    else
	      {
		lop = ClassHierarchy.v().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 = ClassHierarchy.v().typeNode(((Local) rv).getType());
	      }
	  }
	else if(rv instanceof DoubleConstant)
	  {
	  }
	else if(rv instanceof FloatConstant)
	  {
	  }
	else if(rv instanceof IntConstant)
	  {
	    int value  = ((IntConstant) rv).value;
	    
	    if(value < -32768)
	      {
		rop = ClassHierarchy.v().INT;
	      }
	    else if(value < -128)
	      {
		rop = ClassHierarchy.v().SHORT;
	      }
	    else if(value < 0)
	      {
		rop = ClassHierarchy.v().BYTE;
	      }
	    else if(value < 2)
	      {
		rop = ClassHierarchy.v().R0_1;
	      }
	    else if(value < 128)
	      {
		rop = ClassHierarchy.v().R0_127;
	      }
	    else if(value < 32768)
	      {
		rop = ClassHierarchy.v().R0_32767;
	      }
	    else if(value < 65536)
	      {
		rop = ClassHierarchy.v().CHAR;
	      }
	    else
	      {
		rop = ClassHierarchy.v().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 MulExpr) ||
	   (be instanceof DivExpr) ||
	   (be instanceof RemExpr))
	  {
	    if(lop != null && rop != null)
	      {
		if(!lop.hasAncestor_1(ClassHierarchy.v().INT))
		  {
		    if(fix)
		      {
			be.setOp1(insertCast(be.getOp1(), getTypeForCast(lop), IntType.v(), stmt));
		      }
		    else
		      {
			error("Type Error(7)");
		      }
		  }

		if(!rop.hasAncestor_1(ClassHierarchy.v().INT))
		  {
		    if(fix)
		      {
			be.setOp2(insertCast(be.getOp2(), getTypeForCast(rop), IntType.v(), stmt));
		      }
		    else
		      {
			error("Type Error(8)");
		      }
		  }
	      }
	    
	    right = ClassHierarchy.v().INT;
	  }
	else if((be instanceof AndExpr) ||
		(be instanceof OrExpr) ||
		(be instanceof XorExpr))
	  {
	    if(lop != null && rop != null)
	      {
		TypeNode lca = lop.lca_1(rop);
		
		if(lca == ClassHierarchy.v().TOP)
		  {
		    if(fix)
		      {
			if(!lop.hasAncestor_1(ClassHierarchy.v().INT))
			  {
			    be.setOp1(insertCast(be.getOp1(), getTypeForCast(lop), getTypeForCast(rop), stmt));
			    lca = rop;
			  }
			
			if(!rop.hasAncestor_1(ClassHierarchy.v().INT))
			  {
			    be.setOp2(insertCast(be.getOp2(), getTypeForCast(rop), getTypeForCast(lop), stmt));
			    lca = lop;			
			  }
		      }
		    else
		      {
			error("Type Error(11)");
		      }
		  }
		
		right = lca;
	      }
	  }
	else if(be instanceof ShlExpr)
	  {
	    if(lop != null)
	      {
		if(!lop.hasAncestor_1(ClassHierarchy.v().INT))
		  {
		    if(fix)
		      {
			be.setOp1(insertCast(be.getOp1(), getTypeForCast(lop), IntType.v(), stmt));
		      }
		    else
		      {
			error("Type Error(9)");
		      }
		  }
	      }
		
	    if(!rop.hasAncestor_1(ClassHierarchy.v().INT))
	      {
		if(fix)
		  {
		    be.setOp2(insertCast(be.getOp2(), getTypeForCast(rop), IntType.v(), stmt));
		  }
		else
		  {
		    error("Type Error(10)");
		  }
	      }
	    
	    right = (lop == null) ? null : ClassHierarchy.v().INT;
	  }
	else if((be instanceof ShrExpr) ||
		(be instanceof UshrExpr))
	  {
	    if(lop != null)
	      {
		if(!lop.hasAncestor_1(ClassHierarchy.v().INT))
		  {
		    if(fix)
		      {
			be.setOp1(insertCast(be.getOp1(), getTypeForCast(lop), ByteType.v(), stmt));
			lop = ClassHierarchy.v().BYTE;
		      }
		    else
		      {
			error("Type Error(9)");
		      }
		  }
	      }
		
	    if(!rop.hasAncestor_1(ClassHierarchy.v().INT))
	      {
		if(fix)
		  {
		    be.setOp2(insertCast(be.getOp2(), getTypeForCast(rop), IntType.v(), stmt));
		  }
		else
		  {
		    error("Type Error(10)");
		  }
	      }

	    right = lop;
	  }
	else if((be instanceof CmpExpr) ||
		(be instanceof CmpgExpr) ||
		(be instanceof CmplExpr))
	  {
	    right = ClassHierarchy.v().BYTE;
	  }
	else if((be instanceof EqExpr) ||
		(be instanceof GeExpr) ||
		(be instanceof GtExpr) ||
		(be instanceof LeExpr) ||
		(be instanceof LtExpr) ||
		(be instanceof NeExpr))
	  {
	    TypeNode lca = lop.lca_1(rop);
	    
	    if(lca == ClassHierarchy.v().TOP)
	      {
		if(fix)
		  {
		    if(!lop.hasAncestor_1(ClassHierarchy.v().INT))
		      {
			be.setOp1(insertCast(be.getOp1(), getTypeForCast(lop), getTypeForCast(rop), stmt));
		      }
		    
		    if(!rop.hasAncestor_1(ClassHierarchy.v().INT))
		      {
			be.setOp2(insertCast(be.getOp2(), getTypeForCast(rop), getTypeForCast(lop), stmt));
		      }
		  }
		else
		  {
		    error("Type Error(11)");
		  }
	      }
	    
	    right = ClassHierarchy.v().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 = ClassHierarchy.v().typeNode(ce.getCastType());
	  }
      }
    else if(r instanceof InstanceOfExpr)
      {
	right = ClassHierarchy.v().BOOLEAN;
      }
    else if(r instanceof InvokeExpr)
      {
	InvokeExpr ie = (InvokeExpr) r;

	handleInvokeExpr(ie, stmt);
	
	if(ie.getMethodRef().returnType() instanceof IntegerType)
	  {
	    right = ClassHierarchy.v().typeNode(ie.getMethodRef().returnType());
	  }
      }
    else if(r instanceof NewArrayExpr)
      {
	NewArrayExpr nae = (NewArrayExpr) r;
	Value size = nae.getSize();

	if(size instanceof Local)
	  {
	    if(!ClassHierarchy.v().typeNode(((Local) size).getType()).
	       hasAncestor_1(ClassHierarchy.v().INT))
	      {
		if(fix)
		  {
		    nae.setSize(insertCast((Local) size, IntType.v(), stmt));
		  }
		else
		  {
		    error("Type Error(12)");
		  }
	      }
	  }
      }
    else if(r instanceof NewExpr)
      {
      }
    else if(r instanceof NewMultiArrayExpr)
      {
	NewMultiArrayExpr nmae = (NewMultiArrayExpr) r;

	for(int i = 0; i < nmae.getSizeCount(); i++)
	  {
	    Value size = nmae.getSize(i);

	    if(size instanceof Local)
	      {
		if(!ClassHierarchy.v().typeNode(((Local) size).getType()).
		   hasAncestor_1(ClassHierarchy.v().INT))
		  {
		    if(fix)
		      {
			nmae.setSize(i, insertCast((Local) size, IntType.v(), stmt));
		      }
		    else
		      {
			error("Type Error(13)");
		      }
		  }
	      }
	  }
      }
    else if(r instanceof LengthExpr)
      {
	right = ClassHierarchy.v().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)
	      {
		TypeNode ltype = ClassHierarchy.v().typeNode(local.getType());
		if(!ltype.hasAncestor_1(ClassHierarchy.v().INT))
		  {
		    if(fix)
		      {
			ne.setOp(insertCast(local, IntType.v(), stmt));
			ltype = ClassHierarchy.v().BYTE;
		      }
		    else
		      {
			error("Type Error(14)");
		      }
		  }

		right = (ltype == ClassHierarchy.v().CHAR) ? ClassHierarchy.v().INT : ltype;
	      }
	  }
	else if(ne.getOp() instanceof DoubleConstant)
	  {
	  }
	else if(ne.getOp() instanceof FloatConstant)
	  {
	  }
	else if(ne.getOp() instanceof IntConstant)
	  {
	    right = ClassHierarchy.v().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 = ClassHierarchy.v().typeNode(local.getType());
	  }
      }
    else if(r instanceof InstanceFieldRef)
      {
	InstanceFieldRef ref = (InstanceFieldRef) r;

	if(ref.getField().getType() instanceof IntegerType)
	  {
	    right = ClassHierarchy.v().typeNode(ref.getField().getType());
	  }
      }
    else if(r instanceof StaticFieldRef)
      {
	StaticFieldRef ref = (StaticFieldRef) r;

	if(ref.getField().getType() instanceof IntegerType)
	  {
	    right = ClassHierarchy.v().typeNode(ref.getField().getType());
	  }
      }
    else
      {
	throw new RuntimeException("Unhandled assignment right hand side type: " + r.getClass());
      }

    if(left != null && right != null)
      {
	if(!right.hasAncestor_1(left))
	  {
	    if(fix)
	      {
		stmt.setRightOp(insertCast(stmt.getRightOp(), getTypeForCast(right), getTypeForCast(left), stmt));
	      }
	    else
	      {
		error("Type Error(15)");
	      }
	  }
      }
  }

  static Type getTypeForCast(TypeNode node)
      // This method is a local kludge, for avoiding NullPointerExceptions
      // when a R0_1, R0_127, or R0_32767 node is used in a type
      // cast. A more elegant solution would work with the TypeNode 
      // type definition itself, but that would require a more thorough
      // knowledge of the typing system than the kludger posesses.
  {
    if (node.type() == null) 
      {
	if (node == ClassHierarchy.v().R0_1) 
	  {
	    return BooleanType.v();
	  }
	else if (node == ClassHierarchy.v().R0_127) 
	  { 
	    return ByteType.v();
	  }
	else if (node == ClassHierarchy.v().R0_32767)
	  {
	    return ShortType.v();
	  }
	// Perhaps we should throw an exception here, since I don't think
	// there should be any other cases where node.type() is null. 
	// In case that supposition is incorrect, though, we'll just
	// go on to return the null, and let the callers worry about it.
      }
    return node.type();
  }

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

    if(l instanceof Local)
      {
	if(((Local) l).getType() instanceof IntegerType)
	  {
	    TypeNode left = ClassHierarchy.v().typeNode((((Local) l).getType()));
	    TypeNode right = ClassHierarchy.v().typeNode(r.getType());

	    if(!right.hasAncestor_1(left))
	      {
		if(fix)
		  {
		    ((soot.jimple.internal.JIdentityStmt) stmt).setLeftOp(insertCastAfter((Local) l, getTypeForCast(left), getTypeForCast(right), stmt));
		  }
		else
		  {
		    error("Type Error(16)");
		  }
	      }
	  }
      }
  }

  public void caseEnterMonitorStmt(EnterMonitorStmt stmt)
  {
  }

  public void caseExitMonitorStmt(ExitMonitorStmt stmt)
  {
  }

  public void caseGotoStmt(GotoStmt stmt)
  {
  }

  public void caseIfStmt(IfStmt stmt)
  {
    ConditionExpr cond = (ConditionExpr) stmt.getCondition();
    
    BinopExpr expr = cond;
    Value lv = expr.getOp1();
    Value rv = expr.getOp2();
    
    TypeNode lop = null;
    TypeNode rop = null;
    
    //******** LEFT ********
    if(lv instanceof Local)
      {
	if(((Local) lv).getType() instanceof IntegerType)
	  {
	    lop = ClassHierarchy.v().typeNode(((Local) lv).getType());
	  }
      }
    else if(lv instanceof DoubleConstant)
      {
      }
    else if(lv instanceof FloatConstant)
      {
      }
    else if(lv instanceof IntConstant)
      {
	int value  = ((IntConstant) lv).value;
	    
	if(value < -32768)
	  {
	    lop = ClassHierarchy.v().INT;
	  }
	else if(value < -128)
	  {
	    lop = ClassHierarchy.v().SHORT;
	  }
	else if(value < 0)
	  {
	    lop = ClassHierarchy.v().BYTE;
	  }
	else if(value < 2)
	  {
	    lop = ClassHierarchy.v().R0_1;
	  }
	else if(value < 128)
	  {
		lop = ClassHierarchy.v().R0_127;
	  }
	else if(value < 32768)
	  {
	    lop = ClassHierarchy.v().R0_32767;
	  }
	else if(value < 65536)
	  {
	    lop = ClassHierarchy.v().CHAR;
	  }
	else
	  {
	    lop = ClassHierarchy.v().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 = ClassHierarchy.v().typeNode(((Local) rv).getType());
	  }
      }
    else if(rv instanceof DoubleConstant)
      {
      }
    else if(rv instanceof FloatConstant)
      {
      }
    else if(rv instanceof IntConstant)
      {
	int value  = ((IntConstant) rv).value;
	
	if(value < -32768)
	  {
	    rop = ClassHierarchy.v().INT;
	  }
	else if(value < -128)
	  {
	    rop = ClassHierarchy.v().SHORT;
	  }
	else if(value < 0)
	  {
	    rop = ClassHierarchy.v().BYTE;
	  }
	else if(value < 2)
	  {
	    rop = ClassHierarchy.v().R0_1;
	  }
	else if(value < 128)
	  {
	    rop = ClassHierarchy.v().R0_127;
	  }
	else if(value < 32768)
	  {
	    rop = ClassHierarchy.v().R0_32767;
	  }
	else if(value < 65536)
	  {
	    rop = ClassHierarchy.v().CHAR;
	  }
	else
	  {
	    rop = ClassHierarchy.v().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(lop != null && rop != null)
      {
	if(lop.lca_1(rop) == ClassHierarchy.v().TOP)
	  {
	    if(fix)
	      {
		if(!lop.hasAncestor_1(ClassHierarchy.v().INT))
		  {
		    expr.setOp1(insertCast(expr.getOp1(), getTypeForCast(lop), getTypeForCast(rop), stmt));
		  }
		
		if(!rop.hasAncestor_1(ClassHierarchy.v().INT))
		  {
		    expr.setOp2(insertCast(expr.getOp2(), getTypeForCast(rop), getTypeForCast(lop), stmt));
		  }
	      }
	    else
	      {
		error("Type Error(17)");
	      }
	  }
      }
  }

  public void caseLookupSwitchStmt(LookupSwitchStmt stmt)
  {
    Value key = stmt.getKey();
    
    if(key instanceof Local)
      {
	if(!ClassHierarchy.v().typeNode(((Local) key).getType()).
	   hasAncestor_1(ClassHierarchy.v().INT))
	  {
	    if(fix)
	      {
		stmt.setKey(insertCast((Local) key, IntType.v(), stmt));
	      }
	    else
	      {
		error("Type Error(18)");
	      }
	  }
      }
  }

  public void caseNopStmt(NopStmt stmt)
  {
  }

  public void caseReturnStmt(ReturnStmt stmt)
  {
    if(stmt.getOp() instanceof Local)
      {
	if(((Local) stmt.getOp()).getType() instanceof IntegerType)
	  {
	    if(!ClassHierarchy.v().typeNode(((Local) stmt.getOp()).getType()).
	       hasAncestor_1(ClassHierarchy.v().typeNode(stmtBody.getMethod().getReturnType())))
	      {
		if(fix)
		  {
		    stmt.setOp(insertCast((Local) stmt.getOp(), stmtBody.getMethod().getReturnType(), stmt));
		  }
		else
		  {
		    error("Type Error(19)");
		  }
	      }
	  }
      }
  }

  public void caseReturnVoidStmt(ReturnVoidStmt stmt)
  {
  }

  public void caseTableSwitchStmt(TableSwitchStmt stmt)
  {
    Value key = stmt.getKey();
    
    if(key instanceof Local)
      {
	if(!ClassHierarchy.v().typeNode(((Local) key).getType()).
	   hasAncestor_1(ClassHierarchy.v().INT))
	  {
	    if(fix)
	      {
		stmt.setKey(insertCast((Local) key, IntType.v(), stmt));
	      }
	    else
	      {
		error("Type Error(20)");
	      }
	  }
	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());
  }

  private Local insertCast(Local oldlocal, Type type, Stmt stmt)
  {
    Local newlocal = Jimple.v().newLocal("tmp", type);
    stmtBody.getLocals().add(newlocal);
    
    stmtBody.getUnits().insertBefore(Jimple.v().newAssignStmt(newlocal, Jimple.v().newCastExpr(oldlocal, type)), stmt);
    return newlocal;
  }

  private Local insertCastAfter(Local leftlocal, Type lefttype, Type righttype, Stmt stmt)
  {
    Local newlocal = Jimple.v().newLocal("tmp", righttype);
    stmtBody.getLocals().add(newlocal);
    
    stmtBody.getUnits().insertAfter(Jimple.v().newAssignStmt(leftlocal, Jimple.v().newCastExpr(newlocal, lefttype)), stmt);
    return newlocal;
  }

  private Local insertCast(Value oldvalue, Type oldtype, Type type, Stmt stmt)
  {
    Local newlocal1 = Jimple.v().newLocal("tmp", oldtype);
    Local newlocal2 = Jimple.v().newLocal("tmp", type);
    stmtBody.getLocals().add(newlocal1);
    stmtBody.getLocals().add(newlocal2);
    
    stmtBody.getUnits().insertBefore(Jimple.v().newAssignStmt(newlocal1, oldvalue), stmt);
    stmtBody.getUnits().insertBefore(Jimple.v().newAssignStmt(newlocal2, Jimple.v().newCastExpr(newlocal1, type)), stmt);
    return newlocal2;
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy