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

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gcc/] [gcc-4.1.1/] [gcc/] [fortran/] [trans-stmt.c] - Blame information for rev 20

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

Line No. Rev Author Line
1 12 jlechner
/* Statement translation -- generate GCC trees from gfc_code.
2
   Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
3
   Contributed by Paul Brook <paul@nowt.org>
4
   and Steven Bosscher <s.bosscher@student.tudelft.nl>
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 2, 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 COPYING.  If not, write to the Free
20
Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
21
02110-1301, USA.  */
22
 
23
 
24
#include "config.h"
25
#include "system.h"
26
#include "coretypes.h"
27
#include "tree.h"
28
#include "tree-gimple.h"
29
#include "ggc.h"
30
#include "toplev.h"
31
#include "real.h"
32
#include "gfortran.h"
33
#include "trans.h"
34
#include "trans-stmt.h"
35
#include "trans-types.h"
36
#include "trans-array.h"
37
#include "trans-const.h"
38
#include "arith.h"
39
 
40
typedef struct iter_info
41
{
42
  tree var;
43
  tree start;
44
  tree end;
45
  tree step;
46
  struct iter_info *next;
47
}
48
iter_info;
49
 
50
typedef  struct temporary_list
51
{
52
  tree temporary;
53
  struct temporary_list *next;
54
}
55
temporary_list;
56
 
57
typedef struct forall_info
58
{
59
  iter_info *this_loop;
60
  tree mask;
61
  tree pmask;
62
  tree maskindex;
63
  int nvar;
64
  tree size;
65
  struct forall_info  *outer;
66
  struct forall_info  *next_nest;
67
}
68
forall_info;
69
 
70
static void gfc_trans_where_2 (gfc_code *, tree, tree, forall_info *,
71
                               stmtblock_t *, temporary_list **temp);
72
 
73
/* Translate a F95 label number to a LABEL_EXPR.  */
74
 
75
tree
76
gfc_trans_label_here (gfc_code * code)
77
{
78
  return build1_v (LABEL_EXPR, gfc_get_label_decl (code->here));
79
}
80
 
81
 
82
/* Given a variable expression which has been ASSIGNed to, find the decl
83
   containing the auxiliary variables.  For variables in common blocks this
84
   is a field_decl.  */
85
 
86
void
87
gfc_conv_label_variable (gfc_se * se, gfc_expr * expr)
88
{
89
  gcc_assert (expr->symtree->n.sym->attr.assign == 1);
90
  gfc_conv_expr (se, expr);
91
  /* Deals with variable in common block. Get the field declaration.  */
92
  if (TREE_CODE (se->expr) == COMPONENT_REF)
93
    se->expr = TREE_OPERAND (se->expr, 1);
94
  /* Deals with dummy argument. Get the parameter declaration.  */
95
  else if (TREE_CODE (se->expr) == INDIRECT_REF)
96
    se->expr = TREE_OPERAND (se->expr, 0);
97
}
98
 
99
/* Translate a label assignment statement.  */
100
 
101
tree
102
gfc_trans_label_assign (gfc_code * code)
103
{
104
  tree label_tree;
105
  gfc_se se;
106
  tree len;
107
  tree addr;
108
  tree len_tree;
109
  char *label_str;
110
  int label_len;
111
 
112
  /* Start a new block.  */
113
  gfc_init_se (&se, NULL);
114
  gfc_start_block (&se.pre);
115
  gfc_conv_label_variable (&se, code->expr);
116
 
117
  len = GFC_DECL_STRING_LEN (se.expr);
118
  addr = GFC_DECL_ASSIGN_ADDR (se.expr);
119
 
120
  label_tree = gfc_get_label_decl (code->label);
121
 
122
  if (code->label->defined == ST_LABEL_TARGET)
123
    {
124
      label_tree = gfc_build_addr_expr (pvoid_type_node, label_tree);
125
      len_tree = integer_minus_one_node;
126
    }
127
  else
128
    {
129
      label_str = code->label->format->value.character.string;
130
      label_len = code->label->format->value.character.length;
131
      len_tree = build_int_cst (NULL_TREE, label_len);
132
      label_tree = gfc_build_string_const (label_len + 1, label_str);
133
      label_tree = gfc_build_addr_expr (pvoid_type_node, label_tree);
134
    }
135
 
136
  gfc_add_modify_expr (&se.pre, len, len_tree);
137
  gfc_add_modify_expr (&se.pre, addr, label_tree);
138
 
139
  return gfc_finish_block (&se.pre);
140
}
141
 
142
/* Translate a GOTO statement.  */
143
 
144
tree
145
gfc_trans_goto (gfc_code * code)
146
{
147
  tree assigned_goto;
148
  tree target;
149
  tree tmp;
150
  tree assign_error;
151
  tree range_error;
152
  gfc_se se;
153
 
154
 
155
  if (code->label != NULL)
156
    return build1_v (GOTO_EXPR, gfc_get_label_decl (code->label));
157
 
158
  /* ASSIGNED GOTO.  */
159
  gfc_init_se (&se, NULL);
160
  gfc_start_block (&se.pre);
161
  gfc_conv_label_variable (&se, code->expr);
162
  assign_error =
163
    gfc_build_cstring_const ("Assigned label is not a target label");
164
  tmp = GFC_DECL_STRING_LEN (se.expr);
165
  tmp = build2 (NE_EXPR, boolean_type_node, tmp, integer_minus_one_node);
166
  gfc_trans_runtime_check (tmp, assign_error, &se.pre);
167
 
168
  assigned_goto = GFC_DECL_ASSIGN_ADDR (se.expr);
169
 
170
  code = code->block;
171
  if (code == NULL)
172
    {
173
      target = build1 (GOTO_EXPR, void_type_node, assigned_goto);
174
      gfc_add_expr_to_block (&se.pre, target);
175
      return gfc_finish_block (&se.pre);
176
    }
177
 
178
  /* Check the label list.  */
179
  range_error = gfc_build_cstring_const ("Assigned label is not in the list");
180
 
181
  do
182
    {
183
      target = gfc_get_label_decl (code->label);
184
      tmp = gfc_build_addr_expr (pvoid_type_node, target);
185
      tmp = build2 (EQ_EXPR, boolean_type_node, tmp, assigned_goto);
186
      tmp = build3_v (COND_EXPR, tmp,
187
                      build1 (GOTO_EXPR, void_type_node, target),
188
                      build_empty_stmt ());
189
      gfc_add_expr_to_block (&se.pre, tmp);
190
      code = code->block;
191
    }
192
  while (code != NULL);
193
  gfc_trans_runtime_check (boolean_true_node, range_error, &se.pre);
194
  return gfc_finish_block (&se.pre);
195
}
196
 
197
 
198
/* Translate an ENTRY statement.  Just adds a label for this entry point.  */
199
tree
200
gfc_trans_entry (gfc_code * code)
201
{
202
  return build1_v (LABEL_EXPR, code->ext.entry->label);
203
}
204
 
205
 
206
/* Translate the CALL statement.  Builds a call to an F95 subroutine.  */
207
 
208
tree
209
gfc_trans_call (gfc_code * code)
210
{
211
  gfc_se se;
212
  gfc_ss * ss;
213
  int has_alternate_specifier;
214
 
215
  /* A CALL starts a new block because the actual arguments may have to
216
     be evaluated first.  */
217
  gfc_init_se (&se, NULL);
218
  gfc_start_block (&se.pre);
219
 
220
  gcc_assert (code->resolved_sym);
221
 
222
  ss = gfc_ss_terminator;
223
  if (code->resolved_sym->attr.elemental)
224
    ss = gfc_walk_elemental_function_args (ss, code->ext.actual, GFC_SS_REFERENCE);
225
 
226
  /* Is not an elemental subroutine call with array valued arguments.  */
227
  if (ss == gfc_ss_terminator)
228
    {
229
 
230
      /* Translate the call.  */
231
      has_alternate_specifier
232
        = gfc_conv_function_call (&se, code->resolved_sym, code->ext.actual);
233
 
234
      /* A subroutine without side-effect, by definition, does nothing!  */
235
      TREE_SIDE_EFFECTS (se.expr) = 1;
236
 
237
      /* Chain the pieces together and return the block.  */
238
      if (has_alternate_specifier)
239
        {
240
          gfc_code *select_code;
241
          gfc_symbol *sym;
242
          select_code = code->next;
243
          gcc_assert(select_code->op == EXEC_SELECT);
244
          sym = select_code->expr->symtree->n.sym;
245
          se.expr = convert (gfc_typenode_for_spec (&sym->ts), se.expr);
246
          gfc_add_modify_expr (&se.pre, sym->backend_decl, se.expr);
247
        }
248
      else
249
        gfc_add_expr_to_block (&se.pre, se.expr);
250
 
251
      gfc_add_block_to_block (&se.pre, &se.post);
252
    }
253
 
254
  else
255
    {
256
      /* An elemental subroutine call with array valued arguments has
257
         to be scalarized.  */
258
      gfc_loopinfo loop;
259
      stmtblock_t body;
260
      stmtblock_t block;
261
      gfc_se loopse;
262
 
263
      /* gfc_walk_elemental_function_args renders the ss chain in the
264
         reverse order to the actual argument order.  */
265
      ss = gfc_reverse_ss (ss);
266
 
267
      /* Initialize the loop.  */
268
      gfc_init_se (&loopse, NULL);
269
      gfc_init_loopinfo (&loop);
270
      gfc_add_ss_to_loop (&loop, ss);
271
 
272
      gfc_conv_ss_startstride (&loop);
273
      gfc_conv_loop_setup (&loop);
274
      gfc_mark_ss_chain_used (ss, 1);
275
 
276
      /* Generate the loop body.  */
277
      gfc_start_scalarized_body (&loop, &body);
278
      gfc_init_block (&block);
279
      gfc_copy_loopinfo_to_se (&loopse, &loop);
280
      loopse.ss = ss;
281
 
282
      /* Add the subroutine call to the block.  */
283
      gfc_conv_function_call (&loopse, code->resolved_sym, code->ext.actual);
284
      gfc_add_expr_to_block (&loopse.pre, loopse.expr);
285
 
286
      gfc_add_block_to_block (&block, &loopse.pre);
287
      gfc_add_block_to_block (&block, &loopse.post);
288
 
289
      /* Finish up the loop block and the loop.  */
290
      gfc_add_expr_to_block (&body, gfc_finish_block (&block));
291
      gfc_trans_scalarizing_loops (&loop, &body);
292
      gfc_add_block_to_block (&se.pre, &loop.pre);
293
      gfc_add_block_to_block (&se.pre, &loop.post);
294
      gfc_cleanup_loop (&loop);
295
    }
296
 
297
  return gfc_finish_block (&se.pre);
298
}
299
 
300
 
301
/* Translate the RETURN statement.  */
302
 
303
tree
304
gfc_trans_return (gfc_code * code ATTRIBUTE_UNUSED)
305
{
306
  if (code->expr)
307
    {
308
      gfc_se se;
309
      tree tmp;
310
      tree result;
311
 
312
      /* if code->expr is not NULL, this return statement must appear
313
         in a subroutine and current_fake_result_decl has already
314
         been generated.  */
315
 
316
      result = gfc_get_fake_result_decl (NULL);
317
      if (!result)
318
        {
319
          gfc_warning ("An alternate return at %L without a * dummy argument",
320
                        &code->expr->where);
321
          return build1_v (GOTO_EXPR, gfc_get_return_label ());
322
        }
323
 
324
      /* Start a new block for this statement.  */
325
      gfc_init_se (&se, NULL);
326
      gfc_start_block (&se.pre);
327
 
328
      gfc_conv_expr (&se, code->expr);
329
 
330
      tmp = build2 (MODIFY_EXPR, TREE_TYPE (result), result, se.expr);
331
      gfc_add_expr_to_block (&se.pre, tmp);
332
 
333
      tmp = build1_v (GOTO_EXPR, gfc_get_return_label ());
334
      gfc_add_expr_to_block (&se.pre, tmp);
335
      gfc_add_block_to_block (&se.pre, &se.post);
336
      return gfc_finish_block (&se.pre);
337
    }
338
  else
339
    return build1_v (GOTO_EXPR, gfc_get_return_label ());
340
}
341
 
342
 
343
/* Translate the PAUSE statement.  We have to translate this statement
344
   to a runtime library call.  */
345
 
346
tree
347
gfc_trans_pause (gfc_code * code)
348
{
349
  tree gfc_int4_type_node = gfc_get_int_type (4);
350
  gfc_se se;
351
  tree args;
352
  tree tmp;
353
  tree fndecl;
354
 
355
  /* Start a new block for this statement.  */
356
  gfc_init_se (&se, NULL);
357
  gfc_start_block (&se.pre);
358
 
359
 
360
  if (code->expr == NULL)
361
    {
362
      tmp = build_int_cst (gfc_int4_type_node, code->ext.stop_code);
363
      args = gfc_chainon_list (NULL_TREE, tmp);
364
      fndecl = gfor_fndecl_pause_numeric;
365
    }
366
  else
367
    {
368
      gfc_conv_expr_reference (&se, code->expr);
369
      args = gfc_chainon_list (NULL_TREE, se.expr);
370
      args = gfc_chainon_list (args, se.string_length);
371
      fndecl = gfor_fndecl_pause_string;
372
    }
373
 
374
  tmp = gfc_build_function_call (fndecl, args);
375
  gfc_add_expr_to_block (&se.pre, tmp);
376
 
377
  gfc_add_block_to_block (&se.pre, &se.post);
378
 
379
  return gfc_finish_block (&se.pre);
380
}
381
 
382
 
383
/* Translate the STOP statement.  We have to translate this statement
384
   to a runtime library call.  */
385
 
386
tree
387
gfc_trans_stop (gfc_code * code)
388
{
389
  tree gfc_int4_type_node = gfc_get_int_type (4);
390
  gfc_se se;
391
  tree args;
392
  tree tmp;
393
  tree fndecl;
394
 
395
  /* Start a new block for this statement.  */
396
  gfc_init_se (&se, NULL);
397
  gfc_start_block (&se.pre);
398
 
399
 
400
  if (code->expr == NULL)
401
    {
402
      tmp = build_int_cst (gfc_int4_type_node, code->ext.stop_code);
403
      args = gfc_chainon_list (NULL_TREE, tmp);
404
      fndecl = gfor_fndecl_stop_numeric;
405
    }
406
  else
407
    {
408
      gfc_conv_expr_reference (&se, code->expr);
409
      args = gfc_chainon_list (NULL_TREE, se.expr);
410
      args = gfc_chainon_list (args, se.string_length);
411
      fndecl = gfor_fndecl_stop_string;
412
    }
413
 
414
  tmp = gfc_build_function_call (fndecl, args);
415
  gfc_add_expr_to_block (&se.pre, tmp);
416
 
417
  gfc_add_block_to_block (&se.pre, &se.post);
418
 
419
  return gfc_finish_block (&se.pre);
420
}
421
 
422
 
423
/* Generate GENERIC for the IF construct. This function also deals with
424
   the simple IF statement, because the front end translates the IF
425
   statement into an IF construct.
426
 
427
   We translate:
428
 
429
        IF (cond) THEN
430
           then_clause
431
        ELSEIF (cond2)
432
           elseif_clause
433
        ELSE
434
           else_clause
435
        ENDIF
436
 
437
   into:
438
 
439
        pre_cond_s;
440
        if (cond_s)
441
          {
442
            then_clause;
443
          }
444
        else
445
          {
446
            pre_cond_s
447
            if (cond_s)
448
              {
449
                elseif_clause
450
              }
451
            else
452
              {
453
                else_clause;
454
              }
455
          }
456
 
457
   where COND_S is the simplified version of the predicate. PRE_COND_S
458
   are the pre side-effects produced by the translation of the
459
   conditional.
460
   We need to build the chain recursively otherwise we run into
461
   problems with folding incomplete statements.  */
462
 
