PIPS
proper_effects_engine.c
Go to the documentation of this file.
1 /*
2 
3  $Id: proper_effects_engine.c 23412 2017-08-09 15:07:09Z irigoin $
4 
5  Copyright 1989-2016 MINES ParisTech
6 
7  This file is part of PIPS.
8 
9  PIPS is free software: you can redistribute it and/or modify it
10  under the terms of the GNU General Public License as published by
11  the Free Software Foundation, either version 3 of the License, or
12  any later version.
13 
14  PIPS is distributed in the hope that it will be useful, but WITHOUT ANY
15  WARRANTY; without even the implied warranty of MERCHANTABILITY or
16  FITNESS FOR A PARTICULAR PURPOSE.
17 
18  See the GNU General Public License for more details.
19 
20  You should have received a copy of the GNU General Public License
21  along with PIPS. If not, see <http://www.gnu.org/licenses/>.
22 
23 */
24 #ifdef HAVE_CONFIG_H
25  #include "pips_config.h"
26 #endif
27 /* package generic effects : Be'atrice Creusillet 5/97
28  *
29  * File: proper_effects_engine.c
30  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
31  *
32  * This File contains the generic functions necessary for the computation of
33  * all types of proper effects and proper references.
34  *
35  */
36 #include <stdio.h>
37 #include <string.h>
38 
39 #include "genC.h"
40 
41 #include "linear.h"
42 #include "ri.h"
43 #include "effects.h"
44 #include "database.h"
45 
46 #include "misc.h"
47 #include "ri-util.h"
48 #include "prettyprint.h"
49 #include "effects-util.h"
50 #include "constants.h"
51 #include "misc.h"
52 #include "text-util.h"
53 #include "text.h"
54 
55 #include "properties.h"
56 
57 #include "pipsdbm.h"
58 #include "resources.h"
59 
60 #include "pointer_values.h"
61 #include "effects-generic.h"
62 
63 /* For debuging
64 
65 static void debug_ctxt(string s, transformer t)
66 {
67  Psysteme p;
68  fprintf(stderr, "context %p at %s\n", t, s);
69  if (transformer_undefined_p(t))
70  fprintf(stderr, "UNDEFINED...");
71  else
72  {
73  p = predicate_system(transformer_relation(t));
74  fprintf(stderr, "%p: %d/%d\n", p, sc_nbre_egalites(p), sc_nbre_inegalites(p));
75  sc_syst_debug(p);
76  assert(sc_weak_consistent_p(p));
77  }
78 }
79 */
80 
81 /************************************************ TO CONTRACT PROPER EFFECTS */
82 
83 static bool contract_p = true;
84 
85 void
87 {
88  contract_p = b;
89 }
90 
91 
92 /**************************************** LOCAL STACK FOR LOOP RANGE EFFECTS */
93 
94 /* Effects on loop ranges have to be added to inner statements to model
95  * control dependances (see loop filter for PUSH).
96  */
97 
98 DEFINE_LOCAL_STACK(current_downward_cumulated_range_effects, effects)
99 
101 {
104  error_reset_current_downward_cumulated_range_effects_stack();
105 }
106 
107 static list
108 cumu_range_effects()
109 {
110  list l_cumu_range = NIL;
111 
112  if(! current_downward_cumulated_range_effects_empty_p())
113  {
114  l_cumu_range = effects_effects
115  (current_downward_cumulated_range_effects_head());
116  }
117  return(l_cumu_range);
118 }
119 
120 static void
121 free_cumu_range_effects()
122 {
123  if(! current_downward_cumulated_range_effects_empty_p())
124  free_effects(current_downward_cumulated_range_effects_head());
125 }
126 
127 ␌
128 /************************************************************** EXPRESSSIONS */
129 
130 /* list generic_proper_effects_of_range(range r, context)
131  * input : a loop range (bounds and stride) and the context.
132  * output : the corresponding list of effects.
133  * modifies : nothing.
134  * comment :
135  */
137 {
138  list le;
139  expression el = range_lower(r);
140  expression eu = range_upper(r);
141  expression ei = range_increment(r);
142 
143  pips_debug(5, "begin\n");
144 
148 
149  pips_debug(5, "end\n");
150  return(le);
151 }
152 
153 
154 static list generic_r_proper_effects_of_derived_reference(effect input_eff, type input_type)
155 {
156  basic b = variable_basic(type_variable(input_type));
157  list l_dim = variable_dimensions(type_variable(input_type));
158  list le = NIL;
159 
160  pips_debug_effect(8, "input effects:\n", input_eff);
161 
162  pips_assert("input entity type basic must be derived", basic_derived_p(b));
163 
164  // we first add as many unbounded indices as there are dimensions in the type.
165  for(int i=0; i< (int) gen_length(l_dim); i++) {
166  // functions that can be pointed by effect_add_expression_dimension_func:
167  // simple_effect_add_expression_dimension
168  // convex_region_add_expression_dimension
169  (*effect_add_expression_dimension_func)(input_eff, make_unbounded_expression());
170  }
171 
172  pips_debug(8, "type of basic derived : %s\n",string_of_type(entity_type(basic_derived(b))));
173  list l_fields = type_fields(entity_type(basic_derived(b)));
174 
175  FOREACH(ENTITY, f, l_fields)
176  {
177  type current_type = entity_basic_concrete_type(f);
178  basic current_basic = variable_basic(type_variable(current_type));
179  // functions that can be pointed by effect_dup_func:
180  // simple_effect_dup
181  // region_dup
182  // copy_effect
183  effect current_eff = (*effect_dup_func)(input_eff);
184 
185  // we add the field index
186  effect_add_field_dimension(current_eff, f);
187 
188  switch (basic_tag(current_basic))
189  {
190  case is_basic_derived:
191  if (type_enum_p(entity_type(basic_derived(current_basic))))
192  {
193  pips_debug(8, "enum case \n");
194  le = gen_nconc(CONS(EFFECT, current_eff, NIL), le);
195  }
196  else
197  {
198  pips_debug(8, "derived case : recursing\n");
199  le = gen_nconc(generic_r_proper_effects_of_derived_reference(current_eff, current_type),le);
200  effect_free(current_eff);
201  }
202  break;
203  case is_basic_typedef:
204  // should not happen
205  pips_internal_error("typedef case should not be possible here! ");
206  break;
207  default:
208  {
209  // we have reached a leaf : we just have to add as many unbounded indices as there are dimensions in the field type.
210  list l_dim = variable_dimensions(type_variable(current_type));
211  pips_debug(8, "default case\n");
212  for(int i=0; i< (int) gen_length(l_dim); i++) {
213  // functions that can be pointed by effect_add_expression_dimension_func:
214  // simple_effect_add_expression_dimension
215  // convex_region_add_expression_dimension
216  (*effect_add_expression_dimension_func)(current_eff, make_unbounded_expression());
217  }
218 
219  le = gen_nconc(CONS(EFFECT, current_eff, NIL), le);
220  break;
221  }
222  }
223  }
224  pips_debug_effects(8, "output effects:\n", le);
225 
226  return le;
227 }
228 
230 {
233  list le = NIL;
234 
235  pips_debug(8, "type of basic derived : %s\n",
237 
238  /* should'nt it be something more direct here ? ?*/
239  // functions that can be pointed by reference_to_effect_func:
240  // reference_to_simple_effect
241  // reference_to_convex_region
242  // reference_to_reference_effect
243  effect eff = (*reference_to_effect_func)(
245 
247  le = CONS(EFFECT, eff, NIL);
248  else
249  {
250  le = generic_r_proper_effects_of_derived_reference(eff, t);
251  le = gen_nreverse(le);
252  }
253 
254  return le;
255 }
256 
258 {
259  list le = NIL;
262  list l_ind_orig = reference_indices(ref);
263  list l_ind = l_ind_orig;
264 
265  pips_debug(7, "begin \n");
266  /* there should be a while here, I guess. Well work for tomorrow */
267 
268  if (type_variable_p(t))
269  {
270  variable v = type_variable(t);
271  basic b = variable_basic(v);
272 
273  pips_debug(4, "reference %s to entity %s of basic %s and"
274  " number of dimensions %d.\n",
276  entity_name(ent),
278  (int) gen_length(variable_dimensions(v)));
279 
280  if (basic_pointer_p(b))
281  {
282  reference read_ref = make_reference(ent, NIL);
283  list l_dim_tmp = variable_dimensions(v);
284 
285  pips_debug(8, "it's a pointer type. l_dim_tmp = %d, "
286  "l_inds_tmp = %d\n",
287  (int) gen_length(l_dim_tmp),
288  (int) gen_length(l_ind));
289 
290  /* while there is non partially subscripted references to pointers */
291  while((basic_pointer_p(variable_basic(v)))
292  && gen_length(l_dim_tmp) < gen_length(l_ind) )
293  {
294  effect eff_read;
295 
296  /* first we add the indices corresponding to the current
297  * array dimensions if any
298  */
299 
300  pips_debug(8, "l_dim_tmp = %d, l_inds_tmp = %d\n",
301  (int) gen_length(l_dim_tmp),
302  (int) gen_length(l_ind));
303 
304  while (!ENDP(l_dim_tmp))
305  {
306  reference_indices(read_ref)=
307  gen_nconc(reference_indices(read_ref),
309  NIL));
310  POP(l_dim_tmp);
311  POP(l_ind);
312  }
313 
314  pips_debug(4, "adding a read effect on reference %s\n",
315  reference_to_string(read_ref));
316 
317  // functions that can be pointed by reference_to_effect_func:
318  // reference_to_simple_effect
319  // reference_to_convex_region
320  // reference_to_reference_effect
321  eff_read = (*reference_to_effect_func)(copy_reference(read_ref),
323  false);
324  pips_assert("le is weakly consistent", regions_weakly_consistent_p(le));
325  le = gen_nconc(le, CONS(EFFECT, eff_read, NIL));
326  pips_assert("le is weakly consistent", regions_weakly_consistent_p(le));
327 
329  l_dim_tmp = variable_dimensions(v);
330 
331  /* if there are remaining indices, there is necessarily an index
332  * to reach the pointed dimension */
333  if(!ENDP(l_ind))
334  {
335  pips_debug(4, "adding an index for pointer dimension \n");
336  reference_indices(read_ref)=
337  gen_nconc(reference_indices(read_ref),
339  copy_expression(EXPRESSION(CAR(l_ind))),
340  NIL));
341  POP(l_ind);
342  }
343  }
344  free_reference(read_ref);
345  }
346 
347  } /* if (type_variable_p(t)) */
348  gen_nreverse(le);
350 
351  pips_debug_effects(7, "end with \n", le);
352  return le;
353 }
354 
355 
356 
357 
358 /**
359  @param ref a reference.
360  @param *pme : a pointer on the main effect corresponding to the reference.
361  if there is no effect (partially subscripted array for instance)
362  then *pme is set to effect undefined. If the main effect
363  could not be computed, *pme is set to a new anywhere effect.
364  @param write_p : true if the main effect is write, false otherwise.
365  @param allow_read_on_pme : true if we want to allow the generation of
366  read effects on reference even if it's a partially subscripted
367  array. The default value should be false, but it is useful
368  to set it to true when recusrsively building pme).
369  @return : a list of read effects corresponding to the intermediate reads
370  performed to access the main memory location.
371 
372 */
374  effect *pme,
375  bool write_p,
376  bool allow_partials_on_pme)
377 {
378  list le = NIL; /* list of read effects */
379 
381  list l_inds = reference_indices(ref);
382  list l_inds_tmp = l_inds;
383 
385 
386  *pme = effect_undefined;
387 
388  /* now we generate the read effects on intermediate pointer dimensions */
389  /* if the entity reference is a pointer, then we scan the dimensions
390  * until we reach a non-pointer basic.
391  */
392 
394  {
395  variable v = type_variable(t);
396  basic b = variable_basic(v);
397 
398  pips_debug(4, "reference %s to entity %s of basic %s and"
399  " number of dimensions %d.\n",
401  entity_name(ent),
403  (int) gen_length(variable_dimensions(v)));
404 
405  if (basic_pointer_p(b))
406  {
407  reference read_ref = make_reference(ent, NIL);
408  list l_dim_tmp = variable_dimensions(v);
409 
410  pips_debug(8, "it's a pointer type. l_dim_tmp = %d, "
411  "l_inds_tmp = %d\n",
412  (int) gen_length(l_dim_tmp),
413  (int) gen_length(l_inds_tmp));
414 
415  /* while there is non partially subscripted references to pointers */
416  while((basic_pointer_p(variable_basic(v)))
417  && gen_length(l_dim_tmp) < gen_length(l_inds_tmp) )
418  {
419  effect eff_read;
420 
421  /* first we add the indices corresponding to the current
422  * array dimensions if any
423  */
424 
425  pips_debug(8, "l_dim_tmp = %d, l_inds_tmp = %d\n",
426  (int) gen_length(l_dim_tmp),
427  (int) gen_length(l_inds_tmp));
428 
429  while (!ENDP(l_dim_tmp))
430  {
431  reference_indices(read_ref)=
432  gen_nconc(reference_indices(read_ref),
434  NIL));
435  POP(l_dim_tmp);
436  POP(l_inds_tmp);
437  }
438 
439  pips_debug(4, "adding a read effect on reference %s\n",
440  reference_to_string(read_ref));
441 
442  // functions that can be pointed by reference_to_effect_func:
443  // reference_to_simple_effect
444  // reference_to_convex_region
445  // reference_to_reference_effect
446  eff_read = (*reference_to_effect_func)(copy_reference(read_ref),
448  false);
449  pips_assert("le is weakly consistent", regions_weakly_consistent_p(le));
450  le = gen_nconc(le, CONS(EFFECT, eff_read, NIL));
451  pips_assert("le is weakly consistent", regions_weakly_consistent_p(le));
452 
454  l_dim_tmp = variable_dimensions(v);
455 
456  /* if there are remaining indices, there is necessarily an index
457  to reach the pointed dimension */
458  if(!ENDP(l_inds_tmp))
459  {
460  pips_debug(4, "adding an index for pointer dimension \n");
461  reference_indices(read_ref)=
462  gen_nconc(reference_indices(read_ref),
464  copy_expression(EXPRESSION(CAR(l_inds_tmp))),
465  NIL));
466  POP(l_inds_tmp);
467  }
468  }
469  free_reference(read_ref);
470  }
471 
472  /* no read or write effects on partial array if
473  * allow_partials_on_pme is false */
474  if(
475  (
476  basic_pointer_p(b) &&
477  ( gen_length(variable_dimensions(v)) <= gen_length(l_inds)
478  || allow_partials_on_pme
479  )
480  )
481  || (!basic_pointer_p(b) &&
482  (allow_partials_on_pme ||
483  gen_length(variable_dimensions(v)) == gen_length(l_inds))))
484  {
486  // functions that can be pointed by reference_to_effect_func:
487  // reference_to_simple_effect
488  // reference_to_convex_region
489  // reference_to_reference_effect
490  *pme = (*reference_to_effect_func)(ref, a, true);
491  pips_assert("*pme is wekly consistent", region_weakly_consistent_p(*pme));
492  }
493  }
494  else
495  {
496  /* Just compute the main memory effect of the reference
497  *
498  * This should maybe be refined ? */
499 
500  /* If the entity referenced is a function, we do not want a
501  * memory effect since it is a constant. Note: we end up here
502  * because its type as been converted to a pointer to a
503  * function above. */
505  type rvt = ultimate_type(entity_type(rv));
506 
507  if(type_functional_p(rvt))
508  *pme = effect_undefined;
509  else {
510  // functions that can be pointed by reference_to_effect_func:
511  // reference_to_simple_effect
512  // reference_to_convex_region
513  // reference_to_reference_effect
514  *pme = (*reference_to_effect_func)(
516  }
517 
518  if(!effect_undefined_p(*pme))
519  pips_assert("*pme is weakly consistent", region_weakly_consistent_p(*pme));
520  }
521 
522  /* we must add the read effects on the indices ; these reads are performed
523  before the main effect */
524  pips_assert("le is weakly consistent", regions_weakly_consistent_p(le));
526  (reference_indices(ref)), le);
527  pips_assert("le is weakly consistent", regions_weakly_consistent_p(le));
528 
529  /* and there is a declaration effect */
530  if(!get_bool_property("MEMORY_EFFECTS_ONLY"))
531  le = CONS(EFFECT, make_declaration_effect(ent, false), le);
532  ifdebug(4)
533  {
534  if(effect_undefined_p(*pme))
535  pips_debug(4, "ending no main effect "
536  "(e.g. a non-subscribed reference to an array)\n");
537  else
538  pips_debug_effect(4, "ending with main effect : \n", *pme);
539 
540  pips_debug_effects(4, "and intermediate read effects : \n",le);
541  }
542 
543  return le;
544 }
545 
546 
547 ␌
548 /* list generic_proper_effects_of_reference(reference ref, bool written_p)
549  * input : a reference and a boolean true if it is a written reference.
550  * output : the corresponding list of effects.
551  * modifies : nothing.
552  * comment : effects of a reference that is either read or written.
553  */
555 {
556  list le = NIL;
558 
559  pips_debug(3, "begin with reference %s\n",
561  pips_assert("no effect on entity fields\n",!entity_field_p(v));
563 
567  }
568  else {
570  }
571 
572  if (! (*empty_context_test)(context)) {
573  effect eff = effect_undefined;
574  bool vla_effect_p = get_bool_property("VLA_EFFECT_READ");
575  // NL: I don't understand why we need reference_to_type instead of entity_basic_concrete_type(v)
576  // or symply entity_type(v)?
577  // uncomment the free if use reference_to_type
578  type ref_type = reference_to_type(ref);
579  // comment the free and ENDP(variable_dimensions(ref_type_var)) if use entity_basic_concrete_type or entity_type
580  //type ref_type = entity_basic_concrete_type(v);
581  //type ref_type = entity_type(v);
582 
583  if (type_variable_p(ref_type) && !place_holder_variable_p(v)) {
584  variable ref_type_var = type_variable(ref_type);
585  if (basic_derived_p(variable_basic(ref_type_var))
586  && ENDP(variable_dimensions(ref_type_var))
587  ) {
590  le = gen_nconc(lint, le);
591  pips_assert("le is weakly consistent", regions_weakly_consistent_p(le));
592 
593  /* Environment and declaration type effects */
594  if(!get_bool_property("MEMORY_EFFECTS_ONLY")) {
595  /* May not be generic enough altough contexts seem useless for
596  * environment effects */
597  /* FI: these effects do not seem to always combine. A statement
598  * with a read and a write of v seems to end with two reference
599  * effects. See Bootstrap/iand01.f, assuming all effects are
600  * computed, of course. */
601  effect re = make_declaration_effect(v, false); // reference effect
602  //type vt = entity_type(v);
603  le = CONS(EFFECT, re, le);
604 
605  /*
606  if(typedef_type_p(vt)) {
607  entity te = basic_typedef(variable_basic(type_variable(vt)));
608  effect tre = make_declaration_effect(te, false); // type
609  // reference effect
610  le = CONS(EFFECT, tre, le);
611  }
612  */
613  }
614  }
615  else {
616  /* environment effects are also computed here */
618  false);
619  pips_assert("le is weakly consistent", regions_weakly_consistent_p(le));
620 
621  if (!effect_undefined_p(eff)) {
622  le = gen_nconc(le, CONS(EFFECT, eff, NIL));
623  pips_assert("le is weakly consistent", regions_weakly_consistent_p(le));
624  }
625  }
626  // NL: If we don't use reference_to_type don't have to free it, it will be done by pipsmake
627  free_type(ref_type);
628  }
629  else if (type_functional_p(ref_type)) {
630  // This case never happen with reference_to_type, it convert functionnal into variable type
631  /* environment effects are also computed here */
633  false);
634  pips_assert("le is weakly consistent", regions_weakly_consistent_p(le));
635 
636  if (!effect_undefined_p(eff)) {
637  le = gen_nconc(le, CONS(EFFECT, eff, NIL));
638  pips_assert("le is weakly consistent", regions_weakly_consistent_p(le));
639  }
640  }
641  else {
642  print_type(ref_type);
643  pips_internal_error("case not handled yet : %d", type_to_string(ref_type));
644  }
645 
646  // add vla read effect
647  if (vla_effect_p) {
648  type t = entity_type(v);
649  /*
650  if (type_variable_p(t)) {
651  variable var = type_variable(t);
652  list dims = variable_dimensions(var);
653  list lel = NIL, leu = NIL;
654  FOREACH(DIMENSION, dim, dims) {
655  //lel = generic_proper_effects_of_address_expression(dimension_lower(dim), false);
656  //leu = generic_proper_effects_of_address_expression(dimension_upper(dim), false);
657  lel = generic_proper_effects_of_expression(dimension_lower(dim));
658  leu = generic_proper_effects_of_expression(dimension_upper(dim));
659  pips_assert("lel is weakly consistent", regions_weakly_consistent_p(lel));
660  pips_assert("leu is weakly consistent", regions_weakly_consistent_p(leu));
661 
662  le = gen_nconc(le, lel);
663  le = gen_nconc(le, leu);
664  pips_assert("le is weakly consistent", regions_weakly_consistent_p(le));
665 
666  lel = NIL;
667  leu = NIL;
668  }
669  }
670  else
671  */
672  {
673  list let = NIL;
674  let = type_to_effects(t);
675  pips_assert("let is weakly consistent", regions_weakly_consistent_p(let));
676 
677  le = gen_nconc(le, let);
678  pips_assert("le is weakly consistent", regions_weakly_consistent_p(le));
679  }
680  }
681 
682  // functions that can be pointed by effects_precondition_composition_op:
683  // effects_composition_with_preconditions_nop
684  // convex_regions_precondition_compose
685  (*effects_precondition_composition_op)(le, context, false);
686  }
687 
688  pips_debug(3, "end\n");
689  return(le);
690 }
691 
692 ␌
693 /* list generic_proper_effects_of_read_reference(reference ref)
694  * input : a reference that is read.
695  * output : the corresponding list of effects.
696  * modifies : nothing.
697  * comment : effects of a reference that is read
698  */
700 {
701  list le = NIL;
702 
704 
705  return(le);
706 }
707 
708 /* list proper_effects_of_written_reference(reference ref)
709  * input : a reference that is written.
710  * output : the corresponding list of effects.
711  * modifies : nothing.
712  * comment : effects of a reference that is written
713  */
715 {
716  list le = NIL;
717 
719 
720  return(le);
721 }
722 
723 
724 static list generic_proper_effects_of_complex_address_field_op(list l_args, list *l_pme, int write_p)
725 {
726  list le = NIL;
727  /* first get an effect on the structure */
728  /* is the structure a constant as in {0, 1}.im */
729  expression struct_exp = EXPRESSION(CAR(l_args));
730  // very inefficient. g_p_e_o_c_a_e should convey a way to say that it's argument is constant
731  /* list le1 = generic_proper_effects_of_expression(struct_exp); */
732 
733 /* if (ENDP(le1)) */
734 /* { */
735 /* pips_debug(8, "field operator applied on a constant expression -> no effect"); */
736 /* } */
737 /* else */
738 /* { */
739 /* gen_full_free_list(le1);*/
741  (struct_exp, l_pme, write_p);
742 
743  /* and add the field */
744  FOREACH(EFFECT, pme, *l_pme)
745  {
746  if(!effect_undefined_p(pme) && !anywhere_effect_p(pme))
747  {
748  expression field_exp = EXPRESSION(CAR(CDR(l_args)));
749  syntax s = expression_syntax(field_exp);
750  entity f;
753  /* we extend *pme by adding a dimension corresponding
754  * to the field */
756  }
757  }
758  /*}*/
759  pips_debug_effects(8, "End with le=\n", le);
760  pips_debug_effects(8, "and with *l_pme=\n", *l_pme);
761 
762  return le;
763 }
764 
765 static list generic_proper_effects_of_complex_address_point_to_op(list l_args, list *l_pme, int write_p)
766 {
767  /* first get an effect on the structure */
769  (EXPRESSION(CAR(l_args)), l_pme, write_p);
770 
771  /* and add the field */
772  FOREACH(EFFECT, pme, *l_pme)
773  {
774  if(!effect_undefined_p(pme) && !anywhere_effect_p(pme))
775  {
776  expression field_exp = EXPRESSION(CAR(CDR(l_args)));
777  syntax s = expression_syntax(field_exp);
778  entity f;
779  effect eff_read;
782  /* the pointer is read */
783  pips_debug(4, "we add a read effect on the pointer. \n");
784 
785  // functions that can be pointed by effect_dup_func:
786  // simple_effect_dup
787  // region_dup
788  // copy_effect
789  eff_read = (*effect_dup_func)(pme);
790  /* memory leak */
792  le = gen_nconc(le, CONS(EFFECT, eff_read, NIL));
793 
794 
795  /* We add a dereferencing */
797 
798  /* we add the field dimension */
800  }
801  }
802  pips_debug_effects(8, "End with le=\n", le);
803  pips_debug_effects(8, "and with *l_pme=\n", *l_pme);
804  return le;
805 }
806 ␌
807 /* Functions to handle all subcases of *(f(e1, e2...en))
808  *
809  * These functions are all called:
810  *
811  * generic_proper_effects_of_complex_address_xxxx_dereferencing_op
812  *
813  * where xxxx is the name of the function handled. The different cases
814  * for xxx are:
815  * - ENTITY_PLUS
816  * - ENTITY_POST_INCREMENT, ENTITY_POST_DECREMENT
817  * - ENTITY_PRE_INCREMENT, ENTITY_PRE_DECREMENT
818  * - ENTITY_ADDRESS
819  * - ENTITY_ASSIGN
820  * - ENTITY_DEREFERENCING
821  * - ENTITY_FIELD
822  * - ENTITY_POINT_TO
823  * - ...
824  * - user call
825  *
826  * These functions are called from:
827  *
828  * generic_proper_effects_of_complex_address_call_dereferencing_op()
829  *
830  * which is itslef called from:
831  *
832  * generic_proper_effects_of_complex_address_dereferencing_op()
833  */
834 
835 /* Compute the effet of *(++e) or *(--e) where e is any updatable
836  expression, i.e. a lhs expression. */
837 static list generic_proper_effects_of_complex_address_pre_update_dereferencing_op(entity op, expression e1, list *l_pme, int write_p)
838 {
839  list le = NIL;
843 
844  /* YOU DO NOT WANT TO GO DOWN RECURSIVELY. DO AS FOR C_PLUS ABOVE */
845 
846  pips_assert("The argument is a reference", syntax_reference_p(s1));
847  pips_assert("The reference is scalar", ENDP(reference_indices(r1)));
848 
851 
852  nr1 = copy_reference(r1);
853  if(ENTITY_PRE_INCREMENT_P(op))
855  else
858 
859  // functions that can be pointed by reference_to_effect_func:
860  // reference_to_simple_effect
861  // reference_to_convex_region
862  // reference_to_reference_effect
864  (nr1, a, false));
865 
866  return le;
867 }
868 
869 /* Compute the effet of *(e++) or *(e--) where e is any updatable expressions */
870 static list generic_proper_effects_of_complex_address_post_update_dereferencing_op(entity op __attribute__ ((__unused__)), expression e1, list *l_pme, int write_p)
871 {
872  list le = NIL;
874  (e1, l_pme, write_p);
875 
876  FOREACH(EFFECT, pme, *l_pme) {
877  if (! effect_undefined_p(pme)&& !anywhere_effect_p(pme)) {
878  /* we must add a read effect on *pme if it is a pointer type
879  */
880  if (effect_pointer_type_p(pme)) {
881  pips_debug(4, "It's a pointer; we add a read and write effect \n");
882 
883  // functions that can be pointed by effect_dup_func:
884  // simple_effect_dup
885  // region_dup
886  // copy_effect
887  effect eff_read = (*effect_dup_func)(pme);
889  le = gen_nconc(le, CONS(EFFECT, eff_read, NIL));
890  // functions that can be pointed by effect_dup_func:
891  // simple_effect_dup
892  // region_dup
893  // copy_effect
894  effect eff_write = (*effect_dup_func)(pme);
896  le = gen_nconc(le, CONS(EFFECT, eff_write, NIL));
897  }
898  /* We add a dereferencing */
900  }
901  }
902  return le;
903 }
904 
905 /* Compute the effet of *(e1+e2) where e1 and e2 are any expressions */
906 static list generic_proper_effects_of_complex_address_addition_dereferencing_op(expression e1, expression e2, list *l_pme, int write_p)
907 {
908  list le = NIL;
909  /* This might be tractable if e1 is a reference to a
910  * pointer. For instance, *(p+q-r) can be converted to p[q-r] */
913 
914  pips_debug(8,"*(p+q) case, with p = %s and q = %s\n",
917 
918  /* Beware, sometimes, *(p+i+j+k) is represented as *((p+i) + (j+k)):
919  * we must first retrieve p
920  */
921  if (syntax_call_p(s1))
922  {
923  call e1_c = syntax_call(s1);
924  entity e1_op = call_function(e1_c);
925  list e1_args = call_arguments(e1_c);
926 
927  if(ENTITY_PLUS_C_P(e1_op) || ENTITY_MINUS_C_P(e1_op))
928  {
929  expression e11 = EXPRESSION(CAR(e1_args));
930  expression e22 = EXPRESSION(CAR(CDR(e1_args)));
931 
932  /* SG this is a way to handle commutativity of PLUS_C */
933  if(ENTITY_PLUS_C_P(e1_op)) {
936  if(basic_pointer_p(b2)) {
937  expression etmp = e1;
938  e1=e2;
939  e2=etmp;
940  }
941  free_basic(b1);
942  free_basic(b2);
943  }
944 
945  pips_debug(8,"p is itself a complicated expression, with e11 = %s and e22 = %s\n",
947  expression_to_string(e22));
948  /* not too much ;-) */
950  {
951  pips_user_warning("Pips does not currently handle this complicated arithmetic pointer expression\n");
952  }
953  else
954  {
955  e1 = e11;
956  new_e2 = MakeBinaryCall(e1_op, copy_expression(e2), copy_expression(e22));
957  pips_debug(8, "new_e2 : %s\n",
958  expression_to_string(new_e2));
959  }
960  }
961  }
962 
964  (e1, l_pme, write_p);
965 
966  expression current_e2 = expression_undefined_p(new_e2) ? e2: new_e2;
967  FOREACH(EFFECT, pme, *l_pme)
968  {
969  if (! effect_undefined_p(pme)&& !anywhere_effect_p(pme))
970  {
971  syntax s2 = expression_syntax(current_e2);
972 
973  /* we must add a read effect on pme if it is a pointer type
974  */
975  /* deal with case *(p+(i=exp))
976  * the effect is equivalent to an effect on *(p+exp)
977  */
978  if (syntax_call_p(s2))
979  {
980  call s2_c = syntax_call(s2);
981  entity s2_op = call_function(s2_c);
982  list s2_args = call_arguments(s2_c);
983  if (ENTITY_ASSIGN_P(s2_op))
984  {
985  current_e2 = EXPRESSION(CAR(CDR(s2_args)));
986  }
987  }
988 
989  if (effect_pointer_type_p(pme))
990  {
991  effect eff_read;
992  pips_debug(4, "It's a pointer; we add a read effect \n");
993 
994  // functions that can be pointed by effect_dup_func:
995  // simple_effect_dup
996  // region_dup
997  // copy_effect
998  eff_read = (*effect_dup_func)(pme);
1000  le = gen_nconc(le, CONS(EFFECT, eff_read, NIL));
1001  // functions that can be pointed by effect_add_expression_dimension_func:
1002  // simple_effect_add_expression_dimension
1003  // convex_region_add_expression_dimension
1004  (*effect_add_expression_dimension_func)(pme, current_e2);
1005  }
1006  else /* array case */
1007  {
1009 
1010  if (type_variable_p(pme_t))
1011  {
1012  list l_ind = variable_dimensions(type_variable(pme_t));
1013 
1014  if (gen_length(l_ind) == 1)
1015  {
1016  // functions that can be pointed by effect_add_expression_dimension_func:
1017  // simple_effect_add_expression_dimension
1018  // convex_region_add_expression_dimension
1019  (*effect_add_expression_dimension_func)(pme, current_e2);
1020  }
1021  else
1022  {
1023  pips_user_warning("Pips does not precisely handle linearized array references\n");
1024  FOREACH(EXPRESSION, ind, l_ind)
1025  {
1026  // functions that can be pointed by effect_add_expression_dimension_func:
1027  // simple_effect_add_expression_dimension
1028  // convex_region_add_expression_dimension
1029  (*effect_add_expression_dimension_func)(pme, make_unbounded_expression());
1030  }
1031  }
1032  }
1033  else
1034  {
1035  /* replace current effect by an anywhere effect */
1036  effect new_eff = make_anywhere_effect
1038  free_cell(effect_cell(pme));
1039  effect_cell(pme) = effect_cell(new_eff);
1040  effect_cell(new_eff) = cell_undefined;
1041  free_action(effect_action(pme));
1042  effect_action(pme) = effect_action(new_eff);
1043  effect_action(new_eff) = action_undefined;
1045  effect_descriptor(pme) = effect_descriptor(new_eff);
1047  effect_to_may_effect(pme);
1048  free_effect(new_eff);
1049  }
1050 
1051  free_type(pme_t);
1052  }
1053  }
1054  }
1055  le = gen_nconc(le,
1057  if (!expression_undefined_p(new_e2))
1058  free_expression(new_e2);
1059  return le;
1060 }
1061 
1062 /* Compute the effect of *(lhs=rhs) */
1064 {
1065  // list le = generic_p_proper_effects_of_expression(lhs);
1066  // FI: temporary; we need a write effect on the addressed location
1068  le = gen_nconc(le,
1071  type pt = type_to_pointed_type(t);
1074  le = CONS(EFFECT, e, le);
1075  return le;
1076 }
1077 
1078 static list generic_proper_effects_of_complex_address_default_call_dereferencing_op(entity s_op, list s_args __attribute__((unused)), expression deref_exp, list *l_pme, int write_p)
1079 {
1080  list le = NIL;
1081  value op_init = entity_initial(s_op);
1082  tag t = value_tag(op_init);
1083  /* do nothing, go down recursively to handle other calls */
1084  pips_debug(8, "We go down recursively\n");
1085  // FI: the expression may be dereferenced and the resulting location
1086  // written, but the expression is only read
1088  (deref_exp, l_pme, false);
1089 
1090  bool success = !ENDP(*l_pme);
1091  if (!success)
1092  {
1093  type op_type = ultimate_type(entity_type(s_op));
1094  if (type_functional_p(op_type) && t == is_value_constant)
1095  {
1096  constant op_const = value_constant(op_init);
1097  if (constant_int_p(op_const) && (constant_int(op_const) == 0))
1098  {
1099  success = false;
1100  }
1101  else
1102  {
1103  type tt = functional_result(type_functional(op_type));
1104  if (type_variable_p(tt))
1105  {
1106  variable v = type_variable(tt);
1107  basic b = variable_basic(v);
1108  if (basic_string_p(b))/* constant strings */
1109  {
1110  /*the user dereferences a constant string -> it's a constant,
1111  -> no effect */
1112  success = true;
1113  }
1114  }
1115  }
1116  }
1117  }
1118  if (!success)
1119  {
1120  pips_user_warning("dereferencing a constant address expression: "
1121  "PIPS doesn't know how to handled that precisely\n");
1122  *l_pme = effect_to_list(make_anywhere_effect(write_p?
1125  }
1126  else
1127  {
1128  // FI: many cases seemed to work fine without list nle, but
1129  // Points-to/dereferencing21.c which probably failed the test
1130  // for adding read effect
1131  // effects added to nle may already exist
1132 
1133  // list nle = NIL;
1134  FOREACH(EFFECT, pme, *l_pme) {
1135  if(!effect_undefined_p(pme) && !anywhere_effect_p(pme))
1136  {
1137  effect eff_read;
1138  //expression e1 = EXPRESSION(CAR(l_args));
1139  //expression e1 = EXPRESSION(CAR(s_args));
1140  expression e1 = deref_exp;
1141  type e1t = expression_to_type(e1);
1142 
1143  pips_debug(4,"adding a read effect on dereferenced expression\n");
1144 
1145  /* we add the read effect on the dereferenced expression
1146  if it's a pointer
1147  */
1148  if (type_variable_p(e1t) &&
1151  {
1152  pips_debug(8, "adding read effect on argument \n");
1153  // functions that can be pointed by effect_dup_func:
1154  // simple_effect_dup
1155  // region_dup
1156  // copy_effect
1157  eff_read = (*effect_dup_func)(pme);
1158  /* memory leak? */
1160  le = gen_nconc(le, CONS(EFFECT, eff_read, NIL));
1161  }
1162 
1163  free_type (e1t);
1164 
1165  pips_debug(8, "adding dereferencing dimension \n");
1166  // effect npme = (*effect_dup_func)(pme);
1167  // effect_add_dereferencing_dimension(npme);
1169  action na = write_p?
1171  free_action(effect_action(pme));
1172  effect_action(pme) = na;
1173  //nle = CONS(EFFECT, npme, nle);
1174  }
1175  }
1176  //*l_pme = gen_nconc(*l_pme, nle);
1177  }
1178  return le;
1179 }
1180 
1181 /* Compute the effect of "*&e"
1182  *
1183  * FI: I am not sure it is of any use. The default call might be
1184  * perfect. I based my analysis on test case Points-to/lhs04.c, which
1185  * I mis read.
1186 */
1188 {
1189  list le = NIL;
1190  if(false && expression_reference_p(e1)) {
1192  list sl = reference_indices(r1);
1193 
1194  // Get the effects of the subscript expressions
1195  FOREACH(EXPRESSION, se, sl) {
1196  list nle =
1198  l_pme,
1199  write_p);
1200  le = gen_nconc(le, nle);
1201  }
1202 
1203  /* Generate a generic effect for the reference itself */
1205  // cell c1 = make_cell_preference(r1); // preserve r1, part of IR
1206  // approximation ap1 = make_approximation_must();
1207  //descriptor d1 = make_descriptor_none();
1208  // effect e1 = make_effect(c1, x1, ap1, d1);
1209  effect e1 = (*reference_to_effect_func)(r1, a1, true);
1210  le = CONS(EFFECT, e1, le);
1211  }
1212  else {
1214  l_pme,
1215  write_p);
1216  }
1217  return le;
1218 }
1219 
1220 /* Compute the effect of *(f(e1, e2...en)) where f is a function,
1221  * possibly an intrinsic.
1222  *
1223  * Some precision is gained by dispatching the processing according to
1224  * f, for some f. A default processing is used when no gain is
1225  * expected.
1226  *
1227  * This is the first component of the old version of function
1228  * generic_proper_effects_of_complex_address_dereferencing_op() which
1229  * has been broken down in about ten different functions.
1230  *
1231  * deref_exp is redundant but used by the default function
1232  */
1233 static list generic_proper_effects_of_complex_address_call_dereferencing_op(entity s_op, list s_args, expression deref_exp, list *l_pme, int write_p)
1234 {
1235  list le = NIL;
1236  //value op_init = entity_initial(s_op);
1237  //tag t = value_tag(op_init);
1238 
1239  pips_debug(4,"The dereferenced expression is a call itself (%s)\n",
1240  entity_local_name(s_op));
1241  ifdebug(8)
1242  {
1243  pips_debug(8,"with arguments : \n");
1244  print_expressions(s_args);
1245  }
1246 
1247  /* MINUS_C should be handled as well BC */
1248  if(ENTITY_PLUS_C_P(s_op))
1249  {
1250  /* case *(e1+e2) */
1251  expression e1 = EXPRESSION(CAR(s_args));
1252  expression e2 = EXPRESSION(CAR(CDR(s_args)));
1253  le = generic_proper_effects_of_complex_address_addition_dereferencing_op(e1, e2, l_pme, write_p);
1254  }
1255  /* Other functions to process: *(p++), *(++p), *(p--), *(--p) */
1256  else if(ENTITY_POST_INCREMENT_P(s_op) ||
1258  {
1259  // case *(e1++) or *(e1--)
1260  // the update has a read and write effect on e1
1261  expression e1 = EXPRESSION(CAR(s_args));
1262  le = generic_proper_effects_of_complex_address_post_update_dereferencing_op(s_op, e1, l_pme, write_p);
1263  }
1264  else if(ENTITY_PRE_INCREMENT_P(s_op) ||
1265  ENTITY_PRE_DECREMENT_P(s_op))
1266  {
1267  expression e1 = EXPRESSION(CAR(s_args));
1268  le = generic_proper_effects_of_complex_address_pre_update_dereferencing_op(s_op, e1, l_pme, write_p);
1269  }
1270  else if(ENTITY_ADDRESS_OF_P(s_op))
1271  {
1272  // case *&e
1273  expression e1 = EXPRESSION(CAR(s_args));
1275  }
1276  else if(ENTITY_ASSIGN_P(s_op)) // New
1277  {
1278  expression lhs = EXPRESSION(CAR(s_args));
1279  expression rhs = EXPRESSION(CAR(CDR(s_args)));
1281  }
1282  else if(ENTITY_DEREFERENCING_P(s_op)) // New
1283  {
1284  // FI: not clear if a special case is needed here?
1285  le = generic_proper_effects_of_complex_address_default_call_dereferencing_op(s_op, s_args, deref_exp, l_pme, write_p);
1286  }
1287  else if(ENTITY_FIELD_P(s_op)) // New
1288  {
1289  // FI: not clear if a special case is needed here?
1290  le = generic_proper_effects_of_complex_address_default_call_dereferencing_op(s_op, s_args, deref_exp, l_pme, write_p);
1291  }
1292  else if(ENTITY_POINT_TO_P(s_op)) // New
1293  {
1294  // FI: not clear if a special case is needed here?
1295  le = generic_proper_effects_of_complex_address_default_call_dereferencing_op(s_op, s_args, deref_exp, l_pme, write_p);
1296  }
1297  else if(ENTITY_CONDITIONAL_P(s_op)) // New
1298  {
1299  expression cond = EXPRESSION(CAR(s_args));
1300  expression e1 = EXPRESSION(CAR(CDR(s_args)));
1301  expression e2 = EXPRESSION(CAR(CDR(CDR(s_args))));
1303  }
1304  else
1305  {
1306  le = generic_proper_effects_of_complex_address_default_call_dereferencing_op(s_op, s_args, deref_exp, l_pme, write_p);
1307  }
1308 
1309  // l_pme is returned by side effect
1310 
1311  return le;
1312 }
1313 ␌
1314 /* Process "*((t) e)"
1315  *
1316  * Could be rewritten as "*(e)" or "(pt) *(e)" where pt is the type
1317  * pointed by "t".
1318  *
1319  * Could return an anywhere effect, possibly typed by pt.
1320  */
1322 {
1323  expression dce = cast_expression(dc); // dereferenced casted expression
1325  // FI: not too sure if a new object type is allocated...
1326  type pt = type_to_pointed_type(dcet);
1328  syntax s2 = make_syntax_cast(make_cast(pt, ne1));
1329  expression ne2 = syntax_to_expression(s2);
1331  // Free ne1 and ne2 but not dce
1333  free_expression(ne2);
1334  return le;
1335 }
1336 ␌
1337 /* Default processing of *(e)
1338  *
1339  * See detailed processing in
1340  * generic_proper_effects_of_complex_address_dereferencing_op()
1341  */
1342 static list generic_proper_effects_of_complex_address_default_dereferencing_op(expression deref_exp, list *l_pme, int write_p)
1343 {
1345  (deref_exp, l_pme, write_p);
1346 
1347  if (ENDP(*l_pme))
1348  {
1349  pips_user_warning("Dereferencing a constant address expression: "
1350  "PIPS doesn't know how to handle that precisely\n");
1352  action a = write_p? make_action_write_memory()
1355  }
1356  else
1357  {
1358  FOREACH(EFFECT, pme, *l_pme) {
1359  if(!effect_undefined_p(pme) && !anywhere_effect_p(pme))
1360  {
1361  effect eff_read;
1362  // expression e1 = EXPRESSION(CAR(l_args));
1363  expression e1 = deref_exp;
1364  type e1t = expression_to_type(e1);
1365 
1366  pips_debug(4,"adding a read effect on dereferenced expression\n");
1367 
1368  /* we add the read effect on the dereferenced expression
1369  if it's a pointer
1370  */
1371  if (type_variable_p(e1t) &&
1374  {
1375  pips_debug(8, "adding read effect on argument \n");
1376  // functions that can be pointed by effect_dup_func:
1377  // simple_effect_dup
1378  // region_dup
1379  // copy_effect
1380  eff_read = (*effect_dup_func)(pme);
1381  /* memory leak? */
1383  le = gen_nconc(le, CONS(EFFECT, eff_read, NIL));
1384  }
1385 
1386  free_type (e1t);
1387 
1388  pips_debug(8, "adding dereferencing dimension \n");
1390  }
1391  }
1392  }
1393  return le;
1394 }
1395 
1396 /* Compute the effet of *(e) where e is not a simple expression, that
1397  * is probably not a reference.
1398  *
1399  * This function should be further cleaned up - see call_to_post_pv -
1400  * in particular pointer arithmetic should be externalized - BC.
1401  */
1402 static list generic_proper_effects_of_complex_address_dereferencing_op(list l_args, list *l_pme, int write_p)
1403 {
1404  list le = NIL;
1405  expression deref_exp = EXPRESSION(CAR(l_args));
1406  syntax deref_s = expression_syntax(deref_exp);
1407 
1408  if(syntax_call_p(deref_s))
1409  {
1410  call s_c = syntax_call(expression_syntax(deref_exp));
1411  entity s_op = call_function(s_c);
1412  list s_args = call_arguments(s_c);
1413  // FI: I am not sure how to handle write_p... but it is needed by
1414  // generic_proper_effects_of_complex_address_default_call_dereferencing_op(
1415  le = generic_proper_effects_of_complex_address_call_dereferencing_op(s_op, s_args, deref_exp, l_pme, write_p);
1416  }
1417  else if (syntax_va_arg_p(deref_s))
1418  {
1419  /* there could be more work here, but va_arg is very poorly
1420  * handled everywhere for the moment.
1421  */
1422  /* we generated an effect on the va_list, and that is all */
1423  list vararg_list = syntax_va_arg(expression_syntax(deref_exp));
1424  sizeofexpression soe = SIZEOFEXPRESSION(CAR(vararg_list));
1425 
1426  pips_debug(4,"The dereferenced expression is a va_arg\n");
1427 
1429  /* and we must add an anywhere effect because we don't know where
1430  * the dereferenced location is. TO BE CHECKED OR REFINED
1431  *
1432  * We could apply effect(s)_to_pointed_effect(s) to le and not
1433  * forget l_pme.
1434  */
1435  type t = sizeofexpression_type(soe);
1438  le = CONS(EFFECT, make_typed_anywhere_effect(a, ct), le);
1439  }
1440  else if (syntax_cast_p(deref_s))
1441  {
1442  cast dc = syntax_cast(deref_s);
1443  le = generic_proper_effects_of_complex_address_cast_dereferencing_op(dc, deref_exp, l_pme, write_p);
1444  }
1445  else
1446  {
1447  /* This is not a call, nor a va_arg, nor a cast go down recursively */
1448  pips_debug(4,"The dereferenced expression is not a call, nor a va_arg, nor a cast itself: we go down recursively\n");
1449  le = generic_proper_effects_of_complex_address_default_dereferencing_op(deref_exp, l_pme, write_p);
1450  }
1451 
1452  pips_debug_effects(8, "End with le=\n", le);
1453  pips_debug_effects(8, "End with *l_pme=\n", *l_pme);
1454 
1455  return le;
1456 }
1457 
1458 /* Conditional case *(cond?e1:e2). Rewrite as cond? *(e1) : *(e2).
1459  *
1460  * FI: And pray that references used in effects are not shared with
1461  * references used in expressions... or reuse the source code is the
1462  * new expressions.
1463  *
1464  * Should be static... and placed elsewhere in the source code
1465  */
1467 {
1470  list le1 = NIL, le2 = NIL;
1471  if(write_p) {
1472  // FI: to be safe,
1473  // generic_proper_effects_of_complex_address_expression() should
1474  // be called
1477  }
1478  else {
1481  }
1482  list le = gen_nconc(le1, le2);
1485  // Clean-up de1 and de2 without breaking e1 or e2
1486  call c1 = expression_call(de1);
1487  call c2 = expression_call(de2);
1488  call_arguments(c1) = NIL;
1489  call_arguments(c2) = NIL;
1490  free_expression(de1);
1491  free_expression(de2);
1492  return le;
1493 }
1494 
1495 /* Effect of *((cast) e) */
1497 {
1498  list le = NIL;
1499  syntax op_arg_s = expression_syntax(EXPRESSION(CAR(args)));
1500  if (syntax_cast_p(op_arg_s))
1501  {
1502  pips_debug(4, "Dereferencing a cast expression \n");
1503  // we cannot call generic_proper_effects_of_complex_address_dereferencing_op here
1504  // because we need to test the relationship between the type of call_exp and cast_exp.
1505 
1506  cast c = syntax_cast(op_arg_s);
1507  expression cast_exp = cast_expression(c);
1508 
1509  // try to see if we have something like *((int (*)[]) t) where t is of type int * for instance
1510 
1511  // FI: temporary change, call_exp is not an argument for the
1512  // time being. The type could be passe directly to make sure
1513  // each recurrence level peels off the argument expression.
1514 
1515  // type call_exp_t = expression_to_type(call_exp);
1516  type call_exp_t = type_undefined; // FI TEMPORARY
1517  type cast_exp_t = expression_to_type(cast_exp);
1518 
1519  list l_me1 = NIL;
1520  le = generic_proper_effects_of_complex_address_expression(cast_exp, &l_me1, write_p);
1521  // re-use an existing function because currently it checks if types are the same
1522  // or if each array dimension corresponds to a pointer dimension
1523  if (!ENDP(l_me1) && !anywhere_effect_p(EFFECT(CAR(l_me1))))
1524  {
1526  {
1527  // current result is ok;
1528  pips_debug(4, "compatible types \n");
1529  *l_pme = l_me1;
1530 
1531  if (write_p && pointer_type_p(cast_exp_t))
1532  {
1533  FOREACH(EFFECT, eff, l_me1) {
1534  // functions that can be pointed by effect_dup_func:
1535  // simple_effect_dup
1536  // region_dup
1537  // copy_effect
1538  effect read_eff = (*effect_dup_func)(eff);
1539  effect_to_read_effect(read_eff);
1540  le = CONS(EFFECT, read_eff, le);
1541  }
1542  }
1543  }
1544  else
1545  {
1546  pips_debug(4, "non compatible types \n");
1547 
1548  // we generate all possible paths from the cast expression main effects
1549  /* No, we currently don't know how to handle that at all call sites */
1550  /* It may be more advisable to return an effect on the base adress, and check the
1551  * type of the base adress. If it's not compatible, then all paths effects
1552  * should be generated if it is appropriate.
1553  */
1554  /* FOREACH(EFFECT, eff, l_me1) */
1555  /* { */
1556  /* list l_tmp = generic_effect_generate_all_accessible_paths_effects(eff, cast_t, write_p?'w':'r'); */
1557  /* effects_to_may_effects(l_tmp); */
1558  /* *l_pme = gen_nconc(l_tmp, *l_pme); */
1559  /* } */
1560 
1561  pips_user_warning("PIPS currently does not know how to precisely handle "
1562  "complex cast expressions\n");
1563  // FI->BC: this is pretty pessimistic when the C
1564  // standard claims that the pointed object is unchanged.
1567  }
1568  }
1569  else
1570  {
1571  pips_user_warning("dereferencing a constant address expression: "
1572  "PIPS doesn't know how to handled that precisely\n");
1573  *l_pme = effect_to_list(make_anywhere_effect(write_p?
1576  }
1577  free_type(call_exp_t);
1578  free_type(cast_exp_t);
1579  }
1580  else
1581  {
1582  le = generic_proper_effects_of_complex_address_dereferencing_op(args, l_pme, write_p);
1583  }
1584  return le;
1585 }
1586 
1587 /* Conditional case cond?e1:e2 (new version) */
1589 {
1590  //list l_pme1 = NIL;
1591  //list l_pme2 = NIL;
1592  expression cond = EXPRESSION(CAR(args));
1593  expression e1 = EXPRESSION(CAR(CDR(args)));
1594  expression e2 = EXPRESSION(CAR(CDR(CDR(args))));
1595 
1596  // FI: why not use proper_effects_of_expression() ?
1597  // list le1 = generic_proper_effects_of_complex_address_expression(e1, &l_pme1, write_p);
1598  list le1 = NIL, le2 = NIL;
1599  if(write_p) {
1602  }
1603  else {
1606  }
1608  //effects_to_may_effects(l_pme1);
1609  //list le2 = generic_proper_effects_of_complex_address_expression(e2, &l_pme2, write_p);
1611  //effects_to_may_effects(l_pme2);
1612  // *l_pme = gen_nconc(l_pme1, l_pme2);
1613  // l_pme is unused
1614  *l_pme = NIL;
1615  list le = gen_nconc(le1, le2);
1617  return le;
1618 }
1619 
1620 /* Conditional case cond?e1:e2 (old version) */
1622 {
1623  list l_pme1 = NIL;
1624  list l_pme2 = NIL;
1625  expression cond = EXPRESSION(CAR(args));
1626  expression e1 = EXPRESSION(CAR(CDR(args)));
1627  expression e2 = EXPRESSION(CAR(CDR(CDR(args))));
1628 
1629  // FI: why not use proper_effects_of_expression() ?
1630  list le1 = generic_proper_effects_of_complex_address_expression(e1, &l_pme1, write_p);
1631  //list le1 = NIL, le2 = NIL;
1632  //if(write_p) {
1633  // le1 = generic_proper_effects_of_any_lhs(e1);
1634  // le2 = generic_proper_effects_of_any_lhs(e2);
1635  //}
1636  //else {
1637  // le1 = generic_proper_effects_of_expression(e1);
1638  // le2 = generic_proper_effects_of_expression(e2);
1639  // }
1641  effects_to_may_effects(l_pme1);
1642  list le2 = generic_proper_effects_of_complex_address_expression(e2, &l_pme2, write_p);
1644  effects_to_may_effects(l_pme2);
1645  *l_pme = gen_nconc(l_pme1, l_pme2);
1646  list le = gen_nconc(le1, le2);
1648  return le;
1649 }
1650 
1651 list generic_proper_effects_of_complex_address_assign_op(list args, list * l_pme __attribute__((unused)), bool write_p __attribute__((unused)))
1652 {
1653  // FI: looks very much like affect_effects() to me...
1654  expression lhs = EXPRESSION(CAR(args));
1655  expression rhs = EXPRESSION(CAR(CDR(args)));
1659  pips_internal_error("Not implemented yet: assignment.\n");
1660  return le;
1661 }
1662 
1663 list generic_proper_effects_of_complex_address_update_op(list args __attribute__((unused)), list * l_pme __attribute__((unused)), bool write_p __attribute__((unused)))
1664 {
1665  list le = NIL;
1666  pips_internal_error("Not implemented yet: update operators.\n");
1667  // le = unique_update_effects(op, args);
1668  return le;
1669 }
1670 
1671 /* The left hand side expression is f(e1, e2...en) */
1672 static list generic_proper_effects_of_complex_address_call_expression(expression call_exp, list *l_pme, int write_p)
1673 {
1674  list le = NIL;
1675  call c = syntax_call(expression_syntax(call_exp));
1676  entity op = call_function(c);
1677  list args = call_arguments(c);
1678  /* FI: we assume there it at least one argument */
1679  pips_debug(4, "This is a call\n");
1680 
1681  // FI: because of recursive calls, this low-level reset does not seem right
1682  // *l_pme = NIL;
1683 
1684  if(ENTITY_FIELD_P(op))
1685  {
1686  pips_debug(4, "Call is a field operator\n");
1687  le = generic_proper_effects_of_complex_address_field_op(args, l_pme, write_p);
1688  }
1689  else if(ENTITY_POINT_TO_P(op))
1690  {
1691  pips_debug(4, "Call is a point to operator\n");
1692  le = generic_proper_effects_of_complex_address_point_to_op(args, l_pme, write_p);
1693  }
1694  else if(ENTITY_DEREFERENCING_P(op))
1695  {
1696  pips_debug(4, "Call is a dereferencing operator \n");
1697  le = generic_proper_effects_of_complex_address_dereferencing_op(args, l_pme, write_p);
1698  }
1699  else if(ENTITY_CONDITIONAL_P(op))
1700  {
1701  pips_debug(4, "Call is a conditional operator\n");
1702  // le = generic_proper_effects_of_complex_address_conditional_op(args, l_pme, write_p);
1703  //le = new_generic_proper_effects_of_complex_address_conditional_op(args, l_pme, write_p);
1705  }
1706  else if(ENTITY_ASSIGN_P(op))
1707  {
1708  pips_debug(4, "Call is an assignment operator\n");
1709  le = generic_proper_effects_of_complex_address_assign_op(args, l_pme, write_p);
1710  }
1711  else if(ENTITY_ADDRESS_OF_P(op))
1712  {
1713  pips_debug(4, "Call is an address-of operator\n");
1714  // FI: not too pleased; &a[i] implies reading i, but not a; &a is a constant
1715  expression e1 = EXPRESSION(CAR(args));
1717  }
1718  else if(ENTITY_POST_INCREMENT_P(op) ||
1722  ) {
1723  pips_debug(4, "Call is an update operator\n");
1724  le = generic_proper_effects_of_complex_address_update_op(args, l_pme, write_p);
1725  }
1726  else
1727  {
1728  /* failure: a user function is called to return a structure or an address */
1729  /* if it's a structure, it's ok -> no effect. If it's an adress,
1730  * it may be anywhere until we can retrieve it from pointer
1731  * analysis.
1732  */
1733  type t = expression_to_type(call_exp);
1734  if(pointer_type_p(t) || array_type_p(t))
1735  {
1736  pips_user_warning("PIPS currently does not know how to precisely handle "
1737  "address values used in complex call expressions expression\n");
1738  // FI: the anywhere effect could be typed, but this is kind of a
1739  // not implemented yet situation that will show up because of
1740  // the untyped anywhere...
1743  }
1744  else
1745  {
1746  pips_debug(8, "constant return value: -> no main effects\n");
1747  }
1748  free_type(t);
1749  le = generic_proper_effects_of_expression(call_exp);
1750  }
1751 
1752  pips_debug_effects(8, "End with le=\n", le);
1753  pips_debug_effects(8, "and with *l_pme=\n", *l_pme);
1754  return le;
1755 }
1756 
1757 static list generic_proper_effects_of_complex_address_cast_expression(cast c, list *l_pme, int write_p __attribute__((unused)))
1758 {
1759  list le = NIL;
1760 
1761  if(!get_bool_property("ALIASING_ACROSS_TYPES"))
1762  pips_user_warning("Property ALIASING_ACROSS_TYPE should be set to true because casts are used in the source code.\n");
1763 
1764  /* FI: The cast has an impact on pointer arithmetic. I do not know
1765  how to take it into account. The cast may also use a typedef
1766  type. */
1767  /* BC : it is a translation. The main effect should be translated
1768  accordingly to the cast type on return of the recursion. */
1769  pips_user_warning("Cast impact on pointer arithmetic and indexing is ignored\n");
1770  if(!get_bool_property("MEMORY_EFFECTS_ONLY")) {
1771  type ct = cast_type(c);
1772 
1773  if(typedef_type_p(ct)) {
1775  effect tre = make_declaration_effect(te, false); // type
1776  le = gen_nconc(le, CONS(EFFECT, tre, NIL));
1777  }
1778  }
1779  expression cast_exp = cast_expression(c);
1780  pips_debug(8, "We go down recursively on the cast expression \n");
1781  // le = gen_nconc(le, generic_proper_effects_of_expression(cast_exp));
1783  (cast_exp, l_pme, write_p));
1784 
1785  pips_debug_effects(8, "End with le=\n", le);
1786  pips_debug_effects(8, "and with *l_pme=\n", *l_pme);
1787 
1788  // pips_assert("*l_pme is empty", ENDP(*l_pme));
1789  // le = gen_nconc(le, *l_pme);
1790 
1791  return le;
1792 }
1793 
1794 static list generic_proper_effects_of_complex_address_subscript_expression(subscript subsc, list *l_pme, int write_p)
1795 {
1796  pips_debug(8, "begin\n");
1797 
1798  list le = NIL;
1799 
1800  expression subsc_exp = subscript_array(subsc);
1801  list ind = subscript_indices(subsc);
1802  type t_subsc_exp = expression_to_type(subsc_exp);
1803  pips_debug(8, "We go down recursively on the subscripted expression \n");
1805  (subsc_exp, l_pme, write_p);
1806 
1807  FOREACH(EFFECT, pme, *l_pme)
1808  {
1809  if(!effect_undefined_p(pme) && !anywhere_effect_p(pme))
1810  {
1811  /* if the array expression is a pointer, we must add a read
1812  effect on it, that is to say a read effect on pme.
1813  */
1814  if (pointer_type_p(t_subsc_exp))
1815  {
1816  // functions that can be pointed by effect_dup_func:
1817  // simple_effect_dup
1818  // region_dup
1819  // copy_effect
1820  effect eff_read = (*effect_dup_func)(pme);
1821 
1822  pips_debug(5, "adding read effect on array expression\n");
1823  /* memory leak? */
1824  effect_action(eff_read) = make_action_read_memory();
1825  le = gen_nconc(le, CONS(EFFECT, eff_read, NIL));
1826  }
1827 
1828  /* We add the corresponding dimensions to the effect *pme
1829  * and we should add read effects on pointer subscript indices
1830  */
1831  FOREACH(EXPRESSION, ind_exp, ind)
1832  {
1833  // functions that can be pointed by effect_add_expression_dimension_func:
1834  // simple_effect_add_expression_dimension
1835  // convex_region_add_expression_dimension
1836  (*effect_add_expression_dimension_func)(pme, ind_exp);
1838 
1839  }
1840  }
1841  }
1842  pips_debug_effects(8, "End with le=\n", le);
1843  pips_debug_effects(8, "and with *l_pme=\n", *l_pme);
1844 
1845  return le;
1846 }
1847 
1848 static list generic_proper_effects_of_complex_address_va_arg_expression(list __attribute__((unused)) v, list *l_pme, int write_p)
1849 {
1850  pips_debug(8, "begin");
1851 
1852  list le = NIL;
1853 
1854  /* The built-in can return a pointer which is dereferenced */
1855  /* va_args is read... */
1858 
1859  pips_debug_effects(8, "End with le=\n", le);
1860  pips_debug_effects(8, "and with *l_pme=\n", *l_pme);
1861 
1862  return le;
1863 }
1864 
1865 
1866 ␌
1867 /**
1868  @return : a list of read effects corresponding to intermediate read and write
1869  memory accesses during the evaluation of add_exp.
1870  @param add_exp is the expression which memory effects we are looking for
1871 
1872  @param pme is a Pointer towards the Main memory Effect of
1873  add_exp. There may be more than one when the evaluation cannot be
1874  performed statically, e.g. because o a conditional operator or
1875  because the points-to information is imprecise.
1876 
1877  @param write_p is a boolean set to true if the main effect is write, false
1878  otherwise.
1879 
1880  Go down along the first argument till you find a reference or a
1881  dereferencing and build the effect *pme by side effects as well as
1882  the auxiliary effect list le on the way back up. To start with
1883  dispatch the execution according to the kind of expression
1884  add_exp. If is is a call, dispatch again according to the intrinsics
1885  or use function called. If it is a call to dereferencing, dispatch
1886  again according to what is dereferenced to have some look ahead and
1887  compute the effects more precisely than with a pure recursive
1888  descent.
1889 
1890  Checks at each step that no effect is generated on partially subscripted
1891  arrays.
1892 
1893  Beware that add_exp may hide any C expressions, including updates and
1894  even assignments. *l_pme may have to be reset at some points, the
1895  result be merged into le, and the previous *l_pme used again.
1896 
1897  Beware also that this is a generic function that may be used to
1898  compute convex array regions. Effects must be handled thru function
1899  pointers, not directly.
1900 
1901  FI: I am afraid I haven't always managed properly the use of *l_pme
1902  and le (17 July 2016). Also, many functions should be declared static
1903  as they shuld only be entered from
1904  generic_proper_effects_of_complex_address_expression() or its
1905  callees.
1906 */
1908 {
1909  list le = NIL;
1910  syntax s = expression_syntax(add_exp);
1911 
1912  pips_debug(3, "begin for expression : %s\n",
1913  expression_to_string(add_exp));
1914 
1915  if(syntax_reference_p(s))
1916  {
1917  pips_debug(4, "reference case \n");
1919  effect pme;
1921  write_p, true);
1922  if (pme != effect_undefined)
1923  *l_pme = effect_to_list(pme);
1924  else
1926 
1927  }
1928  else if(syntax_call_p(s))
1929  {
1930  pips_debug(4, "call case\n");
1931  le = generic_proper_effects_of_complex_address_call_expression(add_exp, l_pme, write_p);
1932  }
1933  else if(syntax_cast_p(s))
1934  {
1935  pips_debug(4, "cast case\n");
1936  le = generic_proper_effects_of_complex_address_cast_expression(syntax_cast(s), l_pme, write_p);
1937 
1938  }
1939  else if(syntax_subscript_p(s))
1940  {
1941  pips_debug(4,"subscript case\n");
1942  le = generic_proper_effects_of_complex_address_subscript_expression(syntax_subscript(s), l_pme, write_p);
1943  }
1944  else if(syntax_va_arg_p(s))
1945  {
1946  pips_debug(4,"va_arg case\n");
1947  le = generic_proper_effects_of_complex_address_va_arg_expression(syntax_va_arg(s), l_pme, write_p);
1948  }
1949  else
1950  {
1951  /* sizeofexpression, application.*/
1952  pips_internal_error("Unexpected case");
1953  }
1954 
1955  pips_debug_effects(8, "End with le=\n", le);
1956  pips_debug_effects(8, "and with *l_pme=\n", *l_pme);
1957 
1958  return le;
1959 }
1960 
1961 
1963 {
1965 }
1966 
1967 
1968 /**
1969  @return : a list of read effects corresponding to intermediate read memory
1970  accesses during the evaluation of add_exp.
1971  @param add_exp is the expression which memory effects we are looking for
1972  @param l_addexp_pme is a Pointer towards the Main memory Effects of add_exp.
1973  @param lpme is a pointer towars the memory effects of the expression if it is
1974  of type struct or union (but not an array of structs or union).
1975  @param write_p is a boolean set to true if the main effect is write, false
1976  otherwise.
1977 
1978  This function is an interface to generic_proper_effects_of_complex_address_expression
1979  that also generates effects on paths accessible from struct and union fields down
1980  to pointers if the expression type is a struct or union (basic derived but not enum, and
1981  no dimensions).
1982  If *lpme is not set to NIL, then the main effects have no real sense (effects on a variable name),
1983  and should be freed.
1984 */
1985 /* It's unused */
1986 list generic_proper_effects_of_complex_memory_access_expression(expression addexp, list *l_addexp_pme, list *lpme, int write_p)
1987 {
1988  list le = NIL;
1989  *lpme = NIL;
1990 
1991  pips_debug(5, "call or subscript case\n");
1992  /* Look for a main read-write effect of the lhs and for its
1993  * secondary effects */
1994  le = generic_proper_effects_of_complex_address_expression(addexp, l_addexp_pme, write_p);
1995 
1996  FOREACH(EFFECT, pme, *l_addexp_pme)
1997  {
1998  if(!effect_undefined_p(pme))
1999  {
2000  type addexp_t = expression_to_type(addexp);
2001 
2002  if (type_variable_p(addexp_t))
2003  {
2004  variable addexp_tv = type_variable(addexp_t);
2005  if (ENDP(variable_dimensions(addexp_tv)))
2006  {
2007  basic addexp_tvb = variable_basic(addexp_tv);
2008  if (basic_derived_p(addexp_tvb) && !(type_enum_p(entity_type(basic_derived(addexp_tvb)))))
2009  {
2010  *lpme = gen_nconc(generic_r_proper_effects_of_derived_reference(pme, addexp_t), *lpme);
2011  }
2012  }
2013  else
2014  {
2015  pips_debug(8, "main effect is on array name \n");
2016  }
2017  }
2018  else
2019  {
2020  pips_internal_error("case not handled yet ");
2021  }
2022  free_type(addexp_t);
2023  }
2024  }
2030  // functions that can be pointed by effects_precondition_composition_op:
2031  // effects_composition_with_preconditions_nop
2032  // convex_regions_precondition_compose
2033  (*effects_precondition_composition_op)(*lpme, context, false);
2034  }
2035 
2036  return le;
2037 }
2038 
2039 /* This function merges the le and *l_pme lists that are used
2040  * concurrently at lower level to distinguish between the main effect
2041  * (?) and the side effects (?).
2042  */
2044 {
2045  list le = NIL;
2046  syntax s = expression_syntax(addexp);
2047 
2048 
2049  pips_debug(5, "begin for expression : %s\n",
2050  expression_to_string(addexp));
2051 
2052  switch (syntax_tag(s))
2053  {
2054  case is_syntax_reference:
2055  {
2056  pips_debug(5, "reference case\n");
2057  if(write_p)
2059  else
2060  pips_internal_error("Case not taken into account");
2061  break;
2062  }
2063  case is_syntax_call:
2064  case is_syntax_subscript:
2065  {
2066  list l_pme = NIL; /* main data read-write effect: p[*] */
2067 
2068  pips_debug(5, "%s case\n",
2069  syntax_tag(s) == is_syntax_call? "call": "subscript");
2070  /* Look for a main read-write effect of the lhs and for its
2071  * secondary effects */
2072  le = generic_proper_effects_of_complex_address_expression(addexp, &l_pme, write_p);
2073 
2074  FOREACH(EFFECT, e, l_pme)
2075  {
2076  if(!effect_undefined_p(e))
2077  {
2079 
2083 
2084  type addexp_t = expression_to_type(addexp);
2085 
2086  /* we add the read effect if it's not an array name
2087  */
2088  if (type_variable_p(addexp_t))
2089  {
2090  variable addexp_tv = type_variable(addexp_t);
2091  if (ENDP(variable_dimensions(addexp_tv)))
2092  {
2093  basic addexp_tvb = variable_basic(addexp_tv);
2094  pips_debug(8, "adding main read effect \n");
2095  if (basic_derived_p(addexp_tvb) && !(type_enum_p(entity_type(basic_derived(addexp_tvb)))))
2096  {
2097  list l_tmp = generic_r_proper_effects_of_derived_reference(e, addexp_t);
2098  le = gen_nconc(le, l_tmp);
2099  }
2100  else
2101  le = CONS(EFFECT, e, le);
2102  }
2103  else
2104  {
2105  pips_debug(8, "main read effect is on array name : discarded\n");
2106  free_effect(e);
2107  }
2108  }
2109  else if (type_functional_p(addexp_t))
2110  {
2111  // FI: we must have bumped into a pointer to a
2112  // function. It may be dereferenced or not. See
2113  // Effects-New/function03
2114  print_expression(addexp);
2115  pips_internal_error("case of address expression not handled yet\n");
2116  }
2117  else
2118  {
2119  pips_internal_error("case not handled yet ");
2120  }
2121 
2122  free_type(addexp_t);
2124  // functions that can be pointed by effects_precondition_composition_op:
2125  // effects_composition_with_preconditions_nop
2126  // convex_regions_precondition_compose
2127  (*effects_precondition_composition_op)(le, context, false);
2128  }
2129  }
2130  }
2131  gen_free_list(l_pme);
2132 
2133  ifdebug(8) {
2134  pips_debug(8, "Effect for a call or a subscripted expression:\n");
2135  (*effects_prettyprint_func)(le);
2136  }
2137  break;
2138  }
2139  case is_syntax_cast:
2140  {
2141  pips_user_error("use of cast expressions as lvalues is deprecated\n");
2142  break;
2143  }
2145  {
2146  pips_user_error("sizeof cannot be a lhs\n");
2147  break;
2148  }
2149  case is_syntax_application:
2150  {
2151  /* I assume this not any more possible than a standard call */
2152  pips_user_error("use of indirect function call as lhs is not allowed\n");
2153  break;
2154  }
2155  default:
2156  pips_internal_error("lhs is not a reference and is not handled yet: syntax tag=%d\n",
2157  syntax_tag(s));
2158  break;
2159  } /* end switch */
2160 
2161  ifdebug(8) {
2162  pips_debug(8, "End with le=\n");
2163  (*effects_prettyprint_func)(le);
2164  fprintf(stderr, "\n");
2165  }
2166 
2167  return le;
2168 }
2169 
2170 
2171 /* TO VERIFY !!!!!!!!!!!!!*/
2172 /* UNUSED ? */
2173 /* It's unused */
2174 list
2176 {
2177  list inds = subscript_indices(s);
2178  list le = NIL;
2180 
2184  else
2185  {
2187  }
2188 
2189  pips_debug(3, "begin\n");
2190 
2191  if (! (*empty_context_test)(context))
2192  {
2194 
2195  if (! ENDP(inds))
2197 
2198  // functions that can be pointed by effects_precondition_composition_op:
2199  // effects_composition_with_preconditions_nop
2200  // convex_regions_precondition_compose
2201  (*effects_precondition_composition_op)(le, context, false);
2202  }
2203 
2204  pips_debug(3, "end\n");
2205  return(le);
2206 }
2207 
2209 {
2210  list le = NIL;
2211 
2212  pips_user_warning("Effect of indirect calls not implemented -> returning anywhere\n");
2213 
2215  return(le);
2216 }
2217 
2218 
2219 ␌
2220 /* Compute the proper effects of an expression
2221 
2222  @param[in] e is the expression we want the effects
2223 
2224  @return the corresponding list of effects.
2225 
2226  It calls store_expr_prw_effects() to keep track of expression effects
2227  if needed
2228 */
2229 list
2231 {
2232  list le = NIL;
2233  syntax s;
2234 
2235  pips_debug(3, "begin\n");
2236 
2237  s = expression_syntax(e);
2238 
2239  switch(syntax_tag(s))
2240  {
2241  case is_syntax_reference: {
2242  reference r = syntax_reference(s);
2244  break;
2245  }
2246  case is_syntax_range:
2248  break;
2249  case is_syntax_call:
2250  {
2251  entity op = call_function(syntax_call(s));
2252 
2253  /* first the case of an adressing operator : this could also be done
2254  * by calling generic_r_proper_effects_of_call, but then the expression
2255  * is lost and must be rebuild later to call
2256  * g_p_e_of_address_expression.
2257  */
2258  if (ENTITY_FIELD_P(op) ||
2259  ENTITY_POINT_TO_P(op) ||
2262  else {
2264  if(entity_variable_p(op)) {
2265  /* op is a pointer to a function. A memory read effect
2266  * must be added as this is in fact a read reference. See
2267  * Effects-new/function03.c */
2268  reference r = make_reference(op, NIL);
2270  // FI: by default, a preference will be used. This
2271  //artifical reference cannot be freed. I whish there would
2272  //be a cleaner way to do this:
2273  // generic_proper_effects_of_read_entity()?
2274  //free_reference(r);
2275  le = gen_nconc(ople, le);
2276  }
2277  }
2278  break;
2279  }
2280  case is_syntax_cast:
2281  {
2283  if(!get_bool_property("MEMORY_EFFECTS_ONLY")) {
2284  type ct = cast_type(syntax_cast(s));
2285 
2286  if(typedef_type_p(ct)) {
2288  effect tre = make_declaration_effect(te, false); // type
2289  le = gen_nconc(le, CONS(EFFECT, tre, NIL));
2290  }
2291  }
2292 
2293  break;
2294  }
2296  {
2299  {
2300  /* FI: If the type of the reference is a dependent type, this
2301  * may imply the reading of some expressions... See for
2302  * instance type_supporting_entities()? Is sizeof(a[i]) ok? */
2303  /* The type of the variable is read, not the variable itself.*/
2304  /* le = generic_proper_effects_of_expression(sizeofexpression_expression(se)); */
2305  ;
2306  }
2307  else {
2308  if(!get_bool_property("MEMORY_EFFECTS_ONLY")) {
2309  // FI->BC: this piece of code generates an effect on type
2310  // "size_t" when a FILE * variable is declared...
2311  // See libio.h and Rice/fgetc01
2312  // This might be useful to control loop distribution.
2313  type sot = sizeofexpression_type(se);
2314 
2315  if(typedef_type_p(sot)) {
2317  effect tre = make_declaration_effect(te, false); // type
2318  le = gen_nconc(le, CONS(EFFECT, tre, NIL));
2319  }
2320  }
2321  }
2322  break;
2323  }
2324  case is_syntax_subscript:
2325  {
2327  break;
2328  }
2329  case is_syntax_application:
2331  break;
2332  case is_syntax_va_arg:
2333  {
2334  /* there is first a read of the first argument, and
2335  * subsequent write effects on the va_list depths are simulated
2336  * by write effects on the va_list itself.
2337  */
2338  list al = syntax_va_arg(s);
2342  break;
2343  }
2344  default:
2345  pips_internal_error("unexpected tag %d", syntax_tag(s));
2346  break;
2347  }
2348 
2349  ifdebug(8)
2350  {
2351  pips_debug(8, "Proper effects of expression \"%s\":\n",
2353  (*effects_prettyprint_func)(le);
2354  }
2355 
2356  /* keep track of proper effects associated to sub-expressions if required.
2357  */
2359  {
2360  /* in IO lists, the effects are computed twice,
2361  * once as LHS, once as a REFERENCE...
2362  * so something may already be in. Let's skip it.
2363  * I should investigate further maybe. FC.
2364  */
2365  if (!bound_expr_prw_effects_p(e))
2367  }
2368 
2369  return le;
2370 }
2371 
2372 /* list generic_proper_effects_of_expressions(list exprs)
2373  * input : a list of expressions and the current context.
2374  * outpproper_ut : the correpsonding list of effects.
2375  * modifies : nothing.
2376  * comment :
2377  */
2378 list
2380 {
2381  list le = NIL;
2382 
2383  pips_debug(5, "begin\n");
2384 
2385  FOREACH(EXPRESSION, exp, exprs) {
2386  /* le may be long... */
2388  }
2389 
2390  pips_debug(5, "end\n");
2391  return(le);
2392 }
2393 
2394 bool check_sdfi_effects_p(entity func, list func_sdfi)
2395 {
2396  list ce = list_undefined;
2397  bool check_p = true;
2398  type ut = ultimate_type(entity_type(func));
2399 
2400  pips_assert("func is a function", type_functional_p(ut));
2401 
2402  /* Check the SDFI effects */
2403  for(ce = func_sdfi; !ENDP(ce); POP(ce)) {
2404  effect eff = EFFECT(CAR(ce));
2406  entity v = reference_variable(r);
2407 
2408  if(formal_parameter_p(v)) {
2409  storage s = entity_storage(v);
2410  formal fs = storage_formal(s);
2411  int rank = formal_offset(fs);
2412  entity called_function = formal_function(fs);
2413 
2414  if(called_function!=func) {
2415  fprintf(stderr, "Summary effect %p for function \"%s\" refers to "
2416  "formal parameter \"%s\" of function \"%s\"\n",
2417  eff, entity_name(func), entity_name(v), entity_name(called_function));
2418  check_p = false;
2419  }
2420 
2422  fprintf(stderr, "Formal parameter \"%s\" is ranked %d out of %zd!\n",
2424  check_p = false;
2425  }
2426  }
2427  }
2428  return check_p;
2429 }
2430 
2431 static list
2432 generic_proper_effects_of_external(entity func, list args)
2433 {
2434  list le = NIL;
2435  const char *func_name = module_local_name(func);
2436 
2437  pips_debug(4, "translating effects for %s\n", func_name);
2438 
2439  if (! entity_module_p(func))
2440  {
2441  pips_internal_error("%s: bad function", func_name);
2442  }
2443  else
2444  {
2445  list func_eff;
2447 
2448  /* Get the summary effects of "func". */
2449  func_eff = (*db_get_summary_rw_effects_func)(func_name);
2450 
2451  if(!check_sdfi_effects_p(func, func_eff))
2452  pips_internal_error("SDFI effects for \"%s\" are corrupted in the data base",
2453  entity_name(func));
2454 
2455  /* Translate them using context information. */
2457  le = generic_effects_backward_translation(func, args, func_eff, context);
2458 
2459  if(!check_sdfi_effects_p(func, func_eff))
2460  pips_internal_error("SDFI effects for \"%s\" have been corrupted by the translation",
2461  entity_name(func));
2462  }
2463  ifdebug(1) pips_assert("All effects in \"le\" are consistent",
2465  return le;
2466 }
2467 
2469 {
2470  list le = NIL;
2471  type arg_t = type_undefined;
2472  pips_debug(3, "begin for actual argument: %s\n", expression_to_string(arg));
2473 
2474  arg_t = expression_to_type(arg);
2475 
2476  /* If it's a sub-array, there are only intermediate effects */
2477  if(type_variable_p(arg_t) && !ENDP(variable_dimensions(type_variable(arg_t))))
2478  {
2479  list l_pme = NIL;
2480  /* I'm not sure it is OK for all type of arguments, in particular function calls */
2482 
2483  // when there are casts, actual types are hidden
2484  if (!ENDP(l_pme))
2485  {
2486  effect eff = EFFECT(CAR(l_pme));
2488 
2489 
2490  if (ENDP(reference_indices(ref))
2492  {
2493  le = gen_nconc(le, l_pme);
2494  }
2495  else
2496  gen_full_free_list(l_pme);
2497 
2498  }
2499  }
2500  else
2501  {
2503  }
2504 
2505 
2506  pips_debug_effects(3, "ouput effects: \n", le);
2507 
2508  return le;
2509 }
2510 
2511 
2512 /**
2513  * @return the list of effects found.
2514  * @param c, a call, which can be a call to a subroutine, but also
2515  * to an function, or to an intrinsic, or even an assignement.
2516  */
2517 list
2519 {
2520  list le = NIL;
2521  entity e = call_function(c);
2522  tag t = value_tag(entity_initial(e));
2523  const char* n = module_local_name(e);
2524  type uet = ultimate_type(entity_type(e));
2525  list pc = call_arguments(c);
2526 
2527  pips_debug(2, "begin for %s\n", entity_local_name(e));
2528 
2529  if(type_functional_p(uet)) {
2530  switch (t) {
2531  case is_value_code:
2532  pips_debug(5, "external function %s\n", n);
2533  le = generic_proper_effects_of_external(e, pc);
2534  break;
2535 
2536  case is_value_intrinsic:
2537  pips_debug(5, "intrinsic function %s\n", n);
2539  break;
2540 
2541  case is_value_symbolic:
2542  pips_debug(5, "symbolic\n");
2543  break;
2544 
2545  case is_value_constant:
2546  pips_debug(5, "constant\n");
2547  break;
2548 
2549  case is_value_unknown:
2550  if (get_bool_property("HPFC_FILTER_CALLEES"))
2551  /* hpfc specials are managed here... */
2552  le = NIL;
2553  else
2554  pips_internal_error("unknown function %s", entity_name(e));
2555  break;
2556 
2557  default:
2558  pips_internal_error("unknown tag %d", t);
2559  break;
2560  }
2561  }
2562  else if(type_variable_p(uet)) {
2563  /* We could be less optimistic even when no information about the function called is known.
2564  *
2565  * We could look up all functions with the same type and make the union of their effects.
2566  *
2567  * We could assume that all parameters are read.
2568  *
2569  * We could assume that all pointers are used to produce indirect write.
2570  */
2571  pips_user_warning("Effects of call thru functional pointers are ignored\n");
2572  }
2573  else if(type_statement_p(uet)) {
2574  le = NIL;
2575  }
2576  else {
2577  pips_internal_error("Unexpected case");
2578  }
2579 
2580  pips_debug(2, "end\n");
2581  return(le);
2582 }
2583 
2584 
2585 /**************************************************************** STATEMENTS */
2586 
2587 static void
2588 proper_effects_of_call(call c)
2589 {
2590  list l_proper = NIL;
2592  instruction inst = statement_instruction(current_stat);
2593 
2594  /* Is the call an instruction, or a sub-expression? */
2595  if (instruction_call_p(inst) && (instruction_call(inst) == c))
2596  {
2597  pips_debug(2, "Effects for statement %03zd:\n",
2598  statement_ordering(current_stat));
2599 
2600  l_proper = generic_r_proper_effects_of_call(c);
2601 
2602  l_proper = gen_nconc(l_proper, effects_dup(cumu_range_effects()));
2603 
2604  if (contract_p)
2605  l_proper = proper_effects_contract(l_proper);
2606 
2607  ifdebug(2) {
2608  pips_debug(2, "Proper effects for statement %03zd:\n",
2609  statement_ordering(current_stat));
2610  (*effects_prettyprint_func)(l_proper);
2611  pips_debug(2, "end\n");
2612  }
2613 
2614  /* This change is not compatible with previous Fortran
2615  * oriented phases such as hpfc. We can either forbid this
2616  * feature for all Fortran codes, or add a new property to
2617  * control this effect elimination, specific to C but with an
2618  * impact on CONTINUE, for instance, in Fortran. */
2619  if(!ENDP(l_proper)
2620  && effects_all_read_p(l_proper)
2621  && !statement_may_have_control_effects_p(current_stat)
2622  && !format_statement_p(current_stat)
2624  /* The current statement should be ignored as it does not
2625  * impact the store, nor the control, nor the
2626  * formatting. Examples in C; "0;" or "i;" or "(void)
2627  * i". Because PIPS is interprocedural, it could ignore some
2628  * more statements than gcc, but control effects are not
2629  * analyzed. Such statements can be created by program
2630  * transformations. */
2631  if (!declaration_statement_p(current_stat))
2632  pips_user_warning("Statement %d is ignored because it does not "
2633  "modify the store.\n", statement_number(current_stat));
2634  gen_full_free_list(l_proper);
2635  l_proper = NIL;
2636  }
2637 
2638  if (get_constant_paths_p())
2639  {
2640  list l_tmp = l_proper;
2641  l_proper = pointer_effects_to_constant_path_effects(l_proper);
2642  effects_free(l_tmp);
2643  }
2644 
2645  store_proper_rw_effects_list(current_stat, l_proper);
2646  }
2647 }
2648 
2649 /* just to handle one kind of instruction, expressions which are not calls */
2650 static void proper_effects_of_expression_instruction(instruction i)
2651 {
2652  list l_proper = NIL;
2654  //instruction inst = statement_instruction(current_stat);
2655 
2656  /* Is the call an instruction, or a sub-expression? */
2657  if (instruction_expression_p(i)) {
2659  syntax is = expression_syntax(ie);
2660  call c = call_undefined;
2661 
2662  switch (syntax_tag(is))
2663  {
2664  case is_syntax_cast :
2665  {
2667  syntax sc = expression_syntax(ce);
2668 
2669  if(syntax_call_p(sc)) {
2670  c = syntax_call(sc);
2671  l_proper = generic_r_proper_effects_of_call(c);
2672  }
2673  else if(syntax_reference_p(sc)) {
2674  /* FI: I guess you do not end up here if the cast appears in
2675  * the lhs, assuming this is till compatible with the
2676  * standard. */
2677  reference r = syntax_reference(sc);
2679  }
2680  else {
2681  pips_internal_error("Cast case not implemented");
2682  }
2683  break;
2684  }
2685  case is_syntax_call :
2686  {
2687  /* This may happen when a loop is unstructured by the controlizer */
2688  c = syntax_call(is);
2689  l_proper = generic_r_proper_effects_of_call(c);
2690  break;
2691  }
2692  case is_syntax_application :
2693  {
2694  /* This may happen when a structure field contains a pointer to
2695  * a function. We do not know which function is is... */
2696  //application a = syntax_application(is);
2697  //expression fe = application_function(a);
2698 
2699  /* we should try here to retrieve the name of the function through pointer analysis */
2700  /* NOT IMPLEMENTED -> returning anywhere read and write, as the function
2701  * can read and write any global variable as well as it's pointer arguments targets.
2702  */
2703 
2705 
2706  /* More effects should be added to take the call site into account */
2707  /* Same as for pointer-based call: use type, assume worst case,... */
2708  /* A new function is needed to retrieve all functions with a
2709  * given signature. Then the effects of all the candidates must
2710  * be unioned. */
2711  pips_user_warning("call through a function pointer in a structure -> anywhere effects\n");
2712 
2713  break;
2714  }
2715  case is_syntax_reference:
2716  {
2717  // someone typed "i;" in the code... or "a[i++];". It is
2718  //allowed and may happen in automatic code transformations such as
2719  //inlining.
2720  reference r = syntax_reference(is);
2722  break;
2723  }
2724  case is_syntax_range:
2726  case is_syntax_subscript:
2727  default :
2728  pips_internal_error("Instruction expression case %d not implemented",
2729  syntax_tag(is));
2730  break;
2731  }
2732 
2733  pips_debug(2, "Effects for expression instruction in statement%03zd:\n",
2734  statement_ordering(current_stat));
2735 
2736  l_proper = gen_nconc(l_proper, effects_dup(cumu_range_effects()));
2737 
2738  if (contract_p)
2739  l_proper = proper_effects_contract(l_proper);
2740  ifdebug(2) {
2741  pips_debug(2, "Proper effects for statement%03zd:\n",
2742  statement_ordering(current_stat));
2743  (*effects_prettyprint_func)(l_proper);
2744  pips_debug(2, "end\n");
2745  }
2746 
2747  if(!ENDP(l_proper) && effects_all_read_p(l_proper)) {
2748  /* The current statement should be ignored as it does not impact
2749  * the store. Examples in C; "0;" or "i;" or "(void) i". Because
2750  * PIPS is interprocedural, it may ignore some more statements
2751  * than gcc. Such statements can be created by program
2752  * transformations. */
2753  pips_user_warning("Statement %d is ignored because it does not "
2754  "modify the store.\n", statement_number(current_stat));
2755  gen_full_free_list(l_proper);
2756  l_proper = NIL;
2757  }
2758  if (get_constant_paths_p())
2759  {
2760  list l_tmp = l_proper;
2761  l_proper = pointer_effects_to_constant_path_effects(l_proper);
2762  effects_free(l_tmp);
2763  }
2764  store_proper_rw_effects_list(current_stat, l_proper);
2765  }
2766 }
2767 
2768 static void
2769 proper_effects_of_unstructured(unstructured u __attribute__((__unused__)))
2770 {
2772  store_proper_rw_effects_list(current_stat,NIL);
2773 }
2774 
2775 static bool
2776 loop_filter(loop l)
2777 {
2779  list l_eff = gen_nconc(l_proper, effects_dup(cumu_range_effects()));
2780  current_downward_cumulated_range_effects_push(make_effects(l_eff));
2781  return(true);
2782 }
2783 
2784 static void proper_effects_of_loop(loop l)
2785 {
2787  list l_proper = NIL;
2788 
2789  entity i = loop_index(l);
2790  range r = loop_range(l);
2791 
2792  list li = NIL, lb = NIL;
2793 
2794  pips_debug(2, "Effects for statement%03zd:\n",
2795  statement_ordering(current_stat));
2796 
2797  free_cumu_range_effects();
2798  current_downward_cumulated_range_effects_pop();
2799 
2800  /* proper_effects first */
2801 
2802  /* Effects of loop on loop index.
2803  * loop index is must-written but may-read because the loop might
2804  * execute no iterations.
2805  */
2806  /* FI, RK: the may-read effect on the index variable is masked by
2807  * the initial unconditional write on it (see standard page 11-7, 11.10.3);
2808  * if masking is not performed, the read may prevent privatization
2809  * somewhere else in the module (12 March 1993)
2810  */
2811  /* Parallel case
2812  *
2813  * as I need the same effects on a parallel loop to remove
2814  * unused private variable in rice/codegen.c, I put the
2815  * same code to compute parallel loop proper effects.
2816  * this may not be correct, but I should be the only one to use
2817  * such a feature. FC, 23/09/93
2818  */
2820 
2821  /* effects of loop bound expressions. */
2823 
2824  l_proper = gen_nconc(li, lb);
2825  l_proper = gen_nconc(l_proper, effects_dup(cumu_range_effects()));
2826 
2827  ifdebug(2)
2828  {
2829  pips_debug(2, "Proper effects for statement%03zd:\n",
2830  statement_ordering(current_stat));
2831  (*effects_prettyprint_func)(l_proper);
2832  pips_debug(2, "end\n");
2833  }
2834 
2835  ifdebug(1) pips_assert("l_proper is consistent",
2836  effect_list_consistent_p(l_proper));
2837 
2838  if (contract_p)
2839  l_proper = proper_effects_contract(l_proper);
2840 
2841  ifdebug(1) pips_assert("l_proper is consistent",
2842  effect_list_consistent_p(l_proper));
2843 
2845  {
2846  list l_tmp = l_proper;
2847  l_proper = pointer_effects_to_constant_path_effects(l_proper);
2848  effects_free(l_tmp);
2849  }
2850  store_proper_rw_effects_list(current_stat, l_proper);
2851 }
2852 
2853 static void proper_effects_of_forloop(forloop l)
2854 {
2856  list l_proper = NIL;
2857 
2858  // entity i = loop_index(l);
2859  // range r = loop_range(l);
2860 
2861  list li = NIL, lc = NIL, linc = NIL;
2862 
2863  pips_debug(2, "Effects for statement%03zd:\n",
2864  statement_ordering(current_stat));
2865 
2866  /* proper_effects first */
2867 
2869 
2870  /* effects of condition expression */
2872  /* effects of incrementation expression */
2873  /* we do not know if the incrementation expression will be evaluated -> may effects (see ticket 446) */
2875  effects_to_may_effects(linc);
2876 
2877  l_proper = gen_nconc(li, lc);
2878  l_proper = gen_nconc(l_proper, linc);
2879 
2880  // cumulated range effects are added to internal statements of
2881  // a la fortran do loops to simulate control effects, but it's unclear
2882  // whether it should be the same with C for loops which cannot be
2883  // represented as do loops.
2884  // free_cumu_range_effects();
2885  //current_downward_cumulated_range_effects_pop();
2886  //l_cumu_range = cumu_range_effects();
2887  //l_proper = gen_nconc(l_proper, effects_dup(l_cumu_range));
2888 
2889  ifdebug(2)
2890  {
2891  pips_debug(2, "Proper effects for statement%03zd:\n",
2892  statement_ordering(current_stat));
2893  (*effects_prettyprint_func)(l_proper);
2894  pips_debug(2, "end\n");
2895  }
2896 
2897  if (contract_p)
2898  l_proper = proper_effects_contract(l_proper);
2899 
2900  if (get_constant_paths_p())
2901  {
2902  list l_tmp = l_proper;
2903  l_proper = pointer_effects_to_constant_path_effects(l_proper);
2904  effects_free(l_tmp);
2905  }
2906  store_proper_rw_effects_list(current_stat, l_proper);
2907 }
2908 
2909 static void proper_effects_of_while(whileloop w)
2910 {
2912  list /* of effect */ l_proper =
2914  if (get_constant_paths_p())
2915  {
2916  list l_tmp = l_proper;
2917  l_proper = pointer_effects_to_constant_path_effects(l_proper);
2918  effects_free(l_tmp);
2919  }
2920 
2921  store_proper_rw_effects_list(current_stat, l_proper);
2922 }
2923 
2924 static void proper_effects_of_test(test t)
2925 {
2926  list l_proper=NIL;
2928 
2929  pips_debug(2, "Effects for statement%03zd:\n",
2930  statement_ordering(current_stat));
2931 
2932  /* effects of the condition */
2934  l_proper = gen_nconc(l_proper, effects_dup(cumu_range_effects()));
2935 
2936  ifdebug(2)
2937  {
2938  pips_debug(2, "Proper effects for statement%03zd:\n",
2939  statement_ordering(current_stat));
2940  (*effects_prettyprint_func)(l_proper);
2941  pips_debug(2, "end\n");
2942  }
2943 
2944  if (contract_p)
2945  l_proper = proper_effects_contract(l_proper);
2946  if (get_constant_paths_p())
2947  {
2948  list l_tmp = l_proper;
2949  l_proper = pointer_effects_to_constant_path_effects(l_proper);
2950  effects_free(l_tmp);
2951  }
2952 
2953  store_proper_rw_effects_list(current_stat, l_proper);
2954 }
2955 
2956 static void proper_effects_of_sequence(sequence block __attribute__((__unused__)))
2957 {
2959  store_proper_rw_effects_list(current_stat, NIL);
2960 }
2961 
2962 static bool stmt_filter(statement s)
2963 {
2964  pips_debug(1, "Entering statement with ordering: %03zd and number: %03zd\n",
2969  return(true);
2970 }
2971 
2972 /* Looks for effect hidden in dependent types.
2973  *
2974  * Type have to be traversed recursively, looking for dimensions at
2975  * any level.
2976  *
2977  * Might be better implemented with a gen_multirecurse(), at least if
2978  * it would traverse entities...
2979  *
2980  * FI: This piece of code is certainly not well validated! I have seen
2981  * many example of direct array dimensions and one example with a
2982  * pointer to a dependent type array.
2983  */
2985 {
2986  set ts = set_make(set_pointer);
2987  list t_eff_l = recursive_type_to_effects(t, ts);
2988  set_free(ts);
2989  return t_eff_l;
2990 }
2991 
2993 {
2994  list t_eff = NIL;
2995 
2996  if(!set_belong_p(ts, (void *) t)) {
2997  ts = set_add_element(ts, ts, (void *) t);
2998  if(type_variable_p(t)) {
2999  variable v = type_variable(t);
3000  list dl = variable_dimensions(v);
3001  FOREACH(DIMENSION, d, dl) {
3004  l_eff_l = gen_nconc(l_eff_l, l_eff_u);
3005  t_eff = gen_nconc(t_eff, l_eff_l);
3006  }
3007  basic b = variable_basic(v);
3008  if(basic_pointer_p(b)) {
3009  // You may have a pointer to an array as in
3010  // EffectsWithPointsTo/PointersArithmetic-future.sub/pointer_sub01.diff
3011  type pt = basic_pointer(b);
3012  list p_eff_l = recursive_type_to_effects(pt, ts);
3013  t_eff = gen_nconc(t_eff, p_eff_l);
3014  }
3015  else if(basic_derived_p(b)) {
3016  entity de = basic_derived(b);
3017  type dt = entity_type(de);
3018  list dt_eff = recursive_type_to_effects(dt, ts);
3019  t_eff = gen_nconc(t_eff, dt_eff);
3020  }
3021  else if(basic_typedef_p(b)) {
3022  entity td = basic_typedef(b);
3023  list td_eff = recursive_type_to_effects(entity_type(td), ts);
3024  t_eff = gen_nconc(t_eff, td_eff);
3025  }
3026  }
3027  else if(type_functional_p(t)) {
3029  type rt = functional_result(f);
3030  list r_eff = recursive_type_to_effects(rt, ts);
3032  list pl_eff = NIL;
3033  FOREACH(PARAMETER, p, pl) {
3034  type pt = parameter_type(p);
3035  list p_eff = recursive_type_to_effects(pt, ts);
3036  pl_eff = gen_nconc(pl_eff, p_eff);
3037  }
3038  pl_eff = gen_nconc(r_eff, pl_eff);
3039  t_eff = gen_nconc(t_eff, pl_eff);
3040  }
3041  else if(type_struct_p(t) || type_union_p(t)) {
3042  list fl = type_struct_p(t)? type_struct(t) : type_union(t);
3043  list s_eff = NIL;
3044  FOREACH(ENTITY, f, fl) {
3046  s_eff = gen_nconc(s_eff, f_eff);
3047  }
3048  t_eff = gen_nconc(t_eff, s_eff);
3049  }
3050  // FI: I do not remember if something should be done for enums
3051  // I guess they are only initialized with constant expressions
3052  }
3053  return t_eff;
3054 }
3055 
3056 /**
3057  @param entity is a
3058  @param
3059  @return : a list of effects corresponding to the effects of the rhs if there
3060  is an initialization in the declaration., plus the effects of the lhs
3061 */
3062 static list generic_proper_effects_of_declaration(entity decl)
3063 {
3064  list l_eff = NIL;
3065  pips_debug(1, "declaration of entity %s \n", entity_local_name(decl));
3066 
3067  if(type_variable_p(entity_type(decl)))
3068  {
3069  value v_init = entity_initial(decl);
3070 
3071  pips_debug(1, "begin\n");
3072  /* generate effects due to the initialisation */
3073  if (value_expression_p(v_init))
3074  {
3075  expression exp_init = value_expression(v_init);
3076  l_eff = generic_proper_effects_of_expression(exp_init);
3077  }
3078 
3079  /* Check the dimensions for dependent types - problem in Fortran
3080  * I guess... */
3081  list t_eff = type_to_effects(entity_type(decl));
3082  l_eff = gen_nconc(l_eff, t_eff);
3083 
3084  /* if there is an initial value, and if the variable is not a static one,
3085  * then there is a write on the entity (well on the reference constituted
3086  * by the entity name with no indices !).
3087  * There may be a memory leak here because we do not want a preference in
3088  * the effect. However, I do not have a good solution for the time being
3089  * because in declarations, the left hand side is not a reference. BC.
3090  * I should may be call generic_proper_effects_of lhs instead, but the case is
3091  * slightly different for arrays. Or directly (*reference_to_effect_func) in case of a scalar ?
3092  */
3093  /* To avoid problems with loop distribution, we need a (write)
3094  * effect whether there is an initialization or not. This is
3095  * consistent with transformers and preconditions, but not with
3096  * the used before set analysis. In the short term, you can
3097  * comment out the second part of the condition to solve the
3098  * loop distribution issue. */
3099  if (!variable_static_p(decl) && !value_unknown_p(v_init))
3100  {
3101  type decl_t = entity_basic_concrete_type(decl);
3102  list l_tmp = NIL;
3103 
3104  if (!ENDP(variable_dimensions(type_variable(decl_t))))
3105  {
3106  // functions that can be pointed by reference_to_effect_func:
3107  // reference_to_simple_effect
3108  // reference_to_convex_region
3109  // reference_to_reference_effect
3110  effect decl_eff = (*reference_to_effect_func)(make_reference(decl,NIL), make_action_write_memory(), true);
3112  }
3113  else
3114  {
3115  // make sure the make_reference does not create a memory leak
3116  /* The other problem is that it generates a "is referenced" effect*/
3118  NIL),
3119  true);
3120  }
3121  l_eff= gen_nconc(l_eff, l_tmp);
3122  }
3123  if (contract_p)
3124  l_eff = proper_effects_contract(l_eff);
3125  pips_debug_effects(1, "ending with:", l_eff);
3126  }
3127  return l_eff;
3128 }
3129 
3131 {
3132  effect eff = effect_undefined;
3133  /* FI: generate a declaration or a type write */
3134 
3135  reference r = make_reference(e, NIL);
3138  /* FI: I'm not sure this is a very generic decision; I do not
3139  foresee how predicates could refine dependences. But we already
3140  missed that for scalar variables:-( */
3142  cell c = make_cell_reference(r);
3144 
3145  if(typedef_entity_p(e)) {
3146  /* FI: more work here; you have to check that other typedefed
3147  types or variables are not used in this typedef. Quite a
3148  recursive search... */
3150  }
3151  else
3153 
3154  if(written_p)
3155  a = make_action_write(ak);
3156  else
3157  a = make_action_read(ak);
3158 
3159  eff = make_effect(c, a, ap, d);
3160 
3161  return eff;
3162 }
3163 
3164 static void proper_effects_of_statement(statement s)
3165 {
3166  /* Handling of declarations attached to a declaration statement */
3167  pips_debug(1, "statement%03zd :\n", statement_number(s));
3169  (declaration_statement_p(s) /*|| block_statement_p(s)*/ ))
3170  {
3171  list l_eff = NIL;
3172  list l_decls = statement_declarations(s);
3173 
3174  pips_debug(1, "declaration statement \n");
3175 
3176  FOREACH(ENTITY, e, l_decls)
3177  {
3178  if(!get_bool_property("MEMORY_EFFECTS_ONLY")) {
3179  effect de = make_declaration_effect(e, true);
3180  type vt = entity_type(e);
3181 
3182  l_eff = gen_nconc(l_eff, CONS(EFFECT, de, NIL));
3183  // Should be put first or last?
3184  //l_eff = CONS(EFFECT, re, l_eff);
3185 
3186  if(typedef_type_p(vt)) {
3188  effect tre = make_declaration_effect(te, false); // type
3189  // reference effect
3190  l_eff = gen_nconc(l_eff, CONS(EFFECT, tre, NIL));
3191  //l_eff = CONS(EFFECT, tre, l_eff);
3192  }
3193  }
3194  l_eff = gen_nconc(l_eff, generic_proper_effects_of_declaration(e));
3195  }
3196  if (get_constant_paths_p())
3197  {
3198  list l_tmp = l_eff;
3200  effects_free(l_tmp);
3201  }
3202 
3204  {
3205  l_eff = gen_nconc(l_eff,
3208  }
3209  else
3211  }
3212 
3213  if (!bound_proper_rw_effects_p(s))
3214  {
3215  pips_debug(2, "Warning, proper effects undefined, set to NIL\n");
3217  }
3221 
3222  pips_debug(1, "End statement%03zd :\n", statement_number(s));
3223 }
3224 
3226 {
3228  make_statement_global_stack(); // for improved warnings
3230  make_current_downward_cumulated_range_effects_stack();
3231  pips_debug(1,"begin\n");
3232 
3234  (module_stat,
3235  statement_domain, stmt_filter, proper_effects_of_statement,
3236  sequence_domain, gen_true, proper_effects_of_sequence,
3237  test_domain, gen_true, proper_effects_of_test,
3238  /* Reached only through syntax (see expression rule) */
3239  call_domain, gen_true, proper_effects_of_call,
3240  loop_domain, loop_filter, proper_effects_of_loop,
3241  whileloop_domain, gen_true, proper_effects_of_while,
3242  forloop_domain, gen_true, proper_effects_of_forloop,
3243  unstructured_domain, gen_true, proper_effects_of_unstructured,
3244  /* Just to retrieve effects of instructions with kind
3245  * expression since they are ruled out by the next clause */
3246  instruction_domain, gen_true, proper_effects_of_expression_instruction,
3247  expression_domain, gen_false, gen_null, /* NOT THESE CALLS */
3248  NULL);
3249 
3250  pips_debug(1,"end\n");
3252  free_statement_global_stack(); // for improved warnings
3254  free_current_downward_cumulated_range_effects_stack();
3255 }
3256 
3257 bool proper_effects_engine(const char *module_name)
3258 {
3259  /* Get the code of the module. */
3261  db_get_memory_resource(DBR_CODE, module_name, true));
3262  // The stacks are not stacked...
3263  //make_statement_global_stack();
3264 
3266 
3267  // functions that can be pointed by effects_computation_init_func:
3268  // effects_computation_no_init
3269  // init_convex_in_out_regions
3270  // init_convex_rw_regions
3271  (*effects_computation_init_func)(module_name);
3272 
3273  /* Compute the effects or references of the module. */
3275 
3278  db_get_memory_resource(DBR_POINTS_TO, module_name, true) );
3281 
3282  debug_on("PROPER_EFFECTS_DEBUG_LEVEL");
3283  pips_debug(1, "begin\n");
3284 
3286 
3287  pips_debug(1, "end\n");
3288  debug_off();
3289 
3290  (*db_put_proper_rw_effects_func)(module_name, get_proper_rw_effects());
3291 
3293  reset_pt_to_list();
3295  reset_pv();
3296 
3300  //free_statement_global_stack();
3301 
3302  // functions that can be pointed by effects_computation_reset_func:
3303  // effects_computation_no_reset
3304  // reset_convex_in_out_regions
3305  // reset_convex_rw_regions
3306  (*effects_computation_reset_func)(module_name);
3307 
3308  return(true);
3309 }
3310 
3311 
3312 
3313 
3314 /* compute proper effects for both expressions and statements
3315  WARNING: the functions are set as a side effect.
3316  */
3317 void
3319  const char* module_name,
3321 {
3322  // functions that can be pointed by effects_computation_init_func:
3323  // effects_computation_no_init
3324  // init_convex_in_out_regions
3325  // init_convex_rw_regions
3326  (*effects_computation_init_func)(module_name);
3327 
3330 
3331  debug_on("PROPER_EFFECTS_DEBUG_LEVEL");
3332  pips_debug(1, "begin\n");
3333 
3334  //make_statement_global_stack(); // for potential calls to semantics
3335 
3337 
3338  //free_statement_global_stack(); // for potential calls to semantics
3339 
3340  pips_debug(1, "end\n");
3341  debug_off();
3342 
3343  // functions that can be pointed by effects_computation_reset_func:
3344  // effects_computation_no_reset
3345  // reset_convex_in_out_regions
3346  // reset_convex_rw_regions
3347  (*effects_computation_reset_func)(module_name);
3348 }
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
action make_action_read(action_kind _field_)
Definition: effects.c:123
action_kind make_action_kind_environment(void)
Definition: effects.c:68
cell make_cell_reference(reference _field_)
Definition: effects.c:293
void free_effect(effect p)
Definition: effects.c:451
action_kind make_action_kind_type_declaration(void)
Definition: effects.c:71
effects make_effects(list a)
Definition: effects.c:568
void free_cell(cell p)
Definition: effects.c:249
approximation make_approximation_exact(void)
Definition: effects.c:185
action make_action_write(action_kind _field_)
Definition: effects.c:126
void free_action(action p)
Definition: effects.c:80
effect make_effect(cell a1, action a2, approximation a3, descriptor a4)
Definition: effects.c:484
void free_effects(effects p)
Definition: effects.c:535
descriptor make_descriptor_none(void)
Definition: effects.c:442
void free_descriptor(descriptor p)
Definition: effects.c:392
cast make_cast(type a1, expression a2)
Definition: ri.c:311
void free_reference(reference p)
Definition: ri.c:2050
expression copy_expression(expression p)
EXPRESSION.
Definition: ri.c:850
reference make_reference(entity a1, list a2)
Definition: ri.c:2083
void free_expression(expression p)
Definition: ri.c:853
reference copy_reference(reference p)
REFERENCE.
Definition: ri.c:2047
syntax make_syntax_cast(cast _field_)
Definition: ri.c:2503
void free_type(type p)
Definition: ri.c:2658
void free_basic(basic p)
Definition: ri.c:107
static reference ref
Current stmt (an integer)
Definition: adg_read_paf.c:163
static bool stmt_filter(statement s)
modifies global var current_caller_stmt
Definition: alias_pairs.c:222
void const char const char const int
static bool loop_filter(loop l)
static bool written_p(entity e)
#define pips_debug_effects(level, message, l_eff)
@ with_points_to
@ with_pointer_values
#define pips_debug_effect(level, message, eff)
for debug
void free_effects_private_current_context_stack(void)
list make_anywhere_read_write_memory_effects(void)
list generic_proper_effects_of_complex_address_expression(expression, list *, int)
bool effects_private_current_context_empty_p(void)
void error_reset_effects_private_current_stmt_stack(void)
void proper_effects_error_handler(void)
bool effect_pointer_type_p(effect)
list generic_proper_effects_of_complex_address_dereferencing_cast_op(list, list *, bool)
void effects_to_may_effects(list)
list old_generic_proper_effects_of_complex_address_conditional_op(list, list *, bool)
list generic_proper_effects_of_address_expression(expression, int)
effect make_anywhere_effect(action)
transformer effects_private_current_context_head(void)
bool(* empty_context_test)(transformer)
list generic_proper_effects_of_complex_address_update_op(list, list *, bool)
void make_effects_private_current_context_stack(void)
void effect_add_dereferencing_dimension(effect)
transformer(* load_context_func)(statement)
list generic_proper_effects_of_read_reference(reference)
void make_effects_private_current_stmt_stack(void)
utils.c
list generic_proper_effects_of_complex_address_cast_dereferencing_op(cast, expression, list *, bool)
list generic_proper_effects_of_range(range)
list generic_proper_effects_of_reference(reference, bool)
list generic_r_proper_effects_of_call(call)
list generic_proper_effects_of_complex_address_assign_dereferencing_op(expression, expression, list *, bool)
list type_to_effects(type)
pointer_info_val get_pointer_info_kind(void)
list proper_effects_contract(list)
void store_proper_rw_effects_list(statement, list)
void expression_proper_effects_engine(const char *, statement)
void proper_effects_of_module_statement(statement)
void update_proper_rw_effects_list(statement, list)
list generic_proper_effects_of_complex_memory_access_expression(expression, list *, list *, int)
list generic_proper_effects_of_written_reference(reference)
list load_proper_rw_effects_list(statement)
bool bound_proper_rw_effects_p(statement)
list generic_proper_effects_of_any_lhs(expression)
effect(* reference_to_effect_func)(reference, action, bool)
statement effects_private_current_stmt_pop(void)
bool expr_prw_effects_undefined_p(void)
bool region_weakly_consistent_p(effect)
effect make_declaration_effect(entity, bool)
bool regions_weakly_consistent_p(list)
void error_reset_effects_private_current_context_stack(void)
bool bound_expr_prw_effects_p(expression)
void reset_proper_rw_effects(void)
void free_effects_private_current_stmt_stack(void)
void effect_free(effect)
list recursive_type_to_effects(type, set)
list generic_proper_effects_of_complex_address_address_of_dereferencing_op(expression, list *, bool)
void init_proper_rw_effects(void)
list generic_proper_effects_of_derived_reference(reference, bool)
void effects_free(list)
list generic_effects_backward_translation(entity, list, list, transformer)
bool effects_private_current_context_stack_initialized_p(void)
bool check_sdfi_effects_p(entity, list)
statement effects_private_current_stmt_head(void)
list generic_proper_effects_of_complex_address_assign_op(list, list *, bool)
list generic_proper_effects_of_c_function_call_argument(expression)
list generic_proper_effects_of_subscript(subscript)
void effects_private_current_stmt_push(statement)
list effects_dup(list)
void effect_to_may_effect(effect)
list generic_intermediary_proper_effects_of_reference(reference)
list generic_p_proper_effect_of_reference(reference, effect *, bool, bool)
void set_contracted_proper_effects(bool)
end of effects-generic-local.h
bool get_constant_paths_p(void)
effect make_typed_anywhere_effect(action, type)
list new_generic_proper_effects_of_complex_address_conditional_op(list, list *, bool)
list generic_proper_effects_of_complex_address_conditional_dereferencing_op(expression, expression, expression, list *, bool)
type simple_effect_reference_type(reference)
list generic_proper_effects_of_expression(expression)
void effect_to_read_effect(effect)
list generic_proper_effects_of_application(application)
effect(* effect_dup_func)(effect eff)
transformer effects_private_current_context_pop(void)
void effects_private_current_context_push(transformer)
list pointer_effects_to_constant_path_effects(list)
list effect_to_list(effect)
bool proper_effects_engine(const char *)
void effect_add_field_dimension(effect, entity)
void init_expr_prw_effects(void)
list generic_proper_effects_of_intrinsic(entity, list)
intrinsics.c
list generic_effect_generate_all_accessible_paths_effects(effect, type, tag)
void store_expr_prw_effects(expression, effects)
statement_effects get_proper_rw_effects(void)
list generic_proper_effects_of_expressions(list)
#define effect_any_reference(e)
FI: cannot be used as a left hand side.
action make_action_write_memory(void)
To ease the extension of action with action_kind.
Definition: effects.c:1011
bool effect_list_consistent_p(list)
Debugging.
Definition: effects.c:1340
void set_pt_to_list(statement_points_to)
bool effects_all_read_p(list)
Check that all effects in el are read effects.
Definition: effects.c:1141
bool anywhere_effect_p(effect)
Is it an anywhere effect? ANYMMODULE:ANYWHERE
Definition: effects.c:346
void reset_pt_to_list(void)
action make_action_read_memory(void)
Definition: effects.c:1017
bool types_compatible_for_effects_interprocedural_translation_p(type, type)
tests if the actual argument type and the formal argument type are compatible with the current state ...
Definition: type.c:932
#define effect_undefined_p(x)
Definition: effects.h:615
#define action_undefined
Definition: effects.h:277
#define action_kind_undefined
Definition: effects.h:222
#define cell_undefined
Definition: effects.h:430
#define effect_action(x)
Definition: effects.h:642
#define effect_undefined
Definition: effects.h:614
#define effect_descriptor(x)
Definition: effects.h:646
#define effects_effects(x)
Definition: effects.h:710
#define descriptor_undefined
Definition: effects.h:559
@ is_action_write
Definition: effects.h:293
#define effect_action_(x)
Definition: effects.h:641
#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
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
if(!(yy_init))
Definition: genread_lex.c:1029
bool success
Definition: gpips-local.h:59
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
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
void gen_multi_recurse(void *o,...)
Multi recursion visitor function.
Definition: genClib.c:3428
bool gen_false(__attribute__((unused)) gen_chunk *unused)
Return false and ignore the argument.
Definition: genClib.c:2796
void gen_null(__attribute__((unused)) void *unused)
Ignore the argument.
Definition: genClib.c:2752
bool gen_true(__attribute__((unused)) gen_chunk *unused)
Return true and ignore the argument.
Definition: genClib.c:2780
#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 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
#define CDR(pcons)
Get the list less its first element.
Definition: newgen_list.h:111
#define list_undefined
Undefined list definition :-)
Definition: newgen_list.h:69
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
bool format_statement_p(statement)
Test if a statement is a Fortran FORMAT.
Definition: statement.c:273
bool statement_may_have_control_effects_p(statement)
Definition: statement.c:3978
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 pips_user_error
Definition: misc-local.h:147
static entity rank
#define DEFINE_LOCAL_STACK(name, type)
void set_free(set)
Definition: set.c:332
bool set_belong_p(const set, const void *)
Definition: set.c:194
@ set_pointer
Definition: newgen_set.h:44
set set_make(set_type)
Create an empty set of any type but hash_private.
Definition: set.c:102
set set_add_element(set, const set, const void *)
Definition: set.c:152
int tag
TAG.
Definition: newgen_types.h:92
#define true
Definition: newgen_types.h:81
int f(int off1, int off2, int n, float r[n], float a[n], float b[n])
Definition: offsets.c:15
void set_pv(statement_cell_relations)
statement_cell_relations db_get_simple_pv(const char *)
I don't know how to deal with these mappings if we have to analyse several modules at the same time w...
void reset_pv(void)
void print_expressions(list le)
Definition: expression.c:98
string reference_to_string(reference r)
Definition: expression.c:87
void print_expression(expression e)
no file descriptor is passed to make is easier to use in a debugging stage.
Definition: expression.c:58
string expression_to_string(expression e)
Definition: expression.c:77
list Words_Syntax(syntax obj)
Definition: misc.c:2664
string string_of_type(const type)
Definition: type.c:56
void print_type(type)
For debugging.
Definition: type.c:111
string basic_to_string(basic)
Definition: type.c:87
static hash_table pl
properties are stored in this hash table (string -> property) for fast accesses.
Definition: properties.c:783
#define ENTITY_ASSIGN_P(e)
#define ENTITY_DEREFERENCING_P(e)
#define ENTITY_POINT_TO_P(e)
#define ENTITY_PRE_DECREMENT_P(e)
#define ENTITY_POST_DECREMENT_P(e)
#define ENTITY_POST_INCREMENT_P(e)
#define ENTITY_CONDITIONAL_P(e)
#define ENTITY_PRE_INCREMENT_P(e)
#define ENTITY_PLUS_C_P(e)
#define entity_variable_p(e)
An entity_variable_p(e) may hide a typedef and hence a functional type.
#define ENTITY_FIELD_P(e)
C data structure and pointer management.
#define ENTITY_MINUS_C_P(e)
#define ENTITY_ADDRESS_OF_P(e)
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
bool c_module_p(entity m)
Test if a module "m" is written in C.
Definition: entity.c:2777
entity module_name_to_entity(const char *mn)
This is an alias for local_name_to_top_level_entity.
Definition: entity.c:1479
bool typedef_entity_p(entity e)
Definition: entity.c:1902
bool entity_field_p(entity e)
e is the field of a structure
Definition: entity.c:857
const char * module_local_name(entity e)
Returns the module local user name.
Definition: entity.c:582
bool fortran_module_p(entity m)
Test if a module is in Fortran.
Definition: entity.c:2799
bool entity_module_p(entity e)
Definition: entity.c:683
expression make_unbounded_expression()
Definition: expression.c:4339
expression MakeBinaryCall(entity f, expression eg, expression ed)
Creates a call expression to a function with 2 arguments.
Definition: expression.c:354
call expression_call(expression e)
Definition: expression.c:445
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
expression expression_to_dereferencing_expression(expression e)
Reuse expression e to build expression *(e) without cheking the legality of the construct.
Definition: expression.c:4051
bool expression_reference_p(expression e)
Test if an expression is a reference.
Definition: expression.c:528
reference expression_reference(expression e)
Short cut, meaningful only if expression_reference_p(e) holds.
Definition: expression.c:1832
expression syntax_to_expression(syntax s)
generates an expression from a syntax
Definition: expression.c:3581
basic basic_of_expression(expression)
basic basic_of_expression(expression exp): Makes a basic of the same basic as the expression "exp".
Definition: type.c:1383
type ultimate_type(type)
Definition: type.c:3466
bool array_type_p(type)
Definition: type.c:2942
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
statement pop_statement_global_stack(void)
Definition: static.c:352
bool place_holder_variable_p(entity)
Definition: variable.c:2069
list type_fields(type)
Definition: type.c:3073
type type_to_pointed_type(type)
returns t if t is not a pointer type, and the pointed type if t is a pointer type.
Definition: type.c:5265
type entity_basic_concrete_type(entity)
retrieves or computes and then returns the basic concrete type of an entity
Definition: type.c:3677
bool pointer_type_p(type)
Check for scalar pointers.
Definition: type.c:2993
bool formal_parameter_p(entity)
Definition: variable.c:1489
void push_statement_on_statement_global_stack(statement)
Definition: static.c:333
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
type reference_to_type(reference)
Definition: type.c:2354
void free_statement_global_stack(void)
Definition: static.c:358
bool typedef_type_p(type)
Returns true if t is a typedefED type.
Definition: type.c:3189
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
void make_statement_global_stack(void)
Definition: static.c:318
string type_to_string(const type)
type.c
Definition: type.c:51
#define type_functional_p(x)
Definition: ri.h:2950
#define forloop_domain
newgen_extensions_domain_defined
Definition: ri.h:178
#define formal_offset(x)
Definition: ri.h:1408
#define value_tag(x)
Definition: ri.h:3064
#define type_enum_p(x)
Definition: ri.h:2968
@ is_basic_derived
Definition: ri.h:579
@ is_basic_typedef
Definition: ri.h:580
#define type_struct(x)
Definition: ri.h:2964
#define test_domain
newgen_entity_domain_defined
Definition: ri.h:418
#define basic_pointer(x)
Definition: ri.h:637
#define syntax_reference_p(x)
Definition: ri.h:2728
#define expression_domain
newgen_execution_domain_defined
Definition: ri.h:154
#define type_struct_p(x)
Definition: ri.h:2962
#define transformer_undefined
Definition: ri.h:2847
#define functional_result(x)
Definition: ri.h:1444
#define transformer_undefined_p(x)
Definition: ri.h:2848
#define unstructured_domain
newgen_type_domain_defined
Definition: ri.h:442
#define parameter_type(x)
Definition: ri.h:1819
#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 reference_undefined
Definition: ri.h:2302
#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 loop_domain
newgen_language_domain_defined
Definition: ri.h:218
#define basic_derived(x)
Definition: ri.h:640
#define basic_typedef_p(x)
Definition: ri.h:641
#define SIZEOFEXPRESSION(x)
SIZEOFEXPRESSION.
Definition: ri.h:2364
#define sizeofexpression_type(x)
Definition: ri.h:2406
#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 syntax_call_p(x)
Definition: ri.h:2734
#define statement_ordering(x)
Definition: ri.h:2454
#define sizeofexpression_expression(x)
Definition: ri.h:2409
#define syntax_cast(x)
Definition: ri.h:2739
#define type_functional(x)
Definition: ri.h:2952
#define value_unknown_p(x)
Definition: ri.h:3077
#define syntax_application(x)
Definition: ri.h:2748
#define dimension_lower(x)
Definition: ri.h:980
#define syntax_va_arg(x)
Definition: ri.h:2751
#define basic_tag(x)
Definition: ri.h:613
#define type_variable(x)
Definition: ri.h:2949
#define basic_pointer_p(x)
Definition: ri.h:635
#define basic_derived_p(x)
Definition: ri.h:638
#define syntax_va_arg_p(x)
Definition: ri.h:2749
#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
#define type_union_p(x)
Definition: ri.h:2965
@ is_value_intrinsic
Definition: ri.h:3034
@ is_value_unknown
Definition: ri.h:3035
@ is_value_constant
Definition: ri.h:3033
@ is_value_code
Definition: ri.h:3031
@ is_value_symbolic
Definition: ri.h:3032
#define syntax_range(x)
Definition: ri.h:2733
@ 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 instruction_domain
newgen_functional_domain_defined
Definition: ri.h:202
#define call_domain
newgen_callees_domain_defined
Definition: ri.h:58
#define storage_formal(x)
Definition: ri.h:2524
#define EXPRESSION(x)
EXPRESSION.
Definition: ri.h:1217
#define cast_expression(x)
Definition: ri.h:747
#define basic_typedef(x)
Definition: ri.h:643
#define subscript_indices(x)
Definition: ri.h:2563
#define constant_int_p(x)
Definition: ri.h:848
#define expression_undefined
Definition: ri.h:1223
#define entity_name(x)
Definition: ri.h:2790
#define functional_parameters(x)
Definition: ri.h:1442
#define PARAMETER(x)
PARAMETER.
Definition: ri.h:1788
#define formal_function(x)
Definition: ri.h:1406
#define dimension_upper(x)
Definition: ri.h:982
#define reference_indices(x)
Definition: ri.h:2328
#define syntax_sizeofexpression(x)
Definition: ri.h:2742
#define sizeofexpression_expression_p(x)
Definition: ri.h:2407
#define syntax_call(x)
Definition: ri.h:2736
#define cast_type(x)
Definition: ri.h:745
#define instruction_call_p(x)
Definition: ri.h:1527
#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 subscript_array(x)
Definition: ri.h:2561
#define range_lower(x)
Definition: ri.h:2288
#define variable_dimensions(x)
Definition: ri.h:3122
#define whileloop_domain
newgen_variable_domain_defined
Definition: ri.h:466
#define statement_declarations(x)
Definition: ri.h:2460
#define statement_instruction(x)
Definition: ri.h:2458
#define type_undefined
Definition: ri.h:2883
#define instruction_call(x)
Definition: ri.h:1529
#define syntax_subscript(x)
Definition: ri.h:2745
#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 syntax_cast_p(x)
Definition: ri.h:2737
#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 call_undefined
Definition: ri.h:685
#define statement_number(x)
Definition: ri.h:2452
#define value_expression_p(x)
Definition: ri.h:3080
#define expression_syntax(x)
Definition: ri.h:1247
#define sequence_domain
newgen_reference_domain_defined
Definition: ri.h:346
#define type_variable_p(x)
Definition: ri.h:2947
#define value_expression(x)
Definition: ri.h:3082
#define loop_index(x)
Definition: ri.h:1640
#define type_union(x)
Definition: ri.h:2967
#define variable_basic(x)
Definition: ri.h:3120
#define instruction_expression_p(x)
Definition: ri.h:1539
#define entity_initial(x)
Definition: ri.h:2796
#define syntax_subscript_p(x)
Definition: ri.h:2743
Value b2
Definition: sc_gram.c:105
Value b1
booleen indiquant quel membre est en cours d'analyse
Definition: sc_gram.c:105
int fprintf()
test sc_min : ce test s'appelle par : programme fichier1.data fichier2.data ...
s1
Definition: set.c:247
return(s1)
#define ifdebug(n)
Definition: sg.c:47
static size_t current
Definition: string.c:115
FI: I do not understand why the type is duplicated at the set level.
Definition: set.c:59
The structure used to build lists in NewGen.
Definition: newgen_list.h:41
Definition: delay.c:253
string words_to_string(cons *lw)
Definition: print.c:211
#define exp
Avoid some warnings from "gcc -Wshadow".
Definition: vasnprintf.c:207