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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [gcc-4.5.1/] [gcc/] [fortran/] [data.c] - Blame information for rev 328

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

Line No. Rev Author Line
1 285 jeremybenn
/* Supporting functions for resolving DATA statement.
2
   Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
3
   Free Software Foundation, Inc.
4
   Contributed by Lifang Zeng <zlf605@hotmail.com>
5
 
6
This file is part of GCC.
7
 
8
GCC is free software; you can redistribute it and/or modify it under
9
the terms of the GNU General Public License as published by the Free
10
Software Foundation; either version 3, or (at your option) any later
11
version.
12
 
13
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14
WARRANTY; without even the implied warranty of MERCHANTABILITY or
15
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16
for more details.
17
 
18
You should have received a copy of the GNU General Public License
19
along with GCC; see the file COPYING3.  If not see
20
<http://www.gnu.org/licenses/>.  */
21
 
22
 
23
/* Notes for DATA statement implementation:
24
 
25
   We first assign initial value to each symbol by gfc_assign_data_value
26
   during resolving DATA statement. Refer to check_data_variable and
27
   traverse_data_list in resolve.c.
28
 
29
   The complexity exists in the handling of array section, implied do
30
   and array of struct appeared in DATA statement.
31
 
32
   We call gfc_conv_structure, gfc_con_array_array_initializer,
33
   etc., to convert the initial value. Refer to trans-expr.c and
34
   trans-array.c.  */
35
 
36
#include "config.h"
37
#include "gfortran.h"
38
#include "data.h"
39
 
40
static void formalize_init_expr (gfc_expr *);
41
 
42
/* Calculate the array element offset.  */
43
 
44
static void
45
get_array_index (gfc_array_ref *ar, mpz_t *offset)
46
{
47
  gfc_expr *e;
48
  int i;
49
  mpz_t delta;
50
  mpz_t tmp;
51
 
52
  mpz_init (tmp);
53
  mpz_set_si (*offset, 0);
54
  mpz_init_set_si (delta, 1);
55
  for (i = 0; i < ar->dimen; i++)
56
    {
57
      e = gfc_copy_expr (ar->start[i]);
58
      gfc_simplify_expr (e, 1);
59
 
60
      if ((gfc_is_constant_expr (ar->as->lower[i]) == 0)
61
          || (gfc_is_constant_expr (ar->as->upper[i]) == 0)
62
          || (gfc_is_constant_expr (e) == 0))
63
        gfc_error ("non-constant array in DATA statement %L", &ar->where);
64
 
65
      mpz_set (tmp, e->value.integer);
66
      mpz_sub (tmp, tmp, ar->as->lower[i]->value.integer);
67
      mpz_mul (tmp, tmp, delta);
68
      mpz_add (*offset, tmp, *offset);
69
 
70
      mpz_sub (tmp, ar->as->upper[i]->value.integer,
71
               ar->as->lower[i]->value.integer);
72
      mpz_add_ui (tmp, tmp, 1);
73
      mpz_mul (delta, tmp, delta);
74
    }
75
  mpz_clear (delta);
76
  mpz_clear (tmp);
77
}
78
 
79
 
80
/* Find if there is a constructor which offset is equal to OFFSET.  */
81
 
82
static gfc_constructor *
83
find_con_by_offset (splay_tree spt, mpz_t offset)
84
{
85
  mpz_t tmp;
86
  gfc_constructor *ret = NULL;
87
  gfc_constructor *con;
88
  splay_tree_node sptn;
89
 
90
  /* The complexity is due to needing quick access to the linked list of
91
     constructors.  Both a linked list and a splay tree are used, and both
92
     are kept up to date if they are array elements (which is the only time
93
     that a specific constructor has to be found).  */
94
 
95
  gcc_assert (spt != NULL);
96
  mpz_init (tmp);
97
 
98
  sptn = splay_tree_lookup (spt, (splay_tree_key) mpz_get_si (offset));
99
 
100
  if (sptn)
101
    ret = (gfc_constructor*) sptn->value;
102
  else
103
    {
104
       /* Need to check and see if we match a range, so we will pull
105
          the next lowest index and see if the range matches.  */
106
       sptn = splay_tree_predecessor (spt,
107
                                      (splay_tree_key) mpz_get_si (offset));
108
       if (sptn)
109
         {
110
            con = (gfc_constructor*) sptn->value;
111
            if (mpz_cmp_ui (con->repeat, 1) > 0)
112
              {
113
                 mpz_init (tmp);
114
                 mpz_add (tmp, con->n.offset, con->repeat);
115
                 if (mpz_cmp (offset, tmp) < 0)
116
                   ret = con;
117
                 mpz_clear (tmp);
118
              }
119
            else
120
              ret = NULL; /* The range did not match.  */
121
         }
122
      else
123
        ret = NULL; /* No pred, so no match.  */
124
    }
125
 
126
  return ret;
127
}
128
 
