1 /* equiv.c -- Implementation File (module.c template V1.0)
2 Copyright (C) 1995-1997 Free Software Foundation, Inc.
3 Contributed by James Craig Burley (burley@gnu.org).
5 This file is part of GNU Fortran.
7 GNU Fortran is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
12 GNU Fortran is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Fortran; see the file COPYING. If not, write to
19 the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
26 Handles the EQUIVALENCE relationships in a program unit.
31 #define FFEEQUIV_DEBUG 0
46 /* Externals defined here. */
49 /* Simple definitions and enumerations. */
52 /* Internal typedefs. */
55 /* Private include files. */
58 /* Internal structure definitions. */
60 struct _ffeequiv_list_
66 /* Static objects accessed by functions in this module. */
68 static struct _ffeequiv_list_ ffeequiv_list_;
70 /* Static functions (internal). */
72 static void ffeequiv_destroy_ (ffeequiv eq);
73 static void ffeequiv_layout_local_ (ffeequiv eq);
74 static bool ffeequiv_offset_ (ffetargetOffset *offset, ffesymbol s,
75 ffebld expr, bool subtract,
76 ffetargetOffset adjust, bool no_precede);
78 /* Internal macros. */
82 ffeequiv_destroy_ (ffeequiv victim)
88 for (list = victim->list; list != NULL; list = ffebld_trail (list))
90 for (item = ffebld_head (list); item != NULL; item = ffebld_trail (item))
94 expr = ffebld_head (item);
95 sym = ffeequiv_symbol (expr);
98 if (ffesymbol_equiv (sym) != NULL)
99 ffesymbol_set_equiv (sym, NULL);
102 ffeequiv_kill (victim);
105 /* ffeequiv_layout_local_ -- Lay out storage for local equivalenced vars
108 ffeequiv_layout_local_(eq);
110 Makes a single master ffestorag object that contains all the vars
111 in the equivalence, and makes subordinate ffestorag objects for the
112 vars with the correct offsets.
114 The resulting var offsets are relative not necessarily to 0 -- the
115 are relative to the offset of the master area, which might be 0 or
116 negative, but should never be positive. */
119 ffeequiv_layout_local_ (ffeequiv eq)
121 ffestorag st; /* Equivalence storage area. */
122 ffebld list; /* List of list of equivalences. */
123 ffebld item; /* List of equivalences. */
124 ffebld root_exp; /* Expression for root sym. */
125 ffestorag root_st; /* Storage for root. */
126 ffesymbol root_sym; /* Root itself. */
127 ffebld rooted_exp; /* Expression for rooted sym in an eqlist. */
128 ffestorag rooted_st; /* Storage for rooted. */
129 ffesymbol rooted_sym; /* Rooted symbol itself. */
130 ffetargetOffset eqlist_offset;/* Offset for eqlist from rooted sym. */
131 ffetargetAlign alignment;
132 ffetargetAlign modulo;
134 ffetargetOffset size;
135 ffetargetOffset num_elements;
136 bool new_storage; /* Established new storage info. */
137 bool need_storage; /* Have need for more storage info. */
142 if (ffeequiv_common (eq) != NULL)
143 { /* Put in common due to programmer error. */
144 ffeequiv_destroy_ (eq);
148 /* Find the symbol for the first valid item in the list of lists, use that
149 as the root symbol. Doesn't matter if it won't end up at the beginning
150 of the list, though. */
153 fprintf (stderr, "Equiv1:\n");
159 for (list = ffeequiv_list (eq);
161 list = ffebld_trail (list))
162 { /* For every equivalence list in the list of
164 for (item = ffebld_head (list);
166 item = ffebld_trail (item))
167 { /* For every equivalence item in the list */
168 ffetargetOffset ign; /* Ignored. */
170 root_exp = ffebld_head (item);
171 root_sym = ffeequiv_symbol (root_exp);
172 if (root_sym == NULL)
173 continue; /* Ignore me. */
175 assert (ffesymbol_storage (root_sym) == NULL); /* No storage yet. */
177 if (!ffeequiv_offset_ (&ign, root_sym, root_exp, FALSE, 0, FALSE))
179 /* We can't just eliminate this one symbol from the list
180 of candidates, because it might be the only one that
181 ties all these equivs together. So just destroy the
184 ffeequiv_destroy_ (eq);
188 break; /* Use first valid eqv expr for root exp/sym. */
190 if (root_sym != NULL)
194 if (root_sym == NULL)
196 ffeequiv_destroy_ (eq);
202 fprintf (stderr, " Root: `%s'\n", ffesymbol_text (root_sym));
205 /* We've got work to do, so make the LOCAL storage object that'll hold all
206 the equivalenced vars inside it. */
208 st = ffestorag_new (ffestorag_list_master ());
209 ffestorag_set_parent (st, NULL); /* Initializations happen here. */
210 ffestorag_set_init (st, NULL);
211 ffestorag_set_accretion (st, NULL);
212 ffestorag_set_offset (st, 0); /* Assume equiv will be at root offset 0 for now. */
213 ffestorag_set_alignment (st, 1);
214 ffestorag_set_modulo (st, 0);
215 ffestorag_set_type (st, FFESTORAG_typeLOCAL);
216 ffestorag_set_basictype (st, ffesymbol_basictype (root_sym));
217 ffestorag_set_kindtype (st, ffesymbol_kindtype (root_sym));
218 ffestorag_set_typesymbol (st, root_sym);
219 ffestorag_set_is_save (st, ffeequiv_is_save (eq));
220 if (ffesymbol_is_save (root_sym))
221 ffestorag_update_save (st);
222 ffestorag_set_is_init (st, ffeequiv_is_init (eq));
223 if (ffesymbol_is_init (root_sym))
224 ffestorag_update_init (st);
225 ffestorag_set_symbol (st, root_sym); /* Assume this will be the root until
226 we know better (used only to generate
227 the internal name for the aggregate area,
228 e.g. for debugging). */
230 /* Make the EQUIV storage object for the root symbol. */
232 if (ffesymbol_rank (root_sym) == 0)
235 num_elements = ffebld_constant_integerdefault (ffebld_conter
236 (ffesymbol_arraysize (root_sym)));
237 ffetarget_layout (ffesymbol_text (root_sym), &alignment, &modulo, &size,
238 ffesymbol_basictype (root_sym), ffesymbol_kindtype (root_sym),
239 ffesymbol_size (root_sym), num_elements);
240 ffestorag_set_size (st, size); /* Set initial size of aggregate area. */
242 pad = ffetarget_align (ffestorag_ptr_to_alignment (st),
243 ffestorag_ptr_to_modulo (st), 0, alignment,
247 root_st = ffestorag_new (ffestorag_list_equivs (st));
248 ffestorag_set_parent (root_st, st); /* Initializations happen there. */
249 ffestorag_set_init (root_st, NULL);
250 ffestorag_set_accretion (root_st, NULL);
251 ffestorag_set_symbol (root_st, root_sym);
252 ffestorag_set_size (root_st, size);
253 ffestorag_set_offset (root_st, 0); /* Will not change; always 0 relative to itself! */
254 ffestorag_set_alignment (root_st, alignment);
255 ffestorag_set_modulo (root_st, modulo);
256 ffestorag_set_type (root_st, FFESTORAG_typeEQUIV);
257 ffestorag_set_basictype (root_st, ffesymbol_basictype (root_sym));
258 ffestorag_set_kindtype (root_st, ffesymbol_kindtype (root_sym));
259 ffestorag_set_typesymbol (root_st, root_sym);
260 ffestorag_set_is_save (root_st, FALSE); /* Assume FALSE, then... */
261 if (ffestorag_is_save (st)) /* ...update to TRUE if needed. */
262 ffestorag_update_save (root_st);
263 ffestorag_set_is_init (root_st, FALSE); /* Assume FALSE, then... */
264 if (ffestorag_is_init (st)) /* ...update to TRUE if needed. */
265 ffestorag_update_init (root_st);
266 ffesymbol_set_storage (root_sym, root_st);
267 ffesymbol_signal_unreported (root_sym);
268 init = ffesymbol_is_init (root_sym);
270 /* Now that we know the root (offset=0) symbol, revisit all the lists and
271 do the actual storage allocation. Keep doing this until we've gone
272 through them all without making any new storage objects. */
277 need_storage = FALSE;
278 for (list = ffeequiv_list (eq);
280 list = ffebld_trail (list))
281 { /* For every equivalence list in the list of
283 /* Now find a "rooted" symbol in this list. That is, find the
284 first item we can that is valid and whose symbol already
285 has a storage area, because that means we know where it
286 belongs in the equivalence area and can then allocate the
287 rest of the items in the list accordingly. */
293 for (item = ffebld_head (list);
295 item = ffebld_trail (item))
296 { /* For every equivalence item in the list */
297 rooted_exp = ffebld_head (item);
298 rooted_sym = ffeequiv_symbol (rooted_exp);
299 if ((rooted_sym == NULL)
300 || ((rooted_st = ffesymbol_storage (rooted_sym)) == NULL))
303 continue; /* Ignore me. */
306 need_storage = TRUE; /* Somebody is likely to need
310 fprintf (stderr, " Rooted: `%s' at %" ffetargetOffset_f "d\n",
311 ffesymbol_text (rooted_sym),
312 ffestorag_offset (rooted_st));
315 /* The offset of this symbol from the equiv's root symbol
316 is already known, and the size of this symbol is already
317 incorporated in the size of the equiv's aggregate area.
318 What we now determine is the offset of this equivalence
319 _list_ from the equiv's root symbol.
321 For example, if we know that A is at offset 16 from the
322 root symbol, given EQUIVALENCE (B(24),A(2)), we're looking
323 at A(2), meaning that the offset for this equivalence list
324 is 20 (4 bytes beyond the beginning of A, assuming typical
325 array types, dimensions, and type info). */
327 if (!ffeequiv_offset_ (&eqlist_offset, rooted_sym, rooted_exp, FALSE,
328 ffestorag_offset (rooted_st), FALSE))
330 { /* Can't use this one. */
331 ffesymbol_set_equiv (rooted_sym, NULL);/* Equiv area slated for
334 continue; /* Something's wrong with eqv expr, try another. */
338 fprintf (stderr, " Eqlist offset: %" ffetargetOffset_f "d\n",
345 /* If no rooted symbol, it means this list has no roots -- yet.
346 So, forget this list this time around, but we'll get back
347 to it after the outer loop iterates at least one more time,
348 and, ultimately, it will have a root. */
350 if (rooted_sym == NULL)
353 fprintf (stderr, "No roots.\n");
358 /* We now have a rooted symbol/expr and the offset of this equivalence
359 list from the root symbol. The other expressions in this
360 list all identify an initial storage unit that must have the
363 for (item = ffebld_head (list);
365 item = ffebld_trail (item))
366 { /* For every equivalence item in the list */
367 ffebld item_exp; /* Expression for equivalence. */
368 ffestorag item_st; /* Storage for var. */
369 ffesymbol item_sym; /* Var itself. */
370 ffetargetOffset item_offset; /* Offset for var from root. */
371 ffetargetOffset new_size;
373 item_exp = ffebld_head (item);
374 item_sym = ffeequiv_symbol (item_exp);
375 if ((item_sym == NULL)
376 || (ffesymbol_equiv (item_sym) == NULL))
377 continue; /* Ignore me. */
379 if (item_sym == rooted_sym)
380 continue; /* Rooted sym already set up. */
382 if (!ffeequiv_offset_ (&item_offset, item_sym, item_exp, TRUE,
383 eqlist_offset, FALSE))
385 ffesymbol_set_equiv (item_sym, NULL); /* Don't bother with me anymore. */
390 fprintf (stderr, " Item `%s' at %" ffetargetOffset_f "d",
391 ffesymbol_text (item_sym), item_offset);
394 if (ffesymbol_rank (item_sym) == 0)
397 num_elements = ffebld_constant_integerdefault (ffebld_conter
398 (ffesymbol_arraysize (item_sym)));
399 ffetarget_layout (ffesymbol_text (item_sym), &alignment, &modulo,
400 &size, ffesymbol_basictype (item_sym),
401 ffesymbol_kindtype (item_sym), ffesymbol_size (item_sym),
403 pad = ffetarget_align (ffestorag_ptr_to_alignment (st),
404 ffestorag_ptr_to_modulo (st),
405 item_offset, alignment, modulo);
408 ffebad_start (FFEBAD_EQUIV_ALIGN);
409 ffebad_string (ffesymbol_text (item_sym));
411 ffesymbol_set_equiv (item_sym, NULL); /* Don't bother with me anymore. */
415 /* If the variable's offset is less than the offset for the
416 aggregate storage area, it means it has to expand backwards
417 -- i.e. the new known starting point of the area precedes the
418 old one. This can't happen with COMMON areas (the standard,
419 and common sense, disallow it), but it is normal for local
422 Also handle choosing the "documented" rooted symbol for this
423 area here. It's the symbol at the bottom (lowest offset)
424 of the aggregate area, with ties going to the name that would
425 sort to the top of the list of ties. */
427 if (item_offset == ffestorag_offset (st))
429 if ((item_sym != ffestorag_symbol (st))
430 && (strcmp (ffesymbol_text (item_sym),
431 ffesymbol_text (ffestorag_symbol (st)))
433 ffestorag_set_symbol (st, item_sym);
435 else if (item_offset < ffestorag_offset (st))
437 /* Increase size of equiv area to start for lower offset
438 relative to root symbol. */
439 if (! ffetarget_offset_add (&new_size,
440 ffestorag_offset (st)
442 ffestorag_size (st)))
443 ffetarget_offset_overflow (ffesymbol_text (s));
445 ffestorag_set_size (st, new_size);
447 ffestorag_set_symbol (st, item_sym);
448 ffestorag_set_offset (st, item_offset);
451 fprintf (stderr, " [eq offset=%" ffetargetOffset_f
452 "d, size=%" ffetargetOffset_f "d]",
453 item_offset, new_size);
457 if ((item_st = ffesymbol_storage (item_sym)) == NULL)
458 { /* Create new ffestorag object, extend equiv
461 fprintf (stderr, ".\n");
464 item_st = ffestorag_new (ffestorag_list_equivs (st));
465 ffestorag_set_parent (item_st, st); /* Initializations
467 ffestorag_set_init (item_st, NULL);
468 ffestorag_set_accretion (item_st, NULL);
469 ffestorag_set_symbol (item_st, item_sym);
470 ffestorag_set_size (item_st, size);
471 ffestorag_set_offset (item_st, item_offset);
472 ffestorag_set_alignment (item_st, alignment);
473 ffestorag_set_modulo (item_st, modulo);
474 ffestorag_set_type (item_st, FFESTORAG_typeEQUIV);
475 ffestorag_set_basictype (item_st, ffesymbol_basictype (item_sym));
476 ffestorag_set_kindtype (item_st, ffesymbol_kindtype (item_sym));
477 ffestorag_set_typesymbol (item_st, item_sym);
478 ffestorag_set_is_save (item_st, FALSE); /* Assume FALSE... */
479 if (ffestorag_is_save (st)) /* ...update TRUE */
480 ffestorag_update_save (item_st); /* if needed. */
481 ffestorag_set_is_init (item_st, FALSE); /* Assume FALSE... */
482 if (ffestorag_is_init (st)) /* ...update TRUE */
483 ffestorag_update_init (item_st); /* if needed. */
484 ffesymbol_set_storage (item_sym, item_st);
485 ffesymbol_signal_unreported (item_sym);
486 if (ffesymbol_is_init (item_sym))
489 /* Determine new size of equiv area, complain if overflow. */
491 if (!ffetarget_offset_add (&size, item_offset, size)
492 || !ffetarget_offset_add (&size, -ffestorag_offset (st), size))
493 ffetarget_offset_overflow (ffesymbol_text (s));
494 else if (size > ffestorag_size (st))
495 ffestorag_set_size (st, size);
496 ffestorag_update (st, item_sym, ffesymbol_basictype (item_sym),
497 ffesymbol_kindtype (item_sym));
502 fprintf (stderr, " (was %" ffetargetOffset_f "d).\n",
503 ffestorag_offset (item_st));
505 /* Make sure offset agrees with known offset. */
506 if (item_offset != ffestorag_offset (item_st))
511 sprintf (&io1[0], "%" ffetargetOffset_f "d", item_offset);
512 sprintf (&io2[0], "%" ffetargetOffset_f "d", ffestorag_offset (item_st));
513 ffebad_start (FFEBAD_EQUIV_MISMATCH);
514 ffebad_string (ffesymbol_text (item_sym));
515 ffebad_string (ffesymbol_text (root_sym));
521 ffesymbol_set_equiv (item_sym, NULL); /* Don't bother with me anymore. */
522 } /* (For every equivalence item in the list) */
523 ffebld_set_head (list, NULL); /* Don't do this list again. */
524 } /* (For every equivalence list in the list of
526 } while (new_storage && need_storage);
528 ffesymbol_set_equiv (root_sym, NULL); /* This one has storage now. */
530 ffeequiv_kill (eq); /* Fully processed, no longer needed. */
532 /* If the offset for this storage area is zero (it cannot be positive),
533 that means the alignment/modulo info is already correct. Otherwise,
534 the alignment info is correct, but the modulo info reflects a
535 zero offset, so fix it. */
537 if (ffestorag_offset (st) < 0)
539 /* Calculate the initial padding necessary to preserve
540 the alignment/modulo requirements for the storage area.
541 These requirements are themselves kept track of in the
542 record for the storage area as a whole, but really pertain
543 to offset 0 of that area, which is where the root symbol
544 was originally placed.
546 The goal here is to have the offset and size for the area
547 faithfully reflect the area itself, not extra requirements
548 like alignment. So to meet the alignment requirements,
549 the modulo for the area should be set as if the area had an
550 alignment requirement of alignment/0 and was aligned/padded
551 downward to meet the alignment requirements of the area at
552 offset zero, the amount of padding needed being the desired
553 value for the modulo of the area. */
555 alignment = ffestorag_alignment (st);
556 modulo = ffestorag_modulo (st);
558 /* Since we want to move the whole area *down* (lower memory
559 addresses) as required by the alignment/modulo paid, negate
560 the offset to ffetarget_align, which assumes aligning *up*
562 pad = ffetarget_align (&alignment, &modulo,
563 - ffestorag_offset (st),
565 ffestorag_set_modulo (st, pad);
569 ffedata_gather (st); /* Gather subordinate inits into one init. */
572 /* ffeequiv_offset_ -- Determine offset from start of symbol
574 ffetargetOffset offset;
575 ffesymbol s; // Symbol for error reporting.
576 ffebld expr; // opSUBSTR, opARRAYREF, opSYMTER, opANY.
577 bool subtract; // FALSE means add to adjust, TRUE means subtract from it.
578 ffetargetOffset adjust; // Helps keep answer in pos range (unsigned).
579 if (!ffeequiv_offset_(&offset,s,expr,subtract,adjust))
580 // error doing the calculation, message already printed
582 Returns the offset represented by the SUBSTR, ARRAYREF, or SUBSTR/ARRAYREF
583 combination added-to/subtracted-from the adjustment specified. If there
584 is an error of some kind, returns FALSE, else returns TRUE. Note that
585 only the first storage unit specified is considered; A(1:1) and A(1:2000)
586 have the same first storage unit and so return the same offset. */
589 ffeequiv_offset_ (ffetargetOffset *offset, ffesymbol s UNUSED,
590 ffebld expr, bool subtract, ffetargetOffset adjust,
593 ffetargetIntegerDefault value = 0;
594 ffetargetOffset cval; /* Converted value. */
600 again: /* :::::::::::::::::::: */
602 switch (ffebld_op (expr))
607 case FFEBLD_opSYMTER:
609 ffetargetOffset size; /* Size of a single unit. */
610 ffetargetAlign a; /* Ignored. */
611 ffetargetAlign m; /* Ignored. */
613 sym = ffebld_symter (expr);
614 if (ffesymbol_basictype (sym) == FFEINFO_basictypeANY)
617 ffetarget_layout (ffesymbol_text (sym), &a, &m, &size,
618 ffesymbol_basictype (sym),
619 ffesymbol_kindtype (sym), 1, 1);
622 { /* Really invalid, as in A(-2:5), but in case
624 if (!ffetarget_offset (&cval, -value))
627 if (!ffetarget_offset_multiply (&cval, cval, size))
631 return ffetarget_offset_add (offset, cval, adjust);
633 if (no_precede && (cval > adjust))
635 neg: /* :::::::::::::::::::: */
636 ffebad_start (FFEBAD_COMMON_NEG);
637 ffebad_string (ffesymbol_text (sym));
641 return ffetarget_offset_add (offset, -cval, adjust);
644 if (!ffetarget_offset (&cval, value))
647 if (!ffetarget_offset_multiply (&cval, cval, size))
651 return ffetarget_offset_add (offset, cval, adjust);
653 if (no_precede && (cval > adjust))
654 goto neg; /* :::::::::::::::::::: */
656 return ffetarget_offset_add (offset, -cval, adjust);
659 case FFEBLD_opARRAYREF:
661 ffebld symexp = ffebld_left (expr);
662 ffebld subscripts = ffebld_right (expr);
664 ffetargetIntegerDefault width;
665 ffetargetIntegerDefault arrayval;
666 ffetargetIntegerDefault lowbound;
667 ffetargetIntegerDefault highbound;
674 if (ffebld_op (symexp) != FFEBLD_opSYMTER)
677 sym = ffebld_symter (symexp);
678 if (ffesymbol_basictype (sym) == FFEINFO_basictypeANY)
681 if (ffesymbol_size (sym) == FFETARGET_charactersizeNONE)
684 width = ffesymbol_size (sym);
685 dims = ffesymbol_dims (sym);
687 while (subscripts != NULL)
692 ffebad_start (FFEBAD_EQUIV_MANY);
693 ffebad_string (ffesymbol_text (sym));
698 subscript = ffebld_head (subscripts);
699 dim = ffebld_head (dims);
701 assert (ffebld_op (subscript) == FFEBLD_opCONTER);
702 assert (ffeinfo_basictype (ffebld_info (subscript))
703 == FFEINFO_basictypeINTEGER);
704 assert (ffeinfo_kindtype (ffebld_info (subscript))
705 == FFEINFO_kindtypeINTEGERDEFAULT);
706 arrayval = ffebld_constant_integerdefault (ffebld_conter
709 assert (ffebld_op (dim) == FFEBLD_opBOUNDS);
710 low = ffebld_left (dim);
711 high = ffebld_right (dim);
717 assert (ffeinfo_basictype (ffebld_info (low))
718 == FFEINFO_basictypeINTEGER);
719 assert (ffeinfo_kindtype (ffebld_info (low))
720 == FFEINFO_kindtypeINTEGERDEFAULT);
722 = ffebld_constant_integerdefault (ffebld_conter (low));
725 assert (ffebld_op (high) == FFEBLD_opCONTER);
726 assert (ffeinfo_basictype (ffebld_info (high))
727 == FFEINFO_basictypeINTEGER);
728 assert (ffeinfo_kindtype (ffebld_info (high))
729 == FFEINFO_kindtypeINTEGER1);
731 = ffebld_constant_integerdefault (ffebld_conter (high));
733 if ((arrayval < lowbound) || (arrayval > highbound))
737 sprintf (rankstr, "%d", rank);
738 ffebad_start (FFEBAD_EQUIV_SUBSCRIPT);
739 ffebad_string (ffesymbol_text (sym));
740 ffebad_string (rankstr);
744 subscripts = ffebld_trail (subscripts);
745 dims = ffebld_trail (dims);
747 value += width * (arrayval - lowbound);
748 if (subscripts != NULL)
749 width *= highbound - lowbound + 1;
754 ffebad_start (FFEBAD_EQUIV_FEW);
755 ffebad_string (ffesymbol_text (sym));
762 goto again; /* :::::::::::::::::::: */
764 case FFEBLD_opSUBSTR:
766 ffebld begin = ffebld_head (ffebld_right (expr));
768 expr = ffebld_left (expr);
769 if (ffebld_op (expr) == FFEBLD_opARRAYREF)
770 sym = ffebld_symter (ffebld_left (expr));
771 else if (ffebld_op (expr) == FFEBLD_opSYMTER)
772 sym = ffebld_symter (expr);
777 && (ffesymbol_basictype (sym) == FFEINFO_basictypeANY))
784 assert (ffebld_op (begin) == FFEBLD_opCONTER);
785 assert (ffeinfo_basictype (ffebld_info (begin))
786 == FFEINFO_basictypeINTEGER);
787 assert (ffeinfo_kindtype (ffebld_info (begin))
788 == FFEINFO_kindtypeINTEGERDEFAULT);
790 value = ffebld_constant_integerdefault (ffebld_conter (begin));
794 && (value > ffesymbol_size (sym))))
796 ffebad_start (FFEBAD_EQUIV_RANGE);
797 ffebad_string (ffesymbol_text (sym));
804 && (ffesymbol_basictype (sym) != FFEINFO_basictypeCHARACTER))
806 ffebad_start (FFEBAD_EQUIV_SUBSTR);
807 ffebad_string (ffesymbol_text (sym));
812 goto again; /* :::::::::::::::::::: */
815 assert ("bad op" == NULL);
821 /* ffeequiv_add -- Add list of equivalences to list of lists for eq object
825 ffelexToken t; // points to first item in equivalence list
826 ffeequiv_add(eq,list,t);
828 Check the list to make sure only one common symbol is involved (even
829 if multiple times) and agrees with the common symbol for the equivalence
830 object (or it has no common symbol until now). Prepend (or append, it
831 doesn't matter) the list to the list of lists for the equivalence object.
832 Otherwise report an error and return. */
835 ffeequiv_add (ffeequiv eq, ffebld list, ffelexToken t)
839 ffesymbol common = ffeequiv_common (eq);
841 for (item = list; item != NULL; item = ffebld_trail (item))
843 symbol = ffeequiv_symbol (ffebld_head (item));
845 if (ffesymbol_common (symbol) != NULL) /* Is symbol known in COMMON yet? */
848 common = ffesymbol_common (symbol);
849 else if (common != ffesymbol_common (symbol))
851 /* Yes, and symbol disagrees with others on the COMMON area. */
852 ffebad_start (FFEBAD_EQUIV_COMMON);
853 ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t));
854 ffebad_string (ffesymbol_text (common));
855 ffebad_string (ffesymbol_text (ffesymbol_common (symbol)));
863 && (ffeequiv_common (eq) == NULL)) /* Is COMMON involved already? */
864 ffeequiv_set_common (eq, common); /* No, but it is now. */
866 for (item = list; item != NULL; item = ffebld_trail (item))
868 symbol = ffeequiv_symbol (ffebld_head (item));
870 if (ffesymbol_equiv (symbol) == NULL)
871 ffesymbol_set_equiv (symbol, eq);
873 assert (ffesymbol_equiv (symbol) == eq);
875 if (ffesymbol_common (symbol) == NULL) /* Is symbol in a COMMON
877 { /* No (at least not yet). */
878 if (ffesymbol_is_save (symbol))
879 ffeequiv_update_save (eq); /* EQUIVALENCE has >=1 SAVEd entity. */
880 if (ffesymbol_is_init (symbol))
881 ffeequiv_update_init (eq); /* EQUIVALENCE has >=1 init'd entity. */
882 continue; /* Nothing more to do here. */
885 #if FFEGLOBAL_ENABLED
886 if (ffesymbol_is_init (symbol))
887 ffeglobal_init_common (ffesymbol_common (symbol), t);
890 if (ffesymbol_is_save (ffesymbol_common (symbol)))
891 ffeequiv_update_save (eq); /* EQUIVALENCE is in a SAVEd COMMON block. */
892 if (ffesymbol_is_init (ffesymbol_common (symbol)))
893 ffeequiv_update_init (eq); /* EQUIVALENCE is in a init'd COMMON block. */
896 ffeequiv_set_list (eq, ffebld_new_item (list, ffeequiv_list (eq)));
899 /* ffeequiv_dump -- Dump info on equivalence object
902 ffeequiv_dump(eq); */
904 #if FFECOM_targetCURRENT == FFECOM_targetFFE
906 ffeequiv_dump (ffeequiv eq)
908 if (ffeequiv_common (eq) != NULL)
909 fprintf (dmpout, "(common %s) ", ffesymbol_text (ffeequiv_common (eq)));
910 ffebld_dump (ffeequiv_list (eq));
914 /* ffeequiv_exec_transition -- Do the hard work on all the equivalence objects
916 ffeequiv_exec_transition(); */
919 ffeequiv_exec_transition ()
921 while (ffeequiv_list_.first != (ffeequiv) &ffeequiv_list_.first)
922 ffeequiv_layout_local_ (ffeequiv_list_.first);
925 /* ffeequiv_init_2 -- Initialize for new program unit
929 Initializes the list of equivalences. */
934 ffeequiv_list_.first = (ffeequiv) &ffeequiv_list_.first;
935 ffeequiv_list_.last = (ffeequiv) &ffeequiv_list_.first;
938 /* ffeequiv_kill -- Kill equivalence object after removing from list
943 Removes equivalence object from master list, then kills it. */
946 ffeequiv_kill (ffeequiv victim)
948 victim->next->previous = victim->previous;
949 victim->previous->next = victim->next;
950 if (ffe_is_do_internal_checks ())
956 /* Assert that nobody our victim points to still points to it. */
958 assert ((victim->common == NULL)
959 || (ffesymbol_equiv (victim->common) == NULL));
961 for (list = victim->list; list != NULL; list = ffebld_trail (list))
963 for (item = ffebld_head (list); item != NULL; item = ffebld_trail (item))
967 expr = ffebld_head (item);
968 sym = ffeequiv_symbol (expr);
971 assert (ffesymbol_equiv (sym) != victim);
975 malloc_kill_ks (ffe_pool_program_unit (), victim, sizeof (*victim));
978 /* ffeequiv_layout_cblock -- Lay out storage for common area
981 if (ffeequiv_layout_cblock(st))
982 // at least one equiv'd symbol has init/accretion expr.
984 Now that the explicitly COMMONed variables in the common area (whose
985 ffestorag object is passed) have been laid out, lay out the storage
986 for all variables equivalenced into the area by making subordinate
987 ffestorag objects for them. */
990 ffeequiv_layout_cblock (ffestorag st)
992 ffesymbol s = ffestorag_symbol (st); /* CBLOCK symbol. */
993 ffebld list; /* List of explicit common vars, in order, in
995 ffebld item; /* List of list of equivalences in a given
996 explicit common var. */
997 ffebld root; /* Expression for (1st) explicit common var
999 ffestorag rst; /* Storage for root. */
1000 ffetargetOffset root_offset; /* Offset for root into common area. */
1001 ffesymbol sr; /* Root itself. */
1002 ffeequiv seq; /* Its equivalence object, if any. */
1003 ffebld var; /* Expression for equivalence. */
1004 ffestorag vst; /* Storage for var. */
1005 ffetargetOffset var_offset; /* Offset for var into common area. */
1006 ffesymbol sv; /* Var itself. */
1007 ffebld altroot; /* Alternate root. */
1008 ffesymbol altrootsym; /* Alternate root symbol. */
1009 ffetargetAlign alignment;
1010 ffetargetAlign modulo;
1012 ffetargetOffset size;
1013 ffetargetOffset num_elements;
1014 bool new_storage; /* Established new storage info. */
1015 bool need_storage; /* Have need for more storage info. */
1019 assert (st != NULL);
1020 assert (ffestorag_type (st) == FFESTORAG_typeCBLOCK);
1021 assert (ffesymbol_kind (ffestorag_symbol (st)) == FFEINFO_kindCOMMON);
1023 for (list = ffesymbol_commonlist (ffestorag_symbol (st));
1025 list = ffebld_trail (list))
1026 { /* For every variable in the common area */
1027 assert (ffebld_op (ffebld_head (list)) == FFEBLD_opSYMTER);
1028 sr = ffebld_symter (ffebld_head (list));
1029 if ((seq = ffesymbol_equiv (sr)) == NULL)
1030 continue; /* No equivalences to process. */
1031 rst = ffesymbol_storage (sr);
1034 assert (ffesymbol_kind (sr) == FFEINFO_kindANY);
1037 ffesymbol_set_equiv (sr, NULL); /* Cancel ref to equiv obj. */
1040 new_storage = FALSE;
1041 need_storage = FALSE;
1042 for (item = ffeequiv_list (seq); /* Get list of equivs. */
1044 item = ffebld_trail (item))
1045 { /* For every eqv list in the list of equivs
1049 for (root = ffebld_head (item);
1051 root = ffebld_trail (root))
1052 { /* For every equivalence item in the list */
1053 sv = ffeequiv_symbol (ffebld_head (root));
1055 break; /* Found first mention of "rooted" symbol. */
1056 if (ffesymbol_storage (sv) != NULL)
1058 altroot = root; /* If no mention, use this guy
1065 root = ffebld_head (root); /* Lose its opITEM. */
1066 ok = ffeequiv_offset_ (&root_offset, sr, root, FALSE,
1067 ffestorag_offset (rst), TRUE);
1068 /* Equiv point prior to start of common area? */
1070 else if (altroot != NULL)
1072 /* Equiv point prior to start of common area? */
1073 root = ffebld_head (altroot);
1074 ok = ffeequiv_offset_ (&root_offset, altrootsym, root,
1076 ffestorag_offset (ffesymbol_storage (altrootsym)),
1078 ffesymbol_set_equiv (altrootsym, NULL);
1081 /* No rooted symbol in list of equivalences! */
1082 { /* Assume this was due to opANY and ignore
1083 this list for now. */
1084 need_storage = TRUE;
1088 /* We now know the root symbol and the operating offset of that
1089 root into the common area. The other expressions in the
1090 list all identify an initial storage unit that must have the
1093 for (var = ffebld_head (item);
1095 var = ffebld_trail (var))
1096 { /* For every equivalence item in the list */
1097 if (ffebld_head (var) == root)
1098 continue; /* Except root, of course. */
1099 sv = ffeequiv_symbol (ffebld_head (var));
1101 continue; /* Except erroneous stuff (opANY). */
1102 ffesymbol_set_equiv (sv, NULL); /* Don't need this ref
1105 || !ffeequiv_offset_ (&var_offset, sv,
1106 ffebld_head (var), TRUE,
1108 continue; /* Can't do negative offset wrt COMMON. */
1110 if (ffesymbol_rank (sv) == 0)
1113 num_elements = ffebld_constant_integerdefault
1114 (ffebld_conter (ffesymbol_arraysize (sv)));
1115 ffetarget_layout (ffesymbol_text (sv), &alignment,
1117 ffesymbol_basictype (sv),
1118 ffesymbol_kindtype (sv),
1119 ffesymbol_size (sv), num_elements);
1120 pad = ffetarget_align (ffestorag_ptr_to_alignment (st),
1121 ffestorag_ptr_to_modulo (st),
1122 var_offset, alignment, modulo);
1125 ffebad_start (FFEBAD_EQUIV_ALIGN);
1126 ffebad_string (ffesymbol_text (sv));
1131 if ((vst = ffesymbol_storage (sv)) == NULL)
1132 { /* Create new ffestorag object, extend
1135 vst = ffestorag_new (ffestorag_list_equivs (st));
1136 ffestorag_set_parent (vst, st); /* Initializations
1138 ffestorag_set_init (vst, NULL);
1139 ffestorag_set_accretion (vst, NULL);
1140 ffestorag_set_symbol (vst, sv);
1141 ffestorag_set_size (vst, size);
1142 ffestorag_set_offset (vst, var_offset);
1143 ffestorag_set_alignment (vst, alignment);
1144 ffestorag_set_modulo (vst, modulo);
1145 ffestorag_set_type (vst, FFESTORAG_typeEQUIV);
1146 ffestorag_set_basictype (vst, ffesymbol_basictype (sv));
1147 ffestorag_set_kindtype (vst, ffesymbol_kindtype (sv));
1148 ffestorag_set_typesymbol (vst, sv);
1149 ffestorag_set_is_save (vst, FALSE); /* Assume FALSE... */
1150 if (ffestorag_is_save (st)) /* ...update TRUE */
1151 ffestorag_update_save (vst); /* if needed. */
1152 ffestorag_set_is_init (vst, FALSE); /* Assume FALSE... */
1153 if (ffestorag_is_init (st)) /* ...update TRUE */
1154 ffestorag_update_init (vst); /* if needed. */
1155 if (!ffetarget_offset_add (&size, var_offset, size))
1156 /* Find one size of common block, complain if
1158 ffetarget_offset_overflow (ffesymbol_text (s));
1159 else if (size > ffestorag_size (st))
1160 /* Extend common. */
1161 ffestorag_set_size (st, size);
1162 ffesymbol_set_storage (sv, vst);
1163 ffesymbol_set_common (sv, s);
1164 ffesymbol_signal_unreported (sv);
1165 ffestorag_update (st, sv, ffesymbol_basictype (sv),
1166 ffesymbol_kindtype (sv));
1167 if (ffesymbol_is_init (sv))
1172 /* Make sure offset agrees with known offset. */
1173 if (var_offset != ffestorag_offset (vst))
1178 sprintf (&io1[0], "%" ffetargetOffset_f "d", var_offset);
1179 sprintf (&io2[0], "%" ffetargetOffset_f "d", ffestorag_offset (vst));
1180 ffebad_start (FFEBAD_EQUIV_MISMATCH);
1181 ffebad_string (ffesymbol_text (sv));
1182 ffebad_string (ffesymbol_text (s));
1183 ffebad_string (io1);
1184 ffebad_string (io2);
1188 } /* (For every equivalence item in the list) */
1189 } /* (For every eqv list in the list of equivs
1190 for the variable) */
1192 while (new_storage && need_storage);
1194 ffeequiv_kill (seq); /* Kill equiv obj. */
1195 } /* (For every variable in the common area) */
1200 /* ffeequiv_merge -- Merge two equivalence objects, return the merged result
1204 ffelexToken t; // points to current equivalence item forcing the merge.
1205 eq1 = ffeequiv_merge(eq1,eq2,t);
1207 If the two equivalence objects can be merged, they are, all the
1208 ffesymbols in their lists of lists are adjusted to point to the merged
1209 equivalence object, and the merged object is returned.
1211 Otherwise, the two equivalence objects have different non-NULL common
1212 symbols, so the merge cannot take place. An error message is issued and
1213 NULL is returned. */
1216 ffeequiv_merge (ffeequiv eq1, ffeequiv eq2, ffelexToken t)
1223 /* If both equivalence objects point to different common-based symbols,
1224 complain. Of course, one or both might have NULL common symbols now,
1225 and get COMMONed later, but the COMMON statement handler checks for
1228 if ((ffeequiv_common (eq1) != NULL) && (ffeequiv_common (eq2) != NULL)
1229 && (ffeequiv_common (eq1) != ffeequiv_common (eq2)))
1231 ffebad_start (FFEBAD_EQUIV_COMMON);
1232 ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t));
1233 ffebad_string (ffesymbol_text (ffeequiv_common (eq1)));
1234 ffebad_string (ffesymbol_text (ffeequiv_common (eq2)));
1239 /* Make eq1 the new, merged object (arbitrarily). */
1241 if (ffeequiv_common (eq1) == NULL)
1242 ffeequiv_set_common (eq1, ffeequiv_common (eq2));
1244 /* If the victim object has any init'ed entities, so does the new object. */
1247 eq1->is_init = TRUE;
1249 #if FFEGLOBAL_ENABLED
1250 if (eq1->is_init && (ffeequiv_common (eq1) != NULL))
1251 ffeglobal_init_common (ffeequiv_common (eq1), t);
1254 /* If the victim object has any SAVEd entities, then the new object has
1257 if (ffeequiv_is_save (eq2))
1258 ffeequiv_update_save (eq1);
1260 /* If the victim object has any init'd entities, then the new object has
1263 if (ffeequiv_is_init (eq2))
1264 ffeequiv_update_init (eq1);
1266 /* Adjust all the symbols in the list of lists of equivalences for the
1267 victim equivalence object so they point to the new merged object
1270 for (list = ffeequiv_list (eq2); list != NULL; list = ffebld_trail (list))
1272 for (eqs = ffebld_head (list); eqs != NULL; eqs = ffebld_trail (eqs))
1274 symbol = ffeequiv_symbol (ffebld_head (eqs));
1275 if (ffesymbol_equiv (symbol) == eq2)
1276 ffesymbol_set_equiv (symbol, eq1);
1278 assert (ffesymbol_equiv (symbol) == eq1); /* Can see a sym > once. */
1281 /* For convenience, remember where the last ITEM in the outer list is. */
1283 if (ffebld_trail (list) == NULL)
1290 /* Append the list of lists in the new, merged object to the list of lists
1291 in the victim object, then use the new combined list in the new merged
1294 ffebld_set_trail (last, ffeequiv_list (eq1));
1295 ffeequiv_set_list (eq1, ffeequiv_list (eq2));
1297 /* Unlink and kill the victim object. */
1299 ffeequiv_kill (eq2);
1301 return eq1; /* Return the new merged object. */
1304 /* ffeequiv_new -- Create new equivalence object, put in list
1307 eq = ffeequiv_new();
1309 Creates a new equivalence object and adds it to the list of equivalence
1317 eq = malloc_new_ks (ffe_pool_program_unit (), "ffeequiv", sizeof (*eq));
1318 eq->next = (ffeequiv) &ffeequiv_list_.first;
1319 eq->previous = ffeequiv_list_.last;
1320 ffeequiv_set_common (eq, NULL); /* No COMMON area yet. */
1321 ffeequiv_set_list (eq, NULL); /* No list of lists of equivalences yet. */
1322 ffeequiv_set_is_save (eq, FALSE);
1323 ffeequiv_set_is_init (eq, FALSE);
1324 eq->next->previous = eq;
1325 eq->previous->next = eq;
1330 /* ffeequiv_symbol -- Return symbol for equivalence expression
1334 symbol = ffeequiv_symbol(expr);
1336 Finds the terminal SYMTER in an equivalence expression and returns the
1337 ffesymbol for it. */
1340 ffeequiv_symbol (ffebld expr)
1342 assert (expr != NULL);
1344 again: /* :::::::::::::::::::: */
1346 switch (ffebld_op (expr))
1348 case FFEBLD_opARRAYREF:
1349 case FFEBLD_opSUBSTR:
1350 expr = ffebld_left (expr);
1351 goto again; /* :::::::::::::::::::: */
1353 case FFEBLD_opSYMTER:
1354 return ffebld_symter (expr);
1360 assert ("bad eq expr" == NULL);
1365 /* ffeequiv_update_init -- Update the INIT flag for the area to TRUE
1368 ffeequiv_update_init(eq);
1370 If the INIT flag for the <eq> object is already set, return. Else,
1371 set it TRUE and call ffe*_update_init for all objects contained in
1375 ffeequiv_update_init (ffeequiv eq)
1377 ffebld list; /* Current list in list of lists. */
1378 ffebld item; /* Current item in current list. */
1379 ffebld expr; /* Expression in head of current item. */
1386 if ((eq->common != NULL)
1387 && !ffesymbol_is_init (eq->common))
1388 ffesymbol_update_init (eq->common); /* Shouldn't be needed. */
1390 for (list = eq->list; list != NULL; list = ffebld_trail (list))
1392 for (item = ffebld_head (list); item != NULL; item = ffebld_trail (item))
1394 expr = ffebld_head (item);
1396 again: /* :::::::::::::::::::: */
1398 switch (ffebld_op (expr))
1403 case FFEBLD_opSYMTER:
1404 if (!ffesymbol_is_init (ffebld_symter (expr)))
1405 ffesymbol_update_init (ffebld_symter (expr));
1408 case FFEBLD_opARRAYREF:
1409 expr = ffebld_left (expr);
1410 goto again; /* :::::::::::::::::::: */
1412 case FFEBLD_opSUBSTR:
1413 expr = ffebld_left (expr);
1414 goto again; /* :::::::::::::::::::: */
1417 assert ("bad op for ffeequiv_update_init" == NULL);
1424 /* ffeequiv_update_save -- Update the SAVE flag for the area to TRUE
1427 ffeequiv_update_save(eq);
1429 If the SAVE flag for the <eq> object is already set, return. Else,
1430 set it TRUE and call ffe*_update_save for all objects contained in
1434 ffeequiv_update_save (ffeequiv eq)
1436 ffebld list; /* Current list in list of lists. */
1437 ffebld item; /* Current item in current list. */
1438 ffebld expr; /* Expression in head of current item. */
1445 if ((eq->common != NULL)
1446 && !ffesymbol_is_save (eq->common))
1447 ffesymbol_update_save (eq->common); /* Shouldn't be needed. */
1449 for (list = eq->list; list != NULL; list = ffebld_trail (list))
1451 for (item = ffebld_head (list); item != NULL; item = ffebld_trail (item))
1453 expr = ffebld_head (item);
1455 again: /* :::::::::::::::::::: */
1457 switch (ffebld_op (expr))
1462 case FFEBLD_opSYMTER:
1463 if (!ffesymbol_is_save (ffebld_symter (expr)))
1464 ffesymbol_update_save (ffebld_symter (expr));
1467 case FFEBLD_opARRAYREF:
1468 expr = ffebld_left (expr);
1469 goto again; /* :::::::::::::::::::: */
1471 case FFEBLD_opSUBSTR:
1472 expr = ffebld_left (expr);
1473 goto again; /* :::::::::::::::::::: */
1476 assert ("bad op for ffeequiv_update_save" == NULL);