Main Page   Packages   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members  

FGStmt.java

00001 package edu.ksu.cis.bandera.bofa;
00002 
00003 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
00004  * Bandera, a Java(TM) analysis and transformation toolkit           *
00005  * Copyright (C) 1998, 1999                                          *
00006  * John Hatcliff (hatcliff@cis.ksu.edu)
00007  * All rights reserved.                                              *
00008  *                                                                   *
00009  * This work was done as a project in the SAnToS Laboratory,         *
00010  * Department of Computing and Information Sciences, Kansas State    *
00011  * University, USA (http://www.cis.ksu.edu/santos).                  *
00012  * It is understood that any modification not identified as such is  *
00013  * not covered by the preceding statement.                           *
00014  *                                                                   *
00015  * This work is free software; you can redistribute it and/or        *
00016  * modify it under the terms of the GNU Library General Public       *
00017  * License as published by the Free Software Foundation; either      *
00018  * version 2 of the License, or (at your option) any later version.  *
00019  *                                                                   *
00020  * This work is distributed in the hope that it will be useful,      *
00021  * but WITHOUT ANY WARRANTY; without even the implied warranty of    *
00022  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU *
00023  * Library General Public License for more details.                  *
00024  *                                                                   *
00025  * You should have received a copy of the GNU Library General Public *
00026  * License along with this toolkit; if not, write to the             *
00027  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,      *
00028  * Boston, MA  02111-1307, USA.                                      *
00029  *                                                                   *
00030  * Java is a trademark of Sun Microsystems, Inc.                     *
00031  *                                                                   *
00032  * To submit a bug report, send a comment, or get the latest news on *
00033  * this project and other SAnToS projects, please visit the web-site *
00034  *                http://www.cis.ksu.edu/santos                      *
00035  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
00036 
00037 import ca.mcgill.sable.util.*;
00038 import ca.mcgill.sable.soot.*;
00039 import ca.mcgill.sable.soot.jimple.*;
00040 import org.apache.log4j.Category;
00041 
00042 /**
00043  * The class in which the statements of a method are processed to extend the
00044  * FlowGraph for the MethodVariant.
00045  *
00046  * @author <A HREF="http://www.cis.ksu.edu/~hatcliff">John Hatcliff</A> 
00047  * @author 
00048  * <a href="http://www.cis.ksu.edu/~rvprasad">Venkatesh Prasad Ranganath</a>
00049  * @version $Name:  $($Revision: 1.1.1.1 $)
00050  */
00051 public class FGStmt extends AbstractStmtSwitch
00052 {
00053     /** 
00054      * The method variant for which the flow graph needs to be
00055      * extended. 
00056      */
00057     private MethodVariant methodVariant;
00058 
00059     /** 
00060      * The method associated with the method variant.
00061      */
00062     private SootMethod sootMethod; 
00063 
00064     /** 
00065      * Maps the AST nodes occuring in the method to flow graph nodes. 
00066      */
00067     private Map astNodes;
00068 
00069     /** 
00070      * The FGExpr object which will process the expressions that occur in the
00071      *  statement that will be processed.
00072      */
00073     private FGExpr fgExpr;
00074 
00075     /** 
00076      * The current statement in the method being processed. 
00077      */
00078     private Stmt stmt;
00079 
00080     /**
00081      * The object used to process LHS expressions.
00082      *
00083      */
00084     private TempAbstJmplValSwitch sw;
00085 
00086     /**
00087      * Provides logging capability through log4j.
00088      *
00089      */
00090     private static Category cat;
00091 
00092     static {
00093         cat = Category.getInstance("edu.ksu.cis.bandera.bofa.FGStmt");
00094     }
00095     
00096     /**
00097      * The class in which nodes corresponding to LHS expressions are created.
00098      */
00099     class TempAbstJmplValSwitch extends AbstractJimpleValueSwitch
00100     {
00101         /**
00102          * Handles a local variable on LHS.
00103          *
00104          * @param l the local variable on LHS.  
00105          */
00106         public void caseLocal(Local l)
00107         {
00108             FGNodeAST astNode   = new FGNodeAST(l);
00109             FGNode.makeArc(astNode, methodVariant.getLocalNode(l));
00110             astNodes.put(l, astNode);
00111             ((AbstractJimpleValueSwitch)this).setResult(astNode);
00112         }
00113         
00114         /**
00115          * Handles a static field variable on LHS.
00116          *
00117          * @param f the static field variable on LHS.  
00118          */
00119         public void caseStaticFieldRef(StaticFieldRef f)
00120         {
00121             SootField field = f.getField();
00122             FGNodeAST astNode = new FGNodeAST(f);
00123             FGNode.makeArc(astNode, StaticFieldManager.select(field));
00124             astNodes.put(f, astNode);
00125             ((AbstractJimpleValueSwitch)this).setResult(astNode);
00126         }
00127 
00128         /**
00129          * Handles a instance field variable on LHS.
00130          *
00131          * @param f the instance field variable on LHS.  */
00132         public void caseInstanceFieldRef(InstanceFieldRef f)
00133         {
00134             SootField field = f.getField();
00135             FGNodeAST astNode = 
00136                 new FGNodeAST(f);
00137             FGNode.makeArc(astNode,
00138                            InstanceVariantManager.select(field).getNode());
00139             astNodes.put(f, astNode);
00140             ((AbstractJimpleValueSwitch)this).setResult(astNode);
00141         }
00142 
00143         // should we also handle CaughtExceptionRef() and NextNextStmtRef() 
00144 
00145         /**
00146          * Handles array references on LHS.
00147          *
00148          * @param ref the array reference on LHS.  
00149          */
00150         public void caseArrayRef(ArrayRef ref)
00151         {
00152             FGNode baseNode = fgExpr.build(ref.getBase(), stmt);
00153 
00154             /* 
00155              * The "type" attribute of the array ref AST is the component type
00156              * of the array.  Make an array type to use in
00157              * ClassTokenArray.select() 
00158              */
00159             ArrayType arrayType =
00160                 ClassTokenArray.componentToArrayType(ref.getType()); 
00161                   
00162             ClassTokenArray classTokenArray = ClassTokenArray.select(arrayType);
00163                   
00164             // Here, we need to attach an action to the flowgraph as in RHS
00165             // array reference. 
00166             FGNodeAST arrayRefNode = new FGNodeAST(ref); 
00167             /* 
00168              * generate action: Different array objects (represented by value
00169              * variants) may flow into the base node.
00170              *
00171              * For any new value variant that flows into the base node, the
00172              * array variant FGNode that summarizes the contents of the array
00173              * will be found and an FG arc will be made from the AST node to the
00174              * array variant node.  
00175              */
00176             baseNode.addAction(new FGActionArrayStore(classTokenArray,
00177                                                       arrayRefNode));  
00178             astNodes.put(ref,arrayRefNode);
00179             ((AbstractJimpleValueSwitch)this).setResult(arrayRefNode);
00180         }
00181 
00182         /** 
00183          * Handles all cases that are unhandled at present.
00184          *
00185          * @param o the object representing the value occuring on LHS which is
00186          * currently not handled.
00187          */
00188         public void defaultCase(Object o) {
00189             cat.debug("Unhandled LHS: " + o.getClass());
00190             ((AbstractJimpleValueSwitch)this).setResult(null);
00191         }
00192     }
00193 
00194     /* This code seems to be tightly coupled to MethodVariant.  Perhaps
00195        it should be placed in that class (same for FGExpr).
00196     */
00197     /** 
00198      * Constructor of the class.
00199      *
00200      * @param methodVariant the method whose statements needs to be processed.
00201      * @param astNodes the map of AST nodes for the given method. 
00202      */
00203     public FGStmt(MethodVariant methodVariant, Map astNodes)
00204     {
00205         this.methodVariant = methodVariant;
00206         this.sootMethod    = methodVariant.getMethod();
00207         this.fgExpr        = new FGExpr(methodVariant, astNodes);
00208         this.astNodes      = astNodes;
00209         sw = new TempAbstJmplValSwitch();     
00210     }
00211     /**
00212      * Starts the extension of flow graph for the given statement.
00213      *
00214      * @param s the statement for which the FG needs to be created. 
00215      */
00216     public void build(Stmt s)
00217     {
00218         stmt = s;
00219         s.apply(this);
00220     }
00221     /** 
00222      * Extends the part of flow graph for assignment statement.
00223      *
00224      * @param s the object representing an assignment statement.  
00225      */
00226     public void caseAssignStmt(AssignStmt s)
00227     {
00228         Value lhs, rhs;
00229         FGNodeAST lhsNode, rhsNode; 
00230 
00231         lhs = s.getLeftOp();
00232         rhs = s.getRightOp();
00233 
00234         lhsNode = getLHSNode(lhs);
00235         rhsNode = fgExpr.build(rhs, s);
00236         
00237         FGNode.makeArc(rhsNode, lhsNode);
00238     }
00239     /**
00240      * Extends the part of flow graph for the entermonitor statement.  We just
00241      * process the expression.
00242      *
00243      * @param s the object representing the entermonitor statement. 
00244      */
00245     public void caseEnterMonitorStmt(EnterMonitorStmt s)
00246     {
00247         fgExpr.build(s.getOp(), s);  
00248     }
00249     /**
00250      * Extends the part of flow graph for the exitmonitor statement.  We just
00251      * process the expression.
00252      *
00253      * @param s the object representing the exitmonitor statement. 
00254      */
00255     public void caseExitMonitorStmt(ExitMonitorStmt s)
00256     {
00257         fgExpr.build(s.getOp(), s);
00258     }
00259     /** 
00260      * Extends the part of flow graph for identity statement.
00261      *
00262      * @param s the object representing an identity statement.  
00263      */
00264     public void caseIdentityStmt(IdentityStmt s)
00265     {
00266         /*
00267          * Identity: Generate graph for RHS. Then, make a FG arc from RHS
00268          * node to node for (variable) that appears on LHS.  Note that if no
00269          * object values are produced in the RHS, then rhsNode should be null
00270          * and FG.makeArc is defined to do nothing when the source node is null.
00271          *
00272          * Remember: identity is used to represent actions that happen during
00273          * JVM method invocation and manipulation of exceptions.  For example,
00274          * in the actual byte code, there is an implicit transfer of the actual
00275          * parameters into slots in the frame (which represent formal parameters
00276          * which are represented the same as locals).  In this case, we have
00277          * a Jimple statement like local-a := @param2 --- this represents the
00278          * transfer from the stack into the frame location associated with the
00279          * local variable 'local-a'.
00280          * 
00281          * In a similar way, catch blocks like try {...} catch (Exception e)
00282          * {...}  are parameterized on the exception e, and there is an implicit
00283          * transfer when the JVM is executing from the current exception to the
00284          * variable e.  So this generates identity statements like e :=
00285          * @caughtexception.  */
00286         Value lhs, rhs;
00287         FGNodeAST lhsNode, rhsNode; 
00288 
00289         lhs = s.getLeftOp();
00290         rhs = s.getRightOp();
00291 
00292         lhsNode = getLHSNode(lhs);
00293         rhsNode = fgExpr.build(rhs, s);
00294 
00295         FGNode.makeArc(rhsNode, lhsNode);
00296     }
00297     /**
00298      * Extends the part of flow graph for if statement.  We just process the
00299      * boolean expression.
00300      * 
00301      * @param s the object representing the if statement. 
00302      */
00303     public void caseIfStmt(IfStmt s)
00304     {
00305         /*
00306          * If: Generate graph for test expression.  No outgoing arc since there
00307          * is nothing returned here.  We may be able to eliminate traversing the
00308          * expression if there is not object flow within (e.g., no method
00309          * applications).  
00310          */
00311         fgExpr.build(s.getCondition(), s);
00312     }
00313     /**
00314      * Extends the part of flow graph for invoke statement.
00315      *
00316      * @param s the object representing the invocation statement.  
00317      */
00318     public void caseInvokeStmt(InvokeStmt s)
00319     {
00320         fgExpr.build(s.getInvokeExpr(), s);
00321     }
00322     /**
00323      * Extends the part of flow graph for return statement.
00324      *
00325      * @param s the object representing the return statment. 
00326      */ 
00327     public void caseReturnStmt(ReturnStmt s)
00328     {
00329         /**
00330          * Return: 
00331          * Generate a FG for return expression, and make an arc from the return
00332          * expression to the exit node for this method.
00333          */
00334         FGNode.makeArc(fgExpr.build((Value)s.getReturnValue(), s),
00335                    methodVariant.getReturnNode()); 
00336     }
00337     /**
00338      * Extends the part of flow graph for the throw statement.  We just process
00339      * the expression.
00340      * @param s the object representing the throw statement. 
00341      */
00342     public void caseThrowStmt(ThrowStmt s)
00343     {
00344         fgExpr.build(s.getOp(), s);
00345     }
00346     /**
00347      * Raise an exception for all unhandled statement form.
00348      *
00349      * @param obj the object representing the statement.  
00350      */
00351     public void defaultCase(Object obj)
00352     {
00353         System.out.println("Unhandled Statement:  " + obj.getClass());
00354     }
00355     /**
00356      * Extends the part of flow graph node for LHS expressions.
00357      *
00358      * @param v the object representing the LHS expression.
00359      * @return the flow node corresponding to the given LHS expression.
00360      */
00361     public FGNodeAST getLHSNode(Value v) 
00362     {
00363         v.apply(sw);
00364         FGNodeAST astNode = (FGNodeAST)sw.getResult();
00365         if (astNode != null) {
00366             astNode.setStmt(stmt);
00367         } // end of if (astNode != null)
00368         return astNode;
00369     }
00370 }

Generated at Thu Feb 7 06:45:34 2002 for Bandera by doxygen1.2.10 written by Dimitri van Heesch, © 1997-2001