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