PIPS
equivalence.c File Reference
#include <stdio.h>
#include "genC.h"
#include "linear.h"
#include "ri.h"
#include "ri-util.h"
#include "workspace-util.h"
#include "parser_private.h"
#include "properties.h"
#include "misc.h"
#include "syntax.h"
+ Include dependency graph for equivalence.c:

Go to the source code of this file.

Macros

#define EQUIADD   0
 lint More...
 
#define EQUIMERGE   1
 

Functions

void ResetChains ()
 undefine chains between two successives calls to parser More...
 
void SetChains ()
 initialize chains before each call to the parser More...
 
atom MakeEquivAtom (syntax s)
 this function creates an atom of an equivalence chain. More...
 
void StoreEquivChain (chain c)
 This function is called when an equivalence chain has been completely parsed. More...
 
void ComputeEquivalences ()
 This function merges all the equivalence chains to take into account equivalences due to transitivity. More...
 
int AddOrMergeChain (chain ct)
 this function adds a chain ct to the set of equivalences. More...
 
int ChainIntersection (cons *opc1, cons *opc2)
 this function returns true if the there is a variable that occurs in both atom lists. More...
 
consMergeTwoChains (cons *opc1, cons *opc2)
 this function merges two equivalence chains whose intersection is not empty, ie. More...
 
void PrintChains (equivalences e)
 two debugging functions, just in case ... More...
 
void PrintChain (chain c)
 
bool entity_in_equivalence_chains_p (entity e)
 
bool entity_in_equivalence_chain_p (entity e, chain c)
 
void ComputeAddresses ()
 This function computes an address for every variable. More...
 
void SaveChains ()
 Initialize the shared fields of aliased variables. More...
 

Variables

char vcid_syntax_equivalence [] = "$Id: equivalence.c 23065 2016-03-02 09:05:50Z coelho $"
 Support and resolve equivalence chains. More...
 
static equivalences TempoEquivSet = equivalences_undefined
 external variables used by functions from equivalence.c More...
 
static equivalences FinalEquivSet = equivalences_undefined
 

Macro Definition Documentation

◆ EQUIADD

#define EQUIADD   0

lint

equivalence.c: contains EQUIVALENCE related routines

Definition at line 54 of file equivalence.c.

◆ EQUIMERGE

#define EQUIMERGE   1

Definition at line 55 of file equivalence.c.

Function Documentation

◆ AddOrMergeChain()

int AddOrMergeChain ( chain  ct)

this function adds a chain ct to the set of equivalences.

if the intersection with all other chains is empty, ct is just added to the set. Otherwise ct is merged with the chain that intersects ct.

Parameters
ctt

Definition at line 269 of file equivalence.c.

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 }
chain make_chain(list a)
#define EQUIADD
lint
Definition: equivalence.c:54
#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
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
#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 CDR(pcons)
Get the list less its first element.
Definition: newgen_list.h:111
#define CHAIN(x)
CHAIN.
#define chain_atoms(x)
#define equivalences_chains(x)
The structure used to build lists in NewGen.
Definition: newgen_list.h:41

References CAR, CDR, CHAIN, chain_atoms, ChainIntersection(), CONS, EQUIADD, EQUIMERGE, equivalences_chains, FinalEquivSet, make_chain(), MergeTwoChains(), and NIL.

Referenced by ComputeEquivalences().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ ChainIntersection()

int ChainIntersection ( cons opc1,
cons opc2 
)

this function returns true if the there is a variable that occurs in both atom lists.

Parameters
opc1pc1
opc2pc2

Definition at line 302 of file equivalence.c.

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 }
bool gen_eq(const void *obj1, const void *obj2)
Definition: list.c:111
#define ATOM(x)
newgen_equivalences_domain_defined
#define atom_equivar(x)

References ATOM, atom_equivar, CAR, CDR, gen_eq(), and NIL.

Referenced by AddOrMergeChain().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ ComputeAddresses()

void ComputeAddresses ( void  )

This function computes an address for every variable.

Three different cases are adressed: variables in user-declared commons, static variables and dynamic variables.

Variables may have:

  • an undefined storage because they have the default dynamic storage or because they should inherit their storage from an equivalence chain. The inherited storage can be "user-declared common", "static" or even "dynamic".
  • a user-declared common storage. The offsets of these variables can be computed from the common partial layout. Offsets for variables equivalenced to one of them are derived and the layouts are updated.
  • a static storage: the offset must be unknown on entrance in this function.
  • a dynamic storage: this is forbidden because there is no DYNAMIC declaration. The Fortran programmer does not have a way to enforce explictly a dynamic storage. All dynamic variables have an undefined storage upon entrance.
  • a non-ram storage: this obviously is forbidden.

