Do not do src->dest copy if register would not be allocated a normal register
[official-gcc.git] / gcc / f / equiv.c
blob8f87f4643420e9e04fe495dca38aaac7ba734518
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)
10 any later version.
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
20 02111-1307, USA.
22 Related Modules:
23 None
25 Description:
26 Handles the EQUIVALENCE relationships in a program unit.
28 Modifications:
31 #define FFEEQUIV_DEBUG 0
33 /* Include files. */
35 #include "proj.h"
36 #include "equiv.h"
37 #include "bad.h"
38 #include "bld.h"
39 #include "com.h"
40 #include "data.h"
41 #include "global.h"
42 #include "lex.h"
43 #include "malloc.h"
44 #include "symbol.h"
46 /* Externals defined here. */
49 /* Simple definitions and enumerations. */
52 /* Internal typedefs. */
55 /* Private include files. */
58 /* Internal structure definitions. */
60 struct _ffeequiv_list_
62 ffeequiv first;
63 ffeequiv last;
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. */
81 static void
82 ffeequiv_destroy_ (ffeequiv victim)
84 ffebld list;
85 ffebld item;
86 ffebld expr;
88 for (list = victim->list; list != NULL; list = ffebld_trail (list))
90 for (item = ffebld_head (list); item != NULL; item = ffebld_trail (item))
92 ffesymbol sym;
94 expr = ffebld_head (item);
95 sym = ffeequiv_symbol (expr);
96 if (sym == NULL)
97 continue;
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
107 ffeequiv eq;
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. */
118 static void
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;
133 ffetargetAlign pad;
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. */
138 bool init;
140 assert (eq != NULL);
142 if (ffeequiv_common (eq) != NULL)
143 { /* Put in common due to programmer error. */
144 ffeequiv_destroy_ (eq);
145 return;
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. */
152 #if FFEEQUIV_DEBUG
153 fprintf (stderr, "Equiv1:\n");
154 #endif
156 root_sym = NULL;
157 root_exp = NULL;
159 for (list = ffeequiv_list (eq);
160 list != NULL;
161 list = ffebld_trail (list))
162 { /* For every equivalence list in the list of
163 equivs */
164 for (item = ffebld_head (list);
165 item != NULL;
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
182 whole list. */
184 ffeequiv_destroy_ (eq);
185 return;
188 break; /* Use first valid eqv expr for root exp/sym. */
190 if (root_sym != NULL)
191 break;
194 if (root_sym == NULL)
196 ffeequiv_destroy_ (eq);
197 return;
201 #if FFEEQUIV_DEBUG
202 fprintf (stderr, " Root: `%s'\n", ffesymbol_text (root_sym));
203 #endif
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)
233 num_elements = 1;
234 else
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,
244 modulo);
245 assert (pad == 0);
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. */
276 new_storage = FALSE;
277 need_storage = FALSE;
278 for (list = ffeequiv_list (eq);
279 list != NULL;
280 list = ffebld_trail (list))
281 { /* For every equivalence list in the list of
282 equivs */
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. */
289 rooted_sym = NULL;
290 rooted_exp = NULL;
291 eqlist_offset = 0;
293 for (item = ffebld_head (list);
294 item != NULL;
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))
302 rooted_sym = NULL;
303 continue; /* Ignore me. */
306 need_storage = TRUE; /* Somebody is likely to need
307 storage. */
309 #if FFEEQUIV_DEBUG
310 fprintf (stderr, " Rooted: `%s' at %" ffetargetOffset_f "d\n",
311 ffesymbol_text (rooted_sym),
312 ffestorag_offset (rooted_st));
313 #endif
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
332 death. */
333 rooted_sym = NULL;
334 continue; /* Something's wrong with eqv expr, try another. */
337 #if FFEEQUIV_DEBUG
338 fprintf (stderr, " Eqlist offset: %" ffetargetOffset_f "d\n",
339 eqlist_offset);
340 #endif
342 break;
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)
352 #if FFEEQUIV_DEBUG
353 fprintf (stderr, "No roots.\n");
354 #endif
355 continue;
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
361 same offset. */
363 for (item = ffebld_head (list);
364 item != NULL;
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. */
372 item_exp = ffebld_head (item);
373 item_sym = ffeequiv_symbol (item_exp);
374 if ((item_sym == NULL)
375 || (ffesymbol_equiv (item_sym) == NULL))
376 continue; /* Ignore me. */
378 if (item_sym == rooted_sym)
379 continue; /* Rooted sym already set up. */
381 if (!ffeequiv_offset_ (&item_offset, item_sym, item_exp, TRUE,
382 eqlist_offset, FALSE))
384 ffesymbol_set_equiv (item_sym, NULL); /* Don't bother with me anymore. */
385 continue;
388 #if FFEEQUIV_DEBUG
389 fprintf (stderr, " Item `%s' at %" ffetargetOffset_f "d",
390 ffesymbol_text (item_sym), item_offset);
391 #endif
393 if (ffesymbol_rank (item_sym) == 0)
394 num_elements = 1;
395 else
396 num_elements = ffebld_constant_integerdefault (ffebld_conter
397 (ffesymbol_arraysize (item_sym)));
398 ffetarget_layout (ffesymbol_text (item_sym), &alignment, &modulo,
399 &size, ffesymbol_basictype (item_sym),
400 ffesymbol_kindtype (item_sym), ffesymbol_size (item_sym),
401 num_elements);
402 pad = ffetarget_align (ffestorag_ptr_to_alignment (st),
403 ffestorag_ptr_to_modulo (st),
404 item_offset, alignment, modulo);
405 if (pad != 0)
407 ffebad_start (FFEBAD_EQUIV_ALIGN);
408 ffebad_string (ffesymbol_text (item_sym));
409 ffebad_finish ();
410 ffesymbol_set_equiv (item_sym, NULL); /* Don't bother with me anymore. */
411 continue;
414 /* If the variable's offset is less than the offset for the
415 aggregate storage area, it means it has to expand backwards
416 -- i.e. the new known starting point of the area precedes the
417 old one. This can't happen with COMMON areas (the standard,
418 and common sense, disallow it), but it is normal for local
419 EQUIVALENCE areas.
421 Also handle choosing the "documented" rooted symbol for this
422 area here. It's the symbol at the bottom (lowest offset)
423 of the aggregate area, with ties going to the name that would
424 sort to the top of the list of ties. */
426 if (item_offset == ffestorag_offset (st))
428 if ((item_sym != ffestorag_symbol (st))
429 && (strcmp (ffesymbol_text (item_sym),
430 ffesymbol_text (ffestorag_symbol (st)))
431 < 0))
432 ffestorag_set_symbol (st, item_sym);
434 else if (item_offset < ffestorag_offset (st))
436 ffetargetOffset new_size;
438 /* Increase size of equiv area to start for lower offset relative
439 to root symbol. */
441 if (!ffetarget_offset_add (&new_size,
442 ffestorag_offset (st) - item_offset,
443 ffestorag_size (st)))
444 ffetarget_offset_overflow (ffesymbol_text (s));
445 else
446 ffestorag_set_size (st, new_size);
448 ffestorag_set_symbol (st, item_sym);
449 ffestorag_set_offset (st, item_offset);
451 #if FFEEQUIV_DEBUG
452 fprintf (stderr, " [eq offset=%" ffetargetOffset_f
453 "d, size=%" ffetargetOffset_f "d]",
454 item_offset, new_size);
455 #endif
458 if ((item_st = ffesymbol_storage (item_sym)) == NULL)
459 { /* Create new ffestorag object, extend equiv
460 area. */
461 #if FFEEQUIV_DEBUG
462 fprintf (stderr, ".\n");
463 #endif
464 new_storage = TRUE;
465 item_st = ffestorag_new (ffestorag_list_equivs (st));
466 ffestorag_set_parent (item_st, st); /* Initializations
467 happen there. */
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))
488 init = TRUE;
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));
500 else
502 #if FFEEQUIV_DEBUG
503 fprintf (stderr, " (was %" ffetargetOffset_f "d).\n",
504 ffestorag_offset (item_st));
505 #endif
506 /* Make sure offset agrees with known offset. */
507 if (item_offset != ffestorag_offset (item_st))
509 char io1[40];
510 char io2[40];
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));
517 ffebad_string (io1);
518 ffebad_string (io2);
519 ffebad_finish ();
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
526 equivs) */
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 (init)
534 ffedata_gather (st); /* Gather subordinate inits into one init. */
537 /* ffeequiv_offset_ -- Determine offset from start of symbol
539 ffetargetOffset offset;
540 ffesymbol s; // Symbol for error reporting.
541 ffebld expr; // opSUBSTR, opARRAYREF, opSYMTER, opANY.
542 bool subtract; // FALSE means add to adjust, TRUE means subtract from it.
543 ffetargetOffset adjust; // Helps keep answer in pos range (unsigned).
544 if (!ffeequiv_offset_(&offset,s,expr,subtract,adjust))
545 // error doing the calculation, message already printed
547 Returns the offset represented by the SUBSTR, ARRAYREF, or SUBSTR/ARRAYREF
548 combination added-to/subtracted-from the adjustment specified. If there
549 is an error of some kind, returns FALSE, else returns TRUE. Note that
550 only the first storage unit specified is considered; A(1:1) and A(1:2000)
551 have the same first storage unit and so return the same offset. */
553 static bool
554 ffeequiv_offset_ (ffetargetOffset *offset, ffesymbol s UNUSED,
555 ffebld expr, bool subtract, ffetargetOffset adjust,
556 bool no_precede)
558 ffetargetIntegerDefault value = 0;
559 ffetargetOffset cval; /* Converted value. */
560 ffesymbol sym;
562 if (expr == NULL)
563 return FALSE;
565 again: /* :::::::::::::::::::: */
567 switch (ffebld_op (expr))
569 case FFEBLD_opANY:
570 return FALSE;
572 case FFEBLD_opSYMTER:
574 ffetargetOffset size; /* Size of a single unit. */
575 ffetargetAlign a; /* Ignored. */
576 ffetargetAlign m; /* Ignored. */
578 sym = ffebld_symter (expr);
579 if (ffesymbol_basictype (sym) == FFEINFO_basictypeANY)
580 return FALSE;
582 ffetarget_layout (ffesymbol_text (sym), &a, &m, &size,
583 ffesymbol_basictype (sym),
584 ffesymbol_kindtype (sym), 1, 1);
586 if (value < 0)
587 { /* Really invalid, as in A(-2:5), but in case
588 it's wanted.... */
589 if (!ffetarget_offset (&cval, -value))
590 return FALSE;
592 if (!ffetarget_offset_multiply (&cval, cval, size))
593 return FALSE;
595 if (subtract)
596 return ffetarget_offset_add (offset, cval, adjust);
598 if (no_precede && (cval > adjust))
600 neg: /* :::::::::::::::::::: */
601 ffebad_start (FFEBAD_COMMON_NEG);
602 ffebad_string (ffesymbol_text (sym));
603 ffebad_finish ();
604 return FALSE;
606 return ffetarget_offset_add (offset, -cval, adjust);
609 if (!ffetarget_offset (&cval, value))
610 return FALSE;
612 if (!ffetarget_offset_multiply (&cval, cval, size))
613 return FALSE;
615 if (!subtract)
616 return ffetarget_offset_add (offset, cval, adjust);
618 if (no_precede && (cval > adjust))
619 goto neg; /* :::::::::::::::::::: */
621 return ffetarget_offset_add (offset, -cval, adjust);
624 case FFEBLD_opARRAYREF:
626 ffebld symexp = ffebld_left (expr);
627 ffebld subscripts = ffebld_right (expr);
628 ffebld dims;
629 ffetargetIntegerDefault width;
630 ffetargetIntegerDefault arrayval;
631 ffetargetIntegerDefault lowbound;
632 ffetargetIntegerDefault highbound;
633 ffebld subscript;
634 ffebld dim;
635 ffebld low;
636 ffebld high;
637 int rank = 0;
639 if (ffebld_op (symexp) != FFEBLD_opSYMTER)
640 return FALSE;
642 sym = ffebld_symter (symexp);
643 if (ffesymbol_basictype (sym) == FFEINFO_basictypeANY)
644 return FALSE;
646 if (ffesymbol_size (sym) == FFETARGET_charactersizeNONE)
647 width = 1;
648 else
649 width = ffesymbol_size (sym);
650 dims = ffesymbol_dims (sym);
652 while (subscripts != NULL)
654 ++rank;
655 if (dims == NULL)
657 ffebad_start (FFEBAD_EQUIV_MANY);
658 ffebad_string (ffesymbol_text (sym));
659 ffebad_finish ();
660 return FALSE;
663 subscript = ffebld_head (subscripts);
664 dim = ffebld_head (dims);
666 assert (ffebld_op (subscript) == FFEBLD_opCONTER);
667 assert (ffeinfo_basictype (ffebld_info (subscript))
668 == FFEINFO_basictypeINTEGER);
669 assert (ffeinfo_kindtype (ffebld_info (subscript))
670 == FFEINFO_kindtypeINTEGERDEFAULT);
671 arrayval = ffebld_constant_integerdefault (ffebld_conter
672 (subscript));
674 assert (ffebld_op (dim) == FFEBLD_opBOUNDS);
675 low = ffebld_left (dim);
676 high = ffebld_right (dim);
678 if (low == NULL)
679 lowbound = 1;
680 else
682 assert (ffeinfo_basictype (ffebld_info (low))
683 == FFEINFO_basictypeINTEGER);
684 assert (ffeinfo_kindtype (ffebld_info (low))
685 == FFEINFO_kindtypeINTEGERDEFAULT);
686 lowbound
687 = ffebld_constant_integerdefault (ffebld_conter (low));
690 assert (ffebld_op (high) == FFEBLD_opCONTER);
691 assert (ffeinfo_basictype (ffebld_info (high))
692 == FFEINFO_basictypeINTEGER);
693 assert (ffeinfo_kindtype (ffebld_info (high))
694 == FFEINFO_kindtypeINTEGER1);
695 highbound
696 = ffebld_constant_integerdefault (ffebld_conter (high));
698 if ((arrayval < lowbound) || (arrayval > highbound))
700 char rankstr[10];
702 sprintf (rankstr, "%d", rank);
703 ffebad_start (FFEBAD_EQUIV_SUBSCRIPT);
704 ffebad_string (ffesymbol_text (sym));
705 ffebad_string (rankstr);
706 ffebad_finish ();
709 subscripts = ffebld_trail (subscripts);
710 dims = ffebld_trail (dims);
712 value += width * (arrayval - lowbound);
713 if (subscripts != NULL)
714 width *= highbound - lowbound + 1;
717 if (dims != NULL)
719 ffebad_start (FFEBAD_EQUIV_FEW);
720 ffebad_string (ffesymbol_text (sym));
721 ffebad_finish ();
722 return FALSE;
725 expr = symexp;
727 goto again; /* :::::::::::::::::::: */
729 case FFEBLD_opSUBSTR:
731 ffebld begin = ffebld_head (ffebld_right (expr));
733 expr = ffebld_left (expr);
734 if (ffebld_op (expr) == FFEBLD_opARRAYREF)
735 sym = ffebld_symter (ffebld_left (expr));
736 else if (ffebld_op (expr) == FFEBLD_opSYMTER)
737 sym = ffebld_symter (expr);
738 else
739 sym = NULL;
741 if ((sym != NULL)
742 && (ffesymbol_basictype (sym) == FFEINFO_basictypeANY))
743 return FALSE;
745 if (begin == NULL)
746 value = 0;
747 else
749 assert (ffebld_op (begin) == FFEBLD_opCONTER);
750 assert (ffeinfo_basictype (ffebld_info (begin))
751 == FFEINFO_basictypeINTEGER);
752 assert (ffeinfo_kindtype (ffebld_info (begin))
753 == FFEINFO_kindtypeINTEGERDEFAULT);
755 value = ffebld_constant_integerdefault (ffebld_conter (begin));
757 if ((value < 1)
758 || ((sym != NULL)
759 && (value > ffesymbol_size (sym))))
761 ffebad_start (FFEBAD_EQUIV_RANGE);
762 ffebad_string (ffesymbol_text (sym));
763 ffebad_finish ();
766 --value;
768 if ((sym != NULL)
769 && (ffesymbol_basictype (sym) != FFEINFO_basictypeCHARACTER))
771 ffebad_start (FFEBAD_EQUIV_SUBSTR);
772 ffebad_string (ffesymbol_text (sym));
773 ffebad_finish ();
774 value = 0;
777 goto again; /* :::::::::::::::::::: */
779 default:
780 assert ("bad op" == NULL);
781 return FALSE;
786 /* ffeequiv_add -- Add list of equivalences to list of lists for eq object
788 ffeequiv eq;
789 ffebld list;
790 ffelexToken t; // points to first item in equivalence list
791 ffeequiv_add(eq,list,t);
793 Check the list to make sure only one common symbol is involved (even
794 if multiple times) and agrees with the common symbol for the equivalence
795 object (or it has no common symbol until now). Prepend (or append, it
796 doesn't matter) the list to the list of lists for the equivalence object.
797 Otherwise report an error and return. */
799 void
800 ffeequiv_add (ffeequiv eq, ffebld list, ffelexToken t)
802 ffebld item;
803 ffesymbol symbol;
804 ffesymbol common = ffeequiv_common (eq);
806 for (item = list; item != NULL; item = ffebld_trail (item))
808 symbol = ffeequiv_symbol (ffebld_head (item));
810 if (ffesymbol_common (symbol) != NULL) /* Is symbol known in COMMON yet? */
812 if (common == NULL)
813 common = ffesymbol_common (symbol);
814 else if (common != ffesymbol_common (symbol))
816 /* Yes, and symbol disagrees with others on the COMMON area. */
817 ffebad_start (FFEBAD_EQUIV_COMMON);
818 ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t));
819 ffebad_string (ffesymbol_text (common));
820 ffebad_string (ffesymbol_text (ffesymbol_common (symbol)));
821 ffebad_finish ();
822 return;
827 if ((common != NULL)
828 && (ffeequiv_common (eq) == NULL)) /* Is COMMON involved already? */
829 ffeequiv_set_common (eq, common); /* No, but it is now. */
831 for (item = list; item != NULL; item = ffebld_trail (item))
833 symbol = ffeequiv_symbol (ffebld_head (item));
835 if (ffesymbol_equiv (symbol) == NULL)
836 ffesymbol_set_equiv (symbol, eq);
837 else
838 assert (ffesymbol_equiv (symbol) == eq);
840 if (ffesymbol_common (symbol) == NULL) /* Is symbol in a COMMON
841 area? */
842 { /* No (at least not yet). */
843 if (ffesymbol_is_save (symbol))
844 ffeequiv_update_save (eq); /* EQUIVALENCE has >=1 SAVEd entity. */
845 if (ffesymbol_is_init (symbol))
846 ffeequiv_update_init (eq); /* EQUIVALENCE has >=1 init'd entity. */
847 continue; /* Nothing more to do here. */
850 #if FFEGLOBAL_ENABLED
851 if (ffesymbol_is_init (symbol))
852 ffeglobal_init_common (ffesymbol_common (symbol), t);
853 #endif
855 if (ffesymbol_is_save (ffesymbol_common (symbol)))
856 ffeequiv_update_save (eq); /* EQUIVALENCE is in a SAVEd COMMON block. */
857 if (ffesymbol_is_init (ffesymbol_common (symbol)))
858 ffeequiv_update_init (eq); /* EQUIVALENCE is in a init'd COMMON block. */
861 ffeequiv_set_list (eq, ffebld_new_item (list, ffeequiv_list (eq)));
864 /* ffeequiv_dump -- Dump info on equivalence object
866 ffeequiv eq;
867 ffeequiv_dump(eq); */
869 void
870 ffeequiv_dump (ffeequiv eq)
872 if (ffeequiv_common (eq) != NULL)
873 fprintf (dmpout, "(common %s) ", ffesymbol_text (ffeequiv_common (eq)));
874 ffebld_dump (ffeequiv_list (eq));
877 /* ffeequiv_exec_transition -- Do the hard work on all the equivalence objects
879 ffeequiv_exec_transition(); */
881 void
882 ffeequiv_exec_transition ()
884 while (ffeequiv_list_.first != (ffeequiv) &ffeequiv_list_.first)
885 ffeequiv_layout_local_ (ffeequiv_list_.first);
888 /* ffeequiv_init_2 -- Initialize for new program unit
890 ffeequiv_init_2();
892 Initializes the list of equivalences. */
894 void
895 ffeequiv_init_2 ()
897 ffeequiv_list_.first = (ffeequiv) &ffeequiv_list_.first;
898 ffeequiv_list_.last = (ffeequiv) &ffeequiv_list_.first;
901 /* ffeequiv_kill -- Kill equivalence object after removing from list
903 ffeequiv eq;
904 ffeequiv_kill(eq);
906 Removes equivalence object from master list, then kills it. */
908 void
909 ffeequiv_kill (ffeequiv victim)
911 victim->next->previous = victim->previous;
912 victim->previous->next = victim->next;
913 if (ffe_is_do_internal_checks ())
915 ffebld list;
916 ffebld item;
917 ffebld expr;
919 /* Assert that nobody our victim points to still points to it. */
921 assert ((victim->common == NULL)
922 || (ffesymbol_equiv (victim->common) == NULL));
924 for (list = victim->list; list != NULL; list = ffebld_trail (list))
926 for (item = ffebld_head (list); item != NULL; item = ffebld_trail (item))
928 ffesymbol sym;
930 expr = ffebld_head (item);
931 sym = ffeequiv_symbol (expr);
932 if (sym == NULL)
933 continue;
934 assert (ffesymbol_equiv (sym) != victim);
938 malloc_kill_ks (ffe_pool_program_unit (), victim, sizeof (*victim));
941 /* ffeequiv_layout_cblock -- Lay out storage for common area
943 ffestorag st;
944 if (ffeequiv_layout_cblock(st))
945 // at least one equiv'd symbol has init/accretion expr.
947 Now that the explicitly COMMONed variables in the common area (whose
948 ffestorag object is passed) have been laid out, lay out the storage
949 for all variables equivalenced into the area by making subordinate
950 ffestorag objects for them. */
952 bool
953 ffeequiv_layout_cblock (ffestorag st)
955 ffesymbol s = ffestorag_symbol (st); /* CBLOCK symbol. */
956 ffebld list; /* List of explicit common vars, in order, in
957 s. */
958 ffebld item; /* List of list of equivalences in a given
959 explicit common var. */
960 ffebld root; /* Expression for (1st) explicit common var
961 in list of eqs. */
962 ffestorag rst; /* Storage for root. */
963 ffetargetOffset root_offset; /* Offset for root into common area. */
964 ffesymbol sr; /* Root itself. */
965 ffeequiv seq; /* Its equivalence object, if any. */
966 ffebld var; /* Expression for equivalence. */
967 ffestorag vst; /* Storage for var. */
968 ffetargetOffset var_offset; /* Offset for var into common area. */
969 ffesymbol sv; /* Var itself. */
970 ffebld altroot; /* Alternate root. */
971 ffesymbol altrootsym; /* Alternate root symbol. */
972 ffetargetAlign alignment;
973 ffetargetAlign modulo;
974 ffetargetAlign pad;
975 ffetargetOffset size;
976 ffetargetOffset num_elements;
977 bool new_storage; /* Established new storage info. */
978 bool need_storage; /* Have need for more storage info. */
979 bool ok;
980 bool init = FALSE;
982 assert (st != NULL);
983 assert (ffestorag_type (st) == FFESTORAG_typeCBLOCK);
984 assert (ffesymbol_kind (ffestorag_symbol (st)) == FFEINFO_kindCOMMON);
986 for (list = ffesymbol_commonlist (ffestorag_symbol (st));
987 list != NULL;
988 list = ffebld_trail (list))
989 { /* For every variable in the common area */
990 assert (ffebld_op (ffebld_head (list)) == FFEBLD_opSYMTER);
991 sr = ffebld_symter (ffebld_head (list));
992 if ((seq = ffesymbol_equiv (sr)) == NULL)
993 continue; /* No equivalences to process. */
994 rst = ffesymbol_storage (sr);
995 if (rst == NULL)
997 assert (ffesymbol_kind (sr) == FFEINFO_kindANY);
998 continue;
1000 ffesymbol_set_equiv (sr, NULL); /* Cancel ref to equiv obj. */
1003 new_storage = FALSE;
1004 need_storage = FALSE;
1005 for (item = ffeequiv_list (seq); /* Get list of equivs. */
1006 item != NULL;
1007 item = ffebld_trail (item))
1008 { /* For every eqv list in the list of equivs
1009 for the variable */
1010 altroot = NULL;
1011 altrootsym = NULL;
1012 for (root = ffebld_head (item);
1013 root != NULL;
1014 root = ffebld_trail (root))
1015 { /* For every equivalence item in the list */
1016 sv = ffeequiv_symbol (ffebld_head (root));
1017 if (sv == sr)
1018 break; /* Found first mention of "rooted" symbol. */
1019 if (ffesymbol_storage (sv) != NULL)
1021 altroot = root; /* If no mention, use this guy
1022 instead. */
1023 altrootsym = sv;
1026 if (root != NULL)
1028 root = ffebld_head (root); /* Lose its opITEM. */
1029 ok = ffeequiv_offset_ (&root_offset, sr, root, FALSE,
1030 ffestorag_offset (rst), TRUE);
1031 /* Equiv point prior to start of common area? */
1033 else if (altroot != NULL)
1035 /* Equiv point prior to start of common area? */
1036 root = ffebld_head (altroot);
1037 ok = ffeequiv_offset_ (&root_offset, altrootsym, root,
1038 FALSE,
1039 ffestorag_offset (ffesymbol_storage (altrootsym)),
1040 TRUE);
1041 ffesymbol_set_equiv (altrootsym, NULL);
1043 else
1044 /* No rooted symbol in list of equivalences! */
1045 { /* Assume this was due to opANY and ignore
1046 this list for now. */
1047 need_storage = TRUE;
1048 continue;
1051 /* We now know the root symbol and the operating offset of that
1052 root into the common area. The other expressions in the
1053 list all identify an initial storage unit that must have the
1054 same offset. */
1056 for (var = ffebld_head (item);
1057 var != NULL;
1058 var = ffebld_trail (var))
1059 { /* For every equivalence item in the list */
1060 if (ffebld_head (var) == root)
1061 continue; /* Except root, of course. */
1062 sv = ffeequiv_symbol (ffebld_head (var));
1063 if (sv == NULL)
1064 continue; /* Except erroneous stuff (opANY). */
1065 ffesymbol_set_equiv (sv, NULL); /* Don't need this ref
1066 anymore. */
1067 if (!ok
1068 || !ffeequiv_offset_ (&var_offset, sv,
1069 ffebld_head (var), TRUE,
1070 root_offset, TRUE))
1071 continue; /* Can't do negative offset wrt COMMON. */
1073 if (ffesymbol_rank (sv) == 0)
1074 num_elements = 1;
1075 else
1076 num_elements = ffebld_constant_integerdefault
1077 (ffebld_conter (ffesymbol_arraysize (sv)));
1078 ffetarget_layout (ffesymbol_text (sv), &alignment,
1079 &modulo, &size,
1080 ffesymbol_basictype (sv),
1081 ffesymbol_kindtype (sv),
1082 ffesymbol_size (sv), num_elements);
1083 pad = ffetarget_align (ffestorag_ptr_to_alignment (st),
1084 ffestorag_ptr_to_modulo (st),
1085 var_offset, alignment, modulo);
1086 if (pad != 0)
1088 ffebad_start (FFEBAD_EQUIV_ALIGN);
1089 ffebad_string (ffesymbol_text (sv));
1090 ffebad_finish ();
1091 continue;
1094 if ((vst = ffesymbol_storage (sv)) == NULL)
1095 { /* Create new ffestorag object, extend
1096 cblock. */
1097 new_storage = TRUE;
1098 vst = ffestorag_new (ffestorag_list_equivs (st));
1099 ffestorag_set_parent (vst, st); /* Initializations
1100 happen there. */
1101 ffestorag_set_init (vst, NULL);
1102 ffestorag_set_accretion (vst, NULL);
1103 ffestorag_set_symbol (vst, sv);
1104 ffestorag_set_size (vst, size);
1105 ffestorag_set_offset (vst, var_offset);
1106 ffestorag_set_alignment (vst, alignment);
1107 ffestorag_set_modulo (vst, modulo);
1108 ffestorag_set_type (vst, FFESTORAG_typeEQUIV);
1109 ffestorag_set_basictype (vst, ffesymbol_basictype (sv));
1110 ffestorag_set_kindtype (vst, ffesymbol_kindtype (sv));
1111 ffestorag_set_typesymbol (vst, sv);
1112 ffestorag_set_is_save (vst, FALSE); /* Assume FALSE... */
1113 if (ffestorag_is_save (st)) /* ...update TRUE */
1114 ffestorag_update_save (vst); /* if needed. */
1115 ffestorag_set_is_init (vst, FALSE); /* Assume FALSE... */
1116 if (ffestorag_is_init (st)) /* ...update TRUE */
1117 ffestorag_update_init (vst); /* if needed. */
1118 if (!ffetarget_offset_add (&size, var_offset, size))
1119 /* Find one size of common block, complain if
1120 overflow. */
1121 ffetarget_offset_overflow (ffesymbol_text (s));
1122 else if (size > ffestorag_size (st))
1123 /* Extend common. */
1124 ffestorag_set_size (st, size);
1125 ffesymbol_set_storage (sv, vst);
1126 ffesymbol_set_common (sv, s);
1127 ffesymbol_signal_unreported (sv);
1128 ffestorag_update (st, sv, ffesymbol_basictype (sv),
1129 ffesymbol_kindtype (sv));
1130 if (ffesymbol_is_init (sv))
1131 init = TRUE;
1133 else
1135 /* Make sure offset agrees with known offset. */
1136 if (var_offset != ffestorag_offset (vst))
1138 char io1[40];
1139 char io2[40];
1141 sprintf (&io1[0], "%" ffetargetOffset_f "d", var_offset);
1142 sprintf (&io2[0], "%" ffetargetOffset_f "d", ffestorag_offset (vst));
1143 ffebad_start (FFEBAD_EQUIV_MISMATCH);
1144 ffebad_string (ffesymbol_text (sv));
1145 ffebad_string (ffesymbol_text (s));
1146 ffebad_string (io1);
1147 ffebad_string (io2);
1148 ffebad_finish ();
1151 } /* (For every equivalence item in the list) */
1152 } /* (For every eqv list in the list of equivs
1153 for the variable) */
1155 while (new_storage && need_storage);
1157 ffeequiv_kill (seq); /* Kill equiv obj. */
1158 } /* (For every variable in the common area) */
1160 return init;
1163 /* ffeequiv_merge -- Merge two equivalence objects, return the merged result
1165 ffeequiv eq1;
1166 ffeequiv eq2;
1167 ffelexToken t; // points to current equivalence item forcing the merge.
1168 eq1 = ffeequiv_merge(eq1,eq2,t);
1170 If the two equivalence objects can be merged, they are, all the
1171 ffesymbols in their lists of lists are adjusted to point to the merged
1172 equivalence object, and the merged object is returned.
1174 Otherwise, the two equivalence objects have different non-NULL common
1175 symbols, so the merge cannot take place. An error message is issued and
1176 NULL is returned. */
1178 ffeequiv
1179 ffeequiv_merge (ffeequiv eq1, ffeequiv eq2, ffelexToken t)
1181 ffebld list;
1182 ffebld eqs;
1183 ffesymbol symbol;
1184 ffebld last = NULL;
1186 /* If both equivalence objects point to different common-based symbols,
1187 complain. Of course, one or both might have NULL common symbols now,
1188 and get COMMONed later, but the COMMON statement handler checks for
1189 this. */
1191 if ((ffeequiv_common (eq1) != NULL) && (ffeequiv_common (eq2) != NULL)
1192 && (ffeequiv_common (eq1) != ffeequiv_common (eq2)))
1194 ffebad_start (FFEBAD_EQUIV_COMMON);
1195 ffebad_here (0, ffelex_token_where_line (t), ffelex_token_where_column (t));
1196 ffebad_string (ffesymbol_text (ffeequiv_common (eq1)));
1197 ffebad_string (ffesymbol_text (ffeequiv_common (eq2)));
1198 ffebad_finish ();
1199 return NULL;
1202 /* Make eq1 the new, merged object (arbitrarily). */
1204 if (ffeequiv_common (eq1) == NULL)
1205 ffeequiv_set_common (eq1, ffeequiv_common (eq2));
1207 /* If the victim object has any init'ed entities, so does the new object. */
1209 if (eq2->is_init)
1210 eq1->is_init = TRUE;
1212 #if FFEGLOBAL_ENABLED
1213 if (eq1->is_init && (ffeequiv_common (eq1) != NULL))
1214 ffeglobal_init_common (ffeequiv_common (eq1), t);
1215 #endif
1217 /* If the victim object has any SAVEd entities, then the new object has
1218 some. */
1220 if (ffeequiv_is_save (eq2))
1221 ffeequiv_update_save (eq1);
1223 /* If the victim object has any init'd entities, then the new object has
1224 some. */
1226 if (ffeequiv_is_init (eq2))
1227 ffeequiv_update_init (eq1);
1229 /* Adjust all the symbols in the list of lists of equivalences for the
1230 victim equivalence object so they point to the new merged object
1231 instead. */
1233 for (list = ffeequiv_list (eq2); list != NULL; list = ffebld_trail (list))
1235 for (eqs = ffebld_head (list); eqs != NULL; eqs = ffebld_trail (eqs))
1237 symbol = ffeequiv_symbol (ffebld_head (eqs));
1238 if (ffesymbol_equiv (symbol) == eq2)
1239 ffesymbol_set_equiv (symbol, eq1);
1240 else
1241 assert (ffesymbol_equiv (symbol) == eq1); /* Can see a sym > once. */
1244 /* For convenience, remember where the last ITEM in the outer list is. */
1246 if (ffebld_trail (list) == NULL)
1248 last = list;
1249 break;
1253 /* Append the list of lists in the new, merged object to the list of lists
1254 in the victim object, then use the new combined list in the new merged
1255 object. */
1257 ffebld_set_trail (last, ffeequiv_list (eq1));
1258 ffeequiv_set_list (eq1, ffeequiv_list (eq2));
1260 /* Unlink and kill the victim object. */
1262 ffeequiv_kill (eq2);
1264 return eq1; /* Return the new merged object. */
1267 /* ffeequiv_new -- Create new equivalence object, put in list
1269 ffeequiv eq;
1270 eq = ffeequiv_new();
1272 Creates a new equivalence object and adds it to the list of equivalence
1273 objects. */
1275 ffeequiv
1276 ffeequiv_new ()
1278 ffeequiv eq;
1280 eq = malloc_new_ks (ffe_pool_program_unit (), "ffeequiv", sizeof (*eq));
1281 eq->next = (ffeequiv) &ffeequiv_list_.first;
1282 eq->previous = ffeequiv_list_.last;
1283 ffeequiv_set_common (eq, NULL); /* No COMMON area yet. */
1284 ffeequiv_set_list (eq, NULL); /* No list of lists of equivalences yet. */
1285 ffeequiv_set_is_save (eq, FALSE);
1286 ffeequiv_set_is_init (eq, FALSE);
1287 eq->next->previous = eq;
1288 eq->previous->next = eq;
1290 return eq;
1293 /* ffeequiv_symbol -- Return symbol for equivalence expression
1295 ffesymbol symbol;
1296 ffebld expr;
1297 symbol = ffeequiv_symbol(expr);
1299 Finds the terminal SYMTER in an equivalence expression and returns the
1300 ffesymbol for it. */
1302 ffesymbol
1303 ffeequiv_symbol (ffebld expr)
1305 assert (expr != NULL);
1307 again: /* :::::::::::::::::::: */
1309 switch (ffebld_op (expr))
1311 case FFEBLD_opARRAYREF:
1312 case FFEBLD_opSUBSTR:
1313 expr = ffebld_left (expr);
1314 goto again; /* :::::::::::::::::::: */
1316 case FFEBLD_opSYMTER:
1317 return ffebld_symter (expr);
1319 case FFEBLD_opANY:
1320 return NULL;
1322 default:
1323 assert ("bad eq expr" == NULL);
1324 return NULL;
1328 /* ffeequiv_update_init -- Update the INIT flag for the area to TRUE
1330 ffeequiv eq;
1331 ffeequiv_update_init(eq);
1333 If the INIT flag for the <eq> object is already set, return. Else,
1334 set it TRUE and call ffe*_update_init for all objects contained in
1335 this one. */
1337 void
1338 ffeequiv_update_init (ffeequiv eq)
1340 ffebld list; /* Current list in list of lists. */
1341 ffebld item; /* Current item in current list. */
1342 ffebld expr; /* Expression in head of current item. */
1344 if (eq->is_init)
1345 return;
1347 eq->is_init = TRUE;
1349 if ((eq->common != NULL)
1350 && !ffesymbol_is_init (eq->common))
1351 ffesymbol_update_init (eq->common); /* Shouldn't be needed. */
1353 for (list = eq->list; list != NULL; list = ffebld_trail (list))
1355 for (item = ffebld_head (list); item != NULL; item = ffebld_trail (item))
1357 expr = ffebld_head (item);
1359 again: /* :::::::::::::::::::: */
1361 switch (ffebld_op (expr))
1363 case FFEBLD_opANY:
1364 break;
1366 case FFEBLD_opSYMTER:
1367 if (!ffesymbol_is_init (ffebld_symter (expr)))
1368 ffesymbol_update_init (ffebld_symter (expr));
1369 break;
1371 case FFEBLD_opARRAYREF:
1372 expr = ffebld_left (expr);
1373 goto again; /* :::::::::::::::::::: */
1375 case FFEBLD_opSUBSTR:
1376 expr = ffebld_left (expr);
1377 goto again; /* :::::::::::::::::::: */
1379 default:
1380 assert ("bad op for ffeequiv_update_init" == NULL);
1381 break;
1387 /* ffeequiv_update_save -- Update the SAVE flag for the area to TRUE
1389 ffeequiv eq;
1390 ffeequiv_update_save(eq);
1392 If the SAVE flag for the <eq> object is already set, return. Else,
1393 set it TRUE and call ffe*_update_save for all objects contained in
1394 this one. */
1396 void
1397 ffeequiv_update_save (ffeequiv eq)
1399 ffebld list; /* Current list in list of lists. */
1400 ffebld item; /* Current item in current list. */
1401 ffebld expr; /* Expression in head of current item. */
1403 if (eq->is_save)
1404 return;
1406 eq->is_save = TRUE;
1408 if ((eq->common != NULL)
1409 && !ffesymbol_is_save (eq->common))
1410 ffesymbol_update_save (eq->common); /* Shouldn't be needed. */
1412 for (list = eq->list; list != NULL; list = ffebld_trail (list))
1414 for (item = ffebld_head (list); item != NULL; item = ffebld_trail (item))
1416 expr = ffebld_head (item);
1418 again: /* :::::::::::::::::::: */
1420 switch (ffebld_op (expr))
1422 case FFEBLD_opANY:
1423 break;
1425 case FFEBLD_opSYMTER:
1426 if (!ffesymbol_is_save (ffebld_symter (expr)))
1427 ffesymbol_update_save (ffebld_symter (expr));
1428 break;
1430 case FFEBLD_opARRAYREF:
1431 expr = ffebld_left (expr);
1432 goto again; /* :::::::::::::::::::: */
1434 case FFEBLD_opSUBSTR:
1435 expr = ffebld_left (expr);
1436 goto again; /* :::::::::::::::::::: */
1438 default:
1439 assert ("bad op for ffeequiv_update_save" == NULL);
1440 break;