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

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gcc/] [gcc-4.1.1/] [gcc/] [fortran/] [data.c] - Blame information for rev 12

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 12 jlechner
/* Supporting functions for resolving DATA statement.
2
   Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
3
   Contributed by Lifang Zeng <zlf605@hotmail.com>
4
 
5
This file is part of GCC.
6
 
7
GCC is free software; you can redistribute it and/or modify it under
8
the terms of the GNU General Public License as published by the Free
9
Software Foundation; either version 2, or (at your option) any later
10
version.
11
 
12
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13
WARRANTY; without even the implied warranty of MERCHANTABILITY or
14
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15
for more details.
16
 
17
You should have received a copy of the GNU General Public License
18
along with GCC; see the file COPYING.  If not, write to the Free
19
Software Foundation, 51 Franklin Street, Fifth Floor,Boston, MA
20
02110-1301, USA.  */
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 resolveing 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
 
39
static void formalize_init_expr (gfc_expr *);
40
 
41
/* Calculate the array element offset.  */
42
 
43
static void
44
get_array_index (gfc_array_ref * ar, mpz_t * offset)
45
{
46
  gfc_expr *e;
47
  int i;
48
  try re;
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
      re = 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
      mpz_set (tmp, e->value.integer);
65
      mpz_sub (tmp, tmp, ar->as->lower[i]->value.integer);
66
      mpz_mul (tmp, tmp, delta);
67
      mpz_add (*offset, tmp, *offset);
68
 
69
      mpz_sub (tmp, ar->as->upper[i]->value.integer,
70
      ar->as->lower[i]->value.integer);
71
      mpz_add_ui (tmp, tmp, 1);
72
      mpz_mul (delta, tmp, delta);
73
    }
74
  mpz_clear (delta);
75
  mpz_clear (tmp);
76
}
77
 
78
 
79
/* Find if there is a constructor which offset is equal to OFFSET.  */
80
 
81
static gfc_constructor *
82
find_con_by_offset (mpz_t offset, gfc_constructor *con)
83
{
84
  mpz_t tmp;
85
  gfc_constructor *ret = NULL;
86
 
87
  mpz_init (tmp);
88
 
89
  for (; con; con = con->next)
90
    {
91
      int cmp = mpz_cmp (offset, con->n.offset);
92
 
93
      /* We retain a sorted list, so if we're too large, we're done.  */
94
      if (cmp < 0)
95
        break;
96
 
97
      /* Yaye for exact matches.  */
98
      if (cmp == 0)
99
        {
100
          ret = con;
101
          break;
102
        }
103
 
104
      /* If the constructor element is a range, match any element.  */
105
      if (mpz_cmp_ui (con->repeat, 1) > 0)
106
        {
107
          mpz_add (tmp, con->n.offset, con->repeat);
108
          if (mpz_cmp (offset, tmp) < 0)
109
            {
110
              ret = con;
111
              break;
112
            }
113
        }
114
    }
115
 
116
  mpz_clear (tmp);
117
  return ret;
118
}
119
 
120
 
121
/* Find if there is a constructor which component is equal to COM.  */
122
 
123
static gfc_constructor *
124
find_con_by_component (gfc_component *com, gfc_constructor *con)
125
{
126
  for (; con; con = con->next)
127
    {
128
      if (com == con->n.component)
129
        return con;
130
    }
131
  return NULL;
132
}
133
 
134
 
135
/* Create a character type initialization expression from RVALUE.
136
   TS [and REF] describe [the substring of] the variable being initialized.
137
   INIT is thh existing initializer, not NULL.  Initialization is performed
138
   according to normal assignment rules.  */
139
 
140
static gfc_expr *
141
create_character_intializer (gfc_expr * init, gfc_typespec * ts,
142
                             gfc_ref * ref, gfc_expr * rvalue)