129
 
130
/* Find if there is a constructor which component is equal to COM.  */
131
 
132
static gfc_constructor *
133
find_con_by_component (gfc_component *com, gfc_constructor *con)
134
{
135
  for (; con; con = con->next)
136
    {
137
      if (com == con->n.component)
138
        return con;
139
    }
140
  return NULL;
141
}
142
 
143
 
144
/* Create a character type initialization expression from RVALUE.
145
   TS [and REF] describe [the substring of] the variable being initialized.
146
   INIT is the existing initializer, not NULL.  Initialization is performed
147
   according to normal assignment rules.  */
148
 
149
static gfc_expr *
150
create_character_intializer (gfc_expr *init, gfc_typespec *ts,
151
                             gfc_ref *ref, gfc_expr *rvalue)
152
{
153
  int len, start, end;
154
  gfc_char_t *dest;
155
 
156
  gfc_extract_int (ts->u.cl->length, &len);
157
 
158
  if (init == NULL)
159
    {
160
      /* Create a new initializer.  */
161
      init = gfc_get_expr ();
162
      init->expr_type = EXPR_CONSTANT;
163
      init->ts = *ts;
164
 
165
      dest = gfc_get_wide_string (len + 1);
166
      dest[len] = '\0';
167
      init->value.character.length = len;
168
      init->value.character.string = dest;
169
      /* Blank the string if we're only setting a substring.  */
170
      if (ref != NULL)
171
        gfc_wide_memset (dest, ' ', len);
172
    }
173
  else
174
    dest = init->value.character.string;
175
 
176
  if (ref)
177
    {
178
      gfc_expr *start_expr, *end_expr;
179
 
180
      gcc_assert (ref->type == REF_SUBSTRING);
181
 
182
      /* Only set a substring of the destination.  Fortran substring bounds
183
         are one-based [start, end], we want zero based [start, end).  */
184
      start_expr = gfc_copy_expr (ref->u.ss.start);
185
      end_expr = gfc_copy_expr (ref->u.ss.end);
186
 
187
      if ((gfc_simplify_expr (start_expr, 1) == FAILURE)
188
          || (gfc_simplify_expr (end_expr, 1)) == FAILURE)
189
        {
190
          gfc_error ("failure to simplify substring reference in DATA "
191
                     "statement at %L", &ref->u.ss.start->where);
192
          return NULL;
193
        }
194
 
195
      gfc_extract_int (start_expr, &start);
196
      start--;
197
      gfc_extract_int (end_expr, &end);
198
    }
199
  else
200
    {
201
      /* Set the whole string.  */
202
      start = 0;
203
      end = len;
204
    }
205
 
206
  /* Copy the initial value.  */
207
  if (rvalue->ts.type == BT_HOLLERITH)
208
    len = rvalue->representation.length;
209
  else
210
    len = rvalue->value.character.length;
211
 
212
  if (len > end - start)
213
    {
214
      len = end - start;
215
      gfc_warning_now ("initialization string truncated to match variable "
216
                       "at %L", &rvalue->where);
217
    }
218
 
219
  if (rvalue->ts.type == BT_HOLLERITH)
220
    {
221
      int i;
222
      for (i = 0; i < len; i++)
223
        dest[start+i] = rvalue->representation.string[i];
224
    }
225
  else
226
    memcpy (&dest[start], rvalue->value.character.string,
227
            len * sizeof (gfc_char_t));
228
 
229
  /* Pad with spaces.  Substrings will already be blanked.  */
230
  if (len < end - start && ref == NULL)
231
    gfc_wide_memset (&dest[start + len], ' ', end - (start + len));
232
 
233
  if (rvalue->ts.type == BT_HOLLERITH)
234
    {
235
      init->representation.length = init->value.character.length;
236
      init->representation.string
237
        = gfc_widechar_to_char (init->value.character.string,
238
                                init->value.character.length);
239
    }
240
 
241
  return init;
242
}
243
 