All variables explictly declared in a common have a storage fully defined within this common (see update_common_layout() which must have been called before entering ComputeAddresses()). If such a variable occurs in an equivalence chain, all other variables of this chain will have an address in this common. The exact address depends on the offset stored in the atom.

The variables allocated in the static and dynamic areas are handled differently from variables explicitly declared in a common because the programmer does not have a direct control over the offset as within a common declaration. An arbitrary allocation is performed. The same kind of processing is done for chains containing a static variable or only dynamic variables (i.e. each variable in the chain has an undefined storage).

Static variables obviously have a partially defined storage since they are recognized as static.

Each equivalence chain should be either attached to a user-declared common or to the static area or to the dynamic area of the current module.

Static and dynamic chains are processed in a similar way. The size of each chain is computed and the space for the chain is allocated in the corresponding area. As for user-declared commons (but with no good reason?) only one representant of each chain is added to the layouts of the area.

When the processing of equivalenced variables is completed, non-equivalenced static or dynamic (i.e. variables with undefined storage) variables are allocated.

Finally equivalenced variables are appended to the layouts of the static and dynamic areas. This makes update_common_layout() unapplicable.

As a result, variables declared in the static and dynamic area are not ordered by increasing offsets.

the default section for variables with no address is the dynamic area.

Try to locate the area for the current equivalence chain. Only one variable should have a well-defined storage. Or no variables have one because the equivalence chain is located in the dynamic area.

Compute the total size of the chain. This only should be used for the static and dynamic areas

FI: I do not understand why this assignment is not better guarded. Maybe, because lc's later use is guarded.

A variable may be located in a static area because of a SAVE (?) or a DATA statement and be equivalenced with a variable in a common.

Same as above but in a different order

Let's hope this is due to a DATA and not to a SAVE

Compute the offset and set the storage information for each variable in the equivalence chain that has no storage yet.

check that the offset is positive

Static aliases cannot be added right away because implicitly declared static variables still have to be added whereas aliased variables are assumed to be put behind in the layout list. Except the first one.

Well, I'm not so sure!

Add e in sc'layout and check that sc's size does not have to be increased as for: COMMON /FOO/X REAL Y(100) EQUIVALENCE (X,Y)

Dynamic aliases cannot be added right away because implicitly declared dynamic variables still have to be added whereas aliased variables are assumed to be put behind in the layout list. Except the first one.

If sc really is a common, i.e. neither the dynamic nor the static area, check its size

Varying size arrays must be stack allocated. This is an implicit extension that is not compatible with EQUIVALENCE

This test will fail for stack allocatable varying length character strings because of function SizeOfElements() which cannot indicate failure. Let's wait for the problem...

Try to reallocate in stack area

Formal parameters can have varying sizes

Allocatable arrays can have varying sizes

Could be declared explicitly or implicitly STATIC or be EQUIVALENCEd with such a variable. It could be declared in a COMMON.

The array size is known at compile time. Allocate in synamic area.

All declared variables are scanned and stored in the dynamic area if their storage is still undefined or in the static area if their offsets are still unkown.

This should be the case for all non-aliased static variables and most dynamic variables.

area da = type_area(entity_type(DynamicArea));

area_layout(da) = gen_nconc(area_layout(da), CONS(ENTITY, e, NIL));

area sa = type_area(entity_type(StaticArea));

area_layout(sa) = gen_nconc(area_layout(sa), CONS(ENTITY, e, NIL));

Must be stack area

Add aliased dynamic variables

neither gen_concatenate() nor gen_append() are OK

side effect on area_layout

Add aliased static variables

neither gen_concatenate() nor gen_append() are OK

side effect on area_layout

The sizes of the static and dynamic areas are now known

Definition at line 503 of file equivalence.c.

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 }
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 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
size_t common_to_size(entity a)
Definition: declaration.c:990
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
list gen_nconc(list cp1, list cp2)
physically concatenates CP1 and CP2 but do not duplicates the elements
Definition: list.c:344
#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_equioff(x)
#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
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
bool SizeOfArray(entity, int *)
This function computes the total size of a variable in bytes, ie.
Definition: size.c:87
#define storage_formal_p(x)
Definition: ri.h:2522
#define area_size(x)
Definition: ri.h:544
#define ENTITY(x)
ENTITY.
Definition: ri.h:2755
#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
@ is_storage_ram
Definition: ri.h:2492
#define entity_name(x)
Definition: ri.h:2790
#define area_layout(x)
Definition: ri.h:546
#define type_area(x)
Definition: ri.h:2946
#define storage_ram(x)
Definition: ri.h:2521
#define entity_type(x)
Definition: ri.h:2792
#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 ifdebug(n)
Definition: sg.c:47
#define FatalError(f, m)
Definition: syntax-local.h:56
bool ParserError(const char *f, const char *m)
Definition: parser.c:116