463
static tree
464
gfc_trans_if_1 (gfc_code * code)
465
{
466
  gfc_se if_se;
467
  tree stmt, elsestmt;
468
 
469
  /* Check for an unconditional ELSE clause.  */
470
  if (!code->expr)
471
    return gfc_trans_code (code->next);
472
 
473
  /* Initialize a statement builder for each block. Puts in NULL_TREEs.  */
474
  gfc_init_se (&if_se, NULL);
475
  gfc_start_block (&if_se.pre);
476
 
477
  /* Calculate the IF condition expression.  */
478
  gfc_conv_expr_val (&if_se, code->expr);
479
 
480
  /* Translate the THEN clause.  */
481
  stmt = gfc_trans_code (code->next);
482
 
483
  /* Translate the ELSE clause.  */
484
  if (code->block)
485
    elsestmt = gfc_trans_if_1 (code->block);
486
  else
487
    elsestmt = build_empty_stmt ();
488
 
489
  /* Build the condition expression and add it to the condition block.  */
490
  stmt = build3_v (COND_EXPR, if_se.expr, stmt, elsestmt);
491
 
492
  gfc_add_expr_to_block (&if_se.pre, stmt);
493
 
494
  /* Finish off this statement.  */
495
  return gfc_finish_block (&if_se.pre);
496
}
497
 
498
tree
499
gfc_trans_if (gfc_code * code)
500
{
501
  /* Ignore the top EXEC_IF, it only announces an IF construct. The
502
     actual code we must translate is in code->block.  */
503
 
504
  return gfc_trans_if_1 (code->block);
505
}
506
 
507
 
508
/* Translage an arithmetic IF expression.
509
 
510
   IF (cond) label1, label2, label3 translates to
511
 
512
    if (cond <= 0)
513
      {
514
        if (cond < 0)
515
          goto label1;
516
        else // cond == 0
517
          goto label2;
518
      }
519
    else // cond > 0
520
      goto label3;
521
 
522
   An optimized version can be generated in case of equal labels.
523
   E.g., if label1 is equal to label2, we can translate it to
524
 
525
    if (cond <= 0)
526
      goto label1;
527
    else
528
      goto label3;
529
*/
530
 
531
tree
532
gfc_trans_arithmetic_if (gfc_code * code)
533
{
534
  gfc_se se;
535
  tree tmp;
536
  tree branch1;
537
  tree branch2;
538
  tree zero;
539
 
540
  /* Start a new block.  */
541
  gfc_init_se (&se, NULL);
542
  gfc_start_block (&se.pre);
543
 
544
  /* Pre-evaluate COND.  */
545
  gfc_conv_expr_val (&se, code->expr);
546
 
547
  /* Build something to compare with.  */
548
  zero = gfc_build_const (TREE_TYPE (se.expr), integer_zero_node);
549
 
550
  if (code->label->value != code->label2->value)
551
    {
552
      /* If (cond < 0) take branch1 else take branch2.
553
         First build jumps to the COND .LT. 0 and the COND .EQ. 0 cases.  */
554
      branch1 = build1_v (GOTO_EXPR, gfc_get_label_decl (code->label));
555
      branch2 = build1_v (GOTO_EXPR, gfc_get_label_decl (code->label2));
556
 
557
      if (code->label->value != code->label3->value)
558
        tmp = build2 (LT_EXPR, boolean_type_node, se.expr, zero);
559
      else
560
        tmp = build2 (NE_EXPR, boolean_type_node, se.expr, zero);
561
 
562
      branch1 = build3_v (COND_EXPR, tmp, branch1, branch2);
563
    }
564
  else
565
    branch1 = build1_v (GOTO_EXPR, gfc_get_label_decl (code->label));
566
 
567
  if (code->label->value != code->label3->value
568
      && code->label2->value != code->label3->value)
569
    {
570
      /* if (cond <= 0) take branch1 else take branch2.  */
571
      branch2 = build1_v (GOTO_EXPR, gfc_get_label_decl (code->label3));
572
      tmp = build2 (LE_EXPR, boolean_type_node, se.expr, zero);
573
      branch1 = build3_v (COND_EXPR, tmp, branch1, branch2);
574
    }
575
 
576
  /* Append the COND_EXPR to the evaluation of COND, and return.  */
577
  gfc_add_expr_to_block (&se.pre, branch1);
578
  return gfc_finish_block (&se.pre);
579
}
580
 
581
 
582
/* Translate the simple DO construct.  This is where the loop variable has
583
   integer type and step +-1.  We can't use this in the general case
584
   because integer overflow and floating point errors could give incorrect
585
   results.
586
   We translate a do loop from:
587
 
588
   DO dovar = from, to, step
589
      body
590
   END DO
591
 
592
   to:
593
 
594
   [Evaluate loop bounds and step]
595
   dovar = from;
596
   if ((step > 0) ? (dovar <= to) : (dovar => to))
597
    {
598
      for (;;)
599
        {
600
          body;
601
   cycle_label:
602
          cond = (dovar == to);
603
          dovar += step;
604
          if (cond) goto end_label;
605
        }
606
      }
607
   end_label:
608
 
609
   This helps the optimizers by avoiding the extra induction variable
610
   used in the general case.  */
611
 
612
static tree
613
gfc_trans_simple_do (gfc_code * code, stmtblock_t *pblock, tree dovar,
614
                     tree from, tree to, tree step)
615
{
616
  stmtblock_t body;
617
  tree type;
618
  tree cond;
619
  tree tmp;
620
  tree cycle_label;
621
  tree exit_label;
622
 
623
  type = TREE_TYPE (dovar);
624
 
625
  /* Initialize the DO variable: dovar = from.  */
626
  gfc_add_modify_expr (pblock, dovar, from);
627
 
628
  /* Cycle and exit statements are implemented with gotos.  */
629
  cycle_label = gfc_build_label_decl (NULL_TREE);
630
  exit_label = gfc_build_label_decl (NULL_TREE);
631
 
632
  /* Put the labels where they can be found later. See gfc_trans_do().  */
633
  code->block->backend_decl = tree_cons (cycle_label, exit_label, NULL);
634
 
635
  /* Loop body.  */
636
  gfc_start_block (&body);
637
 
638
  /* Main loop body.  */
639
  tmp = gfc_trans_code (code->block->next);
640
  gfc_add_expr_to_block (&body, tmp);
641
 
642
  /* Label for cycle statements (if needed).  */
643
  if (TREE_USED (cycle_label))
644
    {
645
      tmp = build1_v (LABEL_EXPR, cycle_label);
646
      gfc_add_expr_to_block (&body, tmp);
647
    }
648
 
649
  /* Evaluate the loop condition.  */
650
  cond = build2 (EQ_EXPR, boolean_type_node, dovar, to);
651
  cond = gfc_evaluate_now (cond, &body);
652
 
653
  /* Increment the loop variable.  */
654
  tmp = build2 (PLUS_EXPR, type, dovar, step);
655
  gfc_add_modify_expr (&body, dovar, tmp);
656
 
657
  /* The loop exit.  */
658
  tmp = build1_v (GOTO_EXPR, exit_label);
659
  TREE_USED (exit_label) = 1;
660
  tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt ());
661
  gfc_add_expr_to_block (&body, tmp);
662
 
663
  /* Finish the loop body.  */
664
  tmp = gfc_finish_block (&body);
665
  tmp = build1_v (LOOP_EXPR, tmp);
666
 
667
  /* Only execute the loop if the number of iterations is positive.  */
668
  if (tree_int_cst_sgn (step) > 0)
669
    cond = fold_build2 (LE_EXPR, boolean_type_node, dovar, to);
670
  else
671
    cond = fold_build2 (GE_EXPR, boolean_type_node, dovar, to);
672
  tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt ());
673
  gfc_add_expr_to_block (pblock, tmp);
674
 
675
  /* Add the exit label.  */
676
  tmp = build1_v (LABEL_EXPR, exit_label);
677
  gfc_add_expr_to_block (pblock, tmp);
678
 
679
  return gfc_finish_block (pblock);
680
}
681
 
682
/* Translate the DO construct.  This obviously is one of the most
683
   important ones to get right with any compiler, but especially
684
   so for Fortran.
685
 
686
   We special case some loop forms as described in gfc_trans_simple_do.
687
   For other cases we implement them with a separate loop count,
688
   as described in the standard.
689
 
690
   We translate a do loop from:
691
 
692
   DO dovar = from, to, step
693
      body
694
   END DO
695
 
696
   to:
697
 
698
   [evaluate loop bounds and step]
699
   count = to + step - from;
700
   dovar = from;
701
   for (;;)
702
     {
703
       body;
704
cycle_label:
705
       dovar += step
706
       count--;
707
       if (count <=0) goto exit_label;
708
     }
709
exit_label:
710
 
711
   TODO: Large loop counts
712
   The code above assumes the loop count fits into a signed integer kind,
713
   i.e. Does not work for loop counts > 2^31 for integer(kind=4) variables
714
   We must support the full range.  */
715
 
716
tree
717
gfc_trans_do (gfc_code * code)
718
{
719
  gfc_se se;
720
  tree dovar;
721
  tree from;
722
  tree to;
723
  tree step;
724
  tree count;
725
  tree count_one;
726
  tree type;
727
  tree cond;
728
  tree cycle_label;
729
  tree exit_label;
730
  tree tmp;
731
  stmtblock_t block;
732
  stmtblock_t body;
733
 
734
  gfc_start_block (&block);
735
 
736
  /* Evaluate all the expressions in the iterator.  */
737
  gfc_init_se (&se, NULL);
738
  gfc_conv_expr_lhs (&se, code->ext.iterator->var);
739
  gfc_add_block_to_block (&block, &se.pre);
740
  dovar = se.expr;
741
  type = TREE_TYPE (dovar);
742
 
743
  gfc_init_se (&se, NULL);
744
  gfc_conv_expr_val (&se, code->ext.iterator->start);
745
  gfc_add_block_to_block (&block, &se.pre);
746
  from = gfc_evaluate_now (se.expr, &block);
747
 
748
  gfc_init_se (&se, NULL);
749
  gfc_conv_expr_val (&se, code->ext.iterator->end);
750
  gfc_add_block_to_block (&block, &se.pre);
751
  to = gfc_evaluate_now (se.expr, &block);
752
 
753
  gfc_init_se (&se, NULL);
754
  gfc_conv_expr_val (&se, code->ext.iterator->step);
755
  gfc_add_block_to_block (&block, &se.pre);
756
  step = gfc_evaluate_now (se.expr, &block);
757
 
758
  /* Special case simple loops.  */
759
  if (TREE_CODE (type) == INTEGER_TYPE
760
      && (integer_onep (step)
761
        || tree_int_cst_equal (step, integer_minus_one_node)))
762
    return gfc_trans_simple_do (code, &block, dovar, from, to, step);
763
 
764
  /* Initialize loop count. This code is executed before we enter the
765
     loop body. We generate: count = (to + step - from) / step.  */
766
 
767
  tmp = fold_build2 (MINUS_EXPR, type, step, from);
768
  tmp = fold_build2 (PLUS_EXPR, type, to, tmp);
769
  if (TREE_CODE (type) == INTEGER_TYPE)
770
    {
771
      tmp = fold_build2 (TRUNC_DIV_EXPR, type, tmp, step);
772
      count = gfc_create_var (type, "count");
773
    }
774
  else
775
    {
776
      /* TODO: We could use the same width as the real type.
777
         This would probably cause more problems that it solves
778
         when we implement "long double" types.  */
779
      tmp = fold_build2 (RDIV_EXPR, type, tmp, step);
780
      tmp = fold_build1 (FIX_TRUNC_EXPR, gfc_array_index_type, tmp);
781
      count = gfc_create_var (gfc_array_index_type, "count");
782
    }
783
  gfc_add_modify_expr (&block, count, tmp);
784
 
785
  count_one = convert (TREE_TYPE (count), integer_one_node);
786
 
787
  /* Initialize the DO variable: dovar = from.  */
788
  gfc_add_modify_expr (&block, dovar, from);
789
 
790
  /* Loop body.  */
791
  gfc_start_block (&body);
792
 
793
  /* Cycle and exit statements are implemented with gotos.  */
794
  cycle_label = gfc_build_label_decl (NULL_TREE);
795
  exit_label = gfc_build_label_decl (NULL_TREE);
796
 
797
  /* Start with the loop condition.  Loop until count <= 0.  */
798
  cond = build2 (LE_EXPR, boolean_type_node, count,
799
                convert (TREE_TYPE (count), integer_zero_node));
800
  tmp = build1_v (GOTO_EXPR, exit_label);
801
  TREE_USED (exit_label) = 1;
802
  tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt ());
803
  gfc_add_expr_to_block (&body, tmp);
804
 
805
  /* Put these labels where they can be found later. We put the
806
     labels in a TREE_LIST node (because TREE_CHAIN is already
807
     used). cycle_label goes in TREE_PURPOSE (backend_decl), exit
808
     label in TREE_VALUE (backend_decl).  */
809
 
810
  code->block->backend_decl = tree_cons (cycle_label, exit_label, NULL);
811
 
812
  /* Main loop body.  */
813
  tmp = gfc_trans_code (code->block->next);
814
  gfc_add_expr_to_block (&body, tmp);
815
 
816
  /* Label for cycle statements (if needed).  */
817
  if (TREE_USED (cycle_label))
818
    {
819
      tmp = build1_v (LABEL_EXPR, cycle_label);
820
      gfc_add_expr_to_block (&body, tmp);
821
    }
822
 
823
  /* Increment the loop variable.  */
824
  tmp = build2 (PLUS_EXPR, type, dovar, step);
825
  gfc_add_modify_expr (&body, dovar, tmp);
826
 
827
  /* Decrement the loop count.  */
828
  tmp = build2 (MINUS_EXPR, TREE_TYPE (count), count, count_one);
829
  gfc_add_modify_expr (&body, count, tmp);
830
 
831
  /* End of loop body.  */
832
  tmp = gfc_finish_block (&body);
833
 
834
  /* The for loop itself.  */
835
  tmp = build1_v (LOOP_EXPR, tmp);
836
  gfc_add_expr_to_block (&block, tmp);
837
 
838
  /* Add the exit label.  */
839
  tmp = build1_v (LABEL_EXPR, exit_label);
840
  gfc_add_expr_to_block (&block, tmp);
841
 
842
  return gfc_finish_block (&block);
843
}
844
 
845
 
846
/* Translate the DO WHILE construct.
847
 
848
   We translate
849
 
850
   DO WHILE (cond)
851
      body
852
   END DO
853
 
854
   to:
855
 
856
   for ( ; ; )
857
     {
858
       pre_cond;
859
       if (! cond) goto exit_label;
860
       body;
861
cycle_label:
862
     }
863
exit_label:
864
 
865
   Because the evaluation of the exit condition `cond' may have side
866
   effects, we can't do much for empty loop bodies.  The backend optimizers
867
   should be smart enough to eliminate any dead loops.  */
868
 
869
tree
870
gfc_trans_do_while (gfc_code * code)
871
{
872
  gfc_se cond;
873
  tree tmp;
874
  tree cycle_label;
875
  tree exit_label;
876
  stmtblock_t block;
877
 
878
  /* Everything we build here is part of the loop body.  */
879
  gfc_start_block (&block);
880
 
881
  /* Cycle and exit statements are implemented with gotos.  */
882
  cycle_label = gfc_build_label_decl (NULL_TREE);
883
  exit_label = gfc_build_label_decl (NULL_TREE);
884
 
885
  /* Put the labels where they can be found later. See gfc_trans_do().  */
886
  code->block->backend_decl = tree_cons (cycle_label, exit_label, NULL);
887
 
888
  /* Create a GIMPLE version of the exit condition.  */
889
  gfc_init_se (&cond, NULL);
890
  gfc_conv_expr_val (&cond, code->expr);
891
  gfc_add_block_to_block (&block, &cond.pre);
892
  cond.expr = fold_build1 (TRUTH_NOT_EXPR, boolean_type_node, cond.expr);
893
 
894
  /* Build "IF (! cond) GOTO exit_label".  */
895
  tmp = build1_v (GOTO_EXPR, exit_label);
896
  TREE_USED (exit_label) = 1;
897
  tmp = build3_v (COND_EXPR, cond.expr, tmp, build_empty_stmt ());
898
  gfc_add_expr_to_block (&block, tmp);
899
 
900
  /* The main body of the loop.  */
901
  tmp = gfc_trans_code (code->block->next);
902
  gfc_add_expr_to_block (&block, tmp);
903
 
904
  /* Label for cycle statements (if needed).  */
905
  if (TREE_USED (cycle_label))
906
    {
907
      tmp = build1_v (LABEL_EXPR, cycle_label);
908
      gfc_add_expr_to_block (&block, tmp);
909
    }
910
 
911
  /* End of loop body.  */
912
  tmp = gfc_finish_block (&block);
913
 
914
  gfc_init_block (&block);
915
  /* Build the loop.  */
916
  tmp = build1_v (LOOP_EXPR, tmp);
917
  gfc_add_expr_to_block (&block, tmp);
918
 
919
  /* Add the exit label.  */
920
  tmp = build1_v (LABEL_EXPR, exit_label);
921
  gfc_add_expr_to_block (&block, tmp);
922
 
923
  return gfc_finish_block (&block);
924
}
925
 
