1 cananian 1.1.2.9  // TreeGrapher2.java, created Sun Jul 16 18:23:48 2000 by cananian
  2 cananian 1.1.2.9  // Copyright (C) 2000 C. Scott Ananian <cananian@alumni.princeton.edu>
  3 cananian 1.1.2.5  // Licensed under the terms of the GNU GPL; see COPYING for details.
  4 duncan   1.1.2.1  package harpoon.IR.Tree;
  5 duncan   1.1.2.1  
  6 cananian 1.1.2.8  import harpoon.ClassFile.HCode;
  7 duncan   1.1.2.1  import harpoon.ClassFile.HCodeEdge; 
  8 duncan   1.1.2.1  import harpoon.ClassFile.HCodeElement; 
  9 duncan   1.1.2.1  import harpoon.IR.Properties.CFGrapher; 
 10 cananian 1.1.2.9  import harpoon.Temp.Label;
 11 duncan   1.1.2.1  import harpoon.Temp.LabelList; 
 12 cananian 1.6      import net.cscott.jutil.Factories;
 13 cananian 1.6      import net.cscott.jutil.GenericMultiMap;
 14 cananian 1.6      import net.cscott.jutil.MultiMap;
 15 duncan   1.1.2.1  import harpoon.Util.Util; 
 16 duncan   1.1.2.1  
 17 cananian 1.1.2.12 import java.util.ArrayList;
 18 duncan   1.1.2.1  import java.util.Collection; 
 19 duncan   1.1.2.1  import java.util.HashMap; 
 20 duncan   1.1.2.1  import java.util.Iterator; 
 21 cananian 1.1.2.12 import java.util.List;
 22 duncan   1.1.2.1  import java.util.Map; 
 23 duncan   1.1.2.1  
 24 duncan   1.1.2.1  /**
 25 duncan   1.1.2.1   * <code>TreeGrapher</code> provides a means to externally associate
 26 cananian 1.1.2.9   * control-flow graph information with elements of a canonical tree.
 27 duncan   1.1.2.1   * 
 28 cananian 1.1.2.9   * @author  C. Scott Ananian <cananian@alumni.princeton.edu>
 29 cananian 1.6       * @version $Id: TreeGrapher.java,v 1.6 2004/02/08 01:55:51 cananian Exp $
 30 duncan   1.1.2.1   */
 31 cananian 1.3.2.2  class TreeGrapher extends CFGrapher<Tree> {
 32 cananian 1.1.2.9      Tree firstElement = null;
 33 cananian 1.3.2.2      List<Tree> lastElements = new ArrayList<Tree>();
 34 cananian 1.3.2.2      final MultiMap<Tree,HCodeEdge<Tree>> predMap =
 35 cananian 1.6              new GenericMultiMap<Tree,HCodeEdge<Tree>>(Factories.<HCodeEdge<Tree>>arrayListFactory());
 36 cananian 1.3.2.2      final MultiMap<Tree,HCodeEdge<Tree>> succMap =
 37 cananian 1.6              new GenericMultiMap<Tree,HCodeEdge<Tree>>(Factories.<HCodeEdge<Tree>>arrayListFactory());
 38 cananian 1.1.2.9     /** Class constructor.  Don't call this directly -- use
 39 cananian 1.1.2.9      *  the getGrapher() method in <code>harpoon.IR.Tree.Code</code> instead.
 40 cananian 1.1.2.9      */ 
 41 cananian 1.1.2.9      TreeGrapher(Code code) {
 42 duncan   1.1.2.1          // Tree grapher only works on canonical trees. 
 43 cananian 1.3.2.1          assert code.getName().equals("canonical-tree");
 44 cananian 1.1.2.10         Edger e = new Edger(code);
 45 cananian 1.1.2.9          // done.
 46 cananian 1.1.2.9      }
 47 cananian 1.3.2.2      public Tree getFirstElement(HCode<Tree> hcode) { return firstElement; }
 48 cananian 1.3.2.2      public Tree[] getLastElements(HCode<Tree> hcode) {
 49 cananian 1.3.2.2          return
 50 cananian 1.1.2.12             lastElements.toArray(new Tree[lastElements.size()]);
 51 cananian 1.1.2.12     }
 52 cananian 1.5          public List<HCodeEdge<Tree>> predC(Tree hce) {
 53 cananian 1.5              return (List<HCodeEdge<Tree>>) predMap.getValues(hce);
 54 cananian 1.3.2.2      }
 55 cananian 1.5          public List<HCodeEdge<Tree>> succC(Tree hce) {
 56 cananian 1.5              return (List<HCodeEdge<Tree>>) succMap.getValues(hce);
 57 cananian 1.3.2.2      }
 58 cananian 1.1.2.9  
 59 cananian 1.1.2.10     /** this class does the real work of the grapher */
 60 cananian 1.1.2.10     private class Edger {
 61 cananian 1.1.2.10         /** maps Temp.Labels to IR.Tree.LABELs */
 62 cananian 1.3.2.2          private final Map<Label,LABEL> labelmap = new HashMap<Label,LABEL>();
 63 cananian 1.1.2.10         /** Look up an IR.Tree.LABEL given a Temp.Label. */
 64 cananian 1.1.2.10         private LABEL lookup(Label l) {
 65 cananian 1.3.2.1              assert labelmap.containsKey(l);
 66 cananian 1.3.2.2              return labelmap.get(l);
 67 cananian 1.1.2.9          }
 68 cananian 1.1.2.10         /** Add a <from, to> edge to the predMap and succMap */
 69 cananian 1.1.2.10         private void addEdge(final Tree from, final Tree to) {
 70 cananian 1.3.2.2              HCodeEdge<Tree> hce = new HCodeEdge<Tree>() {
 71 cananian 1.3.2.2                  public Tree from() { return from; }
 72 cananian 1.3.2.2                  public Tree to() { return to; }
 73 cananian 1.1.2.9                  public String toString() { return "Edge from "+from+" to "+to;}
 74 cananian 1.1.2.9              };
 75 cananian 1.1.2.9              predMap.add(to, hce);
 76 cananian 1.1.2.9              succMap.add(from, hce);
 77 cananian 1.1.2.9          }
 78 cananian 1.1.2.10         /** the constructor does the analysis. */
 79 cananian 1.1.2.10         Edger(Code code) {
 80 cananian 1.1.2.10             // collect labels from tree
 81 cananian 1.1.2.10             TreeVisitor labelv = new TreeVisitor() {
 82 cananian 1.1.2.10                 public void visit(Tree e) { /* no op */ }
 83 cananian 1.1.2.10                 public void visit(LABEL l) { labelmap.put(l.label, l); }
 84 cananian 1.1.2.10             };
 85 cananian 1.3.2.2              for (Iterator<Tree> it=code.getElementsI(); it.hasNext(); )
 86 cananian 1.3.2.2                  it.next().accept(labelv);
 87 cananian 1.1.2.10             // now make all the edges
 88 cananian 1.1.2.10             TreeVisitor edgev = new TreeVisitor() {
 89 cananian 1.1.2.9                  Tree last = null;
 90 cananian 1.1.2.9                  void linkup(Stm s, boolean canFallThrough) {
 91 cananian 1.1.2.9                      if (firstElement==null) firstElement = s;
 92 cananian 1.1.2.9                      if (last!=null) addEdge(last, s);
 93 cananian 1.1.2.9                      last = canFallThrough ? s : null;
 94 cananian 1.1.2.12                     if (succMap.getValues(s).size()==0)
 95 cananian 1.1.2.12                         lastElements.add(s);
 96 cananian 1.1.2.9                  }
 97 cananian 1.1.2.9                  public void visit(Tree t) { /* ignore */ }
 98 cananian 1.1.2.9                  public void visit(Stm s) { linkup(s, true); }
 99 cananian 1.1.2.9                  public void visit(CALL c) {
100 cananian 1.1.2.9                      // edge to handler; also fall-through.
101 cananian 1.1.2.10                     addEdge(c, lookup(c.getHandler().label));
102 cananian 1.1.2.9                      linkup(c, true);
103 cananian 1.1.2.9                  }
104 cananian 1.1.2.9                  public void visit(CJUMP c) {
105 cananian 1.1.2.9                      // edges to iftrue and iffalse; no fall-through.
106 cananian 1.1.2.10                     addEdge(c, lookup(c.iffalse));
107 cananian 1.1.2.10                     addEdge(c, lookup(c.iftrue));
108 cananian 1.1.2.9                      linkup(c, false);
109 cananian 1.1.2.9                  }
110 cananian 1.1.2.9                  public void visit(ESEQ e) {
111 cananian 1.3.2.1                      assert false : "Not in canonical form!";
112 cananian 1.1.2.9                  }
113 cananian 1.1.2.9                  public void visit(JUMP j) {
114 cananian 1.1.2.9                      // edges to targets list. no fall-through.
115 cananian 1.3.2.1                      assert j.targets!=null : "JUMP WITH NO TARGETS!";
116 cananian 1.1.2.9                      for (LabelList ll=j.targets; ll!=null; ll=ll.tail)
117 cananian 1.1.2.10                         addEdge(j, lookup(ll.head));
118 cananian 1.1.2.9                      linkup(j, false);
119 cananian 1.1.2.9                  }
120 cananian 1.1.2.9                  public void visit(RETURN r) {
121 cananian 1.1.2.9                      // no fall-through.
122 cananian 1.1.2.9                      linkup(r, false);
123 cananian 1.1.2.9                  }
124 cananian 1.1.2.9                  public void visit(SEQ s) { /* ignore this guy! */ }
125 cananian 1.1.2.9                  public void visit(THROW t) {
126 cananian 1.1.2.9                      // no fall-through.
127 cananian 1.1.2.9                      linkup(t, false);
128 duncan   1.1.2.1                  }
129 cananian 1.1.2.10             };
130 cananian 1.1.2.9              // iterate in depth-first pre-order:
131 cananian 1.3.2.2              for (Iterator<Tree> it=code.getElementsI(); it.hasNext(); )
132 cananian 1.3.2.2                  it.next().accept(edgev);
133 cananian 1.1.2.10             // done!
134 duncan   1.1.2.1          }
135 duncan   1.1.2.1      }
136 cananian 1.2      }