PIPS
pointer_values_analyses.c
Go to the documentation of this file.
1 /*
2 
3  $Id: pointer_values_analyses.c 23065 2016-03-02 09:05:50Z coelho $
4 
5  Copyright 1989-2016 MINES ParisTech
6  Copyright 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 
32 #include "genC.h"
33 #include "linear.h"
34 #include "ri.h"
35 #include "ri-util.h"
36 #include "workspace-util.h" // for module_to_all_declarations
37 #include "prettyprint.h"
38 #include "effects.h"
39 #include "effects-util.h"
40 #include "text-util.h"
41 #include "effects-simple.h"
42 #include "effects-generic.h"
43 #include "pipsdbm.h"
44 #include "misc.h"
45 
46 #include "pointer_values.h"
47 
48 /******************** MAPPINGS */
49 
50 /* I don't know how to deal with these mappings if we have to analyse several modules
51  at the same time when performing an interprocedural analysis.
52  We may need a stack of mappings, or a global mapping for the whole program,
53  and a temporary mapping to store the resources one module at a time
54 */
58 
59 
60 
61 /******************** PIPSDBM INTERFACES */
62 
64 {
65  return (statement_cell_relations) db_get_memory_resource(DBR_SIMPLE_POINTER_VALUES, module_name, true);
66 }
67 
69 {
70  DB_PUT_MEMORY_RESOURCE(DBR_SIMPLE_POINTER_VALUES, module_name, (char*) scr);
71 }
72 
74 {
75  return (list) cell_relations_list((cell_relations) db_get_memory_resource(DBR_IN_SIMPLE_POINTER_VALUES, module_name, true));
76 }
77 
78 void db_put_in_simple_pv(const char * module_name, list l_pv)
79 {
80  DB_PUT_MEMORY_RESOURCE(DBR_IN_SIMPLE_POINTER_VALUES, module_name, (char*) make_cell_relations(l_pv));
81 }
82 
84 {
85  return cell_relations_list((cell_relations) db_get_memory_resource(DBR_OUT_SIMPLE_POINTER_VALUES, module_name, true));
86 }
87 
88 void db_put_out_simple_pv(const char * module_name, list l_pv)
89 {
90  DB_PUT_MEMORY_RESOURCE(DBR_OUT_SIMPLE_POINTER_VALUES, module_name, (char*) make_cell_relations(l_pv));
91 }
92 
94 {
95  return cell_relations_list((cell_relations) db_get_memory_resource(DBR_INITIAL_SIMPLE_POINTER_VALUES, module_name, true));
96 }
97 
98 void db_put_initial_simple_pv(const char * module_name, list l_pv)
99 {
100  DB_PUT_MEMORY_RESOURCE(DBR_INITIAL_SIMPLE_POINTER_VALUES, module_name, (char*) make_cell_relations(l_pv));
101 }
102 
104 {
105  return cell_relations_list((cell_relations) db_get_memory_resource(DBR_PROGRAM_SIMPLE_POINTER_VALUES, "", true));
106 }
107 
109 {
110  DB_PUT_MEMORY_RESOURCE(DBR_PROGRAM_SIMPLE_POINTER_VALUES, "", (char*) make_cell_relations(l_pv));
111 }
112 
113 
114 
115 
116 /******************** ANALYSIS CONTEXT */
117 
118 
120 {
121  pv_context ctxt;
122 
123  ctxt.initial_pointer_values_p = false;
124 
135 
146  ctxt.stmt_stack = stack_make(statement_domain, 0, 0);
147  return ctxt;
148 }
149 
150 
151 #define UNDEF abort
152 
153 typedef void (*void_function)();
154 typedef gen_chunk* (*chunks_function)();
155 typedef list (*list_function)();
156 typedef bool (*bool_function)();
161 
163 {
165  p_ctxt->db_put_pv_func = (void_function) UNDEF;
166 /* p_ctxt->db_get_gen_pv_func =(statement_cell_relations_function) UNDEF ; */
167 /* p_ctxt->db_put_gen_pv_func = (void_function) UNDEF; */
168 /* p_ctxt->db_get_kill_pv_func = (statement_effects_function) UNDEF; */
169 /* p_ctxt->db_put_kill_pv_func = (void_function) UNDEF; */
175 }
176 
178 {
179  stack_push((void *) s, ctxt->stmt_stack);
180 }
181 
183 {
184  (void) stack_pop( ctxt->stmt_stack);
185 }
186 
188 {
189  return ((statement) stack_head(ctxt->stmt_stack));
190 }
191 
192 /************* RESULTS HOOK */
193 
195 {
196  pv_results pv_res;
197  pv_res.l_out = NIL;
198  pv_res.result_paths = NIL;
200  return pv_res;
201 }
202 
204 {
206  pv_res->result_paths = NIL;
209 }
210 
212 {
213  fprintf(stderr, "l_out =");
214  print_pointer_values(pv_res.l_out);
215  list l_rp = pv_res.result_paths;
216  list l_rpi = pv_res.result_paths_interpretations;
217 
218  if (!ENDP(l_rp))
219  {
220  fprintf(stderr, "result_paths are:\n");
221  for(; !ENDP(l_rp); POP(l_rp), POP(l_rpi))
222  {
223  effect eff = EFFECT(CAR(l_rp));
225  fprintf(stderr, "%s:",
227  ? "value of" : "address of");
228  (*effect_prettyprint_func)(eff);
229  }
230  }
231  else
232  fprintf(stderr, "result_path is undefined\n");
233 }
234 
235 /******************** SOME UTILITIES (to move elsewhere?) */
236 
238 {
241  copy_cell(anywhere_c),
244  return (CONS(CELL_RELATION, pv, NIL));
245 }
246 
247 /******************** LOCAL FUNCTIONS DECLARATIONS */
248 
249 static
251 
252 static
254 
255 static
256 list declarations_to_post_pv(list l_decl, list l_in, pv_context *ctxt);
257 
258 static
260 
261 static
263 
264 static
265 list test_to_post_pv(test t, list l_in, pv_context *ctxt);
266 
267 static
268 list loop_to_post_pv(loop l, list l_in, pv_context *ctxt);
269 
270 static
272 
273 static
275 
276 static
278 
279 
280 static
281 void call_to_post_pv(call c, list l_in, pv_results *pv_res, pv_context *ctxt);
282 
283 
284 
285 
286 /**************** MODULE ANALYSIS *************/
287 
288 static
290 {
291  list l_cur = l_in;
292  list l_locals = NIL;
293  pips_debug(1, "begin\n");
295  {
296  ifdebug(2){
297 
298  pips_debug(2, "dealing with statement");
300  pips_debug_pvs(2, "l_cur =", l_cur);
301  }
302  /* keep local variables in declaration reverse order */
304  {
306  if(bound_pv_p(stmt))
308  else
311  {
312  type e_type = entity_basic_concrete_type(e);
313  storage e_storage = entity_storage(e);
314  /* beware don't push static variables and non pointer variables. */
315  if (storage_ram_p(e_storage)
316  && ! static_area_p(ram_section(storage_ram(e_storage)))
317  && ! type_fundamental_basic_p(e_type)
319  l_locals = CONS(ENTITY, e, l_locals);
320  l_cur = declaration_to_post_pv(e, l_cur, ctxt);
321  }
322  //store_gen_pv(stmt, make_cell_relations(NIL));
323  //store_kill_pv(stmt, make_effects(NIL));
325  }
326  else
327  l_cur = statement_to_post_pv(stmt, l_cur, ctxt);
328 
329  }
330 
331  /* don't forget to eliminate local declarations on exit */
332  /* ... */
333  if (!ENDP(l_locals))
334  {
335  pips_debug(5, "eliminating local variables\n");
336  expression rhs_exp =
338 
339  FOREACH(ENTITY, e, l_locals)
340  {
341  pips_debug(5, "dealing with %s\n", entity_name(e));
342  pv_results pv_res = make_pv_results();
343  pointer_values_remove_var(e, false, l_cur, &pv_res, ctxt);
344  l_cur= pv_res.l_out;
345  free_pv_results_paths(&pv_res);
346  }
347  free_expression(rhs_exp);
348  }
349 
350  pips_debug_pvs(2, "returning:", l_cur);
351  pips_debug(1, "end\n");
352  return (l_cur);
353 }
354 
355 static
357 {
358  list l_out = NIL;
359  pips_debug(1, "begin\n");
361  pips_debug_pvs(2, "input pvs:", l_in);
362 
363  if(bound_pv_p(stmt))
365  else
367 
369  {
370  list l_decl = statement_declarations(stmt);
371  l_out = declarations_to_post_pv(l_decl, l_in, ctxt);
372  }
373  else
374  {
375  l_out = instruction_to_post_pv(statement_instruction(stmt), l_in, ctxt);
376  }
377 
378  pips_debug_pvs(2, "before composition_with_transformer:", l_out);
380 
381  //store_gen_pv(stmt, make_cell_relations(NIL));
382  //store_kill_pv(stmt, make_effects(NIL));
383  pips_debug_pvs(2, "returning:", l_out);
384  pips_debug(1, "end\n");
386 
387  return (l_out);
388 }
389 
390 static
392 {
393  list l_out = l_in;
394  pips_debug(1, "begin\n");
395 
396  FOREACH(ENTITY, e, l_decl)
397  {
398  /* well, not exactly, we must take kills into account */
399  l_out = gen_nconc(l_out, declaration_to_post_pv(e, l_out, ctxt));
400  }
401  pips_debug_pvs(2, "returning: ", l_out);
402  pips_debug(1, "end\n");
403  return (l_out);
404 }
405 
406 
407 static
409 {
410  list l_out = NIL;
411  type e_type = entity_basic_concrete_type(e);
412 
413  if (type_variable_p(e_type) && !typedef_entity_p(e)
414  && !type_fundamental_basic_p(e_type)
416  {
417  pips_debug(1, "begin\n");
418  pips_debug(1, "entity %s basic concrete type %s %s\n",
419  entity_name(e), type_to_string(e_type), string_of_type(e_type));
420  expression lhs_exp = entity_to_expression(e);
422  bool free_rhs_exp = false; /* turned to true if rhs_exp is built and
423  must be freed */
424 
425  value v_init = entity_initial(e);
426  bool static_p = (!ctxt->initial_pointer_values_p) && entity_static_variable_p(e);
427 
428  bool ignore = false;
429 
430 
431  /* in case of a local static variable, and when not dealing with the initial analysis,
432  we should generate a stub sink */
433 
434  if (v_init == value_undefined)
435  {
436  pips_debug(2, "undefined inital value\n");
437 
438  if (std_file_entity_p(e))
439  {
440  pips_debug(2, "standard file\n");
442  rhs_exp = make_address_of_expression(tmp_exp);
443  free_expression(tmp_exp);
444  }
445  else if (static_p)
446  /* when no initialization is provided for pointer static variables,
447  or aggregate variables which recursively have pointer fields,
448  then all pointers are initialized to NULL previous to program
449  execution.
450  */
452  else
454  free_rhs_exp = true;
455  }
456  else if (std_file_entity_p(e))
457  {
458  pips_debug(2, "standard file\n");
460  rhs_exp = make_address_of_expression(tmp_exp);
461  free_expression(tmp_exp);
462  free_rhs_exp = true;
463  }
464  else
465  {
466  switch (value_tag(v_init))
467  {
468  case is_value_expression:
469  rhs_exp = value_expression(v_init);
470  break;
471  case is_value_unknown:
472  pips_debug(2, "unknown inital value\n");
473  rhs_exp = expression_undefined;
474  break;
475  case is_value_code:
476  pips_debug(2, "value code\n");
478  {
479  const char * e_user_name = entity_user_name(e);
480  if (same_string_p(e_user_name, "__after_morecore_hook")
481  || same_string_p(e_user_name, "__free_hook")
482  || same_string_p(e_user_name, "__malloc_hook")
483  || same_string_p(e_user_name, "__malloc_initialize_hook")
484  || same_string_p(e_user_name, "__memalign_hook")
485  || same_string_p(e_user_name, "__morecore")
486  || same_string_p(e_user_name, "__realloc_hook"))
487  {
488  pips_debug(2, "standard library internal hook\n");
489  ignore = true;
490  }
491  else
492  {
493  pips_debug(2,"compilation unit, ignoring value for the moment\n");
494  }
495  }
496  else
497  pips_internal_error("unexpected tag\n");
498  break;
499  case is_value_symbolic:
500  pips_debug(2, "value symbolic\n");
501  pips_internal_error("unexpected tag\n");
502  break;
503  case is_value_constant:
504  pips_debug(2, "value constant\n");
505  pips_internal_error("unexpected tag\n");
506  break;
507  case is_value_intrinsic:
508  pips_debug(2, "value intrinsic\n");
509  pips_internal_error("unexpected tag\n");
510  break;
511  default:
512  pips_internal_error("unexpected tag\n");
513  }
514  }
515 
516  if (!ignore)
517  {
518  pv_results pv_res = make_pv_results();
519  assignment_to_post_pv(lhs_exp, static_p, rhs_exp, true, l_in, &pv_res, ctxt);
520  l_out = pv_res.l_out;
521  free_pv_results_paths(&pv_res);
522 
523  free_expression(lhs_exp);
524  if (free_rhs_exp) free_expression(rhs_exp);
525  pips_debug_pvs(2, "returning:", l_out);
526  pips_debug(1, "end\n");
527  }
528  else
529  l_out = l_in;
530  }
531  else
532  l_out = l_in;
533  return (l_out);
534 }
535 
536 static
538 {
539  list l_out = NIL;
540  pips_debug(1, "begin\n");
541 
542  switch(instruction_tag(inst))
543  {
545  l_out = sequence_to_post_pv(instruction_sequence(inst), l_in, ctxt);
546  break;
547  case is_instruction_test:
548  l_out = test_to_post_pv(instruction_test(inst), l_in, ctxt);
549  break;
550  case is_instruction_loop:
551  l_out = loop_to_post_pv(instruction_loop(inst), l_in, ctxt);
552  break;
554  l_out = whileloop_to_post_pv(instruction_whileloop(inst), l_in, ctxt);
555  break;
557  l_out = forloop_to_post_pv(instruction_forloop(inst), l_in, ctxt);
558  break;
560  l_out = unstructured_to_post_pv(instruction_unstructured(inst), l_in, ctxt);
561  break;
563  {
564  pv_results pv_res = make_pv_results();
565  expression_to_post_pv(instruction_expression(inst), l_in, &pv_res, ctxt);
566  l_out = pv_res.l_out;
567  free_pv_results_paths(&pv_res);
568  }
569  break;
570  case is_instruction_call:
571  {
572  pv_results pv_res = make_pv_results();
573  call_to_post_pv(instruction_call(inst), l_in, &pv_res, ctxt);
574  l_out = pv_res.l_out;
575  free_pv_results_paths(&pv_res);
576  }
577  break;
578  case is_instruction_goto:
579  pips_internal_error("unexpected goto in pointer values analyses");
580  break;
582  pips_internal_error("unexpected multitest in pointer values analyses");
583  break;
584  default:
585  pips_internal_error("unknown instruction tag");
586  }
587  pips_debug_pvs(2, "returning:", l_out);
588  pips_debug(1, "end\n");
589  return (l_out);
590 }
591 
592 static
594 {
595  list l_out = NIL;
596  pips_debug(1, "begin\n");
597 
598  expression t_cond = test_condition(t);
599  statement t_true = test_true(t);
600  statement t_false = test_false(t);
601 
602  pv_results pv_res = make_pv_results();
603  expression_to_post_pv(t_cond, l_in, &pv_res, ctxt);
604 
605  list l_in_branches = pv_res.l_out;
606 
607  list l_out_true = statement_to_post_pv(t_true, gen_full_copy_list(l_in_branches), ctxt);
608  list l_out_false = statement_to_post_pv(t_false, l_in_branches, ctxt);
609 
610  l_out = (*ctxt->pvs_may_union_func)(l_out_true, l_out_false);
611 
612  free_pv_results_paths(&pv_res);
613 
614  pips_debug_pvs(2, "returning: ", l_out);
615  pips_debug(1, "end\n");
616  return (l_out);
617 }
618 
619 #define PV_NB_MAX_ITER_FIX_POINT 3
620 
621 static
623 {
624  list l_out = NIL;
625  range r = loop_range(l);
626  list l_in_cur = l_in;
627  statement body = loop_body(l);
628  pips_debug(1, "begin\n");
629 
630  /* first loop range is evaluated */
631  pv_results pv_res = make_pv_results();
632  range_to_post_pv(r, l_in_cur, &pv_res, ctxt);
633  free_pv_results_paths(&pv_res);
634  l_in_cur = pv_res.l_out;
635  list l_saved = gen_full_copy_list(l_in_cur);
636 
637  /* then, the loop body is executed if and only if the upper bound
638  is greater than the lower bound, else the loop body is only possibly
639  executed.
640  */
641 
642  /* as a first approximation, we perform no test on the loop bounds,
643  and thus assume that the loop body is only possibly executed
644  */
645  int i = 0;
646  bool fix_point_reached = false;
647  l_out = pv_res.l_out;
648  do
649  {
650  pips_debug(3, "fix point iteration number %d.\n", i+1);
651  list l_iter_in = gen_full_copy_list(l_out);
652  l_out = statement_to_post_pv(body, l_out, ctxt);
653 
654  /* this iteration may never be executed :*/
655  l_out = (*ctxt->pvs_may_union_func)(l_out, gen_full_copy_list(l_iter_in));
656  i++;
657  fix_point_reached = (l_out == l_iter_in)
658  || (*ctxt->pvs_equal_p_func)(l_iter_in, l_out);
659  pips_debug(3, "fix point %s reached\n", fix_point_reached? "":"not");
660  gen_full_free_list(l_iter_in);
661  }
662  while(i<PV_NB_MAX_ITER_FIX_POINT && !fix_point_reached);
663 
664  if (!fix_point_reached)
665  {
666  pv_results pv_res_failed = make_pv_results();
668  list l_anywhere = CONS(EFFECT, anywhere_eff, NIL);
669  list l_kind = CONS(CELL_INTERPRETATION,
671  single_pointer_assignment_to_post_pv(anywhere_eff, l_anywhere, l_kind,
672  false, l_saved,
673  &pv_res_failed, ctxt);
674  l_out = pv_res_failed.l_out;
675  free_pv_results_paths(&pv_res_failed);
676  free_effect(anywhere_eff);
677  gen_free_list(l_anywhere);
678  gen_full_free_list(l_kind);
679 
680  /* now update input pointer values of inner loop statements */
681  l_in_cur = gen_full_copy_list(l_out);
682  list l_tmp = statement_to_post_pv(body, l_in_cur, ctxt);
683  gen_full_free_list(l_tmp);
684  }
685  else
686  gen_full_free_list(l_saved);
687 
688  pips_debug_pvs(1, "end with l_out =\n", l_out);
689  return (l_out);
690 }
691 
692 static
694 {
695  list l_out = NIL;
696  list l_in_cur = NIL;
697  list l_saved = gen_full_copy_list(l_in); /* in case fix point is not reached */
699  bool before_p = evaluation_before_p(whileloop_evaluation(l));
700  statement body = whileloop_body(l);
701  pips_debug(1, "begin\n");
702 
703  int i = 1;
704  bool fix_point_reached = false;
705  l_out = l_in;
706  do
707  {
708  pips_debug(3, "fix point iteration number %d.\n", i);
709  list l_iter_in = gen_full_copy_list(l_out);
710  l_in_cur = l_out;
711 
712  if(before_p)
713  {
714  pv_results pv_res_cond = make_pv_results();
715  expression_to_post_pv(cond, l_in_cur, &pv_res_cond, ctxt);
716  l_in_cur = pv_res_cond.l_out;
717  free_pv_results_paths(&pv_res_cond);
718  }
719 
720  l_out = statement_to_post_pv(body, l_in_cur, ctxt);
721 
722  if(!before_p)
723  {
724  pv_results pv_res_cond = make_pv_results();
725  expression_to_post_pv(cond, l_out, &pv_res_cond, ctxt);
726  l_out = pv_res_cond.l_out;
727  free_pv_results_paths(&pv_res_cond);
728  }
729 
730  /* this iteration may never be executed :*/
731  if (i!=1 || before_p)
732  l_out = (*ctxt->pvs_may_union_func)(l_out,
733  gen_full_copy_list(l_iter_in));
734  else
735  {
736  l_in = gen_full_copy_list(l_out);
737  }
738 
739  i++;
740  fix_point_reached = (l_out == l_iter_in)
741  || (*ctxt->pvs_equal_p_func)(l_iter_in, l_out);
742  pips_debug(3, "fix point %s reached\n", fix_point_reached? "":"not");
743  gen_full_free_list(l_iter_in);
744  }
745  while(i<=PV_NB_MAX_ITER_FIX_POINT && !fix_point_reached);
746 
747  if (!fix_point_reached)
748  {
749  pv_results pv_res_failed = make_pv_results();
751  list l_anywhere = CONS(EFFECT, anywhere_eff, NIL);
752  list l_kind = CONS(CELL_INTERPRETATION,
754  single_pointer_assignment_to_post_pv(anywhere_eff, l_anywhere, l_kind,
755  false, l_saved,
756  &pv_res_failed, ctxt);
757  l_out = pv_res_failed.l_out;
758  free_pv_results_paths(&pv_res_failed);
759  free_effect(anywhere_eff);
760  gen_free_list(l_anywhere);
761  gen_full_free_list(l_kind);
762 
763  /* now update input pointer values of inner loop statements */
764  l_in_cur = gen_full_copy_list(l_out);
765  if(before_p)
766  {
767  pv_results pv_res_cond = make_pv_results();
768  expression_to_post_pv(cond, l_in_cur, &pv_res_cond, ctxt);
769  l_in_cur = pv_res_cond.l_out;
770  free_pv_results_paths(&pv_res_cond);
771  }
772 
773  list l_tmp = statement_to_post_pv(body, l_in_cur, ctxt);
774 
775  if(!before_p)
776  {
777  pv_results pv_res_cond = make_pv_results();
778  expression_to_post_pv(cond, l_tmp, &pv_res_cond, ctxt);
779  free_pv_results_paths(&pv_res_cond);
780  gen_full_free_list(pv_res_cond.l_out);
781  }
782  else
783  gen_full_free_list(l_tmp);
784  }
785  else
786  gen_full_free_list(l_saved);
787 
788  pips_debug_pvs(2, "returning:", l_out);
789  pips_debug(1, "end\n");
790  return (l_out);
791 }
792 
793 static
795 {
796  list l_out = NIL;
797  list l_in_cur = NIL;
798  pips_debug(1, "begin\n");
799 
801  expression cond = forloop_condition(l);
802  expression incr = forloop_increment(l);
803  statement body = forloop_body(l);
804 
805  /* First, the initialization is always evaluatated */
806  pv_results pv_res_init = make_pv_results();
807  expression_to_post_pv(init, l_in, &pv_res_init, ctxt);
808  l_in_cur = pv_res_init.l_out;
809  l_in = gen_full_copy_list(l_in_cur); /* saved in case fix point is not reached */
810  free_pv_results_paths(&pv_res_init);
811 
812  int i = 1;
813  bool fix_point_reached = false;
814  l_out = l_in_cur;
815  do
816  {
817  pips_debug(3, "fix point iteration number %d.\n", i);
818  list l_iter_in = gen_full_copy_list(l_out);
819  l_in_cur = l_out;
820 
821  /* condition is evaluated before each iteration */
822  pv_results pv_res_cond = make_pv_results();
823  expression_to_post_pv(cond, l_in_cur, &pv_res_cond, ctxt);
824  l_in_cur = pv_res_cond.l_out;
825  free_pv_results_paths(&pv_res_cond);
826 
827  l_in_cur = statement_to_post_pv(body, l_in_cur, ctxt);
828 
829  /* increment expression is evaluated at the end of each iteration */
830  pv_results pv_res_incr = make_pv_results();
831  expression_to_post_pv(incr, l_in_cur, &pv_res_incr, ctxt);
832  l_in_cur = pv_res_incr.l_out;
833  free_pv_results_paths(&pv_res_incr);
834 
835  /* this iteration may never be executed :*/
836  l_out = (*ctxt->pvs_may_union_func)(l_in_cur,
837  gen_full_copy_list(l_iter_in));
838  i++;
839  fix_point_reached = (l_out == l_iter_in)
840  || (*ctxt->pvs_equal_p_func)(l_iter_in, l_out);
841  pips_debug(3, "fix point %s reached\n", fix_point_reached? "":"not");
842  gen_full_free_list(l_iter_in);
843  }
844  while(i<=PV_NB_MAX_ITER_FIX_POINT && !fix_point_reached);
845 
846  if (!fix_point_reached)
847  {
848  pv_results pv_res_failed = make_pv_results();
850  list l_anywhere = CONS(EFFECT, anywhere_eff, NIL);
851  list l_kind = CONS(CELL_INTERPRETATION,
853  single_pointer_assignment_to_post_pv(anywhere_eff, l_anywhere, l_kind,
854  false, l_in,
855  &pv_res_failed, ctxt);
856  l_out = pv_res_failed.l_out;
857  free_pv_results_paths(&pv_res_failed);
858  free_effect(anywhere_eff);
859  gen_free_list(l_anywhere);
860  gen_full_free_list(l_kind);
861 
862  /* now update input pointer values of inner loop statements */
863  l_in_cur = gen_full_copy_list(l_out);
864  pv_results pv_res_cond = make_pv_results();
865  expression_to_post_pv(cond, l_in_cur, &pv_res_cond, ctxt);
866  l_in_cur = pv_res_cond.l_out;
867  free_pv_results_paths(&pv_res_cond);
868 
869  list l_tmp = statement_to_post_pv(body, l_in_cur, ctxt);
870 
871  gen_full_free_list(l_tmp);
872  }
873 
874 
875  pips_debug_pvs(2, "returning:", l_out);
876  pips_debug(1, "end\n");
877  return (l_out);
878 }
879 
880 
881 static
883 {
884  list l_out = NIL;
885  control entry_ctrl = unstructured_entry( unstr );
886  statement entry_node = control_statement(entry_ctrl);
887 
888  if(control_predecessors(entry_ctrl) == NIL && control_successors(entry_ctrl) == NIL)
889  {
890  /* there is only one statement in u; */
891  pips_debug(6, "unique node\n");
892  l_out = statement_to_post_pv(entry_node, l_in, ctxt);
893  }
894  else
895  {
896  pips_user_warning("Pointer analysis for unstructured part of code not yet fully implemented:\n"
897  "Consider restructuring your code\n");
898  list l_in_anywhere = make_anywhere_anywhere_pvs();
899  list blocs = NIL ;
900  CONTROL_MAP(c, {
901  list l_out = statement_to_post_pv(control_statement(c), gen_full_copy_list(l_in_anywhere), ctxt);
902  gen_full_free_list(l_out);
903  },
904  unstructured_exit( unstr ), blocs) ;
905  gen_free_list(blocs);
906  l_out = make_anywhere_anywhere_pvs();
907  }
908  pips_debug_pvs(2, "returning: ", l_out);
909  pips_debug(1, "end\n");
910  return (l_out);
911 }
912 
913 void range_to_post_pv(range r, list l_in, pv_results * pv_res, pv_context *ctxt)
914 {
915  expression el = range_lower(r);
916  expression eu = range_upper(r);
917  expression ei = range_increment(r);
918 
919  pips_debug(1, "begin\n");
920 
921  expression_to_post_pv(el, l_in, pv_res, ctxt);
922  expression_to_post_pv(eu, pv_res->l_out, pv_res, ctxt);
923  expression_to_post_pv(ei, pv_res->l_out, pv_res, ctxt);
924 
925  free_pv_results_paths(pv_res);
926 
927  pips_debug_pvs(1, "end with pv_res->l_out:\n", pv_res->l_out);
928 }
929 
931 {
933  {
934  pips_debug(1, "begin for undefined expression, returning undefined pointer_value\n");
935  pv_res->l_out = l_in;
942  }
943  else
944  {
945  pips_debug(1, "begin for expression : %s\n",
947 
948  syntax exp_syntax = expression_syntax(exp);
949 
950  switch(syntax_tag(exp_syntax))
951  {
952  case is_syntax_reference:
953  pips_debug(5, "reference case\n");
954  reference exp_ref = syntax_reference(exp_syntax);
955  if (same_string_p(entity_local_name(reference_variable(exp_ref)), "NULL"))
956  {
963  NIL);
964  }
965  else
966  {
967  // functions that can be pointed by reference_to_effect_func:
968  // reference_to_simple_effect
969  // reference_to_convex_region
970  // reference_to_reference_effect
971  pv_res->result_paths = CONS(EFFECT,
973  (copy_reference(exp_ref),
975  false), NIL);
978  NIL);
979  }
980  /* we assume no effects on aliases due to subscripts evaluations for the moment */
981  pv_res->l_out = l_in;
982  break;
983  case is_syntax_range:
984  pips_internal_error("not yet implemented");
985  break;
986  case is_syntax_call:
987  {
988  call_to_post_pv(syntax_call(exp_syntax), l_in, pv_res, ctxt);
989  break;
990  }
991  case is_syntax_cast:
992  {
994  l_in, pv_res, ctxt);
995  pips_debug(5, "cast case\n");
996  break;
997  }
999  {
1000  /* we assume no effects on aliases due to sizeof argument expression
1001  * for the moment */
1002  pv_res->l_out = l_in;
1003  break;
1004  }
1005  case is_syntax_subscript:
1006  {
1007  pips_debug(5, "subscript case\n");
1008  /* aborts if there are calls in subscript expressions */
1009  list l_eff = NIL;
1011  gen_full_free_list(l_tmp);
1012  FOREACH(EFFECT, eff, l_eff)
1013  {
1014  pv_res->result_paths = CONS(EFFECT, eff, NIL);
1017  NIL);
1018  }
1019  gen_free_list(l_eff); /* free the spine */
1020  /* we assume no effects on aliases due to subscripts evaluations for the moment */
1021  pv_res->l_out = l_in;
1022  break;
1023  }
1024  case is_syntax_application:
1025  pips_internal_error("not yet implemented");
1026  break;
1027  case is_syntax_va_arg:
1028  {
1029  pips_internal_error("not yet implemented");
1030  break;
1031  }
1032  default:
1033  pips_internal_error("unexpected tag %d", syntax_tag(exp_syntax));
1034  break;
1035  }
1036  }
1037 
1038  pips_debug_pv_results(1, "end with pv_results =\n", *pv_res);
1039  pips_debug(1, "end\n");
1040  return;
1041 }
1042 
1043 
1044 
1045 static void
1047 {
1048  entity func = call_function(c);
1049  list func_args = call_arguments(c);
1050  pips_debug(1, "begin for %s\n", entity_local_name(func));
1051 
1052  /* the expression that denotes the called function and the arguments
1053  * are evaluated; then there is a sequence point, and the function is called
1054  */
1055 
1056  /* Arguments evaluation: we don't use expressions_to_post_pv because
1057  * we want to accumulate the results paths
1058  */
1059 
1060  list l_cur = l_in;
1061  pv_results pv_res_exp_eval = make_pv_results();
1062  FOREACH(EXPRESSION, arg, func_args)
1063  {
1064  pv_results pv_res_cur = make_pv_results();
1065  expression_to_post_pv(arg, l_cur, &pv_res_cur, ctxt);
1066  l_cur = pv_res_cur.l_out;
1067  pv_res_exp_eval.result_paths = gen_nconc(pv_res_exp_eval.result_paths, pv_res_cur.result_paths);
1068  pv_res_exp_eval.result_paths_interpretations = gen_nconc(pv_res_exp_eval.result_paths_interpretations,
1069  pv_res_cur.result_paths_interpretations);
1070  }
1071 
1072  /* Function call: we generate abstract_location targets for all
1073  * possible effects from arguments. We should also do the same for
1074  * all global variables in the current compilation unit...
1075  */
1076  list l_ci = pv_res_exp_eval.result_paths_interpretations;
1077  FOREACH(EFFECT, real_arg_eff, pv_res_exp_eval.result_paths)
1078  {
1079  pips_debug_effect(3, "considering effect:\n", real_arg_eff);
1081  bool add_eff = cell_interpretation_address_of_p(ci);
1082  bool to_be_freed = false;
1083  type t = cell_to_type(effect_cell(real_arg_eff), &to_be_freed);
1084 
1085  // generate all possible effects on pointers from the actual parameter
1087  t,
1088  'w',
1089  add_eff,
1090  10, /* to avoid too long paths until GAPS are handled */
1091  true); /* only pointers */
1092  if (to_be_freed) free_type(t);
1093  pips_debug_effects(3, "effects to be killed:\n", lw);
1094 
1095  if (!ENDP(lw))
1096  {
1097  // potentially kill these paths and generate abstract location targets (currently anywhere)
1101  FOREACH(EFFECT, eff, lw)
1102  {
1103  single_pointer_assignment_to_post_pv(eff, l_abstract_eff, l_ci_abstract_eff,
1104  false, l_cur,
1105  pv_res, ctxt);
1106  l_cur = pv_res->l_out;
1107  }
1108 
1109  gen_full_free_list(lw);
1110  }
1111  POP(l_ci);
1112  }
1113  pv_res->l_out = l_cur;
1114 
1115  /* Return value: test the type of the result path : if it's a
1116  * pointer type, generate an abstract location target of the pointed
1117  * type, else it's an empty set/list.
1118  */
1120  if (pointer_type_p(func_res_t))
1121  {
1123  NIL);
1126  NIL);
1127  }
1128  else
1129  {
1130  pv_res->result_paths = NIL;
1132  }
1133  free_type(func_res_t);
1134 
1135  pips_debug_pvs(2, "returning pv_res->l_out:", pv_res->l_out);
1136  pips_debug(1, "end\n");
1137  return;
1138 }
1139 
1140 static
1141 void call_to_post_pv(call c, list l_in, pv_results *pv_res, pv_context *ctxt)
1142 {
1143  entity func = call_function(c);
1144  value func_init = entity_initial(func);
1145  tag t = value_tag(func_init);
1146  list func_args = call_arguments(c);
1147  type func_type = ultimate_type(entity_type(func));
1148 
1149  pips_debug(1, "begin for %s\n", entity_local_name(func));
1150 
1151  if(type_functional_p(func_type))
1152  {
1153  switch (t)
1154  {
1155  case is_value_code:
1156  external_call_to_post_pv(c, l_in, pv_res, ctxt);
1157  break;
1158 
1159  case is_value_intrinsic:
1160  pips_debug(5, "intrinsic function\n");
1161  intrinsic_to_post_pv(func, func_args, l_in, pv_res, ctxt);
1162  break;
1163 
1164  case is_value_symbolic:
1165  pips_debug(5, "symbolic\n");
1166  pv_res->l_out = l_in;
1167  break;
1168 
1169  case is_value_constant:
1170  pips_debug(5, "constant\n");
1171  pv_res->l_out = l_in;
1172 
1173  constant func_const = value_constant(func_init);
1174  /* We should be here only in case of a pointer value rhs, and the value should be 0 */
1175  if (constant_int_p(func_const) && (constant_int(func_const) == 0))
1176  {
1177  /* use approximation_exact to be consistent with effects,
1178  should be approximation_exact */
1179  pv_res->result_paths = CONS(EFFECT,
1184  NIL);
1187  NIL);
1188  }
1189  else
1190  {
1191  type tt = functional_result(type_functional(func_type));
1192  if (type_variable_p(tt))
1193  {
1194  variable v = type_variable(tt);
1195  basic b = variable_basic(v);
1196  if (basic_string_p(b))/* constant strings */
1197  {
1198  /* not generic here */
1204  pv_res->result_paths = CONS(EFFECT, eff, NIL);
1207  NIL);
1208  }
1209  }
1210  }
1211  pv_res->l_out = l_in;
1212  break;
1213 
1214  case is_value_unknown:
1215  pips_internal_error("unknown function ");
1216  break;
1217 
1218  default:
1219  pips_internal_error("unknown tag %d", t);
1220  break;
1221  }
1222  }
1223  else if(type_variable_p(func_type))
1224  {
1225  pips_internal_error("not yet implemented");
1226  }
1227  else if(type_statement_p(func_type))
1228  {
1229  pips_internal_error("not yet implemented");
1230  }
1231  else
1232  {
1233  pips_internal_error("Unexpected case");
1234  }
1235 
1236  pips_debug_pvs(2, "returning pv_res->l_out:", pv_res->l_out);
1237  pips_debug(1, "end\n");
1238  return;
1239 }
1240 
1241 
1242 
1243 /*
1244  @brief returns in pv_res the effects of a single pointer assignment on pointer values
1245  @param lhs_eff is the left hand side path of the assignment
1246  @param l_rhs_eff is a list of rhs paths corresponding to the rhs
1247  @param l_rhs_kind is the list of rhs paths interpretations corresponding to elements of l_rhs_eff
1248  @param l_in is a list of the input pointer values
1249  @param pv_res is the struture holding the output result
1250  @param ctxt gives the functions specific to the kind of pointer values to be
1251  computed.
1252  */
1254  list l_rhs_eff, list l_rhs_kind,
1255  bool declaration_p, list l_in,
1256  pv_results *pv_res, pv_context *ctxt)
1257 {
1258  list l_out = NIL;
1259  list l_aliased = NIL;
1260  list l_kill = NIL;
1261  list l_gen = NIL;
1262 
1263  pips_debug_effect(1, "begin for lhs_eff =", lhs_eff);
1264  pips_debug(1, "and l_rhs_eff:\n");
1265  ifdebug(1)
1266  {
1267  list l_tmp = l_rhs_kind;
1268  FOREACH(EFFECT, rhs_eff, l_rhs_eff)
1269  {
1271  pips_debug(1, "%s of:\n", cell_interpretation_value_of_p(ci)?"value": "address");
1272  pips_debug_effect(1, "\t", rhs_eff);
1273  POP(l_tmp);
1274  }
1275  }
1276  pips_debug_pvs(1, "and l_in =", l_in);
1277  bool anywhere_lhs_p = false;
1278 
1279  /* First search for all killed paths */
1280  /* we could be more precise/generic on abstract locations */
1281  if (anywhere_effect_p(lhs_eff))
1282  {
1283  pips_assert("we cannot have an anywhere lhs for a declaration\n", !declaration_p);
1284  pips_debug(3, "anywhere lhs\n");
1285  anywhere_lhs_p = true;
1286  l_kill = CONS(EFFECT, copy_effect(lhs_eff), NIL);
1287  l_aliased = l_kill;
1288  }
1289  else
1290  {
1291  if (!declaration_p) /* no aliases for a newly declared entity */
1292  {
1293  l_aliased = effect_find_aliased_paths_with_pointer_values(lhs_eff, l_in, ctxt);
1294  if (!ENDP(l_aliased) && anywhere_effect_p(EFFECT(CAR(l_aliased))))
1295  {
1296  pips_debug(3, "anywhere lhs (from aliases)\n");
1297  anywhere_lhs_p = true;
1298  l_kill = l_aliased;
1299  }
1300  else if (!ENDP(l_aliased) && ((int) gen_length(l_aliased) == 1)
1301  && (null_pointer_value_effect_p(EFFECT(CAR(l_aliased)))))
1302  {
1303  // dereferencing a null pointer is considered as undefined by the standard
1304  // with gcc (without any option) the compiler does not complain, but the execution aborts
1305  // I make the choice here that if the pointer value is exactly NULL, then
1306  // the program abort; hence there is no pointer anymore and the pointer values list is empty.
1307  pips_user_warning("null pointer is dereferenced on lhs(%s)\n",
1308  effect_to_string(lhs_eff));
1309  gen_full_free_list(l_in);
1310  l_in = NIL;
1311  l_kill = NIL;
1312  }
1313  else if (!ENDP(l_aliased) && ((int) gen_length(l_aliased) == 1)
1314  && (undefined_pointer_value_effect_p(EFFECT(CAR(l_aliased)))))
1315  {
1316  // dereferencing a non-initialized pointer is considered as undefined by the standard
1317  // However, with gcc (without any option), the compiler does not complain,
1318  // and the execution is sometimes correct.
1319  // I make the choice here that if the pointer value is (exactly) undefined
1320  // then the program does not necessarily abort;
1321  // as I can keep dereferencements in pointer values (I'm not limited
1322  // to constant paths), I still generate a kill and a gen. BC.
1323  pips_user_warning("undefined pointer is dereferenced on lhs(%s)\n",
1324  effect_to_string(lhs_eff));
1325  l_kill = CONS(EFFECT, copy_effect(lhs_eff), NIL);
1326  }
1327  else
1328  {
1329  /* if lhs_eff is a may-be-killed, then all aliased effects are also
1330  may-be-killed effects */
1331  if (effect_may_p(lhs_eff))
1332  {
1333  pips_debug(3, "may lhs effect, changing all aliased effects to may\n");
1334  effects_to_may_effects(l_aliased);
1335  }
1336  l_kill = CONS(EFFECT, copy_effect(lhs_eff), l_aliased);
1337  }
1338  }
1339  else
1340  {
1341  l_kill = CONS(EFFECT, copy_effect(lhs_eff), NIL);
1342  }
1343  }
1344 
1345  pips_debug_effects(2, "l_kill =", l_kill);
1346 
1347  if (anywhere_lhs_p)
1348  {
1349  free_pv_results_paths(pv_res);
1350  pv_res->result_paths = l_aliased;
1352 
1353  /* we must find in l_in all pointers p and generate p == rhs for all rhs if p is
1354  * of a type compatible with rhs, and p == &*anywhere* otherwise.
1355  * in fact, for the moment we generate p == &*anywhere* in all cases
1356  */
1359  FOREACH(CELL_RELATION, pv_in, l_in)
1360  {
1361  /* dealing with first cell */
1362  /* not generic */
1367 
1368  list l_gen_pv = (* ctxt->make_pv_from_effects_func)
1369  (eff_alias, anywhere_eff, rhs_kind, l_in);
1370  l_gen = (*ctxt->pvs_must_union_func)(l_gen_pv, l_gen);
1371  free_effect(eff_alias);
1372 
1376  {
1377  /* not generic */
1382 
1383  list l_gen_pv = (* ctxt->make_pv_from_effects_func)
1384  (eff_alias, anywhere_eff, rhs_kind, l_in);
1385  l_gen = (*ctxt->pvs_must_union_func)(l_gen_pv, l_gen);
1386  free_effect(eff_alias);
1387  }
1388  }
1389  free_effect(anywhere_eff);
1390  free_cell_interpretation(rhs_kind);
1391  }
1392  else
1393  {
1394  /* generate for all alias p in l_kill p == rhs_eff */
1395  /* except for p==undefined or p==null (should other abstract values/locations be ignored here?) */
1396  FOREACH(EFFECT, eff_alias, l_kill) {
1397  if (!null_pointer_value_effect_p(eff_alias)
1398  && ! undefined_pointer_value_effect_p(eff_alias))
1399  {
1400  list l_rhs_kind_tmp = l_rhs_kind;
1401  FOREACH(EFFECT, rhs_eff, l_rhs_eff)
1402  {
1403  cell_interpretation rhs_kind =
1404  CELL_INTERPRETATION(CAR(l_rhs_kind_tmp));
1405  //bool exact_preceding_p = true;
1406  list l_gen_pv = (* ctxt->make_pv_from_effects_func)
1407  (eff_alias, rhs_eff, rhs_kind, l_in);
1408  l_gen = gen_nconc(l_gen_pv, l_gen);
1409  POP(l_rhs_kind_tmp);
1410  }
1411  }
1412  }
1413  if (declaration_p)
1414  {
1415  gen_full_free_list(l_kill);
1416  l_kill = NIL;
1417  }
1418  pips_debug_pvs(2, "l_gen =", l_gen);
1419  }
1420 
1421  /* now take kills into account */
1422  l_out = kill_pointer_values(l_in, l_kill, ctxt);
1423  pips_debug_pvs(2, "l_out_after kill:", l_out);
1424 
1425  /* and add gen */
1426  l_out = (*ctxt->pvs_must_union_func)(l_out, l_gen);
1427 
1428  pv_res->l_out = l_out;
1429 
1430  return;
1431 }
1432 
1433 
1434 /*
1435  @brief returns in pv_res the effects of a multiple pointer assignment (through nested strutures or arrays) on pointer values
1436  @param lhs_base_eff is the left hand side path of the assignment
1437  @param l_rhs_base_eff is a list of rhs paths corresponding to the rhs
1438  @param l_rhs_base_kind is the list of rhs paths interpretations corresponding to elements of l_rhs_eff
1439  @param l_in is a list of the input pointer values
1440  @param pv_res is the struture holding the output result
1441  @param ctxt gives the functions specific to the kind of pointer values to be
1442  computed.
1443  */
1445  list l_rhs_base_eff, list l_rhs_base_kind,
1446  bool declaration_p, list l_in,
1447  pv_results *pv_res, pv_context *ctxt)
1448 {
1449  list l_in_cur = l_in;
1450  cell rhs_base_cell = gen_length(l_rhs_base_eff) > 0
1451  ? effect_cell(EFFECT(CAR(l_rhs_base_eff))): cell_undefined;
1452  bool anywhere_lhs_p = false;
1453 
1454  pips_debug(1, "begin\n");
1455 
1456  pips_assert("assigning NULL to several pointers"
1457  " at the same time is forbidden!\n", !(!cell_undefined_p(rhs_base_cell) && null_pointer_value_cell_p(rhs_base_cell)));
1458 
1459  /* we could be more precise here on abstract locations */
1460  if (anywhere_effect_p(lhs_base_eff))
1461  {
1462  pips_assert("we cannot have an anywhere lhs for a declaration\n", !declaration_p);
1463  pips_debug(3, "anywhere lhs\n");
1464  anywhere_lhs_p = true;
1465 
1468 
1469  single_pointer_assignment_to_post_pv(lhs_base_eff, l_rhs_eff, l_rhs_kind, declaration_p, l_in_cur, pv_res, ctxt);
1470 
1471  gen_full_free_list(l_rhs_eff);
1472  gen_full_free_list(l_rhs_kind);
1473  }
1474  else /* if (!anywhere_lhs_p) */
1475  {
1476  /* lhs is not a pointer, but it is an array of pointers or an aggregate type
1477  with pointers.... */
1478  /* In this case, it cannot be an address_of case */
1479 
1480  /* First, search for all accessible pointers */
1482  (lhs_base_eff, lhs_type, is_action_write, false, 0, true);
1483  if(effect_exact_p(lhs_base_eff))
1484  effects_to_must_effects(l_lhs); /* to work around the fact that exact effects are must effects */
1485  pips_debug_effects(2, "l_lhs = ", l_lhs);
1486 
1487  /* Then for each found pointer, do as if there were an assignment by translating
1488  the rhs path accordingly
1489  */
1490  if (!ENDP(l_lhs))
1491  {
1492  list l_lhs_tmp = l_lhs;
1493  while (!anywhere_lhs_p && !ENDP(l_lhs_tmp))
1494  {
1495  /* build the list of corresponding rhs */
1496  effect lhs_eff = EFFECT(CAR(l_lhs_tmp));
1497  reference lhs_ref = effect_any_reference(lhs_eff);
1498  list lhs_dims = reference_indices(lhs_ref);
1499 
1500  reference lhs_base_ref = effect_any_reference(lhs_base_eff);
1501  size_t lhs_base_nb_dim = gen_length(reference_indices(lhs_base_ref));
1502  list l_rhs_eff = NIL;
1503  list l_rhs_kind = NIL;
1504 
1505  bool free_rhs_kind = false;
1506  list l_rhs_base_kind_tmp = l_rhs_base_kind;
1507  FOREACH(EFFECT, rhs_base_eff, l_rhs_base_eff)
1508  {
1509  effect rhs_eff = copy_effect(rhs_base_eff);
1510  cell_interpretation rhs_kind = CELL_INTERPRETATION(CAR(l_rhs_base_kind));
1511 
1512  if (!undefined_pointer_value_cell_p(rhs_base_cell)
1513  && !anywhere_effect_p(rhs_base_eff))
1514  {
1515  reference rhs_ref = effect_any_reference(rhs_eff);
1516  bool to_be_freed = false;
1517  type rhs_type = cell_reference_to_type(rhs_ref, &to_be_freed);
1518 
1519  if (!type_equal_p(lhs_type, rhs_type))
1520  {
1521  pips_debug(5, "not same lhs and rhs types generating anywhere rhs\n");
1522  rhs_eff = make_anywhere_effect(make_action_write_memory()); /* should be refined */
1524  free_rhs_kind = true;
1525  }
1526  else /* general case at least :-) */
1527  {
1528  /* This is not generic, I should use a translation algorithm here I guess */
1529  /* first skip dimensions of kill_ref similar to lhs_base_ref */
1530  list lhs_dims_tmp = lhs_dims;
1531  for(size_t i = 0; i < lhs_base_nb_dim; i++, POP(lhs_dims_tmp));
1532  /* add the remaining dimensions to the copy of rhs_base_eff */
1533  FOREACH(EXPRESSION, dim, lhs_dims_tmp)
1534  {
1535  // functions that can be pointed by effect_add_expression_dimension_func:
1536  // simple_effect_add_expression_dimension
1537  // convex_region_add_expression_dimension
1538  (*effect_add_expression_dimension_func)(rhs_eff, dim);
1539  }
1540  }
1541  if (to_be_freed) free_type(rhs_type);
1542  }
1543  l_rhs_eff = CONS(EFFECT, rhs_eff, l_rhs_eff);
1544  l_rhs_kind = CONS(CELL_INTERPRETATION, rhs_kind, l_rhs_kind);
1545  POP(l_rhs_base_kind_tmp);
1546  }
1547 
1548  single_pointer_assignment_to_post_pv(lhs_eff, l_rhs_eff, l_rhs_kind, declaration_p, l_in_cur, pv_res, ctxt);
1549 
1550  gen_full_free_list(l_rhs_eff);
1551  if (free_rhs_kind) gen_full_free_list(l_rhs_kind); else gen_free_list(l_rhs_kind);
1552 
1553  list l_out = pv_res->l_out;
1554  if (l_out != l_in_cur)
1555  gen_full_free_list(l_in_cur);
1556  l_in_cur = l_out;
1557 
1558  list l_result_paths = pv_res->result_paths;
1559 
1560  if (gen_length(l_result_paths) > 0 && anywhere_effect_p(EFFECT(CAR(l_result_paths))))
1561  anywhere_lhs_p = true;
1562 
1563  POP(l_lhs_tmp);
1564  } /* while */
1565  } /* if (!ENDP(l_lhs)) */
1566  gen_full_free_list(l_lhs);
1567  } /* if (!anywhere_lhs_p) */
1568 
1569  return;
1570 }
1571 
1572 
1573 /*
1574  @brief computes the gen, post and kill pointer values of an assignment
1575  @param lhs is the left hand side expression of the assignment*
1576  @param may_lhs_p is true if it's only a possible assignment
1577  @param rhs is the right hand side of the assignement
1578  @param l_in is a list of the input pointer values
1579  @param ctxt gives the functions specific to the kind of pointer values to be
1580  computed.
1581  */
1582 void assignment_to_post_pv(expression lhs, bool may_lhs_p,
1583  expression rhs, bool declaration_p,
1584  list l_in, pv_results *pv_res, pv_context *ctxt)
1585 {
1586  list l_in_cur = NIL;
1587  effect lhs_eff = effect_undefined;
1588 
1589  pips_debug(1, "begin with may_lhs_p = %s and declaration_p = %s\n", bool_to_string(may_lhs_p), bool_to_string(declaration_p));
1590  pips_debug_pvs(2, "input pointer values:\n", l_in);
1591  type lhs_type = expression_to_type(lhs);
1592 
1593  /* first convert the rhs and lhs into memory paths, rhs is evaluated first */
1594  /* this is done even if this is a non-pointer assignment, becasue there
1595  maybe side effects on alising hidden in sub-expressions, function calls...
1596  */
1597  pv_results lhs_pv_res = make_pv_results();
1598  pv_results rhs_pv_res = make_pv_results();
1599 
1600  expression_to_post_pv(rhs, l_in, &rhs_pv_res, ctxt);
1601  list l_rhs_eff = rhs_pv_res.result_paths;
1602  list l_rhs_kind = rhs_pv_res.result_paths_interpretations;
1603  l_in_cur = rhs_pv_res.l_out;
1604 
1605  expression_to_post_pv(lhs, l_in_cur, &lhs_pv_res, ctxt);
1606  l_in_cur = lhs_pv_res.l_out;
1607  /* we should test here that lhs_pv_res.result_paths has only one element.
1608  well is it correct? can a relational operator expression be a lhs ?
1609  */
1610  lhs_eff = EFFECT(CAR(lhs_pv_res.result_paths));
1611  if (may_lhs_p) effect_to_may_effect(lhs_eff);
1612  pv_res->result_paths = CONS(EFFECT, copy_effect(lhs_eff), NIL);
1615 
1617  {
1618  pips_debug(2, "non-pointer assignment\n");
1619  /* l_gen = NIL; l_kill = NIL; */
1620  pv_res->l_out = l_in_cur;
1621  }
1622  else
1623  {
1624  if(type_variable_p(lhs_type))
1625  {
1626  if (pointer_type_p(lhs_type)) /* simple case first: lhs is a pointer */
1627  {
1628  single_pointer_assignment_to_post_pv(lhs_eff, l_rhs_eff,
1629  l_rhs_kind,
1630  declaration_p, l_in_cur,
1631  pv_res, ctxt);
1632  }
1633  else /* hidden pointer assignments */
1634  {
1635  multiple_pointer_assignment_to_post_pv(lhs_eff, lhs_type, l_rhs_eff,
1636  l_rhs_kind,
1637  declaration_p, l_in_cur,
1638  pv_res, ctxt);
1639  }
1640  } /* if (type_variable_p(lhs_type) */
1641  else if(type_functional_p(lhs_type))
1642  {
1643  pips_internal_error("not yet implemented");
1644  }
1645  else
1646  pips_internal_error("unexpected_type");
1647  }
1648 
1649 
1650  free_pv_results_paths(&lhs_pv_res);
1651  free_pv_results_paths(&rhs_pv_res);
1652 
1653  pips_debug_pv_results(1, "end with pv_res =\n", *pv_res);
1654  return;
1655 }
1656 
1658 {
1659  list pv_out = NIL;
1661  list l_formals = module_formal_parameters(module);
1662  const char* mod_name = get_current_module_name();
1663  entity pointer_dummy_area = FindOrCreateEntity(mod_name, POINTER_DUMMY_TARGETS_AREA_LOCAL_NAME);
1664  storage pointer_dummy_storage = make_storage_ram(make_ram(module, pointer_dummy_area, UNKNOWN_RAM_OFFSET, NIL));
1665 
1666  FOREACH(ENTITY, formal_ent, l_formals)
1667  {
1668  effect formal_eff = make_reference_simple_effect(make_reference(formal_ent, NIL),
1671  type formal_t = entity_basic_concrete_type(formal_ent);
1672 
1673  // generate all possible effects from the formal parameter
1675  formal_t,
1676  'w',
1677  true,
1678  10, /* to avoid too long paths until GAPS are handled */
1679  false);
1680  const char * formal_name = entity_user_name(formal_ent);
1681  int nb = 1;
1682 
1683  FOREACH(EFFECT, eff, lw)
1684  {
1685  // this should be at least partly be embedded in a representation dependent wrapper
1686  pips_debug_effect(3, "current effect: \n", eff);
1687  bool to_be_freed = false;
1688  type eff_t = cell_to_type(effect_cell(eff), &to_be_freed);
1690  {
1691 
1692  // we generate an address_of pv, the source of which is the effect cell
1693  // and the sink of which is the first element of a new entity, whose type
1694  // is a one dimensional array of the pointed type.
1695 
1696  // first generate the new entity name
1697  entity new_ent = entity_undefined;
1698  string new_name = NULL;
1699  new_name = strdup(concatenate(mod_name, MODULE_SEP_STRING, "_", formal_name,"_", int2a(nb), NULL));
1700  nb ++;
1701 
1702  // then take care of the type and target path indices
1704  type new_type = type_undefined;
1705  list new_dims = NIL; // array dimensions of new type
1706 
1707  // if the effect path contains multiple paths (a[*] or p.end[*].begin for instance)
1708  // then there are several targets;
1709  // the indices of the new_path must have an additional dimension
1710  // and also the new type
1711  bool single_path = true;
1712  list new_inds = NIL; // indices of the target path
1713 
1714  // Not generic
1715  // for simple cells, isn't it sufficient to test the approximation of the effect ?
1717  {
1718  if (unbounded_expression_p(eff_ind_exp))
1719  {
1720  single_path = false;
1721  break;
1722  }
1723  }
1724  if (!single_path)
1725  {
1726  new_inds = CONS(EXPRESSION, make_unbounded_expression(), NIL);
1727  new_dims = CONS(DIMENSION,
1730  NIL),
1731  NIL);
1732  // the approximation will be ok because, as the path is not unique
1733  // the effect approximation is may by construction
1734  }
1735 
1737  {
1738  pips_debug(5, "variable case\n");
1739  variable pointed_type_v = type_variable(pointed_type);
1740  basic new_basic = copy_basic(variable_basic(pointed_type_v));
1741  if (ENDP(variable_dimensions(pointed_type_v)))
1742  {
1743  pips_debug(5, "with 0 dimension\n");
1744  new_dims = gen_nconc(new_dims, CONS(DIMENSION,
1747  new_inds = gen_nconc(new_inds, CONS(EXPRESSION, int_to_expression(0), NIL));
1748  }
1749  else
1750  {
1751  new_dims = gen_full_copy_list(variable_dimensions(pointed_type_v));
1752  pips_debug(5, "with %d dimension\n", (int) gen_length(new_dims));
1753  FOREACH(DIMENSION, dim, new_dims)
1754  {
1755  new_inds = gen_nconc(new_inds, CONS(EXPRESSION, int_to_expression(0), NIL));
1756  }
1757  }
1758  new_type = make_type_variable(make_variable(new_basic, new_dims, NIL));
1759  pips_debug(5, "new_type is: %s (%s)\n", string_of_type(new_type),
1760  type_to_string(new_type));
1761  new_ent = make_entity(new_name,
1762  new_type,
1763  copy_storage(pointer_dummy_storage),
1764  make_value_unknown());
1765  }
1766  else
1767  {
1768  pips_debug(5, "non-variable formal parameter target type -> anywhere\n");
1769  new_ent = entity_all_locations();
1770  gen_full_free_list(new_inds);
1771  new_inds = NIL;
1772  }
1773 
1774  cell new_cell = make_cell_reference(make_reference(new_ent, new_inds));
1775  // then make the new pv
1777  new_cell,
1780  pips_debug_pv(3, "generated pv: \n", new_pv);
1781  // and add it to the return list of pvs
1782  pv_out = CONS(CELL_RELATION, new_pv, pv_out);
1783  }
1784  if (to_be_freed) free_type(eff_t);
1785  }
1786  gen_full_free_list(lw);
1787  }
1788  free_storage(pointer_dummy_storage);
1789  return pv_out;
1790 }
1791 
1792 /**
1793  @brief generic interface to compute the pointer values of a given module
1794  @param module_name is the name of the module
1795  @param ctxt gives the functions specific to the kind of pointer values to be
1796  computed.
1797  */
1799 {
1800 
1801  /* temporary settings : in an interprocedural context we need to keep track
1802  of visited modules */
1803  /* Get the code of the module. */
1805  db_get_memory_resource(DBR_CODE, module_name, true));
1807  init_pv();
1808 
1809  debug_on("POINTER_VALUES_DEBUG_LEVEL");
1810  pips_debug(1, "begin\n");
1811 
1812  list l_init = module_initial_parameter_pv();
1814  {
1815  l_init = (*ctxt->pvs_must_union_func)(l_init, gen_full_copy_list( (*ctxt->db_get_program_pv_func)() ));
1816  }
1817 
1819 
1820  (*ctxt->db_put_pv_func)(module_name, get_pv());
1821  (*ctxt->db_put_in_pv_func)(module_name, l_init);
1822  (*ctxt->db_put_out_pv_func)(module_name, l_out);
1823 
1824  pips_debug(1, "end\n");
1825  debug_off();
1828 
1829  reset_pv();
1830 
1831  return;
1832 }
1833 
1834 
1836 {
1838  db_get_memory_resource(DBR_CODE, module_name, true));
1840  init_pv();
1841 
1842  debug_on("POINTER_VALUES_DEBUG_LEVEL");
1843  pips_debug(1, "begin\n");
1845 
1846  list l_in = NIL;
1847  list l_cur = l_in;
1848  FOREACH(ENTITY, decl, l_decl)
1849  {
1850  if(variable_static_p(decl))
1851  {
1852  l_cur = declaration_to_post_pv(decl, l_cur, ctxt);
1853  }
1854  }
1855  list l_out = l_cur;
1856 
1857  pips_debug_pvs(1, "Resulting pointer values:\n", l_out);
1858 
1859  (*ctxt->db_put_initial_pv_func)(module_name, l_out);
1860 
1861  pips_debug(1, "end\n");
1862  debug_off();
1865 
1866  reset_pv();
1867 
1868  return;
1869 }
1870 
1871 static void generic_program_pointer_values(char * prog_name, pv_context *ctxt)
1872 {
1874  list l_out = NIL;
1875  pips_assert("main was found", the_main!=entity_undefined);
1876 
1877  debug_on("POINTER_VALUES_DEBUG_LEVEL");
1878  pips_debug(1, "begin\n");
1879  pips_debug(1, "considering program \"%s\" with main \"%s\"\n", prog_name,
1880  module_local_name(the_main));
1881  /* Unavoidable pitfall: initializations in uncalled modules may be
1882  * taken into account. It all depends on the "create" command.
1883  */
1884  gen_array_t modules = db_get_module_list();
1885  int nmodules = gen_array_nitems(modules);
1886  pips_assert("some modules in the program", nmodules>0);
1887 
1888  for(int i=0; i<nmodules; i++)
1889  {
1890  string module_name = gen_array_item(modules, i);
1891  pips_debug(1, "considering module %s\n", module_name);
1892 
1894  list l_cur = (ctxt->db_get_initial_pv_func)(module_name);
1895  pips_debug_pvs(2, "module initial pvs: \n", l_cur);
1897  l_out = gen_nconc(gen_full_copy_list(l_cur), l_out);
1898  }
1899 
1900  set_current_module_entity(the_main);
1901  pips_debug_pvs(2, "storing program pvs: \n", l_out);
1903 
1904  (*ctxt->db_put_program_pv_func)(l_out);
1905  pips_debug(1, "end\n");
1906  debug_off();
1907  return;
1908 }
1909 
1910 /**************** INTERFACE *************/
1911 
1912 /**
1913  @brief interface to compute the simple pointer values of a given module
1914  */
1916 {
1920  reset_pv_context(&ctxt);
1922  return(true);
1923 }
1924 
1926 {
1928  ctxt.initial_pointer_values_p = true;
1931  reset_pv_context(&ctxt);
1933  return(true);
1934 }
1935 
1936 bool program_simple_pointer_values(const string prog_name)
1937 {
1940  generic_program_pointer_values(prog_name, &ctxt);
1941  reset_pv_context(&ctxt);
1943  return(true);
1944 }
1945 
cell make_cell_reference(reference _field_)
Definition: effects.c:293
void free_effect(effect p)
Definition: effects.c:451
cell_interpretation make_cell_interpretation_value_of(void)
Definition: effects.c:237
cell_interpretation make_cell_interpretation_address_of(void)
Definition: effects.c:240
cell_relations make_cell_relations(list a)
Definition: effects.c:383
approximation make_approximation_exact(void)
Definition: effects.c:185
approximation make_approximation_may(void)
Definition: effects.c:179
effect make_effect(cell a1, action a2, approximation a3, descriptor a4)
Definition: effects.c:484
effect copy_effect(effect p)
EFFECT.
Definition: effects.c:448
descriptor make_descriptor_none(void)
Definition: effects.c:442
void free_cell_interpretation(cell_interpretation p)
Definition: effects.c:194
cell copy_cell(cell p)
CELL.
Definition: effects.c:246
value make_value_unknown(void)
Definition: ri.c:2847
type make_type_variable(variable _field_)
Definition: ri.c:2715
basic copy_basic(basic p)
BASIC.
Definition: ri.c:104
ram make_ram(entity a1, entity a2, intptr_t a3, list a4)
Definition: ri.c:1999
reference make_reference(entity a1, list a2)
Definition: ri.c:2083
dimension make_dimension(expression a1, expression a2, list a3)
Definition: ri.c:565
variable make_variable(basic a1, list a2, list a3)
Definition: ri.c:2895
void free_expression(expression p)
Definition: ri.c:853
void free_storage(storage p)
Definition: ri.c:2231
storage copy_storage(storage p)
STORAGE.
Definition: ri.c:2228
reference copy_reference(reference p)
REFERENCE.
Definition: ri.c:2047
void free_type(type p)
Definition: ri.c:2658
storage make_storage_ram(ram _field_)
Definition: ri.c:2279
entity entity_all_locations()
eturn ANY_MODULE:ANYWHERE (the top of the lattice)
size_t gen_array_nitems(const gen_array_t a)
Definition: array.c:131
void * gen_array_item(const gen_array_t a, size_t i)
Definition: array.c:143
#define pips_debug_effects(level, message, l_eff)
#define pips_debug_effect(level, message, eff)
for debug
list generic_proper_effects_of_complex_address_expression(expression, list *, int)
void effects_to_may_effects(list)
effect make_anywhere_effect(action)
void effect_add_dereferencing_dimension(effect)
bool null_pointer_value_effect_p(effect)
effect(* reference_to_effect_func)(reference, action, bool)
bool undefined_pointer_value_effect_p(effect)
void effects_to_must_effects(list)
void effect_to_may_effect(effect)
void generic_effects_reset_all_methods(void)
list generic_effect_generate_all_accessible_paths_effects_with_level(effect, type, tag, bool, int, bool)
void simple_cell_reference_with_address_of_cell_reference_translation(reference, descriptor, reference, descriptor, int, reference *, descriptor *, bool *)
bool simple_cell_preceding_p(cell, descriptor, cell, descriptor, transformer, bool, bool *)
Definition: eval.c:119
string effect_to_string(effect)
void simple_cell_reference_with_value_of_cell_reference_translation(reference, descriptor, reference, descriptor, int, reference *, descriptor *, bool *)
void set_methods_for_simple_effects(void)
#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 effect_approximation_tag(eff)
#define make_reference_simple_effect(reference, action, approximation)
#define cell_relation_second_cell(cr)
#define pips_debug_pvs(level, message, l_pv)
#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 cell_to_type(cell, bool *)
Definition: type.c:513
void print_pointer_values(list)
Definition: prettyprint.c:622
entity null_pointer_value_entity(void)
action make_action_write_memory(void)
To ease the extension of action with action_kind.
Definition: effects.c:1011
cell make_null_pointer_value_cell(void)
cell_relation make_address_of_pointer_value(cell, cell, tag, descriptor)
type cell_reference_to_type(reference, bool *)
computes the type of a cell reference representing a memory access path.
Definition: type.c:466
bool anywhere_effect_p(effect)
Is it an anywhere effect? ANYMMODULE:ANYWHERE
Definition: effects.c:346
cell make_undefined_pointer_value_cell(void)
action make_action_read_memory(void)
Definition: effects.c:1017
bool null_pointer_value_cell_p(cell)
entity undefined_pointer_value_entity(void)
pointer_values.c
#define cell_relations_list(x)
Definition: effects.h:549
#define CELL_RELATION(x)
CELL_RELATION.
Definition: effects.h:479
#define cell_undefined_p(x)
Definition: effects.h:431
struct _newgen_struct_cell_relation_ * cell_relation
Definition: effects.h:98
#define cell_undefined
Definition: effects.h:430
#define cell_interpretation_address_of_p(x)
Definition: effects.h:418
#define effect_undefined
Definition: effects.h:614
struct _newgen_struct_statement_effects_ * statement_effects
Definition: effects.h:210
#define cell_interpretation_value_of_p(x)
Definition: effects.h:415
struct _newgen_struct_descriptor_ * descriptor
Definition: effects.h:114
@ is_action_write
Definition: effects.h:293
@ is_approximation_may
Definition: effects.h:341
struct _newgen_struct_statement_cell_relations_ * statement_cell_relations
Definition: effects.h:202
#define CELL_INTERPRETATION(x)
CELL_INTERPRETATION.
Definition: effects.h:375
#define EFFECT(x)
EFFECT.
Definition: effects.h:608
#define effect_cell(x)
Definition: effects.h:640
const char * module_name(const char *s)
Return the module part of an entity name.
Definition: entity_names.c:296
void gen_full_free_list(list l)
Definition: genClib.c:1023
#define CONTROL_MAP(ctl, code, c, list)
Macro to walk through all the controls reachable from a given control node of an unstructured.
void reset_current_module_entity(void)
Reset the current module entity.
Definition: static.c:97
void reset_current_module_statement(void)
Reset the current module statement.
Definition: static.c:221
const char * get_current_module_name(void)
Get the name of the current module.
Definition: static.c:121
statement set_current_module_statement(statement)
Set the current module statement.
Definition: static.c:165
statement get_current_module_statement(void)
Get the current module statement.
Definition: static.c:208
entity set_current_module_entity(entity)
static.c
Definition: static.c:66
entity get_current_module_entity(void)
Get the entity of the current module.
Definition: static.c:85
#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
list gen_nconc(list cp1, list cp2)
physically concatenates CP1 and CP2 but do not duplicates the elements
Definition: list.c:344
#define CAR(pcons)
Get the value of the first element of a list.
Definition: newgen_list.h:92
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
list gen_full_copy_list(list l)
Copy a list structure with element copy.
Definition: list.c:535
string db_get_memory_resource(const char *rname, const char *oname, bool pure)
Return the pointer to the resource, whatever it is.
Definition: database.c:755
gen_array_t db_get_module_list(void)
Get an array of all the modules (functions, procedures and compilation units) of a workspace.
Definition: database.c:1266
#define DB_PUT_MEMORY_RESOURCE(res_name, own_name, res_val)
conform to old interface.
Definition: pipsdbm-local.h:66
bool declaration_statement_p(statement)
Had to be optimized according to Beatrice Creusillet.
Definition: statement.c:224
#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_user_warning
Definition: misc-local.h:146
#define pips_assert(what, predicate)
common macros, two flavors depending on NDEBUG
Definition: misc-local.h:172
#define pips_internal_error
Definition: misc-local.h:149
#define debug_off()
Definition: misc-local.h:160
#define POINTER_DUMMY_TARGETS_AREA_LOCAL_NAME
Definition: naming-local.h:77
#define MODULE_SEP_STRING
Definition: naming-local.h:30
string bool_to_string(bool)
Definition: string.c:243
string concatenate(const char *,...)
Return the concatenation of the given strings.
Definition: string.c:183
#define GENERIC_GLOBAL_FUNCTION(name, type)
#define same_string_p(s1, s2)
void * stack_head(const stack)
returns the item on top of stack s
Definition: stack.c:420
void stack_push(void *, stack)
stack use
Definition: stack.c:373
stack stack_make(int, int, int)
allocation
Definition: stack.c:246
void * stack_pop(stack)
POPs one item from stack s.
Definition: stack.c:399
int bool
we cannot use an enum or stdbool because we need to be compatible with newgen, thus boolean need to h...
Definition: newgen_types.h:78
int tag
TAG.
Definition: newgen_types.h:92
struct cons * list
Definition: newgen_types.h:106
static char * module
Definition: pips.c:74
string get_main_entity_name(void)
Return the local name of the main module if it is available, or the local name of any module by defau...
Definition: util.c:63
#define pips_debug_pv_results(level, message, pv_res)
void pointer_values_remove_var(entity, bool, list, pv_results *, pv_context *)
void update_pv(statement, cell_relations)
list kill_pointer_values(list, list, pv_context *)
eliminate the cells of l_kill from l_in
void intrinsic_to_post_pv(entity, list, list, pv_results *, pv_context *)
pointer_values_intrinsics.c
list pvs_composition_with_transformer(list, transformer, pv_context *)
void init_pv(void)
list simple_pvs_may_union(list, list)
list effect_find_aliased_paths_with_pointer_values(effect, list, pv_context *)
find all paths equivalent to eff cell in l_pv by performing a transitive closure
list simple_pvs_must_union(list, list)
bool simple_pvs_syntactically_equal_p(list, list)
void store_pv(statement, cell_relations)
void reset_pv(void)
cell_relation simple_pv_composition_with_transformer(cell_relation, transformer)
list make_simple_pv_from_simple_effects(effect, effect, cell_interpretation, list)
pointer_values_operators.c
statement_cell_relations get_pv(void)
bool bound_pv_p(statement)
static list sequence_to_post_pv(sequence seq, list l_in, pv_context *ctxt)
static void generic_module_initial_pointer_values(char *module_name, pv_context *ctxt)
static list instruction_to_post_pv(instruction inst, list l_in, pv_context *ctxt)
static list loop_to_post_pv(loop l, list l_in, pv_context *ctxt)
pv_results make_pv_results()
bool program_simple_pointer_values(const string prog_name)
list db_get_in_simple_pv(const char *module_name)
void db_put_in_simple_pv(const char *module_name, list l_pv)
bool simple_pointer_values(const string module_name)
interface to compute the simple pointer values of a given module
static list test_to_post_pv(test t, list l_in, pv_context *ctxt)
statement_cell_relations(* statement_cell_relations_function)()
bool initial_simple_pointer_values(const string module_name)
void(* void_function)()
static list whileloop_to_post_pv(whileloop l, list l_in, pv_context *ctxt)
descriptor(* descriptor_function)()
void range_to_post_pv(range r, list l_in, pv_results *pv_res, pv_context *ctxt)
list db_get_program_simple_pv()
statement_cell_relations db_get_simple_pv(const char *module_name)
I don't know how to deal with these mappings if we have to analyse several modules at the same time w...
pv_context make_simple_pv_context()
static list module_initial_parameter_pv()
static list declarations_to_post_pv(list l_decl, list l_in, pv_context *ctxt)
#define PV_NB_MAX_ITER_FIX_POINT
void expression_to_post_pv(expression exp, list l_in, pv_results *pv_res, pv_context *ctxt)
void free_pv_results_paths(pv_results *pv_res)
static void external_call_to_post_pv(call c, list l_in, pv_results *pv_res, pv_context *ctxt)
bool(* bool_function)()
void single_pointer_assignment_to_post_pv(effect lhs_eff, list l_rhs_eff, list l_rhs_kind, bool declaration_p, list l_in, pv_results *pv_res, pv_context *ctxt)
static list unstructured_to_post_pv(unstructured u, list l_in, pv_context *ctxt)
static void call_to_post_pv(call c, list l_in, pv_results *pv_res, pv_context *ctxt)
void db_put_initial_simple_pv(const char *module_name, list l_pv)
void db_put_program_simple_pv(list l_pv)
statement pv_context_statement_head(pv_context *ctxt)
void db_put_simple_pv(const char *module_name, statement_cell_relations scr)
list(* list_function)()
void print_pv_results(pv_results pv_res)
void db_put_out_simple_pv(const char *module_name, list l_pv)
static void generic_module_pointer_values(char *module_name, pv_context *ctxt)
generic interface to compute the pointer values of a given module
void multiple_pointer_assignment_to_post_pv(effect lhs_base_eff, type lhs_type, list l_rhs_base_eff, list l_rhs_base_kind, bool declaration_p, list l_in, pv_results *pv_res, pv_context *ctxt)
list make_anywhere_anywhere_pvs()
statement_effects(* statement_effects_function)()
list db_get_out_simple_pv(const char *module_name)
static list statement_to_post_pv(statement stmt, list l_in, pv_context *ctxt)
void reset_pv_context(pv_context *p_ctxt)
#define UNDEF
static list forloop_to_post_pv(forloop l, list l_in, pv_context *ctxt)
list db_get_initial_simple_pv(const char *module_name)
static void generic_program_pointer_values(char *prog_name, pv_context *ctxt)
void pv_context_statement_pop(pv_context *ctxt)
cell_relation(* cell_relation_function)()
static list declaration_to_post_pv(entity e, list l_in, pv_context *ctxt)
void pv_context_statement_push(statement s, pv_context *ctxt)
void assignment_to_post_pv(expression lhs, bool may_lhs_p, expression rhs, bool declaration_p, list l_in, pv_results *pv_res, pv_context *ctxt)
string expression_to_string(expression e)
Definition: expression.c:77
string string_of_type(const type)
Definition: type.c:56
void print_statement(statement)
Print a statement on stderr.
Definition: statement.c:98
#define make_entity(n, t, s, i)
#define UNKNOWN_RAM_OFFSET
bool static_area_p(entity aire)
Definition: area.c:77
const char * entity_user_name(entity e)
Since entity_local_name may contain PIPS special characters such as prefixes (label,...
Definition: entity.c:487
const char * entity_local_name(entity e)
entity_local_name modified so that it does not core when used in vect_fprint, since someone thought t...
Definition: entity.c:453
entity FindOrCreateEntity(const char *package, const char *local_name)
Problem: A functional global entity may be referenced without parenthesis or CALL keyword in a functi...
Definition: entity.c:1586
bool std_file_entity_p(entity e)
Definition: entity.c:1232
entity module_name_to_entity(const char *mn)
This is an alias for local_name_to_top_level_entity.
Definition: entity.c:1479
bool entity_main_module_p(entity e)
Definition: entity.c:700
bool typedef_entity_p(entity e)
Definition: entity.c:1902
static int init
Maximal value set for Fortran 77.
Definition: entity.c:320
const char * module_local_name(entity e)
Returns the module local user name.
Definition: entity.c:582
entity std_file_entity_to_pointed_file_entity(entity e)
Dummy standard files targets.
Definition: entity.c:1243
expression make_address_of_expression(expression e)
generate a newly allocated expression for &(e)
Definition: expression.c:3956
expression make_unbounded_expression()
Definition: expression.c:4339
expression entity_to_expression(entity e)
if v is a constant, returns a constant call.
Definition: expression.c:165
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
bool unbounded_expression_p(expression e)
Definition: expression.c:4329
list module_formal_parameters(entity func)
list module_formal_parameters(entity func) input : an entity representing a function.
Definition: module.c:327
bool compilation_unit_entity_p(entity e)
Check if the given module entity is a compilation unit.
Definition: module.c:87
type ultimate_type(type)
Definition: type.c:3466
bool entity_static_variable_p(entity)
return true if the entity is declared with the keyword static
Definition: variable.c:1146
type expression_to_type(expression)
For an array declared as int a[10][20], the type returned for a[i] is int [20].
Definition: type.c:2486
bool type_fundamental_basic_p(type)
Definition: type.c:2930
bool type_equal_p(type, type)
Definition: type.c:547
type entity_basic_concrete_type(entity)
retrieves or computes and then returns the basic concrete type of an entity
Definition: type.c:3677
type pointed_type(type)
returns the type pointed by the input type if it is a pointer or an array of pointers
Definition: type.c:3035
bool basic_concrete_type_leads_to_pointer_p(type)
returns true when the input type successors may be pointers
Definition: type.c:3699
bool pointer_type_p(type)
Check for scalar pointers.
Definition: type.c:2993
type compute_basic_concrete_type(type)
computes a new type which is the basic concrete type of the input type (this new type is not stored i...
Definition: type.c:3556
bool variable_static_p(entity)
true if v appears in a SAVE statement, or in a DATA statement, or is declared static i C.
Definition: variable.c:1579
string type_to_string(const type)
type.c
Definition: type.c:51
#define type_functional_p(x)
Definition: ri.h:2950
#define value_tag(x)
Definition: ri.h:3064
#define value_undefined
Definition: ri.h:3016
#define loop_body(x)
Definition: ri.h:1644
#define basic_pointer(x)
Definition: ri.h:637
#define transformer_undefined
Definition: ri.h:2847
#define functional_result(x)
Definition: ri.h:1444
#define value_constant(x)
Definition: ri.h:3073
#define syntax_reference(x)
Definition: ri.h:2730
#define syntax_tag(x)
Definition: ri.h:2727
#define forloop_initialization(x)
Definition: ri.h:1366
#define call_function(x)
Definition: ri.h:709
#define reference_variable(x)
Definition: ri.h:2326
#define control_predecessors(x)
Definition: ri.h:943
#define range_upper(x)
Definition: ri.h:2290
#define forloop_increment(x)
Definition: ri.h:1370
#define ENTITY(x)
ENTITY.
Definition: ri.h:2755
#define constant_int(x)
Definition: ri.h:850
#define instruction_loop(x)
Definition: ri.h:1520
#define syntax_cast(x)
Definition: ri.h:2739
#define type_functional(x)
Definition: ri.h:2952
#define test_false(x)
Definition: ri.h:2837
#define whileloop_evaluation(x)
Definition: ri.h:3166
#define type_variable(x)
Definition: ri.h:2949
#define basic_pointer_p(x)
Definition: ri.h:635
#define entity_storage(x)
Definition: ri.h:2794
#define statement_domain
newgen_sizeofexpression_domain_defined
Definition: ri.h:362
#define type_statement_p(x)
Definition: ri.h:2941
@ is_value_intrinsic
Definition: ri.h:3034
@ is_value_unknown
Definition: ri.h:3035
@ is_value_expression
Definition: ri.h:3036
@ is_value_constant
Definition: ri.h:3033
@ is_value_code
Definition: ri.h:3031
@ is_value_symbolic
Definition: ri.h:3032
@ is_syntax_range
Definition: ri.h:2692
@ is_syntax_application
Definition: ri.h:2697
@ is_syntax_cast
Definition: ri.h:2694
@ is_syntax_call
Definition: ri.h:2693
@ is_syntax_va_arg
Definition: ri.h:2698
@ is_syntax_reference
Definition: ri.h:2691
@ is_syntax_sizeofexpression
Definition: ri.h:2695
@ is_syntax_subscript
Definition: ri.h:2696
#define range_increment(x)
Definition: ri.h:2292
#define storage_ram_p(x)
Definition: ri.h:2519
#define ram_section(x)
Definition: ri.h:2249
#define EXPRESSION(x)
EXPRESSION.
Definition: ri.h:1217
#define cast_expression(x)
Definition: ri.h:747
#define entity_undefined
Definition: ri.h:2761
#define constant_int_p(x)
Definition: ri.h:848
#define expression_undefined
Definition: ri.h:1223
@ is_instruction_goto
Definition: ri.h:1473
@ is_instruction_unstructured
Definition: ri.h:1475
@ is_instruction_whileloop
Definition: ri.h:1472
@ is_instruction_expression
Definition: ri.h:1478
@ is_instruction_test
Definition: ri.h:1470
@ is_instruction_multitest
Definition: ri.h:1476
@ is_instruction_call
Definition: ri.h:1474
@ is_instruction_sequence
Definition: ri.h:1469
@ is_instruction_forloop
Definition: ri.h:1477
@ is_instruction_loop
Definition: ri.h:1471
#define instruction_tag(x)
Definition: ri.h:1511
#define entity_name(x)
Definition: ri.h:2790
#define test_true(x)
Definition: ri.h:2835
#define sequence_statements(x)
Definition: ri.h:2360
#define reference_indices(x)
Definition: ri.h:2328
#define instruction_sequence(x)
Definition: ri.h:1514
#define instruction_forloop(x)
Definition: ri.h:1538
#define syntax_call(x)
Definition: ri.h:2736
#define control_successors(x)
Definition: ri.h:945
#define unstructured_exit(x)
Definition: ri.h:3006
#define instruction_expression(x)
Definition: ri.h:1541
#define expression_undefined_p(x)
Definition: ri.h:1224
#define test_condition(x)
Definition: ri.h:2833
#define instruction_whileloop(x)
Definition: ri.h:1523
#define unstructured_entry(x)
Definition: ri.h:3004
#define range_lower(x)
Definition: ri.h:2288
#define variable_dimensions(x)
Definition: ri.h:3122
#define whileloop_body(x)
Definition: ri.h:3162
#define statement_declarations(x)
Definition: ri.h:2460
#define statement_instruction(x)
Definition: ri.h:2458
#define storage_ram(x)
Definition: ri.h:2521
#define type_undefined
Definition: ri.h:2883
#define instruction_call(x)
Definition: ri.h:1529
#define loop_range(x)
Definition: ri.h:1642
#define forloop_condition(x)
Definition: ri.h:1368
#define call_arguments(x)
Definition: ri.h:711
#define control_statement(x)
Definition: ri.h:941
#define instruction_test(x)
Definition: ri.h:1517
#define whileloop_condition(x)
Definition: ri.h:3160
#define basic_string_p(x)
Definition: ri.h:629
#define entity_type(x)
Definition: ri.h:2792
#define expression_syntax(x)
Definition: ri.h:1247
#define evaluation_before_p(x)
Definition: ri.h:1159
#define type_variable_p(x)
Definition: ri.h:2947
#define forloop_body(x)
Definition: ri.h:1372
#define value_expression(x)
Definition: ri.h:3082
#define instruction_unstructured(x)
Definition: ri.h:1532
#define variable_basic(x)
Definition: ri.h:3120
#define STATEMENT(x)
STATEMENT.
Definition: ri.h:2413
#define entity_initial(x)
Definition: ri.h:2796
int fprintf()
test sc_min : ce test s'appelle par : programme fichier1.data fichier2.data ...
char * strdup()
#define ifdebug(n)
Definition: sg.c:47
The structure used to build lists in NewGen.
Definition: newgen_list.h:41
pv_context is a structure holding the methods to use during pointer values analyses
void(* cell_reference_with_value_of_cell_reference_translation_func)(reference, descriptor, reference, descriptor, int, reference *, descriptor *, bool *)
TRANSLATION OPERATORS.
bool(* cell_preceding_p_func)(cell, descriptor, cell, descriptor, transformer, bool, bool *)
COMPARISON OPERATORS.
list(* db_get_initial_pv_func)(const char *)
list(* pvs_must_union_func)(list, list)
BINARY OPERATORS.
list(* make_pv_from_effects_func)(effect, effect, cell_interpretation, list)
statement_cell_relations (*db_get_gen_pv_func)(char *);
stack stmt_stack
STACKS.
list(* db_get_program_pv_func)()
void(* db_put_out_pv_func)(const char *, list)
void(* db_put_in_pv_func)(const char *, list)
void(* cell_reference_with_address_of_cell_reference_translation_func)(reference, descriptor, reference, descriptor, int, reference *, descriptor *, bool *)
bool initial_pointer_values_p
ANALYSIS CONTROL.
void(* db_put_pv_func)(const char *, statement_cell_relations)
list(* pvs_may_union_func)(list, list)
list(* db_get_out_pv_func)(const char *)
list(* db_get_in_pv_func)(const char *)
statement_cell_relations(* db_get_pv_func)(const char *)
set to true for an initial module analysis
void(* db_put_initial_pv_func)(const char *, list)
bool(* pvs_equal_p_func)(list, list)
void(* db_put_program_pv_func)(list)
cell_relation(* pv_composition_with_transformer_func)(cell_relation, transformer)
UNARY OPERATORS.
pv_results is a structure holding the different results of an expression pointer values analysis
list result_paths_interpretations
resulting pointer path of the expression evaluation
list result_paths
resulting pointer_values
Definition: statement.c:54
char * int2a(int)
util.c
Definition: util.c:42
A gen_chunk is used to store every object.
Definition: genC.h:58
#define exp
Avoid some warnings from "gcc -Wshadow".
Definition: vasnprintf.c:207
list module_to_all_declarations(entity m)
Definition: module.c:323