OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [gcc/] [fortran/] [trans-common.c] - Blame information for rev 720

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.