244
 
245
/* Assign the initial value RVALUE to  LVALUE's symbol->value. If the
246
   LVALUE already has an initialization, we extend this, otherwise we
247
   create a new one.  */
248
 
249
gfc_try
250
gfc_assign_data_value (gfc_expr *lvalue, gfc_expr *rvalue, mpz_t index)
251
{
252
  gfc_ref *ref;
253
  gfc_expr *init;
254
  gfc_expr *expr;
255
  gfc_constructor *con;
256
  gfc_constructor *last_con;
257
  gfc_constructor *pred;
258
  gfc_symbol *symbol;
259
  gfc_typespec *last_ts;
260
  mpz_t offset;
261
  splay_tree spt;
262
  splay_tree_node sptn;
263
 
264
  symbol = lvalue->symtree->n.sym;
265
  init = symbol->value;
266
  last_ts = &symbol->ts;
267
  last_con = NULL;
268
  mpz_init_set_si (offset, 0);
269
 
270
  /* Find/create the parent expressions for subobject references.  */
271
  for (ref = lvalue->ref; ref; ref = ref->next)
272
    {
273
      /* Break out of the loop if we find a substring.  */
274
      if (ref->type == REF_SUBSTRING)
275
        {
276
          /* A substring should always be the last subobject reference.  */
277
          gcc_assert (ref->next == NULL);
278
          break;
279
        }
280
 
281
      /* Use the existing initializer expression if it exists.  Otherwise
282
         create a new one.  */
283
      if (init == NULL)
284
        expr = gfc_get_expr ();
285
      else
286
        expr = init;
287
 
288
      /* Find or create this element.  */
289
      switch (ref->type)
290
        {
291
        case REF_ARRAY:
292
          if (init && expr->expr_type != EXPR_ARRAY)
293
            {
294
              gfc_error ("'%s' at %L already is initialized at %L",
295
                         lvalue->symtree->n.sym->name, &lvalue->where,
296
                         &init->where);
297
              return FAILURE;
298
            }
299
 
300
          if (init == NULL)
301
            {
302
              /* The element typespec will be the same as the array
303
                 typespec.  */
304
              expr->ts = *last_ts;
305
              /* Setup the expression to hold the constructor.  */
306
              expr->expr_type = EXPR_ARRAY;
307
              expr->rank = ref->u.ar.as->rank;
308
            }
309
 
310
          if (ref->u.ar.type == AR_ELEMENT)
311
            get_array_index (&ref->u.ar, &offset);
312
          else
313
            mpz_set (offset, index);
314
 
315
          /* Check the bounds.  */
316
          if (mpz_cmp_si (offset, 0) < 0)
317
            {
318
              gfc_error ("Data element below array lower bound at %L",
319
                         &lvalue->where);
320
              return FAILURE;
321
            }
322
          else
323
            {
324
              mpz_t size;
325
              if (spec_size (ref->u.ar.as, &size) == SUCCESS)
326
                {
327
                  if (mpz_cmp (offset, size) >= 0)
328
                  {
329
                    mpz_clear (size);
330
                    gfc_error ("Data element above array upper bound at %L",
331
                               &lvalue->where);
332
                    return FAILURE;
333
                  }
334
                  mpz_clear (size);
335
                }
336
            }
337
 
338
          /* Splay tree containing offset and gfc_constructor.  */
339
          spt = expr->con_by_offset;
340
 
341
          if (spt == NULL)
342
            {
343
               spt = splay_tree_new (splay_tree_compare_ints, NULL, NULL);
344
               expr->con_by_offset = spt;
345
               con = NULL;
346
            }
347
         else
348
          con = find_con_by_offset (spt, offset);
349
 
350
          if (con == NULL)
351
            {
352
              splay_tree_key j;
353
 
354
              /* Create a new constructor.  */
355
              con = gfc_get_constructor ();
356
              mpz_set (con->n.offset, offset);
357
              j = (splay_tree_key) mpz_get_si (offset);
358
              sptn = splay_tree_insert (spt, j, (splay_tree_value) con);
359
              /* Fix up the linked list.  */
360
              sptn = splay_tree_predecessor (spt, j);
361
              if (sptn == NULL)
362
                {  /* Insert at the head.  */
363
                   con->next = expr->value.constructor;
364
                   expr->value.constructor = con;
365
                }
366
              else
367
                {  /* Insert in the chain.  */
368
                   pred = (gfc_constructor*) sptn->value;
369
                   con->next = pred->next;
370
                   pred->next = con;
371
                }
372
            }
373
          break;
374
 
375
        case REF_COMPONENT:
376
          if (init == NULL)
377
            {
378
              /* Setup the expression to hold the constructor.  */
379
              expr->expr_type = EXPR_STRUCTURE;
380
              expr->ts.type = BT_DERIVED;
381
              expr->ts.u.derived = ref->u.c.sym;
382
            }
383
          else
384
            gcc_assert (expr->expr_type == EXPR_STRUCTURE);
385
          last_ts = &ref->u.c.component->ts;
386
 
387
          /* Find the same element in the existing constructor.  */
388
          con = expr->value.constructor;
389
          con = find_con_by_component (ref->u.c.component, con);
390
 
391
          if (con == NULL)
392
            {
393
              /* Create a new constructor.  */
394
              con = gfc_get_constructor ();
395
              con->n.component = ref->u.c.component;
396
              con->next = expr->value.constructor;
397
              expr->value.constructor = con;
398
            }
399
          break;
400
 
401
        default:
402
          gcc_unreachable ();
403
        }
404
 
405
      if (init == NULL)
406
        {
407
          /* Point the container at the new expression.  */
408
          if (last_con == NULL)
409
            symbol->value = expr;
410
          else
411
            last_con->expr = expr;
412
        }
413
      init = con->expr;
414
      last_con = con;
415
    }
416
 
417
  if (ref || last_ts->type == BT_CHARACTER)
418
    {
419
      if (lvalue->ts.u.cl->length == NULL && !(ref && ref->u.ss.length != NULL))
420
        return FAILURE;
421
      expr = create_character_intializer (init, last_ts, ref, rvalue);
422
    }
423
  else
424
    {
425
      /* Overwriting an existing initializer is non-standard but usually only
426
         provokes a warning from other compilers.  */
427
      if (init != NULL)
428
        {
429
          /* Order in which the expressions arrive here depends on whether
430
             they are from data statements or F95 style declarations.
431
             Therefore, check which is the most recent.  */
432
          expr = (LOCATION_LINE (init->where.lb->location)
433
                  > LOCATION_LINE (rvalue->where.lb->location))
434
               ? init : rvalue;
435
          gfc_notify_std (GFC_STD_GNU, "Extension: re-initialization "
436
                          "of '%s' at %L", symbol->name, &expr->where);
437
        }
438
 
439
      expr = gfc_copy_expr (rvalue);
440
      if (!gfc_compare_types (&lvalue->ts, &expr->ts))
441
        gfc_convert_type (expr, &lvalue->ts, 0);
442
    }
443
 
444
  if (last_con == NULL)
445
    symbol->value = expr;
446
  else
447
    last_con->expr = expr;
448
 
449
  return SUCCESS;
450
}
451
 
