1 cananian 1.1.2.1 // DerivationGenerator.java, created Tue Feb  1 01:31:34 2000 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.IR.Tree;
  5 cananian 1.1.2.1 
  6 cananian 1.1.2.1 import harpoon.ClassFile.HClass;
  7 cananian 1.1.2.1 import harpoon.Analysis.Maps.Derivation.DList;
  8 cananian 1.1.2.1 import harpoon.Analysis.Maps.TypeMap.TypeNotKnownException;
  9 cananian 1.1.2.1 import harpoon.Temp.Temp;
 10 cananian 1.1.2.5 import harpoon.Temp.TempMap;
 11 cananian 1.1.2.1 import harpoon.Util.Util;
 12 cananian 1.1.2.1 
 13 cananian 1.1.2.1 import java.util.HashMap;
 14 cananian 1.1.2.1 import java.util.Iterator;
 15 cananian 1.1.2.1 import java.util.Map;
 16 cananian 1.1.2.1 /**
 17 cananian 1.1.2.1  * <code>DerivationGenerator</code> takes a partial map of
 18 cananian 1.1.2.1  * <code>Tree.Exp</code>s-to-type/derivations and answers
 19 cananian 1.1.2.1  * type/derivation queries as if the complete map were
 20 cananian 1.1.2.1  * present.  In particular, only <code>Tree.TEMP</code>s
 21 cananian 1.1.2.1  * and <code>Tree.MEM</code>s are typically explicitly
 22 cananian 1.1.2.1  * typed in the map; types for the rest of the
 23 cananian 1.1.2.1  * <code>Tree.Exp</code>s can be inferred from these.
 24 cananian 1.1.2.1  * 
 25 cananian 1.1.2.1  * @author  C. Scott Ananian <cananian@alumni.princeton.edu>
 26 cananian 1.4      * @version $Id: DerivationGenerator.java,v 1.4 2002/04/10 03:05:44 cananian Exp $
 27 cananian 1.1.2.1  */
 28 cananian 1.1.2.3 public class DerivationGenerator implements TreeDerivation {
 29 cananian 1.1.2.1     /** private partial type map */
 30 cananian 1.1.2.1     private Map dtM = new HashMap();
 31 cananian 1.1.2.1     
 32 cananian 1.1.2.1     /** Creates a <code>DerivationGenerator</code>. */
 33 cananian 1.1.2.3     public DerivationGenerator() { }
 34 cananian 1.1.2.1 
 35 cananian 1.1.2.1     /** internal structure of type/derivation information */
 36 cananian 1.1.2.1     private static class TypeAndDerivation {
 37 cananian 1.1.2.1         /** non-null for base pointers */
 38 cananian 1.1.2.1         public final HClass type;
 39 cananian 1.1.2.1         /** non-null for derived pointers */ 
 40 cananian 1.1.2.1         public final DList derivation;
 41 cananian 1.1.2.1         /** for some base pointers, indicates the temp containing this type */
 42 cananian 1.1.2.1         public final Temp temp;
 43 cananian 1.1.2.1         // public constructors
 44 cananian 1.1.2.1         TypeAndDerivation(HClass type) { this(type, null, null); }
 45 cananian 1.1.2.1         TypeAndDerivation(DList deriv) { this(null, deriv, null); }
 46 cananian 1.1.2.1         TypeAndDerivation(HClass type, Temp temp) { this(type, null, temp); }
 47 cananian 1.1.2.1         /** private constructor */
 48 cananian 1.1.2.1         private TypeAndDerivation(HClass type, DList derivation, Temp temp) {
 49 cananian 1.3.2.1             assert type!=null ^ derivation!=null;
 50 cananian 1.1.2.1             this.type = type;
 51 cananian 1.1.2.1             this.derivation = derivation;
 52 cananian 1.1.2.1             this.temp = temp;
 53 cananian 1.1.2.1         }
 54 cananian 1.1.2.5         TypeAndDerivation rename(TempMap tm) {
 55 cananian 1.1.2.5             if (this.derivation!=null)
 56 cananian 1.1.2.5                 return new TypeAndDerivation(DList.rename(this.derivation,tm));
 57 cananian 1.1.2.5             if (this.temp!=null && tm!=null)
 58 cananian 1.1.2.5                 return new TypeAndDerivation(this.type, tm.tempMap(this.temp));
 59 cananian 1.1.2.5             // no need to create a new object, as tad's are immutable.
 60 cananian 1.1.2.5             return this;
 61 cananian 1.1.2.5         }
 62 cananian 1.1.2.1     }
 63 cananian 1.1.2.1 
 64 cananian 1.1.2.1     // public interface
 65 cananian 1.1.2.1     public HClass typeMap(Exp exp) throws TypeNotKnownException {
 66 cananian 1.1.2.1         TypeAndDerivation tad = getDT(exp);
 67 cananian 1.1.2.1         if (tad==null) throw new TypeNotKnownException(exp, null);
 68 cananian 1.1.2.1         if (!dtM.containsKey(exp)) dtM.put(exp, tad); // cache this result.
 69 cananian 1.1.2.1         return tad.type;
 70 cananian 1.1.2.1     }
 71 cananian 1.1.2.1     public DList  derivation(Exp exp) throws TypeNotKnownException {
 72 cananian 1.1.2.1         TypeAndDerivation tad = getDT(exp);
 73 cananian 1.1.2.1         if (tad==null) throw new TypeNotKnownException(exp, null);
 74 cananian 1.1.2.1         if (!dtM.containsKey(exp)) dtM.put(exp, tad); // cache this result.
 75 cananian 1.1.2.1         return tad.derivation;
 76 cananian 1.1.2.1     }
 77 cananian 1.1.2.1 
 78 cananian 1.1.2.1     // allow implementations to add explicit type/derivation information
 79 cananian 1.1.2.3     /** Add a mapping from the given <code>Tree.Exp</code> <code>exp</code>
 80 cananian 1.1.2.3      *  to the given <code>HClass</code> <code>type</code> to this
 81 cananian 1.1.2.3      *  <code>DerivationGenerator</code>. */
 82 cananian 1.1.2.3     public void putType(Exp exp, HClass type) {
 83 cananian 1.3.2.1         assert exp!=null && type!=null;
 84 cananian 1.3.2.1         assert !dtM.containsKey(exp);
 85 cananian 1.1.2.1         dtM.put(exp, new TypeAndDerivation(type));
 86 cananian 1.1.2.1     }
 87 cananian 1.1.2.3     /** Add a mapping from the given <code>Tree.Exp</code> <code>exp</code>
 88 cananian 1.1.2.3      *  to the given <code>HClass</code> <code>type</code> to the 
 89 cananian 1.1.2.3      *  <code>DerivationGenerator</code>, indicating that this value lives
 90 cananian 1.1.2.3      *  in <code>Temp</code> <code>temp</code>. */
 91 cananian 1.1.2.3     public void putTypeAndTemp(Exp exp, HClass type, Temp temp) {
 92 cananian 1.3.2.1         assert exp!=null && type!=null && temp!=null;
 93 cananian 1.3.2.1         assert !dtM.containsKey(exp);
 94 cananian 1.1.2.1         dtM.put(exp, new TypeAndDerivation(type, temp));
 95 cananian 1.1.2.1     }
 96 cananian 1.1.2.3     /** Add a mapping from the given <code>Tree.Exp</code> <code>exp</code>
 97 cananian 1.1.2.3      *  to the given <code>Derivation.DList</code> <code>derivation</code>.
 98 cananian 1.1.2.3      */
 99 cananian 1.1.2.3     public void putDerivation(Exp exp, DList derivation) {
100 cananian 1.3.2.1         assert exp!=null && derivation!=null;
101 cananian 1.3.2.1         assert !dtM.containsKey(exp);
102 cananian 1.1.2.1         dtM.put(exp, new TypeAndDerivation(derivation));
103 cananian 1.1.2.4     }
104 cananian 1.1.2.6     /** Transfer typing from one exp to another. */
105 cananian 1.1.2.6     public void update(Exp oldE, Exp newE) {
106 cananian 1.1.2.6         if (dtM.containsKey(oldE))
107 cananian 1.1.2.6             dtM.put(newE, dtM.remove(oldE));
108 cananian 1.1.2.6     }
109 cananian 1.1.2.4     // allow implementations to flush old data from the derivation generator
110 cananian 1.1.2.4     /** Remove all type and derivation mappings for the given
111 cananian 1.1.2.4      *  <code>Tree.Exp</code>. Used for memory management purposes. */
112 cananian 1.1.2.4     public void remove(Exp exp) {
113 cananian 1.1.2.4         dtM.remove(exp);
114 cananian 1.1.2.5     }
115 cananian 1.1.2.5 
116 cananian 1.1.2.5     // provide for cloning.
117 cananian 1.1.2.5     public Tree.CloneCallback cloneCallback(final TreeDerivation oldDeriv) {
118 cananian 1.1.2.5         if (oldDeriv instanceof DerivationGenerator)
119 cananian 1.1.2.5             return cloneCallback((DerivationGenerator)oldDeriv);
120 cananian 1.1.2.5         // okay, just brute-force add all MEM/NAME/TEMP types to map.
121 cananian 1.1.2.5         return new Tree.CloneCallback() {
122 cananian 1.1.2.5             public Tree callback(Tree oldTree, Tree newTree, TempMap tm) {
123 cananian 1.1.2.5                 if (newTree instanceof MEM || newTree instanceof NAME ||
124 cananian 1.1.2.5                     newTree instanceof TEMP) {
125 cananian 1.1.2.5                     Exp oldExp = (Exp) oldTree, newExp = (Exp) newTree;
126 cananian 1.1.2.5                     HClass hc = oldDeriv.typeMap(oldExp);
127 cananian 1.1.2.5                     TypeAndDerivation tad = (hc == null)
128 cananian 1.1.2.5                         ? new TypeAndDerivation(oldDeriv.derivation(oldExp))
129 cananian 1.1.2.5                         : (newExp instanceof TEMP)
130 cananian 1.1.2.5                         ? new TypeAndDerivation(hc, ((TEMP)newExp).temp)
131 cananian 1.1.2.5                         : new TypeAndDerivation(hc);
132 cananian 1.1.2.5                     DerivationGenerator.this.dtM.put(newExp, tad.rename(tm));
133 cananian 1.1.2.5                 }
134 cananian 1.1.2.5                 return newTree;
135 cananian 1.1.2.5             }
136 cananian 1.1.2.5         };
137 cananian 1.1.2.5     }
138 cananian 1.1.2.5     private Tree.CloneCallback cloneCallback(final
139 cananian 1.1.2.5                                              DerivationGenerator oldDeriv) {
140 cananian 1.1.2.5         return new Tree.CloneCallback() {
141 cananian 1.1.2.5             public Tree callback(Tree oldTree, Tree newTree, TempMap tm) {
142 cananian 1.1.2.5                 if (oldDeriv.dtM.containsKey(oldTree)) {
143 cananian 1.1.2.5                     TypeAndDerivation tad =
144 cananian 1.1.2.5                         (TypeAndDerivation) oldDeriv.dtM.get(oldTree);
145 cananian 1.1.2.5                     DerivationGenerator.this.dtM.put(newTree, tad.rename(tm));
146 cananian 1.1.2.5                 }
147 cananian 1.1.2.5                 return newTree;
148 cananian 1.1.2.5             }
149 cananian 1.1.2.5         };
150 cananian 1.1.2.1     }
151 cananian 1.1.2.1 
152 cananian 1.1.2.1     // private interface
153 cananian 1.1.2.1     private TypeAndDerivation getDT(Exp exp) {
154 cananian 1.1.2.1         if (dtM.containsKey(exp)) return (TypeAndDerivation) dtM.get(exp);
155 cananian 1.1.2.1         return new DTVisitor(exp).tad;
156 cananian 1.1.2.1     }
157 cananian 1.1.2.1     private class DTVisitor extends TreeVisitor {
158 cananian 1.1.2.1         public TypeAndDerivation tad;
159 cananian 1.1.2.1         DTVisitor(Exp exp) { exp.accept(this); }
160 cananian 1.3.2.1         public void visit(Tree e) { assert false : ("Can't type: "+e); }
161 cananian 1.1.2.1         public void visit(CONST e) {
162 cananian 1.1.2.1             // e.type()==Type.POINTER means null constant.
163 cananian 1.1.2.1             this.tad = (e.type() != Type.POINTER) ? type2tad(e.type()) : Void;
164 cananian 1.1.2.1         }
165 cananian 1.1.2.1         public void visit(ESEQ e) {
166 cananian 1.1.2.1             this.tad = getDT(e.getExp());
167 cananian 1.1.2.1         }
168 cananian 1.1.2.1         public void visit(MEM e) {
169 cananian 1.3.2.1             assert e.type() != Type.POINTER : "Can't determine type for MEM.";
170 cananian 1.1.2.1             this.tad = type2tad(e.type());
171 cananian 1.1.2.1         }
172 cananian 1.1.2.1         public void visit(NAME e) {
173 cananian 1.1.2.1             // be careful with NAMEs of pre-constructed objects
174 cananian 1.1.2.1             this.tad = Void;
175 cananian 1.1.2.1         }
176 cananian 1.1.2.1         public void visit(BINOP e) {
177 cananian 1.1.2.1             TypeAndDerivation lefttad = getDT(e.getLeft());
178 cananian 1.1.2.1             TypeAndDerivation righttad = getDT(e.getRight());
179 cananian 1.1.2.1             if (e.type() != Type.POINTER)
180 cananian 1.1.2.1                 this.tad = type2tad(e.type());
181 cananian 1.1.2.1             else switch (e.op) { // this is a pointer operation 
182 cananian 1.1.2.1             case Bop.ADD:
183 cananian 1.1.2.8             case Bop.AND: // XXX: not quite right.
184 cananian 1.1.2.1                 this.tad = TADadd(getDT(e.getLeft()), getDT(e.getRight()));
185 cananian 1.1.2.1                 break;
186 cananian 1.1.2.1             default:
187 cananian 1.3.2.1                 assert false : ("Illegal pointer operation: "+e);
188 cananian 1.1.2.1             }
189 cananian 1.1.2.1         }
190 cananian 1.1.2.1         public void visit(UNOP e) {
191 cananian 1.1.2.1             if (e.type() != Type.POINTER)
192 cananian 1.1.2.1                 this.tad = type2tad(e.type());
193 cananian 1.1.2.1             else switch (e.op) { // this is a pointer operation
194 cananian 1.1.2.1             case Uop.NEG:
195 cananian 1.1.2.1                 this.tad = TADnegate(getDT(e.getOperand()));
196 cananian 1.1.2.1                 break;
197 cananian 1.1.2.1             default:
198 cananian 1.3.2.1                 assert false : ("Illegal pointer operation: "+e);
199 cananian 1.1.2.1             }
200 cananian 1.1.2.1         }
201 cananian 1.1.2.1         public void visit(TEMP e) {
202 cananian 1.3.2.1             assert e.type != Type.POINTER : "Can't determine type for TEMP "+e+".";
203 cananian 1.1.2.1             this.tad = type2tad(e.type());
204 cananian 1.1.2.1         }
205 cananian 1.1.2.1     }
206 cananian 1.1.2.1     // common types.
207 cananian 1.1.2.1     private static final TypeAndDerivation 
208 cananian 1.1.2.1         Void = new TypeAndDerivation(HClass.Void),
209 cananian 1.1.2.1         Int =  new TypeAndDerivation(HClass.Int),
210 cananian 1.1.2.1         Long =  new TypeAndDerivation(HClass.Long),
211 cananian 1.1.2.1         Float =  new TypeAndDerivation(HClass.Float),
212 cananian 1.1.2.1         Double =  new TypeAndDerivation(HClass.Double);
213 cananian 1.1.2.1     // utility methods for operating on/generating types and derivations
214 cananian 1.1.2.1     private static TypeAndDerivation type2tad(int ty) {
215 cananian 1.1.2.1         switch(ty) {
216 cananian 1.1.2.1         case Type.INT: return Int;
217 cananian 1.1.2.1         case Type.LONG: return Long;
218 cananian 1.1.2.1         case Type.FLOAT: return Float;
219 cananian 1.1.2.1         case Type.DOUBLE: return Double;
220 cananian 1.1.2.1         case Type.POINTER:
221 cananian 1.1.2.1             throw new RuntimeException("Pointers do not have inherent types");
222 cananian 1.1.2.1         default:
223 cananian 1.1.2.1             throw new RuntimeException("Unknown type!");
224 cananian 1.1.2.1         }
225 cananian 1.1.2.1     }
226 cananian 1.1.2.1     private static DList makeDL(TypeAndDerivation tad) {
227 cananian 1.1.2.1         if (tad.derivation != null) return tad.derivation;
228 cananian 1.1.2.1         // have to derive from base pointer.
229 cananian 1.3.2.1         assert tad.type != null;
230 cananian 1.3.2.1         assert tad.type == HClass.Void || !tad.type.isPrimitive();
231 cananian 1.3.2.1         assert tad.temp != null : "Can't derive type if we don't know temp.";
232 cananian 1.1.2.1         return new DList(tad.temp, true, null);
233 cananian 1.1.2.1     }
234 cananian 1.1.2.1     private static TypeAndDerivation TADadd(TypeAndDerivation lefttad,
235 cananian 1.1.2.1                                             TypeAndDerivation righttad) {
236 cananian 1.1.2.1         // if there's a constant, put it on the right.
237 cananian 1.1.2.6         if (lefttad.type!=null && lefttad.type.isPrimitive() &&
238 cananian 1.1.2.6             !(righttad.type!=null && righttad.type.isPrimitive()))
239 cananian 1.1.2.1             return TADadd(righttad, lefttad);
240 cananian 1.1.2.1         // okay, deal with adding constants (including opaque pointers)
241 cananian 1.1.2.1         if (righttad.type!=null && righttad.type.isPrimitive())
242 cananian 1.1.2.1             if (lefttad.type!=null && lefttad.type.isPrimitive())
243 cananian 1.1.2.1                 return new TypeAndDerivation(HClass.Void); // opaque!
244 cananian 1.1.2.1             else // we're adding a constant to a base or derived pointer.
245 cananian 1.1.2.1                 return new TypeAndDerivation(makeDL(lefttad));
246 cananian 1.1.2.1         // okay, at this point we have two derived pointers to add.
247 cananian 1.1.2.2         // deal with possible cancellations by adding them the simple
248 cananian 1.1.2.2         // way and then canonicalizing.
249 cananian 1.1.2.2         DList result = makeDL(lefttad);
250 cananian 1.1.2.2         for (DList dl=makeDL(righttad); dl!=null; dl=dl.next)
251 cananian 1.1.2.2             result = new DList(dl.base, dl.sign, result);
252 cananian 1.1.2.2         result = result.canonicalize();
253 cananian 1.1.2.1         return (result==null) ? Void : new TypeAndDerivation(result);
254 cananian 1.1.2.1     }
255 cananian 1.1.2.1     private static TypeAndDerivation TADnegate(TypeAndDerivation tad) {
256 cananian 1.1.2.1         return new TypeAndDerivation(DLnegate(makeDL(tad)));
257 cananian 1.1.2.1     }
258 cananian 1.1.2.1     private static DList DLnegate(DList dl) { // recursive! whee!
259 cananian 1.1.2.1         return (dl==null) ? null :
260 cananian 1.1.2.1             new DList(dl.base, !dl.sign, DLnegate(dl.next));
261 cananian 1.1.2.1     }
262 cananian 1.2     }