1 /* equiv.c -- Implementation File (module.c template V1.0)
2 Copyright (C) 1995, 1996, 1997, 1998, 2003
3 Free Software Foundation, Inc.
4 Contributed by James Craig Burley.
6 This file is part of GNU Fortran.
8 GNU Fortran is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
13 GNU Fortran is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with GNU Fortran; see the file COPYING. If not, write to
20 the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
27 Handles the EQUIVALENCE relationships in a program unit.
32 #define FFEEQUIV_DEBUG 0
47 /* Externals defined here. */
50 /* Simple definitions and enumerations. */
53 /* Internal typedefs. */
56 /* Private include files. */
59 /* Internal structure definitions. */
61 struct _ffeequiv_list_
67 /* Static objects accessed by functions in this module. */
69 static struct _ffeequiv_list_ ffeequiv_list_
;
71 /* Static functions (internal). */
73 static void ffeequiv_destroy_ (ffeequiv eq
);
74 static void ffeequiv_layout_local_ (ffeequiv eq
);
75 static bool ffeequiv_offset_ (ffetargetOffset
*offset
, ffesymbol s
,
76 ffebld expr
, bool subtract
,
77 ffetargetOffset adjust
, bool no_precede
);
79 /* Internal macros. */
83 ffeequiv_destroy_ (ffeequiv victim
)
89 for (list
= victim
->list
; list
!= NULL
; list
= ffebld_trail (list
))
91 for (item
= ffebld_head (list
); item
!= NULL
; item
= ffebld_trail (item
))
95 expr
= ffebld_head (item
);
96 sym
= ffeequiv_symbol (expr
);
99 if (ffesymbol_equiv (sym
) != NULL
)
100 ffesymbol_set_equiv (sym
, NULL
);
103 ffeequiv_kill (victim
);
106 /* ffeequiv_layout_local_ -- Lay out storage for local equivalenced vars
109 ffeequiv_layout_local_(eq);
111 Makes a single master ffestorag object that contains all the vars
112 in the equivalence, and makes subordinate ffestorag objects for the
113 vars with the correct offsets.
115 The resulting var offsets are relative not necessarily to 0 -- the
116 are relative to the offset of the master area, which might be 0 or
117 negative, but should never be positive. */
120 ffeequiv_layout_local_ (ffeequiv eq
)
122 ffestorag st
; /* Equivalence storage area. */
123 ffebld list
; /* List of list of equivalences. */
124 ffebld item
; /* List of equivalences. */
125 ffebld root_exp
; /* Expression for root sym. */
126 ffestorag root_st
; /* Storage for root. */
127 ffesymbol root_sym
; /* Root itself. */
128 ffebld rooted_exp
; /* Expression for rooted sym in an eqlist. */
129 ffestorag rooted_st
; /* Storage for rooted. */
130 ffesymbol rooted_sym
; /* Rooted symbol itself. */
131 ffetargetOffset eqlist_offset
;/* Offset for eqlist from rooted sym. */
132 ffetargetAlign alignment
;
133 ffetargetAlign modulo
;
135 ffetargetOffset size
;
136 ffetargetOffset num_elements
;
137 bool new_storage
; /* Established new storage info. */
138 bool need_storage
; /* Have need for more storage info. */
143 if (ffeequiv_common (eq
) != NULL
)
144 { /* Put in common due to programmer error. */
145 ffeequiv_destroy_ (eq
);
149 /* Find the symbol for the first valid item in the list of lists, use that
150 as the root symbol. Doesn't matter if it won't end up at the beginning
151 of the list, though. */
154 fprintf (stderr
, "Equiv1:\n");
160 for (list
= ffeequiv_list (eq
);
162 list
= ffebld_trail (list
))
163 { /* For every equivalence list in the list of
165 for (item
= ffebld_head (list
);
167 item
= ffebld_trail (item
))
168 { /* For every equivalence item in the list */
169 ffetargetOffset ign
; /* Ignored. */
171 root_exp
= ffebld_head (item
);
172 root_sym
= ffeequiv_symbol (root_exp
);
173 if (root_sym
== NULL
)
174 continue; /* Ignore me. */
176 assert (ffesymbol_storage (root_sym
) == NULL
); /* No storage yet. */
178 if (!ffeequiv_offset_ (&ign
, root_sym
, root_exp
, FALSE
, 0, FALSE
))
180 /* We can't just eliminate this one symbol from the list
181 of candidates, because it might be the only one that
182 ties all these equivs together. So just destroy the
185 ffeequiv_destroy_ (eq
);
189 break; /* Use first valid eqv expr for root exp/sym. */
191 if (root_sym
!= NULL
)
195 if (root_sym
== NULL
)
197 ffeequiv_destroy_ (eq
);
203 fprintf (stderr
, " Root: `%s'\n", ffesymbol_text (root_sym
));
206 /* We've got work to do, so make the LOCAL storage object that'll hold all
207 the equivalenced vars inside it. */
209 st
= ffestorag_new (ffestorag_list_master ());
210 ffestorag_set_parent (st
, NULL
); /* Initializations happen here. */
211 ffestorag_set_init (st
, NULL
);
212 ffestorag_set_accretion (st
, NULL
);
213 ffestorag_set_offset (st
, 0); /* Assume equiv will be at root offset 0 for now. */
214 ffestorag_set_alignment (st
, 1);
215 ffestorag_set_modulo (st
, 0);
216 ffestorag_set_type (st
, FFESTORAG_typeLOCAL
);
217 ffestorag_set_basictype (st
, ffesymbol_basictype (root_sym
));
218 ffestorag_set_kindtype (st
, ffesymbol_kindtype (root_sym
));
219 ffestorag_set_typesymbol (st
, root_sym
);
220 ffestorag_set_is_save (st
, ffeequiv_is_save (eq
));
221 if (ffesymbol_is_save (root_sym
))
222 ffestorag_update_save (st
);
223 ffestorag_set_is_init (st
, ffeequiv_is_init (eq
));
224 if (ffesymbol_is_init (root_sym
))
225 ffestorag_update_init (st
);
226 ffestorag_set_symbol (st
, root_sym
); /* Assume this will be the root until
227 we know better (used only to generate
228 the internal name for the aggregate area,
229 e.g. for debugging). */
231 /* Make the EQUIV storage object for the root symbol. */
233 if (ffesymbol_rank (root_sym
) == 0)
236 num_elements
= ffebld_constant_integerdefault (ffebld_conter
237 (ffesymbol_arraysize (root_sym
)));
238 ffetarget_layout (ffesymbol_text (root_sym
), &alignment
, &modulo
, &size
,
239 ffesymbol_basictype (root_sym
), ffesymbol_kindtype (root_sym
),
240 ffesymbol_size (root_sym
), num_elements
);
241 ffestorag_set_size (st
, size
); /* Set initial size of aggregate area. */
243 pad
= ffetarget_align (ffestorag_ptr_to_alignment (st
),
244 ffestorag_ptr_to_modulo (st
), 0, alignment
,
248 root_st
= ffestorag_new (ffestorag_list_equivs (st
));
249 ffestorag_set_parent (root_st
, st
); /* Initializations happen there. */
250 ffestorag_set_init (root_st
, NULL
);
251 ffestorag_set_accretion (root_st
, NULL
);
252 ffestorag_set_symbol (root_st
, root_sym
);
253 ffestorag_set_size (root_st
, size
);
254 ffestorag_set_offset (root_st
, 0); /* Will not change; always 0 relative to itself! */
255 ffestorag_set_alignment (root_st
, alignment
);
256 ffestorag_set_modulo (root_st
, modulo
);
257 ffestorag_set_type (root_st
, FFESTORAG_typeEQUIV
);
258 ffestorag_set_basictype (root_st
, ffesymbol_basictype (root_sym
));
259 ffestorag_set_kindtype (root_st
, ffesymbol_kindtype (root_sym
));
260 ffestorag_set_typesymbol (root_st
, root_sym
);
261 ffestorag_set_is_save (root_st
, FALSE
); /* Assume FALSE, then... */
262 if (ffestorag_is_save (st
)) /* ...update to TRUE if needed. */
263 ffestorag_update_save (root_st
);
264 ffestorag_set_is_init (root_st
, FALSE
); /* Assume FALSE, then... */
265 if (ffestorag_is_init (st
)) /* ...update to TRUE if needed. */
266 ffestorag_update_init (root_st
);
267 ffesymbol_set_storage (root_sym
, root_st
);
268 ffesymbol_signal_unreported (root_sym
);
269 init
= ffesymbol_is_init (root_sym
);
271 /* Now that we know the root (offset=0) symbol, revisit all the lists and
272 do the actual storage allocation. Keep doing this until we've gone
273 through them all without making any new storage objects. */
278 need_storage
= FALSE
;
279 for (list
= ffeequiv_list (eq
);
281 list
= ffebld_trail (list
))
282 { /* For every equivalence list in the list of
284 /* Now find a "rooted" symbol in this list. That is, find the
285 first item we can that is valid and whose symbol already
286 has a storage area, because that means we know where it
287 belongs in the equivalence area and can then allocate the
288 rest of the items in the list accordingly. */
294 for (item
= ffebld_head (list
);
296 item
= ffebld_trail (item
))
297 { /* For every equivalence item in the list */
298 rooted_exp
= ffebld_head (item
);
299 rooted_sym
= ffeequiv_symbol (rooted_exp
);
300 if ((rooted_sym
== NULL
)
301 || ((rooted_st
= ffesymbol_storage (rooted_sym
)) == NULL
))
304 continue; /* Ignore me. */
307 need_storage
= TRUE
; /* Somebody is likely to need
311 fprintf (stderr
, " Rooted: `%s' at %" ffetargetOffset_f
"d\n",
312 ffesymbol_text (rooted_sym
),
313 ffestorag_offset (rooted_st
));
316 /* The offset of this symbol from the equiv's root symbol
317 is already known, and the size of this symbol is already
318 incorporated in the size of the equiv's aggregate area.
319 What we now determine is the offset of this equivalence
320 _list_ from the equiv's root symbol.
322 For example, if we know that A is at offset 16 from the
323 root symbol, given EQUIVALENCE (B(24),A(2)), we're looking
324 at A(2), meaning that the offset for this equivalence list
325 is 20 (4 bytes beyond the beginning of A, assuming typical
326 array types, dimensions, and type info). */
328 if (!ffeequiv_offset_ (&eqlist_offset
, rooted_sym
, rooted_exp
, FALSE
,
329 ffestorag_offset (rooted_st
), FALSE
))
331 { /* Can't use this one. */
332 ffesymbol_set_equiv (rooted_sym
, NULL
);/* Equiv area slated for
335 continue; /* Something's wrong with eqv expr, try another. */
339 fprintf (stderr
, " Eqlist offset: %" ffetargetOffset_f
"d\n",
346 /* If no rooted symbol, it means this list has no roots -- yet.
347 So, forget this list this time around, but we'll get back
348 to it after the outer loop iterates at least one more time,
349 and, ultimately, it will have a root. */
351 if (rooted_sym
== NULL
)
354 fprintf (stderr
, "No roots.\n");
359 /* We now have a rooted symbol/expr and the offset of this equivalence
360 list from the root symbol. The other expressions in this
361 list all identify an initial storage unit that must have the
364 for (item
= ffebld_head (list
);
366 item
= ffebld_trail (item
))
367 { /* For every equivalence item in the list */
368 ffebld item_exp
; /* Expression for equivalence. */
369 ffestorag item_st
; /* Storage for var. */
370 ffesymbol item_sym
; /* Var itself. */
371 ffetargetOffset item_offset
; /* Offset for var from root. */
372 ffetargetOffset new_size
;
374 item_exp
= ffebld_head (item
);
375 item_sym
= ffeequiv_symbol (item_exp
);
376 if ((item_sym
== NULL
)
377 || (ffesymbol_equiv (item_sym
) == NULL
))
378 continue; /* Ignore me. */
380 if (item_sym
== rooted_sym
)
381 continue; /* Rooted sym already set up. */
383 if (!ffeequiv_offset_ (&item_offset
, item_sym
, item_exp
, TRUE
,
384 eqlist_offset
, FALSE
))
386 ffesymbol_set_equiv (item_sym
, NULL
); /* Don't bother with me anymore. */
391 fprintf (stderr
, " Item `%s' at %" ffetargetOffset_f
"d",
392 ffesymbol_text (item_sym
), item_offset
);
395 if (ffesymbol_rank (item_sym
) == 0)
398 num_elements
= ffebld_constant_integerdefault (ffebld_conter
399 (ffesymbol_arraysize (item_sym
)));
400 ffetarget_layout (ffesymbol_text (item_sym
), &alignment
, &modulo
,
401 &size
, ffesymbol_basictype (item_sym
),
402 ffesymbol_kindtype (item_sym
), ffesymbol_size (item_sym
),
404 pad
= ffetarget_align (ffestorag_ptr_to_alignment (st
),
405 ffestorag_ptr_to_modulo (st
),
406 item_offset
, alignment
, modulo
);
409 ffebad_start (FFEBAD_EQUIV_ALIGN
);
410 ffebad_string (ffesymbol_text (item_sym
));
412 ffesymbol_set_equiv (item_sym
, NULL
); /* Don't bother with me anymore. */
416 /* If the variable's offset is less than the offset for the
417 aggregate storage area, it means it has to expand backwards
418 -- i.e. the new known starting point of the area precedes the
419 old one. This can't happen with COMMON areas (the standard,
420 and common sense, disallow it), but it is normal for local
423 Also handle choosing the "documented" rooted symbol for this
424 area here. It's the symbol at the bottom (lowest offset)
425 of the aggregate area, with ties going to the name that would
426 sort to the top of the list of ties. */
428 if (item_offset
== ffestorag_offset (st
))
430 if ((item_sym
!= ffestorag_symbol (st
))
431 && (strcmp (ffesymbol_text (item_sym
),
432 ffesymbol_text (ffestorag_symbol (st
)))
434 ffestorag_set_symbol (st
, item_sym
);
436 else if (item_offset
< ffestorag_offset (st
))
438 /* Increase size of equiv area to start for lower offset
439 relative to root symbol. */
440 if (! ffetarget_offset_add (&new_size
,
441 ffestorag_offset (st
)
443 ffestorag_size (st
)))
444 ffetarget_offset_overflow (ffesymbol_text (s
));
446 ffestorag_set_size (st
, new_size
);
448 ffestorag_set_symbol (st
, item_sym
);
449 ffestorag_set_offset (st
, item_offset
);
452 fprintf (stderr
, " [eq offset=%" ffetargetOffset_f
453 "d, size=%" ffetargetOffset_f
"d]",
454 item_offset
, new_size
);
458 if ((item_st
= ffesymbol_storage (item_sym
)) == NULL
)
459 { /* Create new ffestorag object, extend equiv
462 fprintf (stderr
, ".\n");
465 item_st
= ffestorag_new (ffestorag_list_equivs (st
));
466 ffestorag_set_parent (item_st
, st
); /* Initializations
468 ffestorag_set_init (item_st
, NULL
);
469 ffestorag_set_accretion (item_st
, NULL
);
470 ffestorag_set_symbol (item_st
, item_sym
);
471 ffestorag_set_size (item_st
, size
);
472 ffestorag_set_offset (item_st
, item_offset
);
473 ffestorag_set_alignment (item_st
, alignment
);
474 ffestorag_set_modulo (item_st
, modulo
);
475 ffestorag_set_type (item_st
, FFESTORAG_typeEQUIV
);
476 ffestorag_set_basictype (item_st
, ffesymbol_basictype (item_sym
));
477 ffestorag_set_kindtype (item_st
, ffesymbol_kindtype (item_sym
));
478 ffestorag_set_typesymbol (item_st
, item_sym
);
479 ffestorag_set_is_save (item_st
, FALSE
); /* Assume FALSE... */
480 if (ffestorag_is_save (st
)) /* ...update TRUE */
481 ffestorag_update_save (item_st
); /* if needed. */
482 ffestorag_set_is_init (item_st
, FALSE
); /* Assume FALSE... */
483 if (ffestorag_is_init (st
)) /* ...update TRUE */
484 ffestorag_update_init (item_st
); /* if needed. */
485 ffesymbol_set_storage (item_sym
, item_st
);
486 ffesymbol_signal_unreported (item_sym
);
487 if (ffesymbol_is_init (item_sym
))
490 /* Determine new size of equiv area, complain if overflow. */
492 if (!ffetarget_offset_add (&size
, item_offset
, size
)
493 || !ffetarget_offset_add (&size
, -ffestorag_offset (st
), size
))
494 ffetarget_offset_overflow (ffesymbol_text (s
));
495 else if (size
> ffestorag_size (st
))
496 ffestorag_set_size (st
, size
);
497 ffestorag_update (st
, item_sym
, ffesymbol_basictype (item_sym
),
498 ffesymbol_kindtype (item_sym
));
503 fprintf (stderr
, " (was %" ffetargetOffset_f
"d).\n",
504 ffestorag_offset (item_st
));
506 /* Make sure offset agrees with known offset. */
507 if (item_offset
!= ffestorag_offset (item_st
))
512 sprintf (&io1
[0], "%" ffetargetOffset_f
"d", item_offset
);
513 sprintf (&io2
[0], "%" ffetargetOffset_f
"d", ffestorag_offset (item_st
));
514 ffebad_start (FFEBAD_EQUIV_MISMATCH
);
515 ffebad_string (ffesymbol_text (item_sym
));
516 ffebad_string (ffesymbol_text (root_sym
));
522 ffesymbol_set_equiv (item_sym
, NULL
); /* Don't bother with me anymore. */
523 } /* (For every equivalence item in the list) */
524 ffebld_set_head (list
, NULL
); /* Don't do this list again. */
525 } /* (For every equivalence list in the list of
527 } while (new_storage
&& need_storage
);
529 ffesymbol_set_equiv (root_sym
, NULL
); /* This one has storage now. */
531 ffeequiv_kill (eq
); /* Fully processed, no longer needed. */
533 /* If the offset for this storage area is zero (it cannot be positive),
534 that means the alignment/modulo info is already correct. Otherwise,
535 the alignment info is correct, but the modulo info reflects a
536 zero offset, so fix it. */
538 if (ffestorag_offset (st
) < 0)
540 /* Calculate the initial padding necessary to preserve
541 the alignment/modulo requirements for the storage area.
542 These requirements are themselves kept track of in the
543 record for the storage area as a whole, but really pertain
544 to offset 0 of that area, which is where the root symbol
545 was originally placed.
547 The goal here is to have the offset and size for the area
548 faithfully reflect the area itself, not extra requirements
549 like alignment. So to meet the alignment requirements,
550 the modulo for the area should be set as if the area had an
551 alignment requirement of alignment/0 and was aligned/padded
552 downward to meet the alignment requirements of the area at
553 offset zero, the amount of padding needed being the desired
554 value for the modulo of the area. */
556 alignment
= ffestorag_alignment (st
);
557 modulo
= ffestorag_modulo (st
);
559 /* Since we want to move the whole area *down* (lower memory
560 addresses) as required by the alignment/modulo paid, negate
561 the offset to ffetarget_align, which assumes aligning *up*
563 pad
= ffetarget_align (&alignment
, &modulo
,
564 - ffestorag_offset (st
),
566 ffestorag_set_modulo (st
, pad
);
570 ffedata_gather (st
); /* Gather subordinate inits into one init. */
573 /* ffeequiv_offset_ -- Determine offset from start of symbol
575 ffetargetOffset offset;
576 ffesymbol s; // Symbol for error reporting.
577 ffebld expr; // opSUBSTR, opARRAYREF, opSYMTER, opANY.
578 bool subtract; // FALSE means add to adjust, TRUE means subtract from it.
579 ffetargetOffset adjust; // Helps keep answer in pos range (unsigned).
580 if (!ffeequiv_offset_(&offset,s,expr,subtract,adjust))
581 // error doing the calculation, message already printed
583 Returns the offset represented by the SUBSTR, ARRAYREF, or SUBSTR/ARRAYREF
584 combination added-to/subtracted-from the adjustment specified. If there
585 is an error of some kind, returns FALSE, else returns TRUE. Note that
586 only the first storage unit specified is considered; A(1:1) and A(1:2000)
587 have the same first storage unit and so return the same offset. */
590 ffeequiv_offset_ (ffetargetOffset
*offset
, ffesymbol s UNUSED
,
591 ffebld expr
, bool subtract
, ffetargetOffset adjust
,
594 ffetargetIntegerDefault value
= 0;
595 ffetargetOffset cval
; /* Converted value. */
601 again
: /* :::::::::::::::::::: */
603 switch (ffebld_op (expr
))
608 case FFEBLD_opSYMTER
:
610 ffetargetOffset size
; /* Size of a single unit. */
611 ffetargetAlign a
; /* Ignored. */
612 ffetargetAlign m
; /* Ignored. */
614 sym
= ffebld_symter (expr
);
615 if (ffesymbol_basictype (sym
) == FFEINFO_basictypeANY
)
618 ffetarget_layout (ffesymbol_text (sym
), &a
, &m
, &size
,
619 ffesymbol_basictype (sym
),
620 ffesymbol_kindtype (sym
), 1, 1);
623 { /* Really invalid, as in A(-2:5), but in case
625 if (!ffetarget_offset (&cval
, -value
))
628 if (!ffetarget_offset_multiply (&cval
, cval
, size
))
632 return ffetarget_offset_add (offset
, cval
, adjust
);
634 if (no_precede
&& (cval
> adjust
))
636 neg
: /* :::::::::::::::::::: */
637 ffebad_start (FFEBAD_COMMON_NEG
);
638 ffebad_string (ffesymbol_text (sym
));
642 return ffetarget_offset_add (offset
, -cval
, adjust
);
645 if (!ffetarget_offset (&cval
, value
))
648 if (!ffetarget_offset_multiply (&cval
, cval
, size
))
652 return ffetarget_offset_add (offset
, cval
, adjust
);
654 if (no_precede
&& (cval
> adjust
))
655 goto neg
; /* :::::::::::::::::::: */
657 return ffetarget_offset_add (offset
, -cval
, adjust
);
660 case FFEBLD_opARRAYREF
:
662 ffebld symexp
= ffebld_left (expr
);
663 ffebld subscripts
= ffebld_right (expr
);
665 ffetargetIntegerDefault width
;
666 ffetargetIntegerDefault arrayval
;
667 ffetargetIntegerDefault lowbound
;
668 ffetargetIntegerDefault highbound
;
675 if (ffebld_op (symexp
) != FFEBLD_opSYMTER
)
678 sym
= ffebld_symter (symexp
);
679 if (ffesymbol_basictype (sym
) == FFEINFO_basictypeANY
)
682 if (ffesymbol_size (sym
) == FFETARGET_charactersizeNONE
)
685 width
= ffesymbol_size (sym
);
686 dims
= ffesymbol_dims (sym
);
688 while (subscripts
!= NULL
)
693 ffebad_start (FFEBAD_EQUIV_MANY
);
694 ffebad_string (ffesymbol_text (sym
));
699 subscript
= ffebld_head (subscripts
);
700 dim
= ffebld_head (dims
);
702 if (ffebld_op (subscript
) == FFEBLD_opANY
)
705 assert (ffebld_op (subscript
) == FFEBLD_opCONTER
);
706 assert (ffeinfo_basictype (ffebld_info (subscript
))
707 == FFEINFO_basictypeINTEGER
);
708 assert (ffeinfo_kindtype (ffebld_info (subscript
))
709 == FFEINFO_kindtypeINTEGERDEFAULT
);
710 arrayval
= ffebld_constant_integerdefault (ffebld_conter
713 if (ffebld_op (dim
) == FFEBLD_opANY
)
716 assert (ffebld_op (dim
) == FFEBLD_opBOUNDS
);
717 low
= ffebld_left (dim
);
718 high
= ffebld_right (dim
);
724 if (ffebld_op (low
) == FFEBLD_opANY
)
727 assert (ffebld_op (low
) == FFEBLD_opCONTER
);
728 assert (ffeinfo_basictype (ffebld_info (low
))
729 == FFEINFO_basictypeINTEGER
);
730 assert (ffeinfo_kindtype (ffebld_info (low
))
731 == FFEINFO_kindtypeINTEGERDEFAULT
);
733 = ffebld_constant_integerdefault (ffebld_conter (low
));
736 if (ffebld_op (high
) == FFEBLD_opANY
)
739 assert (ffebld_op (high
) == FFEBLD_opCONTER
);
740 assert (ffeinfo_basictype (ffebld_info (high
))
741 == FFEINFO_basictypeINTEGER
);
742 assert (ffeinfo_kindtype (ffebld_info (high
))
743 == FFEINFO_kindtypeINTEGER1
);
745 = ffebld_constant_integerdefault (ffebld_conter (high
));
747 if ((arrayval
< lowbound
) || (arrayval
> highbound
))
751 sprintf (rankstr
, "%d", rank
);
752 ffebad_start (FFEBAD_EQUIV_SUBSCRIPT
);
753 ffebad_string (ffesymbol_text (sym
));
754 ffebad_string (rankstr
);
758 subscripts
= ffebld_trail (subscripts
);
759 dims
= ffebld_trail (dims
);
761 value
+= width
* (arrayval
- lowbound
);
762 if (subscripts
!= NULL
)
763 width
*= highbound
- lowbound
+ 1;
768 ffebad_start (FFEBAD_EQUIV_FEW
);
769 ffebad_string (ffesymbol_text (sym
));
776 goto again
; /* :::::::::::::::::::: */
778 case FFEBLD_opSUBSTR
:
780 ffebld begin
= ffebld_head (ffebld_right (expr
));
782 expr
= ffebld_left (expr
);
783 if (ffebld_op (expr
) == FFEBLD_opANY
)
785 if (ffebld_op (expr
) == FFEBLD_opARRAYREF
)
786 sym
= ffebld_symter (ffebld_left (expr
));
787 else if (ffebld_op (expr
) == FFEBLD_opSYMTER
)
788 sym
= ffebld_symter (expr
);
793 && (ffesymbol_basictype (sym
) == FFEINFO_basictypeANY
))
800 if (ffebld_op (begin
) == FFEBLD_opANY
)
802 assert (ffebld_op (begin
) == FFEBLD_opCONTER
);
803 assert (ffeinfo_basictype (ffebld_info (begin
))
804 == FFEINFO_basictypeINTEGER
);
805 assert (ffeinfo_kindtype (ffebld_info (begin
))
806 == FFEINFO_kindtypeINTEGERDEFAULT
);
808 value
= ffebld_constant_integerdefault (ffebld_conter (begin
));
812 && (value
> ffesymbol_size (sym
))))
814 ffebad_start (FFEBAD_EQUIV_RANGE
);
815 ffebad_string (ffesymbol_text (sym
));
822 && (ffesymbol_basictype (sym
) != FFEINFO_basictypeCHARACTER
))
824 ffebad_start (FFEBAD_EQUIV_SUBSTR
);
825 ffebad_string (ffesymbol_text (sym
));
830 goto again
; /* :::::::::::::::::::: */
833 assert ("bad op" == NULL
);
839 /* ffeequiv_add -- Add list of equivalences to list of lists for eq object
843 ffelexToken t; // points to first item in equivalence list
844 ffeequiv_add(eq,list,t);
846 Check the list to make sure only one common symbol is involved (even
847 if multiple times) and agrees with the common symbol for the equivalence
848 object (or it has no common symbol until now). Prepend (or append, it
849 doesn't matter) the list to the list of lists for the equivalence object.
850 Otherwise report an error and return. */
853 ffeequiv_add (ffeequiv eq
, ffebld list
, ffelexToken t
)
857 ffesymbol common
= ffeequiv_common (eq
);
859 for (item
= list
; item
!= NULL
; item
= ffebld_trail (item
))
861 symbol
= ffeequiv_symbol (ffebld_head (item
));
863 if (ffesymbol_common (symbol
) != NULL
) /* Is symbol known in COMMON yet? */
866 common
= ffesymbol_common (symbol
);
867 else if (common
!= ffesymbol_common (symbol
))
869 /* Yes, and symbol disagrees with others on the COMMON area. */
870 ffebad_start (FFEBAD_EQUIV_COMMON
);
871 ffebad_here (0, ffelex_token_where_line (t
), ffelex_token_where_column (t
));
872 ffebad_string (ffesymbol_text (common
));
873 ffebad_string (ffesymbol_text (ffesymbol_common (symbol
)));
881 && (ffeequiv_common (eq
) == NULL
)) /* Is COMMON involved already? */
882 ffeequiv_set_common (eq
, common
); /* No, but it is now. */
884 for (item
= list
; item
!= NULL
; item
= ffebld_trail (item
))
886 symbol
= ffeequiv_symbol (ffebld_head (item
));
888 if (ffesymbol_equiv (symbol
) == NULL
)
889 ffesymbol_set_equiv (symbol
, eq
);
891 assert (ffesymbol_equiv (symbol
) == eq
);
893 if (ffesymbol_common (symbol
) == NULL
) /* Is symbol in a COMMON
895 { /* No (at least not yet). */
896 if (ffesymbol_is_save (symbol
))
897 ffeequiv_update_save (eq
); /* EQUIVALENCE has >=1 SAVEd entity. */
898 if (ffesymbol_is_init (symbol
))
899 ffeequiv_update_init (eq
); /* EQUIVALENCE has >=1 init'd entity. */
900 continue; /* Nothing more to do here. */
903 #if FFEGLOBAL_ENABLED
904 if (ffesymbol_is_init (symbol
))
905 ffeglobal_init_common (ffesymbol_common (symbol
), t
);
908 if (ffesymbol_is_save (ffesymbol_common (symbol
)))
909 ffeequiv_update_save (eq
); /* EQUIVALENCE is in a SAVEd COMMON block. */
910 if (ffesymbol_is_init (ffesymbol_common (symbol
)))
911 ffeequiv_update_init (eq
); /* EQUIVALENCE is in a init'd COMMON block. */
914 ffeequiv_set_list (eq
, ffebld_new_item (list
, ffeequiv_list (eq
)));
917 /* ffeequiv_exec_transition -- Do the hard work on all the equivalence objects
919 ffeequiv_exec_transition(); */
922 ffeequiv_exec_transition (void)
924 while (ffeequiv_list_
.first
!= (ffeequiv
) &ffeequiv_list_
.first
)
925 ffeequiv_layout_local_ (ffeequiv_list_
.first
);
928 /* ffeequiv_init_2 -- Initialize for new program unit
932 Initializes the list of equivalences. */
935 ffeequiv_init_2 (void)
937 ffeequiv_list_
.first
= (ffeequiv
) &ffeequiv_list_
.first
;
938 ffeequiv_list_
.last
= (ffeequiv
) &ffeequiv_list_
.first
;
941 /* ffeequiv_kill -- Kill equivalence object after removing from list
946 Removes equivalence object from master list, then kills it. */
949 ffeequiv_kill (ffeequiv victim
)
951 victim
->next
->previous
= victim
->previous
;
952 victim
->previous
->next
= victim
->next
;
953 if (ffe_is_do_internal_checks ())
959 /* Assert that nobody our victim points to still points to it. */
961 assert ((victim
->common
== NULL
)
962 || (ffesymbol_equiv (victim
->common
) == NULL
));
964 for (list
= victim
->list
; list
!= NULL
; list
= ffebld_trail (list
))
966 for (item
= ffebld_head (list
); item
!= NULL
; item
= ffebld_trail (item
))
970 expr
= ffebld_head (item
);
971 sym
= ffeequiv_symbol (expr
);
974 assert (ffesymbol_equiv (sym
) != victim
);
978 malloc_kill_ks (ffe_pool_program_unit (), victim
, sizeof (*victim
));
981 /* ffeequiv_layout_cblock -- Lay out storage for common area
984 if (ffeequiv_layout_cblock(st))
985 // at least one equiv'd symbol has init/accretion expr.
987 Now that the explicitly COMMONed variables in the common area (whose
988 ffestorag object is passed) have been laid out, lay out the storage
989 for all variables equivalenced into the area by making subordinate
990 ffestorag objects for them. */
993 ffeequiv_layout_cblock (ffestorag st
)
995 ffesymbol s
= ffestorag_symbol (st
); /* CBLOCK symbol. */
996 ffebld list
; /* List of explicit common vars, in order, in
998 ffebld item
; /* List of list of equivalences in a given
999 explicit common var. */
1000 ffebld root
; /* Expression for (1st) explicit common var
1002 ffestorag rst
; /* Storage for root. */
1003 ffetargetOffset root_offset
; /* Offset for root into common area. */
1004 ffesymbol sr
; /* Root itself. */
1005 ffeequiv seq
; /* Its equivalence object, if any. */
1006 ffebld var
; /* Expression for equivalence. */
1007 ffestorag vst
; /* Storage for var. */
1008 ffetargetOffset var_offset
; /* Offset for var into common area. */
1009 ffesymbol sv
; /* Var itself. */
1010 ffebld altroot
; /* Alternate root. */
1011 ffesymbol altrootsym
; /* Alternate root symbol. */
1012 ffetargetAlign alignment
;
1013 ffetargetAlign modulo
;
1015 ffetargetOffset size
;
1016 ffetargetOffset num_elements
;
1017 bool new_storage
; /* Established new storage info. */
1018 bool need_storage
; /* Have need for more storage info. */
1022 assert (st
!= NULL
);
1023 assert (ffestorag_type (st
) == FFESTORAG_typeCBLOCK
);
1024 assert (ffesymbol_kind (ffestorag_symbol (st
)) == FFEINFO_kindCOMMON
);
1026 for (list
= ffesymbol_commonlist (ffestorag_symbol (st
));
1028 list
= ffebld_trail (list
))
1029 { /* For every variable in the common area */
1030 assert (ffebld_op (ffebld_head (list
)) == FFEBLD_opSYMTER
);
1031 sr
= ffebld_symter (ffebld_head (list
));
1032 if ((seq
= ffesymbol_equiv (sr
)) == NULL
)
1033 continue; /* No equivalences to process. */
1034 rst
= ffesymbol_storage (sr
);
1037 assert (ffesymbol_kind (sr
) == FFEINFO_kindANY
);
1040 ffesymbol_set_equiv (sr
, NULL
); /* Cancel ref to equiv obj. */
1043 new_storage
= FALSE
;
1044 need_storage
= FALSE
;
1045 for (item
= ffeequiv_list (seq
); /* Get list of equivs. */
1047 item
= ffebld_trail (item
))
1048 { /* For every eqv list in the list of equivs
1052 for (root
= ffebld_head (item
);
1054 root
= ffebld_trail (root
))
1055 { /* For every equivalence item in the list */
1056 sv
= ffeequiv_symbol (ffebld_head (root
));
1058 break; /* Found first mention of "rooted" symbol. */
1059 if (ffesymbol_storage (sv
) != NULL
)
1061 altroot
= root
; /* If no mention, use this guy
1068 root
= ffebld_head (root
); /* Lose its opITEM. */
1069 ok
= ffeequiv_offset_ (&root_offset
, sr
, root
, FALSE
,
1070 ffestorag_offset (rst
), TRUE
);
1071 /* Equiv point prior to start of common area? */
1073 else if (altroot
!= NULL
)
1075 /* Equiv point prior to start of common area? */
1076 root
= ffebld_head (altroot
);
1077 ok
= ffeequiv_offset_ (&root_offset
, altrootsym
, root
,
1079 ffestorag_offset (ffesymbol_storage (altrootsym
)),
1081 ffesymbol_set_equiv (altrootsym
, NULL
);
1084 /* No rooted symbol in list of equivalences! */
1085 { /* Assume this was due to opANY and ignore
1086 this list for now. */
1087 need_storage
= TRUE
;
1091 /* We now know the root symbol and the operating offset of that
1092 root into the common area. The other expressions in the
1093 list all identify an initial storage unit that must have the
1096 for (var
= ffebld_head (item
);
1098 var
= ffebld_trail (var
))
1099 { /* For every equivalence item in the list */
1100 if (ffebld_head (var
) == root
)
1101 continue; /* Except root, of course. */
1102 sv
= ffeequiv_symbol (ffebld_head (var
));
1104 continue; /* Except erroneous stuff (opANY). */
1105 ffesymbol_set_equiv (sv
, NULL
); /* Don't need this ref
1108 || !ffeequiv_offset_ (&var_offset
, sv
,
1109 ffebld_head (var
), TRUE
,
1111 continue; /* Can't do negative offset wrt COMMON. */
1113 if (ffesymbol_rank (sv
) == 0)
1116 num_elements
= ffebld_constant_integerdefault
1117 (ffebld_conter (ffesymbol_arraysize (sv
)));
1118 ffetarget_layout (ffesymbol_text (sv
), &alignment
,
1120 ffesymbol_basictype (sv
),
1121 ffesymbol_kindtype (sv
),
1122 ffesymbol_size (sv
), num_elements
);
1123 pad
= ffetarget_align (ffestorag_ptr_to_alignment (st
),
1124 ffestorag_ptr_to_modulo (st
),
1125 var_offset
, alignment
, modulo
);
1128 ffebad_start (FFEBAD_EQUIV_ALIGN
);
1129 ffebad_string (ffesymbol_text (sv
));
1134 if ((vst
= ffesymbol_storage (sv
)) == NULL
)
1135 { /* Create new ffestorag object, extend
1138 vst
= ffestorag_new (ffestorag_list_equivs (st
));
1139 ffestorag_set_parent (vst
, st
); /* Initializations
1141 ffestorag_set_init (vst
, NULL
);
1142 ffestorag_set_accretion (vst
, NULL
);
1143 ffestorag_set_symbol (vst
, sv
);
1144 ffestorag_set_size (vst
, size
);
1145 ffestorag_set_offset (vst
, var_offset
);
1146 ffestorag_set_alignment (vst
, alignment
);
1147 ffestorag_set_modulo (vst
, modulo
);
1148 ffestorag_set_type (vst
, FFESTORAG_typeEQUIV
);
1149 ffestorag_set_basictype (vst
, ffesymbol_basictype (sv
));
1150 ffestorag_set_kindtype (vst
, ffesymbol_kindtype (sv
));
1151 ffestorag_set_typesymbol (vst
, sv
);
1152 ffestorag_set_is_save (vst
, FALSE
); /* Assume FALSE... */
1153 if (ffestorag_is_save (st
)) /* ...update TRUE */
1154 ffestorag_update_save (vst
); /* if needed. */
1155 ffestorag_set_is_init (vst
, FALSE
); /* Assume FALSE... */
1156 if (ffestorag_is_init (st
)) /* ...update TRUE */
1157 ffestorag_update_init (vst
); /* if needed. */
1158 if (!ffetarget_offset_add (&size
, var_offset
, size
))
1159 /* Find one size of common block, complain if
1161 ffetarget_offset_overflow (ffesymbol_text (s
));
1162 else if (size
> ffestorag_size (st
))
1163 /* Extend common. */
1164 ffestorag_set_size (st
, size
);
1165 ffesymbol_set_storage (sv
, vst
);
1166 ffesymbol_set_common (sv
, s
);
1167 ffesymbol_signal_unreported (sv
);
1168 ffestorag_update (st
, sv
, ffesymbol_basictype (sv
),
1169 ffesymbol_kindtype (sv
));
1170 if (ffesymbol_is_init (sv
))
1175 /* Make sure offset agrees with known offset. */
1176 if (var_offset
!= ffestorag_offset (vst
))
1181 sprintf (&io1
[0], "%" ffetargetOffset_f
"d", var_offset
);
1182 sprintf (&io2
[0], "%" ffetargetOffset_f
"d", ffestorag_offset (vst
));
1183 ffebad_start (FFEBAD_EQUIV_MISMATCH
);
1184 ffebad_string (ffesymbol_text (sv
));
1185 ffebad_string (ffesymbol_text (s
));
1186 ffebad_string (io1
);
1187 ffebad_string (io2
);
1191 } /* (For every equivalence item in the list) */
1192 } /* (For every eqv list in the list of equivs
1193 for the variable) */
1195 while (new_storage
&& need_storage
);
1197 ffeequiv_kill (seq
); /* Kill equiv obj. */
1198 } /* (For every variable in the common area) */
1203 /* ffeequiv_merge -- Merge two equivalence objects, return the merged result
1207 ffelexToken t; // points to current equivalence item forcing the merge.
1208 eq1 = ffeequiv_merge(eq1,eq2,t);
1210 If the two equivalence objects can be merged, they are, all the
1211 ffesymbols in their lists of lists are adjusted to point to the merged
1212 equivalence object, and the merged object is returned.
1214 Otherwise, the two equivalence objects have different non-NULL common
1215 symbols, so the merge cannot take place. An error message is issued and
1216 NULL is returned. */
1219 ffeequiv_merge (ffeequiv eq1
, ffeequiv eq2
, ffelexToken t
)
1226 /* If both equivalence objects point to different common-based symbols,
1227 complain. Of course, one or both might have NULL common symbols now,
1228 and get COMMONed later, but the COMMON statement handler checks for
1231 if ((ffeequiv_common (eq1
) != NULL
) && (ffeequiv_common (eq2
) != NULL
)
1232 && (ffeequiv_common (eq1
) != ffeequiv_common (eq2
)))
1234 ffebad_start (FFEBAD_EQUIV_COMMON
);
1235 ffebad_here (0, ffelex_token_where_line (t
), ffelex_token_where_column (t
));
1236 ffebad_string (ffesymbol_text (ffeequiv_common (eq1
)));
1237 ffebad_string (ffesymbol_text (ffeequiv_common (eq2
)));
1242 /* Make eq1 the new, merged object (arbitrarily). */
1244 if (ffeequiv_common (eq1
) == NULL
)
1245 ffeequiv_set_common (eq1
, ffeequiv_common (eq2
));
1247 /* If the victim object has any init'ed entities, so does the new object. */
1250 eq1
->is_init
= TRUE
;
1252 #if FFEGLOBAL_ENABLED
1253 if (eq1
->is_init
&& (ffeequiv_common (eq1
) != NULL
))
1254 ffeglobal_init_common (ffeequiv_common (eq1
), t
);
1257 /* If the victim object has any SAVEd entities, then the new object has
1260 if (ffeequiv_is_save (eq2
))
1261 ffeequiv_update_save (eq1
);
1263 /* If the victim object has any init'd entities, then the new object has
1266 if (ffeequiv_is_init (eq2
))
1267 ffeequiv_update_init (eq1
);
1269 /* Adjust all the symbols in the list of lists of equivalences for the
1270 victim equivalence object so they point to the new merged object
1273 for (list
= ffeequiv_list (eq2
); list
!= NULL
; list
= ffebld_trail (list
))
1275 for (eqs
= ffebld_head (list
); eqs
!= NULL
; eqs
= ffebld_trail (eqs
))
1277 symbol
= ffeequiv_symbol (ffebld_head (eqs
));
1278 if (ffesymbol_equiv (symbol
) == eq2
)
1279 ffesymbol_set_equiv (symbol
, eq1
);
1281 assert (ffesymbol_equiv (symbol
) == eq1
); /* Can see a sym > once. */
1284 /* For convenience, remember where the last ITEM in the outer list is. */
1286 if (ffebld_trail (list
) == NULL
)
1293 /* Append the list of lists in the new, merged object to the list of lists
1294 in the victim object, then use the new combined list in the new merged
1297 ffebld_set_trail (last
, ffeequiv_list (eq1
));
1298 ffeequiv_set_list (eq1
, ffeequiv_list (eq2
));
1300 /* Unlink and kill the victim object. */
1302 ffeequiv_kill (eq2
);
1304 return eq1
; /* Return the new merged object. */
1307 /* ffeequiv_new -- Create new equivalence object, put in list
1310 eq = ffeequiv_new();
1312 Creates a new equivalence object and adds it to the list of equivalence
1320 eq
= malloc_new_ks (ffe_pool_program_unit (), "ffeequiv", sizeof (*eq
));
1321 eq
->next
= (ffeequiv
) &ffeequiv_list_
.first
;
1322 eq
->previous
= ffeequiv_list_
.last
;
1323 ffeequiv_set_common (eq
, NULL
); /* No COMMON area yet. */
1324 ffeequiv_set_list (eq
, NULL
); /* No list of lists of equivalences yet. */
1325 ffeequiv_set_is_save (eq
, FALSE
);
1326 ffeequiv_set_is_init (eq
, FALSE
);
1327 eq
->next
->previous
= eq
;
1328 eq
->previous
->next
= eq
;
1333 /* ffeequiv_symbol -- Return symbol for equivalence expression
1337 symbol = ffeequiv_symbol(expr);
1339 Finds the terminal SYMTER in an equivalence expression and returns the
1340 ffesymbol for it. */
1343 ffeequiv_symbol (ffebld expr
)
1345 assert (expr
!= NULL
);
1347 again
: /* :::::::::::::::::::: */
1349 switch (ffebld_op (expr
))
1351 case FFEBLD_opARRAYREF
:
1352 case FFEBLD_opSUBSTR
:
1353 expr
= ffebld_left (expr
);
1354 goto again
; /* :::::::::::::::::::: */
1356 case FFEBLD_opSYMTER
:
1357 return ffebld_symter (expr
);
1363 assert ("bad eq expr" == NULL
);
1368 /* ffeequiv_update_init -- Update the INIT flag for the area to TRUE
1371 ffeequiv_update_init(eq);
1373 If the INIT flag for the <eq> object is already set, return. Else,
1374 set it TRUE and call ffe*_update_init for all objects contained in
1378 ffeequiv_update_init (ffeequiv eq
)
1380 ffebld list
; /* Current list in list of lists. */
1381 ffebld item
; /* Current item in current list. */
1382 ffebld expr
; /* Expression in head of current item. */
1389 if ((eq
->common
!= NULL
)
1390 && !ffesymbol_is_init (eq
->common
))
1391 ffesymbol_update_init (eq
->common
); /* Shouldn't be needed. */
1393 for (list
= eq
->list
; list
!= NULL
; list
= ffebld_trail (list
))
1395 for (item
= ffebld_head (list
); item
!= NULL
; item
= ffebld_trail (item
))
1397 expr
= ffebld_head (item
);
1399 again
: /* :::::::::::::::::::: */
1401 switch (ffebld_op (expr
))
1406 case FFEBLD_opSYMTER
:
1407 if (!ffesymbol_is_init (ffebld_symter (expr
)))
1408 ffesymbol_update_init (ffebld_symter (expr
));
1411 case FFEBLD_opARRAYREF
:
1412 expr
= ffebld_left (expr
);
1413 goto again
; /* :::::::::::::::::::: */
1415 case FFEBLD_opSUBSTR
:
1416 expr
= ffebld_left (expr
);
1417 goto again
; /* :::::::::::::::::::: */
1420 assert ("bad op for ffeequiv_update_init" == NULL
);
1427 /* ffeequiv_update_save -- Update the SAVE flag for the area to TRUE
1430 ffeequiv_update_save(eq);
1432 If the SAVE flag for the <eq> object is already set, return. Else,
1433 set it TRUE and call ffe*_update_save for all objects contained in
1437 ffeequiv_update_save (ffeequiv eq
)
1439 ffebld list
; /* Current list in list of lists. */
1440 ffebld item
; /* Current item in current list. */
1441 ffebld expr
; /* Expression in head of current item. */
1448 if ((eq
->common
!= NULL
)
1449 && !ffesymbol_is_save (eq
->common
))
1450 ffesymbol_update_save (eq
->common
); /* Shouldn't be needed. */
1452 for (list
= eq
->list
; list
!= NULL
; list
= ffebld_trail (list
))
1454 for (item
= ffebld_head (list
); item
!= NULL
; item
= ffebld_trail (item
))
1456 expr
= ffebld_head (item
);
1458 again
: /* :::::::::::::::::::: */
1460 switch (ffebld_op (expr
))
1465 case FFEBLD_opSYMTER
:
1466 if (!ffesymbol_is_save (ffebld_symter (expr
)))
1467 ffesymbol_update_save (ffebld_symter (expr
));
1470 case FFEBLD_opARRAYREF
:
1471 expr
= ffebld_left (expr
);
1472 goto again
; /* :::::::::::::::::::: */
1474 case FFEBLD_opSUBSTR
:
1475 expr
= ffebld_left (expr
);
1476 goto again
; /* :::::::::::::::::::: */
1479 assert ("bad op for ffeequiv_update_save" == NULL
);