452
 
453
/* Similarly, but initialize REPEAT consecutive values in LVALUE the same
454
   value in RVALUE.  For the nonce, LVALUE must refer to a full array, not
455
   an array section.  */
456
 
457
void
458
gfc_assign_data_value_range (gfc_expr *lvalue, gfc_expr *rvalue,
459
                             mpz_t index, mpz_t repeat)
460
{
461
  gfc_ref *ref;
462
  gfc_expr *init, *expr;
463
  gfc_constructor *con, *last_con;
464
  gfc_constructor *pred;
465
  gfc_symbol *symbol;
466
  gfc_typespec *last_ts;
467
  mpz_t offset;
468
  splay_tree spt;
469
  splay_tree_node sptn;
470
 
471
  symbol = lvalue->symtree->n.sym;
472
  init = symbol->value;
473
  last_ts = &symbol->ts;
474
  last_con = NULL;
475
  mpz_init_set_si (offset, 0);
476
 
477
  /* Find/create the parent expressions for subobject references.  */
478
  for (ref = lvalue->ref; ref; ref = ref->next)
479
    {
480
      /* Use the existing initializer expression if it exists.
481
         Otherwise create a new one.  */
482
      if (init == NULL)
483
        expr = gfc_get_expr ();
484
      else
485
        expr = init;
486
 
487
      /* Find or create this element.  */
488
      switch (ref->type)
489
        {
490
        case REF_ARRAY:
491
          if (init == NULL)
492
            {
493
              /* The element typespec will be the same as the array
494
                 typespec.  */
495
              expr->ts = *last_ts;
496
              /* Setup the expression to hold the constructor.  */
497
              expr->expr_type = EXPR_ARRAY;
498
              expr->rank = ref->u.ar.as->rank;
499
            }
500
          else
501
            gcc_assert (expr->expr_type == EXPR_ARRAY);
502
 
503
          if (ref->u.ar.type == AR_ELEMENT)
504
            {
505
              get_array_index (&ref->u.ar, &offset);
506
 
507
              /* This had better not be the bottom of the reference.
508
                 We can still get to a full array via a component.  */
509
              gcc_assert (ref->next != NULL);
510
            }
511
          else
512
            {
513
              mpz_set (offset, index);
514
 
515
              /* We're at a full array or an array section.  This means
516
                 that we've better have found a full array, and that we're
517
                 at the bottom of the reference.  */
518
              gcc_assert (ref->u.ar.type == AR_FULL);
519
              gcc_assert (ref->next == NULL);
520
            }
521
 
522
          /* Find the same element in the existing constructor.  */
523
 
524
          /* Splay tree containing offset and gfc_constructor.  */
525
          spt = expr->con_by_offset;
526
 
527
          if (spt == NULL)
528
            {
529
               spt = splay_tree_new (splay_tree_compare_ints, NULL, NULL);
530
               expr->con_by_offset = spt;
531
               con = NULL;
532
            }
533
          else
534
            con = find_con_by_offset (spt, offset);
535
 
536
          if (con == NULL)
537
            {
538
              splay_tree_key j;
539
              /* Create a new constructor.  */
540
              con = gfc_get_constructor ();
541
              mpz_set (con->n.offset, offset);
542
              j = (splay_tree_key) mpz_get_si (offset);
543
 
544
              if (ref->next == NULL)
545
                mpz_set (con->repeat, repeat);
546
              sptn = splay_tree_insert (spt, j, (splay_tree_value) con);
547
              /* Fix up the linked list.  */
548
              sptn = splay_tree_predecessor (spt, j);
549
              if (sptn == NULL)
550
                {  /* Insert at the head.  */
551
                   con->next = expr->value.constructor;
552
                   expr->value.constructor = con;
553
                }
554
              else
555
                {  /* Insert in the chain.  */
556
                   pred = (gfc_constructor*) sptn->value;
557
                   con->next = pred->next;
558
                   pred->next = con;
559
                }
560
            }
561
          else
562
            gcc_assert (ref->next != NULL);
563
          break;
564
 
565
        case REF_COMPONENT:
566
          if (init == NULL)
567
            {
568
              /* Setup the expression to hold the constructor.  */
569
              expr->expr_type = EXPR_STRUCTURE;
570
              expr->ts.type = BT_DERIVED;
571
              expr->ts.u.derived = ref->u.c.sym;
572
            }
573
          else
574
            gcc_assert (expr->expr_type == EXPR_STRUCTURE);
575
          last_ts = &ref->u.c.component->ts;
576
 
577
          /* Find the same element in the existing constructor.  */
578
          con = expr->value.constructor;
579
          con = find_con_by_component (ref->u.c.component, con);
580
 
581
          if (con == NULL)
582
            {
583
              /* Create a new constructor.  */
584
              con = gfc_get_constructor ();
585
              con->n.component = ref->u.c.component;
586
              con->next = expr->value.constructor;
587
              expr->value.constructor = con;
588
            }
589
 
590
          /* Since we're only intending to initialize arrays here,
591
             there better be an inner reference.  */
592
          gcc_assert (ref->next != NULL);
593
          break;
594
 
595
        case REF_SUBSTRING:
596
        default:
597
          gcc_unreachable ();
598
        }
599
 
600
      if (init == NULL)
601
        {
602
          /* Point the container at the new expression.  */
603
          if (last_con == NULL)
604
            symbol->value = expr;
605
          else
606
            last_con->expr = expr;
607
        }
608
      init = con->expr;
609
      last_con = con;
610
    }
611
 
612
  if (last_ts->type == BT_CHARACTER)
613
    expr = create_character_intializer (init, last_ts, NULL, rvalue);
614
  else
615
    {
616
      /* We should never be overwriting an existing initializer.  */
617
      gcc_assert (!init);
618
 
619
      expr = gfc_copy_expr (rvalue);
620
      if (!gfc_compare_types (&lvalue->ts, &expr->ts))
621
        gfc_convert_type (expr, &lvalue->ts, 0);
622
    }
623
 
624
  if (last_con == NULL)
625
    symbol->value = expr;
626
  else
627
    last_con->expr = expr;
628
}
629
 
