1 /* storag.c -- Implementation File (module.c template V1.0)
2 Copyright (C) 1995, 1996, 2003 Free Software Foundation, Inc.
3 Contributed by James Craig Burley.
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 Maintains information on storage (memory) relationships between
27 COMMON, dummy, and local variables, plus their equivalences (dummies
28 don't have equivalences, however).
42 /* Externals defined here. */
44 ffestoragList_ ffestorag_list_
;
46 /* Simple definitions and enumerations. */
49 /* Internal typedefs. */
52 /* Private include files. */
55 /* Internal structure definitions. */
58 /* Static objects accessed by functions in this module. */
60 static ffetargetOffset ffestorag_local_size_
; /* #units allocated so far. */
61 static bool ffestorag_reported_
;/* Reports happen only once. */
63 /* Static functions (internal). */
66 /* Internal macros. */
68 #define ffestorag_next_(s) ((s)->next)
69 #define ffestorag_previous_(s) ((s)->previous)
71 /* ffestorag_drive -- Drive fn from list of storage objects
74 void (*fn)(ffestorag mst,ffestorag st);
75 ffestorag mst; // the master ffestorag object (or whatever)
76 ffestorag_drive(sl,fn,mst);
78 Calls (*fn)(mst,st) for every st in the list sl. */
81 ffestorag_drive (ffestoragList sl
, void (*fn
) (ffestorag mst
, ffestorag st
),
87 st
!= (ffestorag
) &sl
->first
;
92 /* ffestorag_dump -- Dump information on storage object
94 ffestorag s; // the ffestorag object
97 Dumps information in the storage object. */
100 ffestorag_dump (ffestorag s
)
104 fprintf (dmpout
, "(no storage object)");
110 case FFESTORAG_typeCBLOCK
:
111 fprintf (dmpout
, "CBLOCK ");
114 case FFESTORAG_typeCOMMON
:
115 fprintf (dmpout
, "COMMON ");
118 case FFESTORAG_typeLOCAL
:
119 fprintf (dmpout
, "LOCAL ");
122 case FFESTORAG_typeEQUIV
:
123 fprintf (dmpout
, "EQUIV ");
127 fprintf (dmpout
, "?%d? ", s
->type
);
131 if (s
->symbol
!= NULL
)
132 fprintf (dmpout
, "\"%s\" ", ffesymbol_text (s
->symbol
));
134 fprintf (dmpout
, "at %" ffetargetOffset_f
"d size %" ffetargetOffset_f
136 ffetargetAlign_f
"u=%" ffetargetAlign_f
"u, bt=%s, kt=%s",
138 s
->size
, (unsigned int) s
->alignment
, (unsigned int) s
->modulo
,
139 ffeinfo_basictype_string (s
->basic_type
),
140 ffeinfo_kindtype_string (s
->kind_type
));
142 if (s
->equivs_
.first
!= (ffestorag
) &s
->equivs_
.first
)
146 fprintf (dmpout
, " with equivs");
147 for (sq
= s
->equivs_
.first
;
148 sq
!= (ffestorag
) &s
->equivs_
.first
;
149 sq
= ffestorag_next_ (sq
))
151 if (ffestorag_previous_ (sq
) == (ffestorag
) &s
->equivs_
.first
)
155 fprintf (dmpout
, "%s", ffesymbol_text (ffestorag_symbol (sq
)));
160 /* ffestorag_init_2 -- Initialize for new program unit
162 ffestorag_init_2(); */
165 ffestorag_init_2 (void)
167 ffestorag_list_
.first
= ffestorag_list_
.last
168 = (ffestorag
) &ffestorag_list_
.first
;
169 ffestorag_local_size_
= 0;
170 ffestorag_reported_
= FALSE
;
173 /* ffestorag_end_layout -- Do final layout for symbol
176 ffestorag_end_layout(s); */
179 ffestorag_end_layout (ffesymbol s
)
181 if (ffesymbol_storage (s
) != NULL
)
182 return; /* Already laid out. */
184 ffestorag_exec_layout (s
); /* Do what we have in common. */
186 assert (ffesymbol_storage (s
) == NULL
); /* I'd like to know what
187 cases miss going through
188 ffecom_sym_learned, and
189 why; I don't think we
190 should have to do the
191 exec_layout thing at all
193 /* Now I think I know: we have to do exec_layout here, because equivalence
194 handling could encounter an error that takes a variable off of its
195 equivalence object (and vice versa), and we should then layout the var
196 as a local entity. */
200 /* ffestorag_exec_layout -- Do initial layout for symbol
203 ffestorag_exec_layout(s); */
206 ffestorag_exec_layout (ffesymbol s
)
208 ffetargetAlign alignment
;
209 ffetargetAlign modulo
;
210 ffetargetOffset size
;
211 ffetargetOffset num_elements
;
220 if (ffesymbol_storage (s
) != NULL
)
221 return; /* Already laid out. */
223 switch (ffesymbol_kind (s
))
226 return; /* Do nothing. */
228 case FFEINFO_kindENTITY
:
229 switch (ffesymbol_where (s
))
231 case FFEINFO_whereLOCAL
:
232 if (ffesymbol_equiv (s
) != NULL
)
233 return; /* Let ffeequiv handle this guy. */
234 if (ffesymbol_rank (s
) == 0)
238 if (ffebld_op (ffesymbol_arraysize (s
))
240 return; /* An adjustable local array, just like a dummy. */
242 = ffebld_constant_integerdefault (ffebld_conter
243 (ffesymbol_arraysize (s
)));
245 ffetarget_layout (ffesymbol_text (s
), &alignment
, &modulo
,
246 &size
, ffesymbol_basictype (s
),
247 ffesymbol_kindtype (s
), ffesymbol_size (s
),
249 st
= ffestorag_new (ffestorag_list_master ());
250 st
->parent
= NULL
; /* Initializations happen at sym level. */
252 st
->accretion
= NULL
;
256 st
->alignment
= alignment
;
258 st
->type
= FFESTORAG_typeLOCAL
;
259 st
->basic_type
= ffesymbol_basictype (s
);
260 st
->kind_type
= ffesymbol_kindtype (s
);
262 st
->is_save
= ffesymbol_is_save (s
);
263 st
->is_init
= ffesymbol_is_init (s
);
264 ffesymbol_set_storage (s
, st
);
265 if (ffesymbol_is_init (s
))
266 ffecom_notify_init_symbol (s
); /* Init completed before, but
267 we didn't have a storage
268 object for it; maybe back
269 end wants to see the sym
271 ffesymbol_signal_unreported (s
);
274 case FFEINFO_whereCOMMON
:
275 return; /* Allocate storage for entire common block
278 case FFEINFO_whereDUMMY
:
279 return; /* Don't do anything about dummies for now. */
281 case FFEINFO_whereRESULT
:
282 case FFEINFO_whereIMMEDIATE
:
283 case FFEINFO_whereCONSTANT
:
284 case FFEINFO_whereNONE
:
285 return; /* These don't get storage (esp. NONE, which
289 assert ("bad ENTITY where" == NULL
);
294 case FFEINFO_kindCOMMON
:
295 assert (ffesymbol_where (s
) == FFEINFO_whereLOCAL
);
296 st
= ffestorag_new (ffestorag_list_master ());
297 st
->parent
= NULL
; /* Initializations happen here. */
299 st
->accretion
= NULL
;
305 st
->type
= FFESTORAG_typeCBLOCK
;
306 if (ffesymbol_commonlist (s
) != NULL
)
308 var
= ffebld_symter (ffebld_head (ffesymbol_commonlist (s
)));
309 st
->basic_type
= ffesymbol_basictype (var
);
310 st
->kind_type
= ffesymbol_kindtype (var
);
311 st
->type_symbol
= var
;
314 { /* Special case for empty common area:
315 NONE/NONE means nothing. */
316 st
->basic_type
= FFEINFO_basictypeNONE
;
317 st
->kind_type
= FFEINFO_kindtypeNONE
;
318 st
->type_symbol
= NULL
;
320 st
->is_save
= ffesymbol_is_save (s
);
321 st
->is_init
= ffesymbol_is_init (s
);
322 if (!ffe_is_mainprog ())
323 ffeglobal_save_common (s
,
324 st
->is_save
|| ffe_is_saveall (),
325 ffesymbol_where_line (s
),
326 ffesymbol_where_column (s
));
327 ffesymbol_set_storage (s
, st
);
330 for (list
= ffesymbol_commonlist (s
);
332 list
= ffebld_trail (list
))
334 item
= ffebld_head (list
);
335 assert (ffebld_op (item
) == FFEBLD_opSYMTER
);
336 var
= ffebld_symter (item
);
337 if (ffesymbol_basictype (var
) == FFEINFO_basictypeANY
)
338 continue; /* Ignore any symbols that have errors. */
339 if (ffesymbol_rank (var
) == 0)
342 num_elements
= ffebld_constant_integerdefault (ffebld_conter
343 (ffesymbol_arraysize (var
)));
344 ffetarget_layout (ffesymbol_text (var
), &alignment
, &modulo
,
345 &size
, ffesymbol_basictype (var
),
346 ffesymbol_kindtype (var
), ffesymbol_size (var
),
348 pad
= ffetarget_align (&st
->alignment
, &st
->modulo
, st
->size
,
351 { /* Warn about padding in the midst of a
355 sprintf (&padding
[0], "%" ffetargetAlign_f
"u", pad
);
356 ffebad_start (FFEBAD_COMMON_PAD
);
357 ffebad_string (padding
);
358 ffebad_string (ffesymbol_text (var
));
359 ffebad_string (ffesymbol_text (s
));
360 ffebad_string ((pad
== 1)
361 ? FFECOM_SIZE_UNIT
: FFECOM_SIZE_UNITS
);
362 ffebad_here (0, ffesymbol_where_line (s
), ffesymbol_where_column (s
));
365 stv
= ffestorag_new (ffestorag_list_master ());
366 stv
->parent
= st
; /* Initializations happen in COMMON block. */
368 stv
->accretion
= NULL
;
371 if (!ffetarget_offset_add (&stv
->offset
, st
->size
, pad
))
372 { /* Common block size plus pad, complain if
374 ffetarget_offset_overflow (ffesymbol_text (s
));
376 if (!ffetarget_offset_add (&st
->size
, stv
->offset
, stv
->size
))
377 { /* Adjust size of common block, complain if
379 ffetarget_offset_overflow (ffesymbol_text (s
));
381 stv
->alignment
= alignment
;
382 stv
->modulo
= modulo
;
383 stv
->type
= FFESTORAG_typeCOMMON
;
384 stv
->basic_type
= ffesymbol_basictype (var
);
385 stv
->kind_type
= ffesymbol_kindtype (var
);
386 stv
->type_symbol
= var
;
387 stv
->is_save
= st
->is_save
;
388 stv
->is_init
= st
->is_init
;
389 ffesymbol_set_storage (var
, stv
);
390 ffesymbol_signal_unreported (var
);
391 ffestorag_update (st
, var
, ffesymbol_basictype (var
),
392 ffesymbol_kindtype (var
));
393 if (ffesymbol_is_init (var
))
394 init
= TRUE
; /* Must move inits over to COMMON's
397 if (ffeequiv_layout_cblock (st
))
399 ffeglobal_pad_common (s
, st
->modulo
, ffesymbol_where_line (s
),
400 ffesymbol_where_column (s
));
402 ffedata_gather (st
); /* Gather subordinate inits into one init. */
403 ffesymbol_signal_unreported (s
);
408 /* ffestorag_new -- Create new ffestorag object, append to list
412 s = ffestorag_new(sl); */
415 ffestorag_new (ffestoragList sl
)
419 s
= malloc_new_kp (ffe_pool_program_unit (), "ffestorag", sizeof (*s
));
420 s
->next
= (ffestorag
) &sl
->first
;
421 s
->previous
= sl
->last
;
422 s
->hook
= FFECOM_storageNULL
;
423 s
->previous
->next
= s
;
425 s
->equivs_
.first
= s
->equivs_
.last
= (ffestorag
) &s
->equivs_
.first
;
430 /* Report info on LOCAL non-sym-assoc'ed entities if needed. */
433 ffestorag_report (void)
437 if (ffestorag_reported_
)
440 for (s
= ffestorag_list_
.first
;
441 s
!= (ffestorag
) &ffestorag_list_
.first
;
444 if (s
->symbol
== NULL
)
446 ffestorag_reported_
= TRUE
;
447 fputs ("Storage area: ", dmpout
);
449 fputc ('\n', dmpout
);
454 /* ffestorag_update -- Update type info for ffestorag object
456 ffestorag s; // existing object
457 ffeinfoBasictype bt; // basic type for newly added member of object
458 ffeinfoKindtype kt; // kind type for it
459 ffestorag_update(s,bt,kt);
461 If the existing type for the storage object agrees with the new type
462 info, just returns. If the basic types agree but not the kind types,
463 sets the kind type for the object to NONE. If the basic types
464 disagree, sets the kind type to NONE, and the basic type to NONE if the
465 basic types both are not CHARACTER, otherwise to ANY. If the basic
466 type for the object already is NONE, it is set to ANY if the new basic
467 type is CHARACTER. Any time a transition is made to ANY and pedantic
468 mode is on, a message is issued that mixing CHARACTER and non-CHARACTER
469 stuff in the same COMMON/EQUIVALENCE is invalid. */
472 ffestorag_update (ffestorag s
, ffesymbol sym
, ffeinfoBasictype bt
,
475 if (s
->basic_type
== bt
)
477 if (s
->kind_type
== kt
)
479 s
->kind_type
= FFEINFO_kindtypeNONE
;
483 switch (s
->basic_type
)
485 case FFEINFO_basictypeANY
:
486 return; /* No need to do anything further. */
488 case FFEINFO_basictypeCHARACTER
:
489 any
: /* :::::::::::::::::::: */
490 s
->basic_type
= FFEINFO_basictypeANY
;
491 s
->kind_type
= FFEINFO_kindtypeANY
;
492 if (ffe_is_pedantic ())
494 ffebad_start (FFEBAD_MIXED_TYPES
);
495 ffebad_string (ffesymbol_text (s
->type_symbol
));
496 ffebad_string (ffesymbol_text (sym
));
502 if (bt
== FFEINFO_basictypeCHARACTER
)
503 goto any
; /* :::::::::::::::::::: */
504 s
->basic_type
= FFEINFO_basictypeNONE
;
505 s
->kind_type
= FFEINFO_kindtypeNONE
;
510 /* Update INIT flag for storage object.
512 If the INIT flag for the <s> object is already TRUE, return. Else,
513 set it to TRUE and call ffe*_update_init for all contained objects. */
516 ffestorag_update_init (ffestorag s
)
525 if ((s
->symbol
!= NULL
)
526 && !ffesymbol_is_init (s
->symbol
))
527 ffesymbol_update_init (s
->symbol
);
529 if (s
->parent
!= NULL
)
530 ffestorag_update_init (s
->parent
);
532 for (sq
= s
->equivs_
.first
;
533 sq
!= (ffestorag
) &s
->equivs_
.first
;
534 sq
= ffestorag_next_ (sq
))
537 ffestorag_update_init (sq
);
541 /* Update SAVE flag for storage object.
543 If the SAVE flag for the <s> object is already TRUE, return. Else,
544 set it to TRUE and call ffe*_update_save for all contained objects. */
547 ffestorag_update_save (ffestorag s
)
556 if ((s
->symbol
!= NULL
)
557 && !ffesymbol_is_save (s
->symbol
))
558 ffesymbol_update_save (s
->symbol
);
560 if (s
->parent
!= NULL
)
561 ffestorag_update_save (s
->parent
);
563 for (sq
= s
->equivs_
.first
;
564 sq
!= (ffestorag
) &s
->equivs_
.first
;
565 sq
= ffestorag_next_ (sq
))
568 ffestorag_update_save (sq
);