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