trans-common.cc revision 1.1 1 1.1 mrg /* Common block and equivalence list handling
2 1.1 mrg Copyright (C) 2000-2022 Free Software Foundation, Inc.
3 1.1 mrg Contributed by Canqun Yang <canqun (at) nudt.edu.cn>
4 1.1 mrg
5 1.1 mrg This file is part of GCC.
6 1.1 mrg
7 1.1 mrg GCC is free software; you can redistribute it and/or modify it under
8 1.1 mrg the terms of the GNU General Public License as published by the Free
9 1.1 mrg Software Foundation; either version 3, or (at your option) any later
10 1.1 mrg version.
11 1.1 mrg
12 1.1 mrg GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 1.1 mrg WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 1.1 mrg FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 1.1 mrg for more details.
16 1.1 mrg
17 1.1 mrg You should have received a copy of the GNU General Public License
18 1.1 mrg along with GCC; see the file COPYING3. If not see
19 1.1 mrg <http://www.gnu.org/licenses/>. */
20 1.1 mrg
21 1.1 mrg /* The core algorithm is based on Andy Vaught's g95 tree. Also the
22 1.1 mrg way to build UNION_TYPE is borrowed from Richard Henderson.
23 1.1 mrg
24 1.1 mrg Transform common blocks. An integral part of this is processing
25 1.1 mrg equivalence variables. Equivalenced variables that are not in a
26 1.1 mrg common block end up in a private block of their own.
27 1.1 mrg
28 1.1 mrg Each common block or local equivalence list is declared as a union.
29 1.1 mrg Variables within the block are represented as a field within the
30 1.1 mrg block with the proper offset.
31 1.1 mrg
32 1.1 mrg So if two variables are equivalenced, they just point to a common
33 1.1 mrg area in memory.
34 1.1 mrg
35 1.1 mrg Mathematically, laying out an equivalence block is equivalent to
36 1.1 mrg solving a linear system of equations. The matrix is usually a
37 1.1 mrg sparse matrix in which each row contains all zero elements except
38 1.1 mrg for a +1 and a -1, a sort of a generalized Vandermonde matrix. The
39 1.1 mrg matrix is usually block diagonal. The system can be
40 1.1 mrg overdetermined, underdetermined or have a unique solution. If the
41 1.1 mrg system is inconsistent, the program is not standard conforming.
42 1.1 mrg The solution vector is integral, since all of the pivots are +1 or -1.
43 1.1 mrg
44 1.1 mrg How we lay out an equivalence block is a little less complicated.
45 1.1 mrg In an equivalence list with n elements, there are n-1 conditions to
46 1.1 mrg be satisfied. The conditions partition the variables into what we
47 1.1 mrg will call segments. If A and B are equivalenced then A and B are
48 1.1 mrg in the same segment. If B and C are equivalenced as well, then A,
49 1.1 mrg B and C are in a segment and so on. Each segment is a block of
50 1.1 mrg memory that has one or more variables equivalenced in some way. A
51 1.1 mrg common block is made up of a series of segments that are joined one
52 1.1 mrg after the other. In the linear system, a segment is a block
53 1.1 mrg diagonal.
54 1.1 mrg
55 1.1 mrg To lay out a segment we first start with some variable and
56 1.1 mrg determine its length. The first variable is assumed to start at
57 1.1 mrg offset one and extends to however long it is. We then traverse the
58 1.1 mrg list of equivalences to find an unused condition that involves at
59 1.1 mrg least one of the variables currently in the segment.
60 1.1 mrg
61 1.1 mrg Each equivalence condition amounts to the condition B+b=C+c where B
62 1.1 mrg and C are the offsets of the B and C variables, and b and c are
63 1.1 mrg constants which are nonzero for array elements, substrings or
64 1.1 mrg structure components. So for
65 1.1 mrg
66 1.1 mrg EQUIVALENCE(B(2), C(3))
67 1.1 mrg we have
68 1.1 mrg B + 2*size of B's elements = C + 3*size of C's elements.
69 1.1 mrg
70 1.1 mrg If B and C are known we check to see if the condition already
71 1.1 mrg holds. If B is known we can solve for C. Since we know the length
72 1.1 mrg of C, we can see if the minimum and maximum extents of the segment
73 1.1 mrg are affected. Eventually, we make a full pass through the
74 1.1 mrg equivalence list without finding any new conditions and the segment
75 1.1 mrg is fully specified.
76 1.1 mrg
77 1.1 mrg At this point, the segment is added to the current common block.
78 1.1 mrg Since we know the minimum extent of the segment, everything in the
79 1.1 mrg segment is translated to its position in the common block. The
80 1.1 mrg usual case here is that there are no equivalence statements and the
81 1.1 mrg common block is series of segments with one variable each, which is
82 1.1 mrg a diagonal matrix in the matrix formulation.
83 1.1 mrg
84 1.1 mrg Each segment is described by a chain of segment_info structures. Each
85 1.1 mrg segment_info structure describes the extents of a single variable within
86 1.1 mrg the segment. This list is maintained in the order the elements are
87 1.1 mrg positioned within the segment. If two elements have the same starting
88 1.1 mrg offset the smaller will come first. If they also have the same size their
89 1.1 mrg ordering is undefined.
90 1.1 mrg
91 1.1 mrg Once all common blocks have been created, the list of equivalences
92 1.1 mrg is examined for still-unused equivalence conditions. We create a
93 1.1 mrg block for each merged equivalence list. */
94 1.1 mrg
95 1.1 mrg #include "config.h"
96 1.1 mrg #define INCLUDE_MAP
97 1.1 mrg #include "system.h"
98 1.1 mrg #include "coretypes.h"
99 1.1 mrg #include "tm.h"
100 1.1 mrg #include "tree.h"
101 1.1 mrg #include "gfortran.h"
102 1.1 mrg #include "trans.h"
103 1.1 mrg #include "stringpool.h"
104 1.1 mrg #include "fold-const.h"
105 1.1 mrg #include "stor-layout.h"
106 1.1 mrg #include "varasm.h"
107 1.1 mrg #include "trans-types.h"
108 1.1 mrg #include "trans-const.h"
109 1.1 mrg #include "target-memory.h"
110 1.1 mrg
111 1.1 mrg
112 1.1 mrg /* Holds a single variable in an equivalence set. */
113 1.1 mrg typedef struct segment_info
114 1.1 mrg {
115 1.1 mrg gfc_symbol *sym;
116 1.1 mrg HOST_WIDE_INT offset;
117 1.1 mrg HOST_WIDE_INT length;
118 1.1 mrg /* This will contain the field type until the field is created. */
119 1.1 mrg tree field;
120 1.1 mrg struct segment_info *next;
121 1.1 mrg } segment_info;
122 1.1 mrg
123 1.1 mrg static segment_info * current_segment;
124 1.1 mrg
125 1.1 mrg /* Store decl of all common blocks in this translation unit; the first
126 1.1 mrg tree is the identifier. */
127 1.1 mrg static std::map<tree, tree> gfc_map_of_all_commons;
128 1.1 mrg
129 1.1 mrg
130 1.1 mrg /* Make a segment_info based on a symbol. */
131 1.1 mrg
132 1.1 mrg static segment_info *
133 1.1 mrg get_segment_info (gfc_symbol * sym, HOST_WIDE_INT offset)
134 1.1 mrg {
135 1.1 mrg segment_info *s;
136 1.1 mrg
137 1.1 mrg /* Make sure we've got the character length. */
138 1.1 mrg if (sym->ts.type == BT_CHARACTER)
139 1.1 mrg gfc_conv_const_charlen (sym->ts.u.cl);
140 1.1 mrg
141 1.1 mrg /* Create the segment_info and fill it in. */
142 1.1 mrg s = XCNEW (segment_info);
143 1.1 mrg s->sym = sym;
144 1.1 mrg /* We will use this type when building the segment aggregate type. */
145 1.1 mrg s->field = gfc_sym_type (sym);
146 1.1 mrg s->length = int_size_in_bytes (s->field);
147 1.1 mrg s->offset = offset;
148 1.1 mrg
149 1.1 mrg return s;
150 1.1 mrg }
151 1.1 mrg
152 1.1 mrg
153 1.1 mrg /* Add a copy of a segment list to the namespace. This is specifically for
154 1.1 mrg equivalence segments, so that dependency checking can be done on
155 1.1 mrg equivalence group members. */
156 1.1 mrg
157 1.1 mrg static void
158 1.1 mrg copy_equiv_list_to_ns (segment_info *c)
159 1.1 mrg {
160 1.1 mrg segment_info *f;
161 1.1 mrg gfc_equiv_info *s;
162 1.1 mrg gfc_equiv_list *l;
163 1.1 mrg
164 1.1 mrg l = XCNEW (gfc_equiv_list);
165 1.1 mrg
166 1.1 mrg l->next = c->sym->ns->equiv_lists;
167 1.1 mrg c->sym->ns->equiv_lists = l;
168 1.1 mrg
169 1.1 mrg for (f = c; f; f = f->next)
170 1.1 mrg {
171 1.1 mrg s = XCNEW (gfc_equiv_info);
172 1.1 mrg s->next = l->equiv;
173 1.1 mrg l->equiv = s;
174 1.1 mrg s->sym = f->sym;
175 1.1 mrg s->offset = f->offset;
176 1.1 mrg s->length = f->length;
177 1.1 mrg }
178 1.1 mrg }
179 1.1 mrg
180 1.1 mrg
181 1.1 mrg /* Add combine segment V and segment LIST. */
182 1.1 mrg
183 1.1 mrg static segment_info *
184 1.1 mrg add_segments (segment_info *list, segment_info *v)
185 1.1 mrg {
186 1.1 mrg segment_info *s;
187 1.1 mrg segment_info *p;
188 1.1 mrg segment_info *next;
189 1.1 mrg
190 1.1 mrg p = NULL;
191 1.1 mrg s = list;
192 1.1 mrg
193 1.1 mrg while (v)
194 1.1 mrg {
195 1.1 mrg /* Find the location of the new element. */
196 1.1 mrg while (s)
197 1.1 mrg {
198 1.1 mrg if (v->offset < s->offset)
199 1.1 mrg break;
200 1.1 mrg if (v->offset == s->offset
201 1.1 mrg && v->length <= s->length)
202 1.1 mrg break;
203 1.1 mrg
204 1.1 mrg p = s;
205 1.1 mrg s = s->next;
206 1.1 mrg }
207 1.1 mrg
208 1.1 mrg /* Insert the new element in between p and s. */
209 1.1 mrg next = v->next;
210 1.1 mrg v->next = s;
211 1.1 mrg if (p == NULL)
212 1.1 mrg list = v;
213 1.1 mrg else
214 1.1 mrg p->next = v;
215 1.1 mrg
216 1.1 mrg p = v;
217 1.1 mrg v = next;
218 1.1 mrg }
219 1.1 mrg
220 1.1 mrg return list;
221 1.1 mrg }
222 1.1 mrg
223 1.1 mrg
224 1.1 mrg /* Construct mangled common block name from symbol name. */
225 1.1 mrg
226 1.1 mrg /* We need the bind(c) flag to tell us how/if we should mangle the symbol
227 1.1 mrg name. There are few calls to this function, so few places that this
228 1.1 mrg would need to be added. At the moment, there is only one call, in
229 1.1 mrg build_common_decl(). We can't attempt to look up the common block
230 1.1 mrg because we may be building it for the first time and therefore, it won't
231 1.1 mrg be in the common_root. We also need the binding label, if it's bind(c).
232 1.1 mrg Therefore, send in the pointer to the common block, so whatever info we
233 1.1 mrg have so far can be used. All of the necessary info should be available
234 1.1 mrg in the gfc_common_head by now, so it should be accurate to test the
235 1.1 mrg isBindC flag and use the binding label given if it is bind(c).
236 1.1 mrg
237 1.1 mrg We may NOT know yet if it's bind(c) or not, but we can try at least.
238 1.1 mrg Will have to figure out what to do later if it's labeled bind(c)
239 1.1 mrg after this is called. */
240 1.1 mrg
241 1.1 mrg static tree
242 1.1 mrg gfc_sym_mangled_common_id (gfc_common_head *com)
243 1.1 mrg {
244 1.1 mrg int has_underscore;
245 1.1 mrg /* Provide sufficient space to hold "symbol.symbol.eq.1234567890__". */
246 1.1 mrg char mangled_name[2*GFC_MAX_MANGLED_SYMBOL_LEN + 1 + 16 + 1];
247 1.1 mrg char name[sizeof (mangled_name) - 2];
248 1.1 mrg
249 1.1 mrg /* Get the name out of the common block pointer. */
250 1.1 mrg size_t len = strlen (com->name);
251 1.1 mrg gcc_assert (len < sizeof (name));
252 1.1 mrg strcpy (name, com->name);
253 1.1 mrg
254 1.1 mrg /* If we're suppose to do a bind(c). */
255 1.1 mrg if (com->is_bind_c == 1 && com->binding_label)
256 1.1 mrg return get_identifier (com->binding_label);
257 1.1 mrg
258 1.1 mrg if (strcmp (name, BLANK_COMMON_NAME) == 0)
259 1.1 mrg return get_identifier (name);
260 1.1 mrg
261 1.1 mrg if (flag_underscoring)
262 1.1 mrg {
263 1.1 mrg has_underscore = strchr (name, '_') != 0;
264 1.1 mrg if (flag_second_underscore && has_underscore)
265 1.1 mrg snprintf (mangled_name, sizeof mangled_name, "%s__", name);
266 1.1 mrg else
267 1.1 mrg snprintf (mangled_name, sizeof mangled_name, "%s_", name);
268 1.1 mrg
269 1.1 mrg return get_identifier (mangled_name);
270 1.1 mrg }
271 1.1 mrg else
272 1.1 mrg return get_identifier (name);
273 1.1 mrg }
274 1.1 mrg
275 1.1 mrg
276 1.1 mrg /* Build a field declaration for a common variable or a local equivalence
277 1.1 mrg object. */
278 1.1 mrg
279 1.1 mrg static void
280 1.1 mrg build_field (segment_info *h, tree union_type, record_layout_info rli)
281 1.1 mrg {
282 1.1 mrg tree field;
283 1.1 mrg tree name;
284 1.1 mrg HOST_WIDE_INT offset = h->offset;
285 1.1 mrg unsigned HOST_WIDE_INT desired_align, known_align;
286 1.1 mrg
287 1.1 mrg name = get_identifier (h->sym->name);
288 1.1 mrg field = build_decl (gfc_get_location (&h->sym->declared_at),
289 1.1 mrg FIELD_DECL, name, h->field);
290 1.1 mrg known_align = (offset & -offset) * BITS_PER_UNIT;
291 1.1 mrg if (known_align == 0 || known_align > BIGGEST_ALIGNMENT)
292 1.1 mrg known_align = BIGGEST_ALIGNMENT;
293 1.1 mrg
294 1.1 mrg desired_align = update_alignment_for_field (rli, field, known_align);
295 1.1 mrg if (desired_align > known_align)
296 1.1 mrg DECL_PACKED (field) = 1;
297 1.1 mrg
298 1.1 mrg DECL_FIELD_CONTEXT (field) = union_type;
299 1.1 mrg DECL_FIELD_OFFSET (field) = size_int (offset);
300 1.1 mrg DECL_FIELD_BIT_OFFSET (field) = bitsize_zero_node;
301 1.1 mrg SET_DECL_OFFSET_ALIGN (field, known_align);
302 1.1 mrg
303 1.1 mrg rli->offset = size_binop (MAX_EXPR, rli->offset,
304 1.1 mrg size_binop (PLUS_EXPR,
305 1.1 mrg DECL_FIELD_OFFSET (field),
306 1.1 mrg DECL_SIZE_UNIT (field)));
307 1.1 mrg /* If this field is assigned to a label, we create another two variables.
308 1.1 mrg One will hold the address of target label or format label. The other will
309 1.1 mrg hold the length of format label string. */
310 1.1 mrg if (h->sym->attr.assign)
311 1.1 mrg {
312 1.1 mrg tree len;
313 1.1 mrg tree addr;
314 1.1 mrg
315 1.1 mrg gfc_allocate_lang_decl (field);
316 1.1 mrg GFC_DECL_ASSIGN (field) = 1;
317 1.1 mrg len = gfc_create_var_np (gfc_charlen_type_node,h->sym->name);
318 1.1 mrg addr = gfc_create_var_np (pvoid_type_node, h->sym->name);
319 1.1 mrg TREE_STATIC (len) = 1;
320 1.1 mrg TREE_STATIC (addr) = 1;
321 1.1 mrg DECL_INITIAL (len) = build_int_cst (gfc_charlen_type_node, -2);
322 1.1 mrg gfc_set_decl_location (len, &h->sym->declared_at);
323 1.1 mrg gfc_set_decl_location (addr, &h->sym->declared_at);
324 1.1 mrg GFC_DECL_STRING_LEN (field) = pushdecl_top_level (len);
325 1.1 mrg GFC_DECL_ASSIGN_ADDR (field) = pushdecl_top_level (addr);
326 1.1 mrg }
327 1.1 mrg
328 1.1 mrg /* If this field is volatile, mark it. */
329 1.1 mrg if (h->sym->attr.volatile_)
330 1.1 mrg {
331 1.1 mrg tree new_type;
332 1.1 mrg TREE_THIS_VOLATILE (field) = 1;
333 1.1 mrg TREE_SIDE_EFFECTS (field) = 1;
334 1.1 mrg new_type = build_qualified_type (TREE_TYPE (field), TYPE_QUAL_VOLATILE);
335 1.1 mrg TREE_TYPE (field) = new_type;
336 1.1 mrg }
337 1.1 mrg
338 1.1 mrg h->field = field;
339 1.1 mrg }
340 1.1 mrg
341 1.1 mrg #if !defined (NO_DOT_IN_LABEL)
342 1.1 mrg #define GFC_EQUIV_FMT "equiv.%d"
343 1.1 mrg #elif !defined (NO_DOLLAR_IN_LABEL)
344 1.1 mrg #define GFC_EQUIV_FMT "_Equiv$%d"
345 1.1 mrg #else
346 1.1 mrg #define GFC_EQUIV_FMT "_Equiv_%d"
347 1.1 mrg #endif
348 1.1 mrg
349 1.1 mrg /* Get storage for local equivalence. */
350 1.1 mrg
351 1.1 mrg static tree
352 1.1 mrg build_equiv_decl (tree union_type, bool is_init, bool is_saved, bool is_auto)
353 1.1 mrg {
354 1.1 mrg tree decl;
355 1.1 mrg char name[18];
356 1.1 mrg static int serial = 0;
357 1.1 mrg
358 1.1 mrg if (is_init)
359 1.1 mrg {
360 1.1 mrg decl = gfc_create_var (union_type, "equiv");
361 1.1 mrg TREE_STATIC (decl) = 1;
362 1.1 mrg GFC_DECL_COMMON_OR_EQUIV (decl) = 1;
363 1.1 mrg return decl;
364 1.1 mrg }
365 1.1 mrg
366 1.1 mrg snprintf (name, sizeof (name), GFC_EQUIV_FMT, serial++);
367 1.1 mrg decl = build_decl (input_location,
368 1.1 mrg VAR_DECL, get_identifier (name), union_type);
369 1.1 mrg DECL_ARTIFICIAL (decl) = 1;
370 1.1 mrg DECL_IGNORED_P (decl) = 1;
371 1.1 mrg
372 1.1 mrg if (!is_auto && (!gfc_can_put_var_on_stack (DECL_SIZE_UNIT (decl))
373 1.1 mrg || is_saved))
374 1.1 mrg TREE_STATIC (decl) = 1;
375 1.1 mrg
376 1.1 mrg TREE_ADDRESSABLE (decl) = 1;
377 1.1 mrg TREE_USED (decl) = 1;
378 1.1 mrg GFC_DECL_COMMON_OR_EQUIV (decl) = 1;
379 1.1 mrg
380 1.1 mrg /* The source location has been lost, and doesn't really matter.
381 1.1 mrg We need to set it to something though. */
382 1.1 mrg gfc_set_decl_location (decl, &gfc_current_locus);
383 1.1 mrg
384 1.1 mrg gfc_add_decl_to_function (decl);
385 1.1 mrg
386 1.1 mrg return decl;
387 1.1 mrg }
388 1.1 mrg
389 1.1 mrg
390 1.1 mrg /* Get storage for common block. */
391 1.1 mrg
392 1.1 mrg static tree
393 1.1 mrg build_common_decl (gfc_common_head *com, tree union_type, bool is_init)
394 1.1 mrg {
395 1.1 mrg tree decl, identifier;
396 1.1 mrg
397 1.1 mrg identifier = gfc_sym_mangled_common_id (com);
398 1.1 mrg decl = gfc_map_of_all_commons.count(identifier)
399 1.1 mrg ? gfc_map_of_all_commons[identifier] : NULL_TREE;
400 1.1 mrg
401 1.1 mrg /* Update the size of this common block as needed. */
402 1.1 mrg if (decl != NULL_TREE)
403 1.1 mrg {
404 1.1 mrg tree size = TYPE_SIZE_UNIT (union_type);
405 1.1 mrg
406 1.1 mrg /* Named common blocks of the same name shall be of the same size
407 1.1 mrg in all scoping units of a program in which they appear, but
408 1.1 mrg blank common blocks may be of different sizes. */
409 1.1 mrg if (!tree_int_cst_equal (DECL_SIZE_UNIT (decl), size)
410 1.1 mrg && strcmp (com->name, BLANK_COMMON_NAME))
411 1.1 mrg gfc_warning (0, "Named COMMON block %qs at %L shall be of the "
412 1.1 mrg "same size as elsewhere (%lu vs %lu bytes)", com->name,
413 1.1 mrg &com->where,
414 1.1 mrg (unsigned long) TREE_INT_CST_LOW (size),
415 1.1 mrg (unsigned long) TREE_INT_CST_LOW (DECL_SIZE_UNIT (decl)));
416 1.1 mrg
417 1.1 mrg if (tree_int_cst_lt (DECL_SIZE_UNIT (decl), size))
418 1.1 mrg {
419 1.1 mrg DECL_SIZE (decl) = TYPE_SIZE (union_type);
420 1.1 mrg DECL_SIZE_UNIT (decl) = size;
421 1.1 mrg SET_DECL_MODE (decl, TYPE_MODE (union_type));
422 1.1 mrg TREE_TYPE (decl) = union_type;
423 1.1 mrg layout_decl (decl, 0);
424 1.1 mrg }
425 1.1 mrg }
426 1.1 mrg
427 1.1 mrg /* If this common block has been declared in a previous program unit,
428 1.1 mrg and either it is already initialized or there is no new initialization
429 1.1 mrg for it, just return. */
430 1.1 mrg if ((decl != NULL_TREE) && (!is_init || DECL_INITIAL (decl)))
431 1.1 mrg return decl;
432 1.1 mrg
433 1.1 mrg /* If there is no backend_decl for the common block, build it. */
434 1.1 mrg if (decl == NULL_TREE)
435 1.1 mrg {
436 1.1 mrg tree omp_clauses = NULL_TREE;
437 1.1 mrg
438 1.1 mrg if (com->is_bind_c == 1 && com->binding_label)
439 1.1 mrg decl = build_decl (input_location, VAR_DECL, identifier, union_type);
440 1.1 mrg else
441 1.1 mrg {
442 1.1 mrg decl = build_decl (input_location, VAR_DECL, get_identifier (com->name),
443 1.1 mrg union_type);
444 1.1 mrg gfc_set_decl_assembler_name (decl, identifier);
445 1.1 mrg }
446 1.1 mrg
447 1.1 mrg TREE_PUBLIC (decl) = 1;
448 1.1 mrg TREE_STATIC (decl) = 1;
449 1.1 mrg DECL_IGNORED_P (decl) = 1;
450 1.1 mrg if (!com->is_bind_c)
451 1.1 mrg SET_DECL_ALIGN (decl, BIGGEST_ALIGNMENT);
452 1.1 mrg else
453 1.1 mrg {
454 1.1 mrg /* Do not set the alignment for bind(c) common blocks to
455 1.1 mrg BIGGEST_ALIGNMENT because that won't match what C does. Also,
456 1.1 mrg for common blocks with one element, the alignment must be
457 1.1 mrg that of the field within the common block in order to match
458 1.1 mrg what C will do. */
459 1.1 mrg tree field = NULL_TREE;
460 1.1 mrg field = TYPE_FIELDS (TREE_TYPE (decl));
461 1.1 mrg if (DECL_CHAIN (field) == NULL_TREE)
462 1.1 mrg SET_DECL_ALIGN (decl, TYPE_ALIGN (TREE_TYPE (field)));
463 1.1 mrg }
464 1.1 mrg DECL_USER_ALIGN (decl) = 0;
465 1.1 mrg GFC_DECL_COMMON_OR_EQUIV (decl) = 1;
466 1.1 mrg
467 1.1 mrg gfc_set_decl_location (decl, &com->where);
468 1.1 mrg
469 1.1 mrg if (com->threadprivate)
470 1.1 mrg set_decl_tls_model (decl, decl_default_tls_model (decl));
471 1.1 mrg
472 1.1 mrg if (com->omp_device_type != OMP_DEVICE_TYPE_UNSET)
473 1.1 mrg {
474 1.1 mrg tree c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_DEVICE_TYPE);
475 1.1 mrg switch (com->omp_device_type)
476 1.1 mrg {
477 1.1 mrg case OMP_DEVICE_TYPE_HOST:
478 1.1 mrg OMP_CLAUSE_DEVICE_TYPE_KIND (c) = OMP_CLAUSE_DEVICE_TYPE_HOST;
479 1.1 mrg break;
480 1.1 mrg case OMP_DEVICE_TYPE_NOHOST:
481 1.1 mrg OMP_CLAUSE_DEVICE_TYPE_KIND (c) = OMP_CLAUSE_DEVICE_TYPE_NOHOST;
482 1.1 mrg break;
483 1.1 mrg case OMP_DEVICE_TYPE_ANY:
484 1.1 mrg OMP_CLAUSE_DEVICE_TYPE_KIND (c) = OMP_CLAUSE_DEVICE_TYPE_ANY;
485 1.1 mrg break;
486 1.1 mrg default:
487 1.1 mrg gcc_unreachable ();
488 1.1 mrg }
489 1.1 mrg omp_clauses = c;
490 1.1 mrg }
491 1.1 mrg if (com->omp_declare_target_link)
492 1.1 mrg DECL_ATTRIBUTES (decl)
493 1.1 mrg = tree_cons (get_identifier ("omp declare target link"),
494 1.1 mrg omp_clauses, DECL_ATTRIBUTES (decl));
495 1.1 mrg else if (com->omp_declare_target)
496 1.1 mrg DECL_ATTRIBUTES (decl)
497 1.1 mrg = tree_cons (get_identifier ("omp declare target"),
498 1.1 mrg omp_clauses, DECL_ATTRIBUTES (decl));
499 1.1 mrg
500 1.1 mrg /* Place the back end declaration for this common block in
501 1.1 mrg GLOBAL_BINDING_LEVEL. */
502 1.1 mrg gfc_map_of_all_commons[identifier] = pushdecl_top_level (decl);
503 1.1 mrg }
504 1.1 mrg
505 1.1 mrg /* Has no initial values. */
506 1.1 mrg if (!is_init)
507 1.1 mrg {
508 1.1 mrg DECL_INITIAL (decl) = NULL_TREE;
509 1.1 mrg DECL_COMMON (decl) = 1;
510 1.1 mrg DECL_DEFER_OUTPUT (decl) = 1;
511 1.1 mrg }
512 1.1 mrg else
513 1.1 mrg {
514 1.1 mrg DECL_INITIAL (decl) = error_mark_node;
515 1.1 mrg DECL_COMMON (decl) = 0;
516 1.1 mrg DECL_DEFER_OUTPUT (decl) = 0;
517 1.1 mrg }
518 1.1 mrg return decl;
519 1.1 mrg }
520 1.1 mrg
521 1.1 mrg
522 1.1 mrg /* Return a field that is the size of the union, if an equivalence has
523 1.1 mrg overlapping initializers. Merge the initializers into a single
524 1.1 mrg initializer for this new field, then free the old ones. */
525 1.1 mrg
526 1.1 mrg static tree
527 1.1 mrg get_init_field (segment_info *head, tree union_type, tree *field_init,
528 1.1 mrg record_layout_info rli)
529 1.1 mrg {
530 1.1 mrg segment_info *s;
531 1.1 mrg HOST_WIDE_INT length = 0;
532 1.1 mrg HOST_WIDE_INT offset = 0;
533 1.1 mrg unsigned HOST_WIDE_INT known_align, desired_align;
534 1.1 mrg bool overlap = false;
535 1.1 mrg tree tmp, field;
536 1.1 mrg tree init;
537 1.1 mrg unsigned char *data, *chk;
538 1.1 mrg vec<constructor_elt, va_gc> *v = NULL;
539 1.1 mrg
540 1.1 mrg tree type = unsigned_char_type_node;
541 1.1 mrg int i;
542 1.1 mrg
543 1.1 mrg /* Obtain the size of the union and check if there are any overlapping
544 1.1 mrg initializers. */
545 1.1 mrg for (s = head; s; s = s->next)
546 1.1 mrg {
547 1.1 mrg HOST_WIDE_INT slen = s->offset + s->length;
548 1.1 mrg if (s->sym->value)
549 1.1 mrg {
550 1.1 mrg if (s->offset < offset)
551 1.1 mrg overlap = true;
552 1.1 mrg offset = slen;
553 1.1 mrg }
554 1.1 mrg length = length < slen ? slen : length;
555 1.1 mrg }
556 1.1 mrg
557 1.1 mrg if (!overlap)
558 1.1 mrg return NULL_TREE;
559 1.1 mrg
560 1.1 mrg /* Now absorb all the initializer data into a single vector,
561 1.1 mrg whilst checking for overlapping, unequal values. */
562 1.1 mrg data = XCNEWVEC (unsigned char, (size_t)length);
563 1.1 mrg chk = XCNEWVEC (unsigned char, (size_t)length);
564 1.1 mrg
565 1.1 mrg /* TODO - change this when default initialization is implemented. */
566 1.1 mrg memset (data, '\0', (size_t)length);
567 1.1 mrg memset (chk, '\0', (size_t)length);
568 1.1 mrg for (s = head; s; s = s->next)
569 1.1 mrg if (s->sym->value)
570 1.1 mrg {
571 1.1 mrg locus *loc = NULL;
572 1.1 mrg if (s->sym->ns->equiv && s->sym->ns->equiv->eq)
573 1.1 mrg loc = &s->sym->ns->equiv->eq->expr->where;
574 1.1 mrg gfc_merge_initializers (s->sym->ts, s->sym->value, loc,
575 1.1 mrg &data[s->offset],
576 1.1 mrg &chk[s->offset],
577 1.1 mrg (size_t)s->length);
578 1.1 mrg }
579 1.1 mrg
580 1.1 mrg for (i = 0; i < length; i++)
581 1.1 mrg CONSTRUCTOR_APPEND_ELT (v, NULL, build_int_cst (type, data[i]));
582 1.1 mrg
583 1.1 mrg free (data);
584 1.1 mrg free (chk);
585 1.1 mrg
586 1.1 mrg /* Build a char[length] array to hold the initializers. Much of what
587 1.1 mrg follows is borrowed from build_field, above. */
588 1.1 mrg
589 1.1 mrg tmp = build_int_cst (gfc_array_index_type, length - 1);
590 1.1 mrg tmp = build_range_type (gfc_array_index_type,
591 1.1 mrg gfc_index_zero_node, tmp);
592 1.1 mrg tmp = build_array_type (type, tmp);
593 1.1 mrg field = build_decl (gfc_get_location (&gfc_current_locus),
594 1.1 mrg FIELD_DECL, NULL_TREE, tmp);
595 1.1 mrg
596 1.1 mrg known_align = BIGGEST_ALIGNMENT;
597 1.1 mrg
598 1.1 mrg desired_align = update_alignment_for_field (rli, field, known_align);
599 1.1 mrg if (desired_align > known_align)
600 1.1 mrg DECL_PACKED (field) = 1;
601 1.1 mrg
602 1.1 mrg DECL_FIELD_CONTEXT (field) = union_type;
603 1.1 mrg DECL_FIELD_OFFSET (field) = size_int (0);
604 1.1 mrg DECL_FIELD_BIT_OFFSET (field) = bitsize_zero_node;
605 1.1 mrg SET_DECL_OFFSET_ALIGN (field, known_align);
606 1.1 mrg
607 1.1 mrg rli->offset = size_binop (MAX_EXPR, rli->offset,
608 1.1 mrg size_binop (PLUS_EXPR,
609 1.1 mrg DECL_FIELD_OFFSET (field),
610 1.1 mrg DECL_SIZE_UNIT (field)));
611 1.1 mrg
612 1.1 mrg init = build_constructor (TREE_TYPE (field), v);
613 1.1 mrg TREE_CONSTANT (init) = 1;
614 1.1 mrg
615 1.1 mrg *field_init = init;
616 1.1 mrg
617 1.1 mrg for (s = head; s; s = s->next)
618 1.1 mrg {
619 1.1 mrg if (s->sym->value == NULL)
620 1.1 mrg continue;
621 1.1 mrg
622 1.1 mrg gfc_free_expr (s->sym->value);
623 1.1 mrg s->sym->value = NULL;
624 1.1 mrg }
625 1.1 mrg
626 1.1 mrg return field;
627 1.1 mrg }
628 1.1 mrg
629 1.1 mrg
630 1.1 mrg /* Declare memory for the common block or local equivalence, and create
631 1.1 mrg backend declarations for all of the elements. */
632 1.1 mrg
633 1.1 mrg static void
634 1.1 mrg create_common (gfc_common_head *com, segment_info *head, bool saw_equiv)
635 1.1 mrg {
636 1.1 mrg segment_info *s, *next_s;
637 1.1 mrg tree union_type;
638 1.1 mrg tree *field_link;
639 1.1 mrg tree field;
640 1.1 mrg tree field_init = NULL_TREE;
641 1.1 mrg record_layout_info rli;
642 1.1 mrg tree decl;
643 1.1 mrg bool is_init = false;
644 1.1 mrg bool is_saved = false;
645 1.1 mrg bool is_auto = false;
646 1.1 mrg
647 1.1 mrg /* Declare the variables inside the common block.
648 1.1 mrg If the current common block contains any equivalence object, then
649 1.1 mrg make a UNION_TYPE node, otherwise RECORD_TYPE. This will let the
650 1.1 mrg alias analyzer work well when there is no address overlapping for
651 1.1 mrg common variables in the current common block. */
652 1.1 mrg if (saw_equiv)
653 1.1 mrg union_type = make_node (UNION_TYPE);
654 1.1 mrg else
655 1.1 mrg union_type = make_node (RECORD_TYPE);
656 1.1 mrg
657 1.1 mrg rli = start_record_layout (union_type);
658 1.1 mrg field_link = &TYPE_FIELDS (union_type);
659 1.1 mrg
660 1.1 mrg /* Check for overlapping initializers and replace them with a single,
661 1.1 mrg artificial field that contains all the data. */
662 1.1 mrg if (saw_equiv)
663 1.1 mrg field = get_init_field (head, union_type, &field_init, rli);
664 1.1 mrg else
665 1.1 mrg field = NULL_TREE;
666 1.1 mrg
667 1.1 mrg if (field != NULL_TREE)
668 1.1 mrg {
669 1.1 mrg is_init = true;
670 1.1 mrg *field_link = field;
671 1.1 mrg field_link = &DECL_CHAIN (field);
672 1.1 mrg }
673 1.1 mrg
674 1.1 mrg for (s = head; s; s = s->next)
675 1.1 mrg {
676 1.1 mrg build_field (s, union_type, rli);
677 1.1 mrg
678 1.1 mrg /* Link the field into the type. */
679 1.1 mrg *field_link = s->field;
680 1.1 mrg field_link = &DECL_CHAIN (s->field);
681 1.1 mrg
682 1.1 mrg /* Has initial value. */
683 1.1 mrg if (s->sym->value)
684 1.1 mrg is_init = true;
685 1.1 mrg
686 1.1 mrg /* Has SAVE attribute. */
687 1.1 mrg if (s->sym->attr.save)
688 1.1 mrg is_saved = true;
689 1.1 mrg
690 1.1 mrg /* Has AUTOMATIC attribute. */
691 1.1 mrg if (s->sym->attr.automatic)
692 1.1 mrg is_auto = true;
693 1.1 mrg }
694 1.1 mrg
695 1.1 mrg finish_record_layout (rli, true);
696 1.1 mrg
697 1.1 mrg if (com)
698 1.1 mrg decl = build_common_decl (com, union_type, is_init);
699 1.1 mrg else
700 1.1 mrg decl = build_equiv_decl (union_type, is_init, is_saved, is_auto);
701 1.1 mrg
702 1.1 mrg if (is_init)
703 1.1 mrg {
704 1.1 mrg tree ctor, tmp;
705 1.1 mrg vec<constructor_elt, va_gc> *v = NULL;
706 1.1 mrg
707 1.1 mrg if (field != NULL_TREE && field_init != NULL_TREE)
708 1.1 mrg CONSTRUCTOR_APPEND_ELT (v, field, field_init);
709 1.1 mrg else
710 1.1 mrg for (s = head; s; s = s->next)
711 1.1 mrg {
712 1.1 mrg if (s->sym->value)
713 1.1 mrg {
714 1.1 mrg /* Add the initializer for this field. */
715 1.1 mrg tmp = gfc_conv_initializer (s->sym->value, &s->sym->ts,
716 1.1 mrg TREE_TYPE (s->field),
717 1.1 mrg s->sym->attr.dimension,
718 1.1 mrg s->sym->attr.pointer
719 1.1 mrg || s->sym->attr.allocatable, false);
720 1.1 mrg
721 1.1 mrg CONSTRUCTOR_APPEND_ELT (v, s->field, tmp);
722 1.1 mrg }
723 1.1 mrg }
724 1.1 mrg
725 1.1 mrg gcc_assert (!v->is_empty ());
726 1.1 mrg ctor = build_constructor (union_type, v);
727 1.1 mrg TREE_CONSTANT (ctor) = 1;
728 1.1 mrg TREE_STATIC (ctor) = 1;
729 1.1 mrg DECL_INITIAL (decl) = ctor;
730 1.1 mrg
731 1.1 mrg if (flag_checking)
732 1.1 mrg {
733 1.1 mrg tree field, value;
734 1.1 mrg unsigned HOST_WIDE_INT idx;
735 1.1 mrg FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (ctor), idx, field, value)
736 1.1 mrg gcc_assert (TREE_CODE (field) == FIELD_DECL);
737 1.1 mrg }
738 1.1 mrg }
739 1.1 mrg
740 1.1 mrg /* Build component reference for each variable. */
741 1.1 mrg for (s = head; s; s = next_s)
742 1.1 mrg {
743 1.1 mrg tree var_decl;
744 1.1 mrg
745 1.1 mrg var_decl = build_decl (gfc_get_location (&s->sym->declared_at),
746 1.1 mrg VAR_DECL, DECL_NAME (s->field),
747 1.1 mrg TREE_TYPE (s->field));
748 1.1 mrg TREE_STATIC (var_decl) = TREE_STATIC (decl);
749 1.1 mrg /* Mark the variable as used in order to avoid warnings about
750 1.1 mrg unused variables. */
751 1.1 mrg TREE_USED (var_decl) = 1;
752 1.1 mrg if (s->sym->attr.use_assoc)
753 1.1 mrg DECL_IGNORED_P (var_decl) = 1;
754 1.1 mrg if (s->sym->attr.target)
755 1.1 mrg TREE_ADDRESSABLE (var_decl) = 1;
756 1.1 mrg /* Fake variables are not visible from other translation units. */
757 1.1 mrg TREE_PUBLIC (var_decl) = 0;
758 1.1 mrg gfc_finish_decl_attrs (var_decl, &s->sym->attr);
759 1.1 mrg
760 1.1 mrg /* To preserve identifier names in COMMON, chain to procedure
761 1.1 mrg scope unless at top level in a module definition. */
762 1.1 mrg if (com
763 1.1 mrg && s->sym->ns->proc_name
764 1.1 mrg && s->sym->ns->proc_name->attr.flavor == FL_MODULE)
765 1.1 mrg var_decl = pushdecl_top_level (var_decl);
766 1.1 mrg else
767 1.1 mrg gfc_add_decl_to_function (var_decl);
768 1.1 mrg
769 1.1 mrg tree comp = build3_loc (input_location, COMPONENT_REF,
770 1.1 mrg TREE_TYPE (s->field), decl, s->field, NULL_TREE);
771 1.1 mrg if (TREE_THIS_VOLATILE (s->field))
772 1.1 mrg TREE_THIS_VOLATILE (comp) = 1;
773 1.1 mrg SET_DECL_VALUE_EXPR (var_decl, comp);
774 1.1 mrg DECL_HAS_VALUE_EXPR_P (var_decl) = 1;
775 1.1 mrg GFC_DECL_COMMON_OR_EQUIV (var_decl) = 1;
776 1.1 mrg
777 1.1 mrg if (s->sym->attr.assign)
778 1.1 mrg {
779 1.1 mrg gfc_allocate_lang_decl (var_decl);
780 1.1 mrg GFC_DECL_ASSIGN (var_decl) = 1;
781 1.1 mrg GFC_DECL_STRING_LEN (var_decl) = GFC_DECL_STRING_LEN (s->field);
782 1.1 mrg GFC_DECL_ASSIGN_ADDR (var_decl) = GFC_DECL_ASSIGN_ADDR (s->field);
783 1.1 mrg }
784 1.1 mrg
785 1.1 mrg s->sym->backend_decl = var_decl;
786 1.1 mrg
787 1.1 mrg next_s = s->next;
788 1.1 mrg free (s);
789 1.1 mrg }
790 1.1 mrg }
791 1.1 mrg
792 1.1 mrg
793 1.1 mrg /* Given a symbol, find it in the current segment list. Returns NULL if
794 1.1 mrg not found. */
795 1.1 mrg
796 1.1 mrg static segment_info *
797 1.1 mrg find_segment_info (gfc_symbol *symbol)
798 1.1 mrg {
799 1.1 mrg segment_info *n;
800 1.1 mrg
801 1.1 mrg for (n = current_segment; n; n = n->next)
802 1.1 mrg {
803 1.1 mrg if (n->sym == symbol)
804 1.1 mrg return n;
805 1.1 mrg }
806 1.1 mrg
807 1.1 mrg return NULL;
808 1.1 mrg }
809 1.1 mrg
810 1.1 mrg
811 1.1 mrg /* Given an expression node, make sure it is a constant integer and return
812 1.1 mrg the mpz_t value. */
813 1.1 mrg
814 1.1 mrg static mpz_t *
815 1.1 mrg get_mpz (gfc_expr *e)
816 1.1 mrg {
817 1.1 mrg
818 1.1 mrg if (e->expr_type != EXPR_CONSTANT)
819 1.1 mrg gfc_internal_error ("get_mpz(): Not an integer constant");
820 1.1 mrg
821 1.1 mrg return &e->value.integer;
822 1.1 mrg }
823 1.1 mrg
824 1.1 mrg
825 1.1 mrg /* Given an array specification and an array reference, figure out the
826 1.1 mrg array element number (zero based). Bounds and elements are guaranteed
827 1.1 mrg to be constants. If something goes wrong we generate an error and
828 1.1 mrg return zero. */
829 1.1 mrg
830 1.1 mrg static HOST_WIDE_INT
831 1.1 mrg element_number (gfc_array_ref *ar)
832 1.1 mrg {
833 1.1 mrg mpz_t multiplier, offset, extent, n;
834 1.1 mrg gfc_array_spec *as;
835 1.1 mrg HOST_WIDE_INT i, rank;
836 1.1 mrg
837 1.1 mrg as = ar->as;
838 1.1 mrg rank = as->rank;
839 1.1 mrg mpz_init_set_ui (multiplier, 1);
840 1.1 mrg mpz_init_set_ui (offset, 0);
841 1.1 mrg mpz_init (extent);
842 1.1 mrg mpz_init (n);
843 1.1 mrg
844 1.1 mrg for (i = 0; i < rank; i++)
845 1.1 mrg {
846 1.1 mrg if (ar->dimen_type[i] != DIMEN_ELEMENT)
847 1.1 mrg gfc_internal_error ("element_number(): Bad dimension type");
848 1.1 mrg
849 1.1 mrg if (as && as->lower[i])
850 1.1 mrg mpz_sub (n, *get_mpz (ar->start[i]), *get_mpz (as->lower[i]));
851 1.1 mrg else
852 1.1 mrg mpz_sub_ui (n, *get_mpz (ar->start[i]), 1);
853 1.1 mrg
854 1.1 mrg mpz_mul (n, n, multiplier);
855 1.1 mrg mpz_add (offset, offset, n);
856 1.1 mrg
857 1.1 mrg if (as && as->upper[i] && as->lower[i])
858 1.1 mrg {
859 1.1 mrg mpz_sub (extent, *get_mpz (as->upper[i]), *get_mpz (as->lower[i]));
860 1.1 mrg mpz_add_ui (extent, extent, 1);
861 1.1 mrg }
862 1.1 mrg else
863 1.1 mrg mpz_set_ui (extent, 0);
864 1.1 mrg
865 1.1 mrg if (mpz_sgn (extent) < 0)
866 1.1 mrg mpz_set_ui (extent, 0);
867 1.1 mrg
868 1.1 mrg mpz_mul (multiplier, multiplier, extent);
869 1.1 mrg }
870 1.1 mrg
871 1.1 mrg i = mpz_get_ui (offset);
872 1.1 mrg
873 1.1 mrg mpz_clear (multiplier);
874 1.1 mrg mpz_clear (offset);
875 1.1 mrg mpz_clear (extent);
876 1.1 mrg mpz_clear (n);
877 1.1 mrg
878 1.1 mrg return i;
879 1.1 mrg }
880 1.1 mrg
881 1.1 mrg
882 1.1 mrg /* Given a single element of an equivalence list, figure out the offset
883 1.1 mrg from the base symbol. For simple variables or full arrays, this is
884 1.1 mrg simply zero. For an array element we have to calculate the array
885 1.1 mrg element number and multiply by the element size. For a substring we
886 1.1 mrg have to calculate the further reference. */
887 1.1 mrg
888 1.1 mrg static HOST_WIDE_INT
889 1.1 mrg calculate_offset (gfc_expr *e)
890 1.1 mrg {
891 1.1 mrg HOST_WIDE_INT n, element_size, offset;
892 1.1 mrg gfc_typespec *element_type;
893 1.1 mrg gfc_ref *reference;
894 1.1 mrg
895 1.1 mrg offset = 0;
896 1.1 mrg element_type = &e->symtree->n.sym->ts;
897 1.1 mrg
898 1.1 mrg for (reference = e->ref; reference; reference = reference->next)
899 1.1 mrg switch (reference->type)
900 1.1 mrg {
901 1.1 mrg case REF_ARRAY:
902 1.1 mrg switch (reference->u.ar.type)
903 1.1 mrg {
904 1.1 mrg case AR_FULL:
905 1.1 mrg break;
906 1.1 mrg
907 1.1 mrg case AR_ELEMENT:
908 1.1 mrg n = element_number (&reference->u.ar);
909 1.1 mrg if (element_type->type == BT_CHARACTER)
910 1.1 mrg gfc_conv_const_charlen (element_type->u.cl);
911 1.1 mrg element_size =
912 1.1 mrg int_size_in_bytes (gfc_typenode_for_spec (element_type));
913 1.1 mrg offset += n * element_size;
914 1.1 mrg break;
915 1.1 mrg
916 1.1 mrg default:
917 1.1 mrg gfc_error ("Bad array reference at %L", &e->where);
918 1.1 mrg }
919 1.1 mrg break;
920 1.1 mrg case REF_SUBSTRING:
921 1.1 mrg if (reference->u.ss.start != NULL)
922 1.1 mrg offset += mpz_get_ui (*get_mpz (reference->u.ss.start)) - 1;
923 1.1 mrg break;
924 1.1 mrg default:
925 1.1 mrg gfc_error ("Illegal reference type at %L as EQUIVALENCE object",
926 1.1 mrg &e->where);
927 1.1 mrg }
928 1.1 mrg return offset;
929 1.1 mrg }
930 1.1 mrg
931 1.1 mrg
932 1.1 mrg /* Add a new segment_info structure to the current segment. eq1 is already
933 1.1 mrg in the list, eq2 is not. */
934 1.1 mrg
935 1.1 mrg static void
936 1.1 mrg new_condition (segment_info *v, gfc_equiv *eq1, gfc_equiv *eq2)
937 1.1 mrg {
938 1.1 mrg HOST_WIDE_INT offset1, offset2;
939 1.1 mrg segment_info *a;
940 1.1 mrg
941 1.1 mrg offset1 = calculate_offset (eq1->expr);
942 1.1 mrg offset2 = calculate_offset (eq2->expr);
943 1.1 mrg
944 1.1 mrg a = get_segment_info (eq2->expr->symtree->n.sym,
945 1.1 mrg v->offset + offset1 - offset2);
946 1.1 mrg
947 1.1 mrg current_segment = add_segments (current_segment, a);
948 1.1 mrg }
949 1.1 mrg
950 1.1 mrg
951 1.1 mrg /* Given two equivalence structures that are both already in the list, make
952 1.1 mrg sure that this new condition is not violated, generating an error if it
953 1.1 mrg is. */
954 1.1 mrg
955 1.1 mrg static void
956 1.1 mrg confirm_condition (segment_info *s1, gfc_equiv *eq1, segment_info *s2,
957 1.1 mrg gfc_equiv *eq2)
958 1.1 mrg {
959 1.1 mrg HOST_WIDE_INT offset1, offset2;
960 1.1 mrg
961 1.1 mrg offset1 = calculate_offset (eq1->expr);
962 1.1 mrg offset2 = calculate_offset (eq2->expr);
963 1.1 mrg
964 1.1 mrg if (s1->offset + offset1 != s2->offset + offset2)
965 1.1 mrg gfc_error ("Inconsistent equivalence rules involving %qs at %L and "
966 1.1 mrg "%qs at %L", s1->sym->name, &s1->sym->declared_at,
967 1.1 mrg s2->sym->name, &s2->sym->declared_at);
968 1.1 mrg }
969 1.1 mrg
970 1.1 mrg
971 1.1 mrg /* Process a new equivalence condition. eq1 is know to be in segment f.
972 1.1 mrg If eq2 is also present then confirm that the condition holds.
973 1.1 mrg Otherwise add a new variable to the segment list. */
974 1.1 mrg
975 1.1 mrg static void
976 1.1 mrg add_condition (segment_info *f, gfc_equiv *eq1, gfc_equiv *eq2)
977 1.1 mrg {
978 1.1 mrg segment_info *n;
979 1.1 mrg
980 1.1 mrg n = find_segment_info (eq2->expr->symtree->n.sym);
981 1.1 mrg
982 1.1 mrg if (n == NULL)
983 1.1 mrg new_condition (f, eq1, eq2);
984 1.1 mrg else
985 1.1 mrg confirm_condition (f, eq1, n, eq2);
986 1.1 mrg }
987 1.1 mrg
988 1.1 mrg static void
989 1.1 mrg accumulate_equivalence_attributes (symbol_attribute *dummy_symbol, gfc_equiv *e)
990 1.1 mrg {
991 1.1 mrg symbol_attribute attr = e->expr->symtree->n.sym->attr;
992 1.1 mrg
993 1.1 mrg dummy_symbol->dummy |= attr.dummy;
994 1.1 mrg dummy_symbol->pointer |= attr.pointer;
995 1.1 mrg dummy_symbol->target |= attr.target;
996 1.1 mrg dummy_symbol->external |= attr.external;
997 1.1 mrg dummy_symbol->intrinsic |= attr.intrinsic;
998 1.1 mrg dummy_symbol->allocatable |= attr.allocatable;
999 1.1 mrg dummy_symbol->elemental |= attr.elemental;
1000 1.1 mrg dummy_symbol->recursive |= attr.recursive;
1001 1.1 mrg dummy_symbol->in_common |= attr.in_common;
1002 1.1 mrg dummy_symbol->result |= attr.result;
1003 1.1 mrg dummy_symbol->in_namelist |= attr.in_namelist;
1004 1.1 mrg dummy_symbol->optional |= attr.optional;
1005 1.1 mrg dummy_symbol->entry |= attr.entry;
1006 1.1 mrg dummy_symbol->function |= attr.function;
1007 1.1 mrg dummy_symbol->subroutine |= attr.subroutine;
1008 1.1 mrg dummy_symbol->dimension |= attr.dimension;
1009 1.1 mrg dummy_symbol->in_equivalence |= attr.in_equivalence;
1010 1.1 mrg dummy_symbol->use_assoc |= attr.use_assoc;
1011 1.1 mrg dummy_symbol->cray_pointer |= attr.cray_pointer;
1012 1.1 mrg dummy_symbol->cray_pointee |= attr.cray_pointee;
1013 1.1 mrg dummy_symbol->data |= attr.data;
1014 1.1 mrg dummy_symbol->value |= attr.value;
1015 1.1 mrg dummy_symbol->volatile_ |= attr.volatile_;
1016 1.1 mrg dummy_symbol->is_protected |= attr.is_protected;
1017 1.1 mrg dummy_symbol->is_bind_c |= attr.is_bind_c;
1018 1.1 mrg dummy_symbol->procedure |= attr.procedure;
1019 1.1 mrg dummy_symbol->proc_pointer |= attr.proc_pointer;
1020 1.1 mrg dummy_symbol->abstract |= attr.abstract;
1021 1.1 mrg dummy_symbol->asynchronous |= attr.asynchronous;
1022 1.1 mrg dummy_symbol->codimension |= attr.codimension;
1023 1.1 mrg dummy_symbol->contiguous |= attr.contiguous;
1024 1.1 mrg dummy_symbol->generic |= attr.generic;
1025 1.1 mrg dummy_symbol->automatic |= attr.automatic;
1026 1.1 mrg dummy_symbol->threadprivate |= attr.threadprivate;
1027 1.1 mrg dummy_symbol->omp_declare_target |= attr.omp_declare_target;
1028 1.1 mrg dummy_symbol->omp_declare_target_link |= attr.omp_declare_target_link;
1029 1.1 mrg dummy_symbol->oacc_declare_copyin |= attr.oacc_declare_copyin;
1030 1.1 mrg dummy_symbol->oacc_declare_create |= attr.oacc_declare_create;
1031 1.1 mrg dummy_symbol->oacc_declare_deviceptr |= attr.oacc_declare_deviceptr;
1032 1.1 mrg dummy_symbol->oacc_declare_device_resident
1033 1.1 mrg |= attr.oacc_declare_device_resident;
1034 1.1 mrg
1035 1.1 mrg /* Not strictly correct, but probably close enough. */
1036 1.1 mrg if (attr.save > dummy_symbol->save)
1037 1.1 mrg dummy_symbol->save = attr.save;
1038 1.1 mrg if (attr.access > dummy_symbol->access)
1039 1.1 mrg dummy_symbol->access = attr.access;
1040 1.1 mrg }
1041 1.1 mrg
1042 1.1 mrg /* Given a segment element, search through the equivalence lists for unused
1043 1.1 mrg conditions that involve the symbol. Add these rules to the segment. */
1044 1.1 mrg
1045 1.1 mrg static bool
1046 1.1 mrg find_equivalence (segment_info *n)
1047 1.1 mrg {
1048 1.1 mrg gfc_equiv *e1, *e2, *eq;
1049 1.1 mrg bool found;
1050 1.1 mrg
1051 1.1 mrg found = FALSE;
1052 1.1 mrg
1053 1.1 mrg for (e1 = n->sym->ns->equiv; e1; e1 = e1->next)
1054 1.1 mrg {
1055 1.1 mrg eq = NULL;
1056 1.1 mrg
1057 1.1 mrg /* Search the equivalence list, including the root (first) element
1058 1.1 mrg for the symbol that owns the segment. */
1059 1.1 mrg symbol_attribute dummy_symbol;
1060 1.1 mrg memset (&dummy_symbol, 0, sizeof (dummy_symbol));
1061 1.1 mrg for (e2 = e1; e2; e2 = e2->eq)
1062 1.1 mrg {
1063 1.1 mrg accumulate_equivalence_attributes (&dummy_symbol, e2);
1064 1.1 mrg if (!e2->used && e2->expr->symtree->n.sym == n->sym)
1065 1.1 mrg {
1066 1.1 mrg eq = e2;
1067 1.1 mrg break;
1068 1.1 mrg }
1069 1.1 mrg }
1070 1.1 mrg
1071 1.1 mrg gfc_check_conflict (&dummy_symbol, e1->expr->symtree->name, &e1->expr->where);
1072 1.1 mrg
1073 1.1 mrg /* Go to the next root element. */
1074 1.1 mrg if (eq == NULL)
1075 1.1 mrg continue;
1076 1.1 mrg
1077 1.1 mrg eq->used = 1;
1078 1.1 mrg
1079 1.1 mrg /* Now traverse the equivalence list matching the offsets. */
1080 1.1 mrg for (e2 = e1; e2; e2 = e2->eq)
1081 1.1 mrg {
1082 1.1 mrg if (!e2->used && e2 != eq)
1083 1.1 mrg {
1084 1.1 mrg add_condition (n, eq, e2);
1085 1.1 mrg e2->used = 1;
1086 1.1 mrg found = TRUE;
1087 1.1 mrg }
1088 1.1 mrg }
1089 1.1 mrg }
1090 1.1 mrg return found;
1091 1.1 mrg }
1092 1.1 mrg
1093 1.1 mrg
1094 1.1 mrg /* Add all symbols equivalenced within a segment. We need to scan the
1095 1.1 mrg segment list multiple times to include indirect equivalences. Since
1096 1.1 mrg a new segment_info can inserted at the beginning of the segment list,
1097 1.1 mrg depending on its offset, we have to force a final pass through the
1098 1.1 mrg loop by demanding that completion sees a pass with no matches; i.e.,
1099 1.1 mrg all symbols with equiv_built set and no new equivalences found. */
1100 1.1 mrg
1101 1.1 mrg static void
1102 1.1 mrg add_equivalences (bool *saw_equiv)
1103 1.1 mrg {
1104 1.1 mrg segment_info *f;
1105 1.1 mrg bool more = TRUE;
1106 1.1 mrg
1107 1.1 mrg while (more)
1108 1.1 mrg {
1109 1.1 mrg more = FALSE;
1110 1.1 mrg for (f = current_segment; f; f = f->next)
1111 1.1 mrg {
1112 1.1 mrg if (!f->sym->equiv_built)
1113 1.1 mrg {
1114 1.1 mrg f->sym->equiv_built = 1;
1115 1.1 mrg bool seen_one = find_equivalence (f);
1116 1.1 mrg if (seen_one)
1117 1.1 mrg {
1118 1.1 mrg *saw_equiv = true;
1119 1.1 mrg more = true;
1120 1.1 mrg }
1121 1.1 mrg }
1122 1.1 mrg }
1123 1.1 mrg }
1124 1.1 mrg
1125 1.1 mrg /* Add a copy of this segment list to the namespace. */
1126 1.1 mrg copy_equiv_list_to_ns (current_segment);
1127 1.1 mrg }
1128 1.1 mrg
1129 1.1 mrg
1130 1.1 mrg /* Returns the offset necessary to properly align the current equivalence.
1131 1.1 mrg Sets *palign to the required alignment. */
1132 1.1 mrg
1133 1.1 mrg static HOST_WIDE_INT
1134 1.1 mrg align_segment (unsigned HOST_WIDE_INT *palign)
1135 1.1 mrg {
1136 1.1 mrg segment_info *s;
1137 1.1 mrg unsigned HOST_WIDE_INT offset;
1138 1.1 mrg unsigned HOST_WIDE_INT max_align;
1139 1.1 mrg unsigned HOST_WIDE_INT this_align;
1140 1.1 mrg unsigned HOST_WIDE_INT this_offset;
1141 1.1 mrg
1142 1.1 mrg max_align = 1;
1143 1.1 mrg offset = 0;
1144 1.1 mrg for (s = current_segment; s; s = s->next)
1145 1.1 mrg {
1146 1.1 mrg this_align = TYPE_ALIGN_UNIT (s->field);
1147 1.1 mrg if (s->offset & (this_align - 1))
1148 1.1 mrg {
1149 1.1 mrg /* Field is misaligned. */
1150 1.1 mrg this_offset = this_align - ((s->offset + offset) & (this_align - 1));
1151 1.1 mrg if (this_offset & (max_align - 1))
1152 1.1 mrg {
1153 1.1 mrg /* Aligning this field would misalign a previous field. */
1154 1.1 mrg gfc_error ("The equivalence set for variable %qs "
1155 1.1 mrg "declared at %L violates alignment requirements",
1156 1.1 mrg s->sym->name, &s->sym->declared_at);
1157 1.1 mrg }
1158 1.1 mrg offset += this_offset;
1159 1.1 mrg }
1160 1.1 mrg max_align = this_align;
1161 1.1 mrg }
1162 1.1 mrg if (palign)
1163 1.1 mrg *palign = max_align;
1164 1.1 mrg return offset;
1165 1.1 mrg }
1166 1.1 mrg
1167 1.1 mrg
1168 1.1 mrg /* Adjust segment offsets by the given amount. */
1169 1.1 mrg
1170 1.1 mrg static void
1171 1.1 mrg apply_segment_offset (segment_info *s, HOST_WIDE_INT offset)
1172 1.1 mrg {
1173 1.1 mrg for (; s; s = s->next)
1174 1.1 mrg s->offset += offset;
1175 1.1 mrg }
1176 1.1 mrg
1177 1.1 mrg
1178 1.1 mrg /* Lay out a symbol in a common block. If the symbol has already been seen
1179 1.1 mrg then check the location is consistent. Otherwise create segments
1180 1.1 mrg for that symbol and all the symbols equivalenced with it. */
1181 1.1 mrg
1182 1.1 mrg /* Translate a single common block. */
1183 1.1 mrg
1184 1.1 mrg static void
1185 1.1 mrg translate_common (gfc_common_head *common, gfc_symbol *var_list)
1186 1.1 mrg {
1187 1.1 mrg gfc_symbol *sym;
1188 1.1 mrg segment_info *s;
1189 1.1 mrg segment_info *common_segment;
1190 1.1 mrg HOST_WIDE_INT offset;
1191 1.1 mrg HOST_WIDE_INT current_offset;
1192 1.1 mrg unsigned HOST_WIDE_INT align;
1193 1.1 mrg bool saw_equiv;
1194 1.1 mrg
1195 1.1 mrg common_segment = NULL;
1196 1.1 mrg offset = 0;
1197 1.1 mrg current_offset = 0;
1198 1.1 mrg align = 1;
1199 1.1 mrg saw_equiv = false;
1200 1.1 mrg
1201 1.1 mrg /* Add symbols to the segment. */
1202 1.1 mrg for (sym = var_list; sym; sym = sym->common_next)
1203 1.1 mrg {
1204 1.1 mrg current_segment = common_segment;
1205 1.1 mrg s = find_segment_info (sym);
1206 1.1 mrg
1207 1.1 mrg /* Symbol has already been added via an equivalence. Multiple
1208 1.1 mrg use associations of the same common block result in equiv_built
1209 1.1 mrg being set but no information about the symbol in the segment. */
1210 1.1 mrg if (s && sym->equiv_built)
1211 1.1 mrg {
1212 1.1 mrg /* Ensure the current location is properly aligned. */
1213 1.1 mrg align = TYPE_ALIGN_UNIT (s->field);
1214 1.1 mrg current_offset = (current_offset + align - 1) &~ (align - 1);
1215 1.1 mrg
1216 1.1 mrg /* Verify that it ended up where we expect it. */
1217 1.1 mrg if (s->offset != current_offset)
1218 1.1 mrg {
1219 1.1 mrg gfc_error ("Equivalence for %qs does not match ordering of "
1220 1.1 mrg "COMMON %qs at %L", sym->name,
1221 1.1 mrg common->name, &common->where);
1222 1.1 mrg }
1223 1.1 mrg }
1224 1.1 mrg else
1225 1.1 mrg {
1226 1.1 mrg /* A symbol we haven't seen before. */
1227 1.1 mrg s = current_segment = get_segment_info (sym, current_offset);
1228 1.1 mrg
1229 1.1 mrg /* Add all objects directly or indirectly equivalenced with this
1230 1.1 mrg symbol. */
1231 1.1 mrg add_equivalences (&saw_equiv);
1232 1.1 mrg
1233 1.1 mrg if (current_segment->offset < 0)
1234 1.1 mrg gfc_error ("The equivalence set for %qs cause an invalid "
1235 1.1 mrg "extension to COMMON %qs at %L", sym->name,
1236 1.1 mrg common->name, &common->where);
1237 1.1 mrg
1238 1.1 mrg if (flag_align_commons)
1239 1.1 mrg offset = align_segment (&align);
1240 1.1 mrg
1241 1.1 mrg if (offset)
1242 1.1 mrg {
1243 1.1 mrg /* The required offset conflicts with previous alignment
1244 1.1 mrg requirements. Insert padding immediately before this
1245 1.1 mrg segment. */
1246 1.1 mrg if (warn_align_commons)
1247 1.1 mrg {
1248 1.1 mrg if (strcmp (common->name, BLANK_COMMON_NAME))
1249 1.1 mrg gfc_warning (OPT_Walign_commons,
1250 1.1 mrg "Padding of %d bytes required before %qs in "
1251 1.1 mrg "COMMON %qs at %L; reorder elements or use "
1252 1.1 mrg "%<-fno-align-commons%>", (int)offset,
1253 1.1 mrg s->sym->name, common->name, &common->where);
1254 1.1 mrg else
1255 1.1 mrg gfc_warning (OPT_Walign_commons,
1256 1.1 mrg "Padding of %d bytes required before %qs in "
1257 1.1 mrg "COMMON at %L; reorder elements or use "
1258 1.1 mrg "%<-fno-align-commons%>", (int)offset,
1259 1.1 mrg s->sym->name, &common->where);
1260 1.1 mrg }
1261 1.1 mrg }
1262 1.1 mrg
1263 1.1 mrg /* Apply the offset to the new segments. */
1264 1.1 mrg apply_segment_offset (current_segment, offset);
1265 1.1 mrg current_offset += offset;
1266 1.1 mrg
1267 1.1 mrg /* Add the new segments to the common block. */
1268 1.1 mrg common_segment = add_segments (common_segment, current_segment);
1269 1.1 mrg }
1270 1.1 mrg
1271 1.1 mrg /* The offset of the next common variable. */
1272 1.1 mrg current_offset += s->length;
1273 1.1 mrg }
1274 1.1 mrg
1275 1.1 mrg if (common_segment == NULL)
1276 1.1 mrg {
1277 1.1 mrg gfc_error ("COMMON %qs at %L does not exist",
1278 1.1 mrg common->name, &common->where);
1279 1.1 mrg return;
1280 1.1 mrg }
1281 1.1 mrg
1282 1.1 mrg if (common_segment->offset != 0 && warn_align_commons)
1283 1.1 mrg {
1284 1.1 mrg if (strcmp (common->name, BLANK_COMMON_NAME))
1285 1.1 mrg gfc_warning (OPT_Walign_commons,
1286 1.1 mrg "COMMON %qs at %L requires %d bytes of padding; "
1287 1.1 mrg "reorder elements or use %<-fno-align-commons%>",
1288 1.1 mrg common->name, &common->where, (int)common_segment->offset);
1289 1.1 mrg else
1290 1.1 mrg gfc_warning (OPT_Walign_commons,
1291 1.1 mrg "COMMON at %L requires %d bytes of padding; "
1292 1.1 mrg "reorder elements or use %<-fno-align-commons%>",
1293 1.1 mrg &common->where, (int)common_segment->offset);
1294 1.1 mrg }
1295 1.1 mrg
1296 1.1 mrg create_common (common, common_segment, saw_equiv);
1297 1.1 mrg }
1298 1.1 mrg
1299 1.1 mrg
1300 1.1 mrg /* Create a new block for each merged equivalence list. */
1301 1.1 mrg
1302 1.1 mrg static void
1303 1.1 mrg finish_equivalences (gfc_namespace *ns)
1304 1.1 mrg {
1305 1.1 mrg gfc_equiv *z, *y;
1306 1.1 mrg gfc_symbol *sym;
1307 1.1 mrg gfc_common_head * c;
1308 1.1 mrg HOST_WIDE_INT offset;
1309 1.1 mrg unsigned HOST_WIDE_INT align;
1310 1.1 mrg bool dummy;
1311 1.1 mrg
1312 1.1 mrg for (z = ns->equiv; z; z = z->next)
1313 1.1 mrg for (y = z->eq; y; y = y->eq)
1314 1.1 mrg {
1315 1.1 mrg if (y->used)
1316 1.1 mrg continue;
1317 1.1 mrg sym = z->expr->symtree->n.sym;
1318 1.1 mrg current_segment = get_segment_info (sym, 0);
1319 1.1 mrg
1320 1.1 mrg /* All objects directly or indirectly equivalenced with this
1321 1.1 mrg symbol. */
1322 1.1 mrg add_equivalences (&dummy);
1323 1.1 mrg
1324 1.1 mrg /* Align the block. */
1325 1.1 mrg offset = align_segment (&align);
1326 1.1 mrg
1327 1.1 mrg /* Ensure all offsets are positive. */
1328 1.1 mrg offset -= current_segment->offset & ~(align - 1);
1329 1.1 mrg
1330 1.1 mrg apply_segment_offset (current_segment, offset);
1331 1.1 mrg
1332 1.1 mrg /* Create the decl. If this is a module equivalence, it has a
1333 1.1 mrg unique name, pointed to by z->module. This is written to a
1334 1.1 mrg gfc_common_header to push create_common into using
1335 1.1 mrg build_common_decl, so that the equivalence appears as an
1336 1.1 mrg external symbol. Otherwise, a local declaration is built using
1337 1.1 mrg build_equiv_decl. */
1338 1.1 mrg if (z->module)
1339 1.1 mrg {
1340 1.1 mrg c = gfc_get_common_head ();
1341 1.1 mrg /* We've lost the real location, so use the location of the
1342 1.1 mrg enclosing procedure. If we're in a BLOCK DATA block, then
1343 1.1 mrg use the location in the sym_root. */
1344 1.1 mrg if (ns->proc_name)
1345 1.1 mrg c->where = ns->proc_name->declared_at;
1346 1.1 mrg else if (ns->is_block_data)
1347 1.1 mrg c->where = ns->sym_root->n.sym->declared_at;
1348 1.1 mrg
1349 1.1 mrg size_t len = strlen (z->module);
1350 1.1 mrg gcc_assert (len < sizeof (c->name));
1351 1.1 mrg memcpy (c->name, z->module, len);
1352 1.1 mrg c->name[len] = '\0';
1353 1.1 mrg }
1354 1.1 mrg else
1355 1.1 mrg c = NULL;
1356 1.1 mrg
1357 1.1 mrg create_common (c, current_segment, true);
1358 1.1 mrg break;
1359 1.1 mrg }
1360 1.1 mrg }
1361 1.1 mrg
1362 1.1 mrg
1363 1.1 mrg /* Work function for translating a named common block. */
1364 1.1 mrg
1365 1.1 mrg static void
1366 1.1 mrg named_common (gfc_symtree *st)
1367 1.1 mrg {
1368 1.1 mrg translate_common (st->n.common, st->n.common->head);
1369 1.1 mrg }
1370 1.1 mrg
1371 1.1 mrg
1372 1.1 mrg /* Translate the common blocks in a namespace. Unlike other variables,
1373 1.1 mrg these have to be created before code, because the backend_decl depends
1374 1.1 mrg on the rest of the common block. */
1375 1.1 mrg
1376 1.1 mrg void
1377 1.1 mrg gfc_trans_common (gfc_namespace *ns)
1378 1.1 mrg {
1379 1.1 mrg gfc_common_head *c;
1380 1.1 mrg
1381 1.1 mrg /* Translate the blank common block. */
1382 1.1 mrg if (ns->blank_common.head != NULL)
1383 1.1 mrg {
1384 1.1 mrg c = gfc_get_common_head ();
1385 1.1 mrg c->where = ns->blank_common.head->common_head->where;
1386 1.1 mrg strcpy (c->name, BLANK_COMMON_NAME);
1387 1.1 mrg translate_common (c, ns->blank_common.head);
1388 1.1 mrg }
1389 1.1 mrg
1390 1.1 mrg /* Translate all named common blocks. */
1391 1.1 mrg gfc_traverse_symtree (ns->common_root, named_common);
1392 1.1 mrg
1393 1.1 mrg /* Translate local equivalence. */
1394 1.1 mrg finish_equivalences (ns);
1395 1.1 mrg
1396 1.1 mrg /* Commit the newly created symbols for common blocks and module
1397 1.1 mrg equivalences. */
1398 1.1 mrg gfc_commit_symbols ();
1399 1.1 mrg }
1400