Package soot.jimple.spark.builder

Source Code of soot.jimple.spark.builder.MethodNodeFactory

/* Soot - a J*va Optimization Framework
* Copyright (C) 2002 Ondrej Lhotak
*
* 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.
*/

package soot.jimple.spark.builder;
import soot.jimple.spark.pag.*;
import soot.jimple.*;
import soot.*;
import soot.toolkits.scalar.Pair;
import soot.shimple.*;

/** Class implementing builder parameters (this decides
* what kinds of nodes should be built for each kind of Soot value).
* @author Ondrej Lhotak
*/
public class MethodNodeFactory extends AbstractShimpleValueSwitch {
    public MethodNodeFactory( PAG pag, MethodPAG mpag ) {
  this.pag = pag;
  this.mpag = mpag;
        setCurrentMethod( mpag.getMethod() );
    }
    /** Sets the method for which a graph is currently being built. */
    private void setCurrentMethod( SootMethod m ) {
  method = m;
        if( !m.isStatic() ) {
            SootClass c = m.getDeclaringClass();
            if( c == null ) {
                throw new RuntimeException( "Method "+m+" has no declaring class" );
            }
            caseThis();
        }
        for( int i = 0; i < m.getParameterCount(); i++ ) {
            if( m.getParameterType(i) instanceof RefLikeType ) {
                caseParm( i );
            }
        }
        Type retType = m.getReturnType();
        if( retType instanceof RefLikeType ) {
            caseRet();
        }
    }

    public Node getNode( Value v ) {
        v.apply( this );
        return getNode();
    }
    /** Adds the edges required for this statement to the graph. */
    final public void handleStmt( Stmt s ) {
  if( s.containsInvokeExpr() ) {
      return;
  }
  s.apply( new AbstractStmtSwitch() {
      final public void caseAssignStmt(AssignStmt as) {
                Value l = as.getLeftOp();
                Value r = as.getRightOp();
    if( !( l.getType() instanceof RefLikeType ) ) return;
    l.apply( MethodNodeFactory.this );
    Node dest = getNode();
    r.apply( MethodNodeFactory.this );
    Node src = getNode();
                if( l instanceof InstanceFieldRef ) {
                    ((InstanceFieldRef) l).getBase().apply( MethodNodeFactory.this );
                    pag.addDereference( (VarNode) getNode() );
                }
                if( r instanceof InstanceFieldRef ) {
                    ((InstanceFieldRef) r).getBase().apply( MethodNodeFactory.this );
                    pag.addDereference( (VarNode) getNode() );
                }
                if( r instanceof StaticFieldRef ) {
                  StaticFieldRef sfr = (StaticFieldRef) r;
          SootFieldRef s = sfr.getFieldRef();
                  if (pag.getOpts().empties_as_allocs()) {
                      if (s.declaringClass().getName().equals("java.util.Collections")) {
                                if (s.name().equals("EMPTY_SET")) {
                                    src = pag.makeAllocNode( RefType.v("java.util.HashSet"),
                                                                  RefType.v("java.util.HashSet"), method );
                                } else if (s.name().equals("EMPTY_MAP")) {
                                    src = pag.makeAllocNode( RefType.v("java.util.HashMap"),
                                                                  RefType.v("java.util.HashMap"), method );
                                } else if (s.name().equals("EMPTY_LIST")) {
                                    src = pag.makeAllocNode( RefType.v("java.util.LinkedList"),
                                                                  RefType.v("java.util.LinkedList"), method );
                                }
                        } else if (s.declaringClass().getName().equals("java.util.Hashtable")) {
                            if (s.name().equals("emptyIterator")) {
                                src = pag.makeAllocNode( RefType.v("java.util.Hashtable$EmptyIterator"),
                                                              RefType.v("java.util.Hashtable$EmptyIterator"), method );
                            } else if (s.name().equals("emptyEnumerator")) {
                                src = pag.makeAllocNode( RefType.v("java.util.Hashtable$EmptyEnumerator"),
                                        RefType.v("java.util.Hashtable$EmptyEnumerator"), method );
                            }
                        }
                  }
                }
    mpag.addInternalEdge( src, dest );
      }
      final public void caseReturnStmt(ReturnStmt rs) {
    if( !( rs.getOp().getType() instanceof RefLikeType ) ) return;
    rs.getOp().apply( MethodNodeFactory.this );
                Node retNode = getNode();
                mpag.addInternalEdge( retNode, caseRet() );
      }
      final public void caseIdentityStmt(IdentityStmt is) {
    if( !( is.getLeftOp().getType() instanceof RefLikeType ) ) return;
    is.getLeftOp().apply( MethodNodeFactory.this );
    Node dest = getNode();
    is.getRightOp().apply( MethodNodeFactory.this );
    Node src = getNode();
    mpag.addInternalEdge( src, dest );
      }
      final public void caseThrowStmt(ThrowStmt ts) {
    ts.getOp().apply( MethodNodeFactory.this );
    mpag.addOutEdge( getNode(), pag.nodeFactory().caseThrow() );
      }
  } );
    }
    final public Node getNode() {
  return (Node) getResult();
    }
    final public Node caseThis() {
  VarNode ret = pag.makeLocalVarNode(
        new Pair( method, PointsToAnalysis.THIS_NODE ),
        method.getDeclaringClass().getType(), method );
        ret.setInterProcTarget();
        return ret;
    }

