1 salcianu 1.1.2.1 // TypeInference.java, created Sun Apr  2 14:42:04 2000 by salcianu
  2 cananian 1.1.2.8 // Copyright (C) 2000 Alexandru SALCIANU <salcianu@retezat.lcs.mit.edu>
  3 salcianu 1.1.2.1 // Licensed under the terms of the GNU GPL; see COPYING for details.
  4 salcianu 1.1.2.1 package harpoon.Util.TypeInference;
  5 salcianu 1.1.2.1 
  6 salcianu 1.1.2.1 import java.util.Iterator;
  7 salcianu 1.1.2.1 import java.util.Set;
  8 salcianu 1.1.2.1 import java.util.HashSet;
  9 salcianu 1.1.2.1 
 10 salcianu 1.1.2.1 import java.lang.reflect.Modifier;
 11 salcianu 1.1.2.1 
 12 salcianu 1.1.2.1 import harpoon.ClassFile.HCode;
 13 salcianu 1.1.2.1 import harpoon.ClassFile.HClass;
 14 salcianu 1.1.2.1 import harpoon.ClassFile.HCodeElement;
 15 salcianu 1.1.2.1 import harpoon.ClassFile.HMethod;
 16 salcianu 1.1.2.1 import harpoon.Analysis.PointerAnalysis.PAWorkList;
 17 salcianu 1.1.2.4 import harpoon.Util.DataStructs.Relation;
 18 salcianu 1.1.2.4 import harpoon.Util.DataStructs.LightRelation;
 19 salcianu 1.1.2.1 
 20 salcianu 1.1.2.1 import harpoon.Temp.Temp;
 21 salcianu 1.1.2.1 import harpoon.Util.Util;
 22 salcianu 1.1.2.1 
 23 salcianu 1.1.2.1 import harpoon.Analysis.ReachingDefs;
 24 salcianu 1.1.2.1 import harpoon.Analysis.ReachingDefsImpl;
 25 salcianu 1.1.2.1 
 26 salcianu 1.1.2.1 import harpoon.IR.Quads.Quad;
 27 salcianu 1.1.2.1 import harpoon.IR.Quads.QuadVisitor;
 28 salcianu 1.1.2.1 import harpoon.IR.Quads.HEADER;
 29 salcianu 1.1.2.1 import harpoon.IR.Quads.METHOD;
 30 salcianu 1.1.2.1 import harpoon.IR.Quads.CALL;
 31 bdemsky  1.1.2.7 import harpoon.IR.Quads.COMPONENTOF;
 32 salcianu 1.1.2.1 import harpoon.IR.Quads.MOVE;
 33 bdemsky  1.1.2.7 import harpoon.IR.Quads.INSTANCEOF;
 34 bdemsky  1.1.2.7 import harpoon.IR.Quads.OPER;
 35 salcianu 1.1.2.1 import harpoon.IR.Quads.GET;
 36 salcianu 1.1.2.1 import harpoon.IR.Quads.AGET;
 37 salcianu 1.1.2.1 import harpoon.IR.Quads.NEW;
 38 salcianu 1.1.2.1 import harpoon.IR.Quads.ANEW;
 39 bdemsky  1.1.2.7 import harpoon.IR.Quads.ALENGTH;
 40 salcianu 1.1.2.1 import harpoon.IR.Quads.TYPECAST;
 41 salcianu 1.1.2.1 import harpoon.IR.Quads.CONST;
 42 salcianu 1.1.2.1 
 43 salcianu 1.1.2.1 /**
 44 salcianu 1.1.2.2  * <code>TypeInference</code> is a very simple type inference module.
 45 salcianu 1.1.2.2  It was written to satisfy some immediate needs in the Pointer Analysis
 46 salcianu 1.1.2.2  (mainly determining is a temp could point to an array of non-primitive
 47 salcianu 1.1.2.2  objects (ie not <code>int[]</code>). However, it is very general and can be
 48 salcianu 1.1.2.2  used to compute the types of some arbitrary set of <code>ExactTemp</code>s
 49 salcianu 1.1.2.5  (not necessarily all the <code>Temp</code>s from the body of a method).<br>
 50 salcianu 1.1.2.2  Works for <code>quad-no-ssa</code> only (anyway, it is trivial to write the
 51 salcianu 1.1.2.2  extensions for the other quads).
 52 salcianu 1.1.2.1  * 
 53 cananian 1.1.2.8  * @author  Alexandru SALCIANU <salcianu@retezat.lcs.mit.edu>
 54 cananian 1.5      * @version $Id: TypeInference.java,v 1.5 2004/02/08 03:22:00 cananian Exp $
 55 salcianu 1.1.2.1  */
 56 salcianu 1.1.2.6 public class TypeInference implements java.io.Serializable {
 57 salcianu 1.1.2.2     // switch on the debug messages
 58 salcianu 1.1.2.3     public static boolean DEBUG = false;
 59 salcianu 1.1.2.1 
 60 salcianu 1.1.2.1     /** Creates a <code>TypeInference</code>. This object is
 61 salcianu 1.1.2.2         supposed to provide type information about the <code>ExactTemp</code>s
 62 salcianu 1.1.2.2         from the set <code>ietemps</code>. All these exact temps are
 63 salcianu 1.1.2.2         supposed to be defined in <code>hcode</code>. */
 64 salcianu 1.1.2.2     public TypeInference(HMethod hm, HCode hcode, Set ietemps) {
 65 salcianu 1.1.2.2         analyze(hm, hcode, ietemps);
 66 salcianu 1.1.2.1     }
 67 salcianu 1.1.2.1 
 68 salcianu 1.1.2.2     // the private repositoy of the type information: it is filled in
 69 salcianu 1.1.2.2     // by analyze and read by the query methods.
 70 salcianu 1.1.2.4     private Relation types = new LightRelation();
 71 salcianu 1.1.2.1 
 72 salcianu 1.1.2.2     ///////////////// QUERY METHODS /////////////////////////////
 73 salcianu 1.1.2.2 
 74 salcianu 1.1.2.2     /** Returns the possible types for the temp <code>et.t</code> in the
 75 salcianu 1.1.2.2         quad <code>et.q</code>. This method should be called only for
 76 salcianu 1.1.2.2         <code>ExactTemp</code> that were in the <code>ietemps</code> set
 77 salcianu 1.1.2.2         passed to the constructor of <code>this</code> object. */
 78 salcianu 1.1.2.1     public Set getType(ExactTemp et){
 79 salcianu 1.1.2.4         return types.getValues(et);
 80 salcianu 1.1.2.1     }
 81 salcianu 1.1.2.1 
 82 salcianu 1.1.2.2     /** Checks whether the temp <code>et.t</code> in instruction
 83 salcianu 1.1.2.2         <code>et.q</code> points to an array of non-primitive type
 84 salcianu 1.1.2.2         components (ie non an <code>int[]</code>. This is useful in the
 85 salcianu 1.1.2.2         PointerAnalysis stuff to see if an <code>AGET</code> deserves
 86 salcianu 1.1.2.2         to be introduced (and possibly a new <code>LOAD</code> node). */
 87 salcianu 1.1.2.1     public boolean isArrayOfNonPrimitives(ExactTemp et){
 88 salcianu 1.1.2.1         Set set = getType(et);
 89 salcianu 1.1.2.1 
 90 cananian 1.5             for(Object hclassO : getType(et)){
 91 cananian 1.5                 HClass hclass = (HClass) hclassO;
 92 salcianu 1.1.2.2             HClass comp  = hclass.getComponentType();
 93 salcianu 1.1.2.2             if(comp == null) continue;
 94 salcianu 1.1.2.2             if(DEBUG)
 95 salcianu 1.1.2.2                 System.out.println("Type of component of " + et + ":" +
 96 salcianu 1.1.2.2                                    comp);
 97 salcianu 1.1.2.2             if(!comp.isPrimitive())
 98 salcianu 1.1.2.1                 return true;
 99 salcianu 1.1.2.1         }
100 salcianu 1.1.2.1 
101 salcianu 1.1.2.1         return false;
102 salcianu 1.1.2.1     }
103 salcianu 1.1.2.1     ///////////////// QUERY METHODS END //////////////////////////
104 salcianu 1.1.2.1     
105 salcianu 1.1.2.1     ReachingDefs rdef = null;
106 salcianu 1.1.2.1 
107 salcianu 1.1.2.2     // W is the worklist used for type inference. At any moment, it contains
108 salcianu 1.1.2.2     // ExactTemps whose possible types may have changed.
109 salcianu 1.1.2.2     PAWorkList W = null; 
110 salcianu 1.1.2.2     // The dependency relation: et1 -> et2 if the type of et1 influences
111 salcianu 1.1.2.2     // the type of et2. Generic type: Relation<ExactTemp, ExactTemp>
112 salcianu 1.1.2.1     Relation dependencies = null;
113 salcianu 1.1.2.1 
114 salcianu 1.1.2.2     private void analyze(HMethod hm, HCode hcode, Set ietemps){
115 salcianu 1.1.2.2         W    = new PAWorkList(); 
116 salcianu 1.1.2.1         rdef = new ReachingDefsImpl(hcode);
117 salcianu 1.1.2.4         dependencies  = new LightRelation(); 
118 salcianu 1.1.2.1 
119 salcianu 1.1.2.2         fill_in_dep_and_W(ietemps);
120 salcianu 1.1.2.1         
121 salcianu 1.1.2.2         if(DEBUG){
122 salcianu 1.1.2.2             System.out.println("DEPENDENCIES:");
123 salcianu 1.1.2.2             System.out.println(dependencies);
124 salcianu 1.1.2.2         }
125 salcianu 1.1.2.2 
126 salcianu 1.1.2.1         HEADER header = (HEADER) hcode.getRootElement();
127 salcianu 1.1.2.1         METHOD method = (METHOD) header.next(1);
128 salcianu 1.1.2.1         set_parameter_types(hm, method);
129 salcianu 1.1.2.2         
130 salcianu 1.1.2.2         if(DEBUG){
131 salcianu 1.1.2.2             System.out.println("PARAMETER TYPES:");
132 salcianu 1.1.2.2             System.out.println(types);
133 salcianu 1.1.2.2         }
134 salcianu 1.1.2.1 
135 salcianu 1.1.2.1         compute_types();
136 salcianu 1.1.2.1 
137 salcianu 1.1.2.2         if(DEBUG){
138 salcianu 1.1.2.2             System.out.println("COMPUTED TYPES:");
139 salcianu 1.1.2.2             System.out.println(types);
140 salcianu 1.1.2.2         }
141 salcianu 1.1.2.2 
142 salcianu 1.1.2.2         compute_interesting_types(ietemps);
143 salcianu 1.1.2.2 
144 salcianu 1.1.2.2         if(DEBUG){
145 salcianu 1.1.2.2             System.out.println("THE FINAL TYPES OF THE INTERESTING TEMPS:");
146 salcianu 1.1.2.2             System.out.println(types);
147 salcianu 1.1.2.2         }
148 salcianu 1.1.2.1 
149 salcianu 1.1.2.1         // enable the GC
150 salcianu 1.1.2.2         W    = null;
151 salcianu 1.1.2.1         rdef = null;
152 salcianu 1.1.2.1         dependencies = null;
153 salcianu 1.1.2.1     }
154 salcianu 1.1.2.1 
155 salcianu 1.1.2.1 
156 salcianu 1.1.2.2     private void fill_in_dep_and_W(Set ietemps){
157 salcianu 1.1.2.1 
158 salcianu 1.1.2.2         // Inner classes cannot access non-final local variables
159 salcianu 1.1.2.2         // we work around this through this wrapper hack: the wrapper
160 salcianu 1.1.2.2         // is final, but we can modify its fields!
161 salcianu 1.1.2.2         class Wrapper{
162 salcianu 1.1.2.2             ExactTemp et;
163 salcianu 1.1.2.2         };
164 salcianu 1.1.2.2         final Wrapper wrapper = new Wrapper();
165 salcianu 1.1.2.2 
166 salcianu 1.1.2.2         // Used in the dependencies detection: contains the ExactTemps
167 salcianu 1.1.2.2         // already seen, which have been put in the worrklist (and maybe
168 salcianu 1.1.2.2         // even processed).
169 salcianu 1.1.2.2         final Set seen      = new HashSet();
170 salcianu 1.1.2.2         // W2 is the worklist for finding the dependencies between
171 salcianu 1.1.2.2         // ExactTemps. AT any moment, it contains ExactTemps whose
172 salcianu 1.1.2.2         // dependencies have not been explored yet.
173 salcianu 1.1.2.1         final PAWorkList W2 = new PAWorkList();
174 salcianu 1.1.2.1 
175 cananian 1.5             for(Object etO : ietemps){
176 cananian 1.5                 ExactTemp et = (ExactTemp) etO;
177 salcianu 1.1.2.1 
178 cananian 1.5                 for (Object quadO : rdef.reachingDefs(et.q, et.t)){
179 cananian 1.5                     Quad quad = (Quad) quadO;
180 salcianu 1.1.2.1                 ExactTemp et_def = new ExactTemp(quad, et.t);
181 salcianu 1.1.2.1                 if(seen.add(et_def))
182 salcianu 1.1.2.1                     W2.add(et_def);
183 salcianu 1.1.2.1             }
184 salcianu 1.1.2.1         }
185 salcianu 1.1.2.1 
186 salcianu 1.1.2.2         // quad visitor for detecting the dependencies between ExactTemp types
187 salcianu 1.1.2.1         final QuadVisitor dep_detector = new QuadVisitor(){
188 bdemsky  1.1.2.7                 public void visit(MOVE q) {
189 salcianu 1.1.2.1                     put_deps(q, q.src());
190 salcianu 1.1.2.1                 }
191 salcianu 1.1.2.1                 
192 bdemsky  1.1.2.7                 public void visit(AGET q) {
193 salcianu 1.1.2.1                     put_deps(q, q.objectref());
194 salcianu 1.1.2.1                 }
195 bdemsky  1.1.2.7 
196 bdemsky  1.1.2.7                 public void visit(ALENGTH q) {
197 bdemsky  1.1.2.7                     types.add(wrapper.et, HClass.Int);
198 bdemsky  1.1.2.7                     W.add(wrapper.et);
199 bdemsky  1.1.2.7                 }
200 bdemsky  1.1.2.7 
201 bdemsky  1.1.2.7                 public void visit(COMPONENTOF q) {
202 bdemsky  1.1.2.7                     types.add(wrapper.et, HClass.Boolean);
203 bdemsky  1.1.2.7                     W.add(wrapper.et);
204 bdemsky  1.1.2.7                 }
205 bdemsky  1.1.2.7 
206 bdemsky  1.1.2.7                 public void visit(INSTANCEOF q) {
207 bdemsky  1.1.2.7                     types.add(wrapper.et, HClass.Boolean);
208 bdemsky  1.1.2.7                     W.add(wrapper.et);
209 bdemsky  1.1.2.7                 }
210 salcianu 1.1.2.1             
211 salcianu 1.1.2.1                 public void visit(CALL q){
212 salcianu 1.1.2.1                     types.add(wrapper.et, q.method().getReturnType());
213 salcianu 1.1.2.1                     W.add(wrapper.et);
214 salcianu 1.1.2.1                 }
215 salcianu 1.1.2.1 
216 salcianu 1.1.2.1                 public void visit(NEW q){
217 salcianu 1.1.2.1                     types.add(wrapper.et, q.hclass());
218 salcianu 1.1.2.1                     W.add(wrapper.et);
219 salcianu 1.1.2.1                 }
220 salcianu 1.1.2.1                 
221 bdemsky  1.1.2.7                 public void visit(OPER q) {
222 bdemsky  1.1.2.7                     types.add(wrapper.et, q.evalType());
223 bdemsky  1.1.2.7                     W.add(wrapper.et);
224 bdemsky  1.1.2.7                 }
225 bdemsky  1.1.2.7 
226 salcianu 1.1.2.1                 public void visit(ANEW q){
227 salcianu 1.1.2.1                     types.add(wrapper.et, q.hclass());
228 salcianu 1.1.2.1                     W.add(wrapper.et);
229 salcianu 1.1.2.1                 }
230 salcianu 1.1.2.1                 
231 salcianu 1.1.2.1                 public void visit(TYPECAST q){
232 salcianu 1.1.2.1                     types.add(wrapper.et, q.hclass());
233 salcianu 1.1.2.1                     W.add(wrapper.et);
234 salcianu 1.1.2.1                 }
235 salcianu 1.1.2.1             
236 salcianu 1.1.2.1                 public void visit(GET q){
237 salcianu 1.1.2.1                     types.add(wrapper.et, q.field().getType());
238 salcianu 1.1.2.1                     W.add(wrapper.et);
239 salcianu 1.1.2.1                 }
240 salcianu 1.1.2.1                 
241 salcianu 1.1.2.1                 public void visit(METHOD q){
242 salcianu 1.1.2.2                     // do nothing; the parameters (defined in METHOD)
243 salcianu 1.1.2.2                     // are treated in set_parameter_types
244 salcianu 1.1.2.1                 }
245 salcianu 1.1.2.1                 
246 salcianu 1.1.2.1                 public void visit(CONST q){
247 salcianu 1.1.2.1                     types.add(wrapper.et, q.type());
248 salcianu 1.1.2.1                     W.add(wrapper.et);
249 salcianu 1.1.2.1                 }
250 salcianu 1.1.2.1                 
251 salcianu 1.1.2.1                 public void visit(Quad q){
252 cananian 1.3.2.1                     assert false : "Untreated quad " + q;
253 salcianu 1.1.2.1                 }
254 salcianu 1.1.2.1 
255 salcianu 1.1.2.1                 public void put_deps(Quad q, Temp t){
256 cananian 1.5                         for(Object qdefO : rdef.reachingDefs(q,t)){
257 cananian 1.5                             Quad qdef = (Quad) qdefO;
258 salcianu 1.1.2.1                         ExactTemp et_def = new ExactTemp(qdef,t);
259 salcianu 1.1.2.2                         dependencies.add(et_def, wrapper.et);
260 salcianu 1.1.2.1                         if(seen.add(et_def))
261 salcianu 1.1.2.1                             W2.add(et_def);
262 salcianu 1.1.2.1                     }
263 salcianu 1.1.2.1                 }
264 salcianu 1.1.2.1                 
265 salcianu 1.1.2.1             };
266 salcianu 1.1.2.1 
267 salcianu 1.1.2.2         // Worklist algorithm for detecting the depenmdencies between
268 salcianu 1.1.2.2         // ExactTemp types.
269 salcianu 1.1.2.1         while(!W2.isEmpty()){
270 salcianu 1.1.2.1             ExactTemp et = (ExactTemp) W2.remove();
271 salcianu 1.1.2.2             // Invariant: et.t is defined by et.q
272 salcianu 1.1.2.1             wrapper.et = et;
273 salcianu 1.1.2.1             et.q.accept(dep_detector);
274 salcianu 1.1.2.1         }
275 salcianu 1.1.2.1 
276 salcianu 1.1.2.1     }
277 salcianu 1.1.2.1 
278 salcianu 1.1.2.1     // set the types for the arguments of the method
279 salcianu 1.1.2.1     private void set_parameter_types(HMethod hm, METHOD method){
280 salcianu 1.1.2.2         // all parameter types
281 salcianu 1.1.2.1         HClass[] aptypes = null;
282 salcianu 1.1.2.2         // declared parameter types (no "this" parameter here)
283 salcianu 1.1.2.2         HClass[] dptypes = hm.getParameterTypes();
284 salcianu 1.1.2.1 
285 salcianu 1.1.2.1         if(Modifier.isStatic(hm.getModifiers()))
286 salcianu 1.1.2.2             aptypes = dptypes;
287 salcianu 1.1.2.1         else{
288 salcianu 1.1.2.2             // non-static methods have a hidden parameter: "this"
289 salcianu 1.1.2.2             aptypes = new HClass[dptypes.length + 1];
290 salcianu 1.1.2.1             aptypes[0] = hm.getDeclaringClass();
291 salcianu 1.1.2.2             for(int i = 0; i < dptypes.length; i++)
292 salcianu 1.1.2.2                 aptypes[i+1] = dptypes[i];
293 salcianu 1.1.2.1         }
294 salcianu 1.1.2.1 
295 salcianu 1.1.2.1         Temp[] params = method.params();
296 cananian 1.3.2.1         assert aptypes.length == params.length : " set_parameter_types is broken";
297 salcianu 1.1.2.1 
298 salcianu 1.1.2.1         for(int i = 0; i < params.length; i++){
299 salcianu 1.1.2.1             ExactTemp et = new ExactTemp(method, params[i]);
300 salcianu 1.1.2.1             types.add(et, aptypes[i]);
301 salcianu 1.1.2.1             W.add(et);
302 salcianu 1.1.2.1         }
303 salcianu 1.1.2.1     }
304 salcianu 1.1.2.1 
305 salcianu 1.1.2.2     // do worklist algorithm to propagate our type information. By this
306 salcianu 1.1.2.2     // time, W should contain all teh ExactTemps whose types are trivial to
307 salcianu 1.1.2.2     // determine: the parameters, destination of NEW, ANEW, TYPECAST, GET etc.
308 salcianu 1.1.2.1     private void compute_types(){
309 salcianu 1.1.2.2         // Inner classes cannot access non-final local variables
310 salcianu 1.1.2.2         // we work around this through this wrapper hack: the wrapper
311 salcianu 1.1.2.2         // is final, but we can modify its fields!
312 salcianu 1.1.2.2         class Wrapper2{
313 salcianu 1.1.2.2             ExactTemp et1;
314 salcianu 1.1.2.2             ExactTemp et2;
315 salcianu 1.1.2.2         };
316 salcianu 1.1.2.2         final Wrapper2 wrapper2 = new Wrapper2();
317 salcianu 1.1.2.2 
318 salcianu 1.1.2.2         // quad visitor for propagating the type information:
319 salcianu 1.1.2.2         // MOVE and AGET are the only ones that remained, for all the
320 salcianu 1.1.2.2         // other interesting quads it is trivial to determine the types
321 salcianu 1.1.2.2         // of their destination Temps.
322 salcianu 1.1.2.1         QuadVisitor type_calculator = new QuadVisitor(){
323 salcianu 1.1.2.1 
324 salcianu 1.1.2.1                 public void visit(MOVE q){
325 salcianu 1.1.2.1                     boolean modified = false;
326 salcianu 1.1.2.1 
327 cananian 1.5                         for(Object hclassO : types.getValues(wrapper2.et1)){
328 cananian 1.5                             HClass hclass = (HClass) hclassO;
329 salcianu 1.1.2.1                         if(types.add(wrapper2.et2, hclass))
330 salcianu 1.1.2.1                             modified = true;
331 salcianu 1.1.2.1                     }
332 salcianu 1.1.2.1 
333 salcianu 1.1.2.1                     if(modified) W.add(wrapper2.et2);
334 salcianu 1.1.2.1                 }
335 salcianu 1.1.2.1                 
336 salcianu 1.1.2.1                 public void visit(AGET q){
337 salcianu 1.1.2.1                     boolean modified = false;
338 salcianu 1.1.2.1                     
339 cananian 1.5                         for(Object hclassO : types.getValues(wrapper2.et1)){
340 cananian 1.5                             HClass hclass = (HClass) hclassO;
341 salcianu 1.1.2.1                         HClass hcomp = hclass.getComponentType();
342 salcianu 1.1.2.1                         if(hcomp != null)
343 bdemsky  1.1.2.9                             if(types.add(wrapper2.et2, hcomp))
344 salcianu 1.1.2.1                                 modified = true;
345 salcianu 1.1.2.1                     }
346 salcianu 1.1.2.1 
347 salcianu 1.1.2.1                     if(modified) W.add(wrapper2.et2);
348 salcianu 1.1.2.1                 }
349 salcianu 1.1.2.1 
350 salcianu 1.1.2.1                 public void visit(Quad q){
351 cananian 1.3.2.1                     assert false : "untreated quad!";
352 salcianu 1.1.2.1                 }
353 salcianu 1.1.2.1             };
354 salcianu 1.1.2.1 
355 salcianu 1.1.2.1         while(!W.isEmpty()){
356 salcianu 1.1.2.1             ExactTemp et1 = (ExactTemp) W.remove();
357 salcianu 1.1.2.2             wrapper2.et1  = et1;
358 cananian 1.5                 for (Object et2O : dependencies.getValues(et1)) {
359 cananian 1.5                     ExactTemp et2 = (ExactTemp) et2O;
360 salcianu 1.1.2.2                 wrapper2.et2   = et2;
361 salcianu 1.1.2.1                 et2.q.accept(type_calculator);
362 salcianu 1.1.2.1             }
363 salcianu 1.1.2.1         }
364 salcianu 1.1.2.1     }
365 salcianu 1.1.2.1 
366 salcianu 1.1.2.2     // Computes the types of the exact temps from the set ietemps.
367 salcianu 1.1.2.2     private void compute_interesting_types(Set ietemps){
368 salcianu 1.1.2.4         Relation types2 = new LightRelation();
369 salcianu 1.1.2.1 
370 cananian 1.5             for(Object etO : ietemps){
371 cananian 1.5                 ExactTemp et = (ExactTemp) etO;
372 salcianu 1.1.2.1 
373 cananian 1.5                 for(Object qO : rdef.reachingDefs(et.q, et.t)){
374 cananian 1.5                     Quad q = (Quad) qO;
375 salcianu 1.1.2.4                 types2.addAll(et, types.getValues(new ExactTemp(q, et.t)));
376 salcianu 1.1.2.1             }
377 salcianu 1.1.2.1         }
378 salcianu 1.1.2.1 
379 salcianu 1.1.2.1         types = types2;
380 salcianu 1.1.2.1     }
381 salcianu 1.1.2.1 
382 cananian 1.2     }