143
{
144
  int len;
145
  int start;
146
  int end;
147
  char *dest;
148
 
149
  gfc_extract_int (ts->cl->length, &len);
150
 
151
  if (init == NULL)
152
    {
153
      /* Create a new initializer.  */
154
      init = gfc_get_expr ();
155
      init->expr_type = EXPR_CONSTANT;
156
      init->ts = *ts;
157
 
158
      dest = gfc_getmem (len);
159
      init->value.character.length = len;
160
      init->value.character.string = dest;
161
      /* Blank the string if we're only setting a substring.  */
162
      if (ref != NULL)
163
        memset (dest, ' ', len);
164
    }
165
  else
166
    dest = init->value.character.string;
167
 
168
  if (ref)
169
    {
170
      gcc_assert (ref->type == REF_SUBSTRING);
171
 
172
      /* Only set a substring of the destination.  Fortran substring bounds
173
         are one-based [start, end], we want zero based [start, end).  */
174
      gfc_extract_int (ref->u.ss.start, &start);
175
      start--;
176
      gfc_extract_int (ref->u.ss.end, &end);
177
    }
178
  else
179
    {
180
      /* Set the whole string.  */
181
      start = 0;
182
      end = len;
183
    }
184
 
185
  /* Copy the initial value.  */
186
  len = rvalue->value.character.length;
187
  if (len > end - start)
188
    len = end - start;
189
  memcpy (&dest[start], rvalue->value.character.string, len);
190
 
191
  /* Pad with spaces.  Substrings will already be blanked.  */
192
  if (len < end - start && ref == NULL)
193
    memset (&dest[start + len], ' ', end - (start + len));
194
 
195
  return init;
196
}
197
 
198
/* Assign the initial value RVALUE to  LVALUE's symbol->value. If the
199
   LVALUE already has an initialization, we extend this, otherwise we
200
   create a new one.  */
201
 
202
void
203
gfc_assign_data_value (gfc_expr * lvalue, gfc_expr * rvalue, mpz_t index)
204
{
205
  gfc_ref *ref;
206
  gfc_expr *init;
207
  gfc_expr *expr;
208
  gfc_constructor *con;
209
  gfc_constructor *last_con;
210
  gfc_symbol *symbol;
211
  gfc_typespec *last_ts;
212
  mpz_t offset;
213
 
214
  symbol = lvalue->symtree->n.sym;
215
  init = symbol->value;
216
  last_ts = &symbol->ts;
217
  last_con = NULL;
218
  mpz_init_set_si (offset, 0);
219
 
220
  /* Find/create the parent expressions for subobject references.  */
221
  for (ref = lvalue->ref; ref; ref = ref->next)
222
    {
223
      /* Break out of the loop if we find a substring.  */
224
      if (ref->type == REF_SUBSTRING)
225
        {
226
          /* A substring should always br the last subobject reference.  */
227
          gcc_assert (ref->next == NULL);
228
          break;
229
        }
230
 
231
      /* Use the existing initializer expression if it exists.  Otherwise
232
         create a new one.  */
233
      if (init == NULL)
234
        expr = gfc_get_expr ();
235
      else
236
        expr = init;
237
 
238
      /* Find or create this element.  */
239
      switch (ref->type)
240
        {
241
        case REF_ARRAY:
242
          if (init == NULL)
243
            {
244
              /* The element typespec will be the same as the array
245
                 typespec.  */
246
              expr->ts = *last_ts;
247
              /* Setup the expression to hold the constructor.  */
248
              expr->expr_type = EXPR_ARRAY;
249
              expr->rank = ref->u.ar.as->rank;
250
            }
251
          else
252
            gcc_assert (expr->expr_type == EXPR_ARRAY);
253
 
254
          if (ref->u.ar.type == AR_ELEMENT)
255
            get_array_index (&ref->u.ar, &offset);
256
          else
257
            mpz_set (offset, index);
258
 
259
          /* Find the same element in the existing constructor.  */
260
          con = expr->value.constructor;
261
          con = find_con_by_offset (offset, con);
262
 
263
          if (con == NULL)
264
            {
265
              /* Create a new constructor.  */
266
              con = gfc_get_constructor ();
267
              mpz_set (con->n.offset, offset);
268
              gfc_insert_constructor (expr, con);
269
            }
270
          break;
271
 
272
        case REF_COMPONENT:
273
          if (init == NULL)
274
            {
275
              /* Setup the expression to hold the constructor.  */
276
              expr->expr_type = EXPR_STRUCTURE;
277
              expr->ts.type = BT_DERIVED;
278
              expr->ts.derived = ref->u.c.sym;
279
            }
280
          else
281
            gcc_assert (expr->expr_type == EXPR_STRUCTURE);
282
          last_ts = &ref->u.c.component->ts;
283
 
284
          /* Find the same element in the existing constructor.  */
285
          con = expr->value.constructor;
286
          con = find_con_by_component (ref->u.c.component, con);
287
 
288
          if (con == NULL)
289
            {
290
              /* Create a new constructor.  */
291
              con = gfc_get_constructor ();
292
              con->n.component = ref->u.c.component;
293
              con->next = expr->value.constructor;
294
              expr->value.constructor = con;
295
            }
296
          break;
297
 
298
        default:
299
          gcc_unreachable ();
300
        }
301
 
302
      if (init == NULL)
303
        {
304
          /* Point the container at the new expression.  */
305
          if (last_con == NULL)
306
            symbol->value = expr;
307
          else
308
            last_con->expr = expr;
309
        }
310
      init = con->expr;
311
      last_con = con;
312
    }
313
 
314
  if (ref || last_ts->type == BT_CHARACTER)
315
    expr = create_character_intializer (init, last_ts, ref, rvalue);
316
  else
317
    {
318
      /* Overwriting an existing initializer is non-standard but usually only
319
         provokes a warning from other compilers.  */
320
      if (init != NULL)
321
        {
322
          /* Order in which the expressions arrive here depends on whether they
323
             are from data statements or F95 style declarations. Therefore,
324
             check which is the most recent.  */
325
          expr = (init->where.lb->linenum > rvalue->where.lb->linenum) ?
326
                    init : rvalue;
327
          gfc_notify_std (GFC_STD_GNU, "Extension: re-initialization "
328
                          "of '%s' at %L",  symbol->name, &expr->where);
329
          return;
330
        }
331
 
332
      expr = gfc_copy_expr (rvalue);
333
      if (!gfc_compare_types (&lvalue->ts, &expr->ts))
334
        gfc_convert_type (expr, &lvalue->ts, 0);
335
    }
336
 
337
  if (last_con == NULL)
338
    symbol->value = expr;
339
  else
340
    last_con->expr = expr;
341
}
342
 
