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

JimpleBody.java

00001 package ca.mcgill.sable.soot.jimple;
00002 
00003 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
00004  * Jimple, a 3-address code Java(TM) bytecode representation.        *
00005  * Copyright (C) 1997, 1998 Raja Vallee-Rai (kor@sable.mcgill.ca)    *
00006  * All rights reserved.                                              *
00007  *                                                                   *
00008  * Modifications by Etienne Gagnon (gagnon@sable.mcgill.ca) are      *
00009  * Copyright (C) 1998 Etienne Gagnon (gagnon@sable.mcgill.ca).  All  *
00010  * rights reserved.                                                  *
00011  *                                                                   *
00012  * Modifications by Patrick Lam (plam@sable.mcgill.ca) are           *
00013  * Copyright (C) 1999 Patrick Lam.  All rights reserved.             *
00014  *                                                                   *
00015  * This work was done as a project of the Sable Research Group,      *
00016  * School of Computer Science, McGill University, Canada             *
00017  * (http://www.sable.mcgill.ca/).  It is understood that any         *
00018  * modification not identified as such is not covered by the         *
00019  * preceding statement.                                              *
00020  *                                                                   *
00021  * This work is free software; you can redistribute it and/or        *
00022  * modify it under the terms of the GNU Library General Public       *
00023  * License as published by the Free Software Foundation; either      *
00024  * version 2 of the License, or (at your option) any later version.  *
00025  *                                                                   *
00026  * This work is distributed in the hope that it will be useful,      *
00027  * but WITHOUT ANY WARRANTY; without even the implied warranty of    *
00028  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU *
00029  * Library General Public License for more details.                  *
00030  *                                                                   *
00031  * You should have received a copy of the GNU Library General Public *
00032  * License along with this library; if not, write to the             *
00033  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,      *
00034  * Boston, MA  02111-1307, USA.                                      *
00035  *                                                                   *
00036  * Java is a trademark of Sun Microsystems, Inc.                     *
00037  *                                                                   *
00038  * To submit a bug report, send a comment, or get the latest news on *
00039  * this project and other Sable Research Group projects, please      *
00040  * visit the web site: http://www.sable.mcgill.ca/                   *
00041  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
00042 
00043 /*
00044  Reference Version
00045  -----------------
00046  This is the latest official version on which this file is based.
00047  The reference version is: $SootVersion: 1.beta.4 $
00048 
00049  Change History
00050  --------------
00051  A) Notes:
00052 
00053  Please use the following template.  Most recent changes should
00054  appear at the top of the list.
00055 
00056  - Modified on [date (March 1, 1900)] by [name]. [(*) if appropriate]
00057    [description of modification].
00058 
00059  Any Modification flagged with "(*)" was done as a project of the
00060  Sable Research Group, School of Computer Science,
00061  McGill University, Canada (http://www.sable.mcgill.ca/).
00062 
00063  You should add your copyright, using the following template, at
00064  the top of this file, along with other copyrights.
00065 
00066  *                                                                   *
00067  * Modifications by [name] are                                       *
00068  * Copyright (C) [year(s)] [your name (or company)].  All rights     *
00069  * reserved.                                                         *
00070  *                                                                   *
00071 
00072  B) Changes:
00073 
00074  - Modified on March 16, 1999 by Raja Vallee-Rai (rvalleerai@sable.mcgill.ca) (*)
00075    Introduced a patch to get around current typing limitations.
00076 
00077  - Modified on February 3, 1999 by Patrick Lam (plam@sable.mcgill.ca) (*)
00078    Added changes in support of the Grimp intermediate
00079    representation (with aggregated-expressions).
00080 
00081  - Modified on November 21, 1998 by Raja Vallee-Rai (kor@sable.mcgill.ca) (*)
00082    Added a constructor and handling of debug option.
00083    
00084  - Modified on November 2, 1998 by Raja Vallee-Rai (kor@sable.mcgill.ca) (*)
00085    Repackaged all source files and performed extensive modifications.
00086    First initial release of Soot.
00087 
00088  - Modified on October 4, 1998 by Raja Vallee-Rai (kor@sable.mcgill.ca). (*)
00089    Errors in type inference now throws an exception (disabled with -debug).
00090 
00091  - Modified on September 3, 1998 by Raja Vallee-Rai (kor@sable.mcgill.ca). (*)
00092    Sets coffi pointers to null after usage for memory release.
00093 
00094  - Modified on July 29, 1998 by Etienne Gagnon (gagnon@sable.mcgill.ca). (*)
00095    Added code to hande the "noSplitting" global option.
00096 
00097  - Modified on July 29, 1998 by Etienne Gagnon (gagnon@sable.mcgill.ca). (*)
00098    Added code to hande the "noSplitting" global option.
00099 
00100  - Modified on 23-Jul-1998 by Raja Vallee-Rai (kor@sable.mcgill.ca). (*)
00101    Added a constructor for StmtListBody.
00102    And other misc. changes.
00103 
00104  - Modified on 15-Jun-1998 by Raja Vallee-Rai (kor@sable.mcgill.ca). (*)
00105    First internal release (Version 0.1).
00106 */
00107 
00108 import ca.mcgill.sable.soot.*;
00109 import ca.mcgill.sable.util.*;
00110 import ca.mcgill.sable.soot.baf.*;
00111 import java.io.*;
00112 
00113 public class JimpleBody implements StmtBody
00114 {
00115     List locals = new ArrayList();
00116     SootMethod method;
00117 
00118     StmtList stmtList;
00119     List traps = new ArrayList();
00120 
00121 
00122     /**
00123         Construct an empty JimpleBody 
00124      **/
00125      
00126     JimpleBody(SootMethod m)
00127     {
00128         this.method = m;
00129         stmtList = new StmtList(this);   
00130     }
00131     /**
00132         Constructs a JimpleBody from the given Body.
00133      */
00134 
00135     public JimpleBody(SootMethod m, Body body, int buildOptions)
00136     {
00137         ClassFileBody fileBody;
00138 
00139         if(body instanceof ClassFileBody)
00140             fileBody = (ClassFileBody) body;
00141         else
00142             throw new RuntimeException("Can only construct JimpleBody's directly from ClassFileBody's (for now)");
00143 
00144         this.method = fileBody.getMethod();
00145         this.stmtList = new StmtList(this);
00146 
00147         ca.mcgill.sable.soot.coffi.ClassFile coffiClass = fileBody.coffiClass;
00148         ca.mcgill.sable.soot.coffi.method_info coffiMethod = fileBody.coffiMethod;
00149 
00150         /*
00151             I need to set these to null to free Coffi structures.
00152         fileBody.coffiClass = null;
00153         bafBody.coffiMethod = null;
00154 
00155         */
00156         if(Main.isVerbose)
00157             System.out.println("[" + method.getName() + "] Jimplifying...");
00158 
00159         if(Modifier.isAbstract(method.getModifiers()) || Modifier.isNative(method.getModifiers()))
00160             return;
00161             
00162         if(Main.isProfilingOptimization)
00163             Main.conversionTimer.start();
00164         
00165         if(coffiMethod.cfg == null)
00166         {
00167             if(Main.isVerbose)
00168                 System.out.println("[" + method.getName() +
00169                     "]     Building Coffi CFG...");
00170 
00171              new ca.mcgill.sable.soot.coffi.CFG(coffiMethod);
00172 
00173              if(Main.isVerbose)
00174                 System.out.println("[" + method.getName() +
00175                     "]     Coffi CFG complete.");
00176 
00177          }
00178 
00179          if(Main.isVerbose)
00180              System.out.println("[" + method.getName() +
00181                 "]      Producing naive Jimple...");
00182          coffiMethod.cfg.jimplify(coffiClass.constant_pool,
00183              coffiClass.this_class, this);
00184         
00185          if(Main.isProfilingOptimization)
00186          {
00187              Main.conversionTimer.end();
00188              Main.conversionLocalCount += getLocalCount();
00189              Main.conversionStmtCount += stmtList.size();
00190          }
00191 
00192          if(Main.isVerbose)
00193              System.out.println("[" + method.getName() +
00194                 "]      Naive typeless Jimple produced.");
00195 
00196         // Jimple.printStmtList_debug(this, System.out);
00197 
00198         if(!BuildJimpleBodyOption.noSplitting(buildOptions))
00199         {
00200             if(Main.isProfilingOptimization)
00201                 Main.splitTimer.start();
00202 
00203             LocalSplitter.splitLocals(this);
00204 
00205             if(Main.isProfilingOptimization)
00206             {
00207                 Main.splitTimer.end();
00208                 Main.splitLocalCount += getLocalCount();
00209                 Main.splitStmtCount += stmtList.size();
00210             }
00211 
00212             if(!BuildJimpleBodyOption.noTyping(buildOptions))
00213             {
00214                 if(Main.isProfilingOptimization)
00215                     Main.assignTimer.start();
00216 
00217                 // Jimple.printStmtListBody_debug(this, System.out);
00218                 Transformations.assignTypesToLocals(this);
00219 
00220                 if(typingFailed())
00221                 {
00222                     patchForTyping();
00223                     
00224                     Transformations.assignTypesToLocals(this);
00225                     
00226                     if(typingFailed())
00227                         throw new RuntimeException("type inference failed!");
00228                         
00229                 }
00230                 
00231                 if(Main.isProfilingOptimization)
00232                 {
00233                     Main.assignLocalCount += getLocalCount();
00234                     Main.assignStmtCount += stmtList.size();
00235 
00236                     Main.assignTimer.end();
00237                 }
00238             }
00239         }
00240 
00241         if(!BuildJimpleBodyOption.noCleanup(buildOptions))
00242         {
00243             Transformations.cleanupCode(this);
00244             Transformations.removeUnusedLocals(this);
00245 
00246             if(Main.isProfilingOptimization)
00247             {
00248                 Main.cleanup1LocalCount += getLocalCount();
00249                 Main.cleanup1StmtCount += stmtList.size();
00250             }
00251         }
00252 
00253         if(!BuildJimpleBodyOption.noAggregating(buildOptions))
00254         {
00255             Transformations.aggregate(this);
00256             Transformations.removeUnusedLocals(this);            
00257         }
00258 
00259             Transformations.renameLocals(this);
00260 /*
00261             if(!BuildJimpleBodyOption.noPacking(buildOptions))
00262             {
00263                 if(Main.isProfilingOptimization)
00264                     Main.packTimer.start();
00265 
00266                 Transformations.packLocals(this);
00267                 
00268                 //FastAllocator.packLocals(this);
00269                 Transformations.removeUnusedLocals(this);
00270 
00271                 if(Main.isProfilingOptimization)
00272                 {
00273                     Main.packLocalCount += getLocalCount();
00274                     Main.packStmtCount += stmtList.size();
00275 
00276                     Main.packTimer.end();
00277                 }
00278             }
00279 */
00280 
00281             /*
00282             if(!Main.noCleanUp)
00283             {
00284                 if(Main.isProfilingOptimization)
00285                     Main.cleanup2Timer.start();
00286 
00287                 Transformations.cleanupCode(this);
00288                 Transformations.removeUnusedLocals(this);
00289 
00290                 if(Main.isProfilingOptimization)
00291                 {
00292                     Main.cleanup2LocalCount += getLocalCount();
00293                     Main.cleanup2StmtCount += stmtList.size();
00294 
00295                     Main.cleanup2Timer.end();
00296                 }
00297             }
00298             */
00299 
00300     }
00301     public void addLocal(Local l) throws AlreadyDeclaredException
00302     {
00303         locals.add(l);
00304     }
00305     public void addTrap(Trap t)
00306     {
00307         traps.add(t);
00308     }
00309     public boolean declaresLocal(String localName)
00310     {
00311         Iterator localIt = getLocals().iterator();
00312 
00313         while(localIt.hasNext())
00314         {
00315             Local local = (Local) localIt.next();
00316 
00317             if(local.name.equals(localName))
00318                 return true;
00319         }
00320 
00321         return false;
00322     }
00323     public void eliminateBackPointersTo(Stmt oldLocation)
00324     {
00325         Iterator boxIt = oldLocation.getUnitBoxes().iterator();
00326 
00327         while(boxIt.hasNext())
00328         {
00329             StmtBox box = (StmtBox) boxIt.next();
00330             Stmt stmt = (Stmt) box.getUnit();
00331 
00332             stmt.getBoxesPointingToThis().remove(oldLocation);
00333         }
00334     }
00335     public Local getLocal(String name) throws ca.mcgill.sable.soot.jimple.NoSuchLocalException
00336     {
00337         Iterator localIt = getLocals().iterator();
00338 
00339         while(localIt.hasNext())
00340         {
00341             Local local = (Local) localIt.next();
00342 
00343             if(local.name.equals(name))
00344                 return local;
00345         }
00346 
00347         throw new ca.mcgill.sable.soot.jimple.NoSuchLocalException();
00348     }
00349     public int getLocalCount()
00350     {
00351         return locals.size();
00352     }
00353     /**
00354      * Returns a backed list of locals.
00355      */
00356 
00357     public List getLocals()
00358     {
00359         return locals;
00360     }
00361     public SootMethod getMethod()
00362     {
00363         return method;
00364     }
00365     public StmtList getStmtList()
00366     {
00367         return stmtList;
00368     }
00369     public List getTraps()
00370     {
00371         return traps;
00372     }
00373     public List getUnitBoxes()
00374     {
00375         List stmtBoxes = new ArrayList();
00376 
00377         // Put in all statement boxes from the statements
00378             Iterator stmtIt = stmtList.iterator();
00379 
00380             while(stmtIt.hasNext())
00381             {
00382                 Stmt stmt = (Stmt) stmtIt.next();
00383 
00384                 Iterator boxIt = stmt.getUnitBoxes().iterator();
00385 
00386                 while(boxIt.hasNext())
00387                     stmtBoxes.add(boxIt.next());
00388             }
00389 
00390         // Put in all statement boxes from the trap table
00391         {
00392             Iterator trapIt = traps.iterator();
00393 
00394             while(trapIt.hasNext())
00395             {
00396                 Trap trap = (Trap) trapIt.next();
00397                 stmtBoxes.addAll(trap.getUnitBoxes());
00398             }
00399         }
00400 
00401         return stmtBoxes;
00402     }
00403     /** Temporary patch to get the typing algorithm working.
00404       */
00405       
00406     private void patchForTyping()
00407     {
00408         int localCount = 0;
00409         ListIterator stmtIt = stmtList.listIterator();
00410         Local newObjectLocal = null;
00411         
00412         Transformations.cleanupCode(this);
00413         Transformations.removeUnusedLocals(this);
00414         Transformations.renameLocals(this);
00415         
00416         while(stmtIt.hasNext())
00417         {
00418             Stmt s = (Stmt) stmtIt.next();
00419                     
00420             if(s instanceof AssignStmt)
00421             {
00422                 AssignStmt as = (AssignStmt) s;
00423                 
00424                 if(as.getRightOp() instanceof NewExpr &&
00425                    as.getLeftOp() instanceof Local)
00426                 {
00427                     // Add new local
00428                         Local tmpLocal = Jimple.v().newLocal("tmp" + localCount, 
00429                             UnknownType.v());
00430                         addLocal(tmpLocal);
00431                             
00432                         localCount++;
00433                     
00434                     // Change left hand side of new
00435                         newObjectLocal = (Local) as.getLeftOp();
00436                         as.setLeftOp(tmpLocal);
00437                     
00438                     // Find matching special invoke
00439                     {
00440                         ListIterator matchIt = stmtList.listIterator(stmtIt.nextIndex());
00441                         boolean foundMatch = false;
00442                                
00443                         while(matchIt.hasNext())
00444                         {   
00445                             Stmt r = (Stmt) matchIt.next();
00446                             
00447                             if(r instanceof InvokeStmt)
00448                             {
00449                                InvokeExpr expr = (InvokeExpr) ((InvokeStmt) r).getInvokeExpr();
00450                                 
00451                                 if(expr instanceof SpecialInvokeExpr &&
00452                                     ((SpecialInvokeExpr) expr).getBase() == newObjectLocal)
00453                                 {
00454                                     // Set base of special invoke
00455                                         ((SpecialInvokeExpr) expr).setBase(tmpLocal);
00456                                     
00457                                     // Add copy newObjectLocal = tmpLocal
00458                                     matchIt.add(Jimple.v().newAssignStmt(newObjectLocal,
00459                                         tmpLocal));
00460                                  
00461                                     foundMatch = true;
00462                                     break;       
00463                                 }
00464                             }
00465                         }
00466                         
00467                         if(!foundMatch)
00468                             throw new RuntimeException("unable to patch code"); 
00469                     }
00470                 }
00471             }
00472         }
00473         
00474     }
00475     public void printDebugTo(java.io.PrintWriter out)
00476     {   
00477         StmtBody stmtBody = this; 
00478         StmtList stmtList = stmtBody.getStmtList();
00479         Map stmtToName = new HashMap(stmtList.size() * 2 + 1, 0.7f);
00480         CompleteStmtGraph stmtGraph = new CompleteStmtGraph(stmtList);
00481         
00482         LocalDefs localDefs = new SimpleLocalDefs(stmtGraph);
00483 
00484         /*
00485         LocalUses localUses = new LocalUses(stmtGraph, localDefs);
00486 */
00487         LocalCopies localCopies = new SimpleLocalCopies(stmtGraph);
00488         LiveLocals liveLocals = new SimpleLiveLocals(stmtGraph);
00489         EqualLocals equalLocals = new SimpleEqualLocals(stmtGraph);
00490         
00491         // Create statement name table
00492         {
00493            int labelCount = 0;
00494 
00495             Iterator stmtIt = stmtList.iterator();
00496 
00497             while(stmtIt.hasNext())
00498             {
00499                 Stmt s = (Stmt) stmtIt.next();
00500 
00501                 stmtToName.put(s, new Integer(labelCount++).toString());
00502             }
00503         }
00504 
00505         for(int j = 0; j < stmtList.size(); j++)
00506         {
00507             Stmt s = ((Stmt) stmtList.get(j));
00508 
00509             out.print("    " + stmtToName.get(s) + ": ");
00510 
00511             out.print(s.toBriefString(stmtToName, "        "));
00512             out.print(";");
00513 
00514             /*           
00515             // Print info about live locals
00516             {
00517                 out.print(liveLocals.getLiveLocalsAfter(s));
00518             }*/
00519             /*
00520             // Print info about local copies
00521             {
00522                 out.print(localCopies.getCopiesBefore(s));
00523             }
00524             */
00525             /*
00526             // Print info about local equalities
00527             {
00528                 out.print(equalLocals.getCopiesAt(s));
00529             }
00530 */
00531 
00532              /*
00533              // Print info about uses
00534                 if(s instanceof DefinitionStmt)
00535                 {
00536                     Iterator useIt = localUses.getUsesOf((DefinitionStmt) s).iterator();
00537 
00538                     out.print("   (");
00539 
00540                     while(useIt.hasNext())
00541                     {
00542                         if(k != 0)
00543                             out.print(", ");
00544 
00545                         out.print(stmtToName.get(useIt.next()));
00546                     }
00547 
00548                     out.print(")");
00549                 }
00550             */
00551         /*
00552             // Print info about defs
00553             {
00554                 Iterator boxIt = s.getUseBoxes().iterator();
00555 
00556                 while(boxIt.hasNext())
00557                 {
00558                     ValueBox useBox = (ValueBox) boxIt.next();
00559 
00560                     if(useBox.getValue() instanceof Local)
00561                     {
00562                         Iterator defIt = localDefs.getDefsOfAt((Local) useBox.getValue(), s).iterator();
00563 
00564                         out.print("  " + useBox.getValue() + " = {");
00565 
00566                         while(defIt.hasNext())
00567                         {
00568                             out.print(stmtToName.get((Stmt) defIt.next()));
00569 
00570                             if(defIt.hasNext())
00571                                 out.print(", ");
00572                         }
00573 
00574                         out.print("}");
00575                     }
00576                 }
00577             } 
00578           */
00579             
00580             /*
00581             // Print info about successors
00582             {
00583                 Iterator succIt = stmtGraph.getSuccsOf(s).iterator();
00584 
00585                 out.print("    [");
00586 
00587                 if(succIt.hasNext())
00588                 {
00589                     out.print(stmtToName.get(succIt.next()));
00590 
00591                     while(succIt.hasNext())
00592                     {
00593                         Stmt stmt = (Stmt) succIt.next();
00594 
00595                         out.print(", " + stmtToName.get(stmt));
00596                     }
00597                 }
00598 
00599                 out.print("]");
00600             }
00601                 */
00602             /*
00603             // Print info about predecessors
00604             {
00605                 Stmt[] preds = stmtGraph.getPredsOf(s);
00606 
00607                 out.print("    {");
00608 
00609                 for(int k = 0; k < preds.length; k++)
00610                 {
00611                     if(k != 0)
00612                         out.print(", ");
00613 
00614                     out.print(stmtToName.get(preds[k]));
00615                 }
00616 
00617                 out.print("}");
00618             }
00619             */
00620             out.println();
00621         }
00622 
00623         // Print out exceptions
00624         {
00625             Iterator trapIt = stmtBody.getTraps().iterator();
00626 
00627             while(trapIt.hasNext())
00628             {
00629                 Trap trap = (Trap) trapIt.next();
00630 
00631                 out.println(".catch " + trap.getException().getName() + " from " +
00632                     stmtToName.get(trap.getBeginUnit()) + " to " + stmtToName.get(trap.getEndUnit()) +
00633                     " with " + stmtToName.get(trap.getHandlerUnit()));
00634             }
00635         }
00636     }
00637     void printStatementsInBody(java.io.PrintWriter out, boolean isPrecise)
00638     {
00639         StmtList stmtList = this.getStmtList();
00640 
00641         Map stmtToName = new HashMap(stmtList.size() * 2 + 1, 0.7f);
00642         StmtGraph stmtGraph = new BriefStmtGraph(stmtList);
00643 
00644         // Create statement name table
00645         {
00646             Iterator boxIt = this.getUnitBoxes().iterator();
00647 
00648             Set labelStmts = new HashSet();
00649 
00650             // Build labelStmts
00651             {
00652                 while(boxIt.hasNext())
00653                 {
00654                     StmtBox box = (StmtBox) boxIt.next();
00655                     Stmt stmt = (Stmt) box.getUnit();
00656 
00657                     labelStmts.add(stmt);
00658                 }
00659             }
00660 
00661             // Traverse the stmts and assign a label if necessary
00662             {
00663                 int labelCount = 0;
00664 
00665                 Iterator stmtIt = stmtList.iterator();
00666 
00667                 while(stmtIt.hasNext())
00668                 {
00669                     Stmt s = (Stmt) stmtIt.next();
00670 
00671                     if(labelStmts.contains(s))
00672                         stmtToName.put(s, "label" + (labelCount++));
00673                 }
00674             }
00675         }
00676 
00677         for(int j = 0; j < stmtList.size(); j++)
00678         {
00679             Stmt s = ((Stmt) stmtList.get(j));
00680 
00681             // Put an empty line if the previous node was a branch node, the current node is a join node
00682             //   or the previous statement does not have this statement as a successor, or if
00683             //   this statement has a label on it
00684             {
00685                 if(j != 0)
00686                 {
00687                     Stmt previousStmt = (Stmt) stmtList.get(j - 1);
00688 
00689                     if(stmtGraph.getSuccsOf(previousStmt).size() != 1 ||
00690                         stmtGraph.getPredsOf(s).size() != 1 ||
00691                         stmtToName.containsKey(s))
00692                         out.println();
00693                     else {
00694                         // Or if the previous node does not have this statement as a successor.
00695 
00696                         List succs = stmtGraph.getSuccsOf(previousStmt);
00697 
00698                         if(succs.get(0) != s)
00699                             out.println();
00700 
00701                     }
00702                 }
00703             }
00704 
00705             if(stmtToName.containsKey(s))
00706                 out.println("     " + stmtToName.get(s) + ":");
00707 
00708             if(isPrecise)
00709                 out.print(s.toString(stmtToName, "        "));
00710             else
00711                 out.print(s.toBriefString(stmtToName, "        "));
00712 
00713             out.print(";");
00714             out.println();
00715         }
00716 
00717         // Print out exceptions
00718         {
00719             Iterator trapIt = this.getTraps().iterator();
00720 
00721             if(trapIt.hasNext())
00722                 out.println();
00723 
00724             while(trapIt.hasNext())
00725             {
00726                 Trap trap = (Trap) trapIt.next();
00727 
00728                 out.println("        .catch " + trap.getException().getName() + " from " +
00729                     stmtToName.get(trap.getBeginUnit()) + " to " + stmtToName.get(trap.getEndUnit()) +
00730                     " with " + stmtToName.get(trap.getHandlerUnit()));
00731             }
00732         }
00733     }
00734     public void printTo(java.io.PrintWriter out)
00735     {
00736         printTo(out, 0);
00737     }
00738     public void printTo(PrintWriter out, int printBodyOptions)
00739     {
00740         boolean isPrecise = !PrintJimpleBodyOption.useAbbreviations(printBodyOptions);
00741 
00742         /*
00743         if(PrintJimpleBodyOption.debugMode(printBodyOptions))
00744         {
00745             print_debug(out);
00746             return;
00747         }
00748         */
00749         
00750         //System.out.println("Constructing the graph of " + getName() + "...");
00751 
00752         StmtList stmtList = this.getStmtList();
00753 
00754         Map stmtToName = new HashMap(stmtList.size() * 2 + 1, 0.7f);
00755 
00756         // Print out method name plus parameters
00757         {
00758             StringBuffer buffer = new StringBuffer();
00759 
00760             buffer.append(Modifier.toString(method.getModifiers()));
00761 
00762             if(buffer.length() != 0)
00763                 buffer.append(" ");
00764 
00765             buffer.append(method.getReturnType().toString() + " " + method.getName());
00766             buffer.append("(");
00767 
00768             Iterator typeIt = method.getParameterTypes().iterator();
00769 
00770             if(typeIt.hasNext())
00771             {
00772                 buffer.append(typeIt.next());
00773 
00774                 while(typeIt.hasNext())
00775                 {
00776                     buffer.append(", ");
00777                     buffer.append(typeIt.next());
00778                 }
00779             }
00780 
00781             buffer.append(")");
00782 
00783             out.print("    " + buffer.toString());
00784         }
00785 
00786         out.println();
00787         out.println("    {");
00788 
00789         /*
00790         // Print out local variables
00791         {
00792             Local[] locals = getLocals();
00793 
00794             for(int j = 0; j < locals.length; j++)
00795                 out.println("        " + locals[j].getType().toString() + " " +
00796                     locals[j].getName());
00797         }
00798 
00799         */
00800 
00801         // Print out local variables
00802         {
00803             Map typeToLocalSet = new HashMap(this.getLocalCount() * 2 + 1, 0.7f);
00804 
00805             // Collect locals
00806             {
00807                 Iterator localIt = this.getLocals().iterator();
00808 
00809                 while(localIt.hasNext())
00810                 {
00811                     Local local = (Local) localIt.next();
00812 
00813                     Set localSet;
00814 
00815                     if(typeToLocalSet.containsKey(local.getType().toString()))
00816                         localSet = (Set) typeToLocalSet.get(local.getType().toString());
00817                     else
00818                     {
00819                         localSet = new HashSet();
00820                         typeToLocalSet.put(local.getType().toString(), localSet);
00821                     }
00822 
00823                     localSet.add(local);
00824                 }
00825             }
00826 
00827             // Print locals
00828             {
00829                 Set typeSet = typeToLocalSet.keySet();
00830 
00831                 Object[] types = typeSet.toArray();
00832 
00833                 for(int j = 0; j < types.length; j++)
00834                 {
00835                     String type = (String) types[j];
00836 
00837                     Set localSet = (Set) typeToLocalSet.get(type);
00838                     Object[] locals = localSet.toArray();
00839 
00840                     out.print("        " + type + " ");
00841 
00842                     for(int k = 0; k < locals.length; k++)
00843                     {
00844                         if(k != 0)
00845                             out.print(", ");
00846 
00847                         out.print(((Local) locals[k]).getName());
00848                     }
00849 
00850                     out.println(";");
00851                 }
00852             }
00853 
00854 
00855             if(!typeToLocalSet.isEmpty())
00856                 out.println();
00857         }
00858 
00859         // Print out statements
00860             printStatementsInBody(out, isPrecise);
00861 
00862         out.println("    }");
00863     }
00864     public void redirectJumps(Stmt oldLocation, Stmt newLocation)
00865     {
00866         List boxesPointing = oldLocation.getBoxesPointingToThis();
00867 
00868         Object[] boxes = boxesPointing.toArray();
00869             // important to change this to an array to have a static copy
00870 
00871         for(int i = 0; i < boxes.length; i++)
00872         {
00873             StmtBox box = (StmtBox) boxes[i];
00874 
00875             if(box.getUnit() != oldLocation)
00876                 throw new RuntimeException("Something weird's happening");
00877 
00878             box.setUnit(newLocation);
00879         }
00880 
00881     }
00882     public void removeLocal(Local l) throws IncorrectDeclarerException
00883     {
00884         locals.remove(l);
00885     }
00886     public void removeTrap(Trap t)
00887     {
00888         traps.remove(t);
00889     }
00890     private boolean typingFailed()
00891     {
00892         // Check to see if any locals are untyped
00893         {
00894             Iterator localIt = this.getLocals().iterator();
00895 
00896             while(localIt.hasNext())
00897             {
00898                 Local l = (Local) localIt.next();
00899 
00900                   if(l.getType().equals(UnknownType.v()) ||
00901                     l.getType().equals(ErroneousType.v()))
00902                 {
00903                     return true;
00904                 }
00905             }
00906         }
00907         
00908         return false;
00909     }
00910 }

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