926
 
927
/* Translate the SELECT CASE construct for INTEGER case expressions,
928
   without killing all potential optimizations.  The problem is that
929
   Fortran allows unbounded cases, but the back-end does not, so we
930
   need to intercept those before we enter the equivalent SWITCH_EXPR
931
   we can build.
932
 
933
   For example, we translate this,
934
 
935
   SELECT CASE (expr)
936
      CASE (:100,101,105:115)
937
         block_1
938
      CASE (190:199,200:)
939
         block_2
940
      CASE (300)
941
         block_3
942
      CASE DEFAULT
943
         block_4
944
   END SELECT
945
 
946
   to the GENERIC equivalent,
947
 
948
     switch (expr)
949
       {
950
         case (minimum value for typeof(expr) ... 100:
951
         case 101:
952
         case 105 ... 114:
953
           block1:
954
           goto end_label;
955
 
956
         case 200 ... (maximum value for typeof(expr):
957
         case 190 ... 199:
958
           block2;
959
           goto end_label;
960
 
961
         case 300:
962
           block_3;
963
           goto end_label;
964
 
965
         default:
966
           block_4;
967
           goto end_label;
968
       }
969
 
970
     end_label:  */
971
 
972
static tree
973
gfc_trans_integer_select (gfc_code * code)
974
{
975
  gfc_code *c;
976
  gfc_case *cp;
977
  tree end_label;
978
  tree tmp;
979
  gfc_se se;
980
  stmtblock_t block;
981
  stmtblock_t body;
982
 
983
  gfc_start_block (&block);
984
 
985
  /* Calculate the switch expression.  */
986
  gfc_init_se (&se, NULL);
987
  gfc_conv_expr_val (&se, code->expr);
988
  gfc_add_block_to_block (&block, &se.pre);
989
 
990
  end_label = gfc_build_label_decl (NULL_TREE);
991
 
992
  gfc_init_block (&body);
993
 
994
  for (c = code->block; c; c = c->block)
995
    {
996
      for (cp = c->ext.case_list; cp; cp = cp->next)
997
        {
998
          tree low, high;
999
          tree label;
1000
 
1001
          /* Assume it's the default case.  */
1002
          low = high = NULL_TREE;
1003
 
1004
          if (cp->low)
1005
            {
1006
              low = gfc_conv_constant_to_tree (cp->low);
1007
 
1008
              /* If there's only a lower bound, set the high bound to the
1009
                 maximum value of the case expression.  */
1010
              if (!cp->high)
1011
                high = TYPE_MAX_VALUE (TREE_TYPE (se.expr));
1012
            }
1013
 
1014
          if (cp->high)
1015
            {
1016
              /* Three cases are possible here:
1017
 
1018
                 1) There is no lower bound, e.g. CASE (:N).
1019
                 2) There is a lower bound .NE. high bound, that is
1020
                    a case range, e.g. CASE (N:M) where M>N (we make
1021
                    sure that M>N during type resolution).
1022
                 3) There is a lower bound, and it has the same value
1023
                    as the high bound, e.g. CASE (N:N).  This is our
1024
                    internal representation of CASE(N).
1025
 
1026
                 In the first and second case, we need to set a value for
1027
                 high.  In the thirth case, we don't because the GCC middle
1028
                 end represents a single case value by just letting high be
1029
                 a NULL_TREE.  We can't do that because we need to be able
1030
                 to represent unbounded cases.  */
1031
 
1032
              if (!cp->low
1033
                  || (cp->low
1034
                      && mpz_cmp (cp->low->value.integer,
1035
                                  cp->high->value.integer) != 0))
1036
                high = gfc_conv_constant_to_tree (cp->high);
1037
 
1038
              /* Unbounded case.  */
1039
              if (!cp->low)
1040
                low = TYPE_MIN_VALUE (TREE_TYPE (se.expr));
1041
            }
1042
 
1043
          /* Build a label.  */
1044
          label = gfc_build_label_decl (NULL_TREE);
1045
 
1046
          /* Add this case label.
1047
             Add parameter 'label', make it match GCC backend.  */
1048
          tmp = build3 (CASE_LABEL_EXPR, void_type_node, low, high, label);
1049
          gfc_add_expr_to_block (&body, tmp);
1050
        }
1051
 
1052
      /* Add the statements for this case.  */
1053
      tmp = gfc_trans_code (c->next);
1054
      gfc_add_expr_to_block (&body, tmp);
1055
 
1056
      /* Break to the end of the construct.  */
1057
      tmp = build1_v (GOTO_EXPR, end_label);
1058
      gfc_add_expr_to_block (&body, tmp);
1059
    }
1060
 
1061
  tmp = gfc_finish_block (&body);
1062
  tmp = build3_v (SWITCH_EXPR, se.expr, tmp, NULL_TREE);
1063
  gfc_add_expr_to_block (&block, tmp);
1064
 
1065
  tmp = build1_v (LABEL_EXPR, end_label);
1066
  gfc_add_expr_to_block (&block, tmp);
1067
 
1068
  return gfc_finish_block (&block);
1069
}
1070
 
1071
 
1072
/* Translate the SELECT CASE construct for LOGICAL case expressions.
1073
 
1074
   There are only two cases possible here, even though the standard
1075
   does allow three cases in a LOGICAL SELECT CASE construct: .TRUE.,
1076
   .FALSE., and DEFAULT.
1077
 
1078
   We never generate more than two blocks here.  Instead, we always
1079
   try to eliminate the DEFAULT case.  This way, we can translate this
1080
   kind of SELECT construct to a simple
1081
 
1082
   if {} else {};
1083
 
1084
   expression in GENERIC.  */
1085
 
1086
static tree
1087
gfc_trans_logical_select (gfc_code * code)
1088
{
1089
  gfc_code *c;
1090
  gfc_code *t, *f, *d;
1091
  gfc_case *cp;
1092
  gfc_se se;
1093
  stmtblock_t block;
1094
 
1095
  /* Assume we don't have any cases at all.  */
1096
  t = f = d = NULL;
1097
 
1098
  /* Now see which ones we actually do have.  We can have at most two
1099
     cases in a single case list: one for .TRUE. and one for .FALSE.
1100
     The default case is always separate.  If the cases for .TRUE. and
1101
     .FALSE. are in the same case list, the block for that case list
1102
     always executed, and we don't generate code a COND_EXPR.  */
1103
  for (c = code->block; c; c = c->block)
1104
    {
1105
      for (cp = c->ext.case_list; cp; cp = cp->next)
1106
        {
1107
          if (cp->low)
1108
            {
1109
              if (cp->low->value.logical == 0) /* .FALSE.  */
1110
                f = c;
1111
              else /* if (cp->value.logical != 0), thus .TRUE.  */
1112
                t = c;
1113
            }
1114
          else
1115
            d = c;
1116
        }
1117
    }
1118
 
1119
  /* Start a new block.  */
1120
  gfc_start_block (&block);
1121
 
1122
  /* Calculate the switch expression.  We always need to do this
1123
     because it may have side effects.  */
1124
  gfc_init_se (&se, NULL);
1125
  gfc_conv_expr_val (&se, code->expr);
1126
  gfc_add_block_to_block (&block, &se.pre);
1127
 
1128
  if (t == f && t != NULL)
1129
    {
1130
      /* Cases for .TRUE. and .FALSE. are in the same block.  Just
1131
         translate the code for these cases, append it to the current
1132
         block.  */
1133
      gfc_add_expr_to_block (&block, gfc_trans_code (t->next));
1134
    }
1135
  else
1136
    {
1137
      tree true_tree, false_tree;
1138
 
1139
      true_tree = build_empty_stmt ();
1140
      false_tree = build_empty_stmt ();
1141
 
1142
      /* If we have a case for .TRUE. and for .FALSE., discard the default case.
1143
          Otherwise, if .TRUE. or .FALSE. is missing and there is a default case,
1144
          make the missing case the default case.  */
1145
      if (t != NULL && f != NULL)
1146
        d = NULL;
1147
      else if (d != NULL)
1148
        {
1149
          if (t == NULL)
1150
            t = d;
1151
          else
1152
            f = d;
1153
        }
1154
 
1155
      /* Translate the code for each of these blocks, and append it to
1156
         the current block.  */
1157
      if (t != NULL)
1158
        true_tree = gfc_trans_code (t->next);
1159
 
1160
      if (f != NULL)
1161
        false_tree = gfc_trans_code (f->next);
1162
 
1163
      gfc_add_expr_to_block (&block, build3_v (COND_EXPR, se.expr,
1164
                                               true_tree, false_tree));
1165
    }
1166
 
1167
  return gfc_finish_block (&block);
1168
}
1169
 
1170
 
1171
/* Translate the SELECT CASE construct for CHARACTER case expressions.
1172
   Instead of generating compares and jumps, it is far simpler to
1173
   generate a data structure describing the cases in order and call a
1174
   library subroutine that locates the right case.
1175
   This is particularly true because this is the only case where we
1176
   might have to dispose of a temporary.
1177
   The library subroutine returns a pointer to jump to or NULL if no
1178
   branches are to be taken.  */
1179
 
1180
static tree
1181
gfc_trans_character_select (gfc_code *code)
1182
{
1183
  tree init, node, end_label, tmp, type, args, *labels;
1184
  stmtblock_t block, body;
1185
  gfc_case *cp, *d;
1186
  gfc_code *c;
1187
  gfc_se se;
1188
  int i, n;
1189
 
1190
  static tree select_struct;
1191
  static tree ss_string1, ss_string1_len;
1192
  static tree ss_string2, ss_string2_len;
1193
  static tree ss_target;
1194
 
1195
  if (select_struct == NULL)
1196
    {
1197
      tree gfc_int4_type_node = gfc_get_int_type (4);
1198
 
1199
      select_struct = make_node (RECORD_TYPE);
1200
      TYPE_NAME (select_struct) = get_identifier ("_jump_struct");
1201
 
1202
#undef ADD_FIELD
1203
#define ADD_FIELD(NAME, TYPE)                           \
1204
  ss_##NAME = gfc_add_field_to_struct                   \
1205
     (&(TYPE_FIELDS (select_struct)), select_struct,    \
1206
      get_identifier (stringize(NAME)), TYPE)
1207
 
1208
      ADD_FIELD (string1, pchar_type_node);
1209
      ADD_FIELD (string1_len, gfc_int4_type_node);
1210
 
1211
      ADD_FIELD (string2, pchar_type_node);
1212
      ADD_FIELD (string2_len, gfc_int4_type_node);
1213
 
1214
      ADD_FIELD (target, pvoid_type_node);
1215
#undef ADD_FIELD
1216
 
1217
      gfc_finish_type (select_struct);
1218
    }
1219
 
1220
  cp = code->block->ext.case_list;
1221
  while (cp->left != NULL)
1222
    cp = cp->left;
1223
 
1224
  n = 0;
1225
  for (d = cp; d; d = d->right)
1226
    d->n = n++;
1227
 
1228
  if (n != 0)
1229
    labels = gfc_getmem (n * sizeof (tree));
1230
  else
1231
    labels = NULL;
1232
 
1233
  for(i = 0; i < n; i++)
1234
    {
1235
      labels[i] = gfc_build_label_decl (NULL_TREE);
1236
      TREE_USED (labels[i]) = 1;
1237
      /* TODO: The gimplifier should do this for us, but it has
1238
         inadequacies when dealing with static initializers.  */
1239
      FORCED_LABEL (labels[i]) = 1;
1240
    }
1241
 
1242
  end_label = gfc_build_label_decl (NULL_TREE);
1243
 
1244
  /* Generate the body */
1245
  gfc_start_block (&block);
1246
  gfc_init_block (&body);
1247
 
1248
  for (c = code->block; c; c = c->block)
1249
    {
1250
      for (d = c->ext.case_list; d; d = d->next)
1251
        {
1252
          tmp = build1_v (LABEL_EXPR, labels[d->n]);
1253
          gfc_add_expr_to_block (&body, tmp);
1254
        }
1255
 
1256
      tmp = gfc_trans_code (c->next);
1257
      gfc_add_expr_to_block (&body, tmp);
1258
 
1259
      tmp = build1_v (GOTO_EXPR, end_label);
1260
      gfc_add_expr_to_block (&body, tmp);
1261
    }
1262
 
1263
  /* Generate the structure describing the branches */
1264
  init = NULL_TREE;
1265
  i = 0;
1266
 
1267
  for(d = cp; d; d = d->right, i++)
1268
    {
1269
      node = NULL_TREE;
1270
 
1271
      gfc_init_se (&se, NULL);
1272
 
1273
      if (d->low == NULL)
1274
        {
1275
          node = tree_cons (ss_string1, null_pointer_node, node);
1276
          node = tree_cons (ss_string1_len, integer_zero_node, node);
1277
        }
1278
      else
1279
        {
1280
          gfc_conv_expr_reference (&se, d->low);
1281
 
1282
          node = tree_cons (ss_string1, se.expr, node);
1283
          node = tree_cons (ss_string1_len, se.string_length, node);
1284
        }
1285
 
1286
      if (d->high == NULL)
1287
        {
1288
          node = tree_cons (ss_string2, null_pointer_node, node);
1289
          node = tree_cons (ss_string2_len, integer_zero_node, node);
1290
        }
1291
      else
1292
        {
1293
          gfc_init_se (&se, NULL);
1294
          gfc_conv_expr_reference (&se, d->high);
1295
 
1296
          node = tree_cons (ss_string2, se.expr, node);
1297
          node = tree_cons (ss_string2_len, se.string_length, node);
1298
        }
1299
 
1300
      tmp = gfc_build_addr_expr (pvoid_type_node, labels[i]);
1301
      node = tree_cons (ss_target, tmp, node);
1302
 
1303
      tmp = build_constructor_from_list (select_struct, nreverse (node));
1304
      init = tree_cons (NULL_TREE, tmp, init);
1305
    }
1306
 
1307
  type = build_array_type (select_struct, build_index_type
1308
                           (build_int_cst (NULL_TREE, n - 1)));
1309
 
1310
  init = build_constructor_from_list (type, nreverse(init));
1311
  TREE_CONSTANT (init) = 1;
1312
  TREE_INVARIANT (init) = 1;
1313
  TREE_STATIC (init) = 1;
1314
  /* Create a static variable to hold the jump table.  */
1315
  tmp = gfc_create_var (type, "jumptable");
1316
  TREE_CONSTANT (tmp) = 1;
1317
  TREE_INVARIANT (tmp) = 1;
1318
  TREE_STATIC (tmp) = 1;
1319
  DECL_INITIAL (tmp) = init;
1320
  init = tmp;
1321
 
1322
  /* Build an argument list for the library call */
1323
  init = gfc_build_addr_expr (pvoid_type_node, init);
1324
  args = gfc_chainon_list (NULL_TREE, init);
1325
 
1326
  tmp = build_int_cst (NULL_TREE, n);
1327
  args = gfc_chainon_list (args, tmp);
1328
 
1329
  tmp = gfc_build_addr_expr (pvoid_type_node, end_label);
1330
  args = gfc_chainon_list (args, tmp);
1331
 
1332
  gfc_init_se (&se, NULL);
1333
  gfc_conv_expr_reference (&se, code->expr);
1334
 
1335
  args = gfc_chainon_list (args, se.expr);
1336
  args = gfc_chainon_list (args, se.string_length);
1337
 
1338
  gfc_add_block_to_block (&block, &se.pre);
1339
 
1340
  tmp = gfc_build_function_call (gfor_fndecl_select_string, args);
1341
  tmp = build1 (GOTO_EXPR, void_type_node, tmp);
1342
  gfc_add_expr_to_block (&block, tmp);
1343
 
1344
  tmp = gfc_finish_block (&body);
1345
  gfc_add_expr_to_block (&block, tmp);
1346
  tmp = build1_v (LABEL_EXPR, end_label);
1347
  gfc_add_expr_to_block (&block, tmp);
1348
 
1349
  if (n != 0)
1350
    gfc_free (labels);
1351
 
1352
  return gfc_finish_block (&block);
1353
}
1354
 
1355
 