343
/* Similarly, but initialize REPEAT consecutive values in LVALUE the same
344
   value in RVALUE.  For the nonce, LVALUE must refer to a full array, not
345
   an array section.  */
346
 
347
void
348
gfc_assign_data_value_range (gfc_expr * lvalue, gfc_expr * rvalue,
349
                             mpz_t index, mpz_t repeat)
350
{
351
  gfc_ref *ref;
352
  gfc_expr *init, *expr;
353
  gfc_constructor *con, *last_con;
354
  gfc_symbol *symbol;
355
  gfc_typespec *last_ts;
356
  mpz_t offset;
357
 
358
  symbol = lvalue->symtree->n.sym;
359
  init = symbol->value;
360
  last_ts = &symbol->ts;
361
  last_con = NULL;
362
  mpz_init_set_si (offset, 0);
363
 
364
  /* Find/create the parent expressions for subobject references.  */
365
  for (ref = lvalue->ref; ref; ref = ref->next)
366
    {
367
      /* Use the existing initializer expression if it exists.
368
         Otherwise create a new one.  */
369
      if (init == NULL)
370
        expr = gfc_get_expr ();
371
      else
372
        expr = init;
373
 
374
      /* Find or create this element.  */
375
      switch (ref->type)
376
        {
377
        case REF_ARRAY:
378
          if (init == NULL)
379
            {
380
              /* The element typespec will be the same as the array
381
                 typespec.  */
382
              expr->ts = *last_ts;
383
              /* Setup the expression to hold the constructor.  */
384
              expr->expr_type = EXPR_ARRAY;
385
              expr->rank = ref->u.ar.as->rank;
386
            }
387
          else
388
            gcc_assert (expr->expr_type == EXPR_ARRAY);
389
 
390
          if (ref->u.ar.type == AR_ELEMENT)
391
            {
392
              get_array_index (&ref->u.ar, &offset);
393
 
394
              /* This had better not be the bottom of the reference.
395
                 We can still get to a full array via a component.  */
396
              gcc_assert (ref->next != NULL);
397
            }
398
          else
399
            {
400
              mpz_set (offset, index);
401
 
402
              /* We're at a full array or an array section.  This means
403
                 that we've better have found a full array, and that we're
404
                 at the bottom of the reference.  */
405
              gcc_assert (ref->u.ar.type == AR_FULL);
406
              gcc_assert (ref->next == NULL);
407
            }
408
 
409
          /* Find the same element in the existing constructor.  */
410
          con = expr->value.constructor;
411
          con = find_con_by_offset (offset, con);
412
 
413
          /* Create a new constructor.  */
414
          if (con == NULL)
415
            {
416
              con = gfc_get_constructor ();
417
              mpz_set (con->n.offset, offset);
418
              if (ref->next == NULL)
419
                mpz_set (con->repeat, repeat);
420
              gfc_insert_constructor (expr, con);
421
            }
422
          else
423
            gcc_assert (ref->next != NULL);
424
          break;
425
 
426
        case REF_COMPONENT:
427
          if (init == NULL)
428
            {
429
              /* Setup the expression to hold the constructor.  */
430
              expr->expr_type = EXPR_STRUCTURE;
431
              expr->ts.type = BT_DERIVED;
432
              expr->ts.derived = ref->u.c.sym;
433
            }
434
          else
435
            gcc_assert (expr->expr_type == EXPR_STRUCTURE);
436
          last_ts = &ref->u.c.component->ts;
437
 
438
          /* Find the same element in the existing constructor.  */
439
          con = expr->value.constructor;
440
          con = find_con_by_component (ref->u.c.component, con);
441
 
442
          if (con == NULL)
443
            {
444
              /* Create a new constructor.  */
445
              con = gfc_get_constructor ();
446
              con->n.component = ref->u.c.component;
447
              con->next = expr->value.constructor;
448
              expr->value.constructor = con;
449
            }
450
 
451
          /* Since we're only intending to initialize arrays here,
452
             there better be an inner reference.  */
453
          gcc_assert (ref->next != NULL);
454
          break;
455
 
456
        case REF_SUBSTRING:
457
        default:
458
          gcc_unreachable ();
459
        }
460
 
461
      if (init == NULL)
462
        {
463
          /* Point the container at the new expression.  */
464
          if (last_con == NULL)
465
            symbol->value = expr;
466
          else
467
            last_con->expr = expr;
468
        }
469
      init = con->expr;
470
      last_con = con;
471
    }
472
 
473
  if (last_ts->type == BT_CHARACTER)
474
    expr = create_character_intializer (init, last_ts, NULL, rvalue);
475
  else
476
    {
477
      /* We should never be overwriting an existing initializer.  */
478
      gcc_assert (!init);
479
 
480
      expr = gfc_copy_expr (rvalue);
481
      if (!gfc_compare_types (&lvalue->ts, &expr->ts))
482
        gfc_convert_type (expr, &lvalue->ts, 0);
483
    }
484
 
485
  if (last_con == NULL)
486
    symbol->value = expr;
487
  else
488
    last_con->expr = expr;
489
}
490
 
