1 cananian 1.1.2.1 // MustParamOracle.java, created Wed Nov  7 15:39:11 2001 by cananian
  2 cananian 1.1.2.1 // Copyright (C) 2000 C. Scott Ananian <cananian@alumni.princeton.edu>
  3 cananian 1.1.2.1 // Licensed under the terms of the GNU GPL; see COPYING for details.
  4 cananian 1.1.2.1 package harpoon.Analysis.Quads;
  5 cananian 1.1.2.1 
  6 cananian 1.1.2.2 import harpoon.ClassFile.HCode;
  7 cananian 1.1.2.2 import harpoon.IR.Quads.HEADER;
  8 cananian 1.1.2.2 import harpoon.IR.Quads.METHOD;
  9 cananian 1.1.2.2 import harpoon.IR.Quads.MOVE;
 10 cananian 1.1.2.2 import harpoon.IR.Quads.PHI;
 11 cananian 1.1.2.2 import harpoon.IR.Quads.Quad;
 12 cananian 1.1.2.2 import harpoon.IR.Quads.QuadVisitor;
 13 cananian 1.1.2.2 import harpoon.IR.Quads.SIGMA;
 14 cananian 1.1.2.2 import harpoon.Temp.Temp;
 15 cananian 1.1.2.2 import harpoon.Util.Util;
 16 cananian 1.1.2.1 
 17 cananian 1.1.2.2 import java.util.Arrays;
 18 cananian 1.1.2.2 import java.util.HashMap;
 19 cananian 1.1.2.2 import java.util.HashSet;
 20 cananian 1.1.2.2 import java.util.Iterator;
 21 cananian 1.1.2.2 import java.util.Map;
 22 cananian 1.1.2.2 import java.util.Set;
 23 cananian 1.1.2.1 
 24 cananian 1.1.2.1 /**
 25 cananian 1.1.2.1  * A <code>MustParamOracle</code> tells you what method variables
 26 cananian 1.1.2.1  * *must* contain the values passed in as parameters to the method.
 27 cananian 1.1.2.1  * This can tell you which values must be the 'this' object, for
 28 cananian 1.1.2.1  * non-static methods, or which values in (say) a field-set
 29 cananian 1.1.2.1  * operation directly correspond to constructor parameters.
 30 cananian 1.1.2.1  * 
 31 cananian 1.1.2.1  * @author  C. Scott Ananian <cananian@alumni.princeton.edu>
 32 cananian 1.4      * @version $Id: MustParamOracle.java,v 1.4 2002/04/10 03:00:59 cananian Exp $
 33 cananian 1.1.2.1  */
 34 cananian 1.1.2.1 public class MustParamOracle {
 35 cananian 1.1.2.1     // could make this an invertibleMap if you want sets.
 36 cananian 1.1.2.1     final Map results = new HashMap();
 37 cananian 1.1.2.1 
 38 cananian 1.1.2.1     /** Returns <code>true</code> iff the given <code>Temp</code> *must*
 39 cananian 1.1.2.1      *  contain the value of some parameter. */
 40 cananian 1.1.2.3     public boolean isMustParam(Temp t) { return results.containsKey(t); }
 41 cananian 1.1.2.1     /** Returns the parameter which the given <code>Temp</code> *must*
 42 cananian 1.1.2.1      *  contain the value of. */
 43 cananian 1.1.2.3     public int whichMustParam(Temp t) {
 44 cananian 1.1.2.3         return ((Integer)results.get(t)).intValue();
 45 cananian 1.1.2.3     }
 46 cananian 1.1.2.4     public String toString() { return results.toString(); }
 47 cananian 1.1.2.1     
 48 cananian 1.1.2.1     /** Creates a <code>MustParamOracle</code> which gives you information
 49 cananian 1.1.2.1      *  on variables in <code>HCode</code> <code>hc</code> (which should
 50 cananian 1.1.2.1      *  be in SSI or SSA form, for best results). */
 51 cananian 1.1.2.1     public MustParamOracle(HCode hc) {
 52 cananian 1.1.2.1         // compute # of method parameters
 53 cananian 1.1.2.1         METHOD method = (METHOD) ((HEADER)hc.getRootElement()).next(1);
 54 cananian 1.1.2.1         int nparam = method.paramsLength();
 55 cananian 1.1.2.1         // for each parameter...
 56 cananian 1.1.2.1         for (int i=0; i<nparam; i++) {
 57 cananian 1.1.2.1             // do analysis.
 58 cananian 1.1.2.1             OracleVisitor ov = new OracleVisitor(hc, i);
 59 cananian 1.1.2.1             // transfer results into more compact form.
 60 cananian 1.1.2.1             Integer paramNum = new Integer(i);
 61 cananian 1.1.2.1             for (Iterator it=ov.paramvars.iterator(); it.hasNext(); ) {
 62 cananian 1.1.2.1                 Object old = results.put((Temp)it.next(), paramNum);
 63 cananian 1.3.2.1                 assert old==null : "temp can't be multiple params!";
 64 cananian 1.1.2.1             }
 65 cananian 1.1.2.1             // and do next.
 66 cananian 1.1.2.1         }
 67 cananian 1.1.2.1         // done!
 68 cananian 1.1.2.1     }
 69 cananian 1.1.2.1 
 70 cananian 1.1.2.1     static class OracleVisitor extends QuadVisitor {
 71 cananian 1.1.2.1         final int which_param; // which parameter are we interested in?
 72 cananian 1.1.2.1         /** an array of sets: one for each method parameter.  the sets
 73 cananian 1.1.2.1          *  contain all variables which 'may' contain the method parameter. */
 74 cananian 1.1.2.1         final Set paramvars = new HashSet();
 75 cananian 1.1.2.1         /** an array of sets, as above.  the sets in this case contain
 76 cananian 1.1.2.1          *  all variables which *may not* contain the method parameter. */
 77 cananian 1.1.2.1         final Set notparamvars = new HashSet();
 78 cananian 1.1.2.1         // the paramvars set minus the notparamvars set is the
 79 cananian 1.1.2.1         // set of variables which *must* contain the method parameter.
 80 cananian 1.1.2.1 
 81 cananian 1.1.2.1         /** The 'relevant' set consists of those quads which change the
 82 cananian 1.1.2.1          *  paramvars or notparamvars sets.  We can save time in our
 83 cananian 1.1.2.1          *  dataflow analysis by only iterating over these. */
 84 cananian 1.1.2.1         final Set relevant = new HashSet();
 85 cananian 1.1.2.1 
 86 cananian 1.1.2.1         OracleVisitor(HCode hc, int which) {
 87 cananian 1.1.2.1             this.which_param = which;
 88 cananian 1.1.2.1             // once through all elements.
 89 cananian 1.1.2.1             for (Iterator it=hc.getElementsI(); it.hasNext(); )
 90 cananian 1.1.2.1                 ((Quad)it.next()).accept(this);
 91 cananian 1.1.2.1             // iterate through relevant elements until the sets stop
 92 cananian 1.1.2.1             // changing size.
 93 cananian 1.1.2.1             int oldsize = 0, size = paramvars.size() + notparamvars.size();
 94 cananian 1.1.2.1             while (size > oldsize) {
 95 cananian 1.1.2.1                 for (Iterator it=relevant.iterator(); it.hasNext(); )
 96 cananian 1.1.2.1                     ((Quad)it.next()).accept(this);
 97 cananian 1.1.2.1                 oldsize = size;
 98 cananian 1.1.2.1                 size = paramvars.size() + notparamvars.size();
 99 cananian 1.1.2.1             }
100 cananian 1.1.2.1             // clean up paramvars set by removing not-param variables.
101 cananian 1.1.2.1             paramvars.removeAll(notparamvars);
102 cananian 1.1.2.1             // done!
103 cananian 1.1.2.1         }
104 cananian 1.1.2.1         // lattice: don't know, this, not-this.  -->move-->
105 cananian 1.1.2.1         // presence in 'not-this' overrides presence in 'this'.
106 cananian 1.1.2.1         // sets can only grow.
107 cananian 1.1.2.1         public void visit(Quad q) {
108 cananian 1.1.2.1             /* look for overwrites, which are always not 'this' */
109 cananian 1.1.2.1             notparamvars.addAll(q.defC());
110 cananian 1.1.2.1         }
111 cananian 1.1.2.1         public void visit(METHOD q) {
112 cananian 1.1.2.1             // param 'which' is 'param'; all others are 'not-param'
113 cananian 1.1.2.1             for (int i=0; i<q.paramsLength(); i++)
114 cananian 1.1.2.1                 if (i==which_param)
115 cananian 1.1.2.1                     paramvars.add(q.params(i));
116 cananian 1.1.2.1                 else
117 cananian 1.1.2.1                     notparamvars.add(q.params(i));
118 cananian 1.1.2.1         }
119 cananian 1.1.2.1         public void visit(MOVE q) {
120 cananian 1.1.2.1             relevant.add(q);
121 cananian 1.1.2.1             if (paramvars.contains(q.src()) &&
122 cananian 1.1.2.1                 !notparamvars.contains(q.src()))
123 cananian 1.1.2.1                 paramvars.add(q.dst());
124 cananian 1.1.2.1             else
125 cananian 1.1.2.1                 notparamvars.add(q.dst());
126 cananian 1.1.2.1         }
127 cananian 1.1.2.1         public void visit(SIGMA q) {
128 cananian 1.1.2.1             relevant.add(q);
129 cananian 1.1.2.1             // get rid of overwrites.
130 cananian 1.1.2.1             Set s = new HashSet(q.defC());
131 cananian 1.1.2.1             for (int i=0; i<q.numSigmas(); i++)
132 cananian 1.1.2.1                 s.removeAll(Arrays.asList(q.dst(i)));
133 cananian 1.1.2.1             notparamvars.addAll(s);
134 cananian 1.1.2.1             // now look for src==this.
135 cananian 1.1.2.1             for (int i=0; i<q.numSigmas(); i++)
136 cananian 1.1.2.1                 if (notparamvars.contains(q.src(i)))
137 cananian 1.1.2.1                     notparamvars.addAll(Arrays.asList(q.dst(i)));
138 cananian 1.1.2.1                 else if (paramvars.contains(q.src(i)))
139 cananian 1.1.2.1                     // found! add all dst to paramvars.
140 cananian 1.1.2.1                     paramvars.addAll(Arrays.asList(q.dst(i)));
141 cananian 1.1.2.1         }
142 cananian 1.1.2.1         public void visit(PHI q) {
143 cananian 1.1.2.1             relevant.add(q);
144 cananian 1.1.2.1             // phi(x,y) is 'param' iff x *and* y are 'param' and
145 cananian 1.1.2.1             // neither x nor y is *not* 'param'
146 cananian 1.1.2.1             for (int i=0; i<q.numPhis(); i++)
147 cananian 1.1.2.1                 for (int j=0; j<q.arity(); j++)
148 cananian 1.1.2.1                     if (notparamvars.contains(q.src(i, j)))
149 cananian 1.1.2.1                         notparamvars.add(q.dst(i));
150 cananian 1.1.2.1                     else if (paramvars.contains(q.src(i, j)))
151 cananian 1.1.2.1                         paramvars.add(q.dst(i));
152 cananian 1.1.2.1         }
153 cananian 1.1.2.1     }
154 cananian 1.2     }