1356
/* Translate the three variants of the SELECT CASE construct.
1357
 
1358
   SELECT CASEs with INTEGER case expressions can be translated to an
1359
   equivalent GENERIC switch statement, and for LOGICAL case
1360
   expressions we build one or two if-else compares.
1361
 
1362
   SELECT CASEs with CHARACTER case expressions are a whole different
1363
   story, because they don't exist in GENERIC.  So we sort them and
1364
   do a binary search at runtime.
1365
 
1366
   Fortran has no BREAK statement, and it does not allow jumps from
1367
   one case block to another.  That makes things a lot easier for
1368
   the optimizers.  */
1369
 
1370
tree
1371
gfc_trans_select (gfc_code * code)
1372
{
1373
  gcc_assert (code && code->expr);
1374
 
1375
  /* Empty SELECT constructs are legal.  */
1376
  if (code->block == NULL)
1377
    return build_empty_stmt ();
1378
 
1379
  /* Select the correct translation function.  */
1380
  switch (code->expr->ts.type)
1381
    {
1382
    case BT_LOGICAL:    return gfc_trans_logical_select (code);
1383
    case BT_INTEGER:    return gfc_trans_integer_select (code);
1384
    case BT_CHARACTER:  return gfc_trans_character_select (code);
1385
    default:
1386
      gfc_internal_error ("gfc_trans_select(): Bad type for case expr.");
1387
      /* Not reached */
1388
    }
1389
}
1390
 
1391
 
1392
/* Generate the loops for a FORALL block.  The normal loop format:
1393
    count = (end - start + step) / step
1394
    loopvar = start
1395
    while (1)
1396
      {
1397
        if (count <=0 )
1398
          goto end_of_loop
1399
        <body>
1400
        loopvar += step
1401
        count --
1402
      }
1403
    end_of_loop:  */
1404
 
1405
static tree
1406
gfc_trans_forall_loop (forall_info *forall_tmp, int nvar, tree body, int mask_flag)
1407
{
1408
  int n;
1409
  tree tmp;
1410
  tree cond;
1411
  stmtblock_t block;
1412
  tree exit_label;
1413
  tree count;
1414
  tree var, start, end, step;
1415
  iter_info *iter;
1416
 
1417
  iter = forall_tmp->this_loop;
1418
  for (n = 0; n < nvar; n++)
1419
    {
1420
      var = iter->var;
1421
      start = iter->start;
1422
      end = iter->end;
1423
      step = iter->step;
1424
 
1425
      exit_label = gfc_build_label_decl (NULL_TREE);
1426
      TREE_USED (exit_label) = 1;
1427
 
1428
      /* The loop counter.  */
1429
      count = gfc_create_var (TREE_TYPE (var), "count");
1430
 
1431
      /* The body of the loop.  */
1432
      gfc_init_block (&block);
1433
 
1434
      /* The exit condition.  */
1435
      cond = build2 (LE_EXPR, boolean_type_node, count, integer_zero_node);
1436
      tmp = build1_v (GOTO_EXPR, exit_label);
1437
      tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt ());
1438
      gfc_add_expr_to_block (&block, tmp);
1439
 
1440
      /* The main loop body.  */
1441
      gfc_add_expr_to_block (&block, body);
1442
 
1443
      /* Increment the loop variable.  */
1444
      tmp = build2 (PLUS_EXPR, TREE_TYPE (var), var, step);
1445
      gfc_add_modify_expr (&block, var, tmp);
1446
 
1447
      /* Advance to the next mask element.  Only do this for the
1448
         innermost loop.  */
1449
      if (n == 0 && mask_flag && forall_tmp->mask)
1450
        {
1451
          tree maskindex = forall_tmp->maskindex;
1452
          tmp = build2 (PLUS_EXPR, gfc_array_index_type,
1453
                        maskindex, gfc_index_one_node);
1454
          gfc_add_modify_expr (&block, maskindex, tmp);
1455
        }
1456
 
1457
      /* Decrement the loop counter.  */
1458
      tmp = build2 (MINUS_EXPR, TREE_TYPE (var), count, gfc_index_one_node);
1459
      gfc_add_modify_expr (&block, count, tmp);
1460
 
1461
      body = gfc_finish_block (&block);
1462
 
1463
      /* Loop var initialization.  */
1464
      gfc_init_block (&block);
1465
      gfc_add_modify_expr (&block, var, start);
1466
 
1467
      /* Initialize maskindex counter.  Only do this before the
1468
         outermost loop.  */
1469
      if (n == nvar - 1 && mask_flag && forall_tmp->mask)
1470
        gfc_add_modify_expr (&block, forall_tmp->maskindex,
1471
                             gfc_index_zero_node);
1472
 
1473
      /* Initialize the loop counter.  */
1474
      tmp = fold_build2 (MINUS_EXPR, TREE_TYPE (var), step, start);
1475
      tmp = fold_build2 (PLUS_EXPR, TREE_TYPE (var), end, tmp);
1476
      tmp = fold_build2 (TRUNC_DIV_EXPR, TREE_TYPE (var), tmp, step);
1477
      gfc_add_modify_expr (&block, count, tmp);
1478
 
1479
      /* The loop expression.  */
1480
      tmp = build1_v (LOOP_EXPR, body);
1481
      gfc_add_expr_to_block (&block, tmp);
1482
 
1483
      /* The exit label.  */
1484
      tmp = build1_v (LABEL_EXPR, exit_label);
1485
      gfc_add_expr_to_block (&block, tmp);
1486
 
1487
      body = gfc_finish_block (&block);
1488
      iter = iter->next;
1489
    }
1490
  return body;
1491
}
1492
 
1493
 
1494
/* Generate the body and loops according to MASK_FLAG and NEST_FLAG.
1495
   if MASK_FLAG is nonzero, the body is controlled by maskes in forall
1496
   nest, otherwise, the body is not controlled by maskes.
1497
   if NEST_FLAG is nonzero, generate loops for nested forall, otherwise,
1498
   only generate loops for the current forall level.  */
1499
 
1500
static tree
1501
gfc_trans_nested_forall_loop (forall_info * nested_forall_info, tree body,
1502
                              int mask_flag, int nest_flag)
1503
{
1504
  tree tmp;
1505
  int nvar;
1506
  forall_info *forall_tmp;
1507
  tree pmask, mask, maskindex;
1508
 
1509
  forall_tmp = nested_forall_info;
1510
  /* Generate loops for nested forall.  */
1511
  if (nest_flag)
1512
    {
1513
      while (forall_tmp->next_nest != NULL)
1514
        forall_tmp = forall_tmp->next_nest;
1515
      while (forall_tmp != NULL)
1516
        {
1517
          /* Generate body with masks' control.  */
1518
          if (mask_flag)
1519
            {
1520
              pmask = forall_tmp->pmask;
1521
              mask = forall_tmp->mask;
1522
              maskindex = forall_tmp->maskindex;
1523
 
1524
              if (mask)
1525
                {
1526
                  /* If a mask was specified make the assignment conditional.  */
1527
                  if (pmask)
1528
                    tmp = gfc_build_indirect_ref (mask);
1529
                  else
1530
                    tmp = mask;
1531
                  tmp = gfc_build_array_ref (tmp, maskindex);
1532
 
1533
                  body = build3_v (COND_EXPR, tmp, body, build_empty_stmt ());
1534
                }
1535
            }
1536
          nvar = forall_tmp->nvar;
1537
          body = gfc_trans_forall_loop (forall_tmp, nvar, body, mask_flag);
1538
          forall_tmp = forall_tmp->outer;
1539
        }
1540
    }
1541
  else
1542
    {
1543
      nvar = forall_tmp->nvar;
1544
      body = gfc_trans_forall_loop (forall_tmp, nvar, body, mask_flag);
1545
    }
1546
 
1547
  return body;
1548
}
1549
 
1550
 
1551
/* Allocate data for holding a temporary array.  Returns either a local
1552
   temporary array or a pointer variable.  */
1553
 
1554
static tree
1555
gfc_do_allocate (tree bytesize, tree size, tree * pdata, stmtblock_t * pblock,
1556
                 tree elem_type)
1557
{
1558
  tree tmpvar;
1559
  tree type;
1560
  tree tmp;
1561
  tree args;
1562
 
1563
  if (INTEGER_CST_P (size))
1564
    {
1565
      tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type, size,
1566
                         gfc_index_one_node);
1567
    }
1568
  else
1569
    tmp = NULL_TREE;
1570
 
1571
  type = build_range_type (gfc_array_index_type, gfc_index_zero_node, tmp);
1572
  type = build_array_type (elem_type, type);
1573
  if (gfc_can_put_var_on_stack (bytesize))
1574
    {
1575
      gcc_assert (INTEGER_CST_P (size));
1576
      tmpvar = gfc_create_var (type, "temp");
1577
      *pdata = NULL_TREE;
1578
    }
1579
  else
1580
    {
1581
      tmpvar = gfc_create_var (build_pointer_type (type), "temp");
1582
      *pdata = convert (pvoid_type_node, tmpvar);
1583
 
1584
      args = gfc_chainon_list (NULL_TREE, bytesize);
1585
      if (gfc_index_integer_kind == 4)
1586
        tmp = gfor_fndecl_internal_malloc;
1587
      else if (gfc_index_integer_kind == 8)
1588
        tmp = gfor_fndecl_internal_malloc64;
1589
      else
1590
        gcc_unreachable ();
1591
      tmp = gfc_build_function_call (tmp, args);
1592
      tmp = convert (TREE_TYPE (tmpvar), tmp);
1593
      gfc_add_modify_expr (pblock, tmpvar, tmp);
1594
    }
1595
  return tmpvar;
1596
}
1597
 
1598
 
1599
/* Generate codes to copy the temporary to the actual lhs.  */
1600
 
1601
static tree
1602
generate_loop_for_temp_to_lhs (gfc_expr *expr, tree tmp1, tree count3,
1603
                               tree count1, tree wheremask)
1604
{
1605
  gfc_ss *lss;
1606
  gfc_se lse, rse;
1607
  stmtblock_t block, body;
1608
  gfc_loopinfo loop1;
1609
  tree tmp, tmp2;
1610
  tree wheremaskexpr;
1611
 
1612
  /* Walk the lhs.  */
1613
  lss = gfc_walk_expr (expr);
1614
 
1615
  if (lss == gfc_ss_terminator)
1616
    {
1617
      gfc_start_block (&block);
1618
 
1619
      gfc_init_se (&lse, NULL);
1620
 
1621
      /* Translate the expression.  */
1622
      gfc_conv_expr (&lse, expr);
1623
 
1624
      /* Form the expression for the temporary.  */
1625
      tmp = gfc_build_array_ref (tmp1, count1);
1626
 
1627
      /* Use the scalar assignment as is.  */
1628
      gfc_add_block_to_block (&block, &lse.pre);
1629
      gfc_add_modify_expr (&block, lse.expr, tmp);
1630
      gfc_add_block_to_block (&block, &lse.post);
1631
 
1632
      /* Increment the count1.  */
1633
      tmp = fold_build2 (PLUS_EXPR, TREE_TYPE (count1), count1,
1634
                         gfc_index_one_node);
1635
      gfc_add_modify_expr (&block, count1, tmp);
1636
 
1637
      tmp = gfc_finish_block (&block);
1638
    }
1639
  else
1640
    {
1641
      gfc_start_block (&block);
1642
 
1643
      gfc_init_loopinfo (&loop1);
1644
      gfc_init_se (&rse, NULL);
1645
      gfc_init_se (&lse, NULL);
1646
 
1647
      /* Associate the lss with the loop.  */
1648
      gfc_add_ss_to_loop (&loop1, lss);
1649
 
1650
      /* Calculate the bounds of the scalarization.  */
1651
      gfc_conv_ss_startstride (&loop1);
1652
      /* Setup the scalarizing loops.  */
1653
      gfc_conv_loop_setup (&loop1);
1654
 
1655
      gfc_mark_ss_chain_used (lss, 1);
1656
 
1657
      /* Start the scalarized loop body.  */
1658
      gfc_start_scalarized_body (&loop1, &body);
1659
 
1660
      /* Setup the gfc_se structures.  */
1661
      gfc_copy_loopinfo_to_se (&lse, &loop1);
1662
      lse.ss = lss;
1663
 
1664
      /* Form the expression of the temporary.  */
1665
      if (lss != gfc_ss_terminator)
1666
        rse.expr = gfc_build_array_ref (tmp1, count1);
1667
      /* Translate expr.  */
1668
      gfc_conv_expr (&lse, expr);
1669
 
1670
      /* Use the scalar assignment.  */
1671
      tmp = gfc_trans_scalar_assign (&lse, &rse, expr->ts.type);
1672
 
1673
     /* Form the mask expression according to the mask tree list.  */
1674
     if (wheremask)
1675
       {
1676
         wheremaskexpr = gfc_build_array_ref (wheremask, count3);
1677
         tmp2 = TREE_CHAIN (wheremask);
1678
         while (tmp2)
1679
           {
1680
             tmp1 = gfc_build_array_ref (tmp2, count3);
1681
             wheremaskexpr = build2 (TRUTH_AND_EXPR, TREE_TYPE (tmp1),
1682
                                     wheremaskexpr, tmp1);
1683
             tmp2 = TREE_CHAIN (tmp2);
1684
           }
1685
         tmp = build3_v (COND_EXPR, wheremaskexpr, tmp, build_empty_stmt ());
1686
       }
1687
 
1688
      gfc_add_expr_to_block (&body, tmp);
1689
 
1690
      /* Increment count1.  */
1691
      tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
1692
                         count1, gfc_index_one_node);
1693
      gfc_add_modify_expr (&body, count1, tmp);
1694
 
1695
      /* Increment count3.  */
1696
      if (count3)
1697
        {
1698
          tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
1699
                             count3, gfc_index_one_node);
1700
          gfc_add_modify_expr (&body, count3, tmp);
1701
        }
1702
 
1703
      /* Generate the copying loops.  */
1704
      gfc_trans_scalarizing_loops (&loop1, &body);
1705
      gfc_add_block_to_block (&block, &loop1.pre);
1706
      gfc_add_block_to_block (&block, &loop1.post);
1707
      gfc_cleanup_loop (&loop1);
1708
 
1709
      tmp = gfc_finish_block (&block);
1710
    }
1711
  return tmp;
1712
}
1713
 
1714
 
1715
/* Generate codes to copy rhs to the temporary. TMP1 is the address of temporary
1716
   LSS and RSS are formed in function compute_inner_temp_size(), and should
1717
   not be freed.  */
1718
 
1719
static tree
1720
generate_loop_for_rhs_to_temp (gfc_expr *expr2, tree tmp1, tree count3,
1721
                               tree count1, gfc_ss *lss, gfc_ss *rss,
1722
                               tree wheremask)