491
/* Modify the index of array section and re-calculate the array offset.  */
492
 
493
void
494
gfc_advance_section (mpz_t *section_index, gfc_array_ref *ar,
495
                     mpz_t *offset_ret)
496
{
497
  int i;
498
  mpz_t delta;
499
  mpz_t tmp;
500
  bool forwards;
501
  int cmp;
502
 
503
  for (i = 0; i < ar->dimen; i++)
504
    {
505
      if (ar->dimen_type[i] != DIMEN_RANGE)
506
        continue;
507
 
508
      if (ar->stride[i])
509
        {
510
          mpz_add (section_index[i], section_index[i],
511
                   ar->stride[i]->value.integer);
512
        if (mpz_cmp_si (ar->stride[i]->value.integer, 0) >= 0)
513
          forwards = true;
514
        else
515
          forwards = false;
516
        }
517
      else
518
        {
519
          mpz_add_ui (section_index[i], section_index[i], 1);
520
          forwards = true;
521
        }
522
 
523
      if (ar->end[i])
524
        cmp = mpz_cmp (section_index[i], ar->end[i]->value.integer);
525
      else
526
        cmp = mpz_cmp (section_index[i], ar->as->upper[i]->value.integer);
527
 
528
      if ((cmp > 0 && forwards)
529
          || (cmp < 0 && ! forwards))
530
        {
531
          /* Reset index to start, then loop to advance the next index.  */
532
          if (ar->start[i])
533
            mpz_set (section_index[i], ar->start[i]->value.integer);
534
          else
535
            mpz_set (section_index[i], ar->as->lower[i]->value.integer);
536
        }
537
      else
538
        break;
539
    }
540
 
541
  mpz_set_si (*offset_ret, 0);
542
  mpz_init_set_si (delta, 1);
543
  mpz_init (tmp);
544
  for (i = 0; i < ar->dimen; i++)
545
    {
546
      mpz_sub (tmp, section_index[i], ar->as->lower[i]->value.integer);
547
      mpz_mul (tmp, tmp, delta);
548
      mpz_add (*offset_ret, tmp, *offset_ret);
549
 
550
      mpz_sub (tmp, ar->as->upper[i]->value.integer,
551
               ar->as->lower[i]->value.integer);
552
      mpz_add_ui (tmp, tmp, 1);
553
      mpz_mul (delta, tmp, delta);
554
    }
555
  mpz_clear (tmp);
556
  mpz_clear (delta);
557
}
558
 