References area_layout, area_size, arguments_add_entity(), ATOM, atom_equioff, atom_equivar, CAR, CDR, CHAIN, chain_atoms, code_declarations, common_to_size(), CONS, current_offset_of_area(), DynamicArea, ENDP, ENTITY, entity_is_argument_p(), entity_local_name(), entity_name, entity_storage, entity_type, EntityCode(), equivalences_chains, equivalences_undefined, FatalError, FinalEquivSet, gen_nconc(), get_bool_property(), get_current_module_entity(), HeapArea, ifdebug, is_storage_ram, make_ram(), make_storage(), NIL, ParserError(), pips_assert, pips_debug, pips_internal_error, pips_user_warning, print_arguments(), ram_offset, ram_section, SafeSizeOfArray(), SizeOfArray(), StackArea, StaticArea, storage_formal_p, storage_ram, storage_ram_p, storage_undefined, storage_undefined_p, top_level_entity_p(), type_area, type_variable_p, UNKNOWN_RAM_OFFSET, update_common_to_size(), and user_warning.

Referenced by EndOfProcedure().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ ComputeEquivalences()

void ComputeEquivalences ( void  )

This function merges all the equivalence chains to take into account equivalences due to transitivity.

It is called at the end of the parsing.

They should be properly initialized by SetChains if (FinalEquivSet == equivalences_undefined) { FinalEquivSet = make_equivalences(NIL); }

Definition at line 215 of file equivalence.c.

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 }
void free_equivalences(equivalences p)
equivalences make_equivalences(list a)
static equivalences TempoEquivSet
external variables used by functions from equivalence.c
Definition: equivalence.c:59
void PrintChains(equivalences e)
two debugging functions, just in case ...
Definition: equivalence.c:364
int AddOrMergeChain(chain ct)
this function adds a chain ct to the set of equivalences.
Definition: equivalence.c:269

References AddOrMergeChain(), CAR, CDR, CHAIN, ENDP, EQUIMERGE, equivalences_chains, FinalEquivSet, free_equivalences(), make_equivalences(), NIL, pips_debug, PrintChains(), and TempoEquivSet.

Referenced by EndOfProcedure().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ entity_in_equivalence_chain_p()

bool entity_in_equivalence_chain_p ( entity  e,
chain  c 
)

Definition at line 420 of file equivalence.c.

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 }
#define POP(l)
Modify a list pointer to point on the next element of the list.
Definition: newgen_list.h:59

References ATOM, atom_equivar, CAR, chain_atoms, ENDP, entity_name, pips_debug, and POP.

Referenced by entity_in_equivalence_chains_p().

+ Here is the caller graph for this function:

◆ entity_in_equivalence_chains_p()

bool entity_in_equivalence_chains_p ( entity  e)

Apparently, TempoEquivSet stays undefined when there are no equivalences

Definition at line 403 of file equivalence.c.

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 }
bool entity_in_equivalence_chain_p(entity e, chain c)
Definition: equivalence.c:420
#define equivalences_undefined_p(x)

References CAR, CHAIN, ENDP, entity_in_equivalence_chain_p(), equivalences_chains, equivalences_undefined_p, POP, and TempoEquivSet.

Referenced by remove_ghost_variable_entities().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ MakeEquivAtom()

atom MakeEquivAtom ( syntax  s)

this function creates an atom of an equivalence chain.

s is a reference to a variable.

reference offset

substring offset

Equivalenced variables cannot be initialized by a DATA statement: false

In case, the entity is not of type variable, reject it.

In case an adjustable array which is not a formal parameter has been encountered, reject it.

what is the offset of this reference ?

Definition at line 89 of file equivalence.c.

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 }
atom make_atom(entity a1, intptr_t a2)
int OffsetOfReference(reference r)
This function computes the numerical offset of a variable element from the begining of the variable.
Definition: declaration.c:1565
bool expression_constant_p(expression)
HPFC module by Fabien COELHO.
Definition: expression.c:2453
#define SUBSTRING_FUNCTION_NAME
const char * module_local_name(entity e)
Returns the module local user name.
Definition: entity.c:582
int expression_to_int(expression exp)
================================================================
Definition: expression.c:2205
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 formal_parameter_p(entity)
Definition: variable.c:1489
#define syntax_reference_p(x)
Definition: ri.h:2728
#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 syntax_call_p(x)
Definition: ri.h:2734
#define EXPRESSION(x)
EXPRESSION.
Definition: ri.h:1217
#define syntax_call(x)
Definition: ri.h:2736
#define call_arguments(x)
Definition: ri.h:711
#define expression_syntax(x)
Definition: ri.h:1247

