PIPS
eval.c
Go to the documentation of this file.
1 /*
2 
3  $Id: eval.c 23412 2017-08-09 15:07:09Z irigoin $
4 
5  Copyright 1989-2016 MINES ParisTech
6  Copyright 2009-2010 HPC Project
7 
8  This file is part of PIPS.
9 
10  PIPS is free software: you can redistribute it and/or modify it
11  under the terms of the GNU General Public License as published by
12  the Free Software Foundation, either version 3 of the License, or
13  any later version.
14 
15  PIPS is distributed in the hope that it will be useful, but WITHOUT ANY
16  WARRANTY; without even the implied warranty of MERCHANTABILITY or
17  FITNESS FOR A PARTICULAR PURPOSE.
18 
19  See the GNU General Public License for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with PIPS. If not, see <http://www.gnu.org/licenses/>.
23 
24 */
25 #ifdef HAVE_CONFIG_H
26 #include "pips_config.h"
27 #endif
28 
29 #include <stdio.h>
30 #include <string.h>
31 #include <stdlib.h>
32 
33 #include "genC.h"
34 #include "linear.h"
35 #include "ri.h"
36 #include "effects.h"
37 #include "ri-util.h"
38 #include "prettyprint.h"
39 #include "effects-util.h"
40 #include "misc.h"
41 #include "properties.h"
42 #include "text-util.h"
43 #include "newgen_set.h"
44 //#include "points_to_private.h"
45 #include "effects-generic.h"
46 
47 // For semantics_user_warning()
48 #include "transformer.h"
49 #include "semantics.h"
50 
51 #include "pips-libs.h"
52 #ifdef HAVE_PIPS_points_to_LIBRARY
53 // FC: ARGH, STUPID HIDDEN DEPENDENCIES!
54 extern void print_points_to_relations(list);
55 #else // no HAVE_PIPS_points_to_LIBRARY
56 #define print_points_to_relations(l) NULL
57 #endif // HAVE_PIPS_points_to_LIBRARY
58 
59 #include "pips-libs.h"
60 
61 /* In case, the points-to information is not complete, use anywhere
62  * locations to convert the reference.
63  *
64  * The action will be fixed by a caller or a caller's caller function.
65  *
66  */
68 (reference input_ref,
69  descriptor input_desc __attribute__ ((__unused__)),
70  void (*cell_reference_with_address_of_cell_reference_translation_func)
72  bool *) __attribute__ ((__unused__)),
73  void (*cell_reference_conversion_func)(reference, reference *, descriptor *) __attribute__ ((__unused__))
74  )
75 {
77  cell c = make_anywhere_cell(t);
78  //list l = CONS(CELL, c, NIL);
79  action a = make_action_write_memory(); // will be fixed later
81  descriptor d = make_descriptor_none(); // will be fixed later?
82  effect e = make_effect(c, a, ap, d);
83  list l = CONS(EFFECT, e, NIL);
84  return l;
85 }
86 ␌
87 /* Build the return list with the points-to sinks to which we
88  * add/append the indices of input_ref which are not in the points-to
89  * source reference. This is comparable to an interprocedural
90  * translation where the input_ref is a path from the formal
91  * parameter, the source the formal parameter and the sink the actual
92  * parameter preceded by a & operator.
93  *
94  * Let the remaining indices be the indices from input_ref which are
95  * not in common with the sources of the points-to (which by
96  * construction have all the same path length). For each points-to,
97  * the new path is built from the sink reference. If the latter has
98  * indices, we add to the value of its last index the value of the
99  * first index of the remaining indices. Then we append to the new
100  * path the last indices of the reamining indices. If the sink
101  * reference has no indices, then the first index of the remaining
102  * indices must be equal to zero, and be skipped. And we simply append
103  * to the new path the last indices of the remaining indices.
104  *
105  * The part of the code inside of the FOREACH could certainely be
106  * shared with the interprocedural translation. Besides, it should be
107  * made generic to handle convex input paths as well. Only simple
108  * paths are currently taken into account.
109  *
110  * This function has been outlined from
111  * generic_eval_cell_with_points_to() to reduce its size to about one
112  * page.
113  */
115 (list matching_list,
116  size_t current_max_path_length,
117  bool * exact_p,
118  reference input_ref,
119  descriptor input_desc,
120  void (*cell_reference_with_address_of_cell_reference_translation_func)
122  bool *),
123  void (*cell_reference_conversion_func)(reference, reference *, descriptor *)
124  )
125 {
126  list l = NIL; // returned list of write effects based on the transformed sink_cells
127  type input_t = points_to_reference_to_concrete_type(input_ref);
128 
129  /* Transform each sink reference to add it in the return list */
130  FOREACH(POINTS_TO, pt, matching_list) {
131  cell sink_cell = points_to_sink(pt);
132  reference sink_ref = reference_undefined;
133  reference tmp_ref = cell_to_reference(sink_cell);
135 
136  (*cell_reference_conversion_func)(tmp_ref, &sink_ref, &sink_desc);
137  reference build_ref = reference_undefined;
138 
139  pips_debug(8, "considering point-to : %s\n ", words_to_string(word_points_to(pt)));
140 
141  entity sink_ent = reference_variable(sink_ref);
142  if (entity_abstract_location_p(sink_ent)
144  /* Here, we should analyse the source remaining indices to know
145  if there are remaining dereferencing dimensions. This would
146  imply keeping track of the indices types. In case there are
147  no more dereferencing dimensions, we would then reuse the
148  sink abstract location. Otherwise (which is presently the
149  only default case), we return an all location cell
150  */
151  if (entity_null_locations_p(sink_ent)
153  pips_debug(5, "Null pointer, may approximation: ignore, assuming code is correct\n");
154  }
155  else {
156  cell c = make_anywhere_cell(input_t);
160  effect e = make_effect(c, a, ap, d);
161  l = CONS(EFFECT, e, l);
162  // l = CONS(CELL, make_anywhere_cell(input_t), l);
163  *exact_p = false;
164  }
165  }
166  else {
168  bool exact_translation_p;
169 
170  (*cell_reference_with_address_of_cell_reference_translation_func)
171  (input_ref, input_desc,
172  sink_ref, sink_desc,
173  current_max_path_length,
174  &build_ref, &build_desc,
175  &exact_translation_p);
176  *exact_p = *exact_p && exact_translation_p;
177  /* the approximation tag of the points-to is taken into account
178  for the exactness of the result except if the matching list
179  has been reduced to one element and if the target is
180  atomic. */
181  int mll = (int) gen_length(matching_list); // matching list length
182  if(mll==1) {
183  cell sink_c = points_to_sink(pt);
184  reference sink_c_r = cell_any_reference(sink_c);
185  *exact_p = *exact_p && generic_atomic_points_to_reference_p(sink_c_r, false);
186  }
187  else {
188  /* It should be false as soon as mll>1... */
189  *exact_p = *exact_p && approximation_exact_p(points_to_approximation(pt));
190  }
191  pips_debug(8, "adding reference %s\n",
192  effect_reference_to_string(build_ref));
193  //l = CONS(CELL, make_cell(is_cell_reference, build_ref), l);
194 
198  build_desc), l);
199 
200  } /* end of else branch of if (entity_abstract_location_p(sink_ent)
201  && ! entity_flow_or_context_sentitive_heap_location_p(sink_ent)) */
202  if(sink_cell != points_to_sink(pt)) free_cell(sink_cell);
203  } /* end of FOREACH(POINTS_TO,...) */
204  return l;
205 }
206 
207 /* To provide information when a but is encountered in the source file or within PIPS. */
209 {
211  return statement_number(s);
212 }
213 
214 /* This function has been outlined from
215  * generic_eval_cell_with_points_to() to reduce the size of a function
216  * to about one page.
217  *
218  * It computes a list of points-to arcs whose source is compatible
219  * with the input reference, "input_ref". It provides information about
220  * the number of common indices, "p_current_max_path_length" and about the
221  * approximation of the points-to informationx(?).
222  */
224 (reference input_ref,
225  descriptor input_desc,
226  size_t * p_current_max_path_length,
227  bool * exact_p,
229  list ptl,
230  void (*cell_reference_conversion_func)(reference, reference *, descriptor *),
231  bool (*cell_reference_preceding_p_func)(reference, descriptor,
233  transformer, bool, bool * )
234  )
235 {
236  list matching_list = NIL;
237  *exact_p = true; /* assume exactness */
238  // previous matching list I guess: the initial code looks wrong
239  // since matching_ptl is itialized to NIL...
240  // list matching_ptl = NIL;
241 
242  FOREACH(POINTS_TO, pt, ptl) {
243  cell sink_cell = points_to_sink(pt);
244  if(null_cell_p(sink_cell) || nowhere_cell_p(sink_cell))
245  ; // This points-to arc can be ignored since it would lead to a segfault
246  else {
247  cell source_cell = points_to_source(pt);
248  reference source_ref = reference_undefined;
249  reference tmp_ref = cell_to_reference(source_cell);
251 
252  (*cell_reference_conversion_func)(tmp_ref, &source_ref, &source_desc);
253 
254  pips_debug(8, "considering point-to : %s\n ",
256 
257  list source_indices = reference_indices(source_ref);
258  size_t source_path_length = gen_length(source_indices);
259  bool exact_prec = false;
260 
261  /* eligible points-to candidates must have a path length
262  greater or equal to the current maximum length and
263  their path must be a predecessor of the input_ref
264  path.*/
265  bool strict_p = get_bool_property("POINTS_TO_STRICT_POINTER_TYPES");
266  if ( (source_path_length >= *p_current_max_path_length)
267  && (*cell_reference_preceding_p_func)(source_ref, source_desc, input_ref,
268  input_desc, current_precondition, strict_p,
269  &exact_prec)) {
270  pips_debug(8, "exact_prec is %s\n", exact_prec? "true":"false");
271  if (source_path_length > *p_current_max_path_length ) {
272  /* if the candidate has a path length strictly greater
273  * than the current maximum length, the list of
274  * previously found matching candidates must be cleared
275  */
276  //if(!ENDP(matching_ptl)) {
277  // gen_free_list(matching_ptl);
278  // matching_list = NIL;
279  //}
280  if(!ENDP(matching_list)) {
281  gen_free_list(matching_list);
282  matching_list = NIL;
283  }
284  *p_current_max_path_length = source_path_length;
285  *exact_p = exact_prec;
286  }
287  else
288  *exact_p = *exact_p && exact_prec;
289  /* I keep the whole points_to and not only the sink because I
290  will need the approximation to further test the exactness
291  */
292  /* FI: I try adding the stripping... */
294  matching_list = CONS(POINTS_TO, npt, matching_list);
295  }
296  if(source_cell != points_to_source(pt)) free_cell(source_cell);
297  }
298  } /* end of FOREACH */
299  return matching_list;
300 }
301 
302 /*
303  @brief tries to find in the points-to list ptl a points-to with a
304  maximal length source path but shorter than the length of the
305  input path represented by input_ref. If it's an exact
306  points-to, that's OK, if not we have to find other possible
307  paths.
308 
309  There is no sharing between the returned list cells and the
310  input reference.
311 
312  When the input reference contains no dereferencing dimension
313  the result is an empty list. The caller should check this
314  case before calling the function because an empty list when there
315  is a dereferencing dimension means that no target has been found
316  and that the input path may point to anywhere.
317 
318 
319  @param c is a the cell for which we look an equivalent constant path
320 
321  @param ptl is the list of points-to in which we search for constant paths
322 
323  @param exact_p is a pointer towards a boolean. It is set to true if
324  the result is exact, and to false if it is an approximation,
325  either because the matching points-to sources found in ptl are
326  over-approximations of the preceding path of the input cell or because
327  the matching points-to have MAY approximation tag.
328 
329  @return a list of constant path effect. It is a list because at a given
330  program point the cell may correspond to several constant paths.
331 
332  From the original comment (FI): it is not clear if the decision to
333  replace a dereferencement by a reference to anywhere should be taken
334  here or not. I would rather postpone it as it depends on write
335  effects unknown from this function.
336 
337  Reply (BC): the original function used to return a single
338  reference. It now returns a list of cell. It's up to the caller to
339  take the decision to turn this list into an anywhere effect or not,
340  depending on the context.
341 
342  original comment:
343 
344  goal: see if cell c can be shortened by replacing its indirections
345  by their values when they are defined in ptl. For instance, p[0][0]
346  and (p,q,EXACT) is reduced to q[0]. And if (q,i,EXACT) is also
347  available, the reference is reduced to i. The reduced cell is less likely
348  to be invalidated by a write effect. The function is called "eval"
349  because its goal is to build an as constant as possible reference or
350  gap.
351 
352  This function is called by effects to see if a memory access path
353  can be transformed into a constant. It should also be called by the
354  points-to analysis to see if a sink or a source can be preserved in
355  spite of write effects. This function should be called before
356  points_to_filter_effects() to reduce the number of anywhere
357  locations generated.
358 
359  */
360 
362  cell input_cell, descriptor input_desc, list ptl, bool *exact_p,
364  bool (*cell_reference_preceding_p_func)(reference, descriptor,
366  transformer, bool, bool * ),
367  void (*cell_reference_with_address_of_cell_reference_translation_func)
370  int,
371  reference *, descriptor *,
372  bool *),
373  void (*cell_reference_conversion_func)(reference, reference *, descriptor *))
374 {
375  debug_on("EVAL_CELL_WITH_POINTS_TO_DEBUG_LEVEL");
376  reference input_ref = cell_to_reference(input_cell);
377 
378  /* iterer sur le path p[0][1][2][0] et tester chaque fois si on peut
379  * dereferencer le pointeur*/
380  entity input_ent = reference_variable(input_ref);
381  list input_indices = reference_indices(input_ref);
382  size_t input_path_length = gen_length(input_indices);
383  list l = NIL; // result of this function: a list of effects
384 
386 
387  pips_debug(8, "input reference : %s\n", effect_reference_to_string(input_ref));
389 
390  if (entity_abstract_location_p(input_ent)
391  && !entity_heap_location_p(input_ent)) {
394  // cell c = make_cell_reference(r);
395  // l = CONS(CELL, c, NIL);
399  NIL);
400  *exact_p = false;
401  }
402  else if (input_path_length == 0) {
403  /* simple scalar case. I think this should not happen, because there is no dereferencing dimension. */
404  l = NIL;
405  *exact_p = true;
406  }
407  else {
408  /* first build a temporary list with matching points-to of maximum length */
409  size_t current_max_path_length = 0; /* the current maximum length */
411  (input_ref, input_desc,
412  &current_max_path_length,
413  exact_p, current_precondition, ptl,
414  cell_reference_conversion_func,
415  cell_reference_preceding_p_func);
416 
417  ifdebug(8) {
418  fprintf(stderr, "matching points-to list:\n");
419  print_points_to_relations(matching_list);
420  fprintf(stderr,"\ncurrent_max_path_length = %d\n", (int) current_max_path_length);
421  fprintf(stderr, "*exact_p is %s\n", *exact_p? "true":"false");
422  }
423 
424  if(ENDP(matching_list)) {
426  ("NULL or undefined pointer dereferencing... or insufficient points-to information for reference \"%s\".\n",
427  reference_to_string(input_ref));
428  l = use_default_sink_cell(input_ref, input_desc,
429  cell_reference_with_address_of_cell_reference_translation_func,
430  cell_reference_conversion_func);
431  *exact_p = false;
432  }
433  else {
435  (matching_list,
436  current_max_path_length,
437  exact_p,
438  input_ref,
439  input_desc,
440  cell_reference_with_address_of_cell_reference_translation_func,
441  cell_reference_conversion_func);
442  }
443 
444  } /* else branche of if (input_path_length == 0) */
445 
446  pips_debug_effects(8, "resulting effect list before recursing:", l);
447 
448  /* If the results contain dereferencing dimensions, we must eval them recursively */
449  list l_tmp = l;
450  l = NIL;
451  FOREACH(EFFECT, eff, l_tmp)
452  {
453  bool r_exact_p;
454  // reference ref = cell_any_reference(c);
457 
459  && effect_reference_dereferencing_p(ref, &r_exact_p))
460  {
461  pips_debug(8, "recursing\n");
462  list l_eval = generic_eval_cell_with_points_to(effect_cell(eff), effect_descriptor(eff), ptl, &r_exact_p,
464  cell_reference_preceding_p_func,
465  cell_reference_with_address_of_cell_reference_translation_func,
466  cell_reference_conversion_func);
467  *exact_p = *exact_p && r_exact_p;
468  /* if eff is a may effect, the resulting effects must be may effects */
469  if (effect_may_p(eff) || !(*exact_p))
470  effects_to_may_effects(l_eval);
471  l = gen_nconc(l_eval, l);
472  free_effect(eff);
473  }
474  else
475  {
476  pips_debug(8, "no need to recurse\n");
477  l = CONS(EFFECT, eff, l);
478  }
479  }
480  l = gen_nreverse(l);
481  gen_free_list(l_tmp);
482 
483  pips_debug_effects(8, "resulting cell list after recursing:", l);
484 
485  debug_off();
486 
487  return l;
488 }
489 
490 
491 
492 /**
493  @brief find pointer_values in l_in which give (possible or exact) paths
494  equivalent to eff.
495  @param eff is the considered input path.
496  @param l_in is the input pointer values list.
497  @param exact_aliased_pv gives an exact equivalent path found in l_in if it exists.
498  @param l_in_remnants contains the elemnts of l_in which are neither
499  exact_aliased_pv nor in the returned list.
500 
501  @return a list of elements of l_in which give (possible or exact) paths
502  equivalent to eff, excluding exact_aliased_pv if one exact equivalent
503  path can be found in l_in.
504  */
505 list
507  cell_relation * exact_aliased_pv,
508  list * l_in_remnants,
509  bool (*cells_intersection_p_func)(cell, descriptor,
510  cell, descriptor,
511  bool *),
512  bool (*cells_inclusion_p_func)(cell, descriptor,
513  cell, descriptor,
514  bool*),
515  void (*simple_cell_conversion_func)(cell, cell *, descriptor *))
516 {
517 
518  pips_debug_pvs(1,"begin, l_in =", l_in);
519  pips_debug_effect(1, "and eff:", eff);
520 
521  /* eff characteristics */
522  cell eff_cell = effect_cell(eff);
523  descriptor eff_desc = effect_descriptor(eff);
524  /******/
525 
526  /* first, search for the (exact/possible) values of eff cell in l_in */
527  /* we search for the cell_relations where ref appears
528  * as a first cell, or the exact value_of pointer_values where ref appears as
529  * a second cell. If an exact value_of relation is found, it is retained in
530  * exact_aliased_pv
531  */
532  *l_in_remnants = NIL;
533  *exact_aliased_pv = cell_relation_undefined;
534  list l_res = NIL;
535 
536  FOREACH(CELL_RELATION, pv_in, l_in)
537  {
538  cell first_cell_in = cell_relation_first_cell(pv_in);
539  cell converted_first_cell_in = cell_undefined;
540  descriptor first_cell_in_desc = descriptor_undefined;
541 
542  cell second_cell_in = cell_relation_second_cell(pv_in);
543  cell converted_second_cell_in = cell_undefined;
544  descriptor second_cell_in_desc = descriptor_undefined;
545 
546  bool intersection_test_exact_p = false;
547  bool inclusion_test_exact_p = true;
548 
549  pips_debug_pv(4, "considering:", pv_in);
550 
551  (*simple_cell_conversion_func)(first_cell_in, &converted_first_cell_in, &first_cell_in_desc);
552  (*simple_cell_conversion_func)(second_cell_in, &converted_second_cell_in, &second_cell_in_desc);
553 
554  if ((*cells_intersection_p_func)(eff_cell, eff_desc,
555  converted_first_cell_in, first_cell_in_desc,
556  &intersection_test_exact_p))
557  {
558  pips_debug(4, "non empty intersection with first cell (%sexact)\n",
559  intersection_test_exact_p? "": "non ");
560  if (cell_relation_exact_p(pv_in)
561  && intersection_test_exact_p
562  && (*cells_inclusion_p_func)(eff_cell, eff_desc,
563  converted_first_cell_in, first_cell_in_desc,
564  &inclusion_test_exact_p)
565  && inclusion_test_exact_p)
566  {
567  if (cell_relation_undefined_p(*exact_aliased_pv))
568  {
569  pips_debug(4, "exact value candidate found\n");
570  *exact_aliased_pv = pv_in;
571  }
572  else if ((cell_relation_second_address_of_p(*exact_aliased_pv)
576  {
577  pips_debug(4, "better exact value candidate found\n");
578  l_res = CONS(CELL_RELATION, *exact_aliased_pv, l_res);
579  *exact_aliased_pv = pv_in;
580  }
581  else
582  {
583  pips_debug(4, "not kept as exact candidate\n");
584  l_res = CONS(CELL_RELATION, pv_in, l_res);
585  }
586  }
587  else
588  {
589  pips_debug(5, "potentially non exact value candidate found\n");
590  l_res = CONS(CELL_RELATION, pv_in, l_res);
591  }
592  }
593  else if(cell_relation_second_value_of_p(pv_in)
594  && (*cells_intersection_p_func)(eff_cell, eff_desc,
595  converted_second_cell_in, second_cell_in_desc,
596  &intersection_test_exact_p))
597  {
598  pips_debug(4, "non empty intersection with second value_of cell "
599  "(%sexact)\n", intersection_test_exact_p? "": "non ");
600  if(cell_relation_exact_p(pv_in)
601  && intersection_test_exact_p
602  && (*cells_inclusion_p_func)(eff_cell, eff_desc,
603  second_cell_in, second_cell_in_desc,
604  &inclusion_test_exact_p)
605  && inclusion_test_exact_p)
606  {
607  if (cell_relation_undefined_p(*exact_aliased_pv))
608  {
609  pips_debug(4, "exact value candidate found\n");
610  *exact_aliased_pv = pv_in;
611  }
612  else if (cell_relation_second_address_of_p(*exact_aliased_pv))
613  {
614  pips_debug(4, "better exact value candidate found\n");
615  l_res = CONS(CELL_RELATION, *exact_aliased_pv, l_res);
616  *exact_aliased_pv = pv_in;
617  }
618  else
619  {
620  pips_debug(4, "not kept as exact candidate\n");
621  l_res = CONS(CELL_RELATION, pv_in, l_res);
622  }
623  }
624  else
625  {
626  pips_debug(5, "potentially non exact value candidate found\n");
627  l_res = CONS(CELL_RELATION, pv_in, l_res);
628  }
629  }
630  else
631  {
632  pips_debug(4, "remnant\n");
633  *l_in_remnants = CONS(CELL_RELATION, pv_in, *l_in_remnants);
634  }
635  // here we should free the converted cells and descriptors if necessary
636  }
637  pips_debug_pvs(3, "l_in_remnants:", *l_in_remnants);
638  pips_debug_pvs(3, "l_res:", l_res);
639  pips_debug_pv(3, "*exact_aliased_pv:", *exact_aliased_pv);
640 
641  return l_res;
642 }
643 
644 
645 /*
646  @brief tries to find in the input pointer values list aliases to
647  the input cell and its descriptor.
648 
649  There is no sharing between the returned list cells and the
650  input reference.
651 
652  When the input cell contains no dereferencing dimension
653  the result is an empty list. The caller should check this
654  case before calling the function because an empty list when there
655  is a dereferencing dimension means that no target has been found
656  and that the input path may point to anywhere (this has to evolve).
657 
658 
659  @param c is a the cell for which we look equivalent paths
660  @param l_pv is the list of pointer values in which we search for equivalent paths
661  @param exact_p is a pointer towards a boolean. It is set to true if
662  the result is exact, and to false if it is an approximation,
663  either because the matching pointer values sources found in l_pv are
664  over-approximations of the preceding path of the input cell or because
665  the matching pointer values have MAY approximation tag.
666  @return a list of equivalent path effects. It is a list because at a given
667  program point the cell may correspond to several paths.
668 
669 
670  Comments to generic_eval_cell_with_points_to may apply here to.
671  */
672 
674  effect eff, list l_pv, bool *exact_p,
677  cell, descriptor ,
678  transformer, bool, bool * ),
679  void (*cell_with_address_of_cell_translation_func)
680  (cell, descriptor,
681  cell, descriptor,
682  int,
683  cell *, descriptor *,
684  bool *),
685  void (*cell_with_value_of_cell_translation_func)
686  (cell, descriptor,
687  cell, descriptor,
688  int,
689  cell *, descriptor *,
690  bool *),
691  bool (*cells_intersection_p_func)(cell, descriptor,
692  cell, descriptor,
693  bool *),
694  bool (*cells_inclusion_p_func)(cell, descriptor,
695  cell, descriptor,
696  bool*),
697  void (*simple_cell_conversion_func)(cell, cell *, descriptor *))
698 {
699  list l_res = NIL;
700  list l_remnants = l_pv;
701  cell eff_cell = effect_cell(eff);
702  descriptor eff_desc= effect_descriptor(eff);
703  // reference eff_ref = effect_any_reference(eff);
704  bool anywhere_p = false;
705 
706  pips_debug_effect(5, "begin with eff:", eff);
707  pips_debug_pvs(5, "and l_pv:", l_pv);
708 
709  if (anywhere_effect_p(eff)
711  || undefined_pointer_value_cell_p(effect_cell(eff))) /* should it be turned into entity_abstract_location_p (?) */
712  {
713  pips_debug(5, "anywhere, undefined or null case\n");
714  return (NIL);
715  }
716  else
717  {
718  /* first we must find in eff intermediary paths to pointers */
719  list l_intermediary = effect_intermediary_pointer_paths_effect(eff);
720  pips_debug_effects(5, "intermediary paths to eff:", l_intermediary);
721 
722  /* and find if this gives equivalent paths in l_pv */
723  FOREACH(EFFECT, eff_intermediary, l_intermediary)
724  {
725  pips_debug_effect(5, "considering intermediary path:", eff_intermediary);
726  list tmp_l_remnants = NIL;
728  list l_equiv =
729  generic_effect_find_equivalent_simple_pointer_values(eff_intermediary, l_remnants,
730  &pv_exact, &tmp_l_remnants,
731  cells_intersection_p_func,
732  cells_inclusion_p_func,
733  simple_cell_conversion_func);
734  if (!cell_relation_undefined_p(pv_exact))
735  {
736  l_equiv = CONS(CELL_RELATION, pv_exact, l_equiv);
737  }
738  l_remnants = tmp_l_remnants;
739  pips_debug_pvs(5, "list of equivalent pvs \n", l_equiv);
740 
741  cell cell_intermediary = effect_cell(eff_intermediary);
742  reference ref_intermediary = effect_any_reference(eff_intermediary);
743  //entity ent_intermediary = reference_variable(ref_intermediary);
744  //descriptor d_intermediary = effect_descriptor(eff_intermediary);
745  int nb_common_indices =
746  (int) gen_length(reference_indices(ref_intermediary));
747 
748  FOREACH(CELL_RELATION, pv_equiv, l_equiv)
749  {
750  cell c = cell_undefined;
752  bool exact_translation_p;
753  cell c1 = cell_relation_first_cell(pv_equiv);
754  cell c2 = cell_relation_second_cell(pv_equiv);
755 
756  pips_debug_pv(5, "translating eff using pv: \n", pv_equiv);
757 
760  {
761  pips_debug(5,"potential dereferencement of an undefined pointer -> returning undefined\n");
763  if (cell_relation_may_p(pv_equiv))
764  effects_to_may_effects(l_res);
765  anywhere_p = true;
766  }
767  else if (null_pointer_value_cell_p(c1)
769  {
770  pips_debug(5,"potential dereferencement of a null pointer -> returning null\n");
772  if (cell_relation_may_p(pv_equiv))
773  effects_to_may_effects(l_res);
774  anywhere_p = true;
775  }
776  else
777  {
778  /* this is valid only if the first value_of corresponds
779  * to eff_intermediary
780  */
781 
782  /* This test is valid here because by construction either c1 or c2 is an equivalent
783  * for eff_intermediary
784  */
785  if (same_entity_p(cell_entity(cell_intermediary), cell_entity(c1))
786  && (gen_length(reference_indices(ref_intermediary)) == gen_length(cell_indices(c1))))
787  {
788  cell converted_c2 = cell_undefined;
789  descriptor converted_d2 = descriptor_undefined;
790  (*simple_cell_conversion_func)(c2, &converted_c2, &converted_d2);
791 
792  /* use second cell as equivalent value for intermediary path */
793  if (cell_relation_second_value_of_p(pv_equiv))
794  {
795  (*cell_with_value_of_cell_translation_func)
796  (eff_cell, eff_desc,
797  converted_c2, converted_d2,
798  nb_common_indices,
799  &c, &d, &exact_translation_p);
800  }
801  else /* cell_relation_second_address_of_p is true */
802  {
803  (*cell_with_address_of_cell_translation_func)
804  (eff_cell, eff_desc,
805  converted_c2, converted_d2,
806  nb_common_indices,
807  &c, &d, &exact_translation_p);
808  }
809  // we should maybe free converted stuff here
810  }
811  else /* use first cell as equivalent value for intermediary path */
812  {
813  pips_assert("pv_equiv must be value_of here\n",
815  cell converted_c1 = cell_undefined;
816  descriptor converted_d1 = descriptor_undefined;
817  (*simple_cell_conversion_func)(c1, &converted_c1, &converted_d1);
818 
819  (*cell_with_value_of_cell_translation_func)
820  (eff_cell, eff_desc,
821  converted_c1, converted_d1,
822  nb_common_indices,
823  &c, &d, &exact_translation_p);
824 
825  // we should maybe free converted stuff here
826  }
827  exact_translation_p = effect_exact_p(eff_intermediary) && exact_translation_p && cell_relation_exact_p(pv_equiv);
828 
829  effect eff_alias = make_effect(c,
830  copy_action(effect_action(eff_intermediary)),
831  exact_translation_p ?
835 
836  pips_debug_effect(5, "resulting effect \n", eff_alias);
837  // there we should perform a union...
838  if (anywhere_effect_p(eff_alias))
839  {
840  gen_full_free_list(l_res);
841  l_res = CONS(EFFECT, eff_alias, NIL);
842  anywhere_p = true;
843  }
844  else
845  {
846  l_res = CONS(EFFECT, eff_alias, l_res);
847  }
848  }
849  } /* FOREACH */
850  }
851 
852  if (!anywhere_p)
853  {
854  pips_debug_effects(5, "l_res after first phase : \n", l_res);
855 
856  /* Then we must find if there are address_of second cells
857  * which are preceding paths of eff path
858  * in which case they must be used to generate other aliased paths
859  */
860  list l_remnants_2 = NIL;
861  FOREACH(CELL_RELATION, pv_remnant, l_remnants)
862  {
863  cell pv_remnant_second_cell =
864  cell_relation_second_cell(pv_remnant);
865  bool exact_preceding_test = true;
866 
867  pips_debug_pv(5, "considering pv: \n", pv_remnant);
868 
869  cell pv_remnant_converted_cell = cell_undefined;
870  descriptor pv_remnant_converted_desc = descriptor_undefined;
871 
872  // this (maybe costly) translation should take place after the first 3 tests
873  (*simple_cell_conversion_func)(pv_remnant_second_cell,
874  &pv_remnant_converted_cell,
875  &pv_remnant_converted_desc);
876 
877  if (cell_relation_second_address_of_p(pv_remnant)
879  cell_entity(pv_remnant_second_cell))
880  && (gen_length(cell_indices(eff_cell))
881  >= gen_length(cell_indices(pv_remnant_second_cell)))
882  && (*cell_preceding_p_func)(pv_remnant_converted_cell, pv_remnant_converted_desc,
883  eff_cell, eff_desc,
885  true,
886  &exact_preceding_test))
887  {
888  cell c;
890  bool exact_translation_p;
891 
892  pips_debug(5, "good candidate (%sexact)\n",exact_preceding_test? "":"non ");
893  /* for the translation, add a dereferencing_dimension to pv_remnant_first_cell */
894  reference new_ref = copy_reference
896  int nb_common_indices = (int) gen_length(cell_indices(pv_remnant_second_cell));
897  reference_indices(new_ref) = gen_nconc(reference_indices(new_ref),
900  NIL));
901  cell new_cell = make_cell_reference(new_ref);
902  cell new_converted_cell = cell_undefined;
903  descriptor new_converted_desc = descriptor_undefined;
904  (*simple_cell_conversion_func)(new_cell,
905  &new_converted_cell,
906  &new_converted_desc);
907 
908  (*cell_with_value_of_cell_translation_func)
909  (eff_cell, eff_desc,
910  new_converted_cell, new_converted_desc,
911  nb_common_indices,
912  &c, &d, &exact_translation_p);
913 
914  exact_translation_p = exact_translation_p && cell_relation_exact_p(pv_remnant);
915 
916  effect eff_alias = make_effect(c,
918  exact_translation_p && exact_preceding_test ?
922  free_cell(new_cell);
923  // we should also free new_converted_cell and new_converted_desc if they have actually been translated
924  pips_debug_effect(5, "resulting effect \n", eff_alias);
925  l_res = CONS(EFFECT, eff_alias, l_res);
926 
927  }
928  else
929  {
930  l_remnants_2 = CONS(CELL_RELATION, pv_remnant, l_remnants_2);
931  }
932  } /* FOREACH */
933 
934  l_remnants = l_remnants_2;
935  } /* if (!anywhere_p)*/
936  if (!ENDP(l_remnants))
937  {
938  pips_debug(5, "recursing to find aliases to aliased effect...\n");
939  pips_debug_effects(5, "l_res before recursing : \n", l_res);
940  list l_recurs = NIL;
941  FOREACH(EFFECT, eff_alias, l_res)
942  {
943  l_recurs = gen_nconc(l_recurs,
945  l_remnants,
946  exact_p,
949  cell_with_address_of_cell_translation_func,
950  cell_with_value_of_cell_translation_func,
951  cells_intersection_p_func,
952  cells_inclusion_p_func,
953  simple_cell_conversion_func ));
954  }
955  l_res = gen_nconc(l_recurs, l_res);
956  }
957  } /* else branche of if (anywhere_effect_p(eff))*/
958 
959  pips_debug_effects(5, "returning : \n", l_res);
960  return l_res;
961 }
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
action copy_action(action p)
ACTION.
Definition: effects.c:77
descriptor make_descriptor(enum descriptor_utype tag, void *val)
Definition: effects.c:433
void free_effect(effect p)
Definition: effects.c:451
cell make_cell(enum cell_utype tag, void *val)
Definition: effects.c:290
void free_cell(cell p)
Definition: effects.c:249
approximation make_approximation_exact(void)
Definition: effects.c:185
approximation make_approximation(enum approximation_utype tag, void *val)
Definition: effects.c:176
approximation make_approximation_may(void)
Definition: effects.c:179
effect make_effect(cell a1, action a2, approximation a3, descriptor a4)
Definition: effects.c:484
descriptor make_descriptor_none(void)
Definition: effects.c:442
reference copy_reference(reference p)
REFERENCE.
Definition: ri.c:2047
bool entity_flow_or_context_sentitive_heap_location_p(entity e)
bool entity_heap_location_p(entity b)
package abstract location.
static reference ref
Current stmt (an integer)
Definition: adg_read_paf.c:163
bool entity_null_locations_p(entity e)
test if an entity is the NULL POINTER
bool entity_abstract_location_p(entity al)
reference make_anywhere_reference(type t)
This function should be located somewhere in effect-util in or near abstract locations.
cell make_anywhere_cell(type t)
void const char const char const int
#define pips_debug_effects(level, message, l_eff)
#define pips_debug_effect(level, message, eff)
for debug
static list generic_transform_sink_cells_from_matching_list(list matching_list, size_t current_max_path_length, bool *exact_p, reference input_ref, descriptor input_desc, void(*cell_reference_with_address_of_cell_reference_translation_func)(reference, descriptor, reference, descriptor, int, reference *, descriptor *, bool *), void(*cell_reference_conversion_func)(reference, reference *, descriptor *))
Build the return list with the points-to sinks to which we add/append the indices of input_ref which ...
Definition: eval.c:115
#define print_points_to_relations(l)
Definition: eval.c:56
list generic_reference_to_points_to_matching_list(reference input_ref, descriptor input_desc, size_t *p_current_max_path_length, bool *exact_p, transformer current_precondition, list ptl, void(*cell_reference_conversion_func)(reference, reference *, descriptor *), bool(*cell_reference_preceding_p_func)(reference, descriptor, reference, descriptor, transformer, bool, bool *))
This function has been outlined from generic_eval_cell_with_points_to() to reduce the size of a funct...
Definition: eval.c:224
static list use_default_sink_cell(reference input_ref, descriptor input_desc __attribute__((__unused__)), void(*cell_reference_with_address_of_cell_reference_translation_func)(reference, descriptor, reference, descriptor, int, reference *, descriptor *, bool *) __attribute__((__unused__)), void(*cell_reference_conversion_func)(reference, reference *, descriptor *) __attribute__((__unused__)))
In case, the points-to information is not complete, use anywhere locations to convert the reference.
Definition: eval.c:68
list generic_effect_find_aliases_with_simple_pointer_values(effect eff, list l_pv, bool *exact_p, transformer current_precondition, bool(*cell_preceding_p_func)(cell, descriptor, cell, descriptor, transformer, bool, bool *), void(*cell_with_address_of_cell_translation_func)(cell, descriptor, cell, descriptor, int, cell *, descriptor *, bool *), void(*cell_with_value_of_cell_translation_func)(cell, descriptor, cell, descriptor, int, cell *, descriptor *, bool *), bool(*cells_intersection_p_func)(cell, descriptor, cell, descriptor, bool *), bool(*cells_inclusion_p_func)(cell, descriptor, cell, descriptor, bool *), void(*simple_cell_conversion_func)(cell, cell *, descriptor *))
Definition: eval.c:673
list generic_effect_find_equivalent_simple_pointer_values(effect eff, list l_in, cell_relation *exact_aliased_pv, list *l_in_remnants, bool(*cells_intersection_p_func)(cell, descriptor, cell, descriptor, bool *), bool(*cells_inclusion_p_func)(cell, descriptor, cell, descriptor, bool *), void(*simple_cell_conversion_func)(cell, cell *, descriptor *))
find pointer_values in l_in which give (possible or exact) paths equivalent to eff.
Definition: eval.c:506
list generic_eval_cell_with_points_to(cell input_cell, descriptor input_desc, list ptl, bool *exact_p, transformer current_precondition, bool(*cell_reference_preceding_p_func)(reference, descriptor, reference, descriptor, transformer, bool, bool *), void(*cell_reference_with_address_of_cell_reference_translation_func)(reference, descriptor, reference, descriptor, int, reference *, descriptor *, bool *), void(*cell_reference_conversion_func)(reference, reference *, descriptor *))
Definition: eval.c:361
int effects_statement_line_number(void)
To provide information when a but is encountered in the source file or within PIPS.
Definition: eval.c:208
void effects_to_may_effects(list)
effect make_undefined_pointer_value_effect(action)
bool(* cell_preceding_p_func)(cell, descriptor, cell, descriptor, bool, bool *)
statement effects_private_current_stmt_head(void)
list effect_intermediary_pointer_paths_effect(effect)
effect make_null_pointer_value_effect(action)
list effect_to_list(effect)
#define effect_may_p(eff)
#define effect_any_reference(e)
FI: cannot be used as a left hand side.
#define pips_debug_pv(level, message, pv)
#define make_reference_simple_effect(reference, action, approximation)
#define cell_relation_may_p(cr)
#define cell_relation_second_cell(cr)
#define pips_debug_pvs(level, message, l_pv)
#define cell_relation_exact_p(cr)
#define cell_relation_second_address_of_p(cr)
#define cell_relation_second_value_of_p(cr)
#define cell_relation_first_cell(cr)
#define effect_exact_p(eff)
bool undefined_pointer_value_cell_p(cell)
type points_to_reference_to_concrete_type(reference)
Definition: type.c:685
list cell_indices(cell)
Definition: effects.c:64
reference cell_any_reference(cell)
API for reference.
Definition: effects.c:77
bool effect_reference_dereferencing_p(reference, bool *)
Definition: type.c:233
points_to points_to_with_stripped_sink(points_to, int(*)(void))
The value of the source can often be expressed with different subscript lists.
Definition: points_to.c:1074
bool generic_atomic_points_to_reference_p(reference, bool)
Is it a unique concrete memory location?
Definition: points_to.c:489
entity effect_entity(effect)
cproto-generated files
Definition: effects.c:52
action make_action_write_memory(void)
To ease the extension of action with action_kind.
Definition: effects.c:1011
list word_points_to(points_to)
Definition: prettyprint.c:242
reference cell_to_reference(cell)
FI: probably to be moved elsewhere in ri-util.
Definition: effects.c:1326
bool nowhere_cell_p(cell)
Target of an undefined pointer.
Definition: effects.c:455
bool anywhere_effect_p(effect)
Is it an anywhere effect? ANYMMODULE:ANYWHERE
Definition: effects.c:346
string effect_reference_to_string(reference)
Definition: prettyprint.c:155
bool null_pointer_value_cell_p(cell)
bool null_cell_p(cell)
Definition: effects.c:466
entity cell_entity(cell)
Definition: effects.c:57
#define cell_reference(x)
Definition: effects.h:469
#define CELL_RELATION(x)
CELL_RELATION.
Definition: effects.h:479
#define cell_undefined
Definition: effects.h:430
#define approximation_exact_p(x)
Definition: effects.h:369
#define effect_action(x)
Definition: effects.h:642
#define approximation_may_p(x)
Definition: effects.h:363
#define cell_relation_undefined
Definition: effects.h:485
@ is_cell_reference
Definition: effects.h:445
@ is_descriptor_none
Definition: effects.h:576
#define effect_descriptor(x)
Definition: effects.h:646
#define descriptor_undefined
Definition: effects.h:559
@ is_approximation_may
Definition: effects.h:341
@ is_approximation_exact
Definition: effects.h:343
#define descriptor_undefined_p(x)
Definition: effects.h:560
#define EFFECT(x)
EFFECT.
Definition: effects.h:608
#define effect_cell(x)
Definition: effects.h:640
#define cell_relation_undefined_p(x)
Definition: effects.h:486
bool get_bool_property(const string)
FC 2015-07-20: yuk, moved out to prevent an include cycle dependency include "properties....
void gen_full_free_list(list l)
Definition: genClib.c:1023
#define ENDP(l)
Test if a list is empty.
Definition: newgen_list.h:66
list gen_nreverse(list cp)
reverse a list in place
Definition: list.c:304
#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
list gen_nconc(list cp1, list cp2)
physically concatenates CP1 and CP2 but do not duplicates the elements
Definition: list.c:344
void gen_free_list(list l)
free the spine of the list
Definition: list.c:327
#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
#define debug_on(env)
Definition: misc-local.h:157
#define pips_debug
these macros use the GNU extensions that allow variadic macros, including with an empty list.
Definition: misc-local.h:145
#define pips_assert(what, predicate)
common macros, two flavors depending on NDEBUG
Definition: misc-local.h:172
#define debug_off()
Definition: misc-local.h:160
#define UU
Definition: newgen_types.h:98
#define points_to_approximation(x)
#define points_to_sink(x)
#define POINTS_TO(x)
POINTS_TO.
#define points_to_source(x)
string reference_to_string(reference r)
Definition: expression.c:87
bool same_entity_p(entity e1, entity e2)
predicates on entities
Definition: entity.c:1321
expression int_to_expression(_int i)
transform an int into an expression and generate the corresponding entity if necessary; it is not cle...
Definition: expression.c:1188
#define transformer_undefined
Definition: ri.h:2847
#define reference_undefined
Definition: ri.h:2302
#define reference_variable(x)
Definition: ri.h:2326
#define EXPRESSION(x)
EXPRESSION.
Definition: ri.h:1217
#define reference_indices(x)
Definition: ri.h:2328
#define statement_number(x)
Definition: ri.h:2452
int fprintf()
test sc_min : ce test s'appelle par : programme fichier1.data fichier2.data ...
#define semantics_user_warning
static transformer current_precondition
#define ifdebug(n)
Definition: sg.c:47
The structure used to build lists in NewGen.
Definition: newgen_list.h:41
string words_to_string(cons *lw)
Definition: print.c:211