PIPS
constant-path-utils.c
Go to the documentation of this file.
1 
2 /* This file contains all the operators defining constant paths :
3 
4 CP = Mdodule * Name * Type *Vref.
5 To calculate the lattice PC operators we define these operators first
6 on each of its dimensions.
7 Each dimension represents a lattice with a bottom and a top.
8 
9 
10 */
11 #include <stdlib.h>
12 #include <stdio.h>
13 
14 #include "genC.h"
15 #include "linear.h"
16 
17 #include "ri.h"
18 #include "effects.h"
19 #include "ri-util.h"
20 #include "prettyprint.h" // for debugging
21 #include "effects-util.h"
22 
23 //#include "constants.h"
24 #include "misc.h"
25 #include "text.h"
26 #include "text-util.h"
27 
28 #include "properties.h"
29 
30 #include "effects-generic.h"
31 #include "effects-simple.h"
32 
33 #include "points-to.h"
34 
36 {
39  cell sink = make_cell_reference(r);
40  return sink;
41 }
42 
44 {
47  cell sink = make_cell_reference(r);
48  return sink;
49 }
50 
51 /* assuming source is a reference to a pointer, build the
52  * corresponding sink when the pointer is not initialized, i.e. is
53  * undefined.
54  */
56 {
57  bool type_sensitive_p = !get_bool_property("ALIASING_ACROSS_TYPES");
58  cell sink = cell_undefined;
59  if(type_sensitive_p) {
60  // FI: let's hope we create neither sharing nor memory leak
61  bool to_be_freed_p = true;
62  type t = type_to_pointed_type(cell_to_type(source, &to_be_freed_p));
64  if(to_be_freed_p) free_type(t);
65  }
66  else
67  sink = make_nowhere_cell();
68  return sink;
69 }
70 
71 /* Already exists in points_to_general_algorithm.c, to be removed later...
72  iterate over the lhs_set, if it contains more than an element
73  approximations are set to MAY, otherwise it's set to EXACT
74  Set the sink to anywhere .*/
76 {
86 
88  FOREACH(cell, c, lhs_list) {
90  set_add_element(kill, kill, p);
91  }
92  }
93 
94  /* input - kill */
95  set_difference(input_kill_diff, input, kill);
96 
97  /* if the lhs_set or the rhs set contains more than an element, we
98  set the approximation to MAY. */
99  if((int)gen_length(lhs_list) > 1)// || set_size(rhs_set)>1)
101 
102  /* Computing the gen set*/
103  FOREACH(cell, c, lhs_list) {
104  /* create a new points to with as source the current
105  element of lhs_set and sink the null value .*/
107  entity er = reference_variable(cr);
108  type t = entity_type(er);
110  reference r = make_reference(e, NIL);
111  cell sink = make_cell_reference(r);
112  points_to pt_to = make_points_to(c, sink, a, make_descriptor_none());
113  set_add_element(gen, gen, (void*)pt_to);
114  }
115 
116  set_union(res, gen, input_kill_diff);
117 
118  return res;
119 }
120 
121 
123 {
124  /* lhs_path matches the kill set.*/
134 
135  SET_FOREACH ( points_to, p, input ) {
136  FOREACH ( cell, c, lhs_list ) {
138  set_add_element(kill, kill, p);
139  }
140  }
141 
142  /* input - kill */
143  set_difference(input_kill_diff, input, kill);
144 
145  /* if the lhs_set or the rhs set contains more than an element, we
146  set the approximation to MAY. */
147  if ( (int)gen_length(lhs_list) > 1 )// || set_size(rhs_set)>1)
149 
150  /* Computing the gen set*/
151  FOREACH ( cell, c, lhs_list ) {
152  /* create a new points to with as source the current
153  element of lhs_set and sink the null value .*/
155  reference r = make_reference(e, NIL);
156  cell sink = make_cell_reference(r);
157  points_to pt_to = make_points_to(c, sink, a, make_descriptor_none());
158  set_add_element(gen, gen, (void*)pt_to);
159  }
160  /* gen + input_kill_diff*/
161  set_union(res, gen, input_kill_diff);
162 
163  return res;
164 }
165 
166 
167 /* input : expression e and a set of points_to
168  output : a set of constant paths
169  translates an expression into a set of constant paths
170  by first changing operators like . and -> into
171  p[0](get_memory_path()). Then evaluate this path by using
172  points_toÚrelations already computed (eval_cell_with_points_to()).
173  Finaly construct a set of constant paths according to the list
174  returned by eval_cell_with_points_to().
175 */
177 {
178  list l = NIL;
179  bool changed = false;
180  //effect ef = effect_undefined;
181  //reference r = reference_undefined;
182  cell c = cell_undefined;
183  cell c_new = cell_undefined;
184  //int i;
187  if(array_reference_p(er)) {
188  c = make_cell_reference(er);
189  c_new = simple_cell_to_store_independent_cell(c, &changed);
190  }
191  else {
192  c_new = make_cell_reference(er);
193  }
195  l = CONS(CELL, c_new, NIL);
196 
197  return l;
198 }
199 
200 
201 /* we define operator max fot the lattice Module which has any_module
202  as top and a bottom which is not yet clearly defined (maybe
203  no_module)
204  max_module : Module * Module -> Module
205  Side effects on m1 if we have an anywhere location to return.
206 */
208 {
209  reference r1 = cell_any_reference(m1);
210  reference r2 = cell_any_reference(m2);
211  entity e1 = reference_variable(r1);
212  entity e2 = reference_variable(r2);
213 
215  return m1;
216  else {
217  e1 = entity_all_locations();
218  r1 = make_reference(e1,NIL);
219  m1 = make_cell_reference(r1);
220  }
221  return m1;
222 }
223 /* operator kill for the dimension Module:
224  - modules should be different from any_module otherwise we return
225  false
226  - when modules are different from any_module we test the equality
227  of their names
228  opkill_may_module : Module * Module -> Bool
229  opkill_must_module : Module * Module -> Bool
230 
231 */
232 /* test if a module is the any_module location, to be moved to
233  anywhere_abstract_locations.c later...*/
235 {
236  bool any_module_p;
238 
239  return any_module_p;
240 }
241 
243 {
244  reference r1 = cell_any_reference(m1);
245  reference r2 = cell_any_reference(m2);
246  entity e1 = reference_variable(r1);
247  entity e2 = reference_variable(r2);
248  bool kill_may_p;
249 
250  /* if the lhs or the rhs is a nowhere location or a null/0 value we
251  generate a pips_user_warning */
253  kill_may_p = true;
254  else
255  kill_may_p = same_string_p(entity_name(e1),entity_name(e2));
256 
257  return kill_may_p;
258 }
259 
261 {
262  reference r1 = cell_any_reference(m1);
263  reference r2 = cell_any_reference(m2);
264  entity e1 = reference_variable(r1);
265  entity e2 = reference_variable(r2);
266  bool kill_must_p;
267 
269  kill_must_p = false;
270  else
271  kill_must_p = same_string_p(entity_name(e1),entity_name(e2));
272 
273  return kill_must_p;
274 }
275 
276 
277 /* Operator gen for modules:
278  m1 is the sink, m2 the source (m2 points to m1)
279  opkill_gen_module : Module * Module -> Module
280 
281 */
282 cell op_gen_module(cell m1, __attribute__ ((__unused__))cell m2)
283 {
284  /* we return the module m1 whatever is its type (#any_module,
285  TOP-LEVEL, any_module) */
286  return m1;
287 
288 }
289 
290 /* We define operators for the lattice Name which can be a:
291  -variable of a the program
292  -malloc
293  -NULL /0
294  -STATIC/STACK/DYNAMIC/HEAP/FORMAL
295  -nowhere/anywhere
296 */
297 
298 /* We define the max between 2 names according to the order
299  established by the lattice Name, already done by
300  entity_locations_max() but we have to add a new abstract location
301  for Formal area */
302 
303 /* opkill for the lattice Name tests if 2 names are :
304  -variables of the program then we return the result of the
305  comparison their names.
306  -abstract locations so we return FALSE.
307  Name * Name-> Bool
308 */
309 
311 {
312  reference r1 = cell_any_reference(n1);
313  reference r2 = cell_any_reference(n2);
314  entity e1 = reference_variable(r1);
315  entity e2 = reference_variable(r2);
316  bool kill_may_p;
317 
320  pips_user_error("NULL or ANYWHERE locations can't appear as an lvalue\n");
321 
322  if (entity_abstract_location_p(e2)) {
323  if (entity_all_locations_p(e2))
324  kill_may_p = true;
325  if (entity_abstract_location_p(e1)) {
326  if (entity_all_locations_p(e1))
327  kill_may_p = true;
328  else
329  kill_may_p = same_string_p(entity_name(e1), entity_name(e2));
330  }
331  else {
332  /* if(entity_malloc_p(e2)) kill_may_p = false// function
333  entity_malloc_p() have to be defined and different from
334  entity_heap_location_p() */
336  r1 = make_reference(e1,NIL);
337  n1 = make_cell_reference(r1);
338  kill_may_p = opkill_may_name(n1, n2);
339  }
340  }
341  else if ( entity_abstract_location_p(e1) ) {
342  if (entity_all_locations_p(e1))
343  kill_may_p = true;
344  else {
345  /* if(entity_malloc_p(e1)) kill_may_p = true// function
346  entity_malloc_p() have to be defined and different from
347  entity_heap_location_p() */
349  r2 = make_reference(e2,NIL);
350  n2 = make_cell_reference(r2);
351  kill_may_p = opkill_may_name(n1, n2);
352  }
353  }
354  else
355  kill_may_p = same_string_p(entity_name(e1), entity_name(e2));
356 
357  return kill_may_p ;
358 }
359 
360 
362 {
363  reference r1 = cell_any_reference(n1);
364  reference r2 = cell_any_reference(n2);
365  entity e1 = reference_variable(r1);
366  entity e2 = reference_variable(r2);
367  bool kill_must_p;
368 
371  pips_user_error("NULL or ANYWHERE locations can't appear as an lvalue\n");
372 
373  if (entity_abstract_location_p(e2)) {
374  if (entity_all_locations_p(e2))
375  kill_must_p = false;
376  if (entity_abstract_location_p(e1)) {
377  if(entity_all_locations_p(e1))
378  kill_must_p = false;
379  else
380  kill_must_p = same_string_p(entity_name(e1), entity_name(e2));
381  }
382  else {
383  /* if(entity_malloc_p(e2)) kill_may_p = false// function
384  entity_malloc_p() have to be defined and different from
385  entity_heap_location_p() */
387  r1 = make_reference(e1,NIL);
388  n1 = make_cell_reference(r1);
389  kill_must_p = opkill_may_name(n1, n2);
390  }
391  }
392  else if ( entity_abstract_location_p(e1) ) {
393  if (entity_all_locations_p(e1))
394  kill_must_p = false;
395  else {
396  /* if(entity_malloc_p(e1)) kill_may_p = true// function
397  entity_malloc_p() have to be defined and different from
398  entity_heap_location_p() */
400  r2 = make_reference(e2,NIL);
401  n2 = make_cell_reference(r2);
402  kill_must_p = opkill_may_name(n1, n2);
403  }
404  }
405  else
406  kill_must_p = same_string_p(entity_name(e1), entity_name(e2));
407 
408  return kill_must_p ;
409 }
410 
412 {
413  if (!type_unknown_p(t1) && ! type_unknown_p(t2) && type_equal_p(t1,t2))
414  return t1;
415  else {
416  type t = MakeTypeUnknown();
417  return t;
418  }
419 }
420 
421 
423 {
424  if (!type_unknown_p(t1) && ! type_unknown_p(t2))
425  return type_equal_p(t1,t2);
426  else
427  return false;
428 
429 }
430 
431 /* opkill_must_type is the same as op_kill_may_type...*/
433 {
434  return opkill_may_type(t1,t2);
435 }
436 
438 {
439  if (!type_unknown_p(t1)&& ! type_unknown_p(t2))
440  return t1;
441  else {
442  type t = MakeTypeUnknown();
443  return t;
444  }
445 }
446 
447 /* the same as opgen_may_type*/
449 {
450  return opgen_may_type(t1,t2);
451 }
452 
453 
455 {
458  bool kill_may_p = true;
459 
460  if (cell_reference_p(c1))
461  r1 = cell_reference(c1);
462  else
464  if (cell_reference_p(c2))
465  r2 = cell_reference(c2);
466  else
468 
470  return kill_may_p;
471  else {
472  kill_may_p = reference_equal_p(r1,r2);
473  return kill_may_p;
474  }
475 }
476 
477 
479 {
480  reference r1 = cell_any_reference(c1);
481  reference r2 = cell_any_reference(c2);
482  bool kill_must_p = false;
483 
485  return kill_must_p;
486  else {
487  kill_must_p = reference_equal_p(r1,r2);
488  return kill_must_p;
489  }
490 }
491 
492 
493 /* FI: really weird and unefficient. Also I asummed that vreference
494  was limited to the subscript list... FI->AM: to be checked wrt your
495  dissertation. */
497 {
498  int i = 0;
499  reference r1 = cell_any_reference(c1);
500  reference r2 = cell_any_reference(c2);
501  entity v1 = reference_variable(r1);
502  entity v2 = reference_variable(r2);
503  list sl1 = NIL, sl2 = NIL;
504  // FI: memory leak? generation of a new string?
505  extern const char* entity_minimal_user_name(entity);
506 
507  // FI: why not compare the entities v1==v2?
509  if ( i==0 ) {
510  sl1 = reference_indices(r1);
511  sl2 = reference_indices(r2);
512  for (;i==0 && !ENDP(sl1) && ! ENDP(sl2) ; POP(sl1), POP(sl2)) {
513  expression se1 = EXPRESSION(CAR(sl1));
514  expression se2 = EXPRESSION(CAR(sl2));
516  i = 0;
517  else if (unbounded_expression_p(se1) && expression_constant_p(se2))
518  i = 0;
519  else if (expression_constant_p(se1) && expression_constant_p(se2) ) {
520  int i1 = expression_to_int(se1);
521  int i2 = expression_to_int(se2);
522  i = i2>i1? 1 : (i2<i1? -1 : 0);
523 
524  // FI: this piece of code seems out of place, if i==0, i==0
525  if ( i==0 ) {
526  string s1 = expression_to_string(se1);
527  string s2 = expression_to_string(se2);
528  i = strcmp(s1, s2);
529  }
530  }
531  else if(field_expression_p(se1) && field_expression_p(se2))
532  i = expression_equal_p(se1,se2)? 0 : 1;
533  }
534  }
535 
536  return (i==0? true: false);
537 }
538 
539 /* returns true if c2 must kills c1 because of the subscript expressions
540  *
541  * This function should be rewritten from scratch, with a defined
542  * semantics for "*" as a subscript and possibly a larger use of
543  * expression_equal_p(). Also, we need to specify if the scopes for
544  * each rereference are equal or not.
545  */
547 {
548  int i = 0;
549  reference r1 = cell_any_reference(c1);
550  reference r2 = cell_any_reference(c2);
551  entity v1 = reference_variable(r1);
552  entity v2 = reference_variable(r2);
553  list sl1 = NIL, sl2 = NIL;
554  // FI: memory leak? generation of a new string?
555  extern const char* entity_minimal_user_name(entity);
556 
557  // FI: this step could be assumed performed earlier
559  if (i==0) {
560  sl1 = reference_indices(r1);
561  sl2 = reference_indices(r2);
562  for (;i==0 && !ENDP(sl1) && ! ENDP(sl2) ; POP(sl1), POP(sl2)){
563  expression se1 = EXPRESSION(CAR(sl1));
564  expression se2 = EXPRESSION(CAR(sl2));
566  //i = 0;
567  i = 1;
568  }
569  else if(expression_constant_p(se1) && unbounded_expression_p(se2)){
570  //i = 0; could be true if * is interpreted as "forall"
571  i = 1;
572  }
573  else if (expression_constant_p(se1) && expression_constant_p(se2)){
574  int i1 = expression_to_int(se1);
575  int i2 = expression_to_int(se2);
576  i = i2>i1? 1 : (i2<i1? -1 : 0);
577  if (i==0){ // FI->AM: I do not understand this step
578  string s1 = expression_to_string(se1);
579  string s2 = expression_to_string(se2);
580  i = strcmp(s1, s2);
581  }
582  }
583  else {
584  // FI->AM: very dangerous; only true if both references appear
585  // exactly in the same scope; and "*" were not dealt with!
587  i = 1;
588  else {
589  i = expression_equal_p(se1, se2)? 0 : 1;
590  }
591  }
592  }
593  }
594 
595  return (i==0? true: false);
596 }
597 
598 
599 
600 
602 {
603  bool kill_may_p;
604  reference r1 = cell_any_reference(c1);
605  reference r2 = cell_any_reference(c2);
606  type t1 = type_undefined;
607  type t2 = type_undefined;
608  entity v1 = reference_variable(r1);
609  entity v2 = reference_variable(r2);
610  bool type_equal_p = true;
611 
612  if (! type_area_p(entity_type(v1)) && !type_area_p(entity_type(v2))){
613  bool to_be_freed1, to_be_freed2;
614  t1 = points_to_reference_to_type(r1,&to_be_freed1);
615  t2 = points_to_reference_to_type(r2,&to_be_freed2);
616  type_equal_p = opkill_may_type(t1,t2);
617  if(to_be_freed1) free_type(t1);
618  if(to_be_freed2) free_type(t2);
619  }
620  kill_may_p = opkill_may_module(c1,c2) && opkill_may_name(c1,c2) &&
622 
623  return kill_may_p;
624 }
625 
626 /* returns true if c2 kills c1 */
628 {
629  bool kill_must_p;
630  reference r1 = cell_any_reference(c1);
631  reference r2 = cell_any_reference(c2);
632  type t1 = type_undefined;
633  type t2 = type_undefined;
634  //entity v1 = reference_variable(r1);
635  //entity v2 = reference_variable(r2);
636  bool equal_p = true;
637  t1 = points_to_reference_to_type(r1,&equal_p);
638  t2 = points_to_reference_to_type(r2, &equal_p);
639  equal_p = type_equal_p(t1,t2);
640  /* if (! type_area_p(entity_type(v1)) && !type_area_p(entity_type(v2))){ */
641  /* if (entity_abstract_location_p(v1)) */
642  /* t1 = entity_type(v1); */
643  /* else */
644  /* t1 = simple_effect_reference_type(r1); */
645  /* if (entity_abstract_location_p(v2)) */
646  /* t2 = entity_type(v2); */
647  /* else */
648  /* t2 = simple_effect_reference_type(r2); */
649  /* type_equal_p = opkill_must_type(t1,t2); */
650  /* } */
651  kill_must_p = opkill_must_module(c1,c2) && opkill_must_name(c1,c2) &&
652  equal_p && opkill_must_vreference(c1,c2);
653 
654  return kill_must_p;
655 }
656 
657 
658 /* Compute the set of arcs in the input points-to relation "in" whose
659  * approximation must be changed from "exact" to "may".
660  *
661  * This set is linked to set "gen_may1", although consistency would be
662  * easier to maintain if only "kill_may" were used to generate the new arcs...
663  *
664  * kill_may = { pt in "in"| exact(pt) ^ \exists l in L conflict(l, source(pt))}
665  *
666  * The restriction to !atomic does not seem useful.
667  */
669 {
672  FOREACH(cell, l, L) {
673  SET_FOREACH(points_to, pt, in_may) {
674  cell pt_source = points_to_source(pt);
675  if (opkill_may_constant_path(pt_source,l)) {
676  points_to npt = make_points_to(pt_source,
677  points_to_sink(pt),
680  set_add_element(kill_may, kill_may, (void*)npt);
681  }
682  }
683  }
684  return kill_may;
685 }
686 
687 
688 /* Generate the subset of arcs that must be removed from the
689  * points-to graph "in".
690  *
691  * Set "in_must" is the subset of set "in" with exact points-to arcs only.
692  *
693  * kill_1 = kill_must = {pt in "in" | source(pt) in L ^ |L|=1 ^ atomic(L) }
694  *
695  * where "atomic(L)" is a short cut for "atomic(l) forall l in L"
696  *
697  * Here, correctly, the atomicity is not checked directly, but
698  * properly, using an operator of the lattice.
699  */
701 {
702  set kill_must = new_simple_pt_map();
703  int nL = (int) gen_length(L);
704 
705  if(nL==1) {
706  cell l = CELL(CAR(L));
707  SET_FOREACH(points_to, s, in) {
709  set_add_element(kill_must, kill_must,(void*)s);
710  }
711  }
712  return kill_must;
713 }
714 ␌
715 /* returns a set which contains all the MAY points to */
717 {
720 
721  SET_FOREACH(points_to, pt, in){
723  set_add_element(in_may, in_may, (void*)pt);
724  }
725  return in_may;
726 }
727 
728 /* returns a set which contains all the EXACT points to */
730 {
733  SET_FOREACH(points_to, pt, in){
735  set_add_element(in_must, in_must, (void*)pt);
736  }
737  return in_must;
738 }
739 ␌
740 /* shoud be moved to expression.c*/
742 {
743  bool address_of_p = false;
744  syntax s = expression_syntax(e);
745  if (syntax_call_p(s)) {
746  if (entity_an_operator_p(call_function(syntax_call(s)), ADDRESS_OF))
747  address_of_p = true;
748  }
749  return address_of_p;
750 }
751 
753 {
755 }
756 
757 /* Should be moved to anywhere_abstract_locations.c */
758 
759 #if 0
760 bool expression_null_locations_p(expression e)
761 {
762  if (expression_reference_p(e)) {
764  return entity_null_locations_p(v);
765  }
766  else
767  return false;
768 }
769 #endif
770 
771 /*
772  * Create a new set of points-to arcs "may" from an input points-to
773  * set "in_may" (in fact, "in"), a list of assigned points-to cells,
774  * L, and a list of value cells, R. In fact, "may" is the set "gen"
775  * for the assignment of R to L.
776  *
777  * The arcs in "may" belongs either to subset "may1", which is derived
778  * from "in_may", or to subset "may2", which is derived from couples
779  * (l,r) in L x R, or to subset "may3", which is derived from couples
780  * (l',r) in L' x R, where L' is the set or lower elements of L. In
781  * other words:
782  *
783  * L'(l) = { l' | for all x<l in CP l'<l and x,=l' }
784  *
785  * This is used for element of pointer arrays.If a[1] is updated, then
786  * a[*] must be updated too. This is generalized to a[*][*]..[*] for
787  * multi-dimensional arrays. No distinction is made for a[1][*] and
788  * a[*][2]. They are not considered and are both replaced by a[*][*].
789  *
790  * For "may1":
791  *
792  * may1 = {pt=(l,r,may) | exists pt'=(l,r,a') in in_may and l in L U L'}
793  *
794  * For "may2":
795  *
796  * may2 = {pt=(l,r,a) | exists l in L, exists r in R,
797  * a=(|L|==1 and |R|==1 and atomic(l) and atomic(r) }
798  *
799  * For "may3":
800  *
801  * may3 = {pt=(l',r,may) | exists l in L, l' in L'(l), exists r in R}
802  *
803  * Hence, may = may1 U may2 U may3.
804  *
805  * Note the disymetry between L and R as far as may3 is concerned. If
806  * a[1] points toward b, then a[*] points toward b. If a points toward
807  * b[1], then we do not generate an arc from a to b[*].
808  *
809  * Note also that "may1" must be consistent with "kill_may" in
810  * list_assignment_to_points_to() in order to generate a consistent
811  * pt_out.
812  */
813 set gen_may_set(list L, list R, set in_may, bool *address_of_p)
814 {
821  int len = (int) gen_length(L);
822 
823  //if(len > 1) {
824  ///* If the source is not precisely known */
825  /* It is easier not to have to maintain the consistency between
826  gen_may1 and kill_may. */
827  if(false) {
828  FOREACH(cell, l, L) {
829  SET_FOREACH(points_to, pt, in_may){
831  //if(!atomic_points_to_cell_p(points_to_source(pt))) {
832  //if(points_to_compare_cell(points_to_source(pt),l)) {
834  // FI: it would be much easier/efficient to modify the approximation of pt
835  // But it is incompatible with the implementation of sets...
840  set_add_element(gen_may1, gen_may1, (void*)npt);
841  //set_del_element(gen_may1, gen_may1, (void*)pt);
842  }
843  // }
844  }
845  }
846  }
847  }
848 
849  // Possibly generate an error for dereferencing an undefined pointer
850  bool error_p =
851  !get_bool_property("POINTS_TO_UNINITIALIZED_POINTER_DEREFERENCING");
852  int lc = (int) gen_length(L);
853  FOREACH(cell, l, L){
855  entity lv = reference_variable(lr);
856  bool null_p = entity_null_locations_p(lv);
857  bool nowhere_p = entity_typed_nowhere_locations_p(lv)
859  string bug = null_p? "a null" : "";
860  bug = nowhere_p? "an undefined" : "";
861  // Can the lhs be accessed?
862  if(null_p || nowhere_p) {
863  // No: two options; either a user_error() for dereferencing an
864  // unitialized pointer or a conversion to anywhere, typed or not
865  // FI: why be tolerant of NULL pointer dereferencing? For may information
866  if(lc==1) {
867  if(error_p)
868  pips_user_error("Dereferencing of %s pointer.\n", bug);
869  else {
870  pips_user_warning("Dereferencing of %s pointer.\n", bug);
871  }
872  }
873  else {
874  pips_user_warning("Possible dereferencing of %s pointer.\n", bug);
875  }
876  type t = entity_type(lv);
878  set gen_l = gen_may_constant_paths(nl, R, in_may, address_of_p, len);
879  set_union(gen_may2, gen_may2, gen_l);
880  }
881  else {
882  // FI: memory leak due to call to call to gen_may_constant_paths()
883  set gen_l = gen_may_constant_paths(l, R, in_may, address_of_p, len);
884  // FI: be careful, the union does not preserve consistency because
885  // the same arc may appear with different approximations
886  set_union(gen_may2, gen_may2, gen_l);
887  // free_set(gen_l);
888  }
889  }
890 
891  set_union(gen_may2, gen_may2, gen_may1);
892  set_union(gen_may2, gen_may2, gen_may3);
893 
894  return gen_may2;
895 }
896 
897 
898 /*
899  * create a set of points-to relations of the form:
900  * element_L -> & element_R, EXACT
901  *
902  * FI: address_of_p does not seem to be updated in this function. Why
903  * pass a pointer? My analysis is wrong if gen_must_constant_paths() updates it
904  *
905  * FI: lots of common points between gen_must_set() and
906  * gen_may_set()... Possible unification?
907  */
908 set gen_must_set(list L, list R, set in_must, bool *address_of_p)
909 {
914  int len = (int) gen_length(L);
915 
916  /* if len > 1 we must iterate over in_must and change all points-to
917  relations having L as lhs into may relations */
918  if(len > 1){
919  FOREACH(cell, l, L){
920  SET_FOREACH(points_to, pt, in_must){
925  set_add_element(gen_must1, gen_must1, (void*)npt);
926  }
927  }
928  }
929  }
930 
931  bool error_p = false; // generate an error for dereferencing an undefined pointer
932  int lc = (int) gen_length(L);
933  FOREACH(cell, l, L){
934  // Can the lhs be accessed?
936  entity lv = reference_variable(lr);
937  bool null_p = entity_null_locations_p(lv);
938  bool nowhere_p = entity_typed_nowhere_locations_p(lv)
940  string bug = null_p? "a null" : "";
941  bug = nowhere_p? "an undefined" : "";
942  if(null_p || nowhere_p) {
943  // No: two options; either a user_error() for dereferencing an
944  // unitialized pointer or a conversion to anywhere, typed or not
945  if(lc==1) {
946  if(error_p)
947  pips_user_error("Dereferencing of %s pointer.\n", bug);
948  else {
949  pips_user_warning("Dereferencing of %s pointer.\n", bug);
950  }
951  }
952  else {
953  pips_user_warning("Possible dereferencing of %s pointer.\n", bug);
954  }
955  type t = entity_type(lv);
957  set must_l = gen_must_constant_paths(nl, R, in_must, address_of_p, len);
958  set_union(gen_must2, gen_must2, must_l);
959  }
960  else {
961  set must_l = gen_must_constant_paths(l, R, in_must, address_of_p, len);
962  set_union(gen_must2, gen_must2, must_l);
963  // FI: shouldn't must_l be freed?
964  }
965  }
966  set_union(gen_must2, gen_must2,gen_must1);
967 
968  return gen_must2;
969 }
970 
971 /* Does cell "c" represent a unique memory location or a set of memory
972  * locations?
973  *
974  * This is key to decide if a points-to arc is a must or a may arc.
975  *
976  * Is it always possible to decide when heap abstract locations are concerned?
977  *
978  * See also cell_abstract_location_p()
979  */
981 {
982  bool unique_p = !anywhere_cell_p(c)
984  // FI: typed or not?
985  // FI: how do you know when heap cells are unique and when they
986  // represent a set of cells?
987  && !heap_cell_p(c);
988 
989  // FI: how do you deal with arrays of pointers?
990  if(unique_p) {
992  list sl = reference_indices(r);
993  FOREACH(EXPRESSION, s, sl) {
994  if(unbounded_expression_p(s)) {
995  unique_p = false;
996  break;
997  }
998  }
999  }
1000  return unique_p;
1001 }
1002 
1004  list R,
1005  set in_may,
1006  bool* address_of_p,
1007  int Lc)
1008 {
1010  points_to_rank);
1012  if(!(*address_of_p)){
1013  pips_internal_error("address_of_p should always be true in the new implementation/.\n");
1014  /* here we have x = y, then we generate (x,y1,a)|(y,y1,a) as
1015  points to relation */
1016  FOREACH(cell, r, R){
1017  SET_FOREACH(points_to, i, in_may){
1018  if (/* locations_equal_p */equal_must_vreference(r, points_to_source(i)) /* && !entity_abstract_location_p(el) */ ){
1019  cell nl = copy_cell(l);
1020  pt = make_points_to(nl,
1024  }
1027  bool t_to_be_freed = false;
1028  type t = points_to_reference_to_type(ref, &t_to_be_freed);
1029  if(pointer_type_p(t)) {
1030  cell nl = copy_cell(l);
1032  }
1033  else {
1034  cell nl = copy_cell(l);
1036  }
1037  if (t_to_be_freed) free_type(t);
1038  }
1039  if(!points_to_undefined_p(pt)) {
1040  set_add_element(gen_may_cps, gen_may_cps, (void*) pt);
1041  }
1042  }
1043  }
1044  }
1045  else {
1046  int Rc = (int) gen_length(R);
1047  FOREACH(cell, r, R){
1048  // FI: check the unicity of the locations
1049  // FI: relationship with atomic_points_to_cell_p()?
1050  approximation a = (Lc+Rc>2
1051  || !unique_location_cell_p(l)
1052  || !unique_location_cell_p(r)) ?
1054  /* Should be replaced by opgen_constant_path(l,r) */
1055  //reference ref = cell_any_reference(r);
1056  /* if(reference_unbounded_indices_p(ref)) */
1057  /* a = make_approximation_may(); */
1058  cell nl = copy_cell(l);
1059  /* Make sure the types are compatible... */
1061  pt = make_points_to(nl, copy_cell(r), a, make_descriptor_none());
1062  set_add_element(gen_may_cps, gen_may_cps, (void*)pt);
1063  }
1064  }
1065 
1066  return gen_may_cps;
1067 }
1068 
1069 
1070 /* Build a set of arcs from cell l towards cells in list R if
1071  * *address_p is true, or towards cells pointed by cells in list R if
1072  * not.
1073  *
1074  * Approximation is must if Lc==1. Lc is the cardinal of L, a set
1075  * containing l.
1076  *
1077  * FI->AM: I do not understand why the cardinal of R is not used too
1078  * when deciding if the approximation is may or must. I decide to
1079  * change the semantics of this function although it is used by the
1080  * initial analysis.
1081  *
1082  * FI: since *address_of_p is not modified, I do not understand why a
1083  * pointer is passed.
1084  *
1085  * FI->AM: sharing of a... A new approximation must be generated for
1086  * each new arc
1087  */
1089  list R,
1090  set in_must,
1091  bool* address_of_p,
1092  int Lc)
1093 {
1095  points_to_rank);
1097  //approximation a = approximation_undefined;
1098  bool changed = false;
1099  int Rc = (int) gen_length(R);
1100 
1101  // Rc = 0;
1102  if(*address_of_p){
1103  /* if we have x = &y then we generate (x,y,a) as points to relation*/
1104  FOREACH(cell, r, R){
1105  /* Should be replaced by opgen_constant_path(l,r) */
1106  //reference ref = cell_any_reference(r);
1107  /* if(reference_unbounded_indices_p(ref)) */
1108  /* a = make_approximation_may(); */
1109  approximation a = (Lc+Rc>2
1110  || !unique_location_cell_p(l)
1111  || !unique_location_cell_p(r))?
1113  pt = make_points_to(l, r, a, make_descriptor_none());
1114  set_add_element(gen_must_cps, gen_must_cps, (void*)pt);
1115  }
1116  }
1117  else {
1118  /* here we have x = y, then we generate (x,y1,a)|(y,y1,a) as
1119  points to relation */
1120  FOREACH(cell, r, R){
1121  SET_FOREACH(points_to, i, in_must) {
1122  if (/* locations_equal_p */equal_must_vreference(r, points_to_source(i))/* && !entity_abstract_location_p(el) */){
1124  l = simple_cell_to_store_independent_cell(l, &changed);
1126  approximation a = (Lc+Rc>2)?
1129 
1130 
1131  /* if(array_entity_p(reference_variable(cell_any_reference(r)))){ */
1132  /* reference ref = cell_any_reference(r); */
1133  /* expression ex = reference_to_expression(ref); */
1134 
1135  /* if(!expression_pointer_p(ex)) */
1136  /* pt = make_points_to(l, r, a, make_descriptor_none()); */
1137  /* else */
1138  /* pt = make_points_to(l, points_to_sink(i), a, make_descriptor_none()); */
1139  /* } */
1140 
1141  /* if(!points_to_undefined_p(pt)) */
1142  /* set_add_element(gen_must_cps, gen_must_cps, (void*) pt); */
1143 
1146  bool t_to_be_freed = false;
1147  type t = points_to_reference_to_type(ref, &t_to_be_freed);
1148  /* if(reference_unbounded_indices_p(ref)) */
1149  /* a = make_approximation_may(); */
1150  if(!pointer_type_p(t))
1151  pt = make_points_to(l, r, a, make_descriptor_none());
1152  else
1154 
1155  if (t_to_be_freed) free_type(t);
1156  }
1157  if(!points_to_undefined_p(pt))
1158  set_add_element(gen_must_cps, gen_must_cps, (void*) pt);
1159  }
1160  }
1161  }
1162  }
1163 
1164  return gen_must_cps;
1165 }
1166 
1168 {
1170  return pt;
1171 }
1172 
1174 {
1176  return pt;
1177 }
1178 
1180 {
1181  const char* m1 = entity_module_name(e1);
1182  const char* m2 = entity_module_name(e2);
1183 
1185  return true;
1186  else
1187  return same_string_p(m1, m2);
1188 }
1189 
1191 {
1192  const char* m1 = entity_module_name(e1);
1193  const char* m2 = entity_module_name(e2);
1194 
1196  return false;
1197  else
1198  return same_string_p(m1, m2);
1199 }
1200 
1202 {
1203  string n1 = entity_name(e1);
1204  string n2 = entity_name(e2);
1205 
1207  return true;
1208  else
1209  return same_string_p(n1, n2);
1210 }
1211 
1213 {
1214  string n1 = entity_name(e1);
1215  string n2 = entity_name(e2);
1216 
1218  return false;
1219  else
1220  return same_string_p(n1, n2);
1221 }
1222 
1224 {
1225  bool gen_may_p = true;
1226 
1227  if(ENDP(vr1) || ENDP(vr2))
1228  return gen_may_p;
1229  else{
1230  FOREACH(expression, e, vr1){
1232  gen_may_p = false;
1233  break;
1234  }
1235  }
1236  }
1237 
1238  return gen_may_p;
1239 }
1240 
1241 /* Could be replaced by abstract_location_p() but this later don't
1242  take into account the null location */
1244 {
1245  bool atomic_cp_p = true;
1247  entity e = reference_variable(r);
1248 
1250  atomic_cp_p = false;
1251  return atomic_cp_p;
1252 }
1253 
1255 {
1257  points_to_rank);
1258  SET_FOREACH(cell, l, L){
1260  set_add_element(gen_null, gen_null, (void*) pt);
1261  }
1262 
1263  return gen_null;
1264 }
1265 
1266 
1267 /*
1268  iterate over the points to relation, every tab[i] is changed
1269  into tab[*] in order to obtain points to relations independent of the store
1270 
1271  Used by statement.c
1272 */
1274 {
1276  points_to_rank);
1277  bool changed = false;
1278 
1279  SET_FOREACH(points_to, pt, s){
1280  cell source = points_to_source(pt);
1281  cell sink = points_to_sink(pt);
1282  cell new_source = simple_cell_to_store_independent_cell(source, &changed);
1283  cell new_sink = simple_cell_to_store_independent_cell(sink, &changed);
1284  points_to npt = make_points_to(new_source, new_sink, points_to_approximation(pt),points_to_descriptor(pt));
1285  set_add_element(res, res, (void*) npt);
1286  }
1287 
1288  return res;
1289 }
1290 
1291 
1293 {
1294  int i = 0;
1295  bool changed = false;
1297  c1 = simple_cell_to_store_independent_cell(c1, &changed);
1298  c2 = simple_cell_to_store_independent_cell(c2, &changed);
1300  reference r1 = cell_any_reference(c1);
1301  reference r2 = cell_any_reference(c2);
1302  entity v1 = reference_variable(r1);
1303  entity v2 = reference_variable(r2);
1304  list sl1 = NIL, sl2 = NIL;
1305  // FI: memory leak? generation of a new string?
1306  extern const char* entity_minimal_user_name(entity);
1307 
1309  if (i==0) {
1310  sl1 = reference_indices(r1);
1311  sl2 = reference_indices(r2);
1312  if( (int)gen_length(sl1) == (int)gen_length(sl2) ) {
1313  for (;i==0 && !ENDP(sl1) && ! ENDP(sl2) ; POP(sl1), POP(sl2)){
1314  expression se1 = EXPRESSION(CAR(sl1));
1315  expression se2 = EXPRESSION(CAR(sl2));
1316  if( unbounded_expression_p(se1) ){
1317  i = 0;
1318  }
1319  else if (expression_constant_p(se1) && expression_constant_p(se2)){
1320  int i1 = expression_to_int(se1);
1321  int i2 = expression_to_int(se2);
1322  i = i2>i1? 1 : (i2<i1? -1 : 0);
1323  if (i==0){
1324  // FI: why not use expression_equal_p()? + memory leak
1325  string s1 = expression_to_string(se1);
1326  string s2 = expression_to_string(se2);
1327  i = strcmp(s1, s2);
1328  }
1329  }
1330  else {
1331  string s1 = expression_to_string(se1);
1332  string s2 = expression_to_string(se2);
1333  i = strcmp(s1, s2);
1334  }
1335  }
1336  }
1337  else
1338  i = 1;
1339  }
1340 
1341  return (i==0? true: false);
1342 }
1343 
1344 /* arg1: list of cells
1345  arg2: set of points-to
1346  Create a points-to set with elements of lhs_list as
1347  source and NOWHERE as sink.
1348  Iterate over input and kill all points-to relations
1349  where sinks are elements of lhs_list.
1350 */
1352 {
1354  points_to_rank);
1356  points_to_rank);
1358  points_to_rank);
1360  points_to_rank);
1362 
1363  SET_FOREACH(points_to, p, input) {
1364  FOREACH(cell, c, lhs_list) {
1365  if(points_to_source(p) == c)
1366  set_add_element(kill, kill, p);
1367  }
1368  }
1369  set_difference(input_kill_diff, input, kill);
1370  /* if the lhs_set or the rhs set contains more than an element, we
1371  set the approximation to MAY. */
1372  if((int)gen_length(lhs_list) > 1)// || set_size(rhs_set)>1)
1373  a = make_approximation_may();
1374 
1375  /* Computing the gen set */
1376  FOREACH(cell, c, lhs_list) {
1377  cell sink = make_nowhere_cell();
1379  set_add_element(gen, gen, (void*)pt_to);
1380  }
1381  free_approximation(a);
1382  set_union(res, gen, input_kill_diff);
1383 
1384  return res;
1385 }
float a2sf[2] __attribute__((aligned(16)))
USER generates a user error (i.e., non fatal) by printing the given MSG according to the FMT.
Definition: 3dnow.h:3
cell make_cell_reference(reference _field_)
Definition: effects.c:293
approximation make_approximation_exact(void)
Definition: effects.c:185
approximation copy_approximation(approximation p)
APPROXIMATION.
Definition: effects.c:132
approximation make_approximation_may(void)
Definition: effects.c:179
descriptor make_descriptor_none(void)
Definition: effects.c:442
cell copy_cell(cell p)
CELL.
Definition: effects.c:246
void free_approximation(approximation p)
Definition: effects.c:135
points_to make_points_to(cell a1, cell a2, approximation a3, descriptor a4)
type copy_type(type p)
TYPE.
Definition: ri.c:2655
reference make_reference(entity a1, list a2)
Definition: ri.c:2083
void free_type(type p)
Definition: ri.c:2658
static reference ref
Current stmt (an integer)
Definition: adg_read_paf.c:163
#define new_simple_pt_map()
bool entity_null_locations_p(entity e)
test if an entity is the NULL POINTER
bool entity_abstract_location_p(entity al)
entity variable_to_abstract_location(entity v)
returns the smallest abstract locations containing the location of variable v.
bool cell_typed_anywhere_locations_p(cell c)
test if a cell is the bottom of the lattice
bool entity_all_locations_p(entity e)
test if an entity is the top of the lattice
bool entity_nowhere_locations_p(entity e)
test if an entity is the bottom of the lattice
entity entity_all_xxx_locations(string xxx)
return ANY_MODULE:xxx
entity entity_all_xxx_locations_typed(string xxx, type t)
FI->AM: the predicate entity_all_xxx_locations_typed_p() is missing...
entity entity_all_locations()
eturn ANY_MODULE:ANYWHERE (the top of the lattice)
bool entity_typed_nowhere_locations_p(entity e)
test if an entity is the bottom of the lattice
void const char const char const int
set points_to_independent_store(set s)
set opgen_null_location(set L, cell r)
bool opgen_may_vreference(list vr1, list vr2)
bool opkill_may_reference(cell c1, cell c2)
cell max_module(cell m1, cell m2)
we define operator max fot the lattice Module which has any_module as top and a bottom which is not y...
bool opgen_may_module(entity e1, entity e2)
bool address_of_expression_p(expression e)
shoud be moved to expression.c
bool opkill_may_module(cell m1, cell m2)
set kill_must_set(list L, set in)
Generate the subset of arcs that must be removed from the points-to graph "in".
set points_to_may_filter(set in)
returns a set which contains all the MAY points to
bool opgen_must_module(entity e1, entity e2)
bool opkill_must_module(cell m1, cell m2)
set gen_must_constant_paths(cell l, list R, set in_must, bool *address_of_p, int Lc)
Build a set of arcs from cell l towards cells in list R if *address_p is true, or towards cells point...
set kill_may_set(list L, set in_may)
Compute the set of arcs in the input points-to relation "in" whose approximation must be changed from...
set gen_must_set(list L, list R, set in_must, bool *address_of_p)
bool atomic_constant_path_p(cell cp)
Could be replaced by abstract_location_p() but this later don't take into account the null location.
set points_to_must_filter(set in)
returns a set which contains all the EXACT points to
bool unique_location_cell_p(cell c)
Does cell "c" represent a unique memory location or a set of memory locations?
bool opkill_may_constant_path(cell c1, cell c2)
bool opkill_must_reference(cell c1, cell c2)
bool opkill_may_vreference(cell c1, cell c2)
FI: really weird and unefficient.
cell op_gen_module(cell m1, __attribute__((__unused__)) cell m2)
Operator gen for modules: m1 is the sink, m2 the source (m2 points to m1) opkill_gen_module : Module ...
set points_to_nowhere(list lhs_list, set input)
arg1: list of cells arg2: set of points-to Create a points-to set with elements of lhs_list as source...
cell make_nowhere_cell()
This file contains all the operators defining constant paths :
bool opkill_must_constant_path(cell c1, cell c2)
returns true if c2 kills c1
points_to opgen_must_constant_path(cell l __attribute__((__unused__)), cell r __attribute__((__unused__)))
cell cell_to_nowhere_sink(cell source)
assuming source is a reference to a pointer, build the corresponding sink when the pointer is not ini...
bool opkill_must_vreference(cell c1, cell c2)
returns true if c2 must kills c1 because of the subscript expressions
bool opgen_may_name(entity e1, entity e2)
list array_to_constant_paths(expression e, set in __attribute__((__unused__)))
input : expression e and a set of points_to output : a set of constant paths translates an expression...
bool opkill_must_type(type t1, type t2)
opkill_must_type is the same as op_kill_may_type...
type opgen_may_type(type t1, type t2)
set gen_may_set(list L, list R, set in_may, bool *address_of_p)
Should be moved to anywhere_abstract_locations.c.
set points_to_anywhere(list lhs_list, set input)
cell make_typed_nowhere_cell(type t)
type opgen_must_type(type t1, type t2)
the same as opgen_may_type
points_to opgen_may_constant_path(cell l __attribute__((__unused__)), cell r __attribute__((__unused__)))
set gen_may_constant_paths(cell l, list R, set in_may, bool *address_of_p, int Lc)
bool opkill_must_name(cell n1, cell n2)
bool entity_any_module_p(entity e)
operator kill for the dimension Module:
bool opgen_must_name(entity e1, entity e2)
bool equal_must_vreference(cell c1, cell c2)
set points_to_anywhere_typed(list lhs_list, set input)
Already exists in points_to_general_algorithm.c, to be removed later...
bool subscript_expression_p(expression e)
bool opkill_may_type(type t1, type t2)
bool opkill_may_name(cell n1, cell n2)
We define operators for the lattice Name which can be a: -variable of a the program -malloc -NULL /0 ...
type max_type(type t1, type t2)
void generic_effects_reset_all_methods(void)
void set_methods_for_proper_simple_effects(void)
cell simple_cell_to_store_independent_cell(cell, bool *)
#define NOWHERE_LOCATION
#define ANYWHERE_LOCATION
#define ANY_MODULE_NAME
type cell_to_type(cell, bool *)
Definition: type.c:513
cell make_anywhere_points_to_cell(type)
Function storing points to information attached to a statement.
Definition: points_to.c:87
reference cell_any_reference(cell)
API for reference.
Definition: effects.c:77
type points_to_reference_to_type(reference, bool *)
FI: I need more generality than is offered by cell_to_type()
Definition: type.c:527
bool anywhere_cell_p(cell)
Is it an anywhere cell?
Definition: effects.c:367
void points_to_cell_types_compatibility(cell, cell)
Make sure that cell l can points towards cell r.
Definition: type.c:985
bool heap_cell_p(cell)
Any heap cell, more or less abstract or typed.
Definition: effects.c:420
#define cell_reference(x)
Definition: effects.h:469
#define cell_preference(x)
Definition: effects.h:472
#define cell_reference_p(x)
Definition: effects.h:467
#define cell_undefined
Definition: effects.h:430
#define approximation_exact_p(x)
Definition: effects.h:369
#define approximation_may_p(x)
Definition: effects.h:363
#define CELL(x)
CELL.
Definition: effects.h:424
bool get_bool_property(const string)
FC 2015-07-20: yuk, moved out to prevent an include cycle dependency include "properties....
static int input(void)
bool cells_may_conflict_p(cell c1, cell c2)
Check if two cell may conflict.
Definition: conflicts.c:696
void gen_null(__attribute__((unused)) void *unused)
Ignore the argument.
Definition: genClib.c:2752
#define ENDP(l)
Test if a list is empty.
Definition: newgen_list.h:66
#define POP(l)
Modify a list pointer to point on the next element of the list.
Definition: newgen_list.h:59
#define NIL
The empty list (nil in Lisp)
Definition: newgen_list.h:47
size_t gen_length(const list l)
Definition: list.c:150
#define CONS(_t_, _i_, _l_)
List element cell constructor (insert an element at the beginning of a list)
Definition: newgen_list.h:150
#define CAR(pcons)
Get the value of the first element of a list.
Definition: newgen_list.h:92
#define FOREACH(_fe_CASTER, _fe_item, _fe_list)
Apply/map an instruction block on all the elements of a list.
Definition: newgen_list.h:179
bool expression_constant_p(expression)
HPFC module by Fabien COELHO.
Definition: expression.c:2453
#define pips_user_warning
Definition: misc-local.h:146
#define pips_internal_error
Definition: misc-local.h:149
#define pips_user_error
Definition: misc-local.h:147
const char * entity_minimal_user_name(entity e)
Do not preserve scope information.
Definition: naming.c:223
#define same_string_p(s1, s2)
set set_generic_make(set_type, hash_equals_t, hash_rank_t)
what about this replacement? #define SET_MAP(the_item, the_code, the_set) \ { SET_FOREACH(void *,...
Definition: set.c:83
set set_difference(set, const set, const set)
Definition: set.c:256
#define SET_FOREACH(type_name, the_item, the_set)
enumerate set elements in their internal order.
Definition: newgen_set.h:78
set set_union(set, const set, const set)
Definition: set.c:211
@ set_private
Definition: newgen_set.h:45
set set_add_element(set, const set, const void *)
Definition: set.c:152
_uint points_to_rank(const void *, size_t)
create a key which is a concatenation of the source's name, the sink's name and the approximation of ...
bool points_to_compare_cell(cell, cell)
int points_to_equal_p(const void *, const void *)
returns true if two points-to arcs "vpt1" and "vpt2" are equal.
Definition: points_to_set.c:98
#define points_to_approximation(x)
#define points_to_undefined_p(x)
#define points_to_undefined
#define points_to_sink(x)
#define points_to_descriptor(x)
#define points_to_source(x)
string expression_to_string(expression e)
Definition: expression.c:77
static statement gen(int what, entity src, entity trg, entity lid, entity proc, entity(*create_src)(), entity(*create_trg)(), Psysteme sr, list ldiff)
arguments: all that may be useful to generate some code
Definition: remapping.c:498
#define entity_an_operator_p(e, name)
macros
bool array_entity_p(entity e)
Definition: entity.c:793
const char * entity_module_name(entity e)
See comments about module_name().
Definition: entity.c:1092
bool extended_integer_constant_expression_p(expression e)
More extensive than next function.
Definition: expression.c:858
int expression_to_int(expression exp)
================================================================
Definition: expression.c:2205
bool field_expression_p(expression e)
The expression is of kind "a", where "a" is a field of some struct "s".
Definition: expression.c:498
bool expression_equal_p(expression e1, expression e2)
Syntactic equality e1==e2.
Definition: expression.c:1347
bool reference_equal_p(reference r1, reference r2)
Definition: expression.c:1500
bool array_reference_p(reference r)
predicates on references
Definition: expression.c:1861
bool expression_reference_p(expression e)
Test if an expression is a reference.
Definition: expression.c:528
bool store_independent_reference_p(reference r)
Does this reference define the same set of memory locations regardless of the current (environment an...
Definition: expression.c:3108
bool unbounded_expression_p(expression e)
Definition: expression.c:4329
reference expression_reference(expression e)
Short cut, meaningful only if expression_reference_p(e) holds.
Definition: expression.c:1832
entity expression_variable(expression e)
Definition: expression.c:532
type MakeTypeUnknown(void)
Definition: type.c:97
bool type_equal_p(type, type)
Definition: type.c:547
type type_to_pointed_type(type)
returns t if t is not a pointer type, and the pointed type if t is a pointer type.
Definition: type.c:5265
bool pointer_type_p(type)
Check for scalar pointers.
Definition: type.c:2993
#define type_unknown_p(x)
Definition: ri.h:2956
#define reference_undefined
Definition: ri.h:2302
#define call_function(x)
Definition: ri.h:709
#define reference_variable(x)
Definition: ri.h:2326
#define syntax_call_p(x)
Definition: ri.h:2734
#define EXPRESSION(x)
EXPRESSION.
Definition: ri.h:1217
#define entity_name(x)
Definition: ri.h:2790
#define reference_indices(x)
Definition: ri.h:2328
#define syntax_call(x)
Definition: ri.h:2736
#define preference_reference(x)
Definition: ri.h:2102
#define type_undefined
Definition: ri.h:2883
#define type_area_p(x)
Definition: ri.h:2944
#define entity_type(x)
Definition: ri.h:2792
#define expression_syntax(x)
Definition: ri.h:1247
#define syntax_subscript_p(x)
Definition: ri.h:2743
Pvecteur cp
pointeur sur l'egalite ou l'inegalite courante
Definition: sc_read.c:87
s1
Definition: set.c:247
Definition: pip__tab.h:30
FI: I do not understand why the type is duplicated at the set level.
Definition: set.c:59
The structure used to build lists in NewGen.
Definition: newgen_list.h:41