PIPS
mappings.c
Go to the documentation of this file.
1 /*
2 
3  $Id: mappings.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  /* Variable value mappings package
28  *
29  * Establish mappings between analyzed scalar variable entities and
30  * variable value entities for a given module (see transformer/value.c).
31  *
32  * Handle static aliasing in Fortran, i.e. equivalences too.
33  *
34  * Cannot handle more than one module at a time: no recursivity on
35  * modules or chaos will occur.
36  *
37  * See package value.c for more information on functions more or less
38  * independent of the internal representation.
39  *
40  * Francois Irigoin, 20 April 1990
41  *
42  */
43 
44 #include <stdio.h>
45 
46 #include "genC.h"
47 #include "linear.h"
48 #include "ri.h"
49 #include "effects.h"
50 #include "ri-util.h"
51 #include "workspace-util.h"
52 #include "prettyprint.h"
53 #include "effects-util.h"
54 #include "constants.h"
55 
56 #include "misc.h"
57 
58 #include "arithmetique.h"
59 #include "vecteur.h"
60 #include "contrainte.h"
61 
62 /* To convert non constant effects into constant effects */
63 #include "effects-simple.h"
64 #include "effects-generic.h"
65 
66 #include "transformer.h"
67 
68 #include "semantics.h"
69 #include "preprocessor.h"
70 #include "properties.h"
71 ␌
72 /* FORTRAN 77 EQUIVALENCE */
73 
75 
77 {
80  }
81 }
82 
84 {
85  /* I need here a contraintes_dup() that is not yet available
86  in Linear and I cannot change Linear just before the DRET meeting;
87  I've got to modify transformer_equalities_add() and to give it
88  a behavior different from transformer_equality_add() */
90  return tf;
91 }
92 
94 {
95  /* assumes e and eq are different */
96  Pvecteur v = vect_new((Variable) e, 1);
97  Pcontrainte c;
98 
99  vect_add_elem(&v, (Variable) eq, -1);
100  c = contrainte_make(v);
101  /* Strange: there is no macro to chain a contrainte on a list of
102  contrainte */
105 }
106 
107 void add_equivalenced_values(entity e, entity eq, bool readonly)
108 {
109  /* e and eq are assumed to be different scalar variables of the same
110  analyzed type */
111  /* eq will be seen as e, as far as values are concerned,
112  but for printing */
113  /* new equalities e#new == eq#new and e#old == eq#old
114  have to be added to the preconditions just before they
115  are stored; since eq should never be written no eq#old
116  should appear; thus the first equation is enough */
117 
118  /* By definition, all variables are conflicting
119  with themselves but this is assumed filtered out above. */
120 
121  pips_assert("e is not eq", e!=eq);
122 
123  add_synonym_values(e, eq, readonly);
124  /* add the equivalence equations */
126 
127 }
128 ␌
129 /* ???? */
130 
131 /* void add_interprocedural_value_entities
132  */
134 {
135  pips_debug(8,"for %s\n", entity_name(e));
136  if(!entity_has_values_p(e)) {
138  if((a=value_alias(e))==entity_undefined){
139  add_new_value(e);
140  add_old_value(e);
143  }
144  else {
145  add_new_alias_value(e,a);
146  add_old_alias_value(e,a);
148  }
149  }
150 }
151 
153 {
154  pips_debug(8,"add_interprocedural_new_value_entities" "for %s\n",
155  entity_name(e));
156  if(!entity_has_values_p(e)) {
158  if((a=value_alias(e))==entity_undefined){
159  add_new_value(e);
160  /* CA: information on aliasing variables erased*/
162  }
163  else {
164  add_new_alias_value(e,a);
165  }
166  }
167 }
168 
170 {
171  pips_debug(8, "for %s\n", entity_name(e));
172  add_new_value(e);
176 }
177 
178 /* Use to be static, but may be called from ri_to_transformer. */
179 /* void add_intraprocedural_value_entities(entity e)
180  */
182 {
184 
185  pips_debug(8, "for %s\n", entity_name(e));
186  if(!entity_has_values_p(e) && type_variable_p(ut) ) {
188  }
189 }
190 ␌
191 /* Look for variables equivalenced with e. e already has values associated
192  * although it may not be a canonical representative of its equivalence
193  * class...
194  *
195  * Forget dynamic aliasing between formal parameters.
196  *
197  * Handle intraprocedural aliasing only.
198  *
199  * Do not handle interprocedural aliasing: this does not seem to be the right place
200  * because too many synonyms, not visible from the current procedure, are
201  * introduced (global_shared = area_layout(type_area(t));
202  * */
203 
205 {
206  storage s = entity_storage(e);
207  entity re = e; /* potential canonical representative for all variables equivalenced with e */
208 
209  pips_debug(8, "Begin for %s %s\n", entity_name(e),
210  readonly? "readonly" : "read/write");
211 
212  pips_assert("e has values", entity_has_values_p(e));
213 
214  if(storage_ram_p(s)) {
215  list local_shared = ram_shared(storage_ram(s));
216  bool array_equivalenced = false;
217  entity sec = ram_section(storage_ram(s));
218  type t = entity_type(sec);
219  list ce = list_undefined;
220 
221  pips_assert("t is an area", type_area_p(t));
222 
223  /* Is e intraprocedurally equivalenced/aliased with an array or a
224  * non-analyzable variable which would make e and all its aliased
225  * variables unanalyzable? */
226  for(ce=local_shared; !ENDP(ce); POP(ce)) {
227  entity eq = ENTITY(CAR(ce));
228 
229  /* Since the equivalence is reflexive, no need to process e==eq again. */
230  if(e==eq) continue;
231  /* Since the equivalence is symetrical, eq may have been processed
232  already. */
233  if(entity_has_values_p(eq)) continue;
234 
235  /* this approximate test by Pierre Jouvelot should be
236  replaced by an exact test but it does not really matter;
237  an exact test could only be useful in presence of arrays;
238  and in presence of arrays we do nothing here */
240  pips_user_warning("Values for variable %s are not analyzed because "
241  "%s is aliased with scalar variable %s with non "
242  "analyzed type %s or with array variable\n",
245  array_equivalenced = true;
246  break;
247  }
248 
251  pips_user_warning("Values for variable %s of type %s are not analyzed because "
252  "%s is aliased with scalar variable %s with different "
253  "type %s\n",
257  array_equivalenced = true;
258  break;
259  }
260  }
261  if(entities_may_conflict_p(e, eq) && strcmp(entity_name(eq), entity_name(re))<0) {
262  re = eq;
263  }
264  }
265 
266  /* if it's not, go ahead: it exists at least one eq such that e and eq
267  are different, are scalars and have the same analyzable type. All
268  eq conflicting with e meets these conditions. */
269  if(!array_equivalenced) {
270 
271  /* Declare values for the canonical representative re */
272  if(e!=re) {
273  pips_debug(8, "Canonical representative is %s\n", entity_local_name(re));
274  /* Give values to re which should have none and remove values of
275  e. Assume that e and re are local variables. */
276  pips_assert("re has no values", !entity_has_values_p(re));
277  remove_entity_values(e, readonly);
278  add_new_value(re);
279  if(!readonly) {
280  add_old_value(re);
282  }
283  }
284 
285  /* If it is intra-procedurally equivalenced, set the synonyms as
286  * read-only variables
287  */
288  for(ce=local_shared; !ENDP(ce); POP(ce)) {
289  entity eq = ENTITY(CAR(ce));
290 
291  if(re==eq) continue;
292  if(entities_may_conflict_p(re, eq)) {
293  /* if eq is an integer scalar variable it does not
294  only have a destructive effect */
295  add_equivalenced_values(re, eq, readonly);
296  }
297  }
298  }
299  else {
300  /* Variable e is equivalenced with an array or a non-integer
301  * variable and cannot be analyzed; it must be removed from
302  * the hash tables.
303  */
304  remove_entity_values(e, readonly);
305  }
306  }
307  else if(storage_return_p(s)) {
308  /* semantics analysis should be performed on this kind of variable
309  but it has probably been eliminated earlier; no equivalence
310  possible anyway! */
311  // FI: the warning message is not useful. See formal parameters
312  // pips_user_warning("storage return\n");
313  ;
314  }
315  else if(storage_formal_p(s))
316  /* to be dealt with later if we assume non-standard dynamic
317  aliasing between formal parameters */
318  ;
319  else
320  pips_internal_error("unproper storage = %d (%s), for entity %s", storage_tag(s), storage_to_string(s), entity_name(e));
321 
322  pips_debug(8, "End for %s\n", entity_name(e));
323 }
324 ␌
326 {
327  /* this routine tries to estimate the sizes of the hash tables,
328  although the hashtable package has enlarging capability;
329  its usefulness is limited... but keep at least hash table
330  allocations! */
331 
332  /* FI: not a good estimate for C codes with local delcarations */
333  list module_intra_effects = load_module_intraprocedural_effects(m);
334  int old_value_number = 0;
335  int intermediate_value_number = 0;
336  int new_value_number = 0;
337 
338  /* count interprocedural effects on scalar integer variables
339  before allocating hash tables; too many entries might be
340  expected because the same variable could appear many times,
341  at least twice, once in a read effect and once in a write
342  effect; entries for arrays equivalenced with scalar variables
343  are ignored; some slack is added before allocating the hash
344  tables; module_inter_effects are (should be) included into
345  module_intra_effects */
346  FOREACH(EFFECT, ef, module_intra_effects)
347  {
349  action a = effect_action(ef);
350  // The estimation is poor when abstract effects occur
352  new_value_number++;
353  if(action_write_p(a))
354  old_value_number++;
355  }
356 
357  /* add 50 % slack for underestimation (some more slack will be added
358  by the hash package */
359  new_value_number *= 3; new_value_number /= 2;
360  old_value_number *= 3; old_value_number /= 2;
361  /* the hash package does not like very small sizes */
362  new_value_number = MAX(10,new_value_number);
363  old_value_number = MAX(10,old_value_number);
364  /* overapproximate intermediate value number */
365  intermediate_value_number = old_value_number;
366 
367  pips_debug(8, "old_value_number = %d\n", old_value_number);
368  pips_debug(8, "new_value_number = %d\n", new_value_number);
369 
370  /* allocate hash tables */
371  allocate_value_mappings(new_value_number, old_value_number,
372  intermediate_value_number);
373 }
374 ␌
375 /* It is assumed that al is an abstract location that is written and
376  which may conflict with effects in effect list el. If there is a
377  conflict, than the variable associated to this effect is
378  written.
379 
380  It should be generalized to non-interprocedural cases.
381 */
383 {
384  type alt = entity_type(al);
385 
386  if(type_unknown_p(alt)
387  || type_area_p(alt) // FI: Let's agree about typing issues!
388  || get_bool_property("ALIASING_ACROSS_TYPES")
389  || overloaded_type_p(alt)) {
390  FOREACH(EFFECT, ef, el) {
392  entity v = reference_variable(r);
393 
395  && entities_may_conflict_p(al, v)
398  }
399  }
400  }
401  else {
402  FOREACH(EFFECT, ef, el) {
404  entity v = reference_variable(r);
405  type vt = ultimate_type(entity_type(v));
406 
408  && entities_may_conflict_p(al, v)
409  && type_equal_p(alt, vt)) {
411  pips_internal_error("Effects cannot be related to dummy parameters.");
413  }
414  }
415  }
416 }
417 
419 {
421  && !typedef_entity_p(e)
422  && !entity_field_p(e);
423 }
424 ␌
425 // Declared because they are called recursively but static
428 
429 /* Check which fields combined with r would lead to analyzed values
430  * and recurse for fields which are struct themselves.
431  *
432  * A similar function would be useful to handle struct assignments in
433  * semantics or points-to or effect analysis.
434  */
436 {
437  FOREACH(ENTITY, f, fl) {
439  if(analyzed_type_p(t)) {
441  entity l = make_location_entity(fr); // Do not free fr as it should be the initial value
442  if(!entity_has_values_p(l)) {
443  if(intra_p)
445  else
447  }
448  }
449  else if(struct_type_p(t)) {
451  list nfl = struct_type_to_fields(t);
452  if(intra_p)
454  else
456  free_reference(fr);
457  }
458  }
459 }
460 
462 {
464 }
465 
467 {
469 }
470 static void add_reference_values(reference r, bool write_p, bool global_p)
471 {
473  if(global_p) {
474  if(write_p)
476  else
478  }
479  else {
480  if(write_p)
482  else
484  }
485 }
486 ␌
487 /* If effect e meets all conditions to represent a location whose
488  * value could and should be analyzed, create the related values.
489  */
491 {
492  if(store_effect_p(e)) {
495  entity v = reference_variable(r);
496  if(entity_variable_p(v)
500  storage vs = entity_storage(v);
501  if(storage_ram_p(vs)
502  || storage_formal_p(vs)
503  /* || storage_return_p(vs)*/) {
504  // atomic_points_to_reference_p(r)
505  // scalar_reference_p(r))
507  if(analyzed_type_p(t)) { // implies scalar_type_p(t)
508  // FI: the effect may be local to the module or visible outside;
509  // the effect may be a read or a write
510  bool write_p = action_write_p(effect_action(e));
511  bool global_p = global_variable_p(v)
514  add_reference_values(r, write_p, global_p);
515  }
516  }
517  }
518  }
519  }
520  return;
521 }
522 ␌
523 /* Declare value entities necessary to analyze locations defined by
524  * proper effects.
525  *
526  */
527 
529 {
530  // #include "effects-generic.h"
534 
535  if(!get_bool_property("CONSTANT_PATH_EFFECTS")) {
536  list el = effects_effects(fx);
537  FOREACH(EFFECT, e, el) {
538  list cel = list_undefined;
539  if(pt_to_list_undefined_p()) {
540  // FI: use of a generic effect function
541  effect (*effect_dup_func_save)(effect eff) = effect_dup_func;
542  effect (*reference_to_effect_func_save)(reference, action, bool) = reference_to_effect_func;
546  effect_dup_func = effect_dup_func_save;
547  reference_to_effect_func = reference_to_effect_func_save;
548  }
549  else {
550  // FI: hopefully, the context is not used for simple effects...
553  }
554  FOREACH(EFFECT, ce, cel)
557  FOREACH(EFFECT, ce, cel)
560  gen_full_free_list(cel);
561  }
562  }
563  else {
564  list el = effects_effects(fx);
565  FOREACH(EFFECT, e, el) {
568  }
569  FOREACH(EFFECT, e, el) {
572  }
573  }
574 
575  return true;
576 }
577 
579 {
581  if(!get_bool_property("CONSTANT_PATH_EFFECTS")) {
582  pips_user_warning("Property \"CONSTANT_PATH_EFFECTS\" is set to its "
583  "experimental value, false.");
584  }
587  gen_null);
588  return;
589 }
590 ␌
591 /* void module_to_value_mappings(entity m): build hash tables between
592  * variables and values (old, new and intermediate), and between values
593  * and names for module m, as well as equivalence equalities
594  *
595  * NW:
596  * before calling "module_to_value_mappings"
597  * to set up the hash table to translate value into value names
598  * for module with name (string) module_name
599  * do:
600  *
601  * set_current_module_entity( local_name_to_top_level_entity(module_name) );
602  *
603  * (the following call is only necessary if a variable of type entity
604  * such as "module" is not already set)
605  * module = get_current_module_entity();
606  *
607  * set_current_module_statement( (statement)
608  * db_get_memory_resource(DBR_CODE,
609  * module_name,
610  * true) );
611  * set_cumulated_rw_effects((statement_effects)
612  * db_get_memory_resource(DBR_CUMULATED_EFFECTS,
613  * module_name,
614  * true));
615  *
616  * (that's it, but we musn't forget to reset everything
617  * after the call to "module_to_value_mappings", as below)
618  *
619  * reset_current_module_statement();
620  * reset_cumulated_rw_effects();
621  * reset_current_module_entity();
622  * free_value_mappings();
623  */
625 {
626  list module_inter_effects;
627  list module_intra_effects;
628 
629  pips_debug(8,"begin for module %s\n", module_local_name(m));
630 
631  pips_assert("m is a module", entity_module_p(m));
632 
633  // hook cleanup in free_value_mappings
635  /* free_value_mappings(); */
636 
638 
639  /* reset local intermediate value counter for
640  make_local_intermediate_value_entity and
641  make_local_old_value_entity */
646 
647  /* module_inter_effects = code_effects(value_code(entity_initial(m))); */
648  module_inter_effects = load_summary_effects(m);
649 
650  /* look for interprocedural write effects on scalar analyzable variables
651  and generate proper entries into hash tables */
652  FOREACH(EFFECT, ef, module_inter_effects) {
653  if(store_effect_p(ef)) {
655  entity e = reference_variable(r);
656  action a = effect_action(ef);
657  if(analyzable_scalar_entity_p(e) // check type
659  && (
660  action_write_p(a)
661  ||
662  /* In C, write effects on scalar formal parameter are
663  masked by the value passing mode but the copy may
664  nevertheless be written inside the function. */
665  (c_module_p(m) && entity_formal_p(e))
666  ||
667  /* To keep the summary transformer consistent
668  although the return value has no old value */
670  ))
671  )
673  else if(entity_abstract_location_p(e) && action_write_p(a)) {
674  add_implicit_interprocedural_write_effects(e, module_inter_effects);
675  }
678  if(analyzed_type_p(t)) {
681  }
682  free_type(t);
683  }
684  }
685  }
686 
687  /* look for interprocedural read effects on scalar analyzable variables
688  and generate proper entries into hash tables */
689  FOREACH(EFFECT, ef, module_inter_effects) {
690  if(store_effect_p(ef)) {
692  action a = effect_action(ef);
694  if(c_module_p(m) &&
696  /* static variables have an old value too */
698  )
699  )
701  else
703  }
704  }
705  }
706 
707  module_intra_effects = load_module_intraprocedural_effects(m);
708 
709  /* look for intraprocedural write effects on scalar analyzable variables
710  and generate proper entries into hash tables */
711  FOREACH(EFFECT, ef, module_intra_effects) {
712  if(store_effect_p(ef)) {
714  action a = effect_action(ef);
718  }
719  else {
722  && !entity_heap_location_p(e))
724  }
725  }
726  else if(constant_path_analyzed_p() && action_write_p(a)) {
728 
729  if (analyzed_reference_p(rlhs)) {
730  entity le = make_location_entity(rlhs);
732  }
733  }
734  }
735  }
736 
737  /* look for intraprocedural read effects on scalar analyzable variables
738  and generate proper entry into value name hash table if it has
739  not been entered before; interprocedural read effects are implicitly
740  dealed with since they are included;
741  most entities are likely to have been encountered before; however
742  in parameters and uninitialized variables have to be dealt with */
743  FOREACH(EFFECT, ef, module_intra_effects) {
744  if(store_effect_p(ef)) {
747  /* FI: although it may only be read within this procedure, e
748  * might be written in another one thru a COMMON; this write
749  * is not visible from OUT, but only from a caller of out;
750  * because we have only a local intraprocedural or a global
751  * interprocedural view of aliasing, we have to create useless
752  * values:-(
753  *
754  * add_new_value(e);
755  *
756  * Note: this makes the control structure of this procedure
757  * obsolete!
758  */
759  /* This call is useless because it only is effective if
760  * entity_has_values_p() is true:
761  * add_intraprocedural_value_entities(e);
762  */
765  && !entity_heap_location_p(e))
767  /* A stronger call to the same subroutine is included in
768  * the previous call:
769  * add_or_kill_equivalenced_variables(e, true);
770  */
771  }
772  }
773  }
774 
775  /* scan declarations to make sure that private variables are
776  * taken into account; assume a read and write effects on these
777  * variables, although they may not even be used.
778  *
779  * Only intraprocedural variables can be privatized (1 Aug. 92)
780  */
782  FOREACH(ENTITY, e, dl) {
786  /* This should be useless if return variables are taken
787  into account by effect analysis. No problem with
788  Fortran because the return variable really is assigned
789  a value. Not obvious in C because the assignment is
790  implicit in the return statement. In C the return
791  variable is more like a value: it cannot be re-assigned. */
793  }
794  else {
796  }
797  }
798  else if(entity_variable_p(e) && !entity_abstract_location_p(e)) {
799  storage es = entity_storage(e);
800  // FI: do not process named or derived types
801  //if(storage_ram_p(es) || storage_return_p(es)) {
802  /* FI: Only return variables are forgotten by effects
803  *
804  * FI: no, this is wrong in C; local variables are dropped
805  * from effect when their declaration statements are
806  * processed. They cannot be found in the effects of the
807  * module statement.
808  */
809  if(storage_ram_p(es) || storage_return_p(es)) {
812  /* We need references to all fields, direct or indirect when
813  * a field is itself a struct
814  */
815  reference r = make_reference(e, NIL);
816  list fl = struct_type_to_fields(t);
818  free_reference(r);
819  }
820  }
821  }
822  }
823 
824  /* scan other referenced variables to make sure everyone has an
825  * entry in the symbol table
826  */
828  SET_FOREACH(entity, e, re) {
830  pips_assert("should not go there ?", !storage_return_p(entity_storage(e)));
832  }
833  }
834 
835  // FI: to analyze array elements with constant subscripts, we would
836  // need to get a list of all constant atomic references with types
837  // that are analyzed.
838 
839  // FI: for points-to analysis, we need to know all formal virtual
840  // entities that have been created by the points-to pass. It is not
841  // clear the information may be retrieved from the module statement
842  // cumulated effect, especially if scopes are used by the
843  // programmer, or the module summary cumulated effects.
845  SET_FOREACH(entity, e, re) {
846  // FI: place holder variables are supposed to have been removed
847  // from internal representation by C parser?
849  storage es = entity_storage(e);
850  if(storage_ram_p(es)/* || storage_return_p(es)*/) {
852  if(struct_type_p(t)) {
853  /* We need references to all fields, direct or indirect when
854  * a field is itself a struct
855  */
856  reference r = make_reference(e, NIL);
857  list fl = struct_type_to_fields(t);
859  free_reference(r);
860  }
861  }
862  }
863  }
864  }
865  set_free(re);
866 
867  /* Beware of struct return values which may generate additional
868  * locations and location values
869  */
871  const char * module_name = entity_local_name(m);
872  callees c = (callees) db_get_memory_resource(DBR_CALLEES,
873  module_name,
874  true);
875  list lc = callees_callees(c);
876  FOREACH(STRING, callee_name, lc) {
877  entity f = module_name_to_entity(callee_name);
880  if(struct_type_p(rt)) {
882  reference rvr = make_reference(rv, NIL);
883  list fl = struct_type_to_fields(rt);
885  free_reference(rvr);
886  }
887  }
888  }
889 
890  /* To be sure to retrieve all relevant locations, including array elements */
893  }
894 
895  /* for debug, print hash tables */
896  ifdebug(8) {
897  pips_debug(8, "hash tables for module %s\n", module_local_name(m));
900  }
901 
902  pips_debug(1, "Number of analyzed variables for module %s: %d\n",
905  pips_debug(1, "Number of analyzed values for module %s: %d\n",
908 
909  pips_debug(8,"end for module %s\n", module_local_name(m));
910 }
911 
912 /* transform a vector based on variable entities into a vector based
913  * on new value entities when possible; does nothing most of the time;
914  * does a little in the presence of equivalenced variables
915  *
916  * Ugly because it has a hidden side effect on v to handle Fortran
917  * equivalences and because its implementation is dependent on type
918  * Pvecteur.
919  *
920  * Assume that the value mappings are available (as implied by the
921  * function's name!), which may not be true when dealing with call
922  * sites.
923  */
925 {
926  Pvecteur v = iv;
927  for(;!VECTEUR_NUL_P(v); v = v->succ) {
928  if(vecteur_var(v) != TCST) {
929  entity e = (entity) vecteur_var(v);
930 
931  /* The variable may denote a constant with compatible type */
932  if(entity_constant_p(e) && !analyzed_constant_p(e)) {
933  return false;
934  }
935 
936  /* or a temporary variable */
937  else if(local_temporary_value_entity_p(e)) {
938  ;
939  }
940 
941  /* Or a variable value */
942  else if(entity_has_values_p(e)) {
943  entity new_v = entity_to_new_value(e);
944 
945  if(new_v != entity_undefined)
946  vecteur_var(v) = (Variable) new_v;
947  else
948  return false;
949  }
950 
951  /* Or a phi variable, when transformers are computed by the
952  region analysis */
953  else if(variable_phi_p(e)) {
954  ;
955  }
956 
957  /* Or the vector cannot be used in the semantics analysis */
958  else {
959  return false;
960  }
961  }
962  }
963  return true;
964 }
965 ␌
967 {
968  list list_val = NIL;
969 
970  FOREACH(ENTITY, e, list_mod) {
971  if(entity_has_values_p(e)) {
972  entity v_old = entity_to_old_value(e);
973  entity v_new = entity_to_new_value(e);
974 
975  list_val = CONS(ENTITY, v_old, list_val);
976  list_val = CONS(ENTITY, v_new, list_val);
977  }
978  }
979  return list_val;
980 }
981 
983 {
984  list list_val = NIL;
985 
986  if(entity_has_values_p(e)) {
987  entity v_old = entity_to_old_value(e);
988  entity v_new = entity_to_new_value(e);
989 
990  list_val = CONS(ENTITY, v_old, list_val);
991  list_val = CONS(ENTITY, v_new, list_val);
992  }
993 
994  return list_val;
995 }
996 
997 /* Build the list of values to be projected when the declaration list
998  * list_mod is no longer valid because a block is closed/left.
999  *
1000  * Values for static variables are preserved. Values for heap
1001  * variables also, in case their values are computed in the future...
1002  *
1003  * This may not be the best algorithm when locations are used because
1004  * the list of locations may be much longer, especially for arrays,
1005  * than the list of values appearing in the transformer.
1006  */
1008 {
1009  list list_val = NIL;
1010 
1011  FOREACH(ENTITY, e, list_mod) {
1012  if(entity_has_values_p(e)
1013  && (variable_dynamic_p(e) || variable_stack_p(e))) {
1014  entity v_old = entity_to_old_value(e);
1015  entity v_new = entity_to_new_value(e);
1016 
1017  list_val = CONS(ENTITY, v_old, list_val);
1018  list_val = CONS(ENTITY, v_new, list_val);
1019  }
1020  }
1021  return list_val;
1022 }
1023 
1025 {
1026  list list_val = NIL;
1027 
1028  MAP(ENTITY, e, {
1029  entity v_old = entity_to_old_value(e);
1030 
1031  list_val = CONS(ENTITY, v_old, list_val);
1032  }, list_mod);
1033  return list_val;
1034 }
1035 ␌
1036 /* replace variables by new values which is necessary for equivalenced
1037  variables */
1039 {
1040  Pvecteur elem = VECTEUR_UNDEFINED;
1041 
1042  for(elem = v; !VECTEUR_NUL_P(elem); elem = vecteur_succ(elem)) {
1043  entity var = (entity) vecteur_var(elem);
1044 
1045  if(vecteur_var(elem)!=TCST) {
1046  entity v_new = entity_to_new_value(var);
1047 
1048  if(v_new!=var) {
1049  (void) vect_variable_rename(v, (Variable) var,
1050  (Variable) v_new);
1051  }
1052  }
1053  }
1054 }
1055 ␌
1056 /* Renaming of variables in v according to transformations occuring
1057  * later. If a variable is modified by post, its old value must
1058  * be used in v
1059  */
1060 
1061 void
1063 {
1064  /* FI: it would probably ne more efficient to
1065  * scan va and vb than the argument list...
1066  */
1067  list modified_values = transformer_arguments(post);
1068 
1069  FOREACH(ENTITY, v_new, modified_values) {
1070  entity v_init = new_value_to_old_value(v_new);
1071 
1072  (void) vect_variable_rename(v, (Variable) v_new,
1073  (Variable) v_init);
1074  }
1075 }
effect copy_effect(effect p)
EFFECT.
Definition: effects.c:448
void free_reference(reference p)
Definition: ri.c:2050
reference make_reference(entity a1, list a2)
Definition: ri.c:2083
reference copy_reference(reference p)
REFERENCE.
Definition: ri.c:2047
void free_type(type p)
Definition: ri.c:2658
struct _newgen_struct_entity_ * entity
Definition: abc_private.h:14
bool entity_heap_location_p(entity b)
package abstract location.
bool entity_abstract_location_p(entity al)
bool entity_typed_anywhere_locations_p(entity e)
Test if an entity is the bottom of the lattice.
bool entity_anywhere_locations_p(entity e)
test if an entity is the bottom of the lattice
Pvecteur vect_variable_rename(Pvecteur v, Variable v_old, Variable v_new)
Pvecteur vect_variable_rename(Pvecteur v, Variable v_old, Variable v_new): rename the potential coord...
Definition: base.c:366
transformer transformer_equalities_add(transformer tf, Pcontrainte eqs)
Definition: basic.c:391
struct _newgen_struct_reference_ * reference
Definition: compsec.h:14
struct _newgen_struct_action_ * action
Definition: compsec.h:21
#define CONTRAINTE_UNDEFINED
Pcontrainte contraintes_free(Pcontrainte pc)
Pcontrainte contraintes_free(Pcontrainte pc): desallocation de toutes les contraintes de la liste pc.
Definition: alloc.c:226
Pcontrainte contrainte_make(Pvecteur pv)
Pcontrainte contrainte_make(Pvecteur pv): allocation et initialisation d'une contrainte avec un vecte...
Definition: alloc.c:73
list load_module_intraprocedural_effects(entity e)
list load_summary_effects(entity e)
FI->FI, FI->BC: these two functions should be moved into effects-util or effects-simple.
struct _newgen_struct_effect_ * effect
Definition: dg.h:21
effects load_proper_rw_effects(statement)
list effect_to_constant_path_effects_with_no_pointer_information(effect)
effect(* reference_to_effect_func)(reference, action, bool)
effect(* effect_dup_func)(effect eff)
effect reference_to_reference_effect(reference, action, bool)
list effect_to_constant_path_effects_with_points_to(effect, statement, transformer)
Definition: eval.c:284
#define effect_any_reference(e)
FI: cannot be used as a left hand side.
#define effect_write_p(eff)
#define variable_phi_p(e)
true if e is a phi variable PHI entities have a name like: REGIONS:PHI#, where # is a number.
bool location_entity_p(entity)
Definition: locations.c:349
type points_to_reference_to_concrete_type(reference)
Definition: type.c:685
reference cell_any_reference(cell)
API for reference.
Definition: effects.c:77
bool generic_atomic_points_to_reference_p(reference, bool)
Is it a unique concrete memory location?
Definition: points_to.c:489
bool store_effect_p(effect)
Definition: effects.c:1062
entity make_location_entity(reference)
locations.c
Definition: locations.c:274
reference simple_reference_add_field_dimension(reference, entity)
Do not check anything, just add f as a last subscript.
Definition: effects.c:1581
bool pt_to_list_undefined_p(void)
points_to.c
bool store_independent_effect_p(effect)
Does this effect define the same set of memory locations regardless of the current (environment and) ...
Definition: effects.c:636
#define effect_action(x)
Definition: effects.h:642
#define action_write_p(x)
Definition: effects.h:314
#define action_read_p(x)
Definition: effects.h:311
#define effects_effects(x)
Definition: effects.h:710
#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....
#define STRING(x)
Definition: genC.h:87
#define gen_recurse(start, domain_number, flt, rwt)
Definition: genC.h:283
void gen_full_free_list(list l)
Definition: genClib.c:1023
bool entities_may_conflict_p(entity e1, entity e2)
Check if two entities may conflict.
Definition: conflicts.c:984
statement get_current_module_statement(void)
Get the current module statement.
Definition: static.c:208
entity get_current_module_entity(void)
Get the entity of the current module.
Definition: static.c:85
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
#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
#define CONS(_t_, _i_, _l_)
List element cell constructor (insert an element at the beginning of a list)
Definition: newgen_list.h:150
#define CAR(pcons)
Get the value of the first element of a list.
Definition: newgen_list.h:92
#define FOREACH(_fe_CASTER, _fe_item, _fe_list)
Apply/map an instruction block on all the elements of a list.
Definition: newgen_list.h:179
#define list_undefined
Undefined list definition :-)
Definition: newgen_list.h:69
#define MAP(_map_CASTER, _map_item, _map_code, _map_list)
Apply/map an instruction block on all the elements of a list (old fashioned)
Definition: newgen_list.h:226
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
#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
void reset_hooks_register(reset_func_t)
reset_hooks.c
Definition: reset_hooks.c:44
#define SET_FOREACH(type_name, the_item, the_set)
enumerate set elements in their internal order.
Definition: newgen_set.h:78
void set_free(set)
Definition: set.c:332
int bool
we cannot use an enum or stdbool because we need to be compatible with newgen, thus boolean need to h...
Definition: newgen_types.h:78
int f(int off1, int off2, int n, float r[n], float a[n], float b[n])
Definition: offsets.c:15
#define entity_variable_p(e)
An entity_variable_p(e) may hide a typedef and hence a functional type.
#define entity_constant_p(e)
bool entity_not_constant_or_intrinsic_p(entity e)
Default entity filter for get_referenced_entities()
Definition: entity.c:3050
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 dummy_parameter_entity_p(entity p)
is p a dummy parameter?
Definition: entity.c:1941
bool entity_formal_p(entity p)
is p a formal parameter?
Definition: entity.c:1935
bool c_module_p(entity m)
Test if a module "m" is written in C.
Definition: entity.c:2777
set get_referenced_entities_filtered(void *elem, bool(*chunk_filter)(void *), bool(*entity_filter)(entity))
Same as get_referenced_entities, but will only consider entities that fulfills entity_filter and will...
Definition: entity.c:2982
entity module_name_to_entity(const char *mn)
This is an alias for local_name_to_top_level_entity.
Definition: entity.c:1479
string storage_to_string(storage s)
Definition: entity.c:2030
bool typedef_entity_p(entity e)
Definition: entity.c:1902
bool effects_package_entity_p(entity e)
checks if an entity is an IO_EFFECTS_PACKAGE_NAME, a MALLOC_EFFECTS_NAME or a RAND_EFFECTS_PACKAGE_NA...
Definition: entity.c:1181
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 entity_module_p(entity e)
Definition: entity.c:683
entity function_to_return_value(entity m)
Returns the entity rv that carries the value returned by module m, when m is not a C void function or...
Definition: module.c:509
type ultimate_type(type)
Definition: type.c:3466
bool formal_context_variable_p(entity)
Such pseudo-variables are generated by the points-to analysis.
Definition: variable.c:1535
bool entity_static_variable_p(entity)
return true if the entity is declared with the keyword static
Definition: variable.c:1146
bool variable_is_a_module_formal_parameter_p(entity, entity)
Definition: variable.c:1547
bool place_holder_variable_p(entity)
Definition: variable.c:2069
bool global_variable_p(entity)
Is v a global variable such as "int i;".
Definition: variable.c:1510
bool variable_dynamic_p(entity)
Definition: variable.c:1586
bool type_equal_p(type, type)
Definition: type.c:547
bool integer_scalar_entity_p(entity)
integer_scalar_entity_p() is obsolete; use entity_integer_scalar_p()
Definition: variable.c:1137
type entity_basic_concrete_type(entity)
retrieves or computes and then returns the basic concrete type of an entity
Definition: type.c:3677
bool variable_stack_p(entity)
Definition: variable.c:1593
list struct_type_to_fields(type)
Definition: type.c:5798
bool struct_type_p(type)
Returns true if t is of type derived and if the derived type is a struct.
Definition: type.c:3121
type compute_basic_concrete_type(type)
computes a new type which is the basic concrete type of the input type (this new type is not stored i...
Definition: type.c:3556
bool overloaded_type_p(type)
Returns true if t is a variable type with a basic overloaded.
Definition: type.c:2666
string type_to_string(const type)
type.c
Definition: type.c:51
struct _newgen_struct_callees_ * callees
Definition: ri.h:55
#define transformer_undefined
Definition: ri.h:2847
#define functional_result(x)
Definition: ri.h:1444
#define storage_formal_p(x)
Definition: ri.h:2522
#define type_unknown_p(x)
Definition: ri.h:2956
#define callees_callees(x)
Definition: ri.h:675
#define reference_variable(x)
Definition: ri.h:2326
#define storage_tag(x)
Definition: ri.h:2515
#define ENTITY(x)
ENTITY.
Definition: ri.h:2755
#define type_functional(x)
Definition: ri.h:2952
#define entity_storage(x)
Definition: ri.h:2794
#define statement_domain
newgen_sizeofexpression_domain_defined
Definition: ri.h:362
#define storage_ram_p(x)
Definition: ri.h:2519
#define ram_section(x)
Definition: ri.h:2249
#define entity_undefined
Definition: ri.h:2761
#define entity_name(x)
Definition: ri.h:2790
#define transformer_arguments(x)
Definition: ri.h:2871
#define storage_ram(x)
Definition: ri.h:2521
#define type_area_p(x)
Definition: ri.h:2944
#define entity_type(x)
Definition: ri.h:2792
#define ram_shared(x)
Definition: ri.h:2253
#define storage_return_p(x)
Definition: ri.h:2516
#define type_variable_p(x)
Definition: ri.h:2947
Pcontrainte eq
element du vecteur colonne du systeme donne par l'analyse
Definition: sc_gram.c:108
static bool entity_for_value_mapping_p(entity e)
Definition: mappings.c:418
static void allocate_module_value_mappings(entity m)
Definition: mappings.c:325
static void add_reference_values(reference r, bool write_p, bool global_p)
Definition: mappings.c:470
void add_or_kill_equivalenced_variables(entity e, bool readonly)
Look for variables equivalenced with e.
Definition: mappings.c:204
transformer tf_equivalence_equalities_add(transformer tf)
mappings.c
Definition: mappings.c:83
bool value_mappings_compatible_vector_p(Pvecteur iv)
transform a vector based on variable entities into a vector based on new value entities when possible...
Definition: mappings.c:924
static void add_inter_or_intraprocedural_field_entities(reference r, list fl, bool intra_p)
Check which fields combined with r would lead to analyzed values and recurse for fields which are str...
Definition: mappings.c:435
void add_intraprocedural_value_entities(entity e)
Use to be static, but may be called from ri_to_transformer.
Definition: mappings.c:181
void variables_to_new_values(Pvecteur v)
replace variables by new values which is necessary for equivalenced variables
Definition: mappings.c:1038
list variables_to_values(list list_mod)
Definition: mappings.c:966
static void reset_equivalence_equalities()
Definition: mappings.c:76
static void add_interprocedural_value_entities(entity e)
????
Definition: mappings.c:133
void upwards_vect_rename(Pvecteur v, transformer post)
Renaming of variables in v according to transformations occuring later.
Definition: mappings.c:1062
static void values_for_current_module_intraprocedural_simple_effects(void)
Definition: mappings.c:578
static void create_values_for_simple_effect(effect e, entity m)
If effect e meets all conditions to represent a location whose value could and should be analyzed,...
Definition: mappings.c:490
list dynamic_variables_to_values(list list_mod)
Build the list of values to be projected when the declaration list list_mod is no longer valid becaus...
Definition: mappings.c:1007
static void add_interprocedural_field_entities(reference r, list fl)
Definition: mappings.c:466
static void add_interprocedural_new_value_entity(entity e)
Definition: mappings.c:152
static void add_intraprocedural_value_entities_unconditionally(entity e)
Definition: mappings.c:169
static void add_intraprocedural_field_entities(reference r, list fl)
Definition: mappings.c:461
list variable_to_values(entity e)
Definition: mappings.c:982
void module_to_value_mappings(entity m)
void module_to_value_mappings(entity m): build hash tables between variables and values (old,...
Definition: mappings.c:624
static bool add_values_for_simple_effects_of_statement(statement s)
Declare value entities necessary to analyze locations defined by proper effects.
Definition: mappings.c:528
static void add_equivalence_equality(entity e, entity eq)
Definition: mappings.c:93
static Pcontrainte equivalence_equalities
Variable value mappings package.
Definition: mappings.c:74
list variables_to_old_values(list list_mod)
Definition: mappings.c:1024
void add_implicit_interprocedural_write_effects(entity al, list el)
It is assumed that al is an abstract location that is written and which may conflict with effects in ...
Definition: mappings.c:382
void add_equivalenced_values(entity e, entity eq, bool readonly)
Definition: mappings.c:107
#define ifdebug(n)
Definition: sg.c:47
#define MAX(x, y)
Definition: string.c:110
struct Scontrainte * succ
le type des coefficients dans les vecteurs: Value est defini dans le package arithmetique
Definition: vecteur-local.h:89
struct Svecteur * succ
Definition: vecteur-local.h:92
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
void add_synonym_values(entity, entity, bool)
Definition: value.c:1578
bool analyzed_reference_p(reference)
FI: Nelson explains the motivation for can_be_constant_path_p() but I do not understand them.
Definition: value.c:518
void reset_value_counters(void)
Definition: value.c:244
void set_analyzed_types(void)
Definition: value.c:271
void add_intermediate_alias_value(entity, entity)
Definition: value.c:1495
bool analyzable_scalar_entity_p(entity)
The entity type is one of the analyzed types.
Definition: value.c:471
void add_new_value(entity)
Definition: value.c:1386
void add_old_alias_value(entity, entity)
Definition: value.c:1463
void test_mapping_entry_consistency(void)
Definition: value.c:1113
void remove_entity_values(entity, bool)
Definition: value.c:1545
entity value_alias(entity)
Static aliasing.
Definition: value.c:1729
entity new_value_to_old_value(entity)
Definition: value.c:1710
void add_intermediate_value(entity)
Definition: value.c:1476
bool constant_path_analyzed_p(void)
Definition: value.c:330
bool analyzed_constant_p(entity)
The constant may appear as a variable in the linear systems.
Definition: value.c:487
void add_old_value(entity)
Definition: value.c:1440
entity entity_to_new_value(entity)
Definition: value.c:859
void reset_temporary_value_counter(void)
Definition: value.c:250
int aproximate_number_of_analyzed_variables(void)
Definition: value.c:1153
void add_local_old_value(entity)
Definition: value.c:1509
void print_value_mappings(void)
Definition: value.c:993
bool entity_has_values_p(entity)
This function could be made more robust by checking the storage of e.
Definition: value.c:911
void add_new_alias_value(entity, entity)
Definition: value.c:1396
bool local_temporary_value_entity_p(entity)
Definition: value.c:654
void add_local_intermediate_value(entity)
Definition: value.c:1526
void allocate_value_mappings(int, int, int)
Definition: value.c:1165
void error_reset_value_mappings(void)
To be called by error handler only.
Definition: value.c:1205
entity entity_to_old_value(entity)
Definition: value.c:869
int number_of_analyzed_values(void)
Definition: value.c:1148
bool analyzed_type_p(type)
The type t is one of the analyzed types.
Definition: value.c:367
#define TCST
VARIABLE REPRESENTANT LE TERME CONSTANT.
#define vecteur_var(v)
#define VECTEUR_UNDEFINED
#define vecteur_succ(v)
#define VECTEUR_NUL_P(v)
void * Variable
arithmetique is a requirement for vecteur, but I do not want to inforce it in all pips files....
Definition: vecteur-local.h:60
Pvecteur vect_new(Variable var, Value coeff)
Pvecteur vect_new(Variable var,Value coeff): allocation d'un vecteur colineaire au vecteur de base va...
Definition: alloc.c:110
void vect_add_elem(Pvecteur *pvect, Variable var, Value val)
void vect_add_elem(Pvecteur * pvect, Variable var, Value val): addition d'un vecteur colineaire au ve...
Definition: unaires.c:72
list current_module_declarations()
Definition: module.c:78