    final public Node caseParm( int index ) {
        VarNode ret = pag.makeLocalVarNode(
                    new Pair( method, new Integer( index ) ),
                    method.getParameterType( index ), method );
        ret.setInterProcTarget();
        return ret;
    }

    final public void casePhiExpr(PhiExpr e) {
        Pair phiPair = new Pair( e, PointsToAnalysis.PHI_NODE );
        Node phiNode = pag.makeLocalVarNode( phiPair, e.getType(), method );
        for (Value op : e.getValues()) {
            op.apply( MethodNodeFactory.this );
            Node opNode = getNode();
            mpag.addInternalEdge( opNode, phiNode );
        }
        setResult( phiNode );
    }
   
    final public Node caseRet() {
        VarNode ret = pag.makeLocalVarNode(
                    Parm.v( method, PointsToAnalysis.RETURN_NODE ),
                    method.getReturnType(), method );
        ret.setInterProcSource();
        return ret;
    }
    final public Node caseArray( VarNode base ) {
  return pag.makeFieldRefNode( base, ArrayElement.v() );
    }
    /* End of public methods. */
    /* End of package methods. */

    // OK, these ones are public, but they really shouldn't be; it's just
    // that Java requires them to be, because they override those other
    // public methods.
    final public void caseArrayRef( ArrayRef ar ) {
      caseLocal( (Local) ar.getBase() );
  setResult( caseArray( (VarNode) getNode() ) );
    }
    final public void caseCastExpr( CastExpr ce ) {
  Pair castPair = new Pair( ce, PointsToAnalysis.CAST_NODE );
  ce.getOp().apply( this );
  Node opNode = getNode();
  Node castNode = pag.makeLocalVarNode( castPair, ce.getCastType(), method );
  mpag.addInternalEdge( opNode, castNode );
  setResult( castNode );
    }
    final public void caseCaughtExceptionRef( CaughtExceptionRef cer ) {
  setResult( pag.nodeFactory().caseThrow() );
    }
    final public void caseInstanceFieldRef( InstanceFieldRef ifr ) {
  if( pag.getOpts().field_based() || pag.getOpts().vta() ) {
      setResult( pag.makeGlobalVarNode(
      ifr.getField(),
      ifr.getField().getType() ) );
  } else {
      setResult( pag.makeLocalFieldRefNode(
      ifr.getBase(),
      ifr.getBase().getType(),
      ifr.getField(),
                        method ) );
  }
    }
    final public void caseLocal( Local l ) {
  setResult( pag.makeLocalVarNode( l,  l.getType(), method ) );
    }
    final public void caseNewArrayExpr( NewArrayExpr nae ) {
        setResult( pag.makeAllocNode( nae, nae.getType(), method ) );
    }
    private boolean isStringBuffer(Type t) {
        if(!(t instanceof RefType)) return false;
        RefType rt = (RefType) t;
        String s = rt.toString();
        if(s.equals("java.lang.StringBuffer")) return true;
        if(s.equals("java.lang.StringBuilder")) return true;
        return false;
    }
    final public void caseNewExpr( NewExpr ne ) {
        if( pag.getOpts().merge_stringbuffer()
        && isStringBuffer(ne.getType())) {
            setResult( pag.makeAllocNode( ne.getType(), ne.getType(), null ) );
        } else {
            setResult( pag.makeAllocNode( ne, ne.getType(), method ) );
        }
    }
    final public void caseNewMultiArrayExpr( NewMultiArrayExpr nmae ) {
        ArrayType type = (ArrayType) nmae.getType();
        AllocNode prevAn = pag.makeAllocNode(
            new Pair( nmae, new Integer( type.numDimensions ) ), type, method );
        VarNode prevVn = pag.makeLocalVarNode( prevAn, prevAn.getType(), method );
        mpag.addInternalEdge( prevAn, prevVn );
        setResult( prevAn );
        while( true ) {
            Type t = type.getElementType();
            if( !( t instanceof ArrayType ) ) break;
            type = (ArrayType) t;
            AllocNode an = pag.makeAllocNode(
                new Pair( nmae, new Integer( type.numDimensions ) ), type, method );
            VarNode vn = pag.makeLocalVarNode( an, an.getType(), method );
            mpag.addInternalEdge( an, vn );
            mpag.addInternalEdge( vn, pag.makeFieldRefNode( prevVn, ArrayElement.v() ) );
            prevAn = an;
            prevVn = vn;
        }
    }
    final public void caseParameterRef( ParameterRef pr ) {
  setResult( caseParm( pr.getIndex() ) );
    }
    final public void caseStaticFieldRef( StaticFieldRef sfr ) {
  setResult( pag.makeGlobalVarNode(
        sfr.getField(),
        sfr.getField().getType() ) );
    }
    final public void caseStringConstant( StringConstant sc ) {
        AllocNode stringConstant;
        if( pag.getOpts().string_constants()
        || Scene.v().containsClass(sc.value)
        || ( sc.value.length() > 0 && sc.value.charAt(0) == '[' ) ) {
            stringConstant = pag.makeStringConstantNode( sc.value );
        } else {
            stringConstant = pag.makeAllocNode(
                PointsToAnalysis.STRING_NODE,
                RefType.v( "java.lang.String" ), null );
        }
        VarNode stringConstantLocal = pag.makeGlobalVarNode(
            stringConstant,
            RefType.v( "java.lang.String" ) );
        pag.addEdge( stringConstant, stringConstantLocal );
        setResult( stringConstantLocal );
    }
    final public void caseThisRef( ThisRef tr ) {
  setResult( caseThis() );
    }
    final public void caseNullConstant( NullConstant nr ) {
  setResult( null );
    }
    final public void caseClassConstant( ClassConstant cc ) {
        AllocNode classConstant = pag.makeClassConstantNode(cc);
        VarNode classConstantLocal = pag.makeGlobalVarNode(
            classConstant,
            RefType.v( "java.lang.Class" ) );
        pag.addEdge(classConstant, classConstantLocal);
        setResult(classConstantLocal);
    }
    final public void defaultCase( Object v ) {
  throw new RuntimeException( "failed to handle "+v );
    }
    protected PAG pag;
    protected MethodPAG mpag;
    protected SootMethod method;
}
TOP

Related Classes of soot.jimple.spark.builder.MethodNodeFactory

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.