1723
{
1724
  stmtblock_t block, body1;
1725
  gfc_loopinfo loop;
1726
  gfc_se lse;
1727
  gfc_se rse;
1728
  tree tmp, tmp2;
1729
  tree wheremaskexpr;
1730
 
1731
  gfc_start_block (&block);
1732
 
1733
  gfc_init_se (&rse, NULL);
1734
  gfc_init_se (&lse, NULL);
1735
 
1736
  if (lss == gfc_ss_terminator)
1737
    {
1738
      gfc_init_block (&body1);
1739
      gfc_conv_expr (&rse, expr2);
1740
      lse.expr = gfc_build_array_ref (tmp1, count1);
1741
    }
1742
  else
1743
    {
1744
      /* Initialize the loop.  */
1745
      gfc_init_loopinfo (&loop);
1746
 
1747
      /* We may need LSS to determine the shape of the expression.  */
1748
      gfc_add_ss_to_loop (&loop, lss);
1749
      gfc_add_ss_to_loop (&loop, rss);
1750
 
1751
      gfc_conv_ss_startstride (&loop);
1752
      gfc_conv_loop_setup (&loop);
1753
 
1754
      gfc_mark_ss_chain_used (rss, 1);
1755
      /* Start the loop body.  */
1756
      gfc_start_scalarized_body (&loop, &body1);
1757
 
1758
      /* Translate the expression.  */
1759
      gfc_copy_loopinfo_to_se (&rse, &loop);
1760
      rse.ss = rss;
1761
      gfc_conv_expr (&rse, expr2);
1762
 
1763
      /* Form the expression of the temporary.  */
1764
      lse.expr = gfc_build_array_ref (tmp1, count1);
1765
    }
1766
 
1767
  /* Use the scalar assignment.  */
1768
  tmp = gfc_trans_scalar_assign (&lse, &rse, expr2->ts.type);
1769
 
1770
  /* Form the mask expression according to the mask tree list.  */
1771
  if (wheremask)
1772
    {
1773
      wheremaskexpr = gfc_build_array_ref (wheremask, count3);
1774
      tmp2 = TREE_CHAIN (wheremask);
1775
      while (tmp2)
1776
        {
1777
          tmp1 = gfc_build_array_ref (tmp2, count3);
1778
          wheremaskexpr = build2 (TRUTH_AND_EXPR, TREE_TYPE (tmp1),
1779
                                  wheremaskexpr, tmp1);
1780
          tmp2 = TREE_CHAIN (tmp2);
1781
        }
1782
      tmp = build3_v (COND_EXPR, wheremaskexpr, tmp, build_empty_stmt ());
1783
    }
1784
 
1785
  gfc_add_expr_to_block (&body1, tmp);
1786
 
1787
  if (lss == gfc_ss_terminator)
1788
    {
1789
      gfc_add_block_to_block (&block, &body1);
1790
 
1791
      /* Increment count1.  */
1792
      tmp = fold_build2 (PLUS_EXPR, TREE_TYPE (count1), count1,
1793
                         gfc_index_one_node);
1794
      gfc_add_modify_expr (&block, count1, tmp);
1795
    }
1796
  else
1797
    {
1798
      /* Increment count1.  */
1799
      tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
1800
                         count1, gfc_index_one_node);
1801
      gfc_add_modify_expr (&body1, count1, tmp);
1802
 
1803
      /* Increment count3.  */
1804
      if (count3)
1805
        {
1806
          tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
1807
                             count3, gfc_index_one_node);
1808
          gfc_add_modify_expr (&body1, count3, tmp);
1809
        }
1810
 
1811
      /* Generate the copying loops.  */
1812
      gfc_trans_scalarizing_loops (&loop, &body1);
1813
 
1814
      gfc_add_block_to_block (&block, &loop.pre);
1815
      gfc_add_block_to_block (&block, &loop.post);
1816
 
1817
      gfc_cleanup_loop (&loop);
1818
      /* TODO: Reuse lss and rss when copying temp->lhs.  Need to be careful
1819
         as tree nodes in SS may not be valid in different scope.  */
1820
    }
1821
 
1822
  tmp = gfc_finish_block (&block);
1823
  return tmp;
1824
}
1825
 
1826
 
1827
/* Calculate the size of temporary needed in the assignment inside forall.
1828
   LSS and RSS are filled in this function.  */
1829
 
1830
static tree
1831
compute_inner_temp_size (gfc_expr *expr1, gfc_expr *expr2,
1832
                         stmtblock_t * pblock,
1833
                         gfc_ss **lss, gfc_ss **rss)
1834
{
1835
  gfc_loopinfo loop;
1836
  tree size;
1837
  int i;
1838
  tree tmp;
1839
 
1840
  *lss = gfc_walk_expr (expr1);
1841
  *rss = NULL;
1842
 
1843
  size = gfc_index_one_node;
1844
  if (*lss != gfc_ss_terminator)
1845
    {
1846
      gfc_init_loopinfo (&loop);
1847
 
1848
      /* Walk the RHS of the expression.  */
1849
      *rss = gfc_walk_expr (expr2);
1850
      if (*rss == gfc_ss_terminator)
1851
        {
1852
          /* The rhs is scalar.  Add a ss for the expression.  */
1853
          *rss = gfc_get_ss ();
1854
          (*rss)->next = gfc_ss_terminator;
1855
          (*rss)->type = GFC_SS_SCALAR;
1856
          (*rss)->expr = expr2;
1857
        }
1858
 
1859
      /* Associate the SS with the loop.  */
1860
      gfc_add_ss_to_loop (&loop, *lss);
1861
      /* We don't actually need to add the rhs at this point, but it might
1862
         make guessing the loop bounds a bit easier.  */
1863
      gfc_add_ss_to_loop (&loop, *rss);
1864
 
1865
      /* We only want the shape of the expression, not rest of the junk
1866
         generated by the scalarizer.  */
1867
      loop.array_parameter = 1;
1868
 
1869
      /* Calculate the bounds of the scalarization.  */
1870
      gfc_conv_ss_startstride (&loop);
1871
      gfc_conv_loop_setup (&loop);
1872
 
1873
      /* Figure out how many elements we need.  */
1874
      for (i = 0; i < loop.dimen; i++)
1875
        {
1876
          tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type,
1877
                             gfc_index_one_node, loop.from[i]);
1878
          tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
1879
                             tmp, loop.to[i]);
1880
          size = fold_build2 (MULT_EXPR, gfc_array_index_type, size, tmp);
1881
        }
1882
      gfc_add_block_to_block (pblock, &loop.pre);
1883
      size = gfc_evaluate_now (size, pblock);
1884
      gfc_add_block_to_block (pblock, &loop.post);
1885
 
1886
      /* TODO: write a function that cleans up a loopinfo without freeing
1887
         the SS chains.  Currently a NOP.  */
1888
    }
1889
 
1890
  return size;
1891
}
1892
 
1893
 
1894
/* Calculate the overall iterator number of the nested forall construct.  */
1895
 
1896
static tree
1897
compute_overall_iter_number (forall_info *nested_forall_info, tree inner_size,
1898
                             stmtblock_t *inner_size_body, stmtblock_t *block)
1899
{
1900
  tree tmp, number;
1901
  stmtblock_t body;
1902
 
1903
  /* TODO: optimizing the computing process.  */
1904
  number = gfc_create_var (gfc_array_index_type, "num");
1905
  gfc_add_modify_expr (block, number, gfc_index_zero_node);
1906
 
1907
  gfc_start_block (&body);
1908
  if (inner_size_body)
1909
    gfc_add_block_to_block (&body, inner_size_body);
1910
  if (nested_forall_info)
1911
    tmp = build2 (PLUS_EXPR, gfc_array_index_type, number,
1912
                  inner_size);
1913
  else
1914
    tmp = inner_size;
1915
  gfc_add_modify_expr (&body, number, tmp);
1916
  tmp = gfc_finish_block (&body);
1917
 
1918
  /* Generate loops.  */
1919
  if (nested_forall_info != NULL)
1920
    tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 0, 1);
1921
 
1922
  gfc_add_expr_to_block (block, tmp);
1923
 
1924
  return number;
1925
}
1926
 
1927
 
1928
/* Allocate temporary for forall construct.  SIZE is the size of temporary
1929
   needed.  PTEMP1 is returned for space free.  */
1930
 
1931
static tree
1932
allocate_temp_for_forall_nest_1 (tree type, tree size, stmtblock_t * block,
1933
                                 tree * ptemp1)
1934
{
1935
  tree unit;
1936
  tree temp1;
1937
  tree tmp;
1938
  tree bytesize;
1939
 
1940
  unit = TYPE_SIZE_UNIT (type);
1941
  bytesize = fold_build2 (MULT_EXPR, gfc_array_index_type, size, unit);
1942
 
1943
  *ptemp1 = NULL;
1944
  temp1 = gfc_do_allocate (bytesize, size, ptemp1, block, type);
1945
 
1946
  if (*ptemp1)
1947
    tmp = gfc_build_indirect_ref (temp1);
1948
  else
1949
    tmp = temp1;
1950
 
1951
  return tmp;
1952
}
1953
 
1954
 
1955
/* Allocate temporary for forall construct according to the information in
1956
   nested_forall_info.  INNER_SIZE is the size of temporary needed in the
1957
   assignment inside forall.  PTEMP1 is returned for space free.  */
1958
 
1959
static tree
1960
allocate_temp_for_forall_nest (forall_info * nested_forall_info, tree type,
1961
                               tree inner_size, stmtblock_t * inner_size_body,
1962
                               stmtblock_t * block, tree * ptemp1)
1963
{
1964
  tree size;
1965
 
1966
  /* Calculate the total size of temporary needed in forall construct.  */
1967
  size = compute_overall_iter_number (nested_forall_info, inner_size,
1968
                                      inner_size_body, block);
1969
 
1970
  return allocate_temp_for_forall_nest_1 (type, size, block, ptemp1);
1971
}
1972
 
1973
 
1974
/* Handle assignments inside forall which need temporary.
1975
 
1976
    forall (i=start:end:stride; maskexpr)
1977
      e<i> = f<i>
1978
    end forall
1979
   (where e,f<i> are arbitrary expressions possibly involving i
1980
    and there is a dependency between e<i> and f<i>)
1981
   Translates to:
1982
    masktmp(:) = maskexpr(:)
1983
 
1984
    maskindex = 0;
1985
    count1 = 0;
1986
    num = 0;
1987
    for (i = start; i <= end; i += stride)
1988
      num += SIZE (f<i>)
1989
    count1 = 0;
1990
    ALLOCATE (tmp(num))
1991
    for (i = start; i <= end; i += stride)
1992
      {
1993
        if (masktmp[maskindex++])
1994
          tmp[count1++] = f<i>
1995
      }
1996
    maskindex = 0;
1997
    count1 = 0;
1998
    for (i = start; i <= end; i += stride)
1999
      {
2000
        if (masktmp[maskindex++])
2001
          e<i> = tmp[count1++]
2002
      }
2003
    DEALLOCATE (tmp)
2004
  */
2005
static void
2006
gfc_trans_assign_need_temp (gfc_expr * expr1, gfc_expr * expr2, tree wheremask,
2007
                            forall_info * nested_forall_info,
2008
                            stmtblock_t * block)
2009
{
2010
  tree type;
2011
  tree inner_size;
2012
  gfc_ss *lss, *rss;
2013
  tree count, count1;
2014
  tree tmp, tmp1;
2015
  tree ptemp1;
2016
  stmtblock_t inner_size_body;
2017
 
2018
  /* Create vars. count1 is the current iterator number of the nested
2019
     forall.  */
2020
  count1 = gfc_create_var (gfc_array_index_type, "count1");
2021
 
2022
  /* Count is the wheremask index.  */
2023
  if (wheremask)
2024
    {
2025
      count = gfc_create_var (gfc_array_index_type, "count");
2026
      gfc_add_modify_expr (block, count, gfc_index_zero_node);
2027
    }
2028
  else
2029
    count = NULL;
2030
 
2031
  /* Initialize count1.  */
2032
  gfc_add_modify_expr (block, count1, gfc_index_zero_node);
2033
 
2034
  /* Calculate the size of temporary needed in the assignment. Return loop, lss
2035
     and rss which are used in function generate_loop_for_rhs_to_temp().  */
2036
  gfc_init_block (&inner_size_body);
2037
  inner_size = compute_inner_temp_size (expr1, expr2, &inner_size_body,
2038
                                        &lss, &rss);
2039
 
2040
  /* The type of LHS. Used in function allocate_temp_for_forall_nest */
2041
  type = gfc_typenode_for_spec (&expr1->ts);
2042
 
2043
  /* Allocate temporary for nested forall construct according to the
2044
     information in nested_forall_info and inner_size.  */
2045
  tmp1 = allocate_temp_for_forall_nest (nested_forall_info, type, inner_size,
2046
                                        &inner_size_body, block, &ptemp1);
2047
 
2048
  /* Generate codes to copy rhs to the temporary .  */
2049
  tmp = generate_loop_for_rhs_to_temp (expr2, tmp1, count, count1, lss, rss,
2050
                                       wheremask);
2051
 
2052
  /* Generate body and loops according to the information in
2053
     nested_forall_info.  */
2054
  tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1, 1);
2055
  gfc_add_expr_to_block (block, tmp);
2056
 
2057
  /* Reset count1.  */
2058
  gfc_add_modify_expr (block, count1, gfc_index_zero_node);
2059
 
2060
  /* Reset count.  */
2061
  if (wheremask)
2062
    gfc_add_modify_expr (block, count, gfc_index_zero_node);
2063
 
2064
  /* Generate codes to copy the temporary to lhs.  */
2065
  tmp = generate_loop_for_temp_to_lhs (expr1, tmp1, count, count1, wheremask);
2066
 
2067
  /* Generate body and loops according to the information in
2068
     nested_forall_info.  */
2069
  tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1, 1);
2070
  gfc_add_expr_to_block (block, tmp);
2071
 
2072
  if (ptemp1)
2073
    {
2074
      /* Free the temporary.  */
2075
      tmp = gfc_chainon_list (NULL_TREE, ptemp1);
2076
      tmp = gfc_build_function_call (gfor_fndecl_internal_free, tmp);
2077
      gfc_add_expr_to_block (block, tmp);
2078
    }
2079
}
2080
 
2081
 
2082
/* Translate pointer assignment inside FORALL which need temporary.  */
2083
 
2084
static void
2085
gfc_trans_pointer_assign_need_temp (gfc_expr * expr1, gfc_expr * expr2,
2086
                                    forall_info * nested_forall_info,
2087
                                    stmtblock_t * block)
2088
{
2089
  tree type;
2090
  tree inner_size;
2091
  gfc_ss *lss, *rss;
2092
  gfc_se lse;
2093
  gfc_se rse;
2094
  gfc_ss_info *info;
2095
  gfc_loopinfo loop;
2096
  tree desc;
2097
  tree parm;
2098
  tree parmtype;
2099
  stmtblock_t body;
2100
  tree count;
2101
  tree tmp, tmp1, ptemp1;
2102
 
2103
  count = gfc_create_var (gfc_array_index_type, "count");
2104
  gfc_add_modify_expr (block, count, gfc_index_zero_node);
2105
 
2106
  inner_size = integer_one_node;
2107
  lss = gfc_walk_expr (expr1);
2108
  rss = gfc_walk_expr (expr2);
2109
  if (lss == gfc_ss_terminator)
2110
    {
2111
      type = gfc_typenode_for_spec (&expr1->ts);
2112
      type = build_pointer_type (type);
2113
 
2114
      /* Allocate temporary for nested forall construct according to the
2115
         information in nested_forall_info and inner_size.  */
2116
      tmp1 = allocate_temp_for_forall_nest (nested_forall_info, type,
2117
                                            inner_size, NULL, block, &ptemp1);
2118
      gfc_start_block (&body);
2119
      gfc_init_se (&lse, NULL);
2120
      lse.expr = gfc_build_array_ref (tmp1, count);
2121
      gfc_init_se (&rse, NULL);
2122
      rse.want_pointer = 1;
2123
      gfc_conv_expr (&rse, expr2);
2124
      gfc_add_block_to_block (&body, &rse.pre);
2125
      gfc_add_modify_expr (&body, lse.expr,
2126
                           fold_convert (TREE_TYPE (lse.expr), rse.expr));
2127
      gfc_add_block_to_block (&body, &rse.post);
2128
 
2129
      /* Increment count.  */
2130
      tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
2131
                         count, gfc_index_one_node);
2132
      gfc_add_modify_expr (&body, count, tmp);
2133
 
2134
      tmp = gfc_finish_block (&body);
2135
 
2136
      /* Generate body and loops according to the information in
2137
         nested_forall_info.  */
2138
      tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1, 1);
2139
      gfc_add_expr_to_block (block, tmp);
2140
 
2141
      /* Reset count.  */
2142
      gfc_add_modify_expr (block, count, gfc_index_zero_node);
2143
 
2144
      gfc_start_block (&body);
2145
      gfc_init_se (&lse, NULL);
2146
      gfc_init_se (&rse, NULL);
2147
      rse.expr = gfc_build_array_ref (tmp1, count);
2148
      lse.want_pointer = 1;
2149
      gfc_conv_expr (&lse, expr1);
2150
      gfc_add_block_to_block (&body, &lse.pre);
2151
      gfc_add_modify_expr (&body, lse.expr, rse.expr);
2152
      gfc_add_block_to_block (&body, &lse.post);
2153
      /* Increment count.  */
2154
      tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
2155
                         count, gfc_index_one_node);
2156
      gfc_add_modify_expr (&body, count, tmp);
2157
      tmp = gfc_finish_block (&body);
2158
 
2159
      /* Generate body and loops according to the information in
2160
         nested_forall_info.  */
2161
      tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1, 1);
2162
      gfc_add_expr_to_block (block, tmp);
2163
    }
2164
  else