References array_with_numerical_bounds_p(), call_arguments, call_function, CAR, CDR, entity_local_name(), entity_storage, entity_type, EXPRESSION, expression_constant_p(), expression_syntax, expression_to_int(), formal_parameter_p(), make_atom(), module_local_name(), OffsetOfReference(), ParserError(), pips_assert, pips_debug, pips_user_warning, reference_undefined, reference_variable, storage_undefined_p, SUBSTRING_FUNCTION_NAME, syntax_call, syntax_call_p, syntax_reference, syntax_reference_p, and type_variable_p.

+ Here is the call graph for this function:

◆ MergeTwoChains()

cons* MergeTwoChains ( cons opc1,
cons opc2 
)

this function merges two equivalence chains whose intersection is not empty, ie.

one variable occurs in both chains.

Parameters
opc1pc1
opc2pc2

Definition at line 322 of file equivalence.c.

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 }
#define abs(v)
Definition: syntax-local.h:48

References abs, ATOM, atom_equioff, atom_equivar, CAR, CDR, FatalError, gen_eq(), and NIL.

Referenced by AddOrMergeChain().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ PrintChain()

void PrintChain ( chain  c)

Definition at line 382 of file equivalence.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 }
int fprintf()
test sc_min : ce test s'appelle par : programme fichier1.data fichier2.data ...

References ATOM, atom_equioff, atom_equivar, CAR, CDR, chain_atoms, entity_name, fprintf(), ifdebug, NIL, and pips_debug.

Referenced by PrintChains().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ PrintChains()

void PrintChains ( equivalences  e)

two debugging functions, just in case ...

Definition at line 364 of file equivalence.c.

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 }
void PrintChain(chain c)
Definition: equivalence.c:382

References CAR, CDR, CHAIN, ENDP, equivalences_chains, fprintf(), ifdebug, NIL, and PrintChain().

Referenced by ComputeEquivalences().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ ResetChains()

void ResetChains ( void  )

undefine chains between two successives calls to parser

Definition at line 65 of file equivalence.c.

References equivalences_undefined, FinalEquivSet, free_equivalences(), and TempoEquivSet.

Referenced by EndOfProcedure(), gfc2pips_namespace(), and ParserError().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ SaveChains()

void SaveChains ( void  )

Initialize the shared fields of aliased variables.

shared = CONS(ENTITY, atom_equivar(ATOM(CAR(pa))), shared);

Check conflicting intializations

Definition at line 859 of file equivalence.c.

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 }
bool value_defined_p(value p)
Definition: ri.c:2797
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 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 variable_entities_may_conflict_p(entity, entity)
Definition: size.c:689
#define value_unknown_p(x)
Definition: ri.h:3077
#define ram_shared(x)
Definition: ri.h:2253
#define entity_initial(x)
Definition: ri.h:2796

References ATOM, atom_equivar, CAR, CHAIN, chain_atoms, ENDP, ENTITY, entity_initial, entity_local_name(), entity_name, entity_storage, equivalences_chains, equivalences_undefined, FinalEquivSet, gen_copy_seq(), gen_once(), MAP, MAPL, NIL, ParserError(), pips_assert, pips_debug, pips_user_warning, ram_shared, storage_ram, value_defined_p(), value_unknown_p, and variable_entities_may_conflict_p().

Referenced by EndOfProcedure().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ SetChains()

void SetChains ( void  )

initialize chains before each call to the parser

Definition at line 76 of file equivalence.c.

77 {
78  pips_assert("TempoEquivSet is undefined", equivalences_undefined_p(TempoEquivSet));
79  pips_assert("FinalEquivSet is undefined", equivalences_undefined_p(FinalEquivSet));
82 }

References equivalences_undefined_p, FinalEquivSet, make_equivalences(), NIL, pips_assert, and TempoEquivSet.

Referenced by MakeCurrentFunction().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ StoreEquivChain()

void StoreEquivChain ( chain  c)

This function is called when an equivalence chain has been completely parsed.

It looks for the atom with the biggest offset, and then substracts this maximum offset from all atoms. The result is that each atom has its offset from the begining of the chain.

Definition at line 176 of file equivalence.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 }

References abs, ATOM, atom_equioff, CAR, CDR, CHAIN, chain_atoms, CONS, equivalences_chains, equivalences_undefined_p, NIL, pips_assert, pips_debug, and TempoEquivSet.

Variable Documentation

◆ FinalEquivSet

◆ TempoEquivSet

equivalences TempoEquivSet = equivalences_undefined
static

external variables used by functions from equivalence.c

Definition at line 59 of file equivalence.c.

Referenced by ComputeEquivalences(), entity_in_equivalence_chains_p(), ResetChains(), SetChains(), and StoreEquivChain().

◆ vcid_syntax_equivalence

char vcid_syntax_equivalence[] = "$Id: equivalence.c 23065 2016-03-02 09:05:50Z coelho $"

Support and resolve equivalence chains.

equivalence.c

Allocate addresses in commons and in the static area and in the dynamic area. The heap area is left aside.

Definition at line 33 of file equivalence.c.