559
 
560
/* Rearrange a structure constructor so the elements are in the specified
561
   order.  Also insert NULL entries if necessary.  */
562
 
563
static void
564
formalize_structure_cons (gfc_expr * expr)
565
{
566
  gfc_constructor *head;
567
  gfc_constructor *tail;
568
  gfc_constructor *cur;
569
  gfc_constructor *last;
570
  gfc_constructor *c;
571
  gfc_component *order;
572
 
573
  c = expr->value.constructor;
574
 
575
  /* Constructor is already formalized.  */
576
  if (c->n.component == NULL)
577
    return;
578
 
579
  head = tail = NULL;
580
  for (order = expr->ts.derived->components; order; order = order->next)
581
    {
582
      /* Find the next component.  */
583
      last = NULL;
584
      cur = c;
585
      while (cur != NULL && cur->n.component != order)
586
        {
587
          last = cur;
588
          cur = cur->next;
589
        }
590
 
591
      if (cur == NULL)
592
        {
593
          /* Create a new one.  */
594
          cur = gfc_get_constructor ();
595
        }
596
      else
597
        {
598
          /* Remove it from the chain.  */
599
          if (last == NULL)
600
            c = cur->next;
601
          else
602
            last->next = cur->next;
603
          cur->next = NULL;
604
 
605
          formalize_init_expr (cur->expr);
606
        }
607
 
608
      /* Add it to the new constructor.  */
609
      if (head == NULL)
610
        head = tail = cur;
611
      else
612
        {
613
          tail->next = cur;
614
          tail = tail->next;
615
        }
616
    }
617
  gcc_assert (c == NULL);
618
  expr->value.constructor = head;
619
}
620
 
621
 
622
/* Make sure an initialization expression is in normalized form.  Ie. all
623
   elements of the constructors are in the correct order.  */
624
 
625
static void
626
formalize_init_expr (gfc_expr * expr)
627
{
628
  expr_t type;
629
  gfc_constructor *c;
630
 
631
  if (expr == NULL)
632
    return;
633
 
634
  type = expr->expr_type;
635
  switch (type)
636
    {
637
    case EXPR_ARRAY:
638
      c = expr->value.constructor;
639
      while (c)
640
        {
641
          formalize_init_expr (c->expr);
642
          c = c->next;
643
        }
644
      break;
645
 
646
    case EXPR_STRUCTURE:
647
      formalize_structure_cons (expr);
648
      break;
649
 
650
    default:
651
      break;
652
    }
653
}
654
 
655
 
656
/* Resolve symbol's initial value after all data statement.  */
657
 
658
void
659
gfc_formalize_init_value (gfc_symbol *sym)
660
{
661
  formalize_init_expr (sym->value);
662
}
663
 
664
 
665
/* Get the integer value into RET_AS and SECTION from AS and AR, and return
666
   offset.  */
667
 
668
void
669
gfc_get_section_index (gfc_array_ref *ar, mpz_t *section_index, mpz_t *offset)
670
{
671
  int i;
672
  mpz_t delta;
673
  mpz_t tmp;
674
 
675
  mpz_set_si (*offset, 0);
676
  mpz_init (tmp);
677
  mpz_init_set_si (delta, 1);
678
  for (i = 0; i < ar->dimen; i++)
679
    {
680
      mpz_init (section_index[i]);
681
      switch (ar->dimen_type[i])
682
        {
683
        case DIMEN_ELEMENT:
684
        case DIMEN_RANGE:
685
          if (ar->start[i])
686
            {
687
              mpz_sub (tmp, ar->start[i]->value.integer,
688
                       ar->as->lower[i]->value.integer);
689
              mpz_mul (tmp, tmp, delta);
690
              mpz_add (*offset, tmp, *offset);
691
              mpz_set (section_index[i], ar->start[i]->value.integer);
692
            }
693
          else
694
              mpz_set (section_index[i], ar->as->lower[i]->value.integer);
695
          break;
696
 
697
        case DIMEN_VECTOR:
698
          gfc_internal_error ("TODO: Vector sections in data statements");
699
 
700
        default:
701
          gcc_unreachable ();
702
        }
703
 
704
      mpz_sub (tmp, ar->as->upper[i]->value.integer,
705
               ar->as->lower[i]->value.integer);
706
      mpz_add_ui (tmp, tmp, 1);
707
      mpz_mul (delta, tmp, delta);
708
    }
709
 
710
  mpz_clear (tmp);
711
  mpz_clear (delta);
712
}
713
 

powered by: WebSVN 2.1.0

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