2165
    {
2166
      gfc_init_loopinfo (&loop);
2167
 
2168
      /* Associate the SS with the loop.  */
2169
      gfc_add_ss_to_loop (&loop, rss);
2170
 
2171
      /* Setup the scalarizing loops and bounds.  */
2172
      gfc_conv_ss_startstride (&loop);
2173
 
2174
      gfc_conv_loop_setup (&loop);
2175
 
2176
      info = &rss->data.info;
2177
      desc = info->descriptor;
2178
 
2179
      /* Make a new descriptor.  */
2180
      parmtype = gfc_get_element_type (TREE_TYPE (desc));
2181
      parmtype = gfc_get_array_type_bounds (parmtype, loop.dimen,
2182
                                            loop.from, loop.to, 1);
2183
 
2184
      /* Allocate temporary for nested forall construct.  */
2185
      tmp1 = allocate_temp_for_forall_nest (nested_forall_info, parmtype,
2186
                                            inner_size, NULL, block, &ptemp1);
2187
      gfc_start_block (&body);
2188
      gfc_init_se (&lse, NULL);
2189
      lse.expr = gfc_build_array_ref (tmp1, count);
2190
      lse.direct_byref = 1;
2191
      rss = gfc_walk_expr (expr2);
2192
      gfc_conv_expr_descriptor (&lse, expr2, rss);
2193
 
2194
      gfc_add_block_to_block (&body, &lse.pre);
2195
      gfc_add_block_to_block (&body, &lse.post);
2196
 
2197
      /* Increment count.  */
2198
      tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
2199
                         count, gfc_index_one_node);
2200
      gfc_add_modify_expr (&body, count, tmp);
2201
 
2202
      tmp = gfc_finish_block (&body);
2203
 
2204
      /* Generate body and loops according to the information in
2205
         nested_forall_info.  */
2206
      tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1, 1);
2207
      gfc_add_expr_to_block (block, tmp);
2208
 
2209
      /* Reset count.  */
2210
      gfc_add_modify_expr (block, count, gfc_index_zero_node);
2211
 
2212
      parm = gfc_build_array_ref (tmp1, count);
2213
      lss = gfc_walk_expr (expr1);
2214
      gfc_init_se (&lse, NULL);
2215
      gfc_conv_expr_descriptor (&lse, expr1, lss);
2216
      gfc_add_modify_expr (&lse.pre, lse.expr, parm);
2217
      gfc_start_block (&body);
2218
      gfc_add_block_to_block (&body, &lse.pre);
2219
      gfc_add_block_to_block (&body, &lse.post);
2220
 
2221
      /* Increment count.  */
2222
      tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
2223
                         count, gfc_index_one_node);
2224
      gfc_add_modify_expr (&body, count, tmp);
2225
 
2226
      tmp = gfc_finish_block (&body);
2227
 
2228
      tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1, 1);
2229
      gfc_add_expr_to_block (block, tmp);
2230
    }
2231
  /* Free the temporary.  */
2232
  if (ptemp1)
2233
    {
2234
      tmp = gfc_chainon_list (NULL_TREE, ptemp1);
2235
      tmp = gfc_build_function_call (gfor_fndecl_internal_free, tmp);
2236
      gfc_add_expr_to_block (block, tmp);
2237
    }
2238
}
2239
 
2240
 
2241
/* FORALL and WHERE statements are really nasty, especially when you nest
2242
   them. All the rhs of a forall assignment must be evaluated before the
2243
   actual assignments are performed. Presumably this also applies to all the
2244
   assignments in an inner where statement.  */
2245
 
2246
/* Generate code for a FORALL statement.  Any temporaries are allocated as a
2247
   linear array, relying on the fact that we process in the same order in all
2248
   loops.
2249
 
2250
    forall (i=start:end:stride; maskexpr)
2251
      e<i> = f<i>
2252
      g<i> = h<i>
2253
    end forall
2254
   (where e,f,g,h<i> are arbitrary expressions possibly involving i)
2255
   Translates to:
2256
    count = ((end + 1 - start) / stride)
2257
    masktmp(:) = maskexpr(:)
2258
 
2259
    maskindex = 0;
2260
    for (i = start; i <= end; i += stride)
2261
      {
2262
        if (masktmp[maskindex++])
2263
          e<i> = f<i>
2264
      }
2265
    maskindex = 0;
2266
    for (i = start; i <= end; i += stride)
2267
      {
2268
        if (masktmp[maskindex++])
2269
          g<i> = h<i>
2270
      }
2271
 
2272
    Note that this code only works when there are no dependencies.
2273
    Forall loop with array assignments and data dependencies are a real pain,
2274
    because the size of the temporary cannot always be determined before the
2275
    loop is executed.  This problem is compounded by the presence of nested
2276
    FORALL constructs.
2277
 */
2278
 
2279
static tree
2280
gfc_trans_forall_1 (gfc_code * code, forall_info * nested_forall_info)
2281
{
2282
  stmtblock_t block;
2283
  stmtblock_t body;
2284
  tree *var;
2285
  tree *start;
2286
  tree *end;
2287
  tree *step;
2288
  gfc_expr **varexpr;
2289
  tree tmp;
2290
  tree assign;
2291
  tree size;
2292
  tree bytesize;
2293
  tree tmpvar;
2294
  tree sizevar;
2295
  tree lenvar;
2296
  tree maskindex;
2297
  tree mask;
2298
  tree pmask;
2299
  int n;
2300
  int nvar;
2301
  int need_temp;
2302
  gfc_forall_iterator *fa;
2303
  gfc_se se;
2304
  gfc_code *c;
2305
  gfc_saved_var *saved_vars;
2306
  iter_info *this_forall, *iter_tmp;
2307
  forall_info *info, *forall_tmp;
2308
  temporary_list *temp;
2309
 
2310
  gfc_start_block (&block);
2311
 
2312
  n = 0;
2313
  /* Count the FORALL index number.  */
2314
  for (fa = code->ext.forall_iterator; fa; fa = fa->next)
2315
    n++;
2316
  nvar = n;
2317
 
2318
  /* Allocate the space for var, start, end, step, varexpr.  */
2319
  var = (tree *) gfc_getmem (nvar * sizeof (tree));
2320
  start = (tree *) gfc_getmem (nvar * sizeof (tree));
2321
  end = (tree *) gfc_getmem (nvar * sizeof (tree));
2322
  step = (tree *) gfc_getmem (nvar * sizeof (tree));
2323
  varexpr = (gfc_expr **) gfc_getmem (nvar * sizeof (gfc_expr *));
2324
  saved_vars = (gfc_saved_var *) gfc_getmem (nvar * sizeof (gfc_saved_var));
2325
 
2326
  /* Allocate the space for info.  */
2327
  info = (forall_info *) gfc_getmem (sizeof (forall_info));
2328
  n = 0;
2329
  for (fa = code->ext.forall_iterator; fa; fa = fa->next)
2330
    {
2331
      gfc_symbol *sym = fa->var->symtree->n.sym;
2332
 
2333
      /* allocate space for this_forall.  */
2334
      this_forall = (iter_info *) gfc_getmem (sizeof (iter_info));
2335
 
2336
      /* Create a temporary variable for the FORALL index.  */
2337
      tmp = gfc_typenode_for_spec (&sym->ts);
2338
      var[n] = gfc_create_var (tmp, sym->name);
2339
      gfc_shadow_sym (sym, var[n], &saved_vars[n]);
2340
 
2341
      /* Record it in this_forall.  */
2342
      this_forall->var = var[n];
2343
 
2344
      /* Replace the index symbol's backend_decl with the temporary decl.  */
2345
      sym->backend_decl = var[n];
2346
 
2347
      /* Work out the start, end and stride for the loop.  */
2348
      gfc_init_se (&se, NULL);
2349
      gfc_conv_expr_val (&se, fa->start);
2350
      /* Record it in this_forall.  */
2351
      this_forall->start = se.expr;
2352
      gfc_add_block_to_block (&block, &se.pre);
2353
      start[n] = se.expr;
2354
 
2355
      gfc_init_se (&se, NULL);
2356
      gfc_conv_expr_val (&se, fa->end);
2357
      /* Record it in this_forall.  */
2358
      this_forall->end = se.expr;
2359
      gfc_make_safe_expr (&se);
2360
      gfc_add_block_to_block (&block, &se.pre);
2361
      end[n] = se.expr;
2362
 
2363
      gfc_init_se (&se, NULL);
2364
      gfc_conv_expr_val (&se, fa->stride);
2365
      /* Record it in this_forall.  */
2366
      this_forall->step = se.expr;
2367
      gfc_make_safe_expr (&se);
2368
      gfc_add_block_to_block (&block, &se.pre);
2369
      step[n] = se.expr;
2370
 
2371
      /* Set the NEXT field of this_forall to NULL.  */
2372
      this_forall->next = NULL;
2373
      /* Link this_forall to the info construct.  */
2374
      if (info->this_loop == NULL)
2375
        info->this_loop = this_forall;
2376
      else
2377
        {
2378
          iter_tmp = info->this_loop;
2379
          while (iter_tmp->next != NULL)
2380
            iter_tmp = iter_tmp->next;
2381
          iter_tmp->next = this_forall;
2382
        }
2383
 
2384
      n++;
2385
    }
2386
  nvar = n;
2387
 
2388
  /* Work out the number of elements in the mask array.  */
2389
  tmpvar = NULL_TREE;
2390
  lenvar = NULL_TREE;
2391
  size = gfc_index_one_node;
2392
  sizevar = NULL_TREE;
2393
 
2394
  for (n = 0; n < nvar; n++)
2395
    {
2396
      if (lenvar && TREE_TYPE (lenvar) != TREE_TYPE (start[n]))
2397
        lenvar = NULL_TREE;
2398
 
2399
      /* size = (end + step - start) / step.  */
2400
      tmp = fold_build2 (MINUS_EXPR, TREE_TYPE (start[n]),
2401
                         step[n], start[n]);
2402
      tmp = fold_build2 (PLUS_EXPR, TREE_TYPE (end[n]), end[n], tmp);
2403
 
2404
      tmp = fold_build2 (FLOOR_DIV_EXPR, TREE_TYPE (tmp), tmp, step[n]);
2405
      tmp = convert (gfc_array_index_type, tmp);
2406
 
2407
      size = fold_build2 (MULT_EXPR, gfc_array_index_type, size, tmp);
2408
    }
2409
 
2410
  /* Record the nvar and size of current forall level.  */
2411
  info->nvar = nvar;
2412
  info->size = size;
2413
 
2414
  /* Link the current forall level to nested_forall_info.  */
2415
  forall_tmp = nested_forall_info;
2416
  if (forall_tmp == NULL)
2417
    nested_forall_info = info;
2418
  else
2419
    {
2420
      while (forall_tmp->next_nest != NULL)
2421
        forall_tmp = forall_tmp->next_nest;
2422
      info->outer = forall_tmp;
2423
      forall_tmp->next_nest = info;
2424
    }
2425
 
2426
  /* Copy the mask into a temporary variable if required.
2427
     For now we assume a mask temporary is needed.  */
2428
  if (code->expr)
2429
    {
2430
      /* As the mask array can be very big, prefer compact
2431
         boolean types.  */
2432
      tree smallest_boolean_type_node
2433
        = gfc_get_logical_type (gfc_logical_kinds[0].kind);
2434
 
2435
      /* Allocate the mask temporary.  */
2436
      bytesize = fold_build2 (MULT_EXPR, gfc_array_index_type, size,
2437
                              TYPE_SIZE_UNIT (smallest_boolean_type_node));
2438
 
2439
      mask = gfc_do_allocate (bytesize, size, &pmask, &block,
2440
                              smallest_boolean_type_node);
2441
 
2442
      maskindex = gfc_create_var_np (gfc_array_index_type, "mi");
2443
      /* Record them in the info structure.  */
2444
      info->pmask = pmask;
2445
      info->mask = mask;
2446
      info->maskindex = maskindex;
2447
 
2448
      gfc_add_modify_expr (&block, maskindex, gfc_index_zero_node);
2449
 
2450
      /* Start of mask assignment loop body.  */
2451
      gfc_start_block (&body);
2452
 
2453
      /* Evaluate the mask expression.  */
2454
      gfc_init_se (&se, NULL);
2455
      gfc_conv_expr_val (&se, code->expr);
2456
      gfc_add_block_to_block (&body, &se.pre);
2457
 
2458
      /* Store the mask.  */
2459
      se.expr = convert (smallest_boolean_type_node, se.expr);
2460
 
2461
      if (pmask)
2462
        tmp = gfc_build_indirect_ref (mask);
2463
      else
2464
        tmp = mask;
2465
      tmp = gfc_build_array_ref (tmp, maskindex);
2466
      gfc_add_modify_expr (&body, tmp, se.expr);
2467
 
2468
      /* Advance to the next mask element.  */
2469
      tmp = build2 (PLUS_EXPR, gfc_array_index_type,
2470
                   maskindex, gfc_index_one_node);
2471
      gfc_add_modify_expr (&body, maskindex, tmp);
2472
 
2473
      /* Generate the loops.  */
2474
      tmp = gfc_finish_block (&body);
2475
      tmp = gfc_trans_nested_forall_loop (info, tmp, 0, 0);
2476
      gfc_add_expr_to_block (&block, tmp);
2477
    }
2478
  else
2479
    {
2480
      /* No mask was specified.  */
2481
      maskindex = NULL_TREE;
2482
      mask = pmask = NULL_TREE;
2483
    }
2484
 
2485
  c = code->block->next;
2486
 
2487
  /* TODO: loop merging in FORALL statements.  */
2488
  /* Now that we've got a copy of the mask, generate the assignment loops.  */
2489
  while (c)
2490
    {
2491
      switch (c->op)
2492
        {
2493
        case EXEC_ASSIGN:
2494
          /* A scalar or array assignment.  */
2495
          need_temp = gfc_check_dependency (c->expr, c->expr2, varexpr, nvar);
2496
          /* Temporaries due to array assignment data dependencies introduce
2497
             no end of problems.  */
2498
          if (need_temp)
2499
            gfc_trans_assign_need_temp (c->expr, c->expr2, NULL,
2500
                                        nested_forall_info, &block);
2501
          else
2502
            {
2503
              /* Use the normal assignment copying routines.  */
2504
              assign = gfc_trans_assignment (c->expr, c->expr2);
2505
 
2506
              /* Generate body and loops.  */
2507
              tmp = gfc_trans_nested_forall_loop (nested_forall_info, assign, 1, 1);
2508
              gfc_add_expr_to_block (&block, tmp);
2509
            }
2510
 
2511
          break;
2512
 
2513
        case EXEC_WHERE:
2514
 
2515
          /* Translate WHERE or WHERE construct nested in FORALL.  */
2516
          temp = NULL;
2517
          gfc_trans_where_2 (c, NULL, NULL, nested_forall_info, &block, &temp);
2518
 
2519
          while (temp)
2520
            {
2521
              tree args;
2522
              temporary_list *p;
2523
 
2524
              /* Free the temporary.  */
2525
              args = gfc_chainon_list (NULL_TREE, temp->temporary);
2526
              tmp = gfc_build_function_call (gfor_fndecl_internal_free, args);
2527
              gfc_add_expr_to_block (&block, tmp);
2528
 
2529
              p = temp;
2530
              temp = temp->next;
2531
              gfc_free (p);
2532
            }
2533
 
2534
          break;
2535
 
2536
        /* Pointer assignment inside FORALL.  */
2537
        case EXEC_POINTER_ASSIGN:
2538
          need_temp = gfc_check_dependency (c->expr, c->expr2, varexpr, nvar);
2539
          if (need_temp)
2540
            gfc_trans_pointer_assign_need_temp (c->expr, c->expr2,
2541
                                                nested_forall_info, &block);
2542
          else
2543
            {
2544
              /* Use the normal assignment copying routines.  */
2545
              assign = gfc_trans_pointer_assignment (c->expr, c->expr2);
2546
 
2547
              /* Generate body and loops.  */
2548
              tmp = gfc_trans_nested_forall_loop (nested_forall_info, assign,
2549
                                                  1, 1);
2550
              gfc_add_expr_to_block (&block, tmp);
2551
            }
2552
          break;
2553
 
2554
        case EXEC_FORALL:
2555
          tmp = gfc_trans_forall_1 (c, nested_forall_info);
2556
          gfc_add_expr_to_block (&block, tmp);
2557
          break;
2558
 
2559
        /* Explicit subroutine calls are prevented by the frontend but interface
2560
           assignments can legitimately produce them.  */
2561
        case EXEC_CALL:
2562
          assign = gfc_trans_call (c);
2563
          tmp = gfc_trans_nested_forall_loop (nested_forall_info, assign, 1, 1);
2564
          gfc_add_expr_to_block (&block, tmp);
2565
          break;
2566
 
2567
        default:
2568
          gcc_unreachable ();
2569
        }
2570
 
2571
      c = c->next;
2572
    }
2573
 
2574
  /* Restore the original index variables.  */
2575
  for (fa = code->ext.forall_iterator, n = 0; fa; fa = fa->next, n++)
2576
    gfc_restore_sym (fa->var->symtree->n.sym, &saved_vars[n]);
2577
 
2578
  /* Free the space for var, start, end, step, varexpr.  */
2579
  gfc_free (var);
2580
  gfc_free (start);
2581
  gfc_free (end);
2582
  gfc_free (step);
2583
  gfc_free (varexpr);
2584
  gfc_free (saved_vars);
2585
 
2586
  if (pmask)
2587
    {
2588
      /* Free the temporary for the mask.  */
2589
      tmp = gfc_chainon_list (NULL_TREE, pmask);
2590
      tmp = gfc_build_function_call (gfor_fndecl_internal_free, tmp);
2591
      gfc_add_expr_to_block (&block, tmp);
2592
    }
2593
  if (maskindex)
2594
    pushdecl (maskindex);
2595
 
2596
  return gfc_finish_block (&block);
2597
}
2598
 
2599
 
2600
/* Translate the FORALL statement or construct.  */
2601
 
2602
tree gfc_trans_forall (gfc_code * code)
2603
{
2604
  return gfc_trans_forall_1 (code, NULL);
2605
}
2606
 
2607
 
2608
/* Evaluate the WHERE mask expression, copy its value to a temporary.
2609
   If the WHERE construct is nested in FORALL, compute the overall temporary
2610
   needed by the WHERE mask expression multiplied by the iterator number of
2611
   the nested forall.
2612
   ME is the WHERE mask expression.
2613
   MASK is the temporary which value is mask's value.
2614
   NMASK is another temporary which value is !mask.
2615
   TEMP records the temporary's address allocated in this function in order to
2616
   free them outside this function.
2617
   MASK, NMASK and TEMP are all OUT arguments.  */
2618
 
2619
static tree
2620
gfc_evaluate_where_mask (gfc_expr * me, forall_info * nested_forall_info,
2621
                         tree * mask, tree * nmask, temporary_list ** temp,
2622
                         stmtblock_t * block)
2623
{
2624
  tree tmp, tmp1;
2625
  gfc_ss *lss, *rss;
2626
  gfc_loopinfo loop;
2627
  tree ptemp1, ntmp, ptemp2;
2628
  tree inner_size, size;
2629
  stmtblock_t body, body1, inner_size_body;
2630
  gfc_se lse, rse;
2631
  tree count;
2632
  tree tmpexpr;
2633
 
2634
  gfc_init_loopinfo (&loop);
2635
 
2636
  /* Calculate the size of temporary needed by the mask-expr.  */
2637
  gfc_init_block (&inner_size_body);
2638
  inner_size = compute_inner_temp_size (me, me, &inner_size_body, &lss, &rss);
2639
 
2640
  /* Calculate the total size of temporary needed.  */
2641
  size = compute_overall_iter_number (nested_forall_info, inner_size,
2642
                                      &inner_size_body, block);
2643
 
2644
  /* Allocate temporary for where mask.  */
2645
  tmp = allocate_temp_for_forall_nest_1 (boolean_type_node, size, block,
2646
                                         &ptemp1);
2647
  /* Record the temporary address in order to free it later.  */
2648
  if (ptemp1)
2649
    {
2650
      temporary_list *tempo;
2651
      tempo = (temporary_list *) gfc_getmem (sizeof (temporary_list));
2652
      tempo->temporary = ptemp1;
2653
      tempo->next = *temp;
2654
      *temp = tempo;
2655
    }
2656
 
2657
  /* Allocate temporary for !mask.  */
2658
  ntmp = allocate_temp_for_forall_nest_1 (boolean_type_node, size, block,
2659
                                          &ptemp2);
2660
  /* Record the temporary  in order to free it later.  */
2661
  if (ptemp2)
2662
    {
2663
      temporary_list *tempo;
2664
      tempo = (temporary_list *) gfc_getmem (sizeof (temporary_list));
2665
      tempo->temporary = ptemp2;
2666
      tempo->next = *temp;
2667
      *temp = tempo;
2668
    }
2669
 
2670
  /* Variable to index the temporary.  */
2671
  count = gfc_create_var (gfc_array_index_type, "count");
2672
  /* Initialize count.  */
2673
  gfc_add_modify_expr (block, count, gfc_index_zero_node);
2674
 
2675
  gfc_start_block (&body);
2676
 
2677
  gfc_init_se (&rse, NULL);
2678
  gfc_init_se (&lse, NULL);
2679
 
2680
  if (lss == gfc_ss_terminator)
2681
    {
2682
      gfc_init_block (&body1);
2683
    }
2684
  else
2685
    {
2686
      /* Initialize the loop.  */
2687
      gfc_init_loopinfo (&loop);
2688
 
2689
      /* We may need LSS to determine the shape of the expression.  */
2690
      gfc_add_ss_to_loop (&loop, lss);
2691
      gfc_add_ss_to_loop (&loop, rss);
2692
 
2693
      gfc_conv_ss_startstride (&loop);
2694
      gfc_conv_loop_setup (&loop);
2695
 
2696
      gfc_mark_ss_chain_used (rss, 1);
2697
      /* Start the loop body.  */
2698
      gfc_start_scalarized_body (&loop, &body1);
2699
 
2700
      /* Translate the expression.  */
2701
      gfc_copy_loopinfo_to_se (&rse, &loop);
2702
      rse.ss = rss;
2703
      gfc_conv_expr (&rse, me);
2704
    }
2705
  /* Form the expression of the temporary.  */
2706
  lse.expr = gfc_build_array_ref (tmp, count);
2707
  tmpexpr = gfc_build_array_ref (ntmp, count);
2708
 
2709
  /* Use the scalar assignment to fill temporary TMP.  */
2710
  tmp1 = gfc_trans_scalar_assign (&lse, &rse, me->ts.type);
2711
  gfc_add_expr_to_block (&body1, tmp1);
2712
 
2713
  /* Fill temporary NTMP.  */
2714
  tmp1 = build1 (TRUTH_NOT_EXPR, TREE_TYPE (lse.expr), lse.expr);
2715
  gfc_add_modify_expr (&body1, tmpexpr, tmp1);
2716
 
2717
 if (lss == gfc_ss_terminator)
2718
    {
2719
      gfc_add_block_to_block (&body, &body1);
2720
    }
2721
  else
2722
    {
2723
      /* Increment count.  */
2724
      tmp1 = fold_build2 (PLUS_EXPR, gfc_array_index_type, count,
2725
                          gfc_index_one_node);
2726
      gfc_add_modify_expr (&body1, count, tmp1);
2727
 
2728
      /* Generate the copying loops.  */
2729
      gfc_trans_scalarizing_loops (&loop, &body1);
2730
 
2731
      gfc_add_block_to_block (&body, &loop.pre);
2732
      gfc_add_block_to_block (&body, &loop.post);
2733
 
2734
      gfc_cleanup_loop (&loop);
2735
      /* TODO: Reuse lss and rss when copying temp->lhs.  Need to be careful
2736
         as tree nodes in SS may not be valid in different scope.  */
2737
    }
2738
 
2739
  tmp1 = gfc_finish_block (&body);
2740
  /* If the WHERE construct is inside FORALL, fill the full temporary.  */
2741
  if (nested_forall_info != NULL)
2742
    tmp1 = gfc_trans_nested_forall_loop (nested_forall_info, tmp1, 1, 1);
2743
 
2744
  gfc_add_expr_to_block (block, tmp1);
2745
 
2746
  *mask = tmp;
2747
  *nmask = ntmp;
2748
 
2749
  return tmp1;
2750
}
2751
 
2752
 
2753
/* Translate an assignment statement in a WHERE statement or construct
2754
   statement. The MASK expression is used to control which elements
2755
   of EXPR1 shall be assigned.  */
2756
 
2757
static tree
2758
gfc_trans_where_assign (gfc_expr *expr1, gfc_expr *expr2, tree mask,
2759
                        tree count1, tree count2)
2760
{
2761
  gfc_se lse;
2762
  gfc_se rse;
2763
  gfc_ss *lss;
2764
  gfc_ss *lss_section;
2765
  gfc_ss *rss;
2766
 
2767
  gfc_loopinfo loop;
2768
  tree tmp;
2769
  stmtblock_t block;
2770
  stmtblock_t body;
2771
  tree index, maskexpr, tmp1;
2772
 
2773
#if 0
2774
  /* TODO: handle this special case.
2775
     Special case a single function returning an array.  */
2776
  if (expr2->expr_type == EXPR_FUNCTION && expr2->rank > 0)
2777
    {
2778
      tmp = gfc_trans_arrayfunc_assign (expr1, expr2);
2779
      if (tmp)
2780
        return tmp;
2781
    }
2782
#endif
2783
 
2784
 /* Assignment of the form lhs = rhs.  */
2785
  gfc_start_block (&block);
2786
 
2787
  gfc_init_se (&lse, NULL);
2788
  gfc_init_se (&rse, NULL);
2789
 
2790
  /* Walk the lhs.  */
2791
  lss = gfc_walk_expr (expr1);
2792
  rss = NULL;
2793
 
2794
  /* In each where-assign-stmt, the mask-expr and the variable being
2795
     defined shall be arrays of the same shape.  */
2796
  gcc_assert (lss != gfc_ss_terminator);
2797
 
2798
  /* The assignment needs scalarization.  */
2799
  lss_section = lss;
2800
 
2801
  /* Find a non-scalar SS from the lhs.  */
2802
  while (lss_section != gfc_ss_terminator
2803
         && lss_section->type != GFC_SS_SECTION)
2804
    lss_section = lss_section->next;
2805
 
2806
  gcc_assert (lss_section != gfc_ss_terminator);
2807
 
2808
  /* Initialize the scalarizer.  */
2809
  gfc_init_loopinfo (&loop);
2810
 
2811
  /* Walk the rhs.  */
2812
  rss = gfc_walk_expr (expr2);
2813
  if (rss == gfc_ss_terminator)
2814
   {
2815
     /* The rhs is scalar.  Add a ss for the expression.  */
2816
     rss = gfc_get_ss ();
2817
     rss->next = gfc_ss_terminator;
2818
     rss->type = GFC_SS_SCALAR;
2819
     rss->expr = expr2;
2820
    }
2821
 
2822
  /* Associate the SS with the loop.  */
2823
  gfc_add_ss_to_loop (&loop, lss);
2824
  gfc_add_ss_to_loop (&loop, rss);
2825
 
2826
  /* Calculate the bounds of the scalarization.  */
2827
  gfc_conv_ss_startstride (&loop);
2828
 
2829
  /* Resolve any data dependencies in the statement.  */
2830
  gfc_conv_resolve_dependencies (&loop, lss_section, rss);
2831
 
2832
  /* Setup the scalarizing loops.  */
2833
  gfc_conv_loop_setup (&loop);
2834
 
2835
  /* Setup the gfc_se structures.  */
2836
  gfc_copy_loopinfo_to_se (&lse, &loop);
2837
  gfc_copy_loopinfo_to_se (&rse, &loop);
2838
 
2839
  rse.ss = rss;
2840
  gfc_mark_ss_chain_used (rss, 1);
2841
  if (loop.temp_ss == NULL)
2842
    {
2843
      lse.ss = lss;
2844
      gfc_mark_ss_chain_used (lss, 1);
2845
    }
2846
  else
2847
    {
2848
      lse.ss = loop.temp_ss;
2849
      gfc_mark_ss_chain_used (lss, 3);
2850
      gfc_mark_ss_chain_used (loop.temp_ss, 3);
2851
    }
2852
 
2853
  /* Start the scalarized loop body.  */
2854
  gfc_start_scalarized_body (&loop, &body);
2855
 
2856
  /* Translate the expression.  */
2857
  gfc_conv_expr (&rse, expr2);
2858
  if (lss != gfc_ss_terminator && loop.temp_ss != NULL)
2859
    {
2860
      gfc_conv_tmp_array_ref (&lse);
2861
      gfc_advance_se_ss_chain (&lse);
2862
    }
2863
  else
2864
    gfc_conv_expr (&lse, expr1);
2865
 
2866
  /* Form the mask expression according to the mask tree list.  */
2867
  index = count1;
2868
  tmp = mask;
2869
  if (tmp != NULL)
2870
    maskexpr = gfc_build_array_ref (tmp, index);
2871
  else
2872
    maskexpr = NULL;
2873
 
2874
  tmp = TREE_CHAIN (tmp);
2875
  while (tmp)
2876
    {
2877
      tmp1 = gfc_build_array_ref (tmp, index);
2878
      maskexpr = build2 (TRUTH_AND_EXPR, TREE_TYPE (tmp1), maskexpr, tmp1);
2879
      tmp = TREE_CHAIN (tmp);
2880
    }
2881
  /* Use the scalar assignment as is.  */
2882
  tmp = gfc_trans_scalar_assign (&lse, &rse, expr1->ts.type);
2883
  tmp = build3_v (COND_EXPR, maskexpr, tmp, build_empty_stmt ());
2884
 
2885
  gfc_add_expr_to_block (&body, tmp);
2886
 
2887
  if (lss == gfc_ss_terminator)
2888
    {
2889
      /* Increment count1.  */
2890
      tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
2891
                         count1, gfc_index_one_node);
2892
      gfc_add_modify_expr (&body, count1, tmp);
2893
 
2894
      /* Use the scalar assignment as is.  */
2895
      gfc_add_block_to_block (&block, &body);
2896
    }
2897
  else
2898
    {
2899
      gcc_assert (lse.ss == gfc_ss_terminator
2900
                  && rse.ss == gfc_ss_terminator);
2901
 
2902
      if (loop.temp_ss != NULL)
2903
        {
2904
          /* Increment count1 before finish the main body of a scalarized
2905
             expression.  */
2906
          tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
2907
                             count1, gfc_index_one_node);
2908
          gfc_add_modify_expr (&body, count1, tmp);
2909
          gfc_trans_scalarized_loop_boundary (&loop, &body);
2910
 
2911
          /* We need to copy the temporary to the actual lhs.  */
2912
          gfc_init_se (&lse, NULL);
2913
          gfc_init_se (&rse, NULL);
2914
          gfc_copy_loopinfo_to_se (&lse, &loop);
2915
          gfc_copy_loopinfo_to_se (&rse, &loop);
2916
 
2917
          rse.ss = loop.temp_ss;
2918
          lse.ss = lss;
2919
 
2920
          gfc_conv_tmp_array_ref (&rse);
2921
          gfc_advance_se_ss_chain (&rse);
2922
          gfc_conv_expr (&lse, expr1);
2923
 
2924
          gcc_assert (lse.ss == gfc_ss_terminator
2925
                      && rse.ss == gfc_ss_terminator);
2926
 
2927
          /* Form the mask expression according to the mask tree list.  */
2928
          index = count2;
2929
          tmp = mask;
2930
          if (tmp != NULL)
2931
            maskexpr = gfc_build_array_ref (tmp, index);
2932
          else
2933
            maskexpr = NULL;
2934
 
2935
          tmp = TREE_CHAIN (tmp);
2936
          while (tmp)
2937
            {
2938
              tmp1 = gfc_build_array_ref (tmp, index);
2939
              maskexpr = build2 (TRUTH_AND_EXPR, TREE_TYPE (tmp1),
2940
                                 maskexpr, tmp1);
2941
              tmp = TREE_CHAIN (tmp);
2942
            }
2943
          /* Use the scalar assignment as is.  */
2944
          tmp = gfc_trans_scalar_assign (&lse, &rse, expr1->ts.type);
2945
          tmp = build3_v (COND_EXPR, maskexpr, tmp, build_empty_stmt ());
2946
          gfc_add_expr_to_block (&body, tmp);
2947
 
2948
          /* Increment count2.  */
2949
          tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
2950
                             count2, gfc_index_one_node);
2951
          gfc_add_modify_expr (&body, count2, tmp);
2952
        }
2953
      else
2954
        {
2955
          /* Increment count1.  */
2956
          tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
2957
                             count1, gfc_index_one_node);
2958
          gfc_add_modify_expr (&body, count1, tmp);
2959
        }
2960
 
2961
      /* Generate the copying loops.  */
2962
      gfc_trans_scalarizing_loops (&loop, &body);
2963
 
2964
      /* Wrap the whole thing up.  */
2965
      gfc_add_block_to_block (&block, &loop.pre);
2966
      gfc_add_block_to_block (&block, &loop.post);
2967
      gfc_cleanup_loop (&loop);
2968
    }
2969
 
2970
  return gfc_finish_block (&block);
2971
}
2972
 
2973
 
2974
/* Translate the WHERE construct or statement.
2975
   This function can be called iteratively to translate the nested WHERE
2976
   construct or statement.
2977
   MASK is the control mask, and PMASK is the pending control mask.
2978
   TEMP records the temporary address which must be freed later.  */
2979
 
2980
static void
2981
gfc_trans_where_2 (gfc_code * code, tree mask, tree pmask,
2982
                   forall_info * nested_forall_info, stmtblock_t * block,
2983
                   temporary_list ** temp)
2984
{
2985
  gfc_expr *expr1;
2986
  gfc_expr *expr2;
2987
  gfc_code *cblock;
2988
  gfc_code *cnext;
2989
  tree tmp, tmp1, tmp2;
2990
  tree count1, count2;
2991
  tree mask_copy;
2992
  int need_temp;
2993
 
2994
  /* the WHERE statement or the WHERE construct statement.  */
2995
  cblock = code->block;
2996
  while (cblock)
2997
    {
2998
      /* Has mask-expr.  */
2999
      if (cblock->expr)
3000
        {
3001
          /* Ensure that the WHERE mask be evaluated only once.  */
3002
          tmp2 = gfc_evaluate_where_mask (cblock->expr, nested_forall_info,
3003
                                          &tmp, &tmp1, temp, block);
3004
 
3005
          /* Set the control mask and the pending control mask.  */
3006
          /* It's a where-stmt.  */
3007
          if (mask == NULL)
3008
            {
3009
              mask = tmp;
3010
              pmask = tmp1;
3011
            }
3012
          /* It's a nested where-stmt.  */
3013
          else if (mask && pmask == NULL)
3014
            {
3015
              tree tmp2;
3016
              /* Use the TREE_CHAIN to list the masks.  */
3017
              tmp2 = copy_list (mask);
3018
              pmask = chainon (mask, tmp1);
3019
              mask = chainon (tmp2, tmp);
3020
            }
3021
          /* It's a masked-elsewhere-stmt.  */
3022
          else if (mask && cblock->expr)
3023
            {
3024
              tree tmp2;
3025
              tmp2 = copy_list (pmask);
3026
 
3027
              mask = pmask;
3028
              tmp2 = chainon (tmp2, tmp);
3029
              pmask = chainon (mask, tmp1);
3030
              mask = tmp2;
3031
            }
3032
        }
3033
      /* It's a elsewhere-stmt. No mask-expr is present.  */
3034
      else
3035
        mask = pmask;
3036
 
3037
      /* Get the assignment statement of a WHERE statement, or the first
3038
         statement in where-body-construct of a WHERE construct.  */
3039
      cnext = cblock->next;
3040
      while (cnext)
3041
        {
3042
          switch (cnext->op)
3043
            {
3044
            /* WHERE assignment statement.  */
3045
            case EXEC_ASSIGN:
3046
              expr1 = cnext->expr;
3047
              expr2 = cnext->expr2;
3048
              if (nested_forall_info != NULL)
3049
                {
3050
                  int nvar;
3051
                  gfc_expr **varexpr;
3052
 
3053
                  nvar = nested_forall_info->nvar;
3054
                  varexpr = (gfc_expr **)
3055
                            gfc_getmem (nvar * sizeof (gfc_expr *));
3056
                  need_temp = gfc_check_dependency (expr1, expr2, varexpr,
3057
                                                    nvar);
3058
                  if (need_temp)
3059
                    gfc_trans_assign_need_temp (expr1, expr2, mask,
3060
                                                nested_forall_info, block);
3061
                  else
3062
                    {
3063
                      /* Variables to control maskexpr.  */
3064
                      count1 = gfc_create_var (gfc_array_index_type, "count1");
3065
                      count2 = gfc_create_var (gfc_array_index_type, "count2");
3066
                      gfc_add_modify_expr (block, count1, gfc_index_zero_node);
3067
                      gfc_add_modify_expr (block, count2, gfc_index_zero_node);
3068
 
3069
                      tmp = gfc_trans_where_assign (expr1, expr2, mask, count1,
3070
                                                    count2);
3071
 
3072
                      tmp = gfc_trans_nested_forall_loop (nested_forall_info,
3073
                                                          tmp, 1, 1);
3074
                      gfc_add_expr_to_block (block, tmp);
3075
                    }
3076
                }
3077
              else
3078
                {
3079
                  /* Variables to control maskexpr.  */
3080
                  count1 = gfc_create_var (gfc_array_index_type, "count1");
3081
                  count2 = gfc_create_var (gfc_array_index_type, "count2");
3082
                  gfc_add_modify_expr (block, count1, gfc_index_zero_node);
3083
                  gfc_add_modify_expr (block, count2, gfc_index_zero_node);
3084
 
3085
                  tmp = gfc_trans_where_assign (expr1, expr2, mask, count1,
3086
                                                count2);
3087
                  gfc_add_expr_to_block (block, tmp);
3088
 
3089
                }
3090
              break;
3091
 
3092
            /* WHERE or WHERE construct is part of a where-body-construct.  */
3093
            case EXEC_WHERE:
3094
              /* Ensure that MASK is not modified by next gfc_trans_where_2.  */
3095
              mask_copy = copy_list (mask);
3096
              gfc_trans_where_2 (cnext, mask_copy, NULL, nested_forall_info,
3097
                                 block, temp);
3098
              break;
3099
 
3100
            default:
3101
              gcc_unreachable ();
3102
            }
3103
 
3104
         /* The next statement within the same where-body-construct.  */
3105
         cnext = cnext->next;
3106
       }
3107
    /* The next masked-elsewhere-stmt, elsewhere-stmt, or end-where-stmt.  */
3108
    cblock = cblock->block;
3109
  }
3110
}
3111
 
3112
 
3113
/* As the WHERE or WHERE construct statement can be nested, we call
3114
   gfc_trans_where_2 to do the translation, and pass the initial
3115
   NULL values for both the control mask and the pending control mask.  */
3116
 
3117
tree
3118
gfc_trans_where (gfc_code * code)
3119
{
3120
  stmtblock_t block;
3121
  temporary_list *temp, *p;
3122
  tree args;
3123
  tree tmp;
3124
 
3125
  gfc_start_block (&block);
3126
  temp = NULL;
3127
 
3128
  gfc_trans_where_2 (code, NULL, NULL, NULL, &block, &temp);
3129
 
3130
  /* Add calls to free temporaries which were dynamically allocated.  */
3131
  while (temp)
3132
    {
3133
      args = gfc_chainon_list (NULL_TREE, temp->temporary);
3134
      tmp = gfc_build_function_call (gfor_fndecl_internal_free, args);
3135
      gfc_add_expr_to_block (&block, tmp);
3136
 
3137
      p = temp;
3138
      temp = temp->next;
3139
      gfc_free (p);
3140
    }
3141
  return gfc_finish_block (&block);
3142
}
3143
 
3144
 
3145
/* CYCLE a DO loop. The label decl has already been created by
3146
   gfc_trans_do(), it's in TREE_PURPOSE (backend_decl) of the gfc_code
3147
   node at the head of the loop. We must mark the label as used.  */
3148
 
3149
tree
3150
gfc_trans_cycle (gfc_code * code)
3151
{
3152
  tree cycle_label;
3153
 
3154
  cycle_label = TREE_PURPOSE (code->ext.whichloop->backend_decl);
3155
  TREE_USED (cycle_label) = 1;
3156
  return build1_v (GOTO_EXPR, cycle_label);
3157
}
3158
 
3159
 
3160
/* EXIT a DO loop. Similar to CYCLE, but now the label is in
3161
   TREE_VALUE (backend_decl) of the gfc_code node at the head of the
3162
   loop.  */
3163
 
3164
tree
3165
gfc_trans_exit (gfc_code * code)
3166
{
3167
  tree exit_label;
3168
 
3169
  exit_label = TREE_VALUE (code->ext.whichloop->backend_decl);
3170
  TREE_USED (exit_label) = 1;
3171
  return build1_v (GOTO_EXPR, exit_label);
3172
}
3173
 
3174
 
3175
/* Translate the ALLOCATE statement.  */
3176
 
3177
tree
3178
gfc_trans_allocate (gfc_code * code)
3179
{
3180
  gfc_alloc *al;
3181
  gfc_expr *expr;
3182
  gfc_se se;
3183
  tree tmp;
3184
  tree parm;
3185
  tree stat;
3186
  tree pstat;
3187
  tree error_label;
3188
  stmtblock_t block;
3189
 
3190
  if (!code->ext.alloc_list)
3191
    return NULL_TREE;
3192
 
3193
  gfc_start_block (&block);
3194
 
3195
  if (code->expr)
3196
    {
3197
      tree gfc_int4_type_node = gfc_get_int_type (4);
3198
 
3199
      stat = gfc_create_var (gfc_int4_type_node, "stat");
3200
      pstat = gfc_build_addr_expr (NULL, stat);
3201
 
3202
      error_label = gfc_build_label_decl (NULL_TREE);
3203
      TREE_USED (error_label) = 1;
3204
    }
3205
  else
3206
    {
3207
      pstat = integer_zero_node;
3208
      stat = error_label = NULL_TREE;
3209
    }
3210
 
3211
 
3212
  for (al = code->ext.alloc_list; al != NULL; al = al->next)
3213
    {
3214
      expr = al->expr;
3215
 
3216
      gfc_init_se (&se, NULL);
3217
      gfc_start_block (&se.pre);
3218
 
3219
      se.want_pointer = 1;
3220
      se.descriptor_only = 1;
3221
      gfc_conv_expr (&se, expr);
3222
 
3223
      if (!gfc_array_allocate (&se, expr, pstat))
3224
        {
3225
          /* A scalar or derived type.  */
3226
          tree val;
3227
 
3228
          val = gfc_create_var (ppvoid_type_node, "ptr");
3229
          tmp = gfc_build_addr_expr (ppvoid_type_node, se.expr);
3230
          gfc_add_modify_expr (&se.pre, val, tmp);
3231
 
3232
          tmp = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (se.expr)));
3233
 
3234
          if (expr->ts.type == BT_CHARACTER && tmp == NULL_TREE)
3235
            tmp = se.string_length;
3236
 
3237
          parm = gfc_chainon_list (NULL_TREE, val);
3238
          parm = gfc_chainon_list (parm, tmp);
3239
          parm = gfc_chainon_list (parm, pstat);
3240
          tmp = gfc_build_function_call (gfor_fndecl_allocate, parm);
3241
          gfc_add_expr_to_block (&se.pre, tmp);
3242
 
3243
          if (code->expr)
3244
            {
3245
              tmp = build1_v (GOTO_EXPR, error_label);
3246
              parm =
3247
                build2 (NE_EXPR, boolean_type_node, stat, integer_zero_node);
3248
              tmp = build3_v (COND_EXPR, parm, tmp, build_empty_stmt ());
3249
              gfc_add_expr_to_block (&se.pre, tmp);
3250
            }
3251
        }
3252
 
3253
      tmp = gfc_finish_block (&se.pre);
3254
      gfc_add_expr_to_block (&block, tmp);
3255
    }
3256
 
3257
  /* Assign the value to the status variable.  */
3258
  if (code->expr)
3259
    {
3260
      tmp = build1_v (LABEL_EXPR, error_label);
3261
      gfc_add_expr_to_block (&block, tmp);
3262
 
3263
      gfc_init_se (&se, NULL);
3264
      gfc_conv_expr_lhs (&se, code->expr);
3265
      tmp = convert (TREE_TYPE (se.expr), stat);
3266
      gfc_add_modify_expr (&block, se.expr, tmp);
3267
    }
3268
 
3269
  return gfc_finish_block (&block);
3270
}
3271
 
3272
 
3273
/* Translate a DEALLOCATE statement.
3274
   There are two cases within the for loop:
3275
   (1) deallocate(a1, a2, a3) is translated into the following sequence
3276
       _gfortran_deallocate(a1, 0B)
3277
       _gfortran_deallocate(a2, 0B)
3278
       _gfortran_deallocate(a3, 0B)
3279
       where the STAT= variable is passed a NULL pointer.
3280
   (2) deallocate(a1, a2, a3, stat=i) is translated into the following
3281
       astat = 0
3282
       _gfortran_deallocate(a1, &stat)
3283
       astat = astat + stat
3284
       _gfortran_deallocate(a2, &stat)
3285
       astat = astat + stat
3286
       _gfortran_deallocate(a3, &stat)
3287
       astat = astat + stat
3288
    In case (1), we simply return at the end of the for loop.  In case (2)
3289
    we set STAT= astat.  */
3290
tree
3291
gfc_trans_deallocate (gfc_code * code)
3292
{
3293
  gfc_se se;
3294
  gfc_alloc *al;
3295
  gfc_expr *expr;
3296
  tree apstat, astat, parm, pstat, stat, tmp, type, var;
3297
  stmtblock_t block;
3298
 
3299
  gfc_start_block (&block);
3300
 
3301
  /* Set up the optional STAT= */
3302
  if (code->expr)
3303
    {
3304
      tree gfc_int4_type_node = gfc_get_int_type (4);
3305
 
3306
      /* Variable used with the library call.  */
3307
      stat = gfc_create_var (gfc_int4_type_node, "stat");
3308
      pstat = gfc_build_addr_expr (NULL, stat);
3309
 
3310
      /* Running total of possible deallocation failures.  */
3311
      astat = gfc_create_var (gfc_int4_type_node, "astat");
3312
      apstat = gfc_build_addr_expr (NULL, astat);
3313
 
3314
      /* Initialize astat to 0.  */
3315
      gfc_add_modify_expr (&block, astat, build_int_cst (TREE_TYPE (astat), 0));
3316
    }
3317
  else
3318
    {
3319
      pstat = apstat = null_pointer_node;
3320
      stat = astat = NULL_TREE;
3321
    }
3322
 
3323
  for (al = code->ext.alloc_list; al != NULL; al = al->next)
3324
    {
3325
      expr = al->expr;
3326
      gcc_assert (expr->expr_type == EXPR_VARIABLE);
3327
 
3328
      gfc_init_se (&se, NULL);
3329
      gfc_start_block (&se.pre);
3330
 
3331
      se.want_pointer = 1;
3332
      se.descriptor_only = 1;
3333
      gfc_conv_expr (&se, expr);
3334
 
3335
      if (expr->rank)
3336
        tmp = gfc_array_deallocate (se.expr, pstat);
3337
      else
3338
        {
3339
          type = build_pointer_type (TREE_TYPE (se.expr));
3340
          var = gfc_create_var (type, "ptr");
3341
          tmp = gfc_build_addr_expr (type, se.expr);
3342
          gfc_add_modify_expr (&se.pre, var, tmp);
3343
 
3344
          parm = gfc_chainon_list (NULL_TREE, var);
3345
          parm = gfc_chainon_list (parm, pstat);
3346
          tmp = gfc_build_function_call (gfor_fndecl_deallocate, parm);
3347
        }
3348
 
3349
      gfc_add_expr_to_block (&se.pre, tmp);
3350
 
3351
      /* Keep track of the number of failed deallocations by adding stat
3352
         of the last deallocation to the running total.  */
3353
      if (code->expr)
3354
        {
3355
          apstat = build2 (PLUS_EXPR, TREE_TYPE (stat), astat, stat);
3356
          gfc_add_modify_expr (&se.pre, astat, apstat);
3357
        }
3358
 
3359
      tmp = gfc_finish_block (&se.pre);
3360
      gfc_add_expr_to_block (&block, tmp);
3361
 
3362
    }
3363
 
3364
  /* Assign the value to the status variable.  */
3365
  if (code->expr)
3366
    {
3367
      gfc_init_se (&se, NULL);
3368
      gfc_conv_expr_lhs (&se, code->expr);
3369
      tmp = convert (TREE_TYPE (se.expr), astat);
3370
      gfc_add_modify_expr (&block, se.expr, tmp);
3371
    }
3372
 
3373
  return gfc_finish_block (&block);
3374
}
3375
 

powered by: WebSVN 2.1.0

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