630
/* Modify the index of array section and re-calculate the array offset.  */
631
 
632
void
633
gfc_advance_section (mpz_t *section_index, gfc_array_ref *ar,
634
                     mpz_t *offset_ret)
635
{
636
  int i;
637
  mpz_t delta;
638
  mpz_t tmp;
639
  bool forwards;
640
  int cmp;
641
 
642
  for (i = 0; i < ar->dimen; i++)
643
    {
644
      if (ar->dimen_type[i] != DIMEN_RANGE)
645
        continue;
646
 
647
      if (ar->stride[i])
648
        {
649
          mpz_add (section_index[i], section_index[i],
650
                   ar->stride[i]->value.integer);
651
        if (mpz_cmp_si (ar->stride[i]->value.integer, 0) >= 0)
652
          forwards = true;
653
        else
654
          forwards = false;
655
        }
656
      else
657
        {
658
          mpz_add_ui (section_index[i], section_index[i], 1);
659
          forwards = true;
660
        }
661
 
662
      if (ar->end[i])
663
        cmp = mpz_cmp (section_index[i], ar->end[i]->value.integer);
664
      else
665
        cmp = mpz_cmp (section_index[i], ar->as->upper[i]->value.integer);
666
 
667
      if ((cmp > 0 && forwards) || (cmp < 0 && !forwards))
668
        {
669
          /* Reset index to start, then loop to advance the next index.  */
670
          if (ar->start[i])
671
            mpz_set (section_index[i], ar->start[i]->value.integer);
672
          else
673
            mpz_set (section_index[i], ar->as->lower[i]->value.integer);
674
        }
675
      else
676
        break;
677
    }
678
 
679
  mpz_set_si (*offset_ret, 0);
680
  mpz_init_set_si (delta, 1);
681
  mpz_init (tmp);
682
  for (i = 0; i < ar->dimen; i++)
683
    {
684
      mpz_sub (tmp, section_index[i], ar->as->lower[i]->value.integer);
685
      mpz_mul (tmp, tmp, delta);
686
      mpz_add (*offset_ret, tmp, *offset_ret);
687
 
688
      mpz_sub (tmp, ar->as->upper[i]->value.integer,
689
               ar->as->lower[i]->value.integer);
690
      mpz_add_ui (tmp, tmp, 1);
691
      mpz_mul (delta, tmp, delta);
692
    }
693
  mpz_clear (tmp);
694
  mpz_clear (delta);
695
}
696
 
697
 
698
/* Rearrange a structure constructor so the elements are in the specified
699
   order.  Also insert NULL entries if necessary.  */
700
 
701
static void
702
formalize_structure_cons (gfc_expr *expr)
703
{
704
  gfc_constructor *head;
705
  gfc_constructor *tail;
706
  gfc_constructor *cur;
707
  gfc_constructor *last;
708
  gfc_constructor *c;
709
  gfc_component *order;
710
 
711
  c = expr->value.constructor;
712
 
713
  /* Constructor is already formalized.  */
714
  if (!c || c->n.component == NULL)
715
    return;
716
 
717
  head = tail = NULL;
718
  for (order = expr->ts.u.derived->components; order; order = order->next)
719
    {
720
      /* Find the next component.  */
721
      last = NULL;
722
      cur = c;
723
      while (cur != NULL && cur->n.component != order)
724
        {
725
          last = cur;
726
          cur = cur->next;
727
        }
728
 
729
      if (cur == NULL)
730
        {
731
          /* Create a new one.  */
732
          cur = gfc_get_constructor ();
733
        }
734
      else
735
        {
736
          /* Remove it from the chain.  */
737
          if (last == NULL)
738
            c = cur->next;
739
          else
740
            last->next = cur->next;
741
          cur->next = NULL;
742
 
743
          formalize_init_expr (cur->expr);
744
        }
745
 
746
      /* Add it to the new constructor.  */
747
      if (head == NULL)
748
        head = tail = cur;
749
      else
750
        {
751
          tail->next = cur;
752
          tail = tail->next;
753
        }
754
    }
755
  gcc_assert (c == NULL);
756
  expr->value.constructor = head;
757
}
758
 
759
 
760
/* Make sure an initialization expression is in normalized form, i.e., all
761
   elements of the constructors are in the correct order.  */
762
 
763
static void
764
formalize_init_expr (gfc_expr *expr)
765
{
766
  expr_t type;
767
  gfc_constructor *c;
768
 
769
  if (expr == NULL)
770
    return;
771
 
772
  type = expr->expr_type;
773
  switch (type)
774
    {
775
    case EXPR_ARRAY:
776
      c = expr->value.constructor;
777
      while (c)
778
        {
779
          formalize_init_expr (c->expr);
780
          c = c->next;
781
        }
782
      break;
783
 
784
    case EXPR_STRUCTURE:
785
      formalize_structure_cons (expr);
786
      break;
787
 
788
    default:
789
      break;
790
    }
791
}
792
 
793
 
794
/* Resolve symbol's initial value after all data statement.  */
795
 
796
void
797
gfc_formalize_init_value (gfc_symbol *sym)
798
{
799
  formalize_init_expr (sym->value);
800
}
801
 
802
 
803
/* Get the integer value into RET_AS and SECTION from AS and AR, and return
804
   offset.  */
805
 
806
void
807
gfc_get_section_index (gfc_array_ref *ar, mpz_t *section_index, mpz_t *offset)
808
{
809
  int i;
810
  mpz_t delta;
811
  mpz_t tmp;
812
 
813
  mpz_set_si (*offset, 0);
814
  mpz_init (tmp);
815
  mpz_init_set_si (delta, 1);
816
  for (i = 0; i < ar->dimen; i++)
817
    {
818
      mpz_init (section_index[i]);
819
      switch (ar->dimen_type[i])
820
        {
821
        case DIMEN_ELEMENT:
822
        case DIMEN_RANGE:
823
          if (ar->start[i])
824
            {
825
              mpz_sub (tmp, ar->start[i]->value.integer,
826
                       ar->as->lower[i]->value.integer);
827
              mpz_mul (tmp, tmp, delta);
828
              mpz_add (*offset, tmp, *offset);
829
              mpz_set (section_index[i], ar->start[i]->value.integer);
830
            }
831
          else
832
              mpz_set (section_index[i], ar->as->lower[i]->value.integer);
833
          break;
834
 
835
        case DIMEN_VECTOR:
836
          gfc_internal_error ("TODO: Vector sections in data statements");
837
 
838
        default:
839
          gcc_unreachable ();
840
        }
841
 
842
      mpz_sub (tmp, ar->as->upper[i]->value.integer,
843
               ar->as->lower[i]->value.integer);
844
      mpz_add_ui (tmp, tmp, 1);
845
      mpz_mul (delta, tmp, delta);
846
    }
847
 
848
  mpz_clear (tmp);
849
  mpz_clear (delta);
850
}
851
 

powered by: WebSVN 2.1.0

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