Merge current set of OpenACC changes from gomp-4_0-branch.
[gcc.git] / gcc / fortran / trans-stmt.c
1 /* Statement translation -- generate GCC trees from gfc_code.
2 Copyright (C) 2002-2015 Free Software Foundation, Inc.
3 Contributed by Paul Brook <paul@nowt.org>
4 and Steven Bosscher <s.bosscher@student.tudelft.nl>
5
6 This file is part of GCC.
7
8 GCC is free software; you can redistribute it and/or modify it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 3, or (at your option) any later
11 version.
12
13 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING3. If not see
20 <http://www.gnu.org/licenses/>. */
21
22
23 #include "config.h"
24 #include "system.h"
25 #include "coretypes.h"
26 #include "hash-set.h"
27 #include "machmode.h"
28 #include "vec.h"
29 #include "double-int.h"
30 #include "input.h"
31 #include "alias.h"
32 #include "symtab.h"
33 #include "options.h"
34 #include "wide-int.h"
35 #include "inchash.h"
36 #include "tree.h"
37 #include "fold-const.h"
38 #include "stringpool.h"
39 #include "gfortran.h"
40 #include "flags.h"
41 #include "trans.h"
42 #include "trans-stmt.h"
43 #include "trans-types.h"
44 #include "trans-array.h"
45 #include "trans-const.h"
46 #include "arith.h"
47 #include "dependency.h"
48 #include "ggc.h"
49
50 typedef struct iter_info
51 {
52 tree var;
53 tree start;
54 tree end;
55 tree step;
56 struct iter_info *next;
57 }
58 iter_info;
59
60 typedef struct forall_info
61 {
62 iter_info *this_loop;
63 tree mask;
64 tree maskindex;
65 int nvar;
66 tree size;
67 struct forall_info *prev_nest;
68 bool do_concurrent;
69 }
70 forall_info;
71
72 static void gfc_trans_where_2 (gfc_code *, tree, bool,
73 forall_info *, stmtblock_t *);
74
75 /* Translate a F95 label number to a LABEL_EXPR. */
76
77 tree
78 gfc_trans_label_here (gfc_code * code)
79 {
80 return build1_v (LABEL_EXPR, gfc_get_label_decl (code->here));
81 }
82
83
84 /* Given a variable expression which has been ASSIGNed to, find the decl
85 containing the auxiliary variables. For variables in common blocks this
86 is a field_decl. */
87
88 void
89 gfc_conv_label_variable (gfc_se * se, gfc_expr * expr)
90 {
91 gcc_assert (expr->symtree->n.sym->attr.assign == 1);
92 gfc_conv_expr (se, expr);
93 /* Deals with variable in common block. Get the field declaration. */
94 if (TREE_CODE (se->expr) == COMPONENT_REF)
95 se->expr = TREE_OPERAND (se->expr, 1);
96 /* Deals with dummy argument. Get the parameter declaration. */
97 else if (TREE_CODE (se->expr) == INDIRECT_REF)
98 se->expr = TREE_OPERAND (se->expr, 0);
99 }
100
101 /* Translate a label assignment statement. */
102
103 tree
104 gfc_trans_label_assign (gfc_code * code)
105 {
106 tree label_tree;
107 gfc_se se;
108 tree len;
109 tree addr;
110 tree len_tree;
111 int label_len;
112
113 /* Start a new block. */
114 gfc_init_se (&se, NULL);
115 gfc_start_block (&se.pre);
116 gfc_conv_label_variable (&se, code->expr1);
117
118 len = GFC_DECL_STRING_LEN (se.expr);
119 addr = GFC_DECL_ASSIGN_ADDR (se.expr);
120
121 label_tree = gfc_get_label_decl (code->label1);
122
123 if (code->label1->defined == ST_LABEL_TARGET
124 || code->label1->defined == ST_LABEL_DO_TARGET)
125 {
126 label_tree = gfc_build_addr_expr (pvoid_type_node, label_tree);
127 len_tree = integer_minus_one_node;
128 }
129 else
130 {
131 gfc_expr *format = code->label1->format;
132
133 label_len = format->value.character.length;
134 len_tree = build_int_cst (gfc_charlen_type_node, label_len);
135 label_tree = gfc_build_wide_string_const (format->ts.kind, label_len + 1,
136 format->value.character.string);
137 label_tree = gfc_build_addr_expr (pvoid_type_node, label_tree);
138 }
139
140 gfc_add_modify (&se.pre, len, len_tree);
141 gfc_add_modify (&se.pre, addr, label_tree);
142
143 return gfc_finish_block (&se.pre);
144 }
145
146 /* Translate a GOTO statement. */
147
148 tree
149 gfc_trans_goto (gfc_code * code)
150 {
151 locus loc = code->loc;
152 tree assigned_goto;
153 tree target;
154 tree tmp;
155 gfc_se se;
156
157 if (code->label1 != NULL)
158 return build1_v (GOTO_EXPR, gfc_get_label_decl (code->label1));
159
160 /* ASSIGNED GOTO. */
161 gfc_init_se (&se, NULL);
162 gfc_start_block (&se.pre);
163 gfc_conv_label_variable (&se, code->expr1);
164 tmp = GFC_DECL_STRING_LEN (se.expr);
165 tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, tmp,
166 build_int_cst (TREE_TYPE (tmp), -1));
167 gfc_trans_runtime_check (true, false, tmp, &se.pre, &loc,
168 "Assigned label is not a target label");
169
170 assigned_goto = GFC_DECL_ASSIGN_ADDR (se.expr);
171
172 /* We're going to ignore a label list. It does not really change the
173 statement's semantics (because it is just a further restriction on
174 what's legal code); before, we were comparing label addresses here, but
175 that's a very fragile business and may break with optimization. So
176 just ignore it. */
177
178 target = fold_build1_loc (input_location, GOTO_EXPR, void_type_node,
179 assigned_goto);
180 gfc_add_expr_to_block (&se.pre, target);
181 return gfc_finish_block (&se.pre);
182 }
183
184
185 /* Translate an ENTRY statement. Just adds a label for this entry point. */
186 tree
187 gfc_trans_entry (gfc_code * code)
188 {
189 return build1_v (LABEL_EXPR, code->ext.entry->label);
190 }
191
192
193 /* Replace a gfc_ss structure by another both in the gfc_se struct
194 and the gfc_loopinfo struct. This is used in gfc_conv_elemental_dependencies
195 to replace a variable ss by the corresponding temporary. */
196
197 static void
198 replace_ss (gfc_se *se, gfc_ss *old_ss, gfc_ss *new_ss)
199 {
200 gfc_ss **sess, **loopss;
201
202 /* The old_ss is a ss for a single variable. */
203 gcc_assert (old_ss->info->type == GFC_SS_SECTION);
204
205 for (sess = &(se->ss); *sess != gfc_ss_terminator; sess = &((*sess)->next))
206 if (*sess == old_ss)
207 break;
208 gcc_assert (*sess != gfc_ss_terminator);
209
210 *sess = new_ss;
211 new_ss->next = old_ss->next;
212
213
214 for (loopss = &(se->loop->ss); *loopss != gfc_ss_terminator;
215 loopss = &((*loopss)->loop_chain))
216 if (*loopss == old_ss)
217 break;
218 gcc_assert (*loopss != gfc_ss_terminator);
219
220 *loopss = new_ss;
221 new_ss->loop_chain = old_ss->loop_chain;
222 new_ss->loop = old_ss->loop;
223
224 gfc_free_ss (old_ss);
225 }
226
227
228 /* Check for dependencies between INTENT(IN) and INTENT(OUT) arguments of
229 elemental subroutines. Make temporaries for output arguments if any such
230 dependencies are found. Output arguments are chosen because internal_unpack
231 can be used, as is, to copy the result back to the variable. */
232 static void
233 gfc_conv_elemental_dependencies (gfc_se * se, gfc_se * loopse,
234 gfc_symbol * sym, gfc_actual_arglist * arg,
235 gfc_dep_check check_variable)
236 {
237 gfc_actual_arglist *arg0;
238 gfc_expr *e;
239 gfc_formal_arglist *formal;
240 gfc_se parmse;
241 gfc_ss *ss;
242 gfc_symbol *fsym;
243 tree data;
244 tree size;
245 tree tmp;
246
247 if (loopse->ss == NULL)
248 return;
249
250 ss = loopse->ss;
251 arg0 = arg;
252 formal = gfc_sym_get_dummy_args (sym);
253
254 /* Loop over all the arguments testing for dependencies. */
255 for (; arg != NULL; arg = arg->next, formal = formal ? formal->next : NULL)
256 {
257 e = arg->expr;
258 if (e == NULL)
259 continue;
260
261 /* Obtain the info structure for the current argument. */
262 for (ss = loopse->ss; ss && ss != gfc_ss_terminator; ss = ss->next)
263 if (ss->info->expr == e)
264 break;
265
266 /* If there is a dependency, create a temporary and use it
267 instead of the variable. */
268 fsym = formal ? formal->sym : NULL;
269 if (e->expr_type == EXPR_VARIABLE
270 && e->rank && fsym
271 && fsym->attr.intent != INTENT_IN
272 && gfc_check_fncall_dependency (e, fsym->attr.intent,
273 sym, arg0, check_variable))
274 {
275 tree initial, temptype;
276 stmtblock_t temp_post;
277 gfc_ss *tmp_ss;
278
279 tmp_ss = gfc_get_array_ss (gfc_ss_terminator, NULL, ss->dimen,
280 GFC_SS_SECTION);
281 gfc_mark_ss_chain_used (tmp_ss, 1);
282 tmp_ss->info->expr = ss->info->expr;
283 replace_ss (loopse, ss, tmp_ss);
284
285 /* Obtain the argument descriptor for unpacking. */
286 gfc_init_se (&parmse, NULL);
287 parmse.want_pointer = 1;
288 gfc_conv_expr_descriptor (&parmse, e);
289 gfc_add_block_to_block (&se->pre, &parmse.pre);
290
291 /* If we've got INTENT(INOUT) or a derived type with INTENT(OUT),
292 initialize the array temporary with a copy of the values. */
293 if (fsym->attr.intent == INTENT_INOUT
294 || (fsym->ts.type ==BT_DERIVED
295 && fsym->attr.intent == INTENT_OUT))
296 initial = parmse.expr;
297 /* For class expressions, we always initialize with the copy of
298 the values. */
299 else if (e->ts.type == BT_CLASS)
300 initial = parmse.expr;
301 else
302 initial = NULL_TREE;
303
304 if (e->ts.type != BT_CLASS)
305 {
306 /* Find the type of the temporary to create; we don't use the type
307 of e itself as this breaks for subcomponent-references in e
308 (where the type of e is that of the final reference, but
309 parmse.expr's type corresponds to the full derived-type). */
310 /* TODO: Fix this somehow so we don't need a temporary of the whole
311 array but instead only the components referenced. */
312 temptype = TREE_TYPE (parmse.expr); /* Pointer to descriptor. */
313 gcc_assert (TREE_CODE (temptype) == POINTER_TYPE);
314 temptype = TREE_TYPE (temptype);
315 temptype = gfc_get_element_type (temptype);
316 }
317
318 else
319 /* For class arrays signal that the size of the dynamic type has to
320 be obtained from the vtable, using the 'initial' expression. */
321 temptype = NULL_TREE;
322
323 /* Generate the temporary. Cleaning up the temporary should be the
324 very last thing done, so we add the code to a new block and add it
325 to se->post as last instructions. */
326 size = gfc_create_var (gfc_array_index_type, NULL);
327 data = gfc_create_var (pvoid_type_node, NULL);
328 gfc_init_block (&temp_post);
329 tmp = gfc_trans_create_temp_array (&se->pre, &temp_post, tmp_ss,
330 temptype, initial, false, true,
331 false, &arg->expr->where);
332 gfc_add_modify (&se->pre, size, tmp);
333 tmp = fold_convert (pvoid_type_node, tmp_ss->info->data.array.data);
334 gfc_add_modify (&se->pre, data, tmp);
335
336 /* Update other ss' delta. */
337 gfc_set_delta (loopse->loop);
338
339 /* Copy the result back using unpack..... */
340 if (e->ts.type != BT_CLASS)
341 tmp = build_call_expr_loc (input_location,
342 gfor_fndecl_in_unpack, 2, parmse.expr, data);
343 else
344 {
345 /* ... except for class results where the copy is
346 unconditional. */
347 tmp = build_fold_indirect_ref_loc (input_location, parmse.expr);
348 tmp = gfc_conv_descriptor_data_get (tmp);
349 tmp = build_call_expr_loc (input_location,
350 builtin_decl_explicit (BUILT_IN_MEMCPY),
351 3, tmp, data,
352 fold_convert (size_type_node, size));
353 }
354 gfc_add_expr_to_block (&se->post, tmp);
355
356 /* parmse.pre is already added above. */
357 gfc_add_block_to_block (&se->post, &parmse.post);
358 gfc_add_block_to_block (&se->post, &temp_post);
359 }
360 }
361 }
362
363
364 /* Get the interface symbol for the procedure corresponding to the given call.
365 We can't get the procedure symbol directly as we have to handle the case
366 of (deferred) type-bound procedures. */
367
368 static gfc_symbol *
369 get_proc_ifc_for_call (gfc_code *c)
370 {
371 gfc_symbol *sym;
372
373 gcc_assert (c->op == EXEC_ASSIGN_CALL || c->op == EXEC_CALL);
374
375 sym = gfc_get_proc_ifc_for_expr (c->expr1);
376
377 /* Fall back/last resort try. */
378 if (sym == NULL)
379 sym = c->resolved_sym;
380
381 return sym;
382 }
383
384
385 /* Translate the CALL statement. Builds a call to an F95 subroutine. */
386
387 tree
388 gfc_trans_call (gfc_code * code, bool dependency_check,
389 tree mask, tree count1, bool invert)
390 {
391 gfc_se se;
392 gfc_ss * ss;
393 int has_alternate_specifier;
394 gfc_dep_check check_variable;
395 tree index = NULL_TREE;
396 tree maskexpr = NULL_TREE;
397 tree tmp;
398
399 /* A CALL starts a new block because the actual arguments may have to
400 be evaluated first. */
401 gfc_init_se (&se, NULL);
402 gfc_start_block (&se.pre);
403
404 gcc_assert (code->resolved_sym);
405
406 ss = gfc_ss_terminator;
407 if (code->resolved_sym->attr.elemental)
408 ss = gfc_walk_elemental_function_args (ss, code->ext.actual,
409 get_proc_ifc_for_call (code),
410 GFC_SS_REFERENCE);
411
412 /* Is not an elemental subroutine call with array valued arguments. */
413 if (ss == gfc_ss_terminator)
414 {
415
416 /* Translate the call. */
417 has_alternate_specifier
418 = gfc_conv_procedure_call (&se, code->resolved_sym, code->ext.actual,
419 code->expr1, NULL);
420
421 /* A subroutine without side-effect, by definition, does nothing! */
422 TREE_SIDE_EFFECTS (se.expr) = 1;
423
424 /* Chain the pieces together and return the block. */
425 if (has_alternate_specifier)
426 {
427 gfc_code *select_code;
428 gfc_symbol *sym;
429 select_code = code->next;
430 gcc_assert(select_code->op == EXEC_SELECT);
431 sym = select_code->expr1->symtree->n.sym;
432 se.expr = convert (gfc_typenode_for_spec (&sym->ts), se.expr);
433 if (sym->backend_decl == NULL)
434 sym->backend_decl = gfc_get_symbol_decl (sym);
435 gfc_add_modify (&se.pre, sym->backend_decl, se.expr);
436 }
437 else
438 gfc_add_expr_to_block (&se.pre, se.expr);
439
440 gfc_add_block_to_block (&se.pre, &se.post);
441 }
442
443 else
444 {
445 /* An elemental subroutine call with array valued arguments has
446 to be scalarized. */
447 gfc_loopinfo loop;
448 stmtblock_t body;
449 stmtblock_t block;
450 gfc_se loopse;
451 gfc_se depse;
452
453 /* gfc_walk_elemental_function_args renders the ss chain in the
454 reverse order to the actual argument order. */
455 ss = gfc_reverse_ss (ss);
456
457 /* Initialize the loop. */
458 gfc_init_se (&loopse, NULL);
459 gfc_init_loopinfo (&loop);
460 gfc_add_ss_to_loop (&loop, ss);
461
462 gfc_conv_ss_startstride (&loop);
463 /* TODO: gfc_conv_loop_setup generates a temporary for vector
464 subscripts. This could be prevented in the elemental case
465 as temporaries are handled separatedly
466 (below in gfc_conv_elemental_dependencies). */
467 gfc_conv_loop_setup (&loop, &code->expr1->where);
468 gfc_mark_ss_chain_used (ss, 1);
469
470 /* Convert the arguments, checking for dependencies. */
471 gfc_copy_loopinfo_to_se (&loopse, &loop);
472 loopse.ss = ss;
473
474 /* For operator assignment, do dependency checking. */
475 if (dependency_check)
476 check_variable = ELEM_CHECK_VARIABLE;
477 else
478 check_variable = ELEM_DONT_CHECK_VARIABLE;
479
480 gfc_init_se (&depse, NULL);
481 gfc_conv_elemental_dependencies (&depse, &loopse, code->resolved_sym,
482 code->ext.actual, check_variable);
483
484 gfc_add_block_to_block (&loop.pre, &depse.pre);
485 gfc_add_block_to_block (&loop.post, &depse.post);
486
487 /* Generate the loop body. */
488 gfc_start_scalarized_body (&loop, &body);
489 gfc_init_block (&block);
490
491 if (mask && count1)
492 {
493 /* Form the mask expression according to the mask. */
494 index = count1;
495 maskexpr = gfc_build_array_ref (mask, index, NULL);
496 if (invert)
497 maskexpr = fold_build1_loc (input_location, TRUTH_NOT_EXPR,
498 TREE_TYPE (maskexpr), maskexpr);
499 }
500
501 /* Add the subroutine call to the block. */
502 gfc_conv_procedure_call (&loopse, code->resolved_sym,
503 code->ext.actual, code->expr1,
504 NULL);
505
506 if (mask && count1)
507 {
508 tmp = build3_v (COND_EXPR, maskexpr, loopse.expr,
509 build_empty_stmt (input_location));
510 gfc_add_expr_to_block (&loopse.pre, tmp);
511 tmp = fold_build2_loc (input_location, PLUS_EXPR,
512 gfc_array_index_type,
513 count1, gfc_index_one_node);
514 gfc_add_modify (&loopse.pre, count1, tmp);
515 }
516 else
517 gfc_add_expr_to_block (&loopse.pre, loopse.expr);
518
519 gfc_add_block_to_block (&block, &loopse.pre);
520 gfc_add_block_to_block (&block, &loopse.post);
521
522 /* Finish up the loop block and the loop. */
523 gfc_add_expr_to_block (&body, gfc_finish_block (&block));
524 gfc_trans_scalarizing_loops (&loop, &body);
525 gfc_add_block_to_block (&se.pre, &loop.pre);
526 gfc_add_block_to_block (&se.pre, &loop.post);
527 gfc_add_block_to_block (&se.pre, &se.post);
528 gfc_cleanup_loop (&loop);
529 }
530
531 return gfc_finish_block (&se.pre);
532 }
533
534
535 /* Translate the RETURN statement. */
536
537 tree
538 gfc_trans_return (gfc_code * code)
539 {
540 if (code->expr1)
541 {
542 gfc_se se;
543 tree tmp;
544 tree result;
545
546 /* If code->expr is not NULL, this return statement must appear
547 in a subroutine and current_fake_result_decl has already
548 been generated. */
549
550 result = gfc_get_fake_result_decl (NULL, 0);
551 if (!result)
552 {
553 gfc_warning ("An alternate return at %L without a * dummy argument",
554 &code->expr1->where);
555 return gfc_generate_return ();
556 }
557
558 /* Start a new block for this statement. */
559 gfc_init_se (&se, NULL);
560 gfc_start_block (&se.pre);
561
562 gfc_conv_expr (&se, code->expr1);
563
564 /* Note that the actually returned expression is a simple value and
565 does not depend on any pointers or such; thus we can clean-up with
566 se.post before returning. */
567 tmp = fold_build2_loc (input_location, MODIFY_EXPR, TREE_TYPE (result),
568 result, fold_convert (TREE_TYPE (result),
569 se.expr));
570 gfc_add_expr_to_block (&se.pre, tmp);
571 gfc_add_block_to_block (&se.pre, &se.post);
572
573 tmp = gfc_generate_return ();
574 gfc_add_expr_to_block (&se.pre, tmp);
575 return gfc_finish_block (&se.pre);
576 }
577
578 return gfc_generate_return ();
579 }
580
581
582 /* Translate the PAUSE statement. We have to translate this statement
583 to a runtime library call. */
584
585 tree
586 gfc_trans_pause (gfc_code * code)
587 {
588 tree gfc_int4_type_node = gfc_get_int_type (4);
589 gfc_se se;
590 tree tmp;
591
592 /* Start a new block for this statement. */
593 gfc_init_se (&se, NULL);
594 gfc_start_block (&se.pre);
595
596
597 if (code->expr1 == NULL)
598 {
599 tmp = build_int_cst (gfc_int4_type_node, 0);
600 tmp = build_call_expr_loc (input_location,
601 gfor_fndecl_pause_string, 2,
602 build_int_cst (pchar_type_node, 0), tmp);
603 }
604 else if (code->expr1->ts.type == BT_INTEGER)
605 {
606 gfc_conv_expr (&se, code->expr1);
607 tmp = build_call_expr_loc (input_location,
608 gfor_fndecl_pause_numeric, 1,
609 fold_convert (gfc_int4_type_node, se.expr));
610 }
611 else
612 {
613 gfc_conv_expr_reference (&se, code->expr1);
614 tmp = build_call_expr_loc (input_location,
615 gfor_fndecl_pause_string, 2,
616 se.expr, se.string_length);
617 }
618
619 gfc_add_expr_to_block (&se.pre, tmp);
620
621 gfc_add_block_to_block (&se.pre, &se.post);
622
623 return gfc_finish_block (&se.pre);
624 }
625
626
627 /* Translate the STOP statement. We have to translate this statement
628 to a runtime library call. */
629
630 tree
631 gfc_trans_stop (gfc_code *code, bool error_stop)
632 {
633 tree gfc_int4_type_node = gfc_get_int_type (4);
634 gfc_se se;
635 tree tmp;
636
637 /* Start a new block for this statement. */
638 gfc_init_se (&se, NULL);
639 gfc_start_block (&se.pre);
640
641 if (flag_coarray == GFC_FCOARRAY_LIB && !error_stop)
642 {
643 /* Per F2008, 8.5.1 STOP implies a SYNC MEMORY. */
644 tmp = builtin_decl_explicit (BUILT_IN_SYNC_SYNCHRONIZE);
645 tmp = build_call_expr_loc (input_location, tmp, 0);
646 gfc_add_expr_to_block (&se.pre, tmp);
647
648 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_finalize, 0);
649 gfc_add_expr_to_block (&se.pre, tmp);
650 }
651
652 if (code->expr1 == NULL)
653 {
654 tmp = build_int_cst (gfc_int4_type_node, 0);
655 tmp = build_call_expr_loc (input_location,
656 error_stop
657 ? (flag_coarray == GFC_FCOARRAY_LIB
658 ? gfor_fndecl_caf_error_stop_str
659 : gfor_fndecl_error_stop_string)
660 : gfor_fndecl_stop_string,
661 2, build_int_cst (pchar_type_node, 0), tmp);
662 }
663 else if (code->expr1->ts.type == BT_INTEGER)
664 {
665 gfc_conv_expr (&se, code->expr1);
666 tmp = build_call_expr_loc (input_location,
667 error_stop
668 ? (flag_coarray == GFC_FCOARRAY_LIB
669 ? gfor_fndecl_caf_error_stop
670 : gfor_fndecl_error_stop_numeric)
671 : gfor_fndecl_stop_numeric_f08, 1,
672 fold_convert (gfc_int4_type_node, se.expr));
673 }
674 else
675 {
676 gfc_conv_expr_reference (&se, code->expr1);
677 tmp = build_call_expr_loc (input_location,
678 error_stop
679 ? (flag_coarray == GFC_FCOARRAY_LIB
680 ? gfor_fndecl_caf_error_stop_str
681 : gfor_fndecl_error_stop_string)
682 : gfor_fndecl_stop_string,
683 2, se.expr, se.string_length);
684 }
685
686 gfc_add_expr_to_block (&se.pre, tmp);
687
688 gfc_add_block_to_block (&se.pre, &se.post);
689
690 return gfc_finish_block (&se.pre);
691 }
692
693
694 tree
695 gfc_trans_lock_unlock (gfc_code *code, gfc_exec_op type ATTRIBUTE_UNUSED)
696 {
697 gfc_se se, argse;
698 tree stat = NULL_TREE, lock_acquired = NULL_TREE;
699
700 /* Short cut: For single images without STAT= or LOCK_ACQUIRED
701 return early. (ERRMSG= is always untouched for -fcoarray=single.) */
702 if (!code->expr2 && !code->expr4 && flag_coarray != GFC_FCOARRAY_LIB)
703 return NULL_TREE;
704
705 gfc_init_se (&se, NULL);
706 gfc_start_block (&se.pre);
707
708 if (code->expr2)
709 {
710 gcc_assert (code->expr2->expr_type == EXPR_VARIABLE);
711 gfc_init_se (&argse, NULL);
712 gfc_conv_expr_val (&argse, code->expr2);
713 stat = argse.expr;
714 }
715
716 if (code->expr4)
717 {
718 gcc_assert (code->expr4->expr_type == EXPR_VARIABLE);
719 gfc_init_se (&argse, NULL);
720 gfc_conv_expr_val (&argse, code->expr4);
721 lock_acquired = argse.expr;
722 }
723
724 if (stat != NULL_TREE)
725 gfc_add_modify (&se.pre, stat, build_int_cst (TREE_TYPE (stat), 0));
726
727 if (lock_acquired != NULL_TREE)
728 gfc_add_modify (&se.pre, lock_acquired,
729 fold_convert (TREE_TYPE (lock_acquired),
730 boolean_true_node));
731
732 return gfc_finish_block (&se.pre);
733 }
734
735
736 tree
737 gfc_trans_sync (gfc_code *code, gfc_exec_op type)
738 {
739 gfc_se se, argse;
740 tree tmp;
741 tree images = NULL_TREE, stat = NULL_TREE,
742 errmsg = NULL_TREE, errmsglen = NULL_TREE;
743
744 /* Short cut: For single images without bound checking or without STAT=,
745 return early. (ERRMSG= is always untouched for -fcoarray=single.) */
746 if (!code->expr2 && !(gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
747 && flag_coarray != GFC_FCOARRAY_LIB)
748 return NULL_TREE;
749
750 gfc_init_se (&se, NULL);
751 gfc_start_block (&se.pre);
752
753 if (code->expr1 && code->expr1->rank == 0)
754 {
755 gfc_init_se (&argse, NULL);
756 gfc_conv_expr_val (&argse, code->expr1);
757 images = argse.expr;
758 }
759
760 if (code->expr2)
761 {
762 gcc_assert (code->expr2->expr_type == EXPR_VARIABLE);
763 gfc_init_se (&argse, NULL);
764 gfc_conv_expr_val (&argse, code->expr2);
765 stat = argse.expr;
766 }
767 else
768 stat = null_pointer_node;
769
770 if (code->expr3 && flag_coarray == GFC_FCOARRAY_LIB
771 && type != EXEC_SYNC_MEMORY)
772 {
773 gcc_assert (code->expr3->expr_type == EXPR_VARIABLE);
774 gfc_init_se (&argse, NULL);
775 gfc_conv_expr (&argse, code->expr3);
776 gfc_conv_string_parameter (&argse);
777 errmsg = gfc_build_addr_expr (NULL, argse.expr);
778 errmsglen = argse.string_length;
779 }
780 else if (flag_coarray == GFC_FCOARRAY_LIB && type != EXEC_SYNC_MEMORY)
781 {
782 errmsg = null_pointer_node;
783 errmsglen = build_int_cst (integer_type_node, 0);
784 }
785
786 /* Check SYNC IMAGES(imageset) for valid image index.
787 FIXME: Add a check for image-set arrays. */
788 if (code->expr1 && (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
789 && code->expr1->rank == 0)
790 {
791 tree cond;
792 if (flag_coarray != GFC_FCOARRAY_LIB)
793 cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
794 images, build_int_cst (TREE_TYPE (images), 1));
795 else
796 {
797 tree cond2;
798 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_num_images,
799 2, integer_zero_node,
800 build_int_cst (integer_type_node, -1));
801 cond = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
802 images, tmp);
803 cond2 = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
804 images,
805 build_int_cst (TREE_TYPE (images), 1));
806 cond = fold_build2_loc (input_location, TRUTH_OR_EXPR,
807 boolean_type_node, cond, cond2);
808 }
809 gfc_trans_runtime_check (true, false, cond, &se.pre,
810 &code->expr1->where, "Invalid image number "
811 "%d in SYNC IMAGES",
812 fold_convert (integer_type_node, images));
813 }
814
815 /* Per F2008, 8.5.1, a SYNC MEMORY is implied by calling the
816 image control statements SYNC IMAGES and SYNC ALL. */
817 if (flag_coarray == GFC_FCOARRAY_LIB)
818 {
819 tmp = builtin_decl_explicit (BUILT_IN_SYNC_SYNCHRONIZE);
820 tmp = build_call_expr_loc (input_location, tmp, 0);
821 gfc_add_expr_to_block (&se.pre, tmp);
822 }
823
824 if (flag_coarray != GFC_FCOARRAY_LIB || type == EXEC_SYNC_MEMORY)
825 {
826 /* Set STAT to zero. */
827 if (code->expr2)
828 gfc_add_modify (&se.pre, stat, build_int_cst (TREE_TYPE (stat), 0));
829 }
830 else if (type == EXEC_SYNC_ALL)
831 {
832 /* SYNC ALL => stat == null_pointer_node
833 SYNC ALL(stat=s) => stat has an integer type
834
835 If "stat" has the wrong integer type, use a temp variable of
836 the right type and later cast the result back into "stat". */
837 if (stat == null_pointer_node || TREE_TYPE (stat) == integer_type_node)
838 {
839 if (TREE_TYPE (stat) == integer_type_node)
840 stat = gfc_build_addr_expr (NULL, stat);
841
842 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sync_all,
843 3, stat, errmsg, errmsglen);
844 gfc_add_expr_to_block (&se.pre, tmp);
845 }
846 else
847 {
848 tree tmp_stat = gfc_create_var (integer_type_node, "stat");
849
850 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sync_all,
851 3, gfc_build_addr_expr (NULL, tmp_stat),
852 errmsg, errmsglen);
853 gfc_add_expr_to_block (&se.pre, tmp);
854
855 gfc_add_modify (&se.pre, stat,
856 fold_convert (TREE_TYPE (stat), tmp_stat));
857 }
858 }
859 else
860 {
861 tree len;
862
863 gcc_assert (type == EXEC_SYNC_IMAGES);
864
865 if (!code->expr1)
866 {
867 len = build_int_cst (integer_type_node, -1);
868 images = null_pointer_node;
869 }
870 else if (code->expr1->rank == 0)
871 {
872 len = build_int_cst (integer_type_node, 1);
873 images = gfc_build_addr_expr (NULL_TREE, images);
874 }
875 else
876 {
877 /* FIXME. */
878 if (code->expr1->ts.kind != gfc_c_int_kind)
879 gfc_fatal_error ("Sorry, only support for integer kind %d "
880 "implemented for image-set at %L",
881 gfc_c_int_kind, &code->expr1->where);
882
883 gfc_conv_array_parameter (&se, code->expr1, true, NULL, NULL, &len);
884 images = se.expr;
885
886 tmp = gfc_typenode_for_spec (&code->expr1->ts);
887 if (GFC_ARRAY_TYPE_P (tmp) || GFC_DESCRIPTOR_TYPE_P (tmp))
888 tmp = gfc_get_element_type (tmp);
889
890 len = fold_build2_loc (input_location, TRUNC_DIV_EXPR,
891 TREE_TYPE (len), len,
892 fold_convert (TREE_TYPE (len),
893 TYPE_SIZE_UNIT (tmp)));
894 len = fold_convert (integer_type_node, len);
895 }
896
897 /* SYNC IMAGES(imgs) => stat == null_pointer_node
898 SYNC IMAGES(imgs,stat=s) => stat has an integer type
899
900 If "stat" has the wrong integer type, use a temp variable of
901 the right type and later cast the result back into "stat". */
902 if (stat == null_pointer_node || TREE_TYPE (stat) == integer_type_node)
903 {
904 if (TREE_TYPE (stat) == integer_type_node)
905 stat = gfc_build_addr_expr (NULL, stat);
906
907 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sync_images,
908 5, fold_convert (integer_type_node, len),
909 images, stat, errmsg, errmsglen);
910 gfc_add_expr_to_block (&se.pre, tmp);
911 }
912 else
913 {
914 tree tmp_stat = gfc_create_var (integer_type_node, "stat");
915
916 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sync_images,
917 5, fold_convert (integer_type_node, len),
918 images, gfc_build_addr_expr (NULL, tmp_stat),
919 errmsg, errmsglen);
920 gfc_add_expr_to_block (&se.pre, tmp);
921
922 gfc_add_modify (&se.pre, stat,
923 fold_convert (TREE_TYPE (stat), tmp_stat));
924 }
925 }
926
927 return gfc_finish_block (&se.pre);
928 }
929
930
931 /* Generate GENERIC for the IF construct. This function also deals with
932 the simple IF statement, because the front end translates the IF
933 statement into an IF construct.
934
935 We translate:
936
937 IF (cond) THEN
938 then_clause
939 ELSEIF (cond2)
940 elseif_clause
941 ELSE
942 else_clause
943 ENDIF
944
945 into:
946
947 pre_cond_s;
948 if (cond_s)
949 {
950 then_clause;
951 }
952 else
953 {
954 pre_cond_s
955 if (cond_s)
956 {
957 elseif_clause
958 }
959 else
960 {
961 else_clause;
962 }
963 }
964
965 where COND_S is the simplified version of the predicate. PRE_COND_S
966 are the pre side-effects produced by the translation of the
967 conditional.
968 We need to build the chain recursively otherwise we run into
969 problems with folding incomplete statements. */
970
971 static tree
972 gfc_trans_if_1 (gfc_code * code)
973 {
974 gfc_se if_se;
975 tree stmt, elsestmt;
976 locus saved_loc;
977 location_t loc;
978
979 /* Check for an unconditional ELSE clause. */
980 if (!code->expr1)
981 return gfc_trans_code (code->next);
982
983 /* Initialize a statement builder for each block. Puts in NULL_TREEs. */
984 gfc_init_se (&if_se, NULL);
985 gfc_start_block (&if_se.pre);
986
987 /* Calculate the IF condition expression. */
988 if (code->expr1->where.lb)
989 {
990 gfc_save_backend_locus (&saved_loc);
991 gfc_set_backend_locus (&code->expr1->where);
992 }
993
994 gfc_conv_expr_val (&if_se, code->expr1);
995
996 if (code->expr1->where.lb)
997 gfc_restore_backend_locus (&saved_loc);
998
999 /* Translate the THEN clause. */
1000 stmt = gfc_trans_code (code->next);
1001
1002 /* Translate the ELSE clause. */
1003 if (code->block)
1004 elsestmt = gfc_trans_if_1 (code->block);
1005 else
1006 elsestmt = build_empty_stmt (input_location);
1007
1008 /* Build the condition expression and add it to the condition block. */
1009 loc = code->expr1->where.lb ? code->expr1->where.lb->location : input_location;
1010 stmt = fold_build3_loc (loc, COND_EXPR, void_type_node, if_se.expr, stmt,
1011 elsestmt);
1012
1013 gfc_add_expr_to_block (&if_se.pre, stmt);
1014
1015 /* Finish off this statement. */
1016 return gfc_finish_block (&if_se.pre);
1017 }
1018
1019 tree
1020 gfc_trans_if (gfc_code * code)
1021 {
1022 stmtblock_t body;
1023 tree exit_label;
1024
1025 /* Create exit label so it is available for trans'ing the body code. */
1026 exit_label = gfc_build_label_decl (NULL_TREE);
1027 code->exit_label = exit_label;
1028
1029 /* Translate the actual code in code->block. */
1030 gfc_init_block (&body);
1031 gfc_add_expr_to_block (&body, gfc_trans_if_1 (code->block));
1032
1033 /* Add exit label. */
1034 gfc_add_expr_to_block (&body, build1_v (LABEL_EXPR, exit_label));
1035
1036 return gfc_finish_block (&body);
1037 }
1038
1039
1040 /* Translate an arithmetic IF expression.
1041
1042 IF (cond) label1, label2, label3 translates to
1043
1044 if (cond <= 0)
1045 {
1046 if (cond < 0)
1047 goto label1;
1048 else // cond == 0
1049 goto label2;
1050 }
1051 else // cond > 0
1052 goto label3;
1053
1054 An optimized version can be generated in case of equal labels.
1055 E.g., if label1 is equal to label2, we can translate it to
1056
1057 if (cond <= 0)
1058 goto label1;
1059 else
1060 goto label3;
1061 */
1062
1063 tree
1064 gfc_trans_arithmetic_if (gfc_code * code)
1065 {
1066 gfc_se se;
1067 tree tmp;
1068 tree branch1;
1069 tree branch2;
1070 tree zero;
1071
1072 /* Start a new block. */
1073 gfc_init_se (&se, NULL);
1074 gfc_start_block (&se.pre);
1075
1076 /* Pre-evaluate COND. */
1077 gfc_conv_expr_val (&se, code->expr1);
1078 se.expr = gfc_evaluate_now (se.expr, &se.pre);
1079
1080 /* Build something to compare with. */
1081 zero = gfc_build_const (TREE_TYPE (se.expr), integer_zero_node);
1082
1083 if (code->label1->value != code->label2->value)
1084 {
1085 /* If (cond < 0) take branch1 else take branch2.
1086 First build jumps to the COND .LT. 0 and the COND .EQ. 0 cases. */
1087 branch1 = build1_v (GOTO_EXPR, gfc_get_label_decl (code->label1));
1088 branch2 = build1_v (GOTO_EXPR, gfc_get_label_decl (code->label2));
1089
1090 if (code->label1->value != code->label3->value)
1091 tmp = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
1092 se.expr, zero);
1093 else
1094 tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
1095 se.expr, zero);
1096
1097 branch1 = fold_build3_loc (input_location, COND_EXPR, void_type_node,
1098 tmp, branch1, branch2);
1099 }
1100 else
1101 branch1 = build1_v (GOTO_EXPR, gfc_get_label_decl (code->label1));
1102
1103 if (code->label1->value != code->label3->value
1104 && code->label2->value != code->label3->value)
1105 {
1106 /* if (cond <= 0) take branch1 else take branch2. */
1107 branch2 = build1_v (GOTO_EXPR, gfc_get_label_decl (code->label3));
1108 tmp = fold_build2_loc (input_location, LE_EXPR, boolean_type_node,
1109 se.expr, zero);
1110 branch1 = fold_build3_loc (input_location, COND_EXPR, void_type_node,
1111 tmp, branch1, branch2);
1112 }
1113
1114 /* Append the COND_EXPR to the evaluation of COND, and return. */
1115 gfc_add_expr_to_block (&se.pre, branch1);
1116 return gfc_finish_block (&se.pre);
1117 }
1118
1119
1120 /* Translate a CRITICAL block. */
1121 tree
1122 gfc_trans_critical (gfc_code *code)
1123 {
1124 stmtblock_t block;
1125 tree tmp, token = NULL_TREE;
1126
1127 gfc_start_block (&block);
1128
1129 if (flag_coarray == GFC_FCOARRAY_LIB)
1130 {
1131 token = gfc_get_symbol_decl (code->resolved_sym);
1132 token = GFC_TYPE_ARRAY_CAF_TOKEN (TREE_TYPE (token));
1133 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_lock, 7,
1134 token, integer_zero_node, integer_one_node,
1135 null_pointer_node, null_pointer_node,
1136 null_pointer_node, integer_zero_node);
1137 gfc_add_expr_to_block (&block, tmp);
1138 }
1139
1140 tmp = gfc_trans_code (code->block->next);
1141 gfc_add_expr_to_block (&block, tmp);
1142
1143 if (flag_coarray == GFC_FCOARRAY_LIB)
1144 {
1145 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_unlock, 6,
1146 token, integer_zero_node, integer_one_node,
1147 null_pointer_node, null_pointer_node,
1148 integer_zero_node);
1149 gfc_add_expr_to_block (&block, tmp);
1150 }
1151
1152
1153 return gfc_finish_block (&block);
1154 }
1155
1156
1157 /* Do proper initialization for ASSOCIATE names. */
1158
1159 static void
1160 trans_associate_var (gfc_symbol *sym, gfc_wrapped_block *block)
1161 {
1162 gfc_expr *e;
1163 tree tmp;
1164 bool class_target;
1165 bool unlimited;
1166 tree desc;
1167 tree offset;
1168 tree dim;
1169 int n;
1170
1171 gcc_assert (sym->assoc);
1172 e = sym->assoc->target;
1173
1174 class_target = (e->expr_type == EXPR_VARIABLE)
1175 && (gfc_is_class_scalar_expr (e)
1176 || gfc_is_class_array_ref (e, NULL));
1177
1178 unlimited = UNLIMITED_POLY (e);
1179
1180 /* Do a `pointer assignment' with updated descriptor (or assign descriptor
1181 to array temporary) for arrays with either unknown shape or if associating
1182 to a variable. */
1183 if (sym->attr.dimension && !class_target
1184 && (sym->as->type == AS_DEFERRED || sym->assoc->variable))
1185 {
1186 gfc_se se;
1187 tree desc;
1188 bool cst_array_ctor;
1189
1190 desc = sym->backend_decl;
1191 cst_array_ctor = e->expr_type == EXPR_ARRAY
1192 && gfc_constant_array_constructor_p (e->value.constructor);
1193
1194 /* If association is to an expression, evaluate it and create temporary.
1195 Otherwise, get descriptor of target for pointer assignment. */
1196 gfc_init_se (&se, NULL);
1197 if (sym->assoc->variable || cst_array_ctor)
1198 {
1199 se.direct_byref = 1;
1200 se.use_offset = 1;
1201 se.expr = desc;
1202 }
1203
1204 gfc_conv_expr_descriptor (&se, e);
1205
1206 /* If we didn't already do the pointer assignment, set associate-name
1207 descriptor to the one generated for the temporary. */
1208 if (!sym->assoc->variable && !cst_array_ctor)
1209 {
1210 int dim;
1211
1212 gfc_add_modify (&se.pre, desc, se.expr);
1213
1214 /* The generated descriptor has lower bound zero (as array
1215 temporary), shift bounds so we get lower bounds of 1. */
1216 for (dim = 0; dim < e->rank; ++dim)
1217 gfc_conv_shift_descriptor_lbound (&se.pre, desc,
1218 dim, gfc_index_one_node);
1219 }
1220
1221 /* If this is a subreference array pointer associate name use the
1222 associate variable element size for the value of 'span'. */
1223 if (sym->attr.subref_array_pointer)
1224 {
1225 gcc_assert (e->expr_type == EXPR_VARIABLE);
1226 tmp = e->symtree->n.sym->backend_decl;
1227 tmp = gfc_get_element_type (TREE_TYPE (tmp));
1228 tmp = fold_convert (gfc_array_index_type, size_in_bytes (tmp));
1229 gfc_add_modify (&se.pre, GFC_DECL_SPAN(desc), tmp);
1230 }
1231
1232 /* Done, register stuff as init / cleanup code. */
1233 gfc_add_init_cleanup (block, gfc_finish_block (&se.pre),
1234 gfc_finish_block (&se.post));
1235 }
1236
1237 /* Temporaries, arising from TYPE IS, just need the descriptor of class
1238 arrays to be assigned directly. */
1239 else if (class_target && sym->attr.dimension
1240 && (sym->ts.type == BT_DERIVED || unlimited))
1241 {
1242 gfc_se se;
1243
1244 gfc_init_se (&se, NULL);
1245 se.descriptor_only = 1;
1246 gfc_conv_expr (&se, e);
1247
1248 gcc_assert (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (se.expr)));
1249 gcc_assert (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (sym->backend_decl)));
1250
1251 gfc_add_modify (&se.pre, sym->backend_decl, se.expr);
1252
1253 if (unlimited)
1254 {
1255 /* Recover the dtype, which has been overwritten by the
1256 assignment from an unlimited polymorphic object. */
1257 tmp = gfc_conv_descriptor_dtype (sym->backend_decl);
1258 gfc_add_modify (&se.pre, tmp,
1259 gfc_get_dtype (TREE_TYPE (sym->backend_decl)));
1260 }
1261
1262 gfc_add_init_cleanup (block, gfc_finish_block( &se.pre),
1263 gfc_finish_block (&se.post));
1264 }
1265
1266 /* Do a scalar pointer assignment; this is for scalar variable targets. */
1267 else if (gfc_is_associate_pointer (sym))
1268 {
1269 gfc_se se;
1270
1271 gcc_assert (!sym->attr.dimension);
1272
1273 gfc_init_se (&se, NULL);
1274
1275 /* Class associate-names come this way because they are
1276 unconditionally associate pointers and the symbol is scalar. */
1277 if (sym->ts.type == BT_CLASS && CLASS_DATA (sym)->attr.dimension)
1278 {
1279 /* For a class array we need a descriptor for the selector. */
1280 gfc_conv_expr_descriptor (&se, e);
1281
1282 /* Obtain a temporary class container for the result. */
1283 gfc_conv_class_to_class (&se, e, sym->ts, false, true, false, false);
1284 se.expr = build_fold_indirect_ref_loc (input_location, se.expr);
1285
1286 /* Set the offset. */
1287 desc = gfc_class_data_get (se.expr);
1288 offset = gfc_index_zero_node;
1289 for (n = 0; n < e->rank; n++)
1290 {
1291 dim = gfc_rank_cst[n];
1292 tmp = fold_build2_loc (input_location, MULT_EXPR,
1293 gfc_array_index_type,
1294 gfc_conv_descriptor_stride_get (desc, dim),
1295 gfc_conv_descriptor_lbound_get (desc, dim));
1296 offset = fold_build2_loc (input_location, MINUS_EXPR,
1297 gfc_array_index_type,
1298 offset, tmp);
1299 }
1300 gfc_conv_descriptor_offset_set (&se.pre, desc, offset);
1301 }
1302 else if (sym->ts.type == BT_CLASS && e->ts.type == BT_CLASS
1303 && CLASS_DATA (e)->attr.dimension)
1304 {
1305 /* This is bound to be a class array element. */
1306 gfc_conv_expr_reference (&se, e);
1307 /* Get the _vptr component of the class object. */
1308 tmp = gfc_get_vptr_from_expr (se.expr);
1309 /* Obtain a temporary class container for the result. */
1310 gfc_conv_derived_to_class (&se, e, sym->ts, tmp, false, false);
1311 se.expr = build_fold_indirect_ref_loc (input_location, se.expr);
1312 }
1313 else
1314 gfc_conv_expr (&se, e);
1315
1316 tmp = TREE_TYPE (sym->backend_decl);
1317 tmp = gfc_build_addr_expr (tmp, se.expr);
1318 gfc_add_modify (&se.pre, sym->backend_decl, tmp);
1319
1320 gfc_add_init_cleanup (block, gfc_finish_block( &se.pre),
1321 gfc_finish_block (&se.post));
1322 }
1323
1324 /* Do a simple assignment. This is for scalar expressions, where we
1325 can simply use expression assignment. */
1326 else
1327 {
1328 gfc_expr *lhs;
1329
1330 lhs = gfc_lval_expr_from_sym (sym);
1331 tmp = gfc_trans_assignment (lhs, e, false, true);
1332 gfc_add_init_cleanup (block, tmp, NULL_TREE);
1333 }
1334
1335 /* Set the stringlength from the vtable size. */
1336 if (sym->ts.type == BT_CHARACTER && sym->attr.select_type_temporary)
1337 {
1338 tree charlen;
1339 gfc_se se;
1340 gfc_init_se (&se, NULL);
1341 gcc_assert (UNLIMITED_POLY (e->symtree->n.sym));
1342 tmp = gfc_get_symbol_decl (e->symtree->n.sym);
1343 tmp = gfc_vtable_size_get (tmp);
1344 gfc_get_symbol_decl (sym);
1345 charlen = sym->ts.u.cl->backend_decl;
1346 gfc_add_modify (&se.pre, charlen,
1347 fold_convert (TREE_TYPE (charlen), tmp));
1348 gfc_add_init_cleanup (block, gfc_finish_block( &se.pre),
1349 gfc_finish_block (&se.post));
1350 }
1351 }
1352
1353
1354 /* Translate a BLOCK construct. This is basically what we would do for a
1355 procedure body. */
1356
1357 tree
1358 gfc_trans_block_construct (gfc_code* code)
1359 {
1360 gfc_namespace* ns;
1361 gfc_symbol* sym;
1362 gfc_wrapped_block block;
1363 tree exit_label;
1364 stmtblock_t body;
1365 gfc_association_list *ass;
1366
1367 ns = code->ext.block.ns;
1368 gcc_assert (ns);
1369 sym = ns->proc_name;
1370 gcc_assert (sym);
1371
1372 /* Process local variables. */
1373 gcc_assert (!sym->tlink);
1374 sym->tlink = sym;
1375 gfc_process_block_locals (ns);
1376
1377 /* Generate code including exit-label. */
1378 gfc_init_block (&body);
1379 exit_label = gfc_build_label_decl (NULL_TREE);
1380 code->exit_label = exit_label;
1381
1382 /* Generate !$ACC DECLARE directive. */
1383 if (ns->oacc_declare_clauses)
1384 {
1385 tree tmp = gfc_trans_oacc_declare (&body, ns);
1386 gfc_add_expr_to_block (&body, tmp);
1387 }
1388
1389 gfc_add_expr_to_block (&body, gfc_trans_code (ns->code));
1390 gfc_add_expr_to_block (&body, build1_v (LABEL_EXPR, exit_label));
1391
1392 /* Finish everything. */
1393 gfc_start_wrapped_block (&block, gfc_finish_block (&body));
1394 gfc_trans_deferred_vars (sym, &block);
1395 for (ass = code->ext.block.assoc; ass; ass = ass->next)
1396 trans_associate_var (ass->st->n.sym, &block);
1397
1398 return gfc_finish_wrapped_block (&block);
1399 }
1400
1401
1402 /* Translate the simple DO construct. This is where the loop variable has
1403 integer type and step +-1. We can't use this in the general case
1404 because integer overflow and floating point errors could give incorrect
1405 results.
1406 We translate a do loop from:
1407
1408 DO dovar = from, to, step
1409 body
1410 END DO
1411
1412 to:
1413
1414 [Evaluate loop bounds and step]
1415 dovar = from;
1416 if ((step > 0) ? (dovar <= to) : (dovar => to))
1417 {
1418 for (;;)
1419 {
1420 body;
1421 cycle_label:
1422 cond = (dovar == to);
1423 dovar += step;
1424 if (cond) goto end_label;
1425 }
1426 }
1427 end_label:
1428
1429 This helps the optimizers by avoiding the extra induction variable
1430 used in the general case. */
1431
1432 static tree
1433 gfc_trans_simple_do (gfc_code * code, stmtblock_t *pblock, tree dovar,
1434 tree from, tree to, tree step, tree exit_cond)
1435 {
1436 stmtblock_t body;
1437 tree type;
1438 tree cond;
1439 tree tmp;
1440 tree saved_dovar = NULL;
1441 tree cycle_label;
1442 tree exit_label;
1443 location_t loc;
1444
1445 type = TREE_TYPE (dovar);
1446
1447 loc = code->ext.iterator->start->where.lb->location;
1448
1449 /* Initialize the DO variable: dovar = from. */
1450 gfc_add_modify_loc (loc, pblock, dovar,
1451 fold_convert (TREE_TYPE(dovar), from));
1452
1453 /* Save value for do-tinkering checking. */
1454 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
1455 {
1456 saved_dovar = gfc_create_var (type, ".saved_dovar");
1457 gfc_add_modify_loc (loc, pblock, saved_dovar, dovar);
1458 }
1459
1460 /* Cycle and exit statements are implemented with gotos. */
1461 cycle_label = gfc_build_label_decl (NULL_TREE);
1462 exit_label = gfc_build_label_decl (NULL_TREE);
1463
1464 /* Put the labels where they can be found later. See gfc_trans_do(). */
1465 code->cycle_label = cycle_label;
1466 code->exit_label = exit_label;
1467
1468 /* Loop body. */
1469 gfc_start_block (&body);
1470
1471 /* Main loop body. */
1472 tmp = gfc_trans_code_cond (code->block->next, exit_cond);
1473 gfc_add_expr_to_block (&body, tmp);
1474
1475 /* Label for cycle statements (if needed). */
1476 if (TREE_USED (cycle_label))
1477 {
1478 tmp = build1_v (LABEL_EXPR, cycle_label);
1479 gfc_add_expr_to_block (&body, tmp);
1480 }
1481
1482 /* Check whether someone has modified the loop variable. */
1483 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
1484 {
1485 tmp = fold_build2_loc (loc, NE_EXPR, boolean_type_node,
1486 dovar, saved_dovar);
1487 gfc_trans_runtime_check (true, false, tmp, &body, &code->loc,
1488 "Loop variable has been modified");
1489 }
1490
1491 /* Exit the loop if there is an I/O result condition or error. */
1492 if (exit_cond)
1493 {
1494 tmp = build1_v (GOTO_EXPR, exit_label);
1495 tmp = fold_build3_loc (loc, COND_EXPR, void_type_node,
1496 exit_cond, tmp,
1497 build_empty_stmt (loc));
1498 gfc_add_expr_to_block (&body, tmp);
1499 }
1500
1501 /* Evaluate the loop condition. */
1502 cond = fold_build2_loc (loc, EQ_EXPR, boolean_type_node, dovar,
1503 to);
1504 cond = gfc_evaluate_now_loc (loc, cond, &body);
1505
1506 /* Increment the loop variable. */
1507 tmp = fold_build2_loc (loc, PLUS_EXPR, type, dovar, step);
1508 gfc_add_modify_loc (loc, &body, dovar, tmp);
1509
1510 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
1511 gfc_add_modify_loc (loc, &body, saved_dovar, dovar);
1512
1513 /* The loop exit. */
1514 tmp = fold_build1_loc (loc, GOTO_EXPR, void_type_node, exit_label);
1515 TREE_USED (exit_label) = 1;
1516 tmp = fold_build3_loc (loc, COND_EXPR, void_type_node,
1517 cond, tmp, build_empty_stmt (loc));
1518 gfc_add_expr_to_block (&body, tmp);
1519
1520 /* Finish the loop body. */
1521 tmp = gfc_finish_block (&body);
1522 tmp = fold_build1_loc (loc, LOOP_EXPR, void_type_node, tmp);
1523
1524 /* Only execute the loop if the number of iterations is positive. */
1525 if (tree_int_cst_sgn (step) > 0)
1526 cond = fold_build2_loc (loc, LE_EXPR, boolean_type_node, dovar,
1527 to);
1528 else
1529 cond = fold_build2_loc (loc, GE_EXPR, boolean_type_node, dovar,
1530 to);
1531 tmp = fold_build3_loc (loc, COND_EXPR, void_type_node, cond, tmp,
1532 build_empty_stmt (loc));
1533 gfc_add_expr_to_block (pblock, tmp);
1534
1535 /* Add the exit label. */
1536 tmp = build1_v (LABEL_EXPR, exit_label);
1537 gfc_add_expr_to_block (pblock, tmp);
1538
1539 return gfc_finish_block (pblock);
1540 }
1541
1542 /* Translate the DO construct. This obviously is one of the most
1543 important ones to get right with any compiler, but especially
1544 so for Fortran.
1545
1546 We special case some loop forms as described in gfc_trans_simple_do.
1547 For other cases we implement them with a separate loop count,
1548 as described in the standard.
1549
1550 We translate a do loop from:
1551
1552 DO dovar = from, to, step
1553 body
1554 END DO
1555
1556 to:
1557
1558 [evaluate loop bounds and step]
1559 empty = (step > 0 ? to < from : to > from);
1560 countm1 = (to - from) / step;
1561 dovar = from;
1562 if (empty) goto exit_label;
1563 for (;;)
1564 {
1565 body;
1566 cycle_label:
1567 dovar += step
1568 countm1t = countm1;
1569 countm1--;
1570 if (countm1t == 0) goto exit_label;
1571 }
1572 exit_label:
1573
1574 countm1 is an unsigned integer. It is equal to the loop count minus one,
1575 because the loop count itself can overflow. */
1576
1577 tree
1578 gfc_trans_do (gfc_code * code, tree exit_cond)
1579 {
1580 gfc_se se;
1581 tree dovar;
1582 tree saved_dovar = NULL;
1583 tree from;
1584 tree to;
1585 tree step;
1586 tree countm1;
1587 tree type;
1588 tree utype;
1589 tree cond;
1590 tree cycle_label;
1591 tree exit_label;
1592 tree tmp;
1593 stmtblock_t block;
1594 stmtblock_t body;
1595 location_t loc;
1596
1597 gfc_start_block (&block);
1598
1599 loc = code->ext.iterator->start->where.lb->location;
1600
1601 /* Evaluate all the expressions in the iterator. */
1602 gfc_init_se (&se, NULL);
1603 gfc_conv_expr_lhs (&se, code->ext.iterator->var);
1604 gfc_add_block_to_block (&block, &se.pre);
1605 dovar = se.expr;
1606 type = TREE_TYPE (dovar);
1607
1608 gfc_init_se (&se, NULL);
1609 gfc_conv_expr_val (&se, code->ext.iterator->start);
1610 gfc_add_block_to_block (&block, &se.pre);
1611 from = gfc_evaluate_now (se.expr, &block);
1612
1613 gfc_init_se (&se, NULL);
1614 gfc_conv_expr_val (&se, code->ext.iterator->end);
1615 gfc_add_block_to_block (&block, &se.pre);
1616 to = gfc_evaluate_now (se.expr, &block);
1617
1618 gfc_init_se (&se, NULL);
1619 gfc_conv_expr_val (&se, code->ext.iterator->step);
1620 gfc_add_block_to_block (&block, &se.pre);
1621 step = gfc_evaluate_now (se.expr, &block);
1622
1623 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
1624 {
1625 tmp = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, step,
1626 build_zero_cst (type));
1627 gfc_trans_runtime_check (true, false, tmp, &block, &code->loc,
1628 "DO step value is zero");
1629 }
1630
1631 /* Special case simple loops. */
1632 if (TREE_CODE (type) == INTEGER_TYPE
1633 && (integer_onep (step)
1634 || tree_int_cst_equal (step, integer_minus_one_node)))
1635 return gfc_trans_simple_do (code, &block, dovar, from, to, step, exit_cond);
1636
1637
1638 if (TREE_CODE (type) == INTEGER_TYPE)
1639 utype = unsigned_type_for (type);
1640 else
1641 utype = unsigned_type_for (gfc_array_index_type);
1642 countm1 = gfc_create_var (utype, "countm1");
1643
1644 /* Cycle and exit statements are implemented with gotos. */
1645 cycle_label = gfc_build_label_decl (NULL_TREE);
1646 exit_label = gfc_build_label_decl (NULL_TREE);
1647 TREE_USED (exit_label) = 1;
1648
1649 /* Put these labels where they can be found later. */
1650 code->cycle_label = cycle_label;
1651 code->exit_label = exit_label;
1652
1653 /* Initialize the DO variable: dovar = from. */
1654 gfc_add_modify (&block, dovar, from);
1655
1656 /* Save value for do-tinkering checking. */
1657 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
1658 {
1659 saved_dovar = gfc_create_var (type, ".saved_dovar");
1660 gfc_add_modify_loc (loc, &block, saved_dovar, dovar);
1661 }
1662
1663 /* Initialize loop count and jump to exit label if the loop is empty.
1664 This code is executed before we enter the loop body. We generate:
1665 if (step > 0)
1666 {
1667 countm1 = (to - from) / step;
1668 if (to < from)
1669 goto exit_label;
1670 }
1671 else
1672 {
1673 countm1 = (from - to) / -step;
1674 if (to > from)
1675 goto exit_label;
1676 }
1677 */
1678
1679 if (TREE_CODE (type) == INTEGER_TYPE)
1680 {
1681 tree pos, neg, tou, fromu, stepu, tmp2;
1682
1683 /* The distance from FROM to TO cannot always be represented in a signed
1684 type, thus use unsigned arithmetic, also to avoid any undefined
1685 overflow issues. */
1686 tou = fold_convert (utype, to);
1687 fromu = fold_convert (utype, from);
1688 stepu = fold_convert (utype, step);
1689
1690 /* For a positive step, when to < from, exit, otherwise compute
1691 countm1 = ((unsigned)to - (unsigned)from) / (unsigned)step */
1692 tmp = fold_build2_loc (loc, LT_EXPR, boolean_type_node, to, from);
1693 tmp2 = fold_build2_loc (loc, TRUNC_DIV_EXPR, utype,
1694 fold_build2_loc (loc, MINUS_EXPR, utype,
1695 tou, fromu),
1696 stepu);
1697 pos = build2 (COMPOUND_EXPR, void_type_node,
1698 fold_build2 (MODIFY_EXPR, void_type_node,
1699 countm1, tmp2),
1700 build3_loc (loc, COND_EXPR, void_type_node, tmp,
1701 build1_loc (loc, GOTO_EXPR, void_type_node,
1702 exit_label), NULL_TREE));
1703
1704 /* For a negative step, when to > from, exit, otherwise compute
1705 countm1 = ((unsigned)from - (unsigned)to) / -(unsigned)step */
1706 tmp = fold_build2_loc (loc, GT_EXPR, boolean_type_node, to, from);
1707 tmp2 = fold_build2_loc (loc, TRUNC_DIV_EXPR, utype,
1708 fold_build2_loc (loc, MINUS_EXPR, utype,
1709 fromu, tou),
1710 fold_build1_loc (loc, NEGATE_EXPR, utype, stepu));
1711 neg = build2 (COMPOUND_EXPR, void_type_node,
1712 fold_build2 (MODIFY_EXPR, void_type_node,
1713 countm1, tmp2),
1714 build3_loc (loc, COND_EXPR, void_type_node, tmp,
1715 build1_loc (loc, GOTO_EXPR, void_type_node,
1716 exit_label), NULL_TREE));
1717
1718 tmp = fold_build2_loc (loc, LT_EXPR, boolean_type_node, step,
1719 build_int_cst (TREE_TYPE (step), 0));
1720 tmp = fold_build3_loc (loc, COND_EXPR, void_type_node, tmp, neg, pos);
1721
1722 gfc_add_expr_to_block (&block, tmp);
1723 }
1724 else
1725 {
1726 tree pos_step;
1727
1728 /* TODO: We could use the same width as the real type.
1729 This would probably cause more problems that it solves
1730 when we implement "long double" types. */
1731
1732 tmp = fold_build2_loc (loc, MINUS_EXPR, type, to, from);
1733 tmp = fold_build2_loc (loc, RDIV_EXPR, type, tmp, step);
1734 tmp = fold_build1_loc (loc, FIX_TRUNC_EXPR, utype, tmp);
1735 gfc_add_modify (&block, countm1, tmp);
1736
1737 /* We need a special check for empty loops:
1738 empty = (step > 0 ? to < from : to > from); */
1739 pos_step = fold_build2_loc (loc, GT_EXPR, boolean_type_node, step,
1740 build_zero_cst (type));
1741 tmp = fold_build3_loc (loc, COND_EXPR, boolean_type_node, pos_step,
1742 fold_build2_loc (loc, LT_EXPR,
1743 boolean_type_node, to, from),
1744 fold_build2_loc (loc, GT_EXPR,
1745 boolean_type_node, to, from));
1746 /* If the loop is empty, go directly to the exit label. */
1747 tmp = fold_build3_loc (loc, COND_EXPR, void_type_node, tmp,
1748 build1_v (GOTO_EXPR, exit_label),
1749 build_empty_stmt (input_location));
1750 gfc_add_expr_to_block (&block, tmp);
1751 }
1752
1753 /* Loop body. */
1754 gfc_start_block (&body);
1755
1756 /* Main loop body. */
1757 tmp = gfc_trans_code_cond (code->block->next, exit_cond);
1758 gfc_add_expr_to_block (&body, tmp);
1759
1760 /* Label for cycle statements (if needed). */
1761 if (TREE_USED (cycle_label))
1762 {
1763 tmp = build1_v (LABEL_EXPR, cycle_label);
1764 gfc_add_expr_to_block (&body, tmp);
1765 }
1766
1767 /* Check whether someone has modified the loop variable. */
1768 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
1769 {
1770 tmp = fold_build2_loc (loc, NE_EXPR, boolean_type_node, dovar,
1771 saved_dovar);
1772 gfc_trans_runtime_check (true, false, tmp, &body, &code->loc,
1773 "Loop variable has been modified");
1774 }
1775
1776 /* Exit the loop if there is an I/O result condition or error. */
1777 if (exit_cond)
1778 {
1779 tmp = build1_v (GOTO_EXPR, exit_label);
1780 tmp = fold_build3_loc (loc, COND_EXPR, void_type_node,
1781 exit_cond, tmp,
1782 build_empty_stmt (input_location));
1783 gfc_add_expr_to_block (&body, tmp);
1784 }
1785
1786 /* Increment the loop variable. */
1787 tmp = fold_build2_loc (loc, PLUS_EXPR, type, dovar, step);
1788 gfc_add_modify_loc (loc, &body, dovar, tmp);
1789
1790 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
1791 gfc_add_modify_loc (loc, &body, saved_dovar, dovar);
1792
1793 /* Initialize countm1t. */
1794 tree countm1t = gfc_create_var (utype, "countm1t");
1795 gfc_add_modify_loc (loc, &body, countm1t, countm1);
1796
1797 /* Decrement the loop count. */
1798 tmp = fold_build2_loc (loc, MINUS_EXPR, utype, countm1,
1799 build_int_cst (utype, 1));
1800 gfc_add_modify_loc (loc, &body, countm1, tmp);
1801
1802 /* End with the loop condition. Loop until countm1t == 0. */
1803 cond = fold_build2_loc (loc, EQ_EXPR, boolean_type_node, countm1t,
1804 build_int_cst (utype, 0));
1805 tmp = fold_build1_loc (loc, GOTO_EXPR, void_type_node, exit_label);
1806 tmp = fold_build3_loc (loc, COND_EXPR, void_type_node,
1807 cond, tmp, build_empty_stmt (loc));
1808 gfc_add_expr_to_block (&body, tmp);
1809
1810 /* End of loop body. */
1811 tmp = gfc_finish_block (&body);
1812
1813 /* The for loop itself. */
1814 tmp = fold_build1_loc (loc, LOOP_EXPR, void_type_node, tmp);
1815 gfc_add_expr_to_block (&block, tmp);
1816
1817 /* Add the exit label. */
1818 tmp = build1_v (LABEL_EXPR, exit_label);
1819 gfc_add_expr_to_block (&block, tmp);
1820
1821 return gfc_finish_block (&block);
1822 }
1823
1824
1825 /* Translate the DO WHILE construct.
1826
1827 We translate
1828
1829 DO WHILE (cond)
1830 body
1831 END DO
1832
1833 to:
1834
1835 for ( ; ; )
1836 {
1837 pre_cond;
1838 if (! cond) goto exit_label;
1839 body;
1840 cycle_label:
1841 }
1842 exit_label:
1843
1844 Because the evaluation of the exit condition `cond' may have side
1845 effects, we can't do much for empty loop bodies. The backend optimizers
1846 should be smart enough to eliminate any dead loops. */
1847
1848 tree
1849 gfc_trans_do_while (gfc_code * code)
1850 {
1851 gfc_se cond;
1852 tree tmp;
1853 tree cycle_label;
1854 tree exit_label;
1855 stmtblock_t block;
1856
1857 /* Everything we build here is part of the loop body. */
1858 gfc_start_block (&block);
1859
1860 /* Cycle and exit statements are implemented with gotos. */
1861 cycle_label = gfc_build_label_decl (NULL_TREE);
1862 exit_label = gfc_build_label_decl (NULL_TREE);
1863
1864 /* Put the labels where they can be found later. See gfc_trans_do(). */
1865 code->cycle_label = cycle_label;
1866 code->exit_label = exit_label;
1867
1868 /* Create a GIMPLE version of the exit condition. */
1869 gfc_init_se (&cond, NULL);
1870 gfc_conv_expr_val (&cond, code->expr1);
1871 gfc_add_block_to_block (&block, &cond.pre);
1872 cond.expr = fold_build1_loc (code->expr1->where.lb->location,
1873 TRUTH_NOT_EXPR, TREE_TYPE (cond.expr), cond.expr);
1874
1875 /* Build "IF (! cond) GOTO exit_label". */
1876 tmp = build1_v (GOTO_EXPR, exit_label);
1877 TREE_USED (exit_label) = 1;
1878 tmp = fold_build3_loc (code->expr1->where.lb->location, COND_EXPR,
1879 void_type_node, cond.expr, tmp,
1880 build_empty_stmt (code->expr1->where.lb->location));
1881 gfc_add_expr_to_block (&block, tmp);
1882
1883 /* The main body of the loop. */
1884 tmp = gfc_trans_code (code->block->next);
1885 gfc_add_expr_to_block (&block, tmp);
1886
1887 /* Label for cycle statements (if needed). */
1888 if (TREE_USED (cycle_label))
1889 {
1890 tmp = build1_v (LABEL_EXPR, cycle_label);
1891 gfc_add_expr_to_block (&block, tmp);
1892 }
1893
1894 /* End of loop body. */
1895 tmp = gfc_finish_block (&block);
1896
1897 gfc_init_block (&block);
1898 /* Build the loop. */
1899 tmp = fold_build1_loc (code->expr1->where.lb->location, LOOP_EXPR,
1900 void_type_node, tmp);
1901 gfc_add_expr_to_block (&block, tmp);
1902
1903 /* Add the exit label. */
1904 tmp = build1_v (LABEL_EXPR, exit_label);
1905 gfc_add_expr_to_block (&block, tmp);
1906
1907 return gfc_finish_block (&block);
1908 }
1909
1910
1911 /* Translate the SELECT CASE construct for INTEGER case expressions,
1912 without killing all potential optimizations. The problem is that
1913 Fortran allows unbounded cases, but the back-end does not, so we
1914 need to intercept those before we enter the equivalent SWITCH_EXPR
1915 we can build.
1916
1917 For example, we translate this,
1918
1919 SELECT CASE (expr)
1920 CASE (:100,101,105:115)
1921 block_1
1922 CASE (190:199,200:)
1923 block_2
1924 CASE (300)
1925 block_3
1926 CASE DEFAULT
1927 block_4
1928 END SELECT
1929
1930 to the GENERIC equivalent,
1931
1932 switch (expr)
1933 {
1934 case (minimum value for typeof(expr) ... 100:
1935 case 101:
1936 case 105 ... 114:
1937 block1:
1938 goto end_label;
1939
1940 case 200 ... (maximum value for typeof(expr):
1941 case 190 ... 199:
1942 block2;
1943 goto end_label;
1944
1945 case 300:
1946 block_3;
1947 goto end_label;
1948
1949 default:
1950 block_4;
1951 goto end_label;
1952 }
1953
1954 end_label: */
1955
1956 static tree
1957 gfc_trans_integer_select (gfc_code * code)
1958 {
1959 gfc_code *c;
1960 gfc_case *cp;
1961 tree end_label;
1962 tree tmp;
1963 gfc_se se;
1964 stmtblock_t block;
1965 stmtblock_t body;
1966
1967 gfc_start_block (&block);
1968
1969 /* Calculate the switch expression. */
1970 gfc_init_se (&se, NULL);
1971 gfc_conv_expr_val (&se, code->expr1);
1972 gfc_add_block_to_block (&block, &se.pre);
1973
1974 end_label = gfc_build_label_decl (NULL_TREE);
1975
1976 gfc_init_block (&body);
1977
1978 for (c = code->block; c; c = c->block)
1979 {
1980 for (cp = c->ext.block.case_list; cp; cp = cp->next)
1981 {
1982 tree low, high;
1983 tree label;
1984
1985 /* Assume it's the default case. */
1986 low = high = NULL_TREE;
1987
1988 if (cp->low)
1989 {
1990 low = gfc_conv_mpz_to_tree (cp->low->value.integer,
1991 cp->low->ts.kind);
1992
1993 /* If there's only a lower bound, set the high bound to the
1994 maximum value of the case expression. */
1995 if (!cp->high)
1996 high = TYPE_MAX_VALUE (TREE_TYPE (se.expr));
1997 }
1998
1999 if (cp->high)
2000 {
2001 /* Three cases are possible here:
2002
2003 1) There is no lower bound, e.g. CASE (:N).
2004 2) There is a lower bound .NE. high bound, that is
2005 a case range, e.g. CASE (N:M) where M>N (we make
2006 sure that M>N during type resolution).
2007 3) There is a lower bound, and it has the same value
2008 as the high bound, e.g. CASE (N:N). This is our
2009 internal representation of CASE(N).
2010
2011 In the first and second case, we need to set a value for
2012 high. In the third case, we don't because the GCC middle
2013 end represents a single case value by just letting high be
2014 a NULL_TREE. We can't do that because we need to be able
2015 to represent unbounded cases. */
2016
2017 if (!cp->low
2018 || (cp->low
2019 && mpz_cmp (cp->low->value.integer,
2020 cp->high->value.integer) != 0))
2021 high = gfc_conv_mpz_to_tree (cp->high->value.integer,
2022 cp->high->ts.kind);
2023
2024 /* Unbounded case. */
2025 if (!cp->low)
2026 low = TYPE_MIN_VALUE (TREE_TYPE (se.expr));
2027 }
2028
2029 /* Build a label. */
2030 label = gfc_build_label_decl (NULL_TREE);
2031
2032 /* Add this case label.
2033 Add parameter 'label', make it match GCC backend. */
2034 tmp = build_case_label (low, high, label);
2035 gfc_add_expr_to_block (&body, tmp);
2036 }
2037
2038 /* Add the statements for this case. */
2039 tmp = gfc_trans_code (c->next);
2040 gfc_add_expr_to_block (&body, tmp);
2041
2042 /* Break to the end of the construct. */
2043 tmp = build1_v (GOTO_EXPR, end_label);
2044 gfc_add_expr_to_block (&body, tmp);
2045 }
2046
2047 tmp = gfc_finish_block (&body);
2048 tmp = fold_build3_loc (input_location, SWITCH_EXPR, NULL_TREE,
2049 se.expr, tmp, NULL_TREE);
2050 gfc_add_expr_to_block (&block, tmp);
2051
2052 tmp = build1_v (LABEL_EXPR, end_label);
2053 gfc_add_expr_to_block (&block, tmp);
2054
2055 return gfc_finish_block (&block);
2056 }
2057
2058
2059 /* Translate the SELECT CASE construct for LOGICAL case expressions.
2060
2061 There are only two cases possible here, even though the standard
2062 does allow three cases in a LOGICAL SELECT CASE construct: .TRUE.,
2063 .FALSE., and DEFAULT.
2064
2065 We never generate more than two blocks here. Instead, we always
2066 try to eliminate the DEFAULT case. This way, we can translate this
2067 kind of SELECT construct to a simple
2068
2069 if {} else {};
2070
2071 expression in GENERIC. */
2072
2073 static tree
2074 gfc_trans_logical_select (gfc_code * code)
2075 {
2076 gfc_code *c;
2077 gfc_code *t, *f, *d;
2078 gfc_case *cp;
2079 gfc_se se;
2080 stmtblock_t block;
2081
2082 /* Assume we don't have any cases at all. */
2083 t = f = d = NULL;
2084
2085 /* Now see which ones we actually do have. We can have at most two
2086 cases in a single case list: one for .TRUE. and one for .FALSE.
2087 The default case is always separate. If the cases for .TRUE. and
2088 .FALSE. are in the same case list, the block for that case list
2089 always executed, and we don't generate code a COND_EXPR. */
2090 for (c = code->block; c; c = c->block)
2091 {
2092 for (cp = c->ext.block.case_list; cp; cp = cp->next)
2093 {
2094 if (cp->low)
2095 {
2096 if (cp->low->value.logical == 0) /* .FALSE. */
2097 f = c;
2098 else /* if (cp->value.logical != 0), thus .TRUE. */
2099 t = c;
2100 }
2101 else
2102 d = c;
2103 }
2104 }
2105
2106 /* Start a new block. */
2107 gfc_start_block (&block);
2108
2109 /* Calculate the switch expression. We always need to do this
2110 because it may have side effects. */
2111 gfc_init_se (&se, NULL);
2112 gfc_conv_expr_val (&se, code->expr1);
2113 gfc_add_block_to_block (&block, &se.pre);
2114
2115 if (t == f && t != NULL)
2116 {
2117 /* Cases for .TRUE. and .FALSE. are in the same block. Just
2118 translate the code for these cases, append it to the current
2119 block. */
2120 gfc_add_expr_to_block (&block, gfc_trans_code (t->next));
2121 }
2122 else
2123 {
2124 tree true_tree, false_tree, stmt;
2125
2126 true_tree = build_empty_stmt (input_location);
2127 false_tree = build_empty_stmt (input_location);
2128
2129 /* If we have a case for .TRUE. and for .FALSE., discard the default case.
2130 Otherwise, if .TRUE. or .FALSE. is missing and there is a default case,
2131 make the missing case the default case. */
2132 if (t != NULL && f != NULL)
2133 d = NULL;
2134 else if (d != NULL)
2135 {
2136 if (t == NULL)
2137 t = d;
2138 else
2139 f = d;
2140 }
2141
2142 /* Translate the code for each of these blocks, and append it to
2143 the current block. */
2144 if (t != NULL)
2145 true_tree = gfc_trans_code (t->next);
2146
2147 if (f != NULL)
2148 false_tree = gfc_trans_code (f->next);
2149
2150 stmt = fold_build3_loc (input_location, COND_EXPR, void_type_node,
2151 se.expr, true_tree, false_tree);
2152 gfc_add_expr_to_block (&block, stmt);
2153 }
2154
2155 return gfc_finish_block (&block);
2156 }
2157
2158
2159 /* The jump table types are stored in static variables to avoid
2160 constructing them from scratch every single time. */
2161 static GTY(()) tree select_struct[2];
2162
2163 /* Translate the SELECT CASE construct for CHARACTER case expressions.
2164 Instead of generating compares and jumps, it is far simpler to
2165 generate a data structure describing the cases in order and call a
2166 library subroutine that locates the right case.
2167 This is particularly true because this is the only case where we
2168 might have to dispose of a temporary.
2169 The library subroutine returns a pointer to jump to or NULL if no
2170 branches are to be taken. */
2171
2172 static tree
2173 gfc_trans_character_select (gfc_code *code)
2174 {
2175 tree init, end_label, tmp, type, case_num, label, fndecl;
2176 stmtblock_t block, body;
2177 gfc_case *cp, *d;
2178 gfc_code *c;
2179 gfc_se se, expr1se;
2180 int n, k;
2181 vec<constructor_elt, va_gc> *inits = NULL;
2182
2183 tree pchartype = gfc_get_pchar_type (code->expr1->ts.kind);
2184
2185 /* The jump table types are stored in static variables to avoid
2186 constructing them from scratch every single time. */
2187 static tree ss_string1[2], ss_string1_len[2];
2188 static tree ss_string2[2], ss_string2_len[2];
2189 static tree ss_target[2];
2190
2191 cp = code->block->ext.block.case_list;
2192 while (cp->left != NULL)
2193 cp = cp->left;
2194
2195 /* Generate the body */
2196 gfc_start_block (&block);
2197 gfc_init_se (&expr1se, NULL);
2198 gfc_conv_expr_reference (&expr1se, code->expr1);
2199
2200 gfc_add_block_to_block (&block, &expr1se.pre);
2201
2202 end_label = gfc_build_label_decl (NULL_TREE);
2203
2204 gfc_init_block (&body);
2205
2206 /* Attempt to optimize length 1 selects. */
2207 if (integer_onep (expr1se.string_length))
2208 {
2209 for (d = cp; d; d = d->right)
2210 {
2211 int i;
2212 if (d->low)
2213 {
2214 gcc_assert (d->low->expr_type == EXPR_CONSTANT
2215 && d->low->ts.type == BT_CHARACTER);
2216 if (d->low->value.character.length > 1)
2217 {
2218 for (i = 1; i < d->low->value.character.length; i++)
2219 if (d->low->value.character.string[i] != ' ')
2220 break;
2221 if (i != d->low->value.character.length)
2222 {
2223 if (optimize && d->high && i == 1)
2224 {
2225 gcc_assert (d->high->expr_type == EXPR_CONSTANT
2226 && d->high->ts.type == BT_CHARACTER);
2227 if (d->high->value.character.length > 1
2228 && (d->low->value.character.string[0]
2229 == d->high->value.character.string[0])
2230 && d->high->value.character.string[1] != ' '
2231 && ((d->low->value.character.string[1] < ' ')
2232 == (d->high->value.character.string[1]
2233 < ' ')))
2234 continue;
2235 }
2236 break;
2237 }
2238 }
2239 }
2240 if (d->high)
2241 {
2242 gcc_assert (d->high->expr_type == EXPR_CONSTANT
2243 && d->high->ts.type == BT_CHARACTER);
2244 if (d->high->value.character.length > 1)
2245 {
2246 for (i = 1; i < d->high->value.character.length; i++)
2247 if (d->high->value.character.string[i] != ' ')
2248 break;
2249 if (i != d->high->value.character.length)
2250 break;
2251 }
2252 }
2253 }
2254 if (d == NULL)
2255 {
2256 tree ctype = gfc_get_char_type (code->expr1->ts.kind);
2257
2258 for (c = code->block; c; c = c->block)
2259 {
2260 for (cp = c->ext.block.case_list; cp; cp = cp->next)
2261 {
2262 tree low, high;
2263 tree label;
2264 gfc_char_t r;
2265
2266 /* Assume it's the default case. */
2267 low = high = NULL_TREE;
2268
2269 if (cp->low)
2270 {
2271 /* CASE ('ab') or CASE ('ab':'az') will never match
2272 any length 1 character. */
2273 if (cp->low->value.character.length > 1
2274 && cp->low->value.character.string[1] != ' ')
2275 continue;
2276
2277 if (cp->low->value.character.length > 0)
2278 r = cp->low->value.character.string[0];
2279 else
2280 r = ' ';
2281 low = build_int_cst (ctype, r);
2282
2283 /* If there's only a lower bound, set the high bound
2284 to the maximum value of the case expression. */
2285 if (!cp->high)
2286 high = TYPE_MAX_VALUE (ctype);
2287 }
2288
2289 if (cp->high)
2290 {
2291 if (!cp->low
2292 || (cp->low->value.character.string[0]
2293 != cp->high->value.character.string[0]))
2294 {
2295 if (cp->high->value.character.length > 0)
2296 r = cp->high->value.character.string[0];
2297 else
2298 r = ' ';
2299 high = build_int_cst (ctype, r);
2300 }
2301
2302 /* Unbounded case. */
2303 if (!cp->low)
2304 low = TYPE_MIN_VALUE (ctype);
2305 }
2306
2307 /* Build a label. */
2308 label = gfc_build_label_decl (NULL_TREE);
2309
2310 /* Add this case label.
2311 Add parameter 'label', make it match GCC backend. */
2312 tmp = build_case_label (low, high, label);
2313 gfc_add_expr_to_block (&body, tmp);
2314 }
2315
2316 /* Add the statements for this case. */
2317 tmp = gfc_trans_code (c->next);
2318 gfc_add_expr_to_block (&body, tmp);
2319
2320 /* Break to the end of the construct. */
2321 tmp = build1_v (GOTO_EXPR, end_label);
2322 gfc_add_expr_to_block (&body, tmp);
2323 }
2324
2325 tmp = gfc_string_to_single_character (expr1se.string_length,
2326 expr1se.expr,
2327 code->expr1->ts.kind);
2328 case_num = gfc_create_var (ctype, "case_num");
2329 gfc_add_modify (&block, case_num, tmp);
2330
2331 gfc_add_block_to_block (&block, &expr1se.post);
2332
2333 tmp = gfc_finish_block (&body);
2334 tmp = fold_build3_loc (input_location, SWITCH_EXPR, NULL_TREE,
2335 case_num, tmp, NULL_TREE);
2336 gfc_add_expr_to_block (&block, tmp);
2337
2338 tmp = build1_v (LABEL_EXPR, end_label);
2339 gfc_add_expr_to_block (&block, tmp);
2340
2341 return gfc_finish_block (&block);
2342 }
2343 }
2344
2345 if (code->expr1->ts.kind == 1)
2346 k = 0;
2347 else if (code->expr1->ts.kind == 4)
2348 k = 1;
2349 else
2350 gcc_unreachable ();
2351
2352 if (select_struct[k] == NULL)
2353 {
2354 tree *chain = NULL;
2355 select_struct[k] = make_node (RECORD_TYPE);
2356
2357 if (code->expr1->ts.kind == 1)
2358 TYPE_NAME (select_struct[k]) = get_identifier ("_jump_struct_char1");
2359 else if (code->expr1->ts.kind == 4)
2360 TYPE_NAME (select_struct[k]) = get_identifier ("_jump_struct_char4");
2361 else
2362 gcc_unreachable ();
2363
2364 #undef ADD_FIELD
2365 #define ADD_FIELD(NAME, TYPE) \
2366 ss_##NAME[k] = gfc_add_field_to_struct (select_struct[k], \
2367 get_identifier (stringize(NAME)), \
2368 TYPE, \
2369 &chain)
2370
2371 ADD_FIELD (string1, pchartype);
2372 ADD_FIELD (string1_len, gfc_charlen_type_node);
2373
2374 ADD_FIELD (string2, pchartype);
2375 ADD_FIELD (string2_len, gfc_charlen_type_node);
2376
2377 ADD_FIELD (target, integer_type_node);
2378 #undef ADD_FIELD
2379
2380 gfc_finish_type (select_struct[k]);
2381 }
2382
2383 n = 0;
2384 for (d = cp; d; d = d->right)
2385 d->n = n++;
2386
2387 for (c = code->block; c; c = c->block)
2388 {
2389 for (d = c->ext.block.case_list; d; d = d->next)
2390 {
2391 label = gfc_build_label_decl (NULL_TREE);
2392 tmp = build_case_label ((d->low == NULL && d->high == NULL)
2393 ? NULL
2394 : build_int_cst (integer_type_node, d->n),
2395 NULL, label);
2396 gfc_add_expr_to_block (&body, tmp);
2397 }
2398
2399 tmp = gfc_trans_code (c->next);
2400 gfc_add_expr_to_block (&body, tmp);
2401
2402 tmp = build1_v (GOTO_EXPR, end_label);
2403 gfc_add_expr_to_block (&body, tmp);
2404 }
2405
2406 /* Generate the structure describing the branches */
2407 for (d = cp; d; d = d->right)
2408 {
2409 vec<constructor_elt, va_gc> *node = NULL;
2410
2411 gfc_init_se (&se, NULL);
2412
2413 if (d->low == NULL)
2414 {
2415 CONSTRUCTOR_APPEND_ELT (node, ss_string1[k], null_pointer_node);
2416 CONSTRUCTOR_APPEND_ELT (node, ss_string1_len[k], integer_zero_node);
2417 }
2418 else
2419 {
2420 gfc_conv_expr_reference (&se, d->low);
2421
2422 CONSTRUCTOR_APPEND_ELT (node, ss_string1[k], se.expr);
2423 CONSTRUCTOR_APPEND_ELT (node, ss_string1_len[k], se.string_length);
2424 }
2425
2426 if (d->high == NULL)
2427 {
2428 CONSTRUCTOR_APPEND_ELT (node, ss_string2[k], null_pointer_node);
2429 CONSTRUCTOR_APPEND_ELT (node, ss_string2_len[k], integer_zero_node);
2430 }
2431 else
2432 {
2433 gfc_init_se (&se, NULL);
2434 gfc_conv_expr_reference (&se, d->high);
2435
2436 CONSTRUCTOR_APPEND_ELT (node, ss_string2[k], se.expr);
2437 CONSTRUCTOR_APPEND_ELT (node, ss_string2_len[k], se.string_length);
2438 }
2439
2440 CONSTRUCTOR_APPEND_ELT (node, ss_target[k],
2441 build_int_cst (integer_type_node, d->n));
2442
2443 tmp = build_constructor (select_struct[k], node);
2444 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, tmp);
2445 }
2446
2447 type = build_array_type (select_struct[k],
2448 build_index_type (size_int (n-1)));
2449
2450 init = build_constructor (type, inits);
2451 TREE_CONSTANT (init) = 1;
2452 TREE_STATIC (init) = 1;
2453 /* Create a static variable to hold the jump table. */
2454 tmp = gfc_create_var (type, "jumptable");
2455 TREE_CONSTANT (tmp) = 1;
2456 TREE_STATIC (tmp) = 1;
2457 TREE_READONLY (tmp) = 1;
2458 DECL_INITIAL (tmp) = init;
2459 init = tmp;
2460
2461 /* Build the library call */
2462 init = gfc_build_addr_expr (pvoid_type_node, init);
2463
2464 if (code->expr1->ts.kind == 1)
2465 fndecl = gfor_fndecl_select_string;
2466 else if (code->expr1->ts.kind == 4)
2467 fndecl = gfor_fndecl_select_string_char4;
2468 else
2469 gcc_unreachable ();
2470
2471 tmp = build_call_expr_loc (input_location,
2472 fndecl, 4, init,
2473 build_int_cst (gfc_charlen_type_node, n),
2474 expr1se.expr, expr1se.string_length);
2475 case_num = gfc_create_var (integer_type_node, "case_num");
2476 gfc_add_modify (&block, case_num, tmp);
2477
2478 gfc_add_block_to_block (&block, &expr1se.post);
2479
2480 tmp = gfc_finish_block (&body);
2481 tmp = fold_build3_loc (input_location, SWITCH_EXPR, NULL_TREE,
2482 case_num, tmp, NULL_TREE);
2483 gfc_add_expr_to_block (&block, tmp);
2484
2485 tmp = build1_v (LABEL_EXPR, end_label);
2486 gfc_add_expr_to_block (&block, tmp);
2487
2488 return gfc_finish_block (&block);
2489 }
2490
2491
2492 /* Translate the three variants of the SELECT CASE construct.
2493
2494 SELECT CASEs with INTEGER case expressions can be translated to an
2495 equivalent GENERIC switch statement, and for LOGICAL case
2496 expressions we build one or two if-else compares.
2497
2498 SELECT CASEs with CHARACTER case expressions are a whole different
2499 story, because they don't exist in GENERIC. So we sort them and
2500 do a binary search at runtime.
2501
2502 Fortran has no BREAK statement, and it does not allow jumps from
2503 one case block to another. That makes things a lot easier for
2504 the optimizers. */
2505
2506 tree
2507 gfc_trans_select (gfc_code * code)
2508 {
2509 stmtblock_t block;
2510 tree body;
2511 tree exit_label;
2512
2513 gcc_assert (code && code->expr1);
2514 gfc_init_block (&block);
2515
2516 /* Build the exit label and hang it in. */
2517 exit_label = gfc_build_label_decl (NULL_TREE);
2518 code->exit_label = exit_label;
2519
2520 /* Empty SELECT constructs are legal. */
2521 if (code->block == NULL)
2522 body = build_empty_stmt (input_location);
2523
2524 /* Select the correct translation function. */
2525 else
2526 switch (code->expr1->ts.type)
2527 {
2528 case BT_LOGICAL:
2529 body = gfc_trans_logical_select (code);
2530 break;
2531
2532 case BT_INTEGER:
2533 body = gfc_trans_integer_select (code);
2534 break;
2535
2536 case BT_CHARACTER:
2537 body = gfc_trans_character_select (code);
2538 break;
2539
2540 default:
2541 gfc_internal_error ("gfc_trans_select(): Bad type for case expr.");
2542 /* Not reached */
2543 }
2544
2545 /* Build everything together. */
2546 gfc_add_expr_to_block (&block, body);
2547 gfc_add_expr_to_block (&block, build1_v (LABEL_EXPR, exit_label));
2548
2549 return gfc_finish_block (&block);
2550 }
2551
2552
2553 /* Traversal function to substitute a replacement symtree if the symbol
2554 in the expression is the same as that passed. f == 2 signals that
2555 that variable itself is not to be checked - only the references.
2556 This group of functions is used when the variable expression in a
2557 FORALL assignment has internal references. For example:
2558 FORALL (i = 1:4) p(p(i)) = i
2559 The only recourse here is to store a copy of 'p' for the index
2560 expression. */
2561
2562 static gfc_symtree *new_symtree;
2563 static gfc_symtree *old_symtree;
2564
2565 static bool
2566 forall_replace (gfc_expr *expr, gfc_symbol *sym, int *f)
2567 {
2568 if (expr->expr_type != EXPR_VARIABLE)
2569 return false;
2570
2571 if (*f == 2)
2572 *f = 1;
2573 else if (expr->symtree->n.sym == sym)
2574 expr->symtree = new_symtree;
2575
2576 return false;
2577 }
2578
2579 static void
2580 forall_replace_symtree (gfc_expr *e, gfc_symbol *sym, int f)
2581 {
2582 gfc_traverse_expr (e, sym, forall_replace, f);
2583 }
2584
2585 static bool
2586 forall_restore (gfc_expr *expr,
2587 gfc_symbol *sym ATTRIBUTE_UNUSED,
2588 int *f ATTRIBUTE_UNUSED)
2589 {
2590 if (expr->expr_type != EXPR_VARIABLE)
2591 return false;
2592
2593 if (expr->symtree == new_symtree)
2594 expr->symtree = old_symtree;
2595
2596 return false;
2597 }
2598
2599 static void
2600 forall_restore_symtree (gfc_expr *e)
2601 {
2602 gfc_traverse_expr (e, NULL, forall_restore, 0);
2603 }
2604
2605 static void
2606 forall_make_variable_temp (gfc_code *c, stmtblock_t *pre, stmtblock_t *post)
2607 {
2608 gfc_se tse;
2609 gfc_se rse;
2610 gfc_expr *e;
2611 gfc_symbol *new_sym;
2612 gfc_symbol *old_sym;
2613 gfc_symtree *root;
2614 tree tmp;
2615
2616 /* Build a copy of the lvalue. */
2617 old_symtree = c->expr1->symtree;
2618 old_sym = old_symtree->n.sym;
2619 e = gfc_lval_expr_from_sym (old_sym);
2620 if (old_sym->attr.dimension)
2621 {
2622 gfc_init_se (&tse, NULL);
2623 gfc_conv_subref_array_arg (&tse, e, 0, INTENT_IN, false);
2624 gfc_add_block_to_block (pre, &tse.pre);
2625 gfc_add_block_to_block (post, &tse.post);
2626 tse.expr = build_fold_indirect_ref_loc (input_location, tse.expr);
2627
2628 if (e->ts.type != BT_CHARACTER)
2629 {
2630 /* Use the variable offset for the temporary. */
2631 tmp = gfc_conv_array_offset (old_sym->backend_decl);
2632 gfc_conv_descriptor_offset_set (pre, tse.expr, tmp);
2633 }
2634 }
2635 else
2636 {
2637 gfc_init_se (&tse, NULL);
2638 gfc_init_se (&rse, NULL);
2639 gfc_conv_expr (&rse, e);
2640 if (e->ts.type == BT_CHARACTER)
2641 {
2642 tse.string_length = rse.string_length;
2643 tmp = gfc_get_character_type_len (gfc_default_character_kind,
2644 tse.string_length);
2645 tse.expr = gfc_conv_string_tmp (&tse, build_pointer_type (tmp),
2646 rse.string_length);
2647 gfc_add_block_to_block (pre, &tse.pre);
2648 gfc_add_block_to_block (post, &tse.post);
2649 }
2650 else
2651 {
2652 tmp = gfc_typenode_for_spec (&e->ts);
2653 tse.expr = gfc_create_var (tmp, "temp");
2654 }
2655
2656 tmp = gfc_trans_scalar_assign (&tse, &rse, e->ts, true,
2657 e->expr_type == EXPR_VARIABLE, true);
2658 gfc_add_expr_to_block (pre, tmp);
2659 }
2660 gfc_free_expr (e);
2661
2662 /* Create a new symbol to represent the lvalue. */
2663 new_sym = gfc_new_symbol (old_sym->name, NULL);
2664 new_sym->ts = old_sym->ts;
2665 new_sym->attr.referenced = 1;
2666 new_sym->attr.temporary = 1;
2667 new_sym->attr.dimension = old_sym->attr.dimension;
2668 new_sym->attr.flavor = old_sym->attr.flavor;
2669
2670 /* Use the temporary as the backend_decl. */
2671 new_sym->backend_decl = tse.expr;
2672
2673 /* Create a fake symtree for it. */
2674 root = NULL;
2675 new_symtree = gfc_new_symtree (&root, old_sym->name);
2676 new_symtree->n.sym = new_sym;
2677 gcc_assert (new_symtree == root);
2678
2679 /* Go through the expression reference replacing the old_symtree
2680 with the new. */
2681 forall_replace_symtree (c->expr1, old_sym, 2);
2682
2683 /* Now we have made this temporary, we might as well use it for
2684 the right hand side. */
2685 forall_replace_symtree (c->expr2, old_sym, 1);
2686 }
2687
2688
2689 /* Handles dependencies in forall assignments. */
2690 static int
2691 check_forall_dependencies (gfc_code *c, stmtblock_t *pre, stmtblock_t *post)
2692 {
2693 gfc_ref *lref;
2694 gfc_ref *rref;
2695 int need_temp;
2696 gfc_symbol *lsym;
2697
2698 lsym = c->expr1->symtree->n.sym;
2699 need_temp = gfc_check_dependency (c->expr1, c->expr2, 0);
2700
2701 /* Now check for dependencies within the 'variable'
2702 expression itself. These are treated by making a complete
2703 copy of variable and changing all the references to it
2704 point to the copy instead. Note that the shallow copy of
2705 the variable will not suffice for derived types with
2706 pointer components. We therefore leave these to their
2707 own devices. */
2708 if (lsym->ts.type == BT_DERIVED
2709 && lsym->ts.u.derived->attr.pointer_comp)
2710 return need_temp;
2711
2712 new_symtree = NULL;
2713 if (find_forall_index (c->expr1, lsym, 2))
2714 {
2715 forall_make_variable_temp (c, pre, post);
2716 need_temp = 0;
2717 }
2718
2719 /* Substrings with dependencies are treated in the same
2720 way. */
2721 if (c->expr1->ts.type == BT_CHARACTER
2722 && c->expr1->ref
2723 && c->expr2->expr_type == EXPR_VARIABLE
2724 && lsym == c->expr2->symtree->n.sym)
2725 {
2726 for (lref = c->expr1->ref; lref; lref = lref->next)
2727 if (lref->type == REF_SUBSTRING)
2728 break;
2729 for (rref = c->expr2->ref; rref; rref = rref->next)
2730 if (rref->type == REF_SUBSTRING)
2731 break;
2732
2733 if (rref && lref
2734 && gfc_dep_compare_expr (rref->u.ss.start, lref->u.ss.start) < 0)
2735 {
2736 forall_make_variable_temp (c, pre, post);
2737 need_temp = 0;
2738 }
2739 }
2740 return need_temp;
2741 }
2742
2743
2744 static void
2745 cleanup_forall_symtrees (gfc_code *c)
2746 {
2747 forall_restore_symtree (c->expr1);
2748 forall_restore_symtree (c->expr2);
2749 free (new_symtree->n.sym);
2750 free (new_symtree);
2751 }
2752
2753
2754 /* Generate the loops for a FORALL block, specified by FORALL_TMP. BODY
2755 is the contents of the FORALL block/stmt to be iterated. MASK_FLAG
2756 indicates whether we should generate code to test the FORALLs mask
2757 array. OUTER is the loop header to be used for initializing mask
2758 indices.
2759
2760 The generated loop format is:
2761 count = (end - start + step) / step
2762 loopvar = start
2763 while (1)
2764 {
2765 if (count <=0 )
2766 goto end_of_loop
2767 <body>
2768 loopvar += step
2769 count --
2770 }
2771 end_of_loop: */
2772
2773 static tree
2774 gfc_trans_forall_loop (forall_info *forall_tmp, tree body,
2775 int mask_flag, stmtblock_t *outer)
2776 {
2777 int n, nvar;
2778 tree tmp;
2779 tree cond;
2780 stmtblock_t block;
2781 tree exit_label;
2782 tree count;
2783 tree var, start, end, step;
2784 iter_info *iter;
2785
2786 /* Initialize the mask index outside the FORALL nest. */
2787 if (mask_flag && forall_tmp->mask)
2788 gfc_add_modify (outer, forall_tmp->maskindex, gfc_index_zero_node);
2789
2790 iter = forall_tmp->this_loop;
2791 nvar = forall_tmp->nvar;
2792 for (n = 0; n < nvar; n++)
2793 {
2794 var = iter->var;
2795 start = iter->start;
2796 end = iter->end;
2797 step = iter->step;
2798
2799 exit_label = gfc_build_label_decl (NULL_TREE);
2800 TREE_USED (exit_label) = 1;
2801
2802 /* The loop counter. */
2803 count = gfc_create_var (TREE_TYPE (var), "count");
2804
2805 /* The body of the loop. */
2806 gfc_init_block (&block);
2807
2808 /* The exit condition. */
2809 cond = fold_build2_loc (input_location, LE_EXPR, boolean_type_node,
2810 count, build_int_cst (TREE_TYPE (count), 0));
2811 if (forall_tmp->do_concurrent)
2812 cond = build2 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
2813 build_int_cst (integer_type_node,
2814 annot_expr_ivdep_kind));
2815
2816 tmp = build1_v (GOTO_EXPR, exit_label);
2817 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
2818 cond, tmp, build_empty_stmt (input_location));
2819 gfc_add_expr_to_block (&block, tmp);
2820
2821 /* The main loop body. */
2822 gfc_add_expr_to_block (&block, body);
2823
2824 /* Increment the loop variable. */
2825 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (var), var,
2826 step);
2827 gfc_add_modify (&block, var, tmp);
2828
2829 /* Advance to the next mask element. Only do this for the
2830 innermost loop. */
2831 if (n == 0 && mask_flag && forall_tmp->mask)
2832 {
2833 tree maskindex = forall_tmp->maskindex;
2834 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
2835 maskindex, gfc_index_one_node);
2836 gfc_add_modify (&block, maskindex, tmp);
2837 }
2838
2839 /* Decrement the loop counter. */
2840 tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (var), count,
2841 build_int_cst (TREE_TYPE (var), 1));
2842 gfc_add_modify (&block, count, tmp);
2843
2844 body = gfc_finish_block (&block);
2845
2846 /* Loop var initialization. */
2847 gfc_init_block (&block);
2848 gfc_add_modify (&block, var, start);
2849
2850
2851 /* Initialize the loop counter. */
2852 tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (var), step,
2853 start);
2854 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (var), end,
2855 tmp);
2856 tmp = fold_build2_loc (input_location, TRUNC_DIV_EXPR, TREE_TYPE (var),
2857 tmp, step);
2858 gfc_add_modify (&block, count, tmp);
2859
2860 /* The loop expression. */
2861 tmp = build1_v (LOOP_EXPR, body);
2862 gfc_add_expr_to_block (&block, tmp);
2863
2864 /* The exit label. */
2865 tmp = build1_v (LABEL_EXPR, exit_label);
2866 gfc_add_expr_to_block (&block, tmp);
2867
2868 body = gfc_finish_block (&block);
2869 iter = iter->next;
2870 }
2871 return body;
2872 }
2873
2874
2875 /* Generate the body and loops according to MASK_FLAG. If MASK_FLAG
2876 is nonzero, the body is controlled by all masks in the forall nest.
2877 Otherwise, the innermost loop is not controlled by it's mask. This
2878 is used for initializing that mask. */
2879
2880 static tree
2881 gfc_trans_nested_forall_loop (forall_info * nested_forall_info, tree body,
2882 int mask_flag)
2883 {
2884 tree tmp;
2885 stmtblock_t header;
2886 forall_info *forall_tmp;
2887 tree mask, maskindex;
2888
2889 gfc_start_block (&header);
2890
2891 forall_tmp = nested_forall_info;
2892 while (forall_tmp != NULL)
2893 {
2894 /* Generate body with masks' control. */
2895 if (mask_flag)
2896 {
2897 mask = forall_tmp->mask;
2898 maskindex = forall_tmp->maskindex;
2899
2900 /* If a mask was specified make the assignment conditional. */
2901 if (mask)
2902 {
2903 tmp = gfc_build_array_ref (mask, maskindex, NULL);
2904 body = build3_v (COND_EXPR, tmp, body,
2905 build_empty_stmt (input_location));
2906 }
2907 }
2908 body = gfc_trans_forall_loop (forall_tmp, body, mask_flag, &header);
2909 forall_tmp = forall_tmp->prev_nest;
2910 mask_flag = 1;
2911 }
2912
2913 gfc_add_expr_to_block (&header, body);
2914 return gfc_finish_block (&header);
2915 }
2916
2917
2918 /* Allocate data for holding a temporary array. Returns either a local
2919 temporary array or a pointer variable. */
2920
2921 static tree
2922 gfc_do_allocate (tree bytesize, tree size, tree * pdata, stmtblock_t * pblock,
2923 tree elem_type)
2924 {
2925 tree tmpvar;
2926 tree type;
2927 tree tmp;
2928
2929 if (INTEGER_CST_P (size))
2930 tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
2931 size, gfc_index_one_node);
2932 else
2933 tmp = NULL_TREE;
2934
2935 type = build_range_type (gfc_array_index_type, gfc_index_zero_node, tmp);
2936 type = build_array_type (elem_type, type);
2937 if (gfc_can_put_var_on_stack (bytesize))
2938 {
2939 gcc_assert (INTEGER_CST_P (size));
2940 tmpvar = gfc_create_var (type, "temp");
2941 *pdata = NULL_TREE;
2942 }
2943 else
2944 {
2945 tmpvar = gfc_create_var (build_pointer_type (type), "temp");
2946 *pdata = convert (pvoid_type_node, tmpvar);
2947
2948 tmp = gfc_call_malloc (pblock, TREE_TYPE (tmpvar), bytesize);
2949 gfc_add_modify (pblock, tmpvar, tmp);
2950 }
2951 return tmpvar;
2952 }
2953
2954
2955 /* Generate codes to copy the temporary to the actual lhs. */
2956
2957 static tree
2958 generate_loop_for_temp_to_lhs (gfc_expr *expr, tree tmp1, tree count3,
2959 tree count1, tree wheremask, bool invert)
2960 {
2961 gfc_ss *lss;
2962 gfc_se lse, rse;
2963 stmtblock_t block, body;
2964 gfc_loopinfo loop1;
2965 tree tmp;
2966 tree wheremaskexpr;
2967
2968 /* Walk the lhs. */
2969 lss = gfc_walk_expr (expr);
2970
2971 if (lss == gfc_ss_terminator)
2972 {
2973 gfc_start_block (&block);
2974
2975 gfc_init_se (&lse, NULL);
2976
2977 /* Translate the expression. */
2978 gfc_conv_expr (&lse, expr);
2979
2980 /* Form the expression for the temporary. */
2981 tmp = gfc_build_array_ref (tmp1, count1, NULL);
2982
2983 /* Use the scalar assignment as is. */
2984 gfc_add_block_to_block (&block, &lse.pre);
2985 gfc_add_modify (&block, lse.expr, tmp);
2986 gfc_add_block_to_block (&block, &lse.post);
2987
2988 /* Increment the count1. */
2989 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (count1),
2990 count1, gfc_index_one_node);
2991 gfc_add_modify (&block, count1, tmp);
2992
2993 tmp = gfc_finish_block (&block);
2994 }
2995 else
2996 {
2997 gfc_start_block (&block);
2998
2999 gfc_init_loopinfo (&loop1);
3000 gfc_init_se (&rse, NULL);
3001 gfc_init_se (&lse, NULL);
3002
3003 /* Associate the lss with the loop. */
3004 gfc_add_ss_to_loop (&loop1, lss);
3005
3006 /* Calculate the bounds of the scalarization. */
3007 gfc_conv_ss_startstride (&loop1);
3008 /* Setup the scalarizing loops. */
3009 gfc_conv_loop_setup (&loop1, &expr->where);
3010
3011 gfc_mark_ss_chain_used (lss, 1);
3012
3013 /* Start the scalarized loop body. */
3014 gfc_start_scalarized_body (&loop1, &body);
3015
3016 /* Setup the gfc_se structures. */
3017 gfc_copy_loopinfo_to_se (&lse, &loop1);
3018 lse.ss = lss;
3019
3020 /* Form the expression of the temporary. */
3021 if (lss != gfc_ss_terminator)
3022 rse.expr = gfc_build_array_ref (tmp1, count1, NULL);
3023 /* Translate expr. */
3024 gfc_conv_expr (&lse, expr);
3025
3026 /* Use the scalar assignment. */
3027 rse.string_length = lse.string_length;
3028 tmp = gfc_trans_scalar_assign (&lse, &rse, expr->ts, false, true, true);
3029
3030 /* Form the mask expression according to the mask tree list. */
3031 if (wheremask)
3032 {
3033 wheremaskexpr = gfc_build_array_ref (wheremask, count3, NULL);
3034 if (invert)
3035 wheremaskexpr = fold_build1_loc (input_location, TRUTH_NOT_EXPR,
3036 TREE_TYPE (wheremaskexpr),
3037 wheremaskexpr);
3038 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
3039 wheremaskexpr, tmp,
3040 build_empty_stmt (input_location));
3041 }
3042
3043 gfc_add_expr_to_block (&body, tmp);
3044
3045 /* Increment count1. */
3046 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
3047 count1, gfc_index_one_node);
3048 gfc_add_modify (&body, count1, tmp);
3049
3050 /* Increment count3. */
3051 if (count3)
3052 {
3053 tmp = fold_build2_loc (input_location, PLUS_EXPR,
3054 gfc_array_index_type, count3,
3055 gfc_index_one_node);
3056 gfc_add_modify (&body, count3, tmp);
3057 }
3058
3059 /* Generate the copying loops. */
3060 gfc_trans_scalarizing_loops (&loop1, &body);
3061 gfc_add_block_to_block (&block, &loop1.pre);
3062 gfc_add_block_to_block (&block, &loop1.post);
3063 gfc_cleanup_loop (&loop1);
3064
3065 tmp = gfc_finish_block (&block);
3066 }
3067 return tmp;
3068 }
3069
3070
3071 /* Generate codes to copy rhs to the temporary. TMP1 is the address of
3072 temporary, LSS and RSS are formed in function compute_inner_temp_size(),
3073 and should not be freed. WHEREMASK is the conditional execution mask
3074 whose sense may be inverted by INVERT. */
3075
3076 static tree
3077 generate_loop_for_rhs_to_temp (gfc_expr *expr2, tree tmp1, tree count3,
3078 tree count1, gfc_ss *lss, gfc_ss *rss,
3079 tree wheremask, bool invert)
3080 {
3081 stmtblock_t block, body1;
3082 gfc_loopinfo loop;
3083 gfc_se lse;
3084 gfc_se rse;
3085 tree tmp;
3086 tree wheremaskexpr;
3087
3088 gfc_start_block (&block);
3089
3090 gfc_init_se (&rse, NULL);
3091 gfc_init_se (&lse, NULL);
3092
3093 if (lss == gfc_ss_terminator)
3094 {
3095 gfc_init_block (&body1);
3096 gfc_conv_expr (&rse, expr2);
3097 lse.expr = gfc_build_array_ref (tmp1, count1, NULL);
3098 }
3099 else
3100 {
3101 /* Initialize the loop. */
3102 gfc_init_loopinfo (&loop);
3103
3104 /* We may need LSS to determine the shape of the expression. */
3105 gfc_add_ss_to_loop (&loop, lss);
3106 gfc_add_ss_to_loop (&loop, rss);
3107
3108 gfc_conv_ss_startstride (&loop);
3109 gfc_conv_loop_setup (&loop, &expr2->where);
3110
3111 gfc_mark_ss_chain_used (rss, 1);
3112 /* Start the loop body. */
3113 gfc_start_scalarized_body (&loop, &body1);
3114
3115 /* Translate the expression. */
3116 gfc_copy_loopinfo_to_se (&rse, &loop);
3117 rse.ss = rss;
3118 gfc_conv_expr (&rse, expr2);
3119
3120 /* Form the expression of the temporary. */
3121 lse.expr = gfc_build_array_ref (tmp1, count1, NULL);
3122 }
3123
3124 /* Use the scalar assignment. */
3125 lse.string_length = rse.string_length;
3126 tmp = gfc_trans_scalar_assign (&lse, &rse, expr2->ts, true,
3127 expr2->expr_type == EXPR_VARIABLE, true);
3128
3129 /* Form the mask expression according to the mask tree list. */
3130 if (wheremask)
3131 {
3132 wheremaskexpr = gfc_build_array_ref (wheremask, count3, NULL);
3133 if (invert)
3134 wheremaskexpr = fold_build1_loc (input_location, TRUTH_NOT_EXPR,
3135 TREE_TYPE (wheremaskexpr),
3136 wheremaskexpr);
3137 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
3138 wheremaskexpr, tmp,
3139 build_empty_stmt (input_location));
3140 }
3141
3142 gfc_add_expr_to_block (&body1, tmp);
3143
3144 if (lss == gfc_ss_terminator)
3145 {
3146 gfc_add_block_to_block (&block, &body1);
3147
3148 /* Increment count1. */
3149 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (count1),
3150 count1, gfc_index_one_node);
3151 gfc_add_modify (&block, count1, tmp);
3152 }
3153 else
3154 {
3155 /* Increment count1. */
3156 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
3157 count1, gfc_index_one_node);
3158 gfc_add_modify (&body1, count1, tmp);
3159
3160 /* Increment count3. */
3161 if (count3)
3162 {
3163 tmp = fold_build2_loc (input_location, PLUS_EXPR,
3164 gfc_array_index_type,
3165 count3, gfc_index_one_node);
3166 gfc_add_modify (&body1, count3, tmp);
3167 }
3168
3169 /* Generate the copying loops. */
3170 gfc_trans_scalarizing_loops (&loop, &body1);
3171
3172 gfc_add_block_to_block (&block, &loop.pre);
3173 gfc_add_block_to_block (&block, &loop.post);
3174
3175 gfc_cleanup_loop (&loop);
3176 /* TODO: Reuse lss and rss when copying temp->lhs. Need to be careful
3177 as tree nodes in SS may not be valid in different scope. */
3178 }
3179
3180 tmp = gfc_finish_block (&block);
3181 return tmp;
3182 }
3183
3184
3185 /* Calculate the size of temporary needed in the assignment inside forall.
3186 LSS and RSS are filled in this function. */
3187
3188 static tree
3189 compute_inner_temp_size (gfc_expr *expr1, gfc_expr *expr2,
3190 stmtblock_t * pblock,
3191 gfc_ss **lss, gfc_ss **rss)
3192 {
3193 gfc_loopinfo loop;
3194 tree size;
3195 int i;
3196 int save_flag;
3197 tree tmp;
3198
3199 *lss = gfc_walk_expr (expr1);
3200 *rss = NULL;
3201
3202 size = gfc_index_one_node;
3203 if (*lss != gfc_ss_terminator)
3204 {
3205 gfc_init_loopinfo (&loop);
3206
3207 /* Walk the RHS of the expression. */
3208 *rss = gfc_walk_expr (expr2);
3209 if (*rss == gfc_ss_terminator)
3210 /* The rhs is scalar. Add a ss for the expression. */
3211 *rss = gfc_get_scalar_ss (gfc_ss_terminator, expr2);
3212
3213 /* Associate the SS with the loop. */
3214 gfc_add_ss_to_loop (&loop, *lss);
3215 /* We don't actually need to add the rhs at this point, but it might
3216 make guessing the loop bounds a bit easier. */
3217 gfc_add_ss_to_loop (&loop, *rss);
3218
3219 /* We only want the shape of the expression, not rest of the junk
3220 generated by the scalarizer. */
3221 loop.array_parameter = 1;
3222
3223 /* Calculate the bounds of the scalarization. */
3224 save_flag = gfc_option.rtcheck;
3225 gfc_option.rtcheck &= ~GFC_RTCHECK_BOUNDS;
3226 gfc_conv_ss_startstride (&loop);
3227 gfc_option.rtcheck = save_flag;
3228 gfc_conv_loop_setup (&loop, &expr2->where);
3229
3230 /* Figure out how many elements we need. */
3231 for (i = 0; i < loop.dimen; i++)
3232 {
3233 tmp = fold_build2_loc (input_location, MINUS_EXPR,
3234 gfc_array_index_type,
3235 gfc_index_one_node, loop.from[i]);
3236 tmp = fold_build2_loc (input_location, PLUS_EXPR,
3237 gfc_array_index_type, tmp, loop.to[i]);
3238 size = fold_build2_loc (input_location, MULT_EXPR,
3239 gfc_array_index_type, size, tmp);
3240 }
3241 gfc_add_block_to_block (pblock, &loop.pre);
3242 size = gfc_evaluate_now (size, pblock);
3243 gfc_add_block_to_block (pblock, &loop.post);
3244
3245 /* TODO: write a function that cleans up a loopinfo without freeing
3246 the SS chains. Currently a NOP. */
3247 }
3248
3249 return size;
3250 }
3251
3252
3253 /* Calculate the overall iterator number of the nested forall construct.
3254 This routine actually calculates the number of times the body of the
3255 nested forall specified by NESTED_FORALL_INFO is executed and multiplies
3256 that by the expression INNER_SIZE. The BLOCK argument specifies the
3257 block in which to calculate the result, and the optional INNER_SIZE_BODY
3258 argument contains any statements that need to executed (inside the loop)
3259 to initialize or calculate INNER_SIZE. */
3260
3261 static tree
3262 compute_overall_iter_number (forall_info *nested_forall_info, tree inner_size,
3263 stmtblock_t *inner_size_body, stmtblock_t *block)
3264 {
3265 forall_info *forall_tmp = nested_forall_info;
3266 tree tmp, number;
3267 stmtblock_t body;
3268
3269 /* We can eliminate the innermost unconditional loops with constant
3270 array bounds. */
3271 if (INTEGER_CST_P (inner_size))
3272 {
3273 while (forall_tmp
3274 && !forall_tmp->mask
3275 && INTEGER_CST_P (forall_tmp->size))
3276 {
3277 inner_size = fold_build2_loc (input_location, MULT_EXPR,
3278 gfc_array_index_type,
3279 inner_size, forall_tmp->size);
3280 forall_tmp = forall_tmp->prev_nest;
3281 }
3282
3283 /* If there are no loops left, we have our constant result. */
3284 if (!forall_tmp)
3285 return inner_size;
3286 }
3287
3288 /* Otherwise, create a temporary variable to compute the result. */
3289 number = gfc_create_var (gfc_array_index_type, "num");
3290 gfc_add_modify (block, number, gfc_index_zero_node);
3291
3292 gfc_start_block (&body);
3293 if (inner_size_body)
3294 gfc_add_block_to_block (&body, inner_size_body);
3295 if (forall_tmp)
3296 tmp = fold_build2_loc (input_location, PLUS_EXPR,
3297 gfc_array_index_type, number, inner_size);
3298 else
3299 tmp = inner_size;
3300 gfc_add_modify (&body, number, tmp);
3301 tmp = gfc_finish_block (&body);
3302
3303 /* Generate loops. */
3304 if (forall_tmp != NULL)
3305 tmp = gfc_trans_nested_forall_loop (forall_tmp, tmp, 1);
3306
3307 gfc_add_expr_to_block (block, tmp);
3308
3309 return number;
3310 }
3311
3312
3313 /* Allocate temporary for forall construct. SIZE is the size of temporary
3314 needed. PTEMP1 is returned for space free. */
3315
3316 static tree
3317 allocate_temp_for_forall_nest_1 (tree type, tree size, stmtblock_t * block,
3318 tree * ptemp1)
3319 {
3320 tree bytesize;
3321 tree unit;
3322 tree tmp;
3323
3324 unit = fold_convert (gfc_array_index_type, TYPE_SIZE_UNIT (type));
3325 if (!integer_onep (unit))
3326 bytesize = fold_build2_loc (input_location, MULT_EXPR,
3327 gfc_array_index_type, size, unit);
3328 else
3329 bytesize = size;
3330
3331 *ptemp1 = NULL;
3332 tmp = gfc_do_allocate (bytesize, size, ptemp1, block, type);
3333
3334 if (*ptemp1)
3335 tmp = build_fold_indirect_ref_loc (input_location, tmp);
3336 return tmp;
3337 }
3338
3339
3340 /* Allocate temporary for forall construct according to the information in
3341 nested_forall_info. INNER_SIZE is the size of temporary needed in the
3342 assignment inside forall. PTEMP1 is returned for space free. */
3343
3344 static tree
3345 allocate_temp_for_forall_nest (forall_info * nested_forall_info, tree type,
3346 tree inner_size, stmtblock_t * inner_size_body,
3347 stmtblock_t * block, tree * ptemp1)
3348 {
3349 tree size;
3350
3351 /* Calculate the total size of temporary needed in forall construct. */
3352 size = compute_overall_iter_number (nested_forall_info, inner_size,
3353 inner_size_body, block);
3354
3355 return allocate_temp_for_forall_nest_1 (type, size, block, ptemp1);
3356 }
3357
3358
3359 /* Handle assignments inside forall which need temporary.
3360
3361 forall (i=start:end:stride; maskexpr)
3362 e<i> = f<i>
3363 end forall
3364 (where e,f<i> are arbitrary expressions possibly involving i
3365 and there is a dependency between e<i> and f<i>)
3366 Translates to:
3367 masktmp(:) = maskexpr(:)
3368
3369 maskindex = 0;
3370 count1 = 0;
3371 num = 0;
3372 for (i = start; i <= end; i += stride)
3373 num += SIZE (f<i>)
3374 count1 = 0;
3375 ALLOCATE (tmp(num))
3376 for (i = start; i <= end; i += stride)
3377 {
3378 if (masktmp[maskindex++])
3379 tmp[count1++] = f<i>
3380 }
3381 maskindex = 0;
3382 count1 = 0;
3383 for (i = start; i <= end; i += stride)
3384 {
3385 if (masktmp[maskindex++])
3386 e<i> = tmp[count1++]
3387 }
3388 DEALLOCATE (tmp)
3389 */
3390 static void
3391 gfc_trans_assign_need_temp (gfc_expr * expr1, gfc_expr * expr2,
3392 tree wheremask, bool invert,
3393 forall_info * nested_forall_info,
3394 stmtblock_t * block)
3395 {
3396 tree type;
3397 tree inner_size;
3398 gfc_ss *lss, *rss;
3399 tree count, count1;
3400 tree tmp, tmp1;
3401 tree ptemp1;
3402 stmtblock_t inner_size_body;
3403
3404 /* Create vars. count1 is the current iterator number of the nested
3405 forall. */
3406 count1 = gfc_create_var (gfc_array_index_type, "count1");
3407
3408 /* Count is the wheremask index. */
3409 if (wheremask)
3410 {
3411 count = gfc_create_var (gfc_array_index_type, "count");
3412 gfc_add_modify (block, count, gfc_index_zero_node);
3413 }
3414 else
3415 count = NULL;
3416
3417 /* Initialize count1. */
3418 gfc_add_modify (block, count1, gfc_index_zero_node);
3419
3420 /* Calculate the size of temporary needed in the assignment. Return loop, lss
3421 and rss which are used in function generate_loop_for_rhs_to_temp(). */
3422 gfc_init_block (&inner_size_body);
3423 inner_size = compute_inner_temp_size (expr1, expr2, &inner_size_body,
3424 &lss, &rss);
3425
3426 /* The type of LHS. Used in function allocate_temp_for_forall_nest */
3427 if (expr1->ts.type == BT_CHARACTER && expr1->ts.u.cl->length)
3428 {
3429 if (!expr1->ts.u.cl->backend_decl)
3430 {
3431 gfc_se tse;
3432 gfc_init_se (&tse, NULL);
3433 gfc_conv_expr (&tse, expr1->ts.u.cl->length);
3434 expr1->ts.u.cl->backend_decl = tse.expr;
3435 }
3436 type = gfc_get_character_type_len (gfc_default_character_kind,
3437 expr1->ts.u.cl->backend_decl);
3438 }
3439 else
3440 type = gfc_typenode_for_spec (&expr1->ts);
3441
3442 /* Allocate temporary for nested forall construct according to the
3443 information in nested_forall_info and inner_size. */
3444 tmp1 = allocate_temp_for_forall_nest (nested_forall_info, type, inner_size,
3445 &inner_size_body, block, &ptemp1);
3446
3447 /* Generate codes to copy rhs to the temporary . */
3448 tmp = generate_loop_for_rhs_to_temp (expr2, tmp1, count, count1, lss, rss,
3449 wheremask, invert);
3450
3451 /* Generate body and loops according to the information in
3452 nested_forall_info. */
3453 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
3454 gfc_add_expr_to_block (block, tmp);
3455
3456 /* Reset count1. */
3457 gfc_add_modify (block, count1, gfc_index_zero_node);
3458
3459 /* Reset count. */
3460 if (wheremask)
3461 gfc_add_modify (block, count, gfc_index_zero_node);
3462
3463 /* Generate codes to copy the temporary to lhs. */
3464 tmp = generate_loop_for_temp_to_lhs (expr1, tmp1, count, count1,
3465 wheremask, invert);
3466
3467 /* Generate body and loops according to the information in
3468 nested_forall_info. */
3469 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
3470 gfc_add_expr_to_block (block, tmp);
3471
3472 if (ptemp1)
3473 {
3474 /* Free the temporary. */
3475 tmp = gfc_call_free (ptemp1);
3476 gfc_add_expr_to_block (block, tmp);
3477 }
3478 }
3479
3480
3481 /* Translate pointer assignment inside FORALL which need temporary. */
3482
3483 static void
3484 gfc_trans_pointer_assign_need_temp (gfc_expr * expr1, gfc_expr * expr2,
3485 forall_info * nested_forall_info,
3486 stmtblock_t * block)
3487 {
3488 tree type;
3489 tree inner_size;
3490 gfc_ss *lss, *rss;
3491 gfc_se lse;
3492 gfc_se rse;
3493 gfc_array_info *info;
3494 gfc_loopinfo loop;
3495 tree desc;
3496 tree parm;
3497 tree parmtype;
3498 stmtblock_t body;
3499 tree count;
3500 tree tmp, tmp1, ptemp1;
3501
3502 count = gfc_create_var (gfc_array_index_type, "count");
3503 gfc_add_modify (block, count, gfc_index_zero_node);
3504
3505 inner_size = gfc_index_one_node;
3506 lss = gfc_walk_expr (expr1);
3507 rss = gfc_walk_expr (expr2);
3508 if (lss == gfc_ss_terminator)
3509 {
3510 type = gfc_typenode_for_spec (&expr1->ts);
3511 type = build_pointer_type (type);
3512
3513 /* Allocate temporary for nested forall construct according to the
3514 information in nested_forall_info and inner_size. */
3515 tmp1 = allocate_temp_for_forall_nest (nested_forall_info, type,
3516 inner_size, NULL, block, &ptemp1);
3517 gfc_start_block (&body);
3518 gfc_init_se (&lse, NULL);
3519 lse.expr = gfc_build_array_ref (tmp1, count, NULL);
3520 gfc_init_se (&rse, NULL);
3521 rse.want_pointer = 1;
3522 gfc_conv_expr (&rse, expr2);
3523 gfc_add_block_to_block (&body, &rse.pre);
3524 gfc_add_modify (&body, lse.expr,
3525 fold_convert (TREE_TYPE (lse.expr), rse.expr));
3526 gfc_add_block_to_block (&body, &rse.post);
3527
3528 /* Increment count. */
3529 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
3530 count, gfc_index_one_node);
3531 gfc_add_modify (&body, count, tmp);
3532
3533 tmp = gfc_finish_block (&body);
3534
3535 /* Generate body and loops according to the information in
3536 nested_forall_info. */
3537 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
3538 gfc_add_expr_to_block (block, tmp);
3539
3540 /* Reset count. */
3541 gfc_add_modify (block, count, gfc_index_zero_node);
3542
3543 gfc_start_block (&body);
3544 gfc_init_se (&lse, NULL);
3545 gfc_init_se (&rse, NULL);
3546 rse.expr = gfc_build_array_ref (tmp1, count, NULL);
3547 lse.want_pointer = 1;
3548 gfc_conv_expr (&lse, expr1);
3549 gfc_add_block_to_block (&body, &lse.pre);
3550 gfc_add_modify (&body, lse.expr, rse.expr);
3551 gfc_add_block_to_block (&body, &lse.post);
3552 /* Increment count. */
3553 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
3554 count, gfc_index_one_node);
3555 gfc_add_modify (&body, count, tmp);
3556 tmp = gfc_finish_block (&body);
3557
3558 /* Generate body and loops according to the information in
3559 nested_forall_info. */
3560 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
3561 gfc_add_expr_to_block (block, tmp);
3562 }
3563 else
3564 {
3565 gfc_init_loopinfo (&loop);
3566
3567 /* Associate the SS with the loop. */
3568 gfc_add_ss_to_loop (&loop, rss);
3569
3570 /* Setup the scalarizing loops and bounds. */
3571 gfc_conv_ss_startstride (&loop);
3572
3573 gfc_conv_loop_setup (&loop, &expr2->where);
3574
3575 info = &rss->info->data.array;
3576 desc = info->descriptor;
3577
3578 /* Make a new descriptor. */
3579 parmtype = gfc_get_element_type (TREE_TYPE (desc));
3580 parmtype = gfc_get_array_type_bounds (parmtype, loop.dimen, 0,
3581 loop.from, loop.to, 1,
3582 GFC_ARRAY_UNKNOWN, true);
3583
3584 /* Allocate temporary for nested forall construct. */
3585 tmp1 = allocate_temp_for_forall_nest (nested_forall_info, parmtype,
3586 inner_size, NULL, block, &ptemp1);
3587 gfc_start_block (&body);
3588 gfc_init_se (&lse, NULL);
3589 lse.expr = gfc_build_array_ref (tmp1, count, NULL);
3590 lse.direct_byref = 1;
3591 gfc_conv_expr_descriptor (&lse, expr2);
3592
3593 gfc_add_block_to_block (&body, &lse.pre);
3594 gfc_add_block_to_block (&body, &lse.post);
3595
3596 /* Increment count. */
3597 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
3598 count, gfc_index_one_node);
3599 gfc_add_modify (&body, count, tmp);
3600
3601 tmp = gfc_finish_block (&body);
3602
3603 /* Generate body and loops according to the information in
3604 nested_forall_info. */
3605 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
3606 gfc_add_expr_to_block (block, tmp);
3607
3608 /* Reset count. */
3609 gfc_add_modify (block, count, gfc_index_zero_node);
3610
3611 parm = gfc_build_array_ref (tmp1, count, NULL);
3612 gfc_init_se (&lse, NULL);
3613 gfc_conv_expr_descriptor (&lse, expr1);
3614 gfc_add_modify (&lse.pre, lse.expr, parm);
3615 gfc_start_block (&body);
3616 gfc_add_block_to_block (&body, &lse.pre);
3617 gfc_add_block_to_block (&body, &lse.post);
3618
3619 /* Increment count. */
3620 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
3621 count, gfc_index_one_node);
3622 gfc_add_modify (&body, count, tmp);
3623
3624 tmp = gfc_finish_block (&body);
3625
3626 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
3627 gfc_add_expr_to_block (block, tmp);
3628 }
3629 /* Free the temporary. */
3630 if (ptemp1)
3631 {
3632 tmp = gfc_call_free (ptemp1);
3633 gfc_add_expr_to_block (block, tmp);
3634 }
3635 }
3636
3637
3638 /* FORALL and WHERE statements are really nasty, especially when you nest
3639 them. All the rhs of a forall assignment must be evaluated before the
3640 actual assignments are performed. Presumably this also applies to all the
3641 assignments in an inner where statement. */
3642
3643 /* Generate code for a FORALL statement. Any temporaries are allocated as a
3644 linear array, relying on the fact that we process in the same order in all
3645 loops.
3646
3647 forall (i=start:end:stride; maskexpr)
3648 e<i> = f<i>
3649 g<i> = h<i>
3650 end forall
3651 (where e,f,g,h<i> are arbitrary expressions possibly involving i)
3652 Translates to:
3653 count = ((end + 1 - start) / stride)
3654 masktmp(:) = maskexpr(:)
3655
3656 maskindex = 0;
3657 for (i = start; i <= end; i += stride)
3658 {
3659 if (masktmp[maskindex++])
3660 e<i> = f<i>
3661 }
3662 maskindex = 0;
3663 for (i = start; i <= end; i += stride)
3664 {
3665 if (masktmp[maskindex++])
3666 g<i> = h<i>
3667 }
3668
3669 Note that this code only works when there are no dependencies.
3670 Forall loop with array assignments and data dependencies are a real pain,
3671 because the size of the temporary cannot always be determined before the
3672 loop is executed. This problem is compounded by the presence of nested
3673 FORALL constructs.
3674 */
3675
3676 static tree
3677 gfc_trans_forall_1 (gfc_code * code, forall_info * nested_forall_info)
3678 {
3679 stmtblock_t pre;
3680 stmtblock_t post;
3681 stmtblock_t block;
3682 stmtblock_t body;
3683 tree *var;
3684 tree *start;
3685 tree *end;
3686 tree *step;
3687 gfc_expr **varexpr;
3688 tree tmp;
3689 tree assign;
3690 tree size;
3691 tree maskindex;
3692 tree mask;
3693 tree pmask;
3694 tree cycle_label = NULL_TREE;
3695 int n;
3696 int nvar;
3697 int need_temp;
3698 gfc_forall_iterator *fa;
3699 gfc_se se;
3700 gfc_code *c;
3701 gfc_saved_var *saved_vars;
3702 iter_info *this_forall;
3703 forall_info *info;
3704 bool need_mask;
3705
3706 /* Do nothing if the mask is false. */
3707 if (code->expr1
3708 && code->expr1->expr_type == EXPR_CONSTANT
3709 && !code->expr1->value.logical)
3710 return build_empty_stmt (input_location);
3711
3712 n = 0;
3713 /* Count the FORALL index number. */
3714 for (fa = code->ext.forall_iterator; fa; fa = fa->next)
3715 n++;
3716 nvar = n;
3717
3718 /* Allocate the space for var, start, end, step, varexpr. */
3719 var = XCNEWVEC (tree, nvar);
3720 start = XCNEWVEC (tree, nvar);
3721 end = XCNEWVEC (tree, nvar);
3722 step = XCNEWVEC (tree, nvar);
3723 varexpr = XCNEWVEC (gfc_expr *, nvar);
3724 saved_vars = XCNEWVEC (gfc_saved_var, nvar);
3725
3726 /* Allocate the space for info. */
3727 info = XCNEW (forall_info);
3728
3729 gfc_start_block (&pre);
3730 gfc_init_block (&post);
3731 gfc_init_block (&block);
3732
3733 n = 0;
3734 for (fa = code->ext.forall_iterator; fa; fa = fa->next)
3735 {
3736 gfc_symbol *sym = fa->var->symtree->n.sym;
3737
3738 /* Allocate space for this_forall. */
3739 this_forall = XCNEW (iter_info);
3740
3741 /* Create a temporary variable for the FORALL index. */
3742 tmp = gfc_typenode_for_spec (&sym->ts);
3743 var[n] = gfc_create_var (tmp, sym->name);
3744 gfc_shadow_sym (sym, var[n], &saved_vars[n]);
3745
3746 /* Record it in this_forall. */
3747 this_forall->var = var[n];
3748
3749 /* Replace the index symbol's backend_decl with the temporary decl. */
3750 sym->backend_decl = var[n];
3751
3752 /* Work out the start, end and stride for the loop. */
3753 gfc_init_se (&se, NULL);
3754 gfc_conv_expr_val (&se, fa->start);
3755 /* Record it in this_forall. */
3756 this_forall->start = se.expr;
3757 gfc_add_block_to_block (&block, &se.pre);
3758 start[n] = se.expr;
3759
3760 gfc_init_se (&se, NULL);
3761 gfc_conv_expr_val (&se, fa->end);
3762 /* Record it in this_forall. */
3763 this_forall->end = se.expr;
3764 gfc_make_safe_expr (&se);
3765 gfc_add_block_to_block (&block, &se.pre);
3766 end[n] = se.expr;
3767
3768 gfc_init_se (&se, NULL);
3769 gfc_conv_expr_val (&se, fa->stride);
3770 /* Record it in this_forall. */
3771 this_forall->step = se.expr;
3772 gfc_make_safe_expr (&se);
3773 gfc_add_block_to_block (&block, &se.pre);
3774 step[n] = se.expr;
3775
3776 /* Set the NEXT field of this_forall to NULL. */
3777 this_forall->next = NULL;
3778 /* Link this_forall to the info construct. */
3779 if (info->this_loop)
3780 {
3781 iter_info *iter_tmp = info->this_loop;
3782 while (iter_tmp->next != NULL)
3783 iter_tmp = iter_tmp->next;
3784 iter_tmp->next = this_forall;
3785 }
3786 else
3787 info->this_loop = this_forall;
3788
3789 n++;
3790 }
3791 nvar = n;
3792
3793 /* Calculate the size needed for the current forall level. */
3794 size = gfc_index_one_node;
3795 for (n = 0; n < nvar; n++)
3796 {
3797 /* size = (end + step - start) / step. */
3798 tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (start[n]),
3799 step[n], start[n]);
3800 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (end[n]),
3801 end[n], tmp);
3802 tmp = fold_build2_loc (input_location, FLOOR_DIV_EXPR, TREE_TYPE (tmp),
3803 tmp, step[n]);
3804 tmp = convert (gfc_array_index_type, tmp);
3805
3806 size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
3807 size, tmp);
3808 }
3809
3810 /* Record the nvar and size of current forall level. */
3811 info->nvar = nvar;
3812 info->size = size;
3813
3814 if (code->expr1)
3815 {
3816 /* If the mask is .true., consider the FORALL unconditional. */
3817 if (code->expr1->expr_type == EXPR_CONSTANT
3818 && code->expr1->value.logical)
3819 need_mask = false;
3820 else
3821 need_mask = true;
3822 }
3823 else
3824 need_mask = false;
3825
3826 /* First we need to allocate the mask. */
3827 if (need_mask)
3828 {
3829 /* As the mask array can be very big, prefer compact boolean types. */
3830 tree mask_type = gfc_get_logical_type (gfc_logical_kinds[0].kind);
3831 mask = allocate_temp_for_forall_nest (nested_forall_info, mask_type,
3832 size, NULL, &block, &pmask);
3833 maskindex = gfc_create_var_np (gfc_array_index_type, "mi");
3834
3835 /* Record them in the info structure. */
3836 info->maskindex = maskindex;
3837 info->mask = mask;
3838 }
3839 else
3840 {
3841 /* No mask was specified. */
3842 maskindex = NULL_TREE;
3843 mask = pmask = NULL_TREE;
3844 }
3845
3846 /* Link the current forall level to nested_forall_info. */
3847 info->prev_nest = nested_forall_info;
3848 nested_forall_info = info;
3849
3850 /* Copy the mask into a temporary variable if required.
3851 For now we assume a mask temporary is needed. */
3852 if (need_mask)
3853 {
3854 /* As the mask array can be very big, prefer compact boolean types. */
3855 tree mask_type = gfc_get_logical_type (gfc_logical_kinds[0].kind);
3856
3857 gfc_add_modify (&block, maskindex, gfc_index_zero_node);
3858
3859 /* Start of mask assignment loop body. */
3860 gfc_start_block (&body);
3861
3862 /* Evaluate the mask expression. */
3863 gfc_init_se (&se, NULL);
3864 gfc_conv_expr_val (&se, code->expr1);
3865 gfc_add_block_to_block (&body, &se.pre);
3866
3867 /* Store the mask. */
3868 se.expr = convert (mask_type, se.expr);
3869
3870 tmp = gfc_build_array_ref (mask, maskindex, NULL);
3871 gfc_add_modify (&body, tmp, se.expr);
3872
3873 /* Advance to the next mask element. */
3874 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
3875 maskindex, gfc_index_one_node);
3876 gfc_add_modify (&body, maskindex, tmp);
3877
3878 /* Generate the loops. */
3879 tmp = gfc_finish_block (&body);
3880 tmp = gfc_trans_nested_forall_loop (info, tmp, 0);
3881 gfc_add_expr_to_block (&block, tmp);
3882 }
3883
3884 if (code->op == EXEC_DO_CONCURRENT)
3885 {
3886 gfc_init_block (&body);
3887 cycle_label = gfc_build_label_decl (NULL_TREE);
3888 code->cycle_label = cycle_label;
3889 tmp = gfc_trans_code (code->block->next);
3890 gfc_add_expr_to_block (&body, tmp);
3891
3892 if (TREE_USED (cycle_label))
3893 {
3894 tmp = build1_v (LABEL_EXPR, cycle_label);
3895 gfc_add_expr_to_block (&body, tmp);
3896 }
3897
3898 tmp = gfc_finish_block (&body);
3899 nested_forall_info->do_concurrent = true;
3900 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
3901 gfc_add_expr_to_block (&block, tmp);
3902 goto done;
3903 }
3904
3905 c = code->block->next;
3906
3907 /* TODO: loop merging in FORALL statements. */
3908 /* Now that we've got a copy of the mask, generate the assignment loops. */
3909 while (c)
3910 {
3911 switch (c->op)
3912 {
3913 case EXEC_ASSIGN:
3914 /* A scalar or array assignment. DO the simple check for
3915 lhs to rhs dependencies. These make a temporary for the
3916 rhs and form a second forall block to copy to variable. */
3917 need_temp = check_forall_dependencies(c, &pre, &post);
3918
3919 /* Temporaries due to array assignment data dependencies introduce
3920 no end of problems. */
3921 if (need_temp)
3922 gfc_trans_assign_need_temp (c->expr1, c->expr2, NULL, false,
3923 nested_forall_info, &block);
3924 else
3925 {
3926 /* Use the normal assignment copying routines. */
3927 assign = gfc_trans_assignment (c->expr1, c->expr2, false, true);
3928
3929 /* Generate body and loops. */
3930 tmp = gfc_trans_nested_forall_loop (nested_forall_info,
3931 assign, 1);
3932 gfc_add_expr_to_block (&block, tmp);
3933 }
3934
3935 /* Cleanup any temporary symtrees that have been made to deal
3936 with dependencies. */
3937 if (new_symtree)
3938 cleanup_forall_symtrees (c);
3939
3940 break;
3941
3942 case EXEC_WHERE:
3943 /* Translate WHERE or WHERE construct nested in FORALL. */
3944 gfc_trans_where_2 (c, NULL, false, nested_forall_info, &block);
3945 break;
3946
3947 /* Pointer assignment inside FORALL. */
3948 case EXEC_POINTER_ASSIGN:
3949 need_temp = gfc_check_dependency (c->expr1, c->expr2, 0);
3950 if (need_temp)
3951 gfc_trans_pointer_assign_need_temp (c->expr1, c->expr2,
3952 nested_forall_info, &block);
3953 else
3954 {
3955 /* Use the normal assignment copying routines. */
3956 assign = gfc_trans_pointer_assignment (c->expr1, c->expr2);
3957
3958 /* Generate body and loops. */
3959 tmp = gfc_trans_nested_forall_loop (nested_forall_info,
3960 assign, 1);
3961 gfc_add_expr_to_block (&block, tmp);
3962 }
3963 break;
3964
3965 case EXEC_FORALL:
3966 tmp = gfc_trans_forall_1 (c, nested_forall_info);
3967 gfc_add_expr_to_block (&block, tmp);
3968 break;
3969
3970 /* Explicit subroutine calls are prevented by the frontend but interface
3971 assignments can legitimately produce them. */
3972 case EXEC_ASSIGN_CALL:
3973 assign = gfc_trans_call (c, true, NULL_TREE, NULL_TREE, false);
3974 tmp = gfc_trans_nested_forall_loop (nested_forall_info, assign, 1);
3975 gfc_add_expr_to_block (&block, tmp);
3976 break;
3977
3978 default:
3979 gcc_unreachable ();
3980 }
3981
3982 c = c->next;
3983 }
3984
3985 done:
3986 /* Restore the original index variables. */
3987 for (fa = code->ext.forall_iterator, n = 0; fa; fa = fa->next, n++)
3988 gfc_restore_sym (fa->var->symtree->n.sym, &saved_vars[n]);
3989
3990 /* Free the space for var, start, end, step, varexpr. */
3991 free (var);
3992 free (start);
3993 free (end);
3994 free (step);
3995 free (varexpr);
3996 free (saved_vars);
3997
3998 for (this_forall = info->this_loop; this_forall;)
3999 {
4000 iter_info *next = this_forall->next;
4001 free (this_forall);
4002 this_forall = next;
4003 }
4004
4005 /* Free the space for this forall_info. */
4006 free (info);
4007
4008 if (pmask)
4009 {
4010 /* Free the temporary for the mask. */
4011 tmp = gfc_call_free (pmask);
4012 gfc_add_expr_to_block (&block, tmp);
4013 }
4014 if (maskindex)
4015 pushdecl (maskindex);
4016
4017 gfc_add_block_to_block (&pre, &block);
4018 gfc_add_block_to_block (&pre, &post);
4019
4020 return gfc_finish_block (&pre);
4021 }
4022
4023
4024 /* Translate the FORALL statement or construct. */
4025
4026 tree gfc_trans_forall (gfc_code * code)
4027 {
4028 return gfc_trans_forall_1 (code, NULL);
4029 }
4030
4031
4032 /* Translate the DO CONCURRENT construct. */
4033
4034 tree gfc_trans_do_concurrent (gfc_code * code)
4035 {
4036 return gfc_trans_forall_1 (code, NULL);
4037 }
4038
4039
4040 /* Evaluate the WHERE mask expression, copy its value to a temporary.
4041 If the WHERE construct is nested in FORALL, compute the overall temporary
4042 needed by the WHERE mask expression multiplied by the iterator number of
4043 the nested forall.
4044 ME is the WHERE mask expression.
4045 MASK is the current execution mask upon input, whose sense may or may
4046 not be inverted as specified by the INVERT argument.
4047 CMASK is the updated execution mask on output, or NULL if not required.
4048 PMASK is the pending execution mask on output, or NULL if not required.
4049 BLOCK is the block in which to place the condition evaluation loops. */
4050
4051 static void
4052 gfc_evaluate_where_mask (gfc_expr * me, forall_info * nested_forall_info,
4053 tree mask, bool invert, tree cmask, tree pmask,
4054 tree mask_type, stmtblock_t * block)
4055 {
4056 tree tmp, tmp1;
4057 gfc_ss *lss, *rss;
4058 gfc_loopinfo loop;
4059 stmtblock_t body, body1;
4060 tree count, cond, mtmp;
4061 gfc_se lse, rse;
4062
4063 gfc_init_loopinfo (&loop);
4064
4065 lss = gfc_walk_expr (me);
4066 rss = gfc_walk_expr (me);
4067
4068 /* Variable to index the temporary. */
4069 count = gfc_create_var (gfc_array_index_type, "count");
4070 /* Initialize count. */
4071 gfc_add_modify (block, count, gfc_index_zero_node);
4072
4073 gfc_start_block (&body);
4074
4075 gfc_init_se (&rse, NULL);
4076 gfc_init_se (&lse, NULL);
4077
4078 if (lss == gfc_ss_terminator)
4079 {
4080 gfc_init_block (&body1);
4081 }
4082 else
4083 {
4084 /* Initialize the loop. */
4085 gfc_init_loopinfo (&loop);
4086
4087 /* We may need LSS to determine the shape of the expression. */
4088 gfc_add_ss_to_loop (&loop, lss);
4089 gfc_add_ss_to_loop (&loop, rss);
4090
4091 gfc_conv_ss_startstride (&loop);
4092 gfc_conv_loop_setup (&loop, &me->where);
4093
4094 gfc_mark_ss_chain_used (rss, 1);
4095 /* Start the loop body. */
4096 gfc_start_scalarized_body (&loop, &body1);
4097
4098 /* Translate the expression. */
4099 gfc_copy_loopinfo_to_se (&rse, &loop);
4100 rse.ss = rss;
4101 gfc_conv_expr (&rse, me);
4102 }
4103
4104 /* Variable to evaluate mask condition. */
4105 cond = gfc_create_var (mask_type, "cond");
4106 if (mask && (cmask || pmask))
4107 mtmp = gfc_create_var (mask_type, "mask");
4108 else mtmp = NULL_TREE;
4109
4110 gfc_add_block_to_block (&body1, &lse.pre);
4111 gfc_add_block_to_block (&body1, &rse.pre);
4112
4113 gfc_add_modify (&body1, cond, fold_convert (mask_type, rse.expr));
4114
4115 if (mask && (cmask || pmask))
4116 {
4117 tmp = gfc_build_array_ref (mask, count, NULL);
4118 if (invert)
4119 tmp = fold_build1_loc (input_location, TRUTH_NOT_EXPR, mask_type, tmp);
4120 gfc_add_modify (&body1, mtmp, tmp);
4121 }
4122
4123 if (cmask)
4124 {
4125 tmp1 = gfc_build_array_ref (cmask, count, NULL);
4126 tmp = cond;
4127 if (mask)
4128 tmp = fold_build2_loc (input_location, TRUTH_AND_EXPR, mask_type,
4129 mtmp, tmp);
4130 gfc_add_modify (&body1, tmp1, tmp);
4131 }
4132
4133 if (pmask)
4134 {
4135 tmp1 = gfc_build_array_ref (pmask, count, NULL);
4136 tmp = fold_build1_loc (input_location, TRUTH_NOT_EXPR, mask_type, cond);
4137 if (mask)
4138 tmp = fold_build2_loc (input_location, TRUTH_AND_EXPR, mask_type, mtmp,
4139 tmp);
4140 gfc_add_modify (&body1, tmp1, tmp);
4141 }
4142
4143 gfc_add_block_to_block (&body1, &lse.post);
4144 gfc_add_block_to_block (&body1, &rse.post);
4145
4146 if (lss == gfc_ss_terminator)
4147 {
4148 gfc_add_block_to_block (&body, &body1);
4149 }
4150 else
4151 {
4152 /* Increment count. */
4153 tmp1 = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
4154 count, gfc_index_one_node);
4155 gfc_add_modify (&body1, count, tmp1);
4156
4157 /* Generate the copying loops. */
4158 gfc_trans_scalarizing_loops (&loop, &body1);
4159
4160 gfc_add_block_to_block (&body, &loop.pre);
4161 gfc_add_block_to_block (&body, &loop.post);
4162
4163 gfc_cleanup_loop (&loop);
4164 /* TODO: Reuse lss and rss when copying temp->lhs. Need to be careful
4165 as tree nodes in SS may not be valid in different scope. */
4166 }
4167
4168 tmp1 = gfc_finish_block (&body);
4169 /* If the WHERE construct is inside FORALL, fill the full temporary. */
4170 if (nested_forall_info != NULL)
4171 tmp1 = gfc_trans_nested_forall_loop (nested_forall_info, tmp1, 1);
4172
4173 gfc_add_expr_to_block (block, tmp1);
4174 }
4175
4176
4177 /* Translate an assignment statement in a WHERE statement or construct
4178 statement. The MASK expression is used to control which elements
4179 of EXPR1 shall be assigned. The sense of MASK is specified by
4180 INVERT. */
4181
4182 static tree
4183 gfc_trans_where_assign (gfc_expr *expr1, gfc_expr *expr2,
4184 tree mask, bool invert,
4185 tree count1, tree count2,
4186 gfc_code *cnext)
4187 {
4188 gfc_se lse;
4189 gfc_se rse;
4190 gfc_ss *lss;
4191 gfc_ss *lss_section;
4192 gfc_ss *rss;
4193
4194 gfc_loopinfo loop;
4195 tree tmp;
4196 stmtblock_t block;
4197 stmtblock_t body;
4198 tree index, maskexpr;
4199
4200 /* A defined assignment. */
4201 if (cnext && cnext->resolved_sym)
4202 return gfc_trans_call (cnext, true, mask, count1, invert);
4203
4204 #if 0
4205 /* TODO: handle this special case.
4206 Special case a single function returning an array. */
4207 if (expr2->expr_type == EXPR_FUNCTION && expr2->rank > 0)
4208 {
4209 tmp = gfc_trans_arrayfunc_assign (expr1, expr2);
4210 if (tmp)
4211 return tmp;
4212 }
4213 #endif
4214
4215 /* Assignment of the form lhs = rhs. */
4216 gfc_start_block (&block);
4217
4218 gfc_init_se (&lse, NULL);
4219 gfc_init_se (&rse, NULL);
4220
4221 /* Walk the lhs. */
4222 lss = gfc_walk_expr (expr1);
4223 rss = NULL;
4224
4225 /* In each where-assign-stmt, the mask-expr and the variable being
4226 defined shall be arrays of the same shape. */
4227 gcc_assert (lss != gfc_ss_terminator);
4228
4229 /* The assignment needs scalarization. */
4230 lss_section = lss;
4231
4232 /* Find a non-scalar SS from the lhs. */
4233 while (lss_section != gfc_ss_terminator
4234 && lss_section->info->type != GFC_SS_SECTION)
4235 lss_section = lss_section->next;
4236
4237 gcc_assert (lss_section != gfc_ss_terminator);
4238
4239 /* Initialize the scalarizer. */
4240 gfc_init_loopinfo (&loop);
4241
4242 /* Walk the rhs. */
4243 rss = gfc_walk_expr (expr2);
4244 if (rss == gfc_ss_terminator)
4245 {
4246 /* The rhs is scalar. Add a ss for the expression. */
4247 rss = gfc_get_scalar_ss (gfc_ss_terminator, expr2);
4248 rss->info->where = 1;
4249 }
4250
4251 /* Associate the SS with the loop. */
4252 gfc_add_ss_to_loop (&loop, lss);
4253 gfc_add_ss_to_loop (&loop, rss);
4254
4255 /* Calculate the bounds of the scalarization. */
4256 gfc_conv_ss_startstride (&loop);
4257
4258 /* Resolve any data dependencies in the statement. */
4259 gfc_conv_resolve_dependencies (&loop, lss_section, rss);
4260
4261 /* Setup the scalarizing loops. */
4262 gfc_conv_loop_setup (&loop, &expr2->where);
4263
4264 /* Setup the gfc_se structures. */
4265 gfc_copy_loopinfo_to_se (&lse, &loop);
4266 gfc_copy_loopinfo_to_se (&rse, &loop);
4267
4268 rse.ss = rss;
4269 gfc_mark_ss_chain_used (rss, 1);
4270 if (loop.temp_ss == NULL)
4271 {
4272 lse.ss = lss;
4273 gfc_mark_ss_chain_used (lss, 1);
4274 }
4275 else
4276 {
4277 lse.ss = loop.temp_ss;
4278 gfc_mark_ss_chain_used (lss, 3);
4279 gfc_mark_ss_chain_used (loop.temp_ss, 3);
4280 }
4281
4282 /* Start the scalarized loop body. */
4283 gfc_start_scalarized_body (&loop, &body);
4284
4285 /* Translate the expression. */
4286 gfc_conv_expr (&rse, expr2);
4287 if (lss != gfc_ss_terminator && loop.temp_ss != NULL)
4288 gfc_conv_tmp_array_ref (&lse);
4289 else
4290 gfc_conv_expr (&lse, expr1);
4291
4292 /* Form the mask expression according to the mask. */
4293 index = count1;
4294 maskexpr = gfc_build_array_ref (mask, index, NULL);
4295 if (invert)
4296 maskexpr = fold_build1_loc (input_location, TRUTH_NOT_EXPR,
4297 TREE_TYPE (maskexpr), maskexpr);
4298
4299 /* Use the scalar assignment as is. */
4300 tmp = gfc_trans_scalar_assign (&lse, &rse, expr1->ts,
4301 loop.temp_ss != NULL, false, true);
4302
4303 tmp = build3_v (COND_EXPR, maskexpr, tmp, build_empty_stmt (input_location));
4304
4305 gfc_add_expr_to_block (&body, tmp);
4306
4307 if (lss == gfc_ss_terminator)
4308 {
4309 /* Increment count1. */
4310 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
4311 count1, gfc_index_one_node);
4312 gfc_add_modify (&body, count1, tmp);
4313
4314 /* Use the scalar assignment as is. */
4315 gfc_add_block_to_block (&block, &body);
4316 }
4317 else
4318 {
4319 gcc_assert (lse.ss == gfc_ss_terminator
4320 && rse.ss == gfc_ss_terminator);
4321
4322 if (loop.temp_ss != NULL)
4323 {
4324 /* Increment count1 before finish the main body of a scalarized
4325 expression. */
4326 tmp = fold_build2_loc (input_location, PLUS_EXPR,
4327 gfc_array_index_type, count1, gfc_index_one_node);
4328 gfc_add_modify (&body, count1, tmp);
4329 gfc_trans_scalarized_loop_boundary (&loop, &body);
4330
4331 /* We need to copy the temporary to the actual lhs. */
4332 gfc_init_se (&lse, NULL);
4333 gfc_init_se (&rse, NULL);
4334 gfc_copy_loopinfo_to_se (&lse, &loop);
4335 gfc_copy_loopinfo_to_se (&rse, &loop);
4336
4337 rse.ss = loop.temp_ss;
4338 lse.ss = lss;
4339
4340 gfc_conv_tmp_array_ref (&rse);
4341 gfc_conv_expr (&lse, expr1);
4342
4343 gcc_assert (lse.ss == gfc_ss_terminator
4344 && rse.ss == gfc_ss_terminator);
4345
4346 /* Form the mask expression according to the mask tree list. */
4347 index = count2;
4348 maskexpr = gfc_build_array_ref (mask, index, NULL);
4349 if (invert)
4350 maskexpr = fold_build1_loc (input_location, TRUTH_NOT_EXPR,
4351 TREE_TYPE (maskexpr), maskexpr);
4352
4353 /* Use the scalar assignment as is. */
4354 tmp = gfc_trans_scalar_assign (&lse, &rse, expr1->ts, false, false,
4355 true);
4356 tmp = build3_v (COND_EXPR, maskexpr, tmp,
4357 build_empty_stmt (input_location));
4358 gfc_add_expr_to_block (&body, tmp);
4359
4360 /* Increment count2. */
4361 tmp = fold_build2_loc (input_location, PLUS_EXPR,
4362 gfc_array_index_type, count2,
4363 gfc_index_one_node);
4364 gfc_add_modify (&body, count2, tmp);
4365 }
4366 else
4367 {
4368 /* Increment count1. */
4369 tmp = fold_build2_loc (input_location, PLUS_EXPR,
4370 gfc_array_index_type, count1,
4371 gfc_index_one_node);
4372 gfc_add_modify (&body, count1, tmp);
4373 }
4374
4375 /* Generate the copying loops. */
4376 gfc_trans_scalarizing_loops (&loop, &body);
4377
4378 /* Wrap the whole thing up. */
4379 gfc_add_block_to_block (&block, &loop.pre);
4380 gfc_add_block_to_block (&block, &loop.post);
4381 gfc_cleanup_loop (&loop);
4382 }
4383
4384 return gfc_finish_block (&block);
4385 }
4386
4387
4388 /* Translate the WHERE construct or statement.
4389 This function can be called iteratively to translate the nested WHERE
4390 construct or statement.
4391 MASK is the control mask. */
4392
4393 static void
4394 gfc_trans_where_2 (gfc_code * code, tree mask, bool invert,
4395 forall_info * nested_forall_info, stmtblock_t * block)
4396 {
4397 stmtblock_t inner_size_body;
4398 tree inner_size, size;
4399 gfc_ss *lss, *rss;
4400 tree mask_type;
4401 gfc_expr *expr1;
4402 gfc_expr *expr2;
4403 gfc_code *cblock;
4404 gfc_code *cnext;
4405 tree tmp;
4406 tree cond;
4407 tree count1, count2;
4408 bool need_cmask;
4409 bool need_pmask;
4410 int need_temp;
4411 tree pcmask = NULL_TREE;
4412 tree ppmask = NULL_TREE;
4413 tree cmask = NULL_TREE;
4414 tree pmask = NULL_TREE;
4415 gfc_actual_arglist *arg;
4416
4417 /* the WHERE statement or the WHERE construct statement. */
4418 cblock = code->block;
4419
4420 /* As the mask array can be very big, prefer compact boolean types. */
4421 mask_type = gfc_get_logical_type (gfc_logical_kinds[0].kind);
4422
4423 /* Determine which temporary masks are needed. */
4424 if (!cblock->block)
4425 {
4426 /* One clause: No ELSEWHEREs. */
4427 need_cmask = (cblock->next != 0);
4428 need_pmask = false;
4429 }
4430 else if (cblock->block->block)
4431 {
4432 /* Three or more clauses: Conditional ELSEWHEREs. */
4433 need_cmask = true;
4434 need_pmask = true;
4435 }
4436 else if (cblock->next)
4437 {
4438 /* Two clauses, the first non-empty. */
4439 need_cmask = true;
4440 need_pmask = (mask != NULL_TREE
4441 && cblock->block->next != 0);
4442 }
4443 else if (!cblock->block->next)
4444 {
4445 /* Two clauses, both empty. */
4446 need_cmask = false;
4447 need_pmask = false;
4448 }
4449 /* Two clauses, the first empty, the second non-empty. */
4450 else if (mask)
4451 {
4452 need_cmask = (cblock->block->expr1 != 0);
4453 need_pmask = true;
4454 }
4455 else
4456 {
4457 need_cmask = true;
4458 need_pmask = false;
4459 }
4460
4461 if (need_cmask || need_pmask)
4462 {
4463 /* Calculate the size of temporary needed by the mask-expr. */
4464 gfc_init_block (&inner_size_body);
4465 inner_size = compute_inner_temp_size (cblock->expr1, cblock->expr1,
4466 &inner_size_body, &lss, &rss);
4467
4468 gfc_free_ss_chain (lss);
4469 gfc_free_ss_chain (rss);
4470
4471 /* Calculate the total size of temporary needed. */
4472 size = compute_overall_iter_number (nested_forall_info, inner_size,
4473 &inner_size_body, block);
4474
4475 /* Check whether the size is negative. */
4476 cond = fold_build2_loc (input_location, LE_EXPR, boolean_type_node, size,
4477 gfc_index_zero_node);
4478 size = fold_build3_loc (input_location, COND_EXPR, gfc_array_index_type,
4479 cond, gfc_index_zero_node, size);
4480 size = gfc_evaluate_now (size, block);
4481
4482 /* Allocate temporary for WHERE mask if needed. */
4483 if (need_cmask)
4484 cmask = allocate_temp_for_forall_nest_1 (mask_type, size, block,
4485 &pcmask);
4486
4487 /* Allocate temporary for !mask if needed. */
4488 if (need_pmask)
4489 pmask = allocate_temp_for_forall_nest_1 (mask_type, size, block,
4490 &ppmask);
4491 }
4492
4493 while (cblock)
4494 {
4495 /* Each time around this loop, the where clause is conditional
4496 on the value of mask and invert, which are updated at the
4497 bottom of the loop. */
4498
4499 /* Has mask-expr. */
4500 if (cblock->expr1)
4501 {
4502 /* Ensure that the WHERE mask will be evaluated exactly once.
4503 If there are no statements in this WHERE/ELSEWHERE clause,
4504 then we don't need to update the control mask (cmask).
4505 If this is the last clause of the WHERE construct, then
4506 we don't need to update the pending control mask (pmask). */
4507 if (mask)
4508 gfc_evaluate_where_mask (cblock->expr1, nested_forall_info,
4509 mask, invert,
4510 cblock->next ? cmask : NULL_TREE,
4511 cblock->block ? pmask : NULL_TREE,
4512 mask_type, block);
4513 else
4514 gfc_evaluate_where_mask (cblock->expr1, nested_forall_info,
4515 NULL_TREE, false,
4516 (cblock->next || cblock->block)
4517 ? cmask : NULL_TREE,
4518 NULL_TREE, mask_type, block);
4519
4520 invert = false;
4521 }
4522 /* It's a final elsewhere-stmt. No mask-expr is present. */
4523 else
4524 cmask = mask;
4525
4526 /* The body of this where clause are controlled by cmask with
4527 sense specified by invert. */
4528
4529 /* Get the assignment statement of a WHERE statement, or the first
4530 statement in where-body-construct of a WHERE construct. */
4531 cnext = cblock->next;
4532 while (cnext)
4533 {
4534 switch (cnext->op)
4535 {
4536 /* WHERE assignment statement. */
4537 case EXEC_ASSIGN_CALL:
4538
4539 arg = cnext->ext.actual;
4540 expr1 = expr2 = NULL;
4541 for (; arg; arg = arg->next)
4542 {
4543 if (!arg->expr)
4544 continue;
4545 if (expr1 == NULL)
4546 expr1 = arg->expr;
4547 else
4548 expr2 = arg->expr;
4549 }
4550 goto evaluate;
4551
4552 case EXEC_ASSIGN:
4553 expr1 = cnext->expr1;
4554 expr2 = cnext->expr2;
4555 evaluate:
4556 if (nested_forall_info != NULL)
4557 {
4558 need_temp = gfc_check_dependency (expr1, expr2, 0);
4559 if (need_temp && cnext->op != EXEC_ASSIGN_CALL)
4560 gfc_trans_assign_need_temp (expr1, expr2,
4561 cmask, invert,
4562 nested_forall_info, block);
4563 else
4564 {
4565 /* Variables to control maskexpr. */
4566 count1 = gfc_create_var (gfc_array_index_type, "count1");
4567 count2 = gfc_create_var (gfc_array_index_type, "count2");
4568 gfc_add_modify (block, count1, gfc_index_zero_node);
4569 gfc_add_modify (block, count2, gfc_index_zero_node);
4570
4571 tmp = gfc_trans_where_assign (expr1, expr2,
4572 cmask, invert,
4573 count1, count2,
4574 cnext);
4575
4576 tmp = gfc_trans_nested_forall_loop (nested_forall_info,
4577 tmp, 1);
4578 gfc_add_expr_to_block (block, tmp);
4579 }
4580 }
4581 else
4582 {
4583 /* Variables to control maskexpr. */
4584 count1 = gfc_create_var (gfc_array_index_type, "count1");
4585 count2 = gfc_create_var (gfc_array_index_type, "count2");
4586 gfc_add_modify (block, count1, gfc_index_zero_node);
4587 gfc_add_modify (block, count2, gfc_index_zero_node);
4588
4589 tmp = gfc_trans_where_assign (expr1, expr2,
4590 cmask, invert,
4591 count1, count2,
4592 cnext);
4593 gfc_add_expr_to_block (block, tmp);
4594
4595 }
4596 break;
4597
4598 /* WHERE or WHERE construct is part of a where-body-construct. */
4599 case EXEC_WHERE:
4600 gfc_trans_where_2 (cnext, cmask, invert,
4601 nested_forall_info, block);
4602 break;
4603
4604 default:
4605 gcc_unreachable ();
4606 }
4607
4608 /* The next statement within the same where-body-construct. */
4609 cnext = cnext->next;
4610 }
4611 /* The next masked-elsewhere-stmt, elsewhere-stmt, or end-where-stmt. */
4612 cblock = cblock->block;
4613 if (mask == NULL_TREE)
4614 {
4615 /* If we're the initial WHERE, we can simply invert the sense
4616 of the current mask to obtain the "mask" for the remaining
4617 ELSEWHEREs. */
4618 invert = true;
4619 mask = cmask;
4620 }
4621 else
4622 {
4623 /* Otherwise, for nested WHERE's we need to use the pending mask. */
4624 invert = false;
4625 mask = pmask;
4626 }
4627 }
4628
4629 /* If we allocated a pending mask array, deallocate it now. */
4630 if (ppmask)
4631 {
4632 tmp = gfc_call_free (ppmask);
4633 gfc_add_expr_to_block (block, tmp);
4634 }
4635
4636 /* If we allocated a current mask array, deallocate it now. */
4637 if (pcmask)
4638 {
4639 tmp = gfc_call_free (pcmask);
4640 gfc_add_expr_to_block (block, tmp);
4641 }
4642 }
4643
4644 /* Translate a simple WHERE construct or statement without dependencies.
4645 CBLOCK is the "then" clause of the WHERE statement, where CBLOCK->EXPR
4646 is the mask condition, and EBLOCK if non-NULL is the "else" clause.
4647 Currently both CBLOCK and EBLOCK are restricted to single assignments. */
4648
4649 static tree
4650 gfc_trans_where_3 (gfc_code * cblock, gfc_code * eblock)
4651 {
4652 stmtblock_t block, body;
4653 gfc_expr *cond, *tdst, *tsrc, *edst, *esrc;
4654 tree tmp, cexpr, tstmt, estmt;
4655 gfc_ss *css, *tdss, *tsss;
4656 gfc_se cse, tdse, tsse, edse, esse;
4657 gfc_loopinfo loop;
4658 gfc_ss *edss = 0;
4659 gfc_ss *esss = 0;
4660
4661 /* Allow the scalarizer to workshare simple where loops. */
4662 if (ompws_flags & OMPWS_WORKSHARE_FLAG)
4663 ompws_flags |= OMPWS_SCALARIZER_WS;
4664
4665 cond = cblock->expr1;
4666 tdst = cblock->next->expr1;
4667 tsrc = cblock->next->expr2;
4668 edst = eblock ? eblock->next->expr1 : NULL;
4669 esrc = eblock ? eblock->next->expr2 : NULL;
4670
4671 gfc_start_block (&block);
4672 gfc_init_loopinfo (&loop);
4673
4674 /* Handle the condition. */
4675 gfc_init_se (&cse, NULL);
4676 css = gfc_walk_expr (cond);
4677 gfc_add_ss_to_loop (&loop, css);
4678
4679 /* Handle the then-clause. */
4680 gfc_init_se (&tdse, NULL);
4681 gfc_init_se (&tsse, NULL);
4682 tdss = gfc_walk_expr (tdst);
4683 tsss = gfc_walk_expr (tsrc);
4684 if (tsss == gfc_ss_terminator)
4685 {
4686 tsss = gfc_get_scalar_ss (gfc_ss_terminator, tsrc);
4687 tsss->info->where = 1;
4688 }
4689 gfc_add_ss_to_loop (&loop, tdss);
4690 gfc_add_ss_to_loop (&loop, tsss);
4691
4692 if (eblock)
4693 {
4694 /* Handle the else clause. */
4695 gfc_init_se (&edse, NULL);
4696 gfc_init_se (&esse, NULL);
4697 edss = gfc_walk_expr (edst);
4698 esss = gfc_walk_expr (esrc);
4699 if (esss == gfc_ss_terminator)
4700 {
4701 esss = gfc_get_scalar_ss (gfc_ss_terminator, esrc);
4702 esss->info->where = 1;
4703 }
4704 gfc_add_ss_to_loop (&loop, edss);
4705 gfc_add_ss_to_loop (&loop, esss);
4706 }
4707
4708 gfc_conv_ss_startstride (&loop);
4709 gfc_conv_loop_setup (&loop, &tdst->where);
4710
4711 gfc_mark_ss_chain_used (css, 1);
4712 gfc_mark_ss_chain_used (tdss, 1);
4713 gfc_mark_ss_chain_used (tsss, 1);
4714 if (eblock)
4715 {
4716 gfc_mark_ss_chain_used (edss, 1);
4717 gfc_mark_ss_chain_used (esss, 1);
4718 }
4719
4720 gfc_start_scalarized_body (&loop, &body);
4721
4722 gfc_copy_loopinfo_to_se (&cse, &loop);
4723 gfc_copy_loopinfo_to_se (&tdse, &loop);
4724 gfc_copy_loopinfo_to_se (&tsse, &loop);
4725 cse.ss = css;
4726 tdse.ss = tdss;
4727 tsse.ss = tsss;
4728 if (eblock)
4729 {
4730 gfc_copy_loopinfo_to_se (&edse, &loop);
4731 gfc_copy_loopinfo_to_se (&esse, &loop);
4732 edse.ss = edss;
4733 esse.ss = esss;
4734 }
4735
4736 gfc_conv_expr (&cse, cond);
4737 gfc_add_block_to_block (&body, &cse.pre);
4738 cexpr = cse.expr;
4739
4740 gfc_conv_expr (&tsse, tsrc);
4741 if (tdss != gfc_ss_terminator && loop.temp_ss != NULL)
4742 gfc_conv_tmp_array_ref (&tdse);
4743 else
4744 gfc_conv_expr (&tdse, tdst);
4745
4746 if (eblock)
4747 {
4748 gfc_conv_expr (&esse, esrc);
4749 if (edss != gfc_ss_terminator && loop.temp_ss != NULL)
4750 gfc_conv_tmp_array_ref (&edse);
4751 else
4752 gfc_conv_expr (&edse, edst);
4753 }
4754
4755 tstmt = gfc_trans_scalar_assign (&tdse, &tsse, tdst->ts, false, false, true);
4756 estmt = eblock ? gfc_trans_scalar_assign (&edse, &esse, edst->ts, false,
4757 false, true)
4758 : build_empty_stmt (input_location);
4759 tmp = build3_v (COND_EXPR, cexpr, tstmt, estmt);
4760 gfc_add_expr_to_block (&body, tmp);
4761 gfc_add_block_to_block (&body, &cse.post);
4762
4763 gfc_trans_scalarizing_loops (&loop, &body);
4764 gfc_add_block_to_block (&block, &loop.pre);
4765 gfc_add_block_to_block (&block, &loop.post);
4766 gfc_cleanup_loop (&loop);
4767
4768 return gfc_finish_block (&block);
4769 }
4770
4771 /* As the WHERE or WHERE construct statement can be nested, we call
4772 gfc_trans_where_2 to do the translation, and pass the initial
4773 NULL values for both the control mask and the pending control mask. */
4774
4775 tree
4776 gfc_trans_where (gfc_code * code)
4777 {
4778 stmtblock_t block;
4779 gfc_code *cblock;
4780 gfc_code *eblock;
4781
4782 cblock = code->block;
4783 if (cblock->next
4784 && cblock->next->op == EXEC_ASSIGN
4785 && !cblock->next->next)
4786 {
4787 eblock = cblock->block;
4788 if (!eblock)
4789 {
4790 /* A simple "WHERE (cond) x = y" statement or block is
4791 dependence free if cond is not dependent upon writing x,
4792 and the source y is unaffected by the destination x. */
4793 if (!gfc_check_dependency (cblock->next->expr1,
4794 cblock->expr1, 0)
4795 && !gfc_check_dependency (cblock->next->expr1,
4796 cblock->next->expr2, 0))
4797 return gfc_trans_where_3 (cblock, NULL);
4798 }
4799 else if (!eblock->expr1
4800 && !eblock->block
4801 && eblock->next
4802 && eblock->next->op == EXEC_ASSIGN
4803 && !eblock->next->next)
4804 {
4805 /* A simple "WHERE (cond) x1 = y1 ELSEWHERE x2 = y2 ENDWHERE"
4806 block is dependence free if cond is not dependent on writes
4807 to x1 and x2, y1 is not dependent on writes to x2, and y2
4808 is not dependent on writes to x1, and both y's are not
4809 dependent upon their own x's. In addition to this, the
4810 final two dependency checks below exclude all but the same
4811 array reference if the where and elswhere destinations
4812 are the same. In short, this is VERY conservative and this
4813 is needed because the two loops, required by the standard
4814 are coalesced in gfc_trans_where_3. */
4815 if (!gfc_check_dependency (cblock->next->expr1,
4816 cblock->expr1, 0)
4817 && !gfc_check_dependency (eblock->next->expr1,
4818 cblock->expr1, 0)
4819 && !gfc_check_dependency (cblock->next->expr1,
4820 eblock->next->expr2, 1)
4821 && !gfc_check_dependency (eblock->next->expr1,
4822 cblock->next->expr2, 1)
4823 && !gfc_check_dependency (cblock->next->expr1,
4824 cblock->next->expr2, 1)
4825 && !gfc_check_dependency (eblock->next->expr1,
4826 eblock->next->expr2, 1)
4827 && !gfc_check_dependency (cblock->next->expr1,
4828 eblock->next->expr1, 0)
4829 && !gfc_check_dependency (eblock->next->expr1,
4830 cblock->next->expr1, 0))
4831 return gfc_trans_where_3 (cblock, eblock);
4832 }
4833 }
4834
4835 gfc_start_block (&block);
4836
4837 gfc_trans_where_2 (code, NULL, false, NULL, &block);
4838
4839 return gfc_finish_block (&block);
4840 }
4841
4842
4843 /* CYCLE a DO loop. The label decl has already been created by
4844 gfc_trans_do(), it's in TREE_PURPOSE (backend_decl) of the gfc_code
4845 node at the head of the loop. We must mark the label as used. */
4846
4847 tree
4848 gfc_trans_cycle (gfc_code * code)
4849 {
4850 tree cycle_label;
4851
4852 cycle_label = code->ext.which_construct->cycle_label;
4853 gcc_assert (cycle_label);
4854
4855 TREE_USED (cycle_label) = 1;
4856 return build1_v (GOTO_EXPR, cycle_label);
4857 }
4858
4859
4860 /* EXIT a DO loop. Similar to CYCLE, but now the label is in
4861 TREE_VALUE (backend_decl) of the gfc_code node at the head of the
4862 loop. */
4863
4864 tree
4865 gfc_trans_exit (gfc_code * code)
4866 {
4867 tree exit_label;
4868
4869 exit_label = code->ext.which_construct->exit_label;
4870 gcc_assert (exit_label);
4871
4872 TREE_USED (exit_label) = 1;
4873 return build1_v (GOTO_EXPR, exit_label);
4874 }
4875
4876
4877 /* Translate the ALLOCATE statement. */
4878
4879 tree
4880 gfc_trans_allocate (gfc_code * code)
4881 {
4882 gfc_alloc *al;
4883 gfc_expr *e;
4884 gfc_expr *expr;
4885 gfc_se se;
4886 tree tmp;
4887 tree parm;
4888 tree stat;
4889 tree errmsg;
4890 tree errlen;
4891 tree label_errmsg;
4892 tree label_finish;
4893 tree memsz;
4894 tree expr3;
4895 tree slen3;
4896 stmtblock_t block;
4897 stmtblock_t post;
4898 gfc_expr *sz;
4899 gfc_se se_sz;
4900 tree class_expr;
4901 tree nelems;
4902 tree memsize = NULL_TREE;
4903 tree classexpr = NULL_TREE;
4904
4905 if (!code->ext.alloc.list)
4906 return NULL_TREE;
4907
4908 stat = tmp = memsz = NULL_TREE;
4909 label_errmsg = label_finish = errmsg = errlen = NULL_TREE;
4910
4911 gfc_init_block (&block);
4912 gfc_init_block (&post);
4913
4914 /* STAT= (and maybe ERRMSG=) is present. */
4915 if (code->expr1)
4916 {
4917 /* STAT=. */
4918 tree gfc_int4_type_node = gfc_get_int_type (4);
4919 stat = gfc_create_var (gfc_int4_type_node, "stat");
4920
4921 /* ERRMSG= only makes sense with STAT=. */
4922 if (code->expr2)
4923 {
4924 gfc_init_se (&se, NULL);
4925 se.want_pointer = 1;
4926 gfc_conv_expr_lhs (&se, code->expr2);
4927 errmsg = se.expr;
4928 errlen = se.string_length;
4929 }
4930 else
4931 {
4932 errmsg = null_pointer_node;
4933 errlen = build_int_cst (gfc_charlen_type_node, 0);
4934 }
4935
4936 /* GOTO destinations. */
4937 label_errmsg = gfc_build_label_decl (NULL_TREE);
4938 label_finish = gfc_build_label_decl (NULL_TREE);
4939 TREE_USED (label_finish) = 0;
4940 }
4941
4942 expr3 = NULL_TREE;
4943 slen3 = NULL_TREE;
4944
4945 for (al = code->ext.alloc.list; al != NULL; al = al->next)
4946 {
4947 expr = gfc_copy_expr (al->expr);
4948
4949 if (expr->ts.type == BT_CLASS)
4950 gfc_add_data_component (expr);
4951
4952 gfc_init_se (&se, NULL);
4953
4954 se.want_pointer = 1;
4955 se.descriptor_only = 1;
4956 gfc_conv_expr (&se, expr);
4957
4958 /* Evaluate expr3 just once if not a variable. */
4959 if (al == code->ext.alloc.list
4960 && al->expr->ts.type == BT_CLASS
4961 && code->expr3
4962 && code->expr3->ts.type == BT_CLASS
4963 && code->expr3->expr_type != EXPR_VARIABLE)
4964 {
4965 gfc_init_se (&se_sz, NULL);
4966 gfc_conv_expr_reference (&se_sz, code->expr3);
4967 gfc_conv_class_to_class (&se_sz, code->expr3,
4968 code->expr3->ts, false, true, false, false);
4969 gfc_add_block_to_block (&se.pre, &se_sz.pre);
4970 gfc_add_block_to_block (&se.post, &se_sz.post);
4971 classexpr = build_fold_indirect_ref_loc (input_location,
4972 se_sz.expr);
4973 classexpr = gfc_evaluate_now (classexpr, &se.pre);
4974 memsize = gfc_vtable_size_get (classexpr);
4975 memsize = fold_convert (sizetype, memsize);
4976 }
4977
4978 memsz = memsize;
4979 class_expr = classexpr;
4980
4981 nelems = NULL_TREE;
4982 if (!gfc_array_allocate (&se, expr, stat, errmsg, errlen, label_finish,
4983 memsz, &nelems, code->expr3, &code->ext.alloc.ts))
4984 {
4985 bool unlimited_char;
4986
4987 unlimited_char = UNLIMITED_POLY (al->expr)
4988 && ((code->expr3 && code->expr3->ts.type == BT_CHARACTER)
4989 || (code->ext.alloc.ts.type == BT_CHARACTER
4990 && code->ext.alloc.ts.u.cl
4991 && code->ext.alloc.ts.u.cl->length));
4992
4993 /* A scalar or derived type. */
4994
4995 /* Determine allocate size. */
4996 if (al->expr->ts.type == BT_CLASS
4997 && !unlimited_char
4998 && code->expr3
4999 && memsz == NULL_TREE)
5000 {
5001 if (code->expr3->ts.type == BT_CLASS)
5002 {
5003 sz = gfc_copy_expr (code->expr3);
5004 gfc_add_vptr_component (sz);
5005 gfc_add_size_component (sz);
5006 gfc_init_se (&se_sz, NULL);
5007 gfc_conv_expr (&se_sz, sz);
5008 gfc_free_expr (sz);
5009 memsz = se_sz.expr;
5010 }
5011 else
5012 memsz = TYPE_SIZE_UNIT (gfc_typenode_for_spec (&code->expr3->ts));
5013 }
5014 else if (((al->expr->ts.type == BT_CHARACTER && al->expr->ts.deferred)
5015 || unlimited_char) && code->expr3)
5016 {
5017 if (!code->expr3->ts.u.cl->backend_decl)
5018 {
5019 /* Convert and use the length expression. */
5020 gfc_init_se (&se_sz, NULL);
5021 if (code->expr3->expr_type == EXPR_VARIABLE
5022 || code->expr3->expr_type == EXPR_CONSTANT)
5023 {
5024 gfc_conv_expr (&se_sz, code->expr3);
5025 gfc_add_block_to_block (&se.pre, &se_sz.pre);
5026 se_sz.string_length
5027 = gfc_evaluate_now (se_sz.string_length, &se.pre);
5028 gfc_add_block_to_block (&se.pre, &se_sz.post);
5029 memsz = se_sz.string_length;
5030 }
5031 else if (code->expr3->mold
5032 && code->expr3->ts.u.cl
5033 && code->expr3->ts.u.cl->length)
5034 {
5035 gfc_conv_expr (&se_sz, code->expr3->ts.u.cl->length);
5036 gfc_add_block_to_block (&se.pre, &se_sz.pre);
5037 se_sz.expr = gfc_evaluate_now (se_sz.expr, &se.pre);
5038 gfc_add_block_to_block (&se.pre, &se_sz.post);
5039 memsz = se_sz.expr;
5040 }
5041 else
5042 {
5043 /* This is would be inefficient and possibly could
5044 generate wrong code if the result were not stored
5045 in expr3/slen3. */
5046 if (slen3 == NULL_TREE)
5047 {
5048 gfc_conv_expr (&se_sz, code->expr3);
5049 gfc_add_block_to_block (&se.pre, &se_sz.pre);
5050 expr3 = gfc_evaluate_now (se_sz.expr, &se.pre);
5051 gfc_add_block_to_block (&post, &se_sz.post);
5052 slen3 = gfc_evaluate_now (se_sz.string_length,
5053 &se.pre);
5054 }
5055 memsz = slen3;
5056 }
5057 }
5058 else
5059 /* Otherwise use the stored string length. */
5060 memsz = code->expr3->ts.u.cl->backend_decl;
5061 tmp = al->expr->ts.u.cl->backend_decl;
5062
5063 /* Store the string length. */
5064 if (tmp && TREE_CODE (tmp) == VAR_DECL)
5065 gfc_add_modify (&se.pre, tmp, fold_convert (TREE_TYPE (tmp),
5066 memsz));
5067 else if (al->expr->ts.type == BT_CHARACTER
5068 && al->expr->ts.deferred && se.string_length)
5069 gfc_add_modify (&se.pre, se.string_length,
5070 fold_convert (TREE_TYPE (se.string_length),
5071 memsz));
5072
5073 /* Convert to size in bytes, using the character KIND. */
5074 if (unlimited_char)
5075 tmp = TREE_TYPE (gfc_typenode_for_spec (&code->expr3->ts));
5076 else
5077 tmp = TREE_TYPE (gfc_typenode_for_spec (&al->expr->ts));
5078 tmp = TYPE_SIZE_UNIT (tmp);
5079 memsz = fold_build2_loc (input_location, MULT_EXPR,
5080 TREE_TYPE (tmp), tmp,
5081 fold_convert (TREE_TYPE (tmp), memsz));
5082 }
5083 else if ((al->expr->ts.type == BT_CHARACTER && al->expr->ts.deferred)
5084 || unlimited_char)
5085 {
5086 gcc_assert (code->ext.alloc.ts.u.cl && code->ext.alloc.ts.u.cl->length);
5087 gfc_init_se (&se_sz, NULL);
5088 gfc_conv_expr (&se_sz, code->ext.alloc.ts.u.cl->length);
5089 gfc_add_block_to_block (&se.pre, &se_sz.pre);
5090 se_sz.expr = gfc_evaluate_now (se_sz.expr, &se.pre);
5091 gfc_add_block_to_block (&se.pre, &se_sz.post);
5092 /* Store the string length. */
5093 tmp = al->expr->ts.u.cl->backend_decl;
5094 gfc_add_modify (&se.pre, tmp, fold_convert (TREE_TYPE (tmp),
5095 se_sz.expr));
5096 tmp = TREE_TYPE (gfc_typenode_for_spec (&code->ext.alloc.ts));
5097 tmp = TYPE_SIZE_UNIT (tmp);
5098 memsz = fold_build2_loc (input_location, MULT_EXPR,
5099 TREE_TYPE (tmp), tmp,
5100 fold_convert (TREE_TYPE (se_sz.expr),
5101 se_sz.expr));
5102 }
5103 else if (code->ext.alloc.ts.type != BT_UNKNOWN)
5104 memsz = TYPE_SIZE_UNIT (gfc_typenode_for_spec (&code->ext.alloc.ts));
5105 else if (memsz == NULL_TREE)
5106 memsz = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (se.expr)));
5107
5108 if (expr->ts.type == BT_CHARACTER && memsz == NULL_TREE)
5109 {
5110 memsz = se.string_length;
5111
5112 /* Convert to size in bytes, using the character KIND. */
5113 tmp = TREE_TYPE (gfc_typenode_for_spec (&code->ext.alloc.ts));
5114 tmp = TYPE_SIZE_UNIT (tmp);
5115 memsz = fold_build2_loc (input_location, MULT_EXPR,
5116 TREE_TYPE (tmp), tmp,
5117 fold_convert (TREE_TYPE (tmp), memsz));
5118 }
5119
5120 /* Allocate - for non-pointers with re-alloc checking. */
5121 if (gfc_expr_attr (expr).allocatable)
5122 gfc_allocate_allocatable (&se.pre, se.expr, memsz, NULL_TREE,
5123 stat, errmsg, errlen, label_finish, expr);
5124 else
5125 gfc_allocate_using_malloc (&se.pre, se.expr, memsz, stat);
5126
5127 if (al->expr->ts.type == BT_DERIVED
5128 && expr->ts.u.derived->attr.alloc_comp)
5129 {
5130 tmp = build_fold_indirect_ref_loc (input_location, se.expr);
5131 tmp = gfc_nullify_alloc_comp (expr->ts.u.derived, tmp, 0);
5132 gfc_add_expr_to_block (&se.pre, tmp);
5133 }
5134 }
5135
5136 gfc_add_block_to_block (&block, &se.pre);
5137
5138 /* Error checking -- Note: ERRMSG only makes sense with STAT. */
5139 if (code->expr1)
5140 {
5141 tmp = build1_v (GOTO_EXPR, label_errmsg);
5142 parm = fold_build2_loc (input_location, NE_EXPR,
5143 boolean_type_node, stat,
5144 build_int_cst (TREE_TYPE (stat), 0));
5145 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
5146 gfc_unlikely (parm, PRED_FORTRAN_FAIL_ALLOC),
5147 tmp, build_empty_stmt (input_location));
5148 gfc_add_expr_to_block (&block, tmp);
5149 }
5150
5151 /* We need the vptr of CLASS objects to be initialized. */
5152 e = gfc_copy_expr (al->expr);
5153 if (e->ts.type == BT_CLASS)
5154 {
5155 gfc_expr *lhs, *rhs;
5156 gfc_se lse;
5157 gfc_ref *ref, *class_ref, *tail;
5158
5159 /* Find the last class reference. */
5160 class_ref = NULL;
5161 for (ref = e->ref; ref; ref = ref->next)
5162 {
5163 if (ref->type == REF_COMPONENT
5164 && ref->u.c.component->ts.type == BT_CLASS)
5165 class_ref = ref;
5166
5167 if (ref->next == NULL)
5168 break;
5169 }
5170
5171 /* Remove and store all subsequent references after the
5172 CLASS reference. */
5173 if (class_ref)
5174 {
5175 tail = class_ref->next;
5176 class_ref->next = NULL;
5177 }
5178 else
5179 {
5180 tail = e->ref;
5181 e->ref = NULL;
5182 }
5183
5184 lhs = gfc_expr_to_initialize (e);
5185 gfc_add_vptr_component (lhs);
5186
5187 /* Remove the _vptr component and restore the original tail
5188 references. */
5189 if (class_ref)
5190 {
5191 gfc_free_ref_list (class_ref->next);
5192 class_ref->next = tail;
5193 }
5194 else
5195 {
5196 gfc_free_ref_list (e->ref);
5197 e->ref = tail;
5198 }
5199
5200 if (class_expr != NULL_TREE)
5201 {
5202 /* Polymorphic SOURCE: VPTR must be determined at run time. */
5203 gfc_init_se (&lse, NULL);
5204 lse.want_pointer = 1;
5205 gfc_conv_expr (&lse, lhs);
5206 tmp = gfc_class_vptr_get (class_expr);
5207 gfc_add_modify (&block, lse.expr,
5208 fold_convert (TREE_TYPE (lse.expr), tmp));
5209 }
5210 else if (code->expr3 && code->expr3->ts.type == BT_CLASS)
5211 {
5212 /* Polymorphic SOURCE: VPTR must be determined at run time. */
5213 rhs = gfc_copy_expr (code->expr3);
5214 gfc_add_vptr_component (rhs);
5215 tmp = gfc_trans_pointer_assignment (lhs, rhs);
5216 gfc_add_expr_to_block (&block, tmp);
5217 gfc_free_expr (rhs);
5218 rhs = gfc_expr_to_initialize (e);
5219 }
5220 else
5221 {
5222 /* VPTR is fixed at compile time. */
5223 gfc_symbol *vtab;
5224 gfc_typespec *ts;
5225 if (code->expr3)
5226 ts = &code->expr3->ts;
5227 else if (e->ts.type == BT_DERIVED)
5228 ts = &e->ts;
5229 else if (code->ext.alloc.ts.type == BT_DERIVED || UNLIMITED_POLY (al->expr))
5230 ts = &code->ext.alloc.ts;
5231 else if (e->ts.type == BT_CLASS)
5232 ts = &CLASS_DATA (e)->ts;
5233 else
5234 ts = &e->ts;
5235
5236 if (ts->type == BT_DERIVED || UNLIMITED_POLY (e))
5237 {
5238 vtab = gfc_find_vtab (ts);
5239 gcc_assert (vtab);
5240 gfc_init_se (&lse, NULL);
5241 lse.want_pointer = 1;
5242 gfc_conv_expr (&lse, lhs);
5243 tmp = gfc_build_addr_expr (NULL_TREE,
5244 gfc_get_symbol_decl (vtab));
5245 gfc_add_modify (&block, lse.expr,
5246 fold_convert (TREE_TYPE (lse.expr), tmp));
5247 }
5248 }
5249 gfc_free_expr (lhs);
5250 }
5251
5252 gfc_free_expr (e);
5253
5254 if (code->expr3 && !code->expr3->mold)
5255 {
5256 /* Initialization via SOURCE block
5257 (or static default initializer). */
5258 gfc_expr *rhs = gfc_copy_expr (code->expr3);
5259 if (class_expr != NULL_TREE)
5260 {
5261 tree to;
5262 to = TREE_OPERAND (se.expr, 0);
5263
5264 tmp = gfc_copy_class_to_class (class_expr, to, nelems);
5265 }
5266 else if (al->expr->ts.type == BT_CLASS)
5267 {
5268 gfc_actual_arglist *actual;
5269 gfc_expr *ppc;
5270 gfc_code *ppc_code;
5271 gfc_ref *ref, *dataref;
5272
5273 /* Do a polymorphic deep copy. */
5274 actual = gfc_get_actual_arglist ();
5275 actual->expr = gfc_copy_expr (rhs);
5276 if (rhs->ts.type == BT_CLASS)
5277 gfc_add_data_component (actual->expr);
5278 actual->next = gfc_get_actual_arglist ();
5279 actual->next->expr = gfc_copy_expr (al->expr);
5280 actual->next->expr->ts.type = BT_CLASS;
5281 gfc_add_data_component (actual->next->expr);
5282
5283 dataref = NULL;
5284 /* Make sure we go up through the reference chain to
5285 the _data reference, where the arrayspec is found. */
5286 for (ref = actual->next->expr->ref; ref; ref = ref->next)
5287 if (ref->type == REF_COMPONENT
5288 && strcmp (ref->u.c.component->name, "_data") == 0)
5289 dataref = ref;
5290
5291 if (dataref && dataref->u.c.component->as)
5292 {
5293 int dim;
5294 gfc_expr *temp;
5295 gfc_ref *ref = dataref->next;
5296 ref->u.ar.type = AR_SECTION;
5297 /* We have to set up the array reference to give ranges
5298 in all dimensions and ensure that the end and stride
5299 are set so that the copy can be scalarized. */
5300 dim = 0;
5301 for (; dim < dataref->u.c.component->as->rank; dim++)
5302 {
5303 ref->u.ar.dimen_type[dim] = DIMEN_RANGE;
5304 if (ref->u.ar.end[dim] == NULL)
5305 {
5306 ref->u.ar.end[dim] = ref->u.ar.start[dim];
5307 temp = gfc_get_int_expr (gfc_default_integer_kind,
5308 &al->expr->where, 1);
5309 ref->u.ar.start[dim] = temp;
5310 }
5311 temp = gfc_subtract (gfc_copy_expr (ref->u.ar.end[dim]),
5312 gfc_copy_expr (ref->u.ar.start[dim]));
5313 temp = gfc_add (gfc_get_int_expr (gfc_default_integer_kind,
5314 &al->expr->where, 1),
5315 temp);
5316 }
5317 }
5318 if (rhs->ts.type == BT_CLASS)
5319 {
5320 ppc = gfc_copy_expr (rhs);
5321 gfc_add_vptr_component (ppc);
5322 }
5323 else
5324 ppc = gfc_lval_expr_from_sym (gfc_find_vtab (&rhs->ts));
5325 gfc_add_component_ref (ppc, "_copy");
5326
5327 ppc_code = gfc_get_code (EXEC_CALL);
5328 ppc_code->resolved_sym = ppc->symtree->n.sym;
5329 /* Although '_copy' is set to be elemental in class.c, it is
5330 not staying that way. Find out why, sometime.... */
5331 ppc_code->resolved_sym->attr.elemental = 1;
5332 ppc_code->ext.actual = actual;
5333 ppc_code->expr1 = ppc;
5334 /* Since '_copy' is elemental, the scalarizer will take care
5335 of arrays in gfc_trans_call. */
5336 tmp = gfc_trans_call (ppc_code, true, NULL, NULL, false);
5337 gfc_free_statements (ppc_code);
5338 }
5339 else if (expr3 != NULL_TREE)
5340 {
5341 tmp = build_fold_indirect_ref_loc (input_location, se.expr);
5342 gfc_trans_string_copy (&block, slen3, tmp, code->expr3->ts.kind,
5343 slen3, expr3, code->expr3->ts.kind);
5344 tmp = NULL_TREE;
5345 }
5346 else
5347 {
5348 /* Switch off automatic reallocation since we have just done
5349 the ALLOCATE. */
5350 int realloc_lhs = flag_realloc_lhs;
5351 flag_realloc_lhs = 0;
5352 tmp = gfc_trans_assignment (gfc_expr_to_initialize (expr),
5353 rhs, false, false);
5354 flag_realloc_lhs = realloc_lhs;
5355 }
5356 gfc_free_expr (rhs);
5357 gfc_add_expr_to_block (&block, tmp);
5358 }
5359 else if (code->expr3 && code->expr3->mold
5360 && code->expr3->ts.type == BT_CLASS)
5361 {
5362 /* Since the _vptr has already been assigned to the allocate
5363 object, we can use gfc_copy_class_to_class in its
5364 initialization mode. */
5365 tmp = TREE_OPERAND (se.expr, 0);
5366 tmp = gfc_copy_class_to_class (NULL_TREE, tmp, nelems);
5367 gfc_add_expr_to_block (&block, tmp);
5368 }
5369
5370 gfc_free_expr (expr);
5371 }
5372
5373 /* STAT. */
5374 if (code->expr1)
5375 {
5376 tmp = build1_v (LABEL_EXPR, label_errmsg);
5377 gfc_add_expr_to_block (&block, tmp);
5378 }
5379
5380 /* ERRMSG - only useful if STAT is present. */
5381 if (code->expr1 && code->expr2)
5382 {
5383 const char *msg = "Attempt to allocate an allocated object";
5384 tree slen, dlen, errmsg_str;
5385 stmtblock_t errmsg_block;
5386
5387 gfc_init_block (&errmsg_block);
5388
5389 errmsg_str = gfc_create_var (pchar_type_node, "ERRMSG");
5390 gfc_add_modify (&errmsg_block, errmsg_str,
5391 gfc_build_addr_expr (pchar_type_node,
5392 gfc_build_localized_cstring_const (msg)));
5393
5394 slen = build_int_cst (gfc_charlen_type_node, ((int) strlen (msg)));
5395 dlen = gfc_get_expr_charlen (code->expr2);
5396 slen = fold_build2_loc (input_location, MIN_EXPR, TREE_TYPE (slen), dlen,
5397 slen);
5398
5399 gfc_trans_string_copy (&errmsg_block, dlen, errmsg, code->expr2->ts.kind,
5400 slen, errmsg_str, gfc_default_character_kind);
5401 dlen = gfc_finish_block (&errmsg_block);
5402
5403 tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, stat,
5404 build_int_cst (TREE_TYPE (stat), 0));
5405
5406 tmp = build3_v (COND_EXPR, tmp, dlen, build_empty_stmt (input_location));
5407
5408 gfc_add_expr_to_block (&block, tmp);
5409 }
5410
5411 /* STAT block. */
5412 if (code->expr1)
5413 {
5414 if (TREE_USED (label_finish))
5415 {
5416 tmp = build1_v (LABEL_EXPR, label_finish);
5417 gfc_add_expr_to_block (&block, tmp);
5418 }
5419
5420 gfc_init_se (&se, NULL);
5421 gfc_conv_expr_lhs (&se, code->expr1);
5422 tmp = convert (TREE_TYPE (se.expr), stat);
5423 gfc_add_modify (&block, se.expr, tmp);
5424 }
5425
5426 gfc_add_block_to_block (&block, &se.post);
5427 gfc_add_block_to_block (&block, &post);
5428
5429 return gfc_finish_block (&block);
5430 }
5431
5432
5433 /* Translate a DEALLOCATE statement. */
5434
5435 tree
5436 gfc_trans_deallocate (gfc_code *code)
5437 {
5438 gfc_se se;
5439 gfc_alloc *al;
5440 tree apstat, pstat, stat, errmsg, errlen, tmp;
5441 tree label_finish, label_errmsg;
5442 stmtblock_t block;
5443
5444 pstat = apstat = stat = errmsg = errlen = tmp = NULL_TREE;
5445 label_finish = label_errmsg = NULL_TREE;
5446
5447 gfc_start_block (&block);
5448
5449 /* Count the number of failed deallocations. If deallocate() was
5450 called with STAT= , then set STAT to the count. If deallocate
5451 was called with ERRMSG, then set ERRMG to a string. */
5452 if (code->expr1)
5453 {
5454 tree gfc_int4_type_node = gfc_get_int_type (4);
5455
5456 stat = gfc_create_var (gfc_int4_type_node, "stat");
5457 pstat = gfc_build_addr_expr (NULL_TREE, stat);
5458
5459 /* GOTO destinations. */
5460 label_errmsg = gfc_build_label_decl (NULL_TREE);
5461 label_finish = gfc_build_label_decl (NULL_TREE);
5462 TREE_USED (label_finish) = 0;
5463 }
5464
5465 /* Set ERRMSG - only needed if STAT is available. */
5466 if (code->expr1 && code->expr2)
5467 {
5468 gfc_init_se (&se, NULL);
5469 se.want_pointer = 1;
5470 gfc_conv_expr_lhs (&se, code->expr2);
5471 errmsg = se.expr;
5472 errlen = se.string_length;
5473 }
5474
5475 for (al = code->ext.alloc.list; al != NULL; al = al->next)
5476 {
5477 gfc_expr *expr = gfc_copy_expr (al->expr);
5478 gcc_assert (expr->expr_type == EXPR_VARIABLE);
5479
5480 if (expr->ts.type == BT_CLASS)
5481 gfc_add_data_component (expr);
5482
5483 gfc_init_se (&se, NULL);
5484 gfc_start_block (&se.pre);
5485
5486 se.want_pointer = 1;
5487 se.descriptor_only = 1;
5488 gfc_conv_expr (&se, expr);
5489
5490 if (expr->rank || gfc_is_coarray (expr))
5491 {
5492 if (expr->ts.type == BT_DERIVED && expr->ts.u.derived->attr.alloc_comp
5493 && !gfc_is_finalizable (expr->ts.u.derived, NULL))
5494 {
5495 gfc_ref *ref;
5496 gfc_ref *last = NULL;
5497 for (ref = expr->ref; ref; ref = ref->next)
5498 if (ref->type == REF_COMPONENT)
5499 last = ref;
5500
5501 /* Do not deallocate the components of a derived type
5502 ultimate pointer component. */
5503 if (!(last && last->u.c.component->attr.pointer)
5504 && !(!last && expr->symtree->n.sym->attr.pointer))
5505 {
5506 tmp = gfc_deallocate_alloc_comp (expr->ts.u.derived, se.expr,
5507 expr->rank);
5508 gfc_add_expr_to_block (&se.pre, tmp);
5509 }
5510 }
5511 tmp = gfc_array_deallocate (se.expr, pstat, errmsg, errlen,
5512 label_finish, expr);
5513 gfc_add_expr_to_block (&se.pre, tmp);
5514 if (al->expr->ts.type == BT_CLASS)
5515 gfc_reset_vptr (&se.pre, al->expr);
5516 }
5517 else
5518 {
5519 tmp = gfc_deallocate_scalar_with_status (se.expr, pstat, false,
5520 al->expr, al->expr->ts);
5521 gfc_add_expr_to_block (&se.pre, tmp);
5522
5523 /* Set to zero after deallocation. */
5524 tmp = fold_build2_loc (input_location, MODIFY_EXPR, void_type_node,
5525 se.expr,
5526 build_int_cst (TREE_TYPE (se.expr), 0));
5527 gfc_add_expr_to_block (&se.pre, tmp);
5528
5529 if (al->expr->ts.type == BT_CLASS)
5530 gfc_reset_vptr (&se.pre, al->expr);
5531 }
5532
5533 if (code->expr1)
5534 {
5535 tree cond;
5536
5537 cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, stat,
5538 build_int_cst (TREE_TYPE (stat), 0));
5539 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
5540 gfc_unlikely (cond, PRED_FORTRAN_FAIL_ALLOC),
5541 build1_v (GOTO_EXPR, label_errmsg),
5542 build_empty_stmt (input_location));
5543 gfc_add_expr_to_block (&se.pre, tmp);
5544 }
5545
5546 tmp = gfc_finish_block (&se.pre);
5547 gfc_add_expr_to_block (&block, tmp);
5548 gfc_free_expr (expr);
5549 }
5550
5551 if (code->expr1)
5552 {
5553 tmp = build1_v (LABEL_EXPR, label_errmsg);
5554 gfc_add_expr_to_block (&block, tmp);
5555 }
5556
5557 /* Set ERRMSG - only needed if STAT is available. */
5558 if (code->expr1 && code->expr2)
5559 {
5560 const char *msg = "Attempt to deallocate an unallocated object";
5561 stmtblock_t errmsg_block;
5562 tree errmsg_str, slen, dlen, cond;
5563
5564 gfc_init_block (&errmsg_block);
5565
5566 errmsg_str = gfc_create_var (pchar_type_node, "ERRMSG");
5567 gfc_add_modify (&errmsg_block, errmsg_str,
5568 gfc_build_addr_expr (pchar_type_node,
5569 gfc_build_localized_cstring_const (msg)));
5570 slen = build_int_cst (gfc_charlen_type_node, ((int) strlen (msg)));
5571 dlen = gfc_get_expr_charlen (code->expr2);
5572
5573 gfc_trans_string_copy (&errmsg_block, dlen, errmsg, code->expr2->ts.kind,
5574 slen, errmsg_str, gfc_default_character_kind);
5575 tmp = gfc_finish_block (&errmsg_block);
5576
5577 cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, stat,
5578 build_int_cst (TREE_TYPE (stat), 0));
5579 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
5580 gfc_unlikely (cond, PRED_FORTRAN_FAIL_ALLOC), tmp,
5581 build_empty_stmt (input_location));
5582
5583 gfc_add_expr_to_block (&block, tmp);
5584 }
5585
5586 if (code->expr1 && TREE_USED (label_finish))
5587 {
5588 tmp = build1_v (LABEL_EXPR, label_finish);
5589 gfc_add_expr_to_block (&block, tmp);
5590 }
5591
5592 /* Set STAT. */
5593 if (code->expr1)
5594 {
5595 gfc_init_se (&se, NULL);
5596 gfc_conv_expr_lhs (&se, code->expr1);
5597 tmp = convert (TREE_TYPE (se.expr), stat);
5598 gfc_add_modify (&block, se.expr, tmp);
5599 }
5600
5601 return gfc_finish_block (&block);
5602 }
5603
5604 #include "gt-fortran-trans-stmt.h"