Fix tabbing.... Please fix your editors so they do tabbing correctly!!! (Spaces...
[IRC.git] / Robust / src / Analysis / Disjoint / ExistPred.java
1 package Analysis.Disjoint;
2
3 import IR.*;
4 import IR.Flat.*;
5 import java.util.*;
6 import java.io.*;
7
8 ///////////////////////////////////////////
9 //  IMPORTANT
10 //  This class is an immutable Canonical, so
11 //
12 //  0) construct them with a factory pattern
13 //  to ensure only canonical versions escape
14 //
15 //  1) any operation that modifies a Canonical
16 //  is a static method in the Canonical class
17 //
18 //  2) operations that just read this object
19 //  should be defined here
20 //
21 //  3) every Canonical subclass hashCode should
22 //  throw an error if the hash ever changes
23 //
24 ///////////////////////////////////////////
25
26 // Existence predicates in the callee final-result
27 // graph are relevant on the caller's callee-reachable
28 // graph parts.  Any callee result elements with
29 // predicates not satisfied in the caller are not
30 // mapped in the call site transfer function
31
32 public class ExistPred extends Canonical {
33
34   // there are several types of predicates, note that
35   // there are not subclasses of the ExistPred class
36   // because they must be Canonical, no multiple inheritence
37
38   // types: true, node, edge
39   public static final int TYPE_TRUE = 0xa501;
40   public static final int TYPE_NODE = 0x02fd;
41   public static final int TYPE_EDGE = 0x414b;
42   protected int predType;
43
44   // true predicates always evaluate to true
45
46   // A node existence predicate is satisfied if the heap
47   // region ID defining a node is part of the given graph
48   // The reach state may be null--if not the predicate is
49   // satisfied when the edge exists AND it has the state.
50   protected Integer n_hrnID;
51   protected ReachState ne_state;
52
53   // An edge existence predicate is satisfied if the elements
54   // defining an edge are part of the given graph.
55   // The reach state may be null--if not the predicate is
56   // satisfied when the edge exists AND it has the state.
57   // the source of an edge is *either* a variable
58   // node or a heap region node
59   protected TempDescriptor e_tdSrc;
60   protected Integer e_hrnSrcID;
61
62   // the source of an edge might be out of the callee
63   // context but in the caller graph, a normal caller
64   // heap region or variable, OR it might be out of the
65   // caller context ALSO: an ooc node in the caller
66   protected boolean e_srcOutCalleeContext;
67   protected boolean e_srcOutCallerContext;
68
69   // dst is always a heap region
70   protected Integer e_hrnDstID;
71
72   // a reference has a field name and type
73   protected TypeDescriptor e_type;
74   protected String e_field;
75
76   // if the taint is non-null then the predicate
77   // is true only if the edge exists AND has the
78   // taint--ONLY ONE of the ne_state or e_taint
79   // may be non-null for an edge predicate
80   protected Taint e_taint;
81
82
83
84   // a static debug flag for higher abstraction code
85   // to enable debug info at this level
86   public static boolean debug = false;
87
88
89   // to make the true predicate
90   public static ExistPred factory() {
91     ExistPred out = new ExistPred();
92     out = (ExistPred) Canonical.makeCanonical(out);
93     return out;
94   }
95
96   protected ExistPred() {
97     this.predType = TYPE_TRUE;
98     ne_state   = null;
99     n_hrnID    = null;
100     e_tdSrc    = null;
101     e_hrnSrcID = null;
102     e_hrnDstID = null;
103     e_type     = null;
104     e_field    = null;
105     e_taint    = null;
106     e_srcOutCalleeContext = false;
107     e_srcOutCallerContext = false;
108   }
109
110   // node predicates
111   public static ExistPred factory(Integer hrnID,
112                                   ReachState state) {
113
114     ExistPred out = new ExistPred(hrnID, state);
115
116     out = (ExistPred) Canonical.makeCanonical(out);
117     return out;
118   }
119
120   protected ExistPred(Integer hrnID,
121                       ReachState state) {
122     assert hrnID != null;
123     this.n_hrnID  = hrnID;
124     this.ne_state = state;
125     this.predType = TYPE_NODE;
126     e_tdSrc    = null;
127     e_hrnSrcID = null;
128     e_hrnDstID = null;
129     e_type     = null;
130     e_field    = null;
131     e_taint    = null;
132     e_srcOutCalleeContext = false;
133     e_srcOutCallerContext = false;
134   }
135
136   // edge predicates
137   public static ExistPred factory(TempDescriptor tdSrc,
138                                   Integer hrnSrcID,
139                                   Integer hrnDstID,
140                                   TypeDescriptor type,
141                                   String field,
142                                   ReachState state,
143                                   Taint taint,
144                                   boolean srcOutCalleeContext,
145                                   boolean srcOutCallerContext) {
146
147     ExistPred out = new ExistPred(tdSrc,
148                                   hrnSrcID,
149                                   hrnDstID,
150                                   type,
151                                   field,
152                                   state,
153                                   taint,
154                                   srcOutCalleeContext,
155                                   srcOutCallerContext);
156
157     out = (ExistPred) Canonical.makeCanonical(out);
158     return out;
159   }
160
161   protected ExistPred(TempDescriptor tdSrc,
162                       Integer hrnSrcID,
163                       Integer hrnDstID,
164                       TypeDescriptor type,
165                       String field,
166                       ReachState state,
167                       Taint taint,
168                       boolean srcOutCalleeContext,
169                       boolean srcOutCallerContext) {
170
171     assert(tdSrc == null) || (hrnSrcID == null);
172     assert hrnDstID != null;
173     assert type     != null;
174     assert(state == null) || (taint == null);
175
176     // fields can be null when the edge is from
177     // a variable node to a heap region!
178
179     this.e_srcOutCalleeContext = srcOutCalleeContext;
180     this.e_srcOutCallerContext = srcOutCallerContext;
181
182     assert !(e_srcOutCalleeContext && e_srcOutCallerContext);
183
184     this.e_tdSrc    = tdSrc;
185     this.e_hrnSrcID = hrnSrcID;
186     this.e_hrnDstID = hrnDstID;
187     this.e_type     = type;
188     this.e_field    = field;
189     this.ne_state   = state;
190     this.e_taint    = taint;
191     this.predType   = TYPE_EDGE;
192     n_hrnID = null;
193   }
194
195   // for node or edge, check inputs
196   public static ExistPred factory(Integer hrnID,
197                                   TempDescriptor tdSrc,
198                                   Integer hrnSrcID,
199                                   Integer hrnDstID,
200                                   TypeDescriptor type,
201                                   String field,
202                                   ReachState state,
203                                   Taint taint,
204                                   boolean srcOutCalleeContext,
205                                   boolean srcOutCallerContext) {
206     ExistPred out;
207
208     if( hrnID != null ) {
209       out = new ExistPred(hrnID, state);
210
211     } else {
212       out = new ExistPred(tdSrc,
213                           hrnSrcID,
214                           hrnDstID,
215                           type,
216                           field,
217                           state,
218                           taint,
219                           srcOutCalleeContext,
220                           srcOutCallerContext);
221     }
222
223     out = (ExistPred) Canonical.makeCanonical(out);
224     return out;
225   }
226
227
228
229
230   // only consider the subest of the caller elements that
231   // are reachable by callee when testing predicates--if THIS
232   // predicate is satisfied, return the predicate set of the
233   // element that satisfied it, or null for false
234   public ExistPredSet isSatisfiedBy(ReachGraph rg,
235                                     Set<Integer> calleeReachableNodes
236                                     ) {
237     if( predType == TYPE_TRUE ) {
238       return ExistPredSet.factory(ExistPred.factory() );
239     }
240
241     if( predType == TYPE_NODE ) {
242
243       // first find node
244       HeapRegionNode hrn = rg.id2hrn.get(n_hrnID);
245       if( hrn == null ) {
246         return null;
247       }
248
249       if( !calleeReachableNodes.contains(n_hrnID) ) {
250         return null;
251       }
252
253       // when the state is null we're done!
254       if( ne_state == null ) {
255         return hrn.getPreds();
256
257       } else {
258         // otherwise look for state too
259
260         // TODO: contains OR containsSuperSet OR containsWithZeroes??
261         ReachState stateCaller = hrn.getAlpha().containsIgnorePreds(ne_state);
262
263         if( stateCaller == null ) {
264           return null;
265
266         } else {
267           // it was here, return the predicates on the state!!
268           return stateCaller.getPreds();
269         }
270       }
271
272       // unreachable program point!
273     }
274
275     if( predType == TYPE_EDGE ) {
276
277       // first establish whether the source of the
278       // reference edge exists
279       VariableNode vnSrc = null;
280       if( e_tdSrc != null ) {
281         vnSrc = rg.td2vn.get(e_tdSrc);
282       }
283       HeapRegionNode hrnSrc = null;
284       if( e_hrnSrcID != null ) {
285         hrnSrc = rg.id2hrn.get(e_hrnSrcID);
286       }
287       assert(vnSrc == null) || (hrnSrc == null);
288
289       // the source is not present in graph
290       if( vnSrc == null && hrnSrc == null ) {
291         return null;
292       }
293
294       RefSrcNode rsn;
295       if( vnSrc != null ) {
296         rsn = vnSrc;
297         assert e_srcOutCalleeContext;
298         assert !e_srcOutCallerContext;
299
300       } else {
301
302         assert !(e_srcOutCalleeContext && e_srcOutCallerContext);
303
304         if( e_srcOutCalleeContext ) {
305           if( calleeReachableNodes.contains(e_hrnSrcID) ) {
306             return null;
307           }
308
309         } else if( e_srcOutCallerContext ) {
310           if( !hrnSrc.isOutOfContext() ) {
311             return null;
312           }
313
314         } else {
315
316           if( !calleeReachableNodes.contains(e_hrnSrcID) ) {
317             return null;
318           }
319           if( hrnSrc.isOutOfContext() ) {
320             return null;
321           }
322
323         }
324
325         rsn = hrnSrc;
326       }
327
328       // is the destination present?
329       HeapRegionNode hrnDst = rg.id2hrn.get(e_hrnDstID);
330       if( hrnDst == null ) {
331         return null;
332       }
333
334       if( !calleeReachableNodes.contains(e_hrnDstID) ) {
335         return null;
336       }
337
338       // is there an edge between them with the given
339       // type and field?
340       // TODO: type OR a subtype?
341       RefEdge edge = rsn.getReferenceTo(hrnDst,
342                                         e_type,
343                                         e_field);
344       if( edge == null ) {
345         return null;
346       }
347
348       // when the state and taint are null we're done!
349       if( ne_state == null &&
350           e_taint  == null ) {
351         return edge.getPreds();
352
353       } else if( ne_state != null ) {
354         // otherwise look for state too
355
356         // TODO: contains OR containsSuperSet OR containsWithZeroes??
357         ReachState stateCaller = edge.getBeta().containsIgnorePreds(ne_state);
358
359         if( stateCaller == null ) {
360           return null;
361
362         } else {
363           // it was here, return the predicates on the state!!
364           return stateCaller.getPreds();
365         }
366
367       } else {
368         // otherwise look for taint
369
370         Taint tCaller = edge.getTaints().containsIgnorePreds(e_taint);
371
372         if( tCaller == null ) {
373           return null;
374
375         } else {
376           // it was here, return the predicates on the taint!!
377           return tCaller.getPreds();
378         }
379       }
380
381       // unreachable program point!
382     }
383
384     throw new Error("Unknown predicate type");
385   }
386
387
388
389   public boolean equalsSpecific(Object o) {
390     if( o == null ) {
391       return false;
392     }
393
394     if( !(o instanceof ExistPred) ) {
395       return false;
396     }
397
398     ExistPred pred = (ExistPred) o;
399
400     if( this.predType != pred.predType ) {
401       return false;
402     }
403
404     if( ne_state == null ) {
405       if( pred.ne_state != null ) {
406         return false;
407       }
408     } else if( !ne_state.equals(pred.ne_state) ) {
409       return false;
410     }
411
412     if( n_hrnID == null ) {
413       if( pred.n_hrnID != null ) {
414         return false;
415       }
416     } else if( !n_hrnID.equals(pred.n_hrnID) ) {
417       return false;
418     }
419
420     if( e_tdSrc == null ) {
421       if( pred.e_tdSrc != null ) {
422         return false;
423       }
424     } else if( !e_tdSrc.equals(pred.e_tdSrc) ) {
425       return false;
426     }
427
428     if( e_hrnSrcID == null ) {
429       if( pred.e_hrnSrcID != null ) {
430         return false;
431       }
432     } else {
433       if( !e_hrnSrcID.equals(pred.e_hrnSrcID) ) {
434         return false;
435       }
436       if( e_srcOutCalleeContext != pred.e_srcOutCalleeContext ) {
437         return false;
438       }
439       if( e_srcOutCallerContext != pred.e_srcOutCallerContext ) {
440         return false;
441       }
442     }
443
444     if( e_hrnDstID == null ) {
445       if( pred.e_hrnDstID != null ) {
446         return false;
447       }
448     } else if( !e_hrnDstID.equals(pred.e_hrnDstID) ) {
449       return false;
450     }
451
452     if( e_type == null ) {
453       if( pred.e_type != null ) {
454         return false;
455       }
456     } else if( !e_type.equals(pred.e_type) ) {
457       return false;
458     }
459
460     if( e_field == null ) {
461       if( pred.e_field != null ) {
462         return false;
463       }
464     } else if( !e_field.equals(pred.e_field) ) {
465       return false;
466     }
467
468     if( e_taint == null ) {
469       if( pred.e_taint != null ) {
470         return false;
471       }
472     } else if( !e_taint.equals(pred.e_taint) ) {
473       return false;
474     }
475
476     return true;
477   }
478
479
480   public int hashCodeSpecific() {
481     if( predType == TYPE_TRUE ) {
482       return 1;
483     }
484
485     if( predType == TYPE_NODE ) {
486       int hash = n_hrnID.intValue()*17;
487
488       if( ne_state != null ) {
489         hash ^= ne_state.hashCode();
490       }
491
492       return hash;
493     }
494
495     if( predType == TYPE_EDGE ) {
496       int hash = 0;
497
498       hash += e_type.hashCode()*17;
499
500       if( e_field != null ) {
501         hash += e_field.hashCode()*7;
502       }
503
504       if( e_tdSrc != null ) {
505         hash ^= e_tdSrc.hashCode()*11;
506       } else {
507         hash ^= e_hrnSrcID.hashCode()*11;
508         if( e_srcOutCalleeContext ) {
509           hash ^= 0xf1aeb;
510         }
511         if( e_srcOutCallerContext ) {
512           hash ^= 0x875d;
513         }
514       }
515
516       hash += e_hrnDstID.hashCode();
517
518       if( ne_state != null ) {
519         hash ^= ne_state.hashCode();
520       }
521
522       if( e_taint != null ) {
523         hash ^= e_taint.hashCode();
524       }
525
526       return hash;
527     }
528
529     throw new Error("Unknown predicate type");
530   }
531
532
533   public String toString() {
534     if( predType == TYPE_TRUE ) {
535       return "t";
536     }
537
538     if( predType == TYPE_NODE ) {
539       String s = n_hrnID.toString();
540       if( ne_state != null ) {
541         s += "w"+ne_state;
542       }
543       return s;
544     }
545
546     if( predType == TYPE_EDGE ) {
547       String s = "(";
548
549       if( e_tdSrc != null ) {
550         s += e_tdSrc.toString();
551       } else {
552         s += e_hrnSrcID.toString();
553       }
554
555       if( e_srcOutCalleeContext ) {
556         s += "(ooCLEEc)";
557       }
558
559       if( e_srcOutCallerContext ) {
560         s += "(ooCLERc)";
561       }
562
563       s += "-->"+e_hrnDstID+")";
564
565       if( ne_state != null ) {
566         s += "w"+ne_state;
567       }
568
569       if( e_taint != null ) {
570         s += "w"+e_taint;
571       }
572
573       return s;
574     }
575
576     throw new Error("Unknown predicate type");
577   }
578
579 }