PIPS
equivalence.c
Go to the documentation of this file.
1 /*
2 
3  $Id: equivalence.c 23065 2016-03-02 09:05:50Z coelho $
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 /* Support and resolve equivalence chains. Allocate addresses in commons
28  * and in the static area and in the dynamic area. The heap area is left
29  * aside.
30  */
31 
32 #ifndef lint
33 char vcid_syntax_equivalence[] = "$Id: equivalence.c 23065 2016-03-02 09:05:50Z coelho $";
34 #endif /* lint */
35 
36 /* equivalence.c: contains EQUIVALENCE related routines */
37 
38 #include <stdio.h>
39 
40 #include "genC.h"
41 #include "linear.h"
42 #include "ri.h"
43 #include "ri-util.h"
44 #include "workspace-util.h"
45 
46 #include "parser_private.h"
47 
48 #include "properties.h"
49 
50 #include "misc.h"
51 
52 #include "syntax.h"
53 
54 #define EQUIADD 0
55 #define EQUIMERGE 1
56 
57 /* external variables used by functions from equivalence.c
58  */
61 
62 /* undefine chains between two successives calls to parser
63  */
64 void
66 {
71 }
72 
73 /* initialize chains before each call to the parser
74  */
75 void
77 {
78  pips_assert("TempoEquivSet is undefined", equivalences_undefined_p(TempoEquivSet));
79  pips_assert("FinalEquivSet is undefined", equivalences_undefined_p(FinalEquivSet));
82 }
83 
84 
85 /* this function creates an atom of an equivalence chain. s is a
86 reference to a variable. */
87 
88 atom
90 syntax s;
91 {
93  entity e;
94  int o = 0; /* reference offset */
95  int so = 0; /* substring offset */
96 
97  if (!syntax_reference_p(s)) {
98  pips_assert("This is syntax is a call", syntax_call_p(s));
100  SUBSTRING_FUNCTION_NAME) == 0) {
101  list args = call_arguments(syntax_call(s));
102  syntax ss = expression_syntax(EXPRESSION(CAR(args)));
103  expression lb = EXPRESSION(CAR(CDR(args)));
104 
105  pips_assert("syntax is reference",syntax_reference_p(ss));
106 
107  r = syntax_reference(ss);
108  if(expression_constant_p(lb)) {
109  so = expression_to_int(lb)-1;
110  }
111  else {
112  ParserError("MakeEquivAtom",
113  "Non constant substring lower bound in equivalence chain\n");
114  }
115  }
116  else {
117  pips_user_warning("A function call to %s has been identified by the parser "
118  "in an EQUIVALENCE statement. Maybe an array declaration "
119  "should be moved up ahead of the EQUIVALENCE\n",
121  ParserError("MakeEquivAtom", "function call in equivalence chain\n");
122  }
123  }
124  else {
125  r = syntax_reference(s);
126  so = 0;
127  }
128 
129  e = reference_variable(r);
130 
132  pips_user_warning("Formal parameter %s appears in EQUIVALENCE declaration\n",
133  entity_local_name(e));
134  ParserError("MakeEquivAtom", "Formal parameter in equivalence chain\n");
135  }
136 
137  /* Equivalenced variables cannot be initialized by a DATA statement: false */
138  /*
139  if(value_defined_p(entity_initial(e))) {
140  pips_user_warning("Initialized variable %s appears in EQUIVALENCE declaration\n",
141  entity_local_name(e));
142  ParserError("MakeEquivAtom", "Initialized variable in equivalence chain\n");
143  }
144  */
145 
146  /* In case, the entity is not of type variable, reject it. */
147  if(!type_variable_p(entity_type(e))) {
148  pips_user_warning("Illegal symbol %s appears in EQUIVALENCE declaration\n",
149  entity_local_name(e));
150  ParserError("MakeEquivAtom", "Functional variable (?) in equivalence chain.\n");
151  }
152 
153  /* In case an adjustable array which is not a formal parameter has
154  been encountered, reject it. */
156  pips_user_warning("Adjustable array %s appears in EQUIVALENCE declaration\n",
157  entity_local_name(e));
158  ParserError("MakeEquivAtom", "Adjustable array in equivalence chain\n");
159  }
160 
161  /* what is the offset of this reference ? */
162  o = so + OffsetOfReference(r);
163 
164  pips_debug(8, "Offset %d for reference to %s\n",
165  o, entity_local_name(e));
166 
167  return(make_atom(e, o));
168 }
169 ␌
170 /* This function is called when an equivalence chain has been completely
171 parsed. It looks for the atom with the biggest offset, and then substracts
172 this maximum offset from all atoms. The result is that each atom has its
173 offset from the begining of the chain. */
174 
175 void
177 chain c;
178 {
179  cons * pc;
180  int maxoff;
181 
182  maxoff = 0;
183  for (pc = chain_atoms(c); pc != NIL; pc = CDR(pc)) {
184  int o = atom_equioff(ATOM(CAR(pc)));
185 
186  if (o > maxoff)
187  maxoff = o;
188  }
189 
190  pips_debug(9, "maxoff %d\n", maxoff);
191 
192  if (maxoff > 0) {
193  for (pc = chain_atoms(c); pc != NIL; pc = CDR(pc)) {
194  atom a = ATOM(CAR(pc));
195 
196  atom_equioff(a) = abs(atom_equioff(a)-maxoff);
197  }
198  }
199 
200  /*
201  if (TempoEquivSet == equivalences_undefined) {
202  TempoEquivSet = make_equivalences(NIL);
203  }
204  */
205  pips_assert("The TempoEquivSet is defined", !equivalences_undefined_p(TempoEquivSet));
206 
209 }
210 ␌
211 /* This function merges all the equivalence chains to take into account
212 equivalences due to transitivity. It is called at the end of the parsing. */
213 
214 void
216 {
217  cons *pc;
218  int again = true;
219 
220  pips_debug(8, "Begin\n");
221 
222  /*
223  if (TempoEquivSet == equivalences_undefined) {
224  pips_debug(8, "Useless call, end\n");
225  return;
226  }
227  */
228 
230  pips_debug(8, "No equivalences to process, end\n");
231  return;
232  }
233 
234  /* They should be properly initialized by SetChains
235  if (FinalEquivSet == equivalences_undefined) {
236  FinalEquivSet = make_equivalences(NIL);
237  }
238  */
239 
240  pips_debug(8, "Initial equivalence chains\n");
242 
243  while (again) {
244  for (pc = equivalences_chains(TempoEquivSet); pc != NIL; pc = CDR(pc))
245  again = (AddOrMergeChain(CHAIN(CAR(pc))) == EQUIMERGE);
246 
247  if (again) {
251 
252  pips_debug(8, "Intermediate equivalence chains\n");
254  }
255  }
256 
257  pips_debug(8, "Resulting equivalence chains\n");
258 
260 
261  pips_debug(8, "End\n");
262 }
263 ␌
264 /* this function adds a chain ct to the set of equivalences. if the
265 intersection with all other chains is empty, ct is just added to the
266 set. Otherwise ct is merged with the chain that intersects ct. */
267 
268 int
270 chain ct;
271 {
272  cons *pcl, *pcf, *pct;
273 
274  pct = chain_atoms(ct);
275  chain_atoms(ct) = NIL;
276 
277  for (pcl = equivalences_chains(FinalEquivSet); pcl != NIL; pcl=CDR(pcl)) {
278  chain cf;
279 
280  cf = CHAIN(CAR(pcl));
281  pcf = chain_atoms(cf);
282 
283  if (ChainIntersection(pct, pcf)) {
284  chain_atoms(cf) = MergeTwoChains(pct, pcf);
285  return(EQUIMERGE);
286  }
287  }
288 
290  CONS(CHAIN, make_chain(pct),
292 
293  return(EQUIADD);
294 }
295 
296 
297 
298 /* this function returns true if the there is a variable that occurs in
299 both atom lists. */
300 
301 int
302 ChainIntersection(opc1, opc2)
303 cons *opc1, *opc2;
304 {
305  cons *pc1, *pc2;
306 
307  for (pc1 = opc1; pc1 != NIL; pc1 = CDR(pc1))
308  for (pc2 = opc2; pc2 != NIL; pc2 = CDR(pc2))
309  if (gen_eq((atom_equivar(ATOM(CAR(pc1)))),
310  (atom_equivar(ATOM(CAR(pc2))))))
311  return(true);
312 
313  return(false);
314 }
315 
316 
317 
318 /* this function merges two equivalence chains whose intersection is not
319 empty, ie. one variable occurs in both chains. */
320 
321 cons *
322 MergeTwoChains(opc1, opc2)
323 cons *opc1, *opc2;
324 {
325  int deltaoff;
326  cons *pctemp, *pc1, *pc2=NIL;
327 
328  for (pc1 = opc1; pc1 != NIL; pc1 = CDR(pc1)) {
329  for (pc2 = opc2; pc2 != NIL; pc2 = CDR(pc2)) {
330  if (gen_eq((atom_equivar(ATOM(CAR(pc1)))),
331  (atom_equivar(ATOM(CAR(pc2)))))) {
332  break;
333  }
334  }
335  if (pc2 != NIL)
336  break;
337  }
338 
339  if (pc1 == NIL || pc2 == NIL)
340  FatalError("MergeTwoChains", "empty intersection\n");
341 
342  deltaoff = atom_equioff(ATOM(CAR(pc1)))-atom_equioff(ATOM(CAR(pc2)));
343 
344  if (deltaoff < 0) {
345  pctemp = opc2; opc2 = opc1; opc1 = pctemp;
346  }
347  pc1 = opc1;
348  pc2 = opc2;
349 
350  while (1) {
351  atom_equioff(ATOM(CAR(pc2))) += abs(deltaoff);
352  if (CDR(pc2) == NIL)
353  break;
354  pc2 = CDR(pc2);
355  }
356 
357  CDR(pc2) = pc1;
358  return(opc2);
359 }
360 ␌
361 /* two debugging functions, just in case ... */
362 
363 void
365 equivalences e;
366 {
367  cons *pcc;
368 
369  if(ENDP(equivalences_chains(e))) {
370  ifdebug(9) {
371  (void) fprintf(stderr, "Empty list of equivalence chains\n");
372  }
373  }
374  else {
375  for (pcc = equivalences_chains(e); pcc != NIL; pcc = CDR(pcc)) {
376  PrintChain(CHAIN(CAR(pcc)));
377  }
378  }
379 }
380 
381 void
383 chain c;
384 {
385  cons *pca;
386  atom a;
387 
388  ifdebug(9) {
389  pips_debug(9, "Begin: ");
390 
391  for (pca = chain_atoms(c); pca != NIL; pca = CDR(pca)) {
392  a = ATOM(CAR(pca));
393 
394  (void) fprintf(stderr, "(%s,%td) ; ",
396  }
397  (void) fprintf(stderr, "\n");
398  pips_debug(9, "End\n");
399  }
400 }
401 ␌
402 bool
404 {
405  equivalences equiv = TempoEquivSet;
406  list pcc;
407  bool is_in_p = false;
408 
409  /* Apparently, TempoEquivSet stays undefined when there are no equivalences */
410  if(!equivalences_undefined_p(equiv)) {
411  for (pcc = equivalences_chains(equiv); !ENDP(pcc) && !is_in_p; POP(pcc)) {
412  is_in_p = entity_in_equivalence_chain_p(e, CHAIN(CAR(pcc)));
413  }
414  }
415 
416  return is_in_p;
417 }
418 
419 bool
421 {
422  cons *pca;
423  atom a;
424  bool is_in_p = false;
425 
426  pips_debug(9, "Begin for entity %s \n", entity_name(e));
427 
428  for (pca = chain_atoms(c); !ENDP(pca) && !is_in_p; POP(pca)) {
429  a = ATOM(CAR(pca));
430 
431  is_in_p = (atom_equivar(a) == e);
432  }
433  pips_debug(9, "End\n");
434  return is_in_p;
435 }
436 ␌
437 /* This function computes an address for every variable. Three different
438  * cases are adressed: variables in user-declared commons, static variables
439  * and dynamic variables.
440  *
441  * Variables may have:
442  *
443  * - an undefined storage because they have the default dynamic storage
444  * or because they should inherit their storage from an equivalence
445  * chain. The inherited storage can be "user-declared common", "static" or
446  * even "dynamic".
447  *
448  * - a user-declared common storage. The offsets of these variables can
449  * be computed from the common partial layout. Offsets for variables
450  * equivalenced to one of them are derived and the layouts are updated.
451  *
452  * - a static storage: the offset must be unknown on entrance in this
453  * function.
454  *
455  * - a dynamic storage: this is forbidden because there is no DYNAMIC
456  * declaration. The Fortran programmer does not have a way to enforce
457  * explictly a dynamic storage. All dynamic variables have an undefined
458  * storage upon entrance.
459  *
460  * - a non-ram storage: this obviously is forbidden.
461  *
462  * All variables explictly declared in a common have a storage fully
463  * defined within this common (see update_common_layout() which must have
464  * been called before entering ComputeAddresses()). If such a variable
465  * occurs in an equivalence chain, all other variables of this chain will
466  * have an address in this common. The exact address depends on the offset
467  * stored in the atom.
468  *
469  * The variables allocated in the static and dynamic areas are handled
470  * differently from variables explicitly declared in a common because the
471  * programmer does not have a direct control over the offset as within a
472  * common declaration. An arbitrary allocation is performed. The same
473  * kind of processing is done for chains containing a static variable or
474  * only dynamic variables (i.e. each variable in the chain has an
475  * undefined storage).
476  *
477  * Static variables obviously have a partially defined storage since they
478  * are recognized as static.
479  *
480  * Each equivalence chain should be either attached to a user-declared
481  * common or to the static area or to the dynamic area of the current
482  * module.
483  *
484  * Static and dynamic chains are processed in a similar way. The size of
485  * each chain is computed and the space for the chain is allocated in the
486  * corresponding area. As for user-declared commons (but with no good
487  * reason?) only one representant of each chain is added to the layouts of
488  * the area.
489  *
490  * When the processing of equivalenced variables is completed,
491  * non-equivalenced static or dynamic (i.e. variables with undefined
492  * storage) variables are allocated.
493  *
494  * Finally equivalenced variables are appended to the layouts of the
495  * static and dynamic areas. This makes update_common_layout() unapplicable.
496  *
497  * As a result, variables declared in the static and dynamic area are not
498  * ordered by increasing offsets.
499  *
500  */
501 
502 void
504 {
505  cons *pcc, *pca, *pcv;
506  entity sc;
507  int lc, l, ac;
508  list dynamic_aliases = NIL;
509  list static_aliases = NIL;
510 
511  pips_debug(1, "Begin\n");
512 
514  for (pcc = equivalences_chains(FinalEquivSet); pcc != NIL;
515  pcc = CDR(pcc)) {
516  chain c = CHAIN(CAR(pcc));
517 
518  /* the default section for variables with no address is the dynamic
519  * area. */
520  sc = DynamicArea;
521  lc = 0;
522  ac = 0;
523 
524  /* Try to locate the area for the current equivalence chain.
525  * Only one variable should have a well-defined storage.
526  * Or no variables have one because the equivalence chain
527  * is located in the dynamic area.
528  */
529  for (pca = chain_atoms(c); pca != NIL; pca = CDR(pca)) {
530  entity e;
531  int o;
532 
533  e = atom_equivar(ATOM(CAR(pca)));
534  o = atom_equioff(ATOM(CAR(pca)));
535 
536  /* Compute the total size of the chain. This only should
537  be used for the static and dynamic areas */
538  /* FI: I do not understand why this assignment is not better guarded.
539  * Maybe, because lc's later use *is* guarded.
540  */
541  if ((l = SafeSizeOfArray(e)) > lc-o)
542  lc = l+o;
543 
544  if (entity_storage(e) != storage_undefined) {
545  if (storage_ram_p(entity_storage(e))) {
547 
548  if (sc != ram_section(r)) {
549  if (sc == DynamicArea) {
550  sc = ram_section(r);
551  ac = ram_offset(r)-o;
552  }
553  else if (sc == StaticArea) {
554  /* A variable may be located in a static area because
555  * of a SAVE (?) or a DATA statement and be equivalenced
556  * with a variable in a common.
557  */
558  pips_assert("ComputeAddresses", ram_section(r) != DynamicArea);
559  sc = ram_section(r);
560  ac = ram_offset(r)-o;
561  }
562  else if(ram_section(r) == StaticArea) {
563  /* Same as above but in a different order */
564  /* Let's hope this is due to a DATA and not to a SAVE */
565  ram_section(r) = sc;
566  }
567  else {
568  user_warning("ComputeAddresses",
569  "Incompatible default area %s and "
570  "area %s requested by equivalence for %s\n",
572  entity_local_name(e));
573  ParserError("ComputeAddresses",
574  "incompatible areas\n");
575  }
576  }
577  }
578  else
579  FatalError("ComputeAddresses", "non ram storage\n");
580  }
581  }
582 
583  /* Compute the offset and set the storage information for each
584  * variable in the equivalence chain that has no storage yet.
585  */
586  for (pca = chain_atoms(c); pca != NIL; pca = CDR(pca)) {
587  entity e;
588  int o, adr;
589 
590  e = atom_equivar(ATOM(CAR(pca)));
591  o = atom_equioff(ATOM(CAR(pca)));
592 
593  if (sc == DynamicArea || sc == StaticArea) {
594  ac = area_size(type_area(entity_type(sc)));
595  }
596 
597  /* check that the offset is positive */
598  if ((adr = ac+o) < 0) {
599  user_warning("ComputeAddresses", "Offset %d for %s in common /%s/.\n",
600  ac+o, entity_local_name(e), entity_local_name(sc));
601  ParserError("ComputeAddresses",
602  "Attempt to extend common backwards. "
603  "Have you checked the code with a Fortran compiler?\n");
604  }
605 
606  if ((entity_storage(e)) != storage_undefined) {
607  ram r;
608  r = storage_ram(entity_storage(e));
609 
610  if (adr != ram_offset(r)) {
612  ram_offset(r) = adr;
613  if(sc == StaticArea && pca != chain_atoms(c)) {
614  /* Static aliases cannot be added right away because
615  * implicitly declared static variables still have to
616  * be added whereas aliased variables are assumed to be
617  * put behind in the layout list. Except the first one.
618  *
619  * Well, I'm not so sure!
620  */
621  static_aliases = arguments_add_entity(static_aliases, e);
622  }
623  else {
624  area a = type_area(entity_type(sc));
625 
627  CONS(ENTITY, e, NIL));
628  }
629  }
630  else if(ram_offset(r)==UNKNOWN_RAM_OFFSET) {
631  ram_offset(r) = adr;
632  }
633  else {
634  user_warning("ComputeAddresses",
635  "Two conflicting offsets for %s: %d and %d\n",
636  entity_local_name(e), adr, ram_offset(r));
637  ParserError("ComputeAddresses", "incompatible addresses\n");
638  }
639  }
640  }
641  else {
642  area a = type_area(entity_type(sc));
643 
644  entity_storage(e) =
647  sc, adr, NIL)));
648  /* Add e in sc'layout and check that sc's size
649  * does not have to be increased as for:
650  * COMMON /FOO/X
651  * REAL Y(100)
652  * EQUIVALENCE (X,Y)
653  */
654  pips_assert("Entity e is not yet in sc's layout",
656  if(sc == DynamicArea && pca != chain_atoms(c)) {
657  /* Dynamic aliases cannot be added right away because
658  * implicitly declared dynamic variables still have to
659  * be added whereas aliased variables are assumed to be
660  * put behind in the layout list. Except the first one.
661  */
662  dynamic_aliases = arguments_add_entity(dynamic_aliases, e);
663  }
664  else {
666  CONS(ENTITY, e, NIL));
667  }
668 
669  /* If sc really is a common, i.e. neither the *dynamic*
670  * nor the *static* area, check its size
671  */
672  if(top_level_entity_p(sc)) {
673  int s = common_to_size(sc);
674  int new_s = adr + SafeSizeOfArray(e);
675  if(s < new_s) {
676  (void) update_common_to_size(sc, new_s);
677  }
678  }
679  }
680  }
681 
682  if (sc == DynamicArea || sc == StaticArea)
683  area_size(type_area(entity_type(sc))) += lc;
684 
685  }
686  }
687 
688  /* Varying size arrays must be stack allocated. This is an implicit
689  extension that is not compatible with EQUIVALENCE */
690 
691  if(get_bool_property("PARSER_ACCEPT_ANSI_EXTENSIONS")) {
692  pips_debug(2, "Process stack variables\n");
693 
695  pcv = CDR(pcv)) {
696  entity a = ENTITY(CAR(pcv));
697  int s;
698 
699  /* This test will fail for stack allocatable varying length
700  character strings because of function SizeOfElements() which
701  cannot indicate failure. Let's wait for the problem... */
704  && !SizeOfArray(a, &s)) {
705  /* Try to reallocate in stack area */
706  s = 0;
710  StackArea,
712  NIL));
713 
714  pips_debug(8, "Variable %s allocated in stack\n", entity_local_name(a));
715  }
716  else if(storage_formal_p(entity_storage(a))) {
717  /* Formal parameters can have varying sizes */
718  ;
719  }
720  else if(storage_ram_p(entity_storage(a))) {
722 
723  if(sec==DynamicArea) {
725  pips_debug(8, "Variable %s reallocated in stack\n", entity_local_name(a));
726  }
727  else if(sec==HeapArea) {
728  /* Allocatable arrays can have varying sizes */
729  ;
730  }
731  else {
732  /* Could be declared explicitly or implicitly STATIC or be
733  EQUIVALENCEd with such a variable. It could be declared
734  in a COMMON. */
735  pips_user_warning("Variable %s with varying dimension cannot be reallocated"
736  " in stack because it has already been allocated in %s\n",
738  ParserError(__FUNCTION__, "Storage cannot be redefined to stack");
739  }
740  }
741  else {
742  pips_internal_error("Unexpected storage for entity %s",
743  entity_local_name(a));
744  }
745  }
746  else {
747  /* The array size is known at compile time. Allocate in synamic
748  area. */
749  ;
750  }
751  }
752  }
753 
754  /* All declared variables are scanned and stored in the dynamic area if their
755  * storage is still undefined or in the static area if their offsets are still
756  * unkown.
757  *
758  * This should be the case for all non-aliased static variables and most dynamic
759  * variables.
760  *
761  */
762 
763  pips_debug(2, "Process left-over dynamic variables\n");
764 
766  pcv = CDR(pcv)) {
767  entity e = ENTITY(CAR(pcv));
768 
769  if (entity_storage(e) == storage_undefined) {
770  /* area da = type_area(entity_type(DynamicArea)); */
771 
772  pips_debug(2, "Add dynamic non-aliased variable %s\n",
773  entity_local_name(e));
774 
775  entity_storage(e) =
778  DynamicArea,
780  e), NIL)));
781  /* area_layout(da) = gen_nconc(area_layout(da), CONS(ENTITY, e, NIL)); */
782  }
783  else if(storage_ram_p(entity_storage(e))) {
786  if(ram_section(r)==StaticArea) {
787  /* area sa = type_area(entity_type(StaticArea)); */
788 
789  pips_debug(2, "Add static non-aliased variable %s\n",
790  entity_local_name(e));
791 
793  /* area_layout(sa) = gen_nconc(area_layout(sa), CONS(ENTITY, e, NIL)); */
794  }
795  else if(ram_section(r)==HeapArea) {
797 
798  pips_debug(2,
799  "Ignore heap variable %s because its address cannot be computed\n",
800  entity_local_name(e));
801  area_layout(ha) = gen_nconc(area_layout(ha), CONS(ENTITY, e, NIL));
802  }
803  else {
804  /* Must be stack area */
806 
807  pips_debug(2,
808  "Ignore stack variable %s because its address cannot be computed\n",
809  entity_local_name(e));
810  area_layout(sa) = gen_nconc(area_layout(sa), CONS(ENTITY, e, NIL));
811  }
812  }
813  }
814  }
815 
816  /* Add aliased dynamic variables */
817  if(!ENDP(dynamic_aliases)) {
818  /* neither gen_concatenate() nor gen_append() are OK */
820 
821  ifdebug(2) {
822  pips_debug(2, "There are dynamic aliased variables:");
823  print_arguments(dynamic_aliases);
824  }
825 
826  pips_assert("aliased dynamic variables imply standard dynamic variables",
827  !ENDP(dynamics));
828  /* side effect on area_layout */
829  (void) gen_nconc(dynamics, dynamic_aliases);
830  }
831 
832  /* Add aliased static variables */
833  if(!ENDP(static_aliases)) {
834  /* neither gen_concatenate() nor gen_append() are OK */
836 
837  ifdebug(2) {
838  pips_debug(2, "There are static aliased variables:");
839  print_arguments(static_aliases);
840  }
841 
842  pips_assert("aliased static variables imply standard static variables",
843  !ENDP(statics));
844  /* side effect on area_layout */
845  (void) gen_nconc(statics, static_aliases);
846  }
847 
848  /* The sizes of the static and dynamic areas are now known */
853 
854  pips_debug(1, "End\n");
855 }
856 ␌
857 /* Initialize the shared fields of aliased variables */
858 void
860 {
861  pips_debug(8, "Begin\n");
862 
864  pips_debug(8, "No equivalence to process. End\n");
865  return;
866  }
867 
868  MAPL(pc, {
869  cons *shared = NIL;
870  chain c = CHAIN(CAR(pc));
871 
872  pips_debug(8, "Process an equivalence chain:\n");
873 
874  MAPL(pa, {
875  shared = gen_once(atom_equivar(ATOM(CAR(pa))), shared);
876  /* shared = CONS(ENTITY, atom_equivar(ATOM(CAR(pa))), shared); */
877  }, chain_atoms(c));
878 
879  pips_assert("SaveChains", !ENDP(shared));
880 
881  MAPL(pa, {
882  atom a = ATOM(CAR(pa));
883  entity e = atom_equivar(a);
884  storage se = entity_storage(e);
885  ram re = storage_ram(se);
886 
887  pips_debug(8, "\talias %s\n", entity_name(e));
888 
889  ram_shared(re) = gen_copy_seq(shared);
890 
891  }, chain_atoms(c));
892 
893  /* Check conflicting intializations */
894  MAPL(pa, {
895  atom a = ATOM(CAR(pa));
896  entity e = atom_equivar(a);
897  storage se = entity_storage(e);
898  ram re = storage_ram(se);
899  list lce = ram_shared(re);
900 
903  pips_debug(8,
904  "\tCheck initalization consistency for %s\n",
905  entity_name(e));
906  MAP(ENTITY, ce, {
907  if(e!=ce && variable_entities_may_conflict_p(e, ce)) {
909  && !value_unknown_p(entity_initial(ce))) {
910  pips_user_warning("Overlapping initializations for %s and %s\n",
912  ParserError("SaveChains",
913  "ANSI extension: overlapping initializations\n");
914  }
915  }
916  }, lce);
917  }
918 
919  }, chain_atoms(c));
920 
922 
923  pips_debug(8, "End\n");
924 }
void free_equivalences(equivalences p)
chain make_chain(list a)
atom make_atom(entity a1, intptr_t a2)
equivalences make_equivalences(list a)
storage make_storage(enum storage_utype tag, void *val)
Definition: ri.c:2273
ram make_ram(entity a1, entity a2, intptr_t a3, list a4)
Definition: ri.c:1999
bool value_defined_p(value p)
Definition: ri.c:2797
bool entity_is_argument_p(entity e, cons *args)
Definition: arguments.c:150
cons * arguments_add_entity(cons *a, entity e)
Definition: arguments.c:85
entity DynamicArea
These global variables are declared in ri-util/util.c.
Definition: area.c:57
entity HeapArea
Definition: area.c:59
entity StaticArea
Definition: area.c:58
entity StackArea
Definition: area.c:60
int SafeSizeOfArray(entity a)
This function should not be used outside of the syntax library because it depends on ParserError().
Definition: declaration.c:83
void update_common_to_size(entity a, size_t new_size)
Definition: declaration.c:1010
int OffsetOfReference(reference r)
This function computes the numerical offset of a variable element from the begining of the variable.
Definition: declaration.c:1565
size_t common_to_size(entity a)
Definition: declaration.c:990
atom MakeEquivAtom(syntax s)
this function creates an atom of an equivalence chain.
Definition: equivalence.c:89
#define EQUIADD
lint
Definition: equivalence.c:54
static equivalences TempoEquivSet
external variables used by functions from equivalence.c
Definition: equivalence.c:59
void PrintChain(chain c)
Definition: equivalence.c:382
void SaveChains()
Initialize the shared fields of aliased variables.
Definition: equivalence.c:859
void StoreEquivChain(chain c)
This function is called when an equivalence chain has been completely parsed.
Definition: equivalence.c:176
void PrintChains(equivalences e)
two debugging functions, just in case ...
Definition: equivalence.c:364
#define EQUIMERGE
Definition: equivalence.c:55
cons * MergeTwoChains(cons *opc1, cons *opc2)
this function merges two equivalence chains whose intersection is not empty, ie.
Definition: equivalence.c:322
bool entity_in_equivalence_chain_p(entity e, chain c)
Definition: equivalence.c:420
static equivalences FinalEquivSet
Definition: equivalence.c:60
int ChainIntersection(cons *opc1, cons *opc2)
this function returns true if the there is a variable that occurs in both atom lists.
Definition: equivalence.c:302
bool entity_in_equivalence_chains_p(entity e)
Definition: equivalence.c:403
void SetChains()
initialize chains before each call to the parser
Definition: equivalence.c:76
void ResetChains()
undefine chains between two successives calls to parser
Definition: equivalence.c:65
char vcid_syntax_equivalence[]
Support and resolve equivalence chains.
Definition: equivalence.c:33
void ComputeEquivalences()
This function merges all the equivalence chains to take into account equivalences due to transitivity...
Definition: equivalence.c:215
int AddOrMergeChain(chain ct)
this function adds a chain ct to the set of equivalences.
Definition: equivalence.c:269
void ComputeAddresses()
This function computes an address for every variable.
Definition: equivalence.c:503
bool get_bool_property(const string)
FC 2015-07-20: yuk, moved out to prevent an include cycle dependency include "properties....
entity get_current_module_entity(void)
Get the entity of the current module.
Definition: static.c:85
#define ENDP(l)
Test if a list is empty.
Definition: newgen_list.h:66
#define POP(l)
Modify a list pointer to point on the next element of the list.
Definition: newgen_list.h:59
#define NIL
The empty list (nil in Lisp)
Definition: newgen_list.h:47
list gen_once(const void *vo, list l)
Prepend an item to a list only if it is not already in the list.
Definition: list.c:722
list gen_copy_seq(list l)
Copy a list structure.
Definition: list.c:501
#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
#define CDR(pcons)
Get the list less its first element.
Definition: newgen_list.h:111
#define MAPL(_map_list_cp, _code, _l)
Apply some code on the addresses of all the elements of a list.
Definition: newgen_list.h:203
#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
bool gen_eq(const void *obj1, const void *obj2)
Definition: list.c:111
bool expression_constant_p(expression)
HPFC module by Fabien COELHO.
Definition: expression.c:2453
#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 user_warning(fn,...)
Definition: misc-local.h:262
void print_arguments(list args)
Definition: naming.c:228
#define equivalences_undefined
#define ATOM(x)
newgen_equivalences_domain_defined
#define atom_equioff(x)
#define CHAIN(x)
CHAIN.
#define equivalences_undefined_p(x)
#define chain_atoms(x)
#define atom_equivar(x)
#define equivalences_chains(x)
#define SUBSTRING_FUNCTION_NAME
#define UNKNOWN_RAM_OFFSET
int current_offset_of_area(entity a, entity v)
Definition: area.c:174
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
const char * module_local_name(entity e)
Returns the module local user name.
Definition: entity.c:582
code EntityCode(entity e)
this function checks that e has an initial value code.
Definition: entity.c:301
bool top_level_entity_p(entity e)
Check if the scope of entity e is global.
Definition: entity.c:1130
int expression_to_int(expression exp)
================================================================
Definition: expression.c:2205
bool SizeOfArray(entity, int *)
This function computes the total size of a variable in bytes, ie.
Definition: size.c:87
bool array_with_numerical_bounds_p(entity)
bool array_with_numerical_bounds_p(entity a) input : an array entity output : true if all bounds of a...
Definition: variable.c:1266
bool variable_entities_may_conflict_p(entity, entity)
Definition: size.c:689
bool formal_parameter_p(entity)
Definition: variable.c:1489
#define syntax_reference_p(x)
Definition: ri.h:2728
#define storage_formal_p(x)
Definition: ri.h:2522
#define area_size(x)
Definition: ri.h:544
#define syntax_reference(x)
Definition: ri.h:2730
#define reference_undefined
Definition: ri.h:2302
#define call_function(x)
Definition: ri.h:709
#define reference_variable(x)
Definition: ri.h:2326
#define ENTITY(x)
ENTITY.
Definition: ri.h:2755
#define syntax_call_p(x)
Definition: ri.h:2734
#define value_unknown_p(x)
Definition: ri.h:3077
#define entity_storage(x)
Definition: ri.h:2794
#define code_declarations(x)
Definition: ri.h:784
#define storage_ram_p(x)
Definition: ri.h:2519
#define ram_section(x)
Definition: ri.h:2249
#define EXPRESSION(x)
EXPRESSION.
Definition: ri.h:1217
@ is_storage_ram
Definition: ri.h:2492
#define entity_name(x)
Definition: ri.h:2790
#define area_layout(x)
Definition: ri.h:546
#define syntax_call(x)
Definition: ri.h:2736
#define type_area(x)
Definition: ri.h:2946
#define storage_ram(x)
Definition: ri.h:2521
#define call_arguments(x)
Definition: ri.h:711
#define entity_type(x)
Definition: ri.h:2792
#define ram_shared(x)
Definition: ri.h:2253
#define expression_syntax(x)
Definition: ri.h:1247
#define type_variable_p(x)
Definition: ri.h:2947
#define storage_undefined_p(x)
Definition: ri.h:2477
#define ram_offset(x)
Definition: ri.h:2251
#define storage_undefined
Definition: ri.h:2476
#define entity_initial(x)
Definition: ri.h:2796
int fprintf()
test sc_min : ce test s'appelle par : programme fichier1.data fichier2.data ...
#define ifdebug(n)
Definition: sg.c:47
The structure used to build lists in NewGen.
Definition: newgen_list.h:41
#define FatalError(f, m)
Definition: syntax-local.h:56
#define abs(v)
Definition: syntax-local.h:48
bool ParserError(const char *f, const char *m)
Definition: parser.c:116