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

ExprExtractor.java

00001 package edu.ksu.cis.bandera.birc;
00002 
00003 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
00004  * Bandera, a Java(TM) analysis and transformation toolkit           *
00005  * Copyright (C) 1998, 1999   James Corbett (corbett@hawaii.edu)     *
00006  * All rights reserved.                                              *
00007  *                                                                   *
00008  * This work was done as a project in the SAnToS Laboratory,         *
00009  * Department of Computing and Information Sciences, Kansas State    *
00010  * University, USA (http://www.cis.ksu.edu/santos).                  *
00011  * It is understood that any modification not identified as such is  *
00012  * not covered by the preceding statement.                           *
00013  *                                                                   *
00014  * This work is free software; you can redistribute it and/or        *
00015  * modify it under the terms of the GNU Library General Public       *
00016  * License as published by the Free Software Foundation; either      *
00017  * version 2 of the License, or (at your option) any later version.  *
00018  *                                                                   *
00019  * This work is distributed in the hope that it will be useful,      *
00020  * but WITHOUT ANY WARRANTY; without even the implied warranty of    *
00021  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU *
00022  * Library General Public License for more details.                  *
00023  *                                                                   *
00024  * You should have received a copy of the GNU Library General Public *
00025  * License along with this toolkit; if not, write to the             *
00026  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,      *
00027  * Boston, MA  02111-1307, USA.                                      *
00028  *                                                                   *
00029  * Java is a trademark of Sun Microsystems, Inc.                     *
00030  *                                                                   *
00031  * To submit a bug report, send a comment, or get the latest news on *
00032  * this project and other SAnToS projects, please visit the web-site *
00033  *                http://www.cis.ksu.edu/santos                      *
00034  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
00035 import java.io.*;
00036 import java.util.Vector;
00037 import java.util.Hashtable;
00038 
00039 import edu.ksu.cis.bandera.bir.TransSystem;
00040 import edu.ksu.cis.bandera.bir.StateVar;
00041 import edu.ksu.cis.bandera.bir.LocVector;
00042 import edu.ksu.cis.bandera.bir.ThreadLocTest;
00043 import edu.ksu.cis.bandera.bir.IntLit;
00044 import edu.ksu.cis.bandera.jext.*;
00045 
00046 import ca.mcgill.sable.util.*;
00047 import ca.mcgill.sable.soot.*;
00048 import ca.mcgill.sable.soot.jimple.*;
00049 
00050 /**
00051  * A Jimple value switch that translates Jimple expression values into
00052  * BIR expression values.
00053  */
00054 
00055 public class ExprExtractor extends AbstractBanderaValueSwitch {
00056 
00057     TransSystem system;
00058     Stmt stmt;
00059     LocalDefs localDefs;
00060     SootMethod method;
00061     TypeExtractor typeExtract;
00062     PredicateSet predSet;
00063 
00064     boolean observable = false;
00065 
00066     public ExprExtractor(TransSystem system, Stmt stmt, LocalDefs localDefs,
00067              SootMethod method, TypeExtractor typeExtract,
00068              PredicateSet predSet) {
00069     // These params provide a context for the extraction.
00070     // Not all of them are necessary (e.g., the method is
00071     // required only if the expression might contain a Local).
00072     this.system = system;
00073     this.stmt = stmt;
00074     this.localDefs = localDefs;
00075     this.method = method;
00076     this.typeExtract = typeExtract;
00077     this.predSet = predSet;
00078     }
00079     public void caseAddExpr(AddExpr expr) {
00080     expr.getOp1().apply(this);
00081     edu.ksu.cis.bandera.bir.Expr expr1 =
00082         (edu.ksu.cis.bandera.bir.Expr) getResult();
00083     expr.getOp2().apply(this);
00084     edu.ksu.cis.bandera.bir.Expr expr2 =
00085         (edu.ksu.cis.bandera.bir.Expr) getResult();
00086     setResult(new edu.ksu.cis.bandera.bir.AddExpr(expr1, expr2));
00087     }
00088     public void caseAndExpr(AndExpr expr) {
00089     // We don't handle the bitwise integer AND and OR
00090     defaultCase(expr);
00091     }
00092     public void caseArrayRef(ArrayRef expr) {
00093     expr.getBase().apply(this);
00094     edu.ksu.cis.bandera.bir.Expr arrayRef =
00095         (edu.ksu.cis.bandera.bir.Expr) getResult();
00096     // Need to explicitly deref to access element
00097     edu.ksu.cis.bandera.bir.Expr array = 
00098         new edu.ksu.cis.bandera.bir.DerefExpr(arrayRef);
00099     expr.getIndex().apply(this);
00100     edu.ksu.cis.bandera.bir.Expr index =
00101         (edu.ksu.cis.bandera.bir.Expr) getResult();
00102     setResult(new edu.ksu.cis.bandera.bir.ArrayExpr(array, index)); 
00103     }
00104     public void caseCastExpr(CastExpr expr) {
00105     // Casts are implicit in BIR
00106     expr.getOp().apply(this);
00107     }
00108     /**
00109      * Jimple extension: choose from a set of values.
00110      */
00111 
00112     public void caseChooseExpr(ChooseExpr expr) {
00113     Object choices [] = expr.getChoices().toArray();
00114     ((Value)choices[0]).apply(this);
00115     edu.ksu.cis.bandera.bir.Expr choice = 
00116         (edu.ksu.cis.bandera.bir.Expr) getResult();
00117     edu.ksu.cis.bandera.bir.ChooseExpr choose = 
00118         new edu.ksu.cis.bandera.bir.ChooseExpr(choice);
00119     for (int i = 1; i < choices.length; i++) {
00120         ((Value)choices[i]).apply(this);
00121         choose.addChoice((edu.ksu.cis.bandera.bir.Expr) getResult());
00122     }
00123     setResult(choose);
00124     }
00125     public void caseComplementExpr(ComplementExpr expr) {
00126     expr.getOp().apply(this);
00127     edu.ksu.cis.bandera.bir.Expr expr1 =
00128         (edu.ksu.cis.bandera.bir.Expr) getResult();
00129     setResult(new edu.ksu.cis.bandera.bir.NotExpr(expr1));
00130     }
00131     public void caseDivExpr(DivExpr expr) {
00132     expr.getOp1().apply(this);
00133     edu.ksu.cis.bandera.bir.Expr expr1 =
00134         (edu.ksu.cis.bandera.bir.Expr) getResult();
00135     expr.getOp2().apply(this);
00136     edu.ksu.cis.bandera.bir.Expr expr2 =
00137         (edu.ksu.cis.bandera.bir.Expr) getResult();
00138     setResult(new edu.ksu.cis.bandera.bir.DivExpr(expr1, expr2));
00139     }
00140     public void caseEqExpr(EqExpr expr)
00141     {
00142     expr.getOp1().apply(this);
00143     edu.ksu.cis.bandera.bir.Expr expr1 =
00144         (edu.ksu.cis.bandera.bir.Expr) getResult();
00145     expr.getOp2().apply(this);
00146     edu.ksu.cis.bandera.bir.Expr expr2 =
00147         (edu.ksu.cis.bandera.bir.Expr) getResult();
00148     setResult(new edu.ksu.cis.bandera.bir.EqExpr(expr1, expr2));
00149     }
00150     public void caseGeExpr(GeExpr expr) {
00151     expr.getOp1().apply(this);
00152     edu.ksu.cis.bandera.bir.Expr expr1 =
00153         (edu.ksu.cis.bandera.bir.Expr) getResult();
00154     expr.getOp2().apply(this);
00155     edu.ksu.cis.bandera.bir.Expr expr2 =
00156         (edu.ksu.cis.bandera.bir.Expr) getResult();
00157     setResult(new edu.ksu.cis.bandera.bir.LeExpr(expr2, expr1));
00158     }
00159     public void caseGtExpr(GtExpr expr) {
00160     expr.getOp1().apply(this);
00161     edu.ksu.cis.bandera.bir.Expr expr1 =
00162         (edu.ksu.cis.bandera.bir.Expr) getResult();
00163     expr.getOp2().apply(this);
00164     edu.ksu.cis.bandera.bir.Expr expr2 =
00165         (edu.ksu.cis.bandera.bir.Expr) getResult();
00166     setResult(new edu.ksu.cis.bandera.bir.LtExpr(expr2, expr1));
00167     }
00168     /**
00169      * InExpr is a Jimple extension to support tests on abstracted types.
00170      * It tests a value for membership in a set of constants.  We translate
00171      * this test to a disjunction of equality tests.
00172      */
00173 
00174     public void caseInExpr(InExpr expr) {
00175     edu.ksu.cis.bandera.bir.Expr result = null;
00176     expr.getOp1().apply(this);
00177     edu.ksu.cis.bandera.bir.Expr op1 =
00178         (edu.ksu.cis.bandera.bir.Expr) getResult();
00179     Set values = expr.getSet();
00180     Iterator valIt = values.iterator();
00181     while (valIt.hasNext()) {
00182         Value val = (Value) valIt.next();
00183         val.apply(this);
00184         edu.ksu.cis.bandera.bir.Expr element  =
00185         (edu.ksu.cis.bandera.bir.Expr) getResult();
00186         edu.ksu.cis.bandera.bir.Expr compare = 
00187         new edu.ksu.cis.bandera.bir.EqExpr(op1,element);
00188         if (result == null)
00189         result = compare;
00190         else
00191         result = new edu.ksu.cis.bandera.bir.OrExpr(result,compare);
00192     }
00193     setResult(result);
00194     }
00195     public void caseInstanceFieldRef(InstanceFieldRef expr) {
00196     if (predSet.isObservable(expr.getField()))
00197         observable = true;
00198     expr.getBase().apply(this);
00199     edu.ksu.cis.bandera.bir.Expr base =
00200         (edu.ksu.cis.bandera.bir.Expr) getResult();
00201     // Need to explicitly deref to access element
00202     edu.ksu.cis.bandera.bir.Expr rec = 
00203         new edu.ksu.cis.bandera.bir.DerefExpr(base);
00204     edu.ksu.cis.bandera.bir.Record recType = 
00205         (edu.ksu.cis.bandera.bir.Record)
00206         ((edu.ksu.cis.bandera.bir.Ref)base.getType()).getTargetType();
00207     edu.ksu.cis.bandera.bir.Field field = 
00208         recType.getField(system.getNameOf(expr.getField()));
00209     setResult(new edu.ksu.cis.bandera.bir.RecordExpr(rec,field));
00210     }
00211     public void caseInstanceOfExpr(InstanceOfExpr expr) {
00212     expr.getOp().apply(this);
00213     edu.ksu.cis.bandera.bir.Expr refExpr =
00214         (edu.ksu.cis.bandera.bir.Expr) getResult();
00215     // Use type extractor to get BIR type for SootClass
00216     expr.getCheckType().apply(typeExtract);
00217     edu.ksu.cis.bandera.bir.Ref refType = 
00218         (edu.ksu.cis.bandera.bir.Ref) typeExtract.getResult();
00219     setResult(new edu.ksu.cis.bandera.bir.InstanceOfExpr(refExpr,refType));
00220     }
00221     public void caseIntConstant(IntConstant expr) {
00222     setResult(new IntLit(expr.value));
00223     }
00224     public void caseLeExpr(LeExpr expr) {
00225     expr.getOp1().apply(this);
00226     edu.ksu.cis.bandera.bir.Expr expr1 =
00227         (edu.ksu.cis.bandera.bir.Expr) getResult();
00228     expr.getOp2().apply(this);
00229     edu.ksu.cis.bandera.bir.Expr expr2 =
00230         (edu.ksu.cis.bandera.bir.Expr) getResult();
00231     setResult(new edu.ksu.cis.bandera.bir.LeExpr(expr1, expr2));
00232     }
00233     public void caseLengthExpr(LengthExpr expr) {
00234     expr.getOp().apply(this);
00235     edu.ksu.cis.bandera.bir.Expr arrayRef =
00236         (edu.ksu.cis.bandera.bir.Expr) getResult();
00237     // Need to explicitly deref to access element
00238     edu.ksu.cis.bandera.bir.Expr array = 
00239         new edu.ksu.cis.bandera.bir.DerefExpr(arrayRef);
00240     setResult(new edu.ksu.cis.bandera.bir.LengthExpr(array));
00241     }
00242     public void caseLocal(Local expr) {
00243     if (method == null)
00244         throw new RuntimeException("Local appears in predicate outside of a LocalExpr");
00245     String key = localKey(method,expr);
00246     // Mark expression as observable if Local is 
00247     if (predSet.isObservable(key))
00248         observable = true;
00249     edu.ksu.cis.bandera.bir.StateVar var = system.getVarOfKey(key);
00250     if (var == null)
00251         throw new RuntimeException("Variable not declared: " + expr);
00252     setResult(var);
00253     }
00254     /**
00255      * A LocalExpr is a Jimple extension that carries its own method
00256      * (so a Local can appear in a predicate expression, which is
00257      * extracted outside the context of any method).
00258      */
00259 
00260     public void caseLocalExpr(LocalExpr expr) { 
00261     SootMethod method = expr.getMethod();
00262     Local local = expr.getLocal();
00263     String key = ExprExtractor.localKey(method,local);
00264     edu.ksu.cis.bandera.bir.StateVar var = system.getVarOfKey(key);
00265     if (var == null)
00266         throw new RuntimeException("Variable not declared: " + expr);
00267     setResult(var); 
00268     }
00269     public void caseLocationTestExpr(LocationTestExpr expr) {
00270     // Build a large disjunction of ThreadLocTest expressions
00271     // for all the Stmts and their locations.
00272     // Note that the predicate set holds the set of locations
00273     // for a given Stmt.
00274     edu.ksu.cis.bandera.bir.Expr predExpr = null;
00275     Vector stmts = expr.getStmts();
00276     for (int i = 0; i < stmts.size(); i++) {
00277         Stmt stmt = (Stmt) stmts.elementAt(i);
00278         LocVector locs = predSet.getPredicateLocations(stmt);
00279         for (int j = 0; j < locs.size(); j++) {
00280         ThreadLocTest locTest = new ThreadLocTest(locs.elementAt(j));
00281         if (predExpr == null)
00282             predExpr = locTest;
00283         else
00284             predExpr =
00285             new edu.ksu.cis.bandera.bir.OrExpr(predExpr,locTest);
00286         }       
00287     }
00288     if (predExpr == null)
00289         predExpr = new edu.ksu.cis.bandera.bir.BoolLit(false);
00290     setResult(predExpr);
00291     }
00292     public void caseLogicalAndExpr(LogicalAndExpr expr) {
00293     expr.getOp1().apply(this);
00294     edu.ksu.cis.bandera.bir.Expr expr1 =
00295         (edu.ksu.cis.bandera.bir.Expr) getResult();
00296     expr.getOp2().apply(this);
00297     edu.ksu.cis.bandera.bir.Expr expr2 =
00298         (edu.ksu.cis.bandera.bir.Expr) getResult();
00299     setResult(new edu.ksu.cis.bandera.bir.AndExpr(expr1,expr2));
00300     }
00301     public void caseLogicalOrExpr(LogicalOrExpr expr) {
00302     expr.getOp1().apply(this);
00303     edu.ksu.cis.bandera.bir.Expr expr1 =
00304         (edu.ksu.cis.bandera.bir.Expr) getResult();
00305     expr.getOp2().apply(this);
00306     edu.ksu.cis.bandera.bir.Expr expr2 =
00307         (edu.ksu.cis.bandera.bir.Expr) getResult();
00308     setResult(new edu.ksu.cis.bandera.bir.OrExpr(expr1,expr2));
00309     }
00310     public void caseLtExpr(LtExpr expr) {
00311     expr.getOp1().apply(this);
00312     edu.ksu.cis.bandera.bir.Expr expr1 =
00313         (edu.ksu.cis.bandera.bir.Expr) getResult();
00314     expr.getOp2().apply(this);
00315     edu.ksu.cis.bandera.bir.Expr expr2 =
00316         (edu.ksu.cis.bandera.bir.Expr) getResult();
00317     setResult(new edu.ksu.cis.bandera.bir.LtExpr(expr1, expr2));
00318     }
00319     public void caseMulExpr(MulExpr expr) {
00320     expr.getOp1().apply(this);
00321     edu.ksu.cis.bandera.bir.Expr expr1 =
00322         (edu.ksu.cis.bandera.bir.Expr) getResult();
00323     expr.getOp2().apply(this);
00324     edu.ksu.cis.bandera.bir.Expr expr2 =
00325         (edu.ksu.cis.bandera.bir.Expr) getResult();
00326     setResult(new edu.ksu.cis.bandera.bir.MulExpr(expr1, expr2));
00327     }
00328     public void caseNeExpr(NeExpr expr)
00329     {
00330     expr.getOp1().apply(this);
00331     edu.ksu.cis.bandera.bir.Expr expr1 =
00332         (edu.ksu.cis.bandera.bir.Expr) getResult();
00333     expr.getOp2().apply(this);
00334     edu.ksu.cis.bandera.bir.Expr expr2 =
00335         (edu.ksu.cis.bandera.bir.Expr) getResult();
00336     setResult(new edu.ksu.cis.bandera.bir.NeExpr(expr1, expr2));
00337     }
00338     public void caseNegExpr(NegExpr expr) {
00339     expr.getOp().apply(this);
00340     edu.ksu.cis.bandera.bir.Expr expr1 =
00341         (edu.ksu.cis.bandera.bir.Expr) getResult();
00342     setResult(new edu.ksu.cis.bandera.bir.SubExpr(IntLit.ZERO,expr1));
00343     }
00344     public void caseNewArrayExpr(NewArrayExpr expr) {
00345     StateVar col = system.getVarOfKey(expr);
00346     expr.getSize().apply(this);
00347     edu.ksu.cis.bandera.bir.Expr size =
00348         (edu.ksu.cis.bandera.bir.Expr) getResult();
00349     setResult(new edu.ksu.cis.bandera.bir.NewArrayExpr(col,size));
00350     }
00351     public void caseNewExpr(NewExpr expr) {
00352     StateVar col = system.getVarOfKey(expr);
00353     if (col != null)
00354         setResult(new edu.ksu.cis.bandera.bir.NewExpr(col));
00355     else  
00356         // No collection for that allocator---must be for built-in
00357         // class we're not modeling explicitly (e.g., Thread)
00358         setResult(new edu.ksu.cis.bandera.bir.NullExpr(system));
00359     }
00360     public void caseNullConstant(NullConstant expr) {
00361     setResult(new edu.ksu.cis.bandera.bir.NullExpr(system));
00362     }
00363     public void caseOrExpr(OrExpr expr) {
00364     // We don't handle the bitwise integer AND and OR
00365     defaultCase(expr);
00366     }
00367     public void caseRemExpr(RemExpr expr) {
00368     expr.getOp1().apply(this);
00369     edu.ksu.cis.bandera.bir.Expr expr1 =
00370         (edu.ksu.cis.bandera.bir.Expr) getResult();
00371     expr.getOp2().apply(this);
00372     edu.ksu.cis.bandera.bir.Expr expr2 =
00373         (edu.ksu.cis.bandera.bir.Expr) getResult();
00374     setResult(new edu.ksu.cis.bandera.bir.RemExpr(expr1, expr2));
00375     }
00376     public void caseStaticFieldRef(StaticFieldRef expr) {
00377     // Mark expression as observable if field is observable
00378     if (predSet.isObservable(expr.getField()))
00379         observable = true;
00380     edu.ksu.cis.bandera.bir.StateVar var = 
00381         system.getVarOfKey(expr.getField());
00382     if (var == null)
00383         throw new RuntimeException("Field not declared: " + expr);
00384     setResult(var);
00385     }
00386     public void caseStaticInvokeExpr(StaticInvokeExpr expr) {
00387     throw new RuntimeException("Unhandled static method call: " + expr);
00388     }
00389     public void caseStringConstant(StringConstant expr) {
00390     String s = expr.toString();
00391     setResult(s.substring(1,s.length() - 1));
00392     }
00393     public void caseSubExpr(SubExpr expr) {
00394     expr.getOp1().apply(this);
00395     edu.ksu.cis.bandera.bir.Expr expr1 =
00396         (edu.ksu.cis.bandera.bir.Expr) getResult();
00397     expr.getOp2().apply(this);
00398     edu.ksu.cis.bandera.bir.Expr expr2 =
00399         (edu.ksu.cis.bandera.bir.Expr) getResult();
00400     setResult(new edu.ksu.cis.bandera.bir.SubExpr(expr1, expr2));   
00401     }
00402     public void caseThisRef(ThisRef thisRef) {
00403     String threadName = ((RefType)thisRef.getType()).className;
00404     SootClass sClass = 
00405         method.getDeclaringClass().getManager().getClass(threadName);
00406     // For each thread, we create a 'this' var with the thread
00407     // class as the key.
00408     StateVar var = system.getVarOfKey(sClass);
00409     setResult(var);
00410     }
00411     public void defaultCase(Object o) {
00412     throw new RuntimeException("Unhandled expression type " + 
00413                    o.getClass().getName() + ": " + o);
00414     }
00415     public boolean isObservable() { return observable; }
00416     /**
00417      * Construct a unique key for a Jimple Local by concatenating
00418      * the class, method, and local name.
00419      * <p>
00420      * We need to do this rather than just use the Local object
00421      * as a key because the Soot designers decided that two Locals
00422      * would be equal() if they had the same name, even if they
00423      * were in different methods.
00424      */
00425 
00426     public static String localKey(SootMethod method, Local local) {
00427     return  method.getDeclaringClass().getName() + "."
00428         + method.getName() + "." + local.getName();
00429     }
00430 }

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