Skip several gcc.dg/builtin-dynamic-object-size tests on hppa*-*-hpux*
[official-gcc.git] / gcc / fortran / trans-stmt.cc
blob5247d3d39d71bf4ee7871a6539b3d2364d1b821d
1 /* Statement translation -- generate GCC trees from gfc_code.
2 Copyright (C) 2002-2024 Free Software Foundation, Inc.
3 Contributed by Paul Brook <paul@nowt.org>
4 and Steven Bosscher <s.bosscher@student.tudelft.nl>
6 This file is part of GCC.
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.
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.
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/>. */
23 #include "config.h"
24 #include "system.h"
25 #include "coretypes.h"
26 #include "options.h"
27 #include "tree.h"
28 #include "gfortran.h"
29 #include "trans.h"
30 #include "stringpool.h"
31 #include "fold-const.h"
32 #include "trans-stmt.h"
33 #include "trans-types.h"
34 #include "trans-array.h"
35 #include "trans-const.h"
36 #include "dependency.h"
38 typedef struct iter_info
40 tree var;
41 tree start;
42 tree end;
43 tree step;
44 gfc_loop_annot annot;
45 struct iter_info *next;
47 iter_info;
49 typedef struct forall_info
51 iter_info *this_loop;
52 tree mask;
53 tree maskindex;
54 int nvar;
55 tree size;
56 struct forall_info *prev_nest;
57 bool do_concurrent;
59 forall_info;
61 static void gfc_trans_where_2 (gfc_code *, tree, bool,
62 forall_info *, stmtblock_t *);
64 /* Translate a F95 label number to a LABEL_EXPR. */
66 tree
67 gfc_trans_label_here (gfc_code * code)
69 return build1_v (LABEL_EXPR, gfc_get_label_decl (code->here));
73 /* Given a variable expression which has been ASSIGNed to, find the decl
74 containing the auxiliary variables. For variables in common blocks this
75 is a field_decl. */
77 void
78 gfc_conv_label_variable (gfc_se * se, gfc_expr * expr)
80 gcc_assert (expr->symtree->n.sym->attr.assign == 1);
81 gfc_conv_expr (se, expr);
82 /* Deals with variable in common block. Get the field declaration. */
83 if (TREE_CODE (se->expr) == COMPONENT_REF)
84 se->expr = TREE_OPERAND (se->expr, 1);
85 /* Deals with dummy argument. Get the parameter declaration. */
86 else if (INDIRECT_REF_P (se->expr))
87 se->expr = TREE_OPERAND (se->expr, 0);
90 /* Translate a label assignment statement. */
92 tree
93 gfc_trans_label_assign (gfc_code * code)
95 tree label_tree;
96 gfc_se se;
97 tree len;
98 tree addr;
99 tree len_tree;
100 int label_len;
102 /* Start a new block. */
103 gfc_init_se (&se, NULL);
104 gfc_start_block (&se.pre);
105 gfc_conv_label_variable (&se, code->expr1);
107 len = GFC_DECL_STRING_LEN (se.expr);
108 addr = GFC_DECL_ASSIGN_ADDR (se.expr);
110 label_tree = gfc_get_label_decl (code->label1);
112 if (code->label1->defined == ST_LABEL_TARGET
113 || code->label1->defined == ST_LABEL_DO_TARGET)
115 label_tree = gfc_build_addr_expr (pvoid_type_node, label_tree);
116 len_tree = build_int_cst (gfc_charlen_type_node, -1);
118 else
120 gfc_expr *format = code->label1->format;
122 label_len = format->value.character.length;
123 len_tree = build_int_cst (gfc_charlen_type_node, label_len);
124 label_tree = gfc_build_wide_string_const (format->ts.kind, label_len + 1,
125 format->value.character.string);
126 label_tree = gfc_build_addr_expr (pvoid_type_node, label_tree);
129 gfc_add_modify (&se.pre, len, fold_convert (TREE_TYPE (len), len_tree));
130 gfc_add_modify (&se.pre, addr, label_tree);
132 return gfc_finish_block (&se.pre);
135 /* Translate a GOTO statement. */
137 tree
138 gfc_trans_goto (gfc_code * code)
140 locus loc = code->loc;
141 tree assigned_goto;
142 tree target;
143 tree tmp;
144 gfc_se se;
146 if (code->label1 != NULL)
147 return build1_v (GOTO_EXPR, gfc_get_label_decl (code->label1));
149 /* ASSIGNED GOTO. */
150 gfc_init_se (&se, NULL);
151 gfc_start_block (&se.pre);
152 gfc_conv_label_variable (&se, code->expr1);
153 tmp = GFC_DECL_STRING_LEN (se.expr);
154 tmp = fold_build2_loc (input_location, NE_EXPR, logical_type_node, tmp,
155 build_int_cst (TREE_TYPE (tmp), -1));
156 gfc_trans_runtime_check (true, false, tmp, &se.pre, &loc,
157 "Assigned label is not a target label");
159 assigned_goto = GFC_DECL_ASSIGN_ADDR (se.expr);
161 /* We're going to ignore a label list. It does not really change the
162 statement's semantics (because it is just a further restriction on
163 what's legal code); before, we were comparing label addresses here, but
164 that's a very fragile business and may break with optimization. So
165 just ignore it. */
167 target = fold_build1_loc (input_location, GOTO_EXPR, void_type_node,
168 assigned_goto);
169 gfc_add_expr_to_block (&se.pre, target);
170 return gfc_finish_block (&se.pre);
174 /* Translate an ENTRY statement. Just adds a label for this entry point. */
175 tree
176 gfc_trans_entry (gfc_code * code)
178 return build1_v (LABEL_EXPR, code->ext.entry->label);
182 /* Replace a gfc_ss structure by another both in the gfc_se struct
183 and the gfc_loopinfo struct. This is used in gfc_conv_elemental_dependencies
184 to replace a variable ss by the corresponding temporary. */
186 static void
187 replace_ss (gfc_se *se, gfc_ss *old_ss, gfc_ss *new_ss)
189 gfc_ss **sess, **loopss;
191 /* The old_ss is a ss for a single variable. */
192 gcc_assert (old_ss->info->type == GFC_SS_SECTION);
194 for (sess = &(se->ss); *sess != gfc_ss_terminator; sess = &((*sess)->next))
195 if (*sess == old_ss)
196 break;
197 gcc_assert (*sess != gfc_ss_terminator);
199 *sess = new_ss;
200 new_ss->next = old_ss->next;
202 /* Make sure that trailing references are not lost. */
203 if (old_ss->info
204 && old_ss->info->data.array.ref
205 && old_ss->info->data.array.ref->next
206 && !(new_ss->info->data.array.ref
207 && new_ss->info->data.array.ref->next))
208 new_ss->info->data.array.ref = old_ss->info->data.array.ref;
210 for (loopss = &(se->loop->ss); *loopss != gfc_ss_terminator;
211 loopss = &((*loopss)->loop_chain))
212 if (*loopss == old_ss)
213 break;
214 gcc_assert (*loopss != gfc_ss_terminator);
216 *loopss = new_ss;
217 new_ss->loop_chain = old_ss->loop_chain;
218 new_ss->loop = old_ss->loop;
220 gfc_free_ss (old_ss);
224 /* Check for dependencies between INTENT(IN) and INTENT(OUT) arguments of
225 elemental subroutines. Make temporaries for output arguments if any such
226 dependencies are found. Output arguments are chosen because internal_unpack
227 can be used, as is, to copy the result back to the variable. */
228 static void
229 gfc_conv_elemental_dependencies (gfc_se * se, gfc_se * loopse,
230 gfc_symbol * sym, gfc_actual_arglist * arg,
231 gfc_dep_check check_variable)
233 gfc_actual_arglist *arg0;
234 gfc_expr *e;
235 gfc_formal_arglist *formal;
236 gfc_se parmse;
237 gfc_ss *ss;
238 gfc_symbol *fsym;
239 tree data;
240 tree size;
241 tree tmp;
243 if (loopse->ss == NULL)
244 return;
246 ss = loopse->ss;
247 arg0 = arg;
248 formal = gfc_sym_get_dummy_args (sym);
250 /* Loop over all the arguments testing for dependencies. */
251 for (; arg != NULL; arg = arg->next, formal = formal ? formal->next : NULL)
253 e = arg->expr;
254 if (e == NULL)
255 continue;
257 /* Obtain the info structure for the current argument. */
258 for (ss = loopse->ss; ss && ss != gfc_ss_terminator; ss = ss->next)
259 if (ss->info->expr == e)
260 break;
262 /* If there is a dependency, create a temporary and use it
263 instead of the variable. */
264 fsym = formal ? formal->sym : NULL;
265 if (e->expr_type == EXPR_VARIABLE
266 && e->rank && fsym
267 && fsym->attr.intent != INTENT_IN
268 && !fsym->attr.value
269 && gfc_check_fncall_dependency (e, fsym->attr.intent,
270 sym, arg0, check_variable))
272 tree initial, temptype;
273 stmtblock_t temp_post;
274 gfc_ss *tmp_ss;
276 tmp_ss = gfc_get_array_ss (gfc_ss_terminator, NULL, ss->dimen,
277 GFC_SS_SECTION);
278 gfc_mark_ss_chain_used (tmp_ss, 1);
279 tmp_ss->info->expr = ss->info->expr;
280 replace_ss (loopse, ss, tmp_ss);
282 /* Obtain the argument descriptor for unpacking. */
283 gfc_init_se (&parmse, NULL);
284 parmse.want_pointer = 1;
285 gfc_conv_expr_descriptor (&parmse, e);
286 gfc_add_block_to_block (&se->pre, &parmse.pre);
288 /* If we've got INTENT(INOUT) or a derived type with INTENT(OUT),
289 initialize the array temporary with a copy of the values. */
290 if (fsym->attr.intent == INTENT_INOUT
291 || (fsym->ts.type ==BT_DERIVED
292 && fsym->attr.intent == INTENT_OUT))
293 initial = parmse.expr;
294 /* For class expressions, we always initialize with the copy of
295 the values. */
296 else if (e->ts.type == BT_CLASS)
297 initial = parmse.expr;
298 else
299 initial = NULL_TREE;
301 if (e->ts.type != BT_CLASS)
303 /* Find the type of the temporary to create; we don't use the type
304 of e itself as this breaks for subcomponent-references in e
305 (where the type of e is that of the final reference, but
306 parmse.expr's type corresponds to the full derived-type). */
307 /* TODO: Fix this somehow so we don't need a temporary of the whole
308 array but instead only the components referenced. */
309 temptype = TREE_TYPE (parmse.expr); /* Pointer to descriptor. */
310 gcc_assert (TREE_CODE (temptype) == POINTER_TYPE);
311 temptype = TREE_TYPE (temptype);
312 temptype = gfc_get_element_type (temptype);
315 else
316 /* For class arrays signal that the size of the dynamic type has to
317 be obtained from the vtable, using the 'initial' expression. */
318 temptype = NULL_TREE;
320 /* Generate the temporary. Cleaning up the temporary should be the
321 very last thing done, so we add the code to a new block and add it
322 to se->post as last instructions. */
323 size = gfc_create_var (gfc_array_index_type, NULL);
324 data = gfc_create_var (pvoid_type_node, NULL);
325 gfc_init_block (&temp_post);
326 tmp = gfc_trans_create_temp_array (&se->pre, &temp_post, tmp_ss,
327 temptype, initial, false, true,
328 false, &arg->expr->where);
329 gfc_add_modify (&se->pre, size, tmp);
330 tmp = fold_convert (pvoid_type_node, tmp_ss->info->data.array.data);
331 gfc_add_modify (&se->pre, data, tmp);
333 /* Update other ss' delta. */
334 gfc_set_delta (loopse->loop);
336 /* Copy the result back using unpack..... */
337 if (e->ts.type != BT_CLASS)
338 tmp = build_call_expr_loc (input_location,
339 gfor_fndecl_in_unpack, 2, parmse.expr, data);
340 else
342 /* ... except for class results where the copy is
343 unconditional. */
344 tmp = build_fold_indirect_ref_loc (input_location, parmse.expr);
345 tmp = gfc_conv_descriptor_data_get (tmp);
346 tmp = build_call_expr_loc (input_location,
347 builtin_decl_explicit (BUILT_IN_MEMCPY),
348 3, tmp, data,
349 fold_convert (size_type_node, size));
351 gfc_add_expr_to_block (&se->post, tmp);
353 /* parmse.pre is already added above. */
354 gfc_add_block_to_block (&se->post, &parmse.post);
355 gfc_add_block_to_block (&se->post, &temp_post);
361 /* Given an executable statement referring to an intrinsic function call,
362 returns the intrinsic symbol. */
364 static gfc_intrinsic_sym *
365 get_intrinsic_for_code (gfc_code *code)
367 if (code->op == EXEC_CALL)
369 gfc_intrinsic_sym * const isym = code->resolved_isym;
370 if (isym)
371 return isym;
372 else
373 return gfc_get_intrinsic_for_expr (code->expr1);
376 return NULL;
380 /* Translate the CALL statement. Builds a call to an F95 subroutine. */
382 tree
383 gfc_trans_call (gfc_code * code, bool dependency_check,
384 tree mask, tree count1, bool invert)
386 gfc_se se;
387 gfc_ss * ss;
388 int has_alternate_specifier;
389 gfc_dep_check check_variable;
390 tree index = NULL_TREE;
391 tree maskexpr = NULL_TREE;
392 tree tmp;
393 bool is_intrinsic_mvbits;
395 /* A CALL starts a new block because the actual arguments may have to
396 be evaluated first. */
397 gfc_init_se (&se, NULL);
398 gfc_start_block (&se.pre);
400 gcc_assert (code->resolved_sym);
402 ss = gfc_ss_terminator;
403 if (code->resolved_sym->attr.elemental)
404 ss = gfc_walk_elemental_function_args (ss, code->ext.actual,
405 get_intrinsic_for_code (code),
406 GFC_SS_REFERENCE);
408 /* MVBITS is inlined but needs the dependency checking found here. */
409 is_intrinsic_mvbits = code->resolved_isym
410 && code->resolved_isym->id == GFC_ISYM_MVBITS;
412 /* Is not an elemental subroutine call with array valued arguments. */
413 if (ss == gfc_ss_terminator)
416 if (is_intrinsic_mvbits)
418 has_alternate_specifier = 0;
419 gfc_conv_intrinsic_mvbits (&se, code->ext.actual, NULL);
421 else
423 /* Translate the call. */
424 has_alternate_specifier =
425 gfc_conv_procedure_call (&se, code->resolved_sym,
426 code->ext.actual, code->expr1, NULL);
428 /* A subroutine without side-effect, by definition, does nothing! */
429 TREE_SIDE_EFFECTS (se.expr) = 1;
432 /* Chain the pieces together and return the block. */
433 if (has_alternate_specifier)
435 gfc_code *select_code;
436 gfc_symbol *sym;
437 select_code = code->next;
438 gcc_assert(select_code->op == EXEC_SELECT);
439 sym = select_code->expr1->symtree->n.sym;
440 se.expr = convert (gfc_typenode_for_spec (&sym->ts), se.expr);
441 if (sym->backend_decl == NULL)
442 sym->backend_decl = gfc_get_symbol_decl (sym);
443 gfc_add_modify (&se.pre, sym->backend_decl, se.expr);
445 else
446 gfc_add_expr_to_block (&se.pre, se.expr);
448 gfc_add_block_to_block (&se.finalblock, &se.post);
449 gfc_add_block_to_block (&se.pre, &se.finalblock);
452 else
454 /* An elemental subroutine call with array valued arguments has
455 to be scalarized. */
456 gfc_loopinfo loop;
457 stmtblock_t body;
458 stmtblock_t block;
459 gfc_se loopse;
460 gfc_se depse;
462 /* gfc_walk_elemental_function_args renders the ss chain in the
463 reverse order to the actual argument order. */
464 ss = gfc_reverse_ss (ss);
466 /* Initialize the loop. */
467 gfc_init_se (&loopse, NULL);
468 gfc_init_loopinfo (&loop);
469 gfc_add_ss_to_loop (&loop, ss);
471 gfc_conv_ss_startstride (&loop);
472 /* TODO: gfc_conv_loop_setup generates a temporary for vector
473 subscripts. This could be prevented in the elemental case
474 as temporaries are handled separately
475 (below in gfc_conv_elemental_dependencies). */
476 if (code->expr1)
477 gfc_conv_loop_setup (&loop, &code->expr1->where);
478 else
479 gfc_conv_loop_setup (&loop, &code->loc);
481 gfc_mark_ss_chain_used (ss, 1);
483 /* Convert the arguments, checking for dependencies. */
484 gfc_copy_loopinfo_to_se (&loopse, &loop);
485 loopse.ss = ss;
487 /* For operator assignment, do dependency checking. */
488 if (dependency_check)
489 check_variable = ELEM_CHECK_VARIABLE;
490 else
491 check_variable = ELEM_DONT_CHECK_VARIABLE;
493 gfc_init_se (&depse, NULL);
494 gfc_conv_elemental_dependencies (&depse, &loopse, code->resolved_sym,
495 code->ext.actual, check_variable);
497 gfc_add_block_to_block (&loop.pre, &depse.pre);
498 gfc_add_block_to_block (&loop.post, &depse.post);
500 /* Generate the loop body. */
501 gfc_start_scalarized_body (&loop, &body);
502 gfc_init_block (&block);
504 if (mask && count1)
506 /* Form the mask expression according to the mask. */
507 index = count1;
508 maskexpr = gfc_build_array_ref (mask, index, NULL);
509 if (invert)
510 maskexpr = fold_build1_loc (input_location, TRUTH_NOT_EXPR,
511 TREE_TYPE (maskexpr), maskexpr);
514 if (is_intrinsic_mvbits)
516 has_alternate_specifier = 0;
517 gfc_conv_intrinsic_mvbits (&loopse, code->ext.actual, &loop);
519 else
521 /* Add the subroutine call to the block. */
522 gfc_conv_procedure_call (&loopse, code->resolved_sym,
523 code->ext.actual, code->expr1,
524 NULL);
527 if (mask && count1)
529 tmp = build3_v (COND_EXPR, maskexpr, loopse.expr,
530 build_empty_stmt (input_location));
531 gfc_add_expr_to_block (&loopse.pre, tmp);
532 tmp = fold_build2_loc (input_location, PLUS_EXPR,
533 gfc_array_index_type,
534 count1, gfc_index_one_node);
535 gfc_add_modify (&loopse.pre, count1, tmp);
537 else
538 gfc_add_expr_to_block (&loopse.pre, loopse.expr);
540 gfc_add_block_to_block (&block, &loopse.pre);
541 gfc_add_block_to_block (&block, &loopse.post);
543 /* Finish up the loop block and the loop. */
544 gfc_add_expr_to_block (&body, gfc_finish_block (&block));
545 gfc_trans_scalarizing_loops (&loop, &body);
546 gfc_add_block_to_block (&se.pre, &loop.pre);
547 gfc_add_block_to_block (&se.pre, &loop.post);
548 gfc_add_block_to_block (&se.pre, &loopse.finalblock);
549 gfc_add_block_to_block (&se.pre, &se.post);
550 gfc_cleanup_loop (&loop);
553 return gfc_finish_block (&se.pre);
557 /* Translate the RETURN statement. */
559 tree
560 gfc_trans_return (gfc_code * code)
562 if (code->expr1)
564 gfc_se se;
565 tree tmp;
566 tree result;
568 /* If code->expr is not NULL, this return statement must appear
569 in a subroutine and current_fake_result_decl has already
570 been generated. */
572 result = gfc_get_fake_result_decl (NULL, 0);
573 if (!result)
575 gfc_warning (0,
576 "An alternate return at %L without a * dummy argument",
577 &code->expr1->where);
578 return gfc_generate_return ();
581 /* Start a new block for this statement. */
582 gfc_init_se (&se, NULL);
583 gfc_start_block (&se.pre);
585 gfc_conv_expr (&se, code->expr1);
587 /* Note that the actually returned expression is a simple value and
588 does not depend on any pointers or such; thus we can clean-up with
589 se.post before returning. */
590 tmp = fold_build2_loc (input_location, MODIFY_EXPR, TREE_TYPE (result),
591 result, fold_convert (TREE_TYPE (result),
592 se.expr));
593 gfc_add_expr_to_block (&se.pre, tmp);
594 gfc_add_block_to_block (&se.pre, &se.post);
596 tmp = gfc_generate_return ();
597 gfc_add_expr_to_block (&se.pre, tmp);
598 return gfc_finish_block (&se.pre);
601 return gfc_generate_return ();
605 /* Translate the PAUSE statement. We have to translate this statement
606 to a runtime library call. */
608 tree
609 gfc_trans_pause (gfc_code * code)
611 tree gfc_int8_type_node = gfc_get_int_type (8);
612 gfc_se se;
613 tree tmp;
615 /* Start a new block for this statement. */
616 gfc_init_se (&se, NULL);
617 gfc_start_block (&se.pre);
620 if (code->expr1 == NULL)
622 tmp = build_int_cst (size_type_node, 0);
623 tmp = build_call_expr_loc (input_location,
624 gfor_fndecl_pause_string, 2,
625 build_int_cst (pchar_type_node, 0), tmp);
627 else if (code->expr1->ts.type == BT_INTEGER)
629 gfc_conv_expr (&se, code->expr1);
630 tmp = build_call_expr_loc (input_location,
631 gfor_fndecl_pause_numeric, 1,
632 fold_convert (gfc_int8_type_node, se.expr));
634 else
636 gfc_conv_expr_reference (&se, code->expr1);
637 tmp = build_call_expr_loc (input_location,
638 gfor_fndecl_pause_string, 2,
639 se.expr, fold_convert (size_type_node,
640 se.string_length));
643 gfc_add_expr_to_block (&se.pre, tmp);
645 gfc_add_block_to_block (&se.pre, &se.post);
647 return gfc_finish_block (&se.pre);
651 /* Translate the STOP statement. We have to translate this statement
652 to a runtime library call. */
654 tree
655 gfc_trans_stop (gfc_code *code, bool error_stop)
657 gfc_se se;
658 tree tmp;
659 tree quiet;
661 /* Start a new block for this statement. */
662 gfc_init_se (&se, NULL);
663 gfc_start_block (&se.pre);
665 if (code->expr2)
667 gfc_conv_expr_val (&se, code->expr2);
668 quiet = fold_convert (boolean_type_node, se.expr);
670 else
671 quiet = boolean_false_node;
673 if (code->expr1 == NULL)
675 tmp = build_int_cst (size_type_node, 0);
676 tmp = build_call_expr_loc (input_location,
677 error_stop
678 ? (flag_coarray == GFC_FCOARRAY_LIB
679 ? gfor_fndecl_caf_error_stop_str
680 : gfor_fndecl_error_stop_string)
681 : (flag_coarray == GFC_FCOARRAY_LIB
682 ? gfor_fndecl_caf_stop_str
683 : gfor_fndecl_stop_string),
684 3, build_int_cst (pchar_type_node, 0), tmp,
685 quiet);
687 else if (code->expr1->ts.type == BT_INTEGER)
689 gfc_conv_expr (&se, code->expr1);
690 tmp = build_call_expr_loc (input_location,
691 error_stop
692 ? (flag_coarray == GFC_FCOARRAY_LIB
693 ? gfor_fndecl_caf_error_stop
694 : gfor_fndecl_error_stop_numeric)
695 : (flag_coarray == GFC_FCOARRAY_LIB
696 ? gfor_fndecl_caf_stop_numeric
697 : gfor_fndecl_stop_numeric), 2,
698 fold_convert (integer_type_node, se.expr),
699 quiet);
701 else
703 gfc_conv_expr_reference (&se, code->expr1);
704 tmp = build_call_expr_loc (input_location,
705 error_stop
706 ? (flag_coarray == GFC_FCOARRAY_LIB
707 ? gfor_fndecl_caf_error_stop_str
708 : gfor_fndecl_error_stop_string)
709 : (flag_coarray == GFC_FCOARRAY_LIB
710 ? gfor_fndecl_caf_stop_str
711 : gfor_fndecl_stop_string),
712 3, se.expr, fold_convert (size_type_node,
713 se.string_length),
714 quiet);
717 gfc_add_expr_to_block (&se.pre, tmp);
719 gfc_add_block_to_block (&se.pre, &se.post);
721 return gfc_finish_block (&se.pre);
724 /* Translate the FAIL IMAGE statement. */
726 tree
727 gfc_trans_fail_image (gfc_code *code ATTRIBUTE_UNUSED)
729 if (flag_coarray == GFC_FCOARRAY_LIB)
730 return build_call_expr_loc (input_location,
731 gfor_fndecl_caf_fail_image, 0);
732 else
734 const char *name = gfc_get_string (PREFIX ("exit_i%d"), 4);
735 gfc_symbol *exsym = gfc_get_intrinsic_sub_symbol (name);
736 tree tmp = gfc_get_symbol_decl (exsym);
737 return build_call_expr_loc (input_location, tmp, 1, integer_zero_node);
741 /* Translate the FORM TEAM statement. */
743 tree
744 gfc_trans_form_team (gfc_code *code)
746 if (flag_coarray == GFC_FCOARRAY_LIB)
748 gfc_se se;
749 gfc_se argse1, argse2;
750 tree team_id, team_type, tmp;
752 gfc_init_se (&se, NULL);
753 gfc_init_se (&argse1, NULL);
754 gfc_init_se (&argse2, NULL);
755 gfc_start_block (&se.pre);
757 gfc_conv_expr_val (&argse1, code->expr1);
758 gfc_conv_expr_val (&argse2, code->expr2);
759 team_id = fold_convert (integer_type_node, argse1.expr);
760 team_type = gfc_build_addr_expr (ppvoid_type_node, argse2.expr);
762 gfc_add_block_to_block (&se.pre, &argse1.pre);
763 gfc_add_block_to_block (&se.pre, &argse2.pre);
764 tmp = build_call_expr_loc (input_location,
765 gfor_fndecl_caf_form_team, 3,
766 team_id, team_type,
767 build_int_cst (integer_type_node, 0));
768 gfc_add_expr_to_block (&se.pre, tmp);
769 gfc_add_block_to_block (&se.pre, &argse1.post);
770 gfc_add_block_to_block (&se.pre, &argse2.post);
771 return gfc_finish_block (&se.pre);
773 else
775 const char *name = gfc_get_string (PREFIX ("exit_i%d"), 4);
776 gfc_symbol *exsym = gfc_get_intrinsic_sub_symbol (name);
777 tree tmp = gfc_get_symbol_decl (exsym);
778 return build_call_expr_loc (input_location, tmp, 1, integer_zero_node);
782 /* Translate the CHANGE TEAM statement. */
784 tree
785 gfc_trans_change_team (gfc_code *code)
787 if (flag_coarray == GFC_FCOARRAY_LIB)
789 gfc_se argse;
790 tree team_type, tmp;
792 gfc_init_se (&argse, NULL);
793 gfc_conv_expr_val (&argse, code->expr1);
794 team_type = gfc_build_addr_expr (ppvoid_type_node, argse.expr);
796 tmp = build_call_expr_loc (input_location,
797 gfor_fndecl_caf_change_team, 2, team_type,
798 build_int_cst (integer_type_node, 0));
799 gfc_add_expr_to_block (&argse.pre, tmp);
800 gfc_add_block_to_block (&argse.pre, &argse.post);
801 return gfc_finish_block (&argse.pre);
803 else
805 const char *name = gfc_get_string (PREFIX ("exit_i%d"), 4);
806 gfc_symbol *exsym = gfc_get_intrinsic_sub_symbol (name);
807 tree tmp = gfc_get_symbol_decl (exsym);
808 return build_call_expr_loc (input_location, tmp, 1, integer_zero_node);
812 /* Translate the END TEAM statement. */
814 tree
815 gfc_trans_end_team (gfc_code *code ATTRIBUTE_UNUSED)
817 if (flag_coarray == GFC_FCOARRAY_LIB)
819 return build_call_expr_loc (input_location,
820 gfor_fndecl_caf_end_team, 1,
821 build_int_cst (pchar_type_node, 0));
823 else
825 const char *name = gfc_get_string (PREFIX ("exit_i%d"), 4);
826 gfc_symbol *exsym = gfc_get_intrinsic_sub_symbol (name);
827 tree tmp = gfc_get_symbol_decl (exsym);
828 return build_call_expr_loc (input_location, tmp, 1, integer_zero_node);
832 /* Translate the SYNC TEAM statement. */
834 tree
835 gfc_trans_sync_team (gfc_code *code)
837 if (flag_coarray == GFC_FCOARRAY_LIB)
839 gfc_se argse;
840 tree team_type, tmp;
842 gfc_init_se (&argse, NULL);
843 gfc_conv_expr_val (&argse, code->expr1);
844 team_type = gfc_build_addr_expr (ppvoid_type_node, argse.expr);
846 tmp = build_call_expr_loc (input_location,
847 gfor_fndecl_caf_sync_team, 2,
848 team_type,
849 build_int_cst (integer_type_node, 0));
850 gfc_add_expr_to_block (&argse.pre, tmp);
851 gfc_add_block_to_block (&argse.pre, &argse.post);
852 return gfc_finish_block (&argse.pre);
854 else
856 const char *name = gfc_get_string (PREFIX ("exit_i%d"), 4);
857 gfc_symbol *exsym = gfc_get_intrinsic_sub_symbol (name);
858 tree tmp = gfc_get_symbol_decl (exsym);
859 return build_call_expr_loc (input_location, tmp, 1, integer_zero_node);
863 tree
864 gfc_trans_lock_unlock (gfc_code *code, gfc_exec_op op)
866 gfc_se se, argse;
867 tree stat = NULL_TREE, stat2 = NULL_TREE;
868 tree lock_acquired = NULL_TREE, lock_acquired2 = NULL_TREE;
870 /* Short cut: For single images without STAT= or LOCK_ACQUIRED
871 return early. (ERRMSG= is always untouched for -fcoarray=single.) */
872 if (!code->expr2 && !code->expr4 && flag_coarray != GFC_FCOARRAY_LIB)
873 return NULL_TREE;
875 if (code->expr2)
877 gcc_assert (code->expr2->expr_type == EXPR_VARIABLE);
878 gfc_init_se (&argse, NULL);
879 gfc_conv_expr_val (&argse, code->expr2);
880 stat = argse.expr;
882 else if (flag_coarray == GFC_FCOARRAY_LIB)
883 stat = null_pointer_node;
885 if (code->expr4)
887 gcc_assert (code->expr4->expr_type == EXPR_VARIABLE);
888 gfc_init_se (&argse, NULL);
889 gfc_conv_expr_val (&argse, code->expr4);
890 lock_acquired = argse.expr;
892 else if (flag_coarray == GFC_FCOARRAY_LIB)
893 lock_acquired = null_pointer_node;
895 gfc_start_block (&se.pre);
896 if (flag_coarray == GFC_FCOARRAY_LIB)
898 tree tmp, token, image_index, errmsg, errmsg_len;
899 tree index = build_zero_cst (gfc_array_index_type);
900 tree caf_decl = gfc_get_tree_for_caf_expr (code->expr1);
902 if (code->expr1->symtree->n.sym->ts.type != BT_DERIVED
903 || code->expr1->symtree->n.sym->ts.u.derived->from_intmod
904 != INTMOD_ISO_FORTRAN_ENV
905 || code->expr1->symtree->n.sym->ts.u.derived->intmod_sym_id
906 != ISOFORTRAN_LOCK_TYPE)
908 gfc_error ("Sorry, the lock component of derived type at %L is not "
909 "yet supported", &code->expr1->where);
910 return NULL_TREE;
913 gfc_get_caf_token_offset (&se, &token, NULL, caf_decl, NULL_TREE,
914 code->expr1);
916 if (gfc_is_coindexed (code->expr1))
917 image_index = gfc_caf_get_image_index (&se.pre, code->expr1, caf_decl);
918 else
919 image_index = integer_zero_node;
921 /* For arrays, obtain the array index. */
922 if (gfc_expr_attr (code->expr1).dimension)
924 tree desc, tmp, extent, lbound, ubound;
925 gfc_array_ref *ar, ar2;
926 int i;
928 /* TODO: Extend this, once DT components are supported. */
929 ar = &code->expr1->ref->u.ar;
930 ar2 = *ar;
931 memset (ar, '\0', sizeof (*ar));
932 ar->as = ar2.as;
933 ar->type = AR_FULL;
935 gfc_init_se (&argse, NULL);
936 argse.descriptor_only = 1;
937 gfc_conv_expr_descriptor (&argse, code->expr1);
938 gfc_add_block_to_block (&se.pre, &argse.pre);
939 desc = argse.expr;
940 *ar = ar2;
942 extent = build_one_cst (gfc_array_index_type);
943 for (i = 0; i < ar->dimen; i++)
945 gfc_init_se (&argse, NULL);
946 gfc_conv_expr_type (&argse, ar->start[i], gfc_array_index_type);
947 gfc_add_block_to_block (&argse.pre, &argse.pre);
948 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[i]);
949 tmp = fold_build2_loc (input_location, MINUS_EXPR,
950 TREE_TYPE (lbound), argse.expr, lbound);
951 tmp = fold_build2_loc (input_location, MULT_EXPR,
952 TREE_TYPE (tmp), extent, tmp);
953 index = fold_build2_loc (input_location, PLUS_EXPR,
954 TREE_TYPE (tmp), index, tmp);
955 if (i < ar->dimen - 1)
957 ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[i]);
958 tmp = gfc_conv_array_extent_dim (lbound, ubound, NULL);
959 extent = fold_build2_loc (input_location, MULT_EXPR,
960 TREE_TYPE (tmp), extent, tmp);
965 /* errmsg. */
966 if (code->expr3)
968 gfc_init_se (&argse, NULL);
969 argse.want_pointer = 1;
970 gfc_conv_expr (&argse, code->expr3);
971 gfc_add_block_to_block (&se.pre, &argse.pre);
972 errmsg = argse.expr;
973 errmsg_len = fold_convert (size_type_node, argse.string_length);
975 else
977 errmsg = null_pointer_node;
978 errmsg_len = build_zero_cst (size_type_node);
981 if (stat != null_pointer_node && TREE_TYPE (stat) != integer_type_node)
983 stat2 = stat;
984 stat = gfc_create_var (integer_type_node, "stat");
987 if (lock_acquired != null_pointer_node
988 && TREE_TYPE (lock_acquired) != integer_type_node)
990 lock_acquired2 = lock_acquired;
991 lock_acquired = gfc_create_var (integer_type_node, "acquired");
994 index = fold_convert (size_type_node, index);
995 if (op == EXEC_LOCK)
996 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_lock, 7,
997 token, index, image_index,
998 lock_acquired != null_pointer_node
999 ? gfc_build_addr_expr (NULL, lock_acquired)
1000 : lock_acquired,
1001 stat != null_pointer_node
1002 ? gfc_build_addr_expr (NULL, stat) : stat,
1003 errmsg, errmsg_len);
1004 else
1005 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_unlock, 6,
1006 token, index, image_index,
1007 stat != null_pointer_node
1008 ? gfc_build_addr_expr (NULL, stat) : stat,
1009 errmsg, errmsg_len);
1010 gfc_add_expr_to_block (&se.pre, tmp);
1012 /* It guarantees memory consistency within the same segment */
1013 tmp = gfc_build_string_const (strlen ("memory")+1, "memory"),
1014 tmp = build5_loc (input_location, ASM_EXPR, void_type_node,
1015 gfc_build_string_const (1, ""), NULL_TREE, NULL_TREE,
1016 tree_cons (NULL_TREE, tmp, NULL_TREE), NULL_TREE);
1017 ASM_VOLATILE_P (tmp) = 1;
1019 gfc_add_expr_to_block (&se.pre, tmp);
1021 if (stat2 != NULL_TREE)
1022 gfc_add_modify (&se.pre, stat2,
1023 fold_convert (TREE_TYPE (stat2), stat));
1025 if (lock_acquired2 != NULL_TREE)
1026 gfc_add_modify (&se.pre, lock_acquired2,
1027 fold_convert (TREE_TYPE (lock_acquired2),
1028 lock_acquired));
1030 return gfc_finish_block (&se.pre);
1033 if (stat != NULL_TREE)
1034 gfc_add_modify (&se.pre, stat, build_int_cst (TREE_TYPE (stat), 0));
1036 if (lock_acquired != NULL_TREE)
1037 gfc_add_modify (&se.pre, lock_acquired,
1038 fold_convert (TREE_TYPE (lock_acquired),
1039 boolean_true_node));
1041 return gfc_finish_block (&se.pre);
1044 tree
1045 gfc_trans_event_post_wait (gfc_code *code, gfc_exec_op op)
1047 gfc_se se, argse;
1048 tree stat = NULL_TREE, stat2 = NULL_TREE;
1049 tree until_count = NULL_TREE;
1051 if (code->expr2)
1053 gcc_assert (code->expr2->expr_type == EXPR_VARIABLE);
1054 gfc_init_se (&argse, NULL);
1055 gfc_conv_expr_val (&argse, code->expr2);
1056 stat = argse.expr;
1058 else if (flag_coarray == GFC_FCOARRAY_LIB)
1059 stat = null_pointer_node;
1061 if (code->expr4)
1063 gfc_init_se (&argse, NULL);
1064 gfc_conv_expr_val (&argse, code->expr4);
1065 until_count = fold_convert (integer_type_node, argse.expr);
1067 else
1068 until_count = integer_one_node;
1070 if (flag_coarray != GFC_FCOARRAY_LIB)
1072 gfc_start_block (&se.pre);
1073 gfc_init_se (&argse, NULL);
1074 gfc_conv_expr_val (&argse, code->expr1);
1076 if (op == EXEC_EVENT_POST)
1077 gfc_add_modify (&se.pre, argse.expr,
1078 fold_build2_loc (input_location, PLUS_EXPR,
1079 TREE_TYPE (argse.expr), argse.expr,
1080 build_int_cst (TREE_TYPE (argse.expr), 1)));
1081 else
1082 gfc_add_modify (&se.pre, argse.expr,
1083 fold_build2_loc (input_location, MINUS_EXPR,
1084 TREE_TYPE (argse.expr), argse.expr,
1085 fold_convert (TREE_TYPE (argse.expr),
1086 until_count)));
1087 if (stat != NULL_TREE)
1088 gfc_add_modify (&se.pre, stat, build_int_cst (TREE_TYPE (stat), 0));
1090 return gfc_finish_block (&se.pre);
1093 gfc_start_block (&se.pre);
1094 tree tmp, token, image_index, errmsg, errmsg_len;
1095 tree index = build_zero_cst (gfc_array_index_type);
1096 tree caf_decl = gfc_get_tree_for_caf_expr (code->expr1);
1098 if (code->expr1->symtree->n.sym->ts.type != BT_DERIVED
1099 || code->expr1->symtree->n.sym->ts.u.derived->from_intmod
1100 != INTMOD_ISO_FORTRAN_ENV
1101 || code->expr1->symtree->n.sym->ts.u.derived->intmod_sym_id
1102 != ISOFORTRAN_EVENT_TYPE)
1104 gfc_error ("Sorry, the event component of derived type at %L is not "
1105 "yet supported", &code->expr1->where);
1106 return NULL_TREE;
1109 gfc_init_se (&argse, NULL);
1110 gfc_get_caf_token_offset (&argse, &token, NULL, caf_decl, NULL_TREE,
1111 code->expr1);
1112 gfc_add_block_to_block (&se.pre, &argse.pre);
1114 if (gfc_is_coindexed (code->expr1))
1115 image_index = gfc_caf_get_image_index (&se.pre, code->expr1, caf_decl);
1116 else
1117 image_index = integer_zero_node;
1119 /* For arrays, obtain the array index. */
1120 if (gfc_expr_attr (code->expr1).dimension)
1122 tree desc, tmp, extent, lbound, ubound;
1123 gfc_array_ref *ar, ar2;
1124 int i;
1126 /* TODO: Extend this, once DT components are supported. */
1127 ar = &code->expr1->ref->u.ar;
1128 ar2 = *ar;
1129 memset (ar, '\0', sizeof (*ar));
1130 ar->as = ar2.as;
1131 ar->type = AR_FULL;
1133 gfc_init_se (&argse, NULL);
1134 argse.descriptor_only = 1;
1135 gfc_conv_expr_descriptor (&argse, code->expr1);
1136 gfc_add_block_to_block (&se.pre, &argse.pre);
1137 desc = argse.expr;
1138 *ar = ar2;
1140 extent = build_one_cst (gfc_array_index_type);
1141 for (i = 0; i < ar->dimen; i++)
1143 gfc_init_se (&argse, NULL);
1144 gfc_conv_expr_type (&argse, ar->start[i], gfc_array_index_type);
1145 gfc_add_block_to_block (&argse.pre, &argse.pre);
1146 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[i]);
1147 tmp = fold_build2_loc (input_location, MINUS_EXPR,
1148 TREE_TYPE (lbound), argse.expr, lbound);
1149 tmp = fold_build2_loc (input_location, MULT_EXPR,
1150 TREE_TYPE (tmp), extent, tmp);
1151 index = fold_build2_loc (input_location, PLUS_EXPR,
1152 TREE_TYPE (tmp), index, tmp);
1153 if (i < ar->dimen - 1)
1155 ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[i]);
1156 tmp = gfc_conv_array_extent_dim (lbound, ubound, NULL);
1157 extent = fold_build2_loc (input_location, MULT_EXPR,
1158 TREE_TYPE (tmp), extent, tmp);
1163 /* errmsg. */
1164 if (code->expr3)
1166 gfc_init_se (&argse, NULL);
1167 argse.want_pointer = 1;
1168 gfc_conv_expr (&argse, code->expr3);
1169 gfc_add_block_to_block (&se.pre, &argse.pre);
1170 errmsg = argse.expr;
1171 errmsg_len = fold_convert (size_type_node, argse.string_length);
1173 else
1175 errmsg = null_pointer_node;
1176 errmsg_len = build_zero_cst (size_type_node);
1179 if (stat != null_pointer_node && TREE_TYPE (stat) != integer_type_node)
1181 stat2 = stat;
1182 stat = gfc_create_var (integer_type_node, "stat");
1185 index = fold_convert (size_type_node, index);
1186 if (op == EXEC_EVENT_POST)
1187 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_event_post, 6,
1188 token, index, image_index,
1189 stat != null_pointer_node
1190 ? gfc_build_addr_expr (NULL, stat) : stat,
1191 errmsg, errmsg_len);
1192 else
1193 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_event_wait, 6,
1194 token, index, until_count,
1195 stat != null_pointer_node
1196 ? gfc_build_addr_expr (NULL, stat) : stat,
1197 errmsg, errmsg_len);
1198 gfc_add_expr_to_block (&se.pre, tmp);
1200 /* It guarantees memory consistency within the same segment */
1201 tmp = gfc_build_string_const (strlen ("memory")+1, "memory"),
1202 tmp = build5_loc (input_location, ASM_EXPR, void_type_node,
1203 gfc_build_string_const (1, ""), NULL_TREE, NULL_TREE,
1204 tree_cons (NULL_TREE, tmp, NULL_TREE), NULL_TREE);
1205 ASM_VOLATILE_P (tmp) = 1;
1206 gfc_add_expr_to_block (&se.pre, tmp);
1208 if (stat2 != NULL_TREE)
1209 gfc_add_modify (&se.pre, stat2, fold_convert (TREE_TYPE (stat2), stat));
1211 return gfc_finish_block (&se.pre);
1214 tree
1215 gfc_trans_sync (gfc_code *code, gfc_exec_op type)
1217 gfc_se se, argse;
1218 tree tmp;
1219 tree images = NULL_TREE, stat = NULL_TREE,
1220 errmsg = NULL_TREE, errmsglen = NULL_TREE;
1222 /* Short cut: For single images without bound checking or without STAT=,
1223 return early. (ERRMSG= is always untouched for -fcoarray=single.) */
1224 if (!code->expr2 && !(gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
1225 && flag_coarray != GFC_FCOARRAY_LIB)
1226 return NULL_TREE;
1228 gfc_init_se (&se, NULL);
1229 gfc_start_block (&se.pre);
1231 if (code->expr1 && code->expr1->rank == 0)
1233 gfc_init_se (&argse, NULL);
1234 gfc_conv_expr_val (&argse, code->expr1);
1235 images = argse.expr;
1238 if (code->expr2)
1240 gcc_assert (code->expr2->expr_type == EXPR_VARIABLE
1241 || code->expr2->expr_type == EXPR_FUNCTION);
1242 gfc_init_se (&argse, NULL);
1243 gfc_conv_expr_val (&argse, code->expr2);
1244 stat = argse.expr;
1246 else
1247 stat = null_pointer_node;
1249 if (code->expr3 && flag_coarray == GFC_FCOARRAY_LIB)
1251 gcc_assert (code->expr3->expr_type == EXPR_VARIABLE
1252 || code->expr3->expr_type == EXPR_FUNCTION);
1253 gfc_init_se (&argse, NULL);
1254 argse.want_pointer = 1;
1255 gfc_conv_expr (&argse, code->expr3);
1256 gfc_conv_string_parameter (&argse);
1257 errmsg = gfc_build_addr_expr (NULL, argse.expr);
1258 errmsglen = fold_convert (size_type_node, argse.string_length);
1260 else if (flag_coarray == GFC_FCOARRAY_LIB)
1262 errmsg = null_pointer_node;
1263 errmsglen = build_int_cst (size_type_node, 0);
1266 /* Check SYNC IMAGES(imageset) for valid image index.
1267 FIXME: Add a check for image-set arrays. */
1268 if (code->expr1 && (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
1269 && code->expr1->rank == 0)
1271 tree images2 = fold_convert (integer_type_node, images);
1272 tree cond;
1273 if (flag_coarray != GFC_FCOARRAY_LIB)
1274 cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
1275 images, build_int_cst (TREE_TYPE (images), 1));
1276 else
1278 tree cond2;
1279 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_num_images,
1280 2, integer_zero_node,
1281 build_int_cst (integer_type_node, -1));
1282 cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
1283 images2, tmp);
1284 cond2 = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
1285 images,
1286 build_int_cst (TREE_TYPE (images), 1));
1287 cond = fold_build2_loc (input_location, TRUTH_OR_EXPR,
1288 logical_type_node, cond, cond2);
1290 gfc_trans_runtime_check (true, false, cond, &se.pre,
1291 &code->expr1->where, "Invalid image number "
1292 "%d in SYNC IMAGES", images2);
1295 /* Per F2008, 8.5.1, a SYNC MEMORY is implied by calling the
1296 image control statements SYNC IMAGES and SYNC ALL. */
1297 if (flag_coarray == GFC_FCOARRAY_LIB)
1299 tmp = gfc_build_string_const (strlen ("memory")+1, "memory"),
1300 tmp = build5_loc (input_location, ASM_EXPR, void_type_node,
1301 gfc_build_string_const (1, ""), NULL_TREE, NULL_TREE,
1302 tree_cons (NULL_TREE, tmp, NULL_TREE), NULL_TREE);
1303 ASM_VOLATILE_P (tmp) = 1;
1304 gfc_add_expr_to_block (&se.pre, tmp);
1307 if (flag_coarray != GFC_FCOARRAY_LIB)
1309 /* Set STAT to zero. */
1310 if (code->expr2)
1311 gfc_add_modify (&se.pre, stat, build_int_cst (TREE_TYPE (stat), 0));
1313 else if (type == EXEC_SYNC_ALL || type == EXEC_SYNC_MEMORY)
1315 /* SYNC ALL => stat == null_pointer_node
1316 SYNC ALL(stat=s) => stat has an integer type
1318 If "stat" has the wrong integer type, use a temp variable of
1319 the right type and later cast the result back into "stat". */
1320 if (stat == null_pointer_node || TREE_TYPE (stat) == integer_type_node)
1322 if (TREE_TYPE (stat) == integer_type_node)
1323 stat = gfc_build_addr_expr (NULL, stat);
1325 if(type == EXEC_SYNC_MEMORY)
1326 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sync_memory,
1327 3, stat, errmsg, errmsglen);
1328 else
1329 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sync_all,
1330 3, stat, errmsg, errmsglen);
1332 gfc_add_expr_to_block (&se.pre, tmp);
1334 else
1336 tree tmp_stat = gfc_create_var (integer_type_node, "stat");
1338 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sync_all,
1339 3, gfc_build_addr_expr (NULL, tmp_stat),
1340 errmsg, errmsglen);
1341 gfc_add_expr_to_block (&se.pre, tmp);
1343 gfc_add_modify (&se.pre, stat,
1344 fold_convert (TREE_TYPE (stat), tmp_stat));
1347 else
1349 tree len;
1351 gcc_assert (type == EXEC_SYNC_IMAGES);
1353 if (!code->expr1)
1355 len = build_int_cst (integer_type_node, -1);
1356 images = null_pointer_node;
1358 else if (code->expr1->rank == 0)
1360 len = build_int_cst (integer_type_node, 1);
1361 images = gfc_build_addr_expr (NULL_TREE, images);
1363 else
1365 /* FIXME. */
1366 if (code->expr1->ts.kind != gfc_c_int_kind)
1367 gfc_fatal_error ("Sorry, only support for integer kind %d "
1368 "implemented for image-set at %L",
1369 gfc_c_int_kind, &code->expr1->where);
1371 gfc_conv_array_parameter (&se, code->expr1, true, NULL, NULL, &len);
1372 images = se.expr;
1374 tmp = gfc_typenode_for_spec (&code->expr1->ts);
1375 if (GFC_ARRAY_TYPE_P (tmp) || GFC_DESCRIPTOR_TYPE_P (tmp))
1376 tmp = gfc_get_element_type (tmp);
1378 len = fold_build2_loc (input_location, TRUNC_DIV_EXPR,
1379 TREE_TYPE (len), len,
1380 fold_convert (TREE_TYPE (len),
1381 TYPE_SIZE_UNIT (tmp)));
1382 len = fold_convert (integer_type_node, len);
1385 /* SYNC IMAGES(imgs) => stat == null_pointer_node
1386 SYNC IMAGES(imgs,stat=s) => stat has an integer type
1388 If "stat" has the wrong integer type, use a temp variable of
1389 the right type and later cast the result back into "stat". */
1390 if (stat == null_pointer_node || TREE_TYPE (stat) == integer_type_node)
1392 if (TREE_TYPE (stat) == integer_type_node)
1393 stat = gfc_build_addr_expr (NULL, stat);
1395 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sync_images,
1396 5, fold_convert (integer_type_node, len),
1397 images, stat, errmsg, errmsglen);
1398 gfc_add_expr_to_block (&se.pre, tmp);
1400 else
1402 tree tmp_stat = gfc_create_var (integer_type_node, "stat");
1404 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sync_images,
1405 5, fold_convert (integer_type_node, len),
1406 images, gfc_build_addr_expr (NULL, tmp_stat),
1407 errmsg, errmsglen);
1408 gfc_add_expr_to_block (&se.pre, tmp);
1410 gfc_add_modify (&se.pre, stat,
1411 fold_convert (TREE_TYPE (stat), tmp_stat));
1415 return gfc_finish_block (&se.pre);
1419 /* Generate GENERIC for the IF construct. This function also deals with
1420 the simple IF statement, because the front end translates the IF
1421 statement into an IF construct.
1423 We translate:
1425 IF (cond) THEN
1426 then_clause
1427 ELSEIF (cond2)
1428 elseif_clause
1429 ELSE
1430 else_clause
1431 ENDIF
1433 into:
1435 pre_cond_s;
1436 if (cond_s)
1438 then_clause;
1440 else
1442 pre_cond_s
1443 if (cond_s)
1445 elseif_clause
1447 else
1449 else_clause;
1453 where COND_S is the simplified version of the predicate. PRE_COND_S
1454 are the pre side-effects produced by the translation of the
1455 conditional.
1456 We need to build the chain recursively otherwise we run into
1457 problems with folding incomplete statements. */
1459 static tree
1460 gfc_trans_if_1 (gfc_code * code)
1462 gfc_se if_se;
1463 tree stmt, elsestmt;
1464 locus saved_loc;
1465 location_t loc;
1467 /* Check for an unconditional ELSE clause. */
1468 if (!code->expr1)
1469 return gfc_trans_code (code->next);
1471 /* Initialize a statement builder for each block. Puts in NULL_TREEs. */
1472 gfc_init_se (&if_se, NULL);
1473 gfc_start_block (&if_se.pre);
1475 /* Calculate the IF condition expression. */
1476 if (code->expr1->where.lb)
1478 gfc_save_backend_locus (&saved_loc);
1479 gfc_set_backend_locus (&code->expr1->where);
1482 gfc_conv_expr_val (&if_se, code->expr1);
1484 if (code->expr1->where.lb)
1485 gfc_restore_backend_locus (&saved_loc);
1487 /* Translate the THEN clause. */
1488 stmt = gfc_trans_code (code->next);
1490 /* Translate the ELSE clause. */
1491 if (code->block)
1492 elsestmt = gfc_trans_if_1 (code->block);
1493 else
1494 elsestmt = build_empty_stmt (input_location);
1496 /* Build the condition expression and add it to the condition block. */
1497 loc = code->expr1->where.lb ? gfc_get_location (&code->expr1->where)
1498 : input_location;
1499 stmt = fold_build3_loc (loc, COND_EXPR, void_type_node, if_se.expr, stmt,
1500 elsestmt);
1502 gfc_add_expr_to_block (&if_se.pre, stmt);
1504 /* Finish off this statement. */
1505 return gfc_finish_block (&if_se.pre);
1508 tree
1509 gfc_trans_if (gfc_code * code)
1511 stmtblock_t body;
1512 tree exit_label;
1514 /* Create exit label so it is available for trans'ing the body code. */
1515 exit_label = gfc_build_label_decl (NULL_TREE);
1516 code->exit_label = exit_label;
1518 /* Translate the actual code in code->block. */
1519 gfc_init_block (&body);
1520 gfc_add_expr_to_block (&body, gfc_trans_if_1 (code->block));
1522 /* Add exit label. */
1523 gfc_add_expr_to_block (&body, build1_v (LABEL_EXPR, exit_label));
1525 return gfc_finish_block (&body);
1529 /* Translate an arithmetic IF expression.
1531 IF (cond) label1, label2, label3 translates to
1533 if (cond <= 0)
1535 if (cond < 0)
1536 goto label1;
1537 else // cond == 0
1538 goto label2;
1540 else // cond > 0
1541 goto label3;
1543 An optimized version can be generated in case of equal labels.
1544 E.g., if label1 is equal to label2, we can translate it to
1546 if (cond <= 0)
1547 goto label1;
1548 else
1549 goto label3;
1552 tree
1553 gfc_trans_arithmetic_if (gfc_code * code)
1555 gfc_se se;
1556 tree tmp;
1557 tree branch1;
1558 tree branch2;
1559 tree zero;
1561 /* Start a new block. */
1562 gfc_init_se (&se, NULL);
1563 gfc_start_block (&se.pre);
1565 /* Pre-evaluate COND. */
1566 gfc_conv_expr_val (&se, code->expr1);
1567 se.expr = gfc_evaluate_now (se.expr, &se.pre);
1569 /* Build something to compare with. */
1570 zero = gfc_build_const (TREE_TYPE (se.expr), integer_zero_node);
1572 if (code->label1->value != code->label2->value)
1574 /* If (cond < 0) take branch1 else take branch2.
1575 First build jumps to the COND .LT. 0 and the COND .EQ. 0 cases. */
1576 branch1 = build1_v (GOTO_EXPR, gfc_get_label_decl (code->label1));
1577 branch2 = build1_v (GOTO_EXPR, gfc_get_label_decl (code->label2));
1579 if (code->label1->value != code->label3->value)
1580 tmp = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
1581 se.expr, zero);
1582 else
1583 tmp = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
1584 se.expr, zero);
1586 branch1 = fold_build3_loc (input_location, COND_EXPR, void_type_node,
1587 tmp, branch1, branch2);
1589 else
1590 branch1 = build1_v (GOTO_EXPR, gfc_get_label_decl (code->label1));
1592 if (code->label1->value != code->label3->value
1593 && code->label2->value != code->label3->value)
1595 /* if (cond <= 0) take branch1 else take branch2. */
1596 branch2 = build1_v (GOTO_EXPR, gfc_get_label_decl (code->label3));
1597 tmp = fold_build2_loc (input_location, LE_EXPR, logical_type_node,
1598 se.expr, zero);
1599 branch1 = fold_build3_loc (input_location, COND_EXPR, void_type_node,
1600 tmp, branch1, branch2);
1603 /* Append the COND_EXPR to the evaluation of COND, and return. */
1604 gfc_add_expr_to_block (&se.pre, branch1);
1605 return gfc_finish_block (&se.pre);
1609 /* Translate a CRITICAL block. */
1610 tree
1611 gfc_trans_critical (gfc_code *code)
1613 stmtblock_t block;
1614 tree tmp, token = NULL_TREE;
1616 gfc_start_block (&block);
1618 if (flag_coarray == GFC_FCOARRAY_LIB)
1620 tree zero_size = build_zero_cst (size_type_node);
1621 token = gfc_get_symbol_decl (code->resolved_sym);
1622 token = GFC_TYPE_ARRAY_CAF_TOKEN (TREE_TYPE (token));
1623 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_lock, 7,
1624 token, zero_size, integer_one_node,
1625 null_pointer_node, null_pointer_node,
1626 null_pointer_node, zero_size);
1627 gfc_add_expr_to_block (&block, tmp);
1629 /* It guarantees memory consistency within the same segment */
1630 tmp = gfc_build_string_const (strlen ("memory")+1, "memory"),
1631 tmp = build5_loc (input_location, ASM_EXPR, void_type_node,
1632 gfc_build_string_const (1, ""),
1633 NULL_TREE, NULL_TREE,
1634 tree_cons (NULL_TREE, tmp, NULL_TREE),
1635 NULL_TREE);
1636 ASM_VOLATILE_P (tmp) = 1;
1638 gfc_add_expr_to_block (&block, tmp);
1641 tmp = gfc_trans_code (code->block->next);
1642 gfc_add_expr_to_block (&block, tmp);
1644 if (flag_coarray == GFC_FCOARRAY_LIB)
1646 tree zero_size = build_zero_cst (size_type_node);
1647 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_unlock, 6,
1648 token, zero_size, integer_one_node,
1649 null_pointer_node, null_pointer_node,
1650 zero_size);
1651 gfc_add_expr_to_block (&block, tmp);
1653 /* It guarantees memory consistency within the same segment */
1654 tmp = gfc_build_string_const (strlen ("memory")+1, "memory"),
1655 tmp = build5_loc (input_location, ASM_EXPR, void_type_node,
1656 gfc_build_string_const (1, ""),
1657 NULL_TREE, NULL_TREE,
1658 tree_cons (NULL_TREE, tmp, NULL_TREE),
1659 NULL_TREE);
1660 ASM_VOLATILE_P (tmp) = 1;
1662 gfc_add_expr_to_block (&block, tmp);
1665 return gfc_finish_block (&block);
1669 /* Return true, when the class has a _len component. */
1671 static bool
1672 class_has_len_component (gfc_symbol *sym)
1674 gfc_component *comp = sym->ts.u.derived->components;
1675 while (comp)
1677 if (strcmp (comp->name, "_len") == 0)
1678 return true;
1679 comp = comp->next;
1681 return false;
1685 static void
1686 copy_descriptor (stmtblock_t *block, tree dst, tree src, int rank)
1688 int n;
1689 tree dim;
1690 tree tmp;
1691 tree tmp2;
1692 tree size;
1693 tree offset;
1695 offset = gfc_index_zero_node;
1697 /* Use memcpy to copy the descriptor. The size is the minimum of
1698 the sizes of 'src' and 'dst'. This avoids a non-trivial conversion. */
1699 tmp = TYPE_SIZE_UNIT (TREE_TYPE (src));
1700 tmp2 = TYPE_SIZE_UNIT (TREE_TYPE (dst));
1701 size = fold_build2_loc (input_location, MIN_EXPR,
1702 TREE_TYPE (tmp), tmp, tmp2);
1703 tmp = builtin_decl_explicit (BUILT_IN_MEMCPY);
1704 tmp = build_call_expr_loc (input_location, tmp, 3,
1705 gfc_build_addr_expr (NULL_TREE, dst),
1706 gfc_build_addr_expr (NULL_TREE, src),
1707 fold_convert (size_type_node, size));
1708 gfc_add_expr_to_block (block, tmp);
1710 /* Set the offset correctly. */
1711 for (n = 0; n < rank; n++)
1713 dim = gfc_rank_cst[n];
1714 tmp = gfc_conv_descriptor_lbound_get (src, dim);
1715 tmp2 = gfc_conv_descriptor_stride_get (src, dim);
1716 tmp = fold_build2_loc (input_location, MULT_EXPR, TREE_TYPE (tmp),
1717 tmp, tmp2);
1718 offset = fold_build2_loc (input_location, MINUS_EXPR,
1719 TREE_TYPE (offset), offset, tmp);
1720 offset = gfc_evaluate_now (offset, block);
1723 gfc_conv_descriptor_offset_set (block, dst, offset);
1727 /* Do proper initialization for ASSOCIATE names. */
1729 static void
1730 trans_associate_var (gfc_symbol *sym, gfc_wrapped_block *block)
1732 gfc_expr *e;
1733 tree tmp;
1734 bool class_target;
1735 bool unlimited;
1736 tree desc;
1737 tree offset;
1738 tree dim;
1739 int n;
1740 tree charlen;
1741 bool need_len_assign;
1742 bool whole_array = true;
1743 gfc_ref *ref;
1744 gfc_symbol *sym2;
1746 gcc_assert (sym->assoc);
1747 e = sym->assoc->target;
1749 class_target = (e->expr_type == EXPR_VARIABLE)
1750 && e->ts.type == BT_CLASS
1751 && (gfc_is_class_scalar_expr (e)
1752 || gfc_is_class_array_ref (e, NULL));
1754 unlimited = UNLIMITED_POLY (e);
1756 for (ref = e->ref; ref; ref = ref->next)
1757 if (ref->type == REF_ARRAY
1758 && ref->u.ar.type == AR_FULL
1759 && ref->next)
1761 whole_array = false;
1762 break;
1765 /* Assignments to the string length need to be generated, when
1766 ( sym is a char array or
1767 sym has a _len component)
1768 and the associated expression is unlimited polymorphic, which is
1769 not (yet) correctly in 'unlimited', because for an already associated
1770 BT_DERIVED the u-poly flag is not set, i.e.,
1771 __tmp_CHARACTER_0_1 => w => arg
1772 ^ generated temp ^ from code, the w does not have the u-poly
1773 flag set, where UNLIMITED_POLY(e) expects it. */
1774 need_len_assign = ((unlimited || (e->ts.type == BT_DERIVED
1775 && e->ts.u.derived->attr.unlimited_polymorphic))
1776 && (sym->ts.type == BT_CHARACTER
1777 || ((sym->ts.type == BT_CLASS || sym->ts.type == BT_DERIVED)
1778 && class_has_len_component (sym)))
1779 && !sym->attr.select_rank_temporary);
1781 /* Do a `pointer assignment' with updated descriptor (or assign descriptor
1782 to array temporary) for arrays with either unknown shape or if associating
1783 to a variable. Select rank temporaries need somewhat different treatment
1784 to other associate names and case temporaries. This because the selector
1785 is assumed rank and so the offset in particular has to be changed. Also,
1786 the case temporaries carry both allocatable and target attributes if
1787 present in the selector. This means that an allocatation or change of
1788 association can occur and so has to be dealt with. */
1789 if (sym->attr.select_rank_temporary)
1791 gfc_se se;
1792 tree class_decl = NULL_TREE;
1793 int rank = 0;
1794 bool class_ptr;
1796 sym2 = e->symtree->n.sym;
1797 gfc_init_se (&se, NULL);
1798 if (e->ts.type == BT_CLASS)
1800 /* Go straight to the class data. */
1801 if (sym2->attr.dummy && !sym2->attr.optional)
1803 class_decl = sym2->backend_decl;
1804 if (DECL_LANG_SPECIFIC (class_decl)
1805 && GFC_DECL_SAVED_DESCRIPTOR (class_decl))
1806 class_decl = GFC_DECL_SAVED_DESCRIPTOR (class_decl);
1807 if (POINTER_TYPE_P (TREE_TYPE (class_decl)))
1808 class_decl = build_fold_indirect_ref_loc (input_location,
1809 class_decl);
1810 gcc_assert (GFC_CLASS_TYPE_P (TREE_TYPE (class_decl)));
1811 se.expr = gfc_class_data_get (class_decl);
1813 else
1815 class_decl = sym2->backend_decl;
1816 gfc_conv_expr_descriptor (&se, e);
1817 if (POINTER_TYPE_P (TREE_TYPE (se.expr)))
1818 se.expr = build_fold_indirect_ref_loc (input_location,
1819 se.expr);
1822 if (CLASS_DATA (sym)->as && CLASS_DATA (sym)->as->rank > 0)
1823 rank = CLASS_DATA (sym)->as->rank;
1825 else
1827 gfc_conv_expr_descriptor (&se, e);
1828 if (sym->as && sym->as->rank > 0)
1829 rank = sym->as->rank;
1832 desc = sym->backend_decl;
1834 /* The SELECT TYPE mechanisms turn class temporaries into pointers, which
1835 point to the selector. */
1836 class_ptr = class_decl != NULL_TREE && POINTER_TYPE_P (TREE_TYPE (desc));
1837 if (class_ptr)
1839 tmp = gfc_create_var (TREE_TYPE (TREE_TYPE (desc)), "class");
1840 tmp = gfc_build_addr_expr (NULL, tmp);
1841 gfc_add_modify (&se.pre, desc, tmp);
1843 tmp = gfc_class_vptr_get (class_decl);
1844 gfc_add_modify (&se.pre, gfc_class_vptr_get (desc), tmp);
1845 if (UNLIMITED_POLY (sym))
1846 gfc_add_modify (&se.pre, gfc_class_len_get (desc),
1847 gfc_class_len_get (class_decl));
1849 desc = gfc_class_data_get (desc);
1852 /* SELECT RANK temporaries can carry the allocatable and pointer
1853 attributes so the selector descriptor must be copied in and
1854 copied out. */
1855 if (rank > 0)
1856 copy_descriptor (&se.pre, desc, se.expr, rank);
1857 else
1859 tmp = gfc_conv_descriptor_data_get (se.expr);
1860 gfc_add_modify (&se.pre, desc,
1861 fold_convert (TREE_TYPE (desc), tmp));
1864 /* Deal with associate_name => selector. Class associate names are
1865 treated in the same way as in SELECT TYPE. */
1866 sym2 = sym->assoc->target->symtree->n.sym;
1867 if (sym2->assoc && sym->assoc->target && sym2->ts.type != BT_CLASS)
1869 sym2 = sym2->assoc->target->symtree->n.sym;
1870 se.expr = sym2->backend_decl;
1872 if (POINTER_TYPE_P (TREE_TYPE (se.expr)))
1873 se.expr = build_fold_indirect_ref_loc (input_location,
1874 se.expr);
1877 /* There could have been reallocation. Copy descriptor back to the
1878 selector and update the offset. */
1879 if (sym->attr.allocatable || sym->attr.pointer
1880 || (sym->ts.type == BT_CLASS
1881 && (CLASS_DATA (sym)->attr.allocatable
1882 || CLASS_DATA (sym)->attr.pointer)))
1884 if (rank > 0)
1885 copy_descriptor (&se.post, se.expr, desc, rank);
1886 else
1887 gfc_conv_descriptor_data_set (&se.post, se.expr, desc);
1889 /* The dynamic type could have changed too. */
1890 if (sym->ts.type == BT_CLASS)
1892 tmp = sym->backend_decl;
1893 if (class_ptr)
1894 tmp = build_fold_indirect_ref_loc (input_location, tmp);
1895 gfc_add_modify (&se.post, gfc_class_vptr_get (class_decl),
1896 gfc_class_vptr_get (tmp));
1897 if (UNLIMITED_POLY (sym))
1898 gfc_add_modify (&se.post, gfc_class_len_get (class_decl),
1899 gfc_class_len_get (tmp));
1903 tmp = gfc_finish_block (&se.post);
1905 gfc_add_init_cleanup (block, gfc_finish_block (&se.pre), tmp);
1907 /* Now all the other kinds of associate variable. */
1908 else if (sym->attr.dimension && !class_target
1909 && (sym->as->type == AS_DEFERRED || sym->assoc->variable))
1911 gfc_se se;
1912 tree desc;
1913 bool cst_array_ctor;
1915 desc = sym->backend_decl;
1916 cst_array_ctor = e->expr_type == EXPR_ARRAY
1917 && gfc_constant_array_constructor_p (e->value.constructor)
1918 && e->ts.type != BT_CHARACTER;
1920 /* If association is to an expression, evaluate it and create temporary.
1921 Otherwise, get descriptor of target for pointer assignment. */
1922 gfc_init_se (&se, NULL);
1924 if (sym->assoc->variable || cst_array_ctor)
1926 se.direct_byref = 1;
1927 se.use_offset = 1;
1928 se.expr = desc;
1929 GFC_DECL_PTR_ARRAY_P (sym->backend_decl) = 1;
1932 gfc_conv_expr_descriptor (&se, e);
1934 if (sym->ts.type == BT_CHARACTER
1935 && !sym->attr.select_type_temporary
1936 && sym->ts.u.cl->backend_decl
1937 && VAR_P (sym->ts.u.cl->backend_decl)
1938 && se.string_length != sym->ts.u.cl->backend_decl)
1939 gfc_add_modify (&se.pre, sym->ts.u.cl->backend_decl,
1940 fold_convert (TREE_TYPE (sym->ts.u.cl->backend_decl),
1941 se.string_length));
1943 /* If we didn't already do the pointer assignment, set associate-name
1944 descriptor to the one generated for the temporary. */
1945 if ((!sym->assoc->variable && !cst_array_ctor)
1946 || !whole_array)
1948 int dim;
1950 if (whole_array)
1951 gfc_add_modify (&se.pre, desc, se.expr);
1953 /* The generated descriptor has lower bound zero (as array
1954 temporary), shift bounds so we get lower bounds of 1. */
1955 for (dim = 0; dim < e->rank; ++dim)
1956 gfc_conv_shift_descriptor_lbound (&se.pre, desc,
1957 dim, gfc_index_one_node);
1960 /* If this is a subreference array pointer associate name use the
1961 associate variable element size for the value of 'span'. */
1962 if (sym->attr.subref_array_pointer && !se.direct_byref)
1964 gcc_assert (e->expr_type == EXPR_VARIABLE);
1965 tmp = gfc_get_array_span (se.expr, e);
1967 gfc_conv_descriptor_span_set (&se.pre, desc, tmp);
1970 if (e->expr_type == EXPR_FUNCTION
1971 && sym->ts.type == BT_DERIVED
1972 && sym->ts.u.derived
1973 && sym->ts.u.derived->attr.pdt_type)
1975 tmp = gfc_deallocate_pdt_comp (sym->ts.u.derived, se.expr,
1976 sym->as->rank);
1977 gfc_add_expr_to_block (&se.post, tmp);
1980 /* Done, register stuff as init / cleanup code. */
1981 gfc_add_init_cleanup (block, gfc_finish_block (&se.pre),
1982 gfc_finish_block (&se.post));
1985 /* Temporaries, arising from TYPE IS, just need the descriptor of class
1986 arrays to be assigned directly. */
1987 else if (class_target && sym->attr.dimension
1988 && (sym->ts.type == BT_DERIVED || unlimited))
1990 gfc_se se;
1992 gfc_init_se (&se, NULL);
1993 se.descriptor_only = 1;
1994 /* In a select type the (temporary) associate variable shall point to
1995 a standard fortran array (lower bound == 1), but conv_expr ()
1996 just maps to the input array in the class object, whose lbound may
1997 be arbitrary. conv_expr_descriptor solves this by inserting a
1998 temporary array descriptor. */
1999 gfc_conv_expr_descriptor (&se, e);
2001 gcc_assert (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (se.expr))
2002 || GFC_ARRAY_TYPE_P (TREE_TYPE (se.expr)));
2003 gcc_assert (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (sym->backend_decl)));
2005 if (GFC_ARRAY_TYPE_P (TREE_TYPE (se.expr)))
2007 if (INDIRECT_REF_P (se.expr))
2008 tmp = TREE_OPERAND (se.expr, 0);
2009 else
2010 tmp = se.expr;
2012 gfc_add_modify (&se.pre, sym->backend_decl,
2013 gfc_class_data_get (GFC_DECL_SAVED_DESCRIPTOR (tmp)));
2015 else
2016 gfc_add_modify (&se.pre, sym->backend_decl, se.expr);
2018 if (unlimited)
2020 /* Recover the dtype, which has been overwritten by the
2021 assignment from an unlimited polymorphic object. */
2022 tmp = gfc_conv_descriptor_dtype (sym->backend_decl);
2023 gfc_add_modify (&se.pre, tmp,
2024 gfc_get_dtype (TREE_TYPE (sym->backend_decl)));
2027 gfc_add_init_cleanup (block, gfc_finish_block (&se.pre),
2028 gfc_finish_block (&se.post));
2031 /* Do a scalar pointer assignment; this is for scalar variable targets. */
2032 else if (gfc_is_associate_pointer (sym))
2034 gfc_se se;
2036 gcc_assert (!sym->attr.dimension);
2038 gfc_init_se (&se, NULL);
2040 /* Class associate-names come this way because they are
2041 unconditionally associate pointers and the symbol is scalar. */
2042 if (sym->ts.type == BT_CLASS && e->expr_type == EXPR_FUNCTION)
2044 gfc_conv_expr (&se, e);
2045 se.expr = gfc_evaluate_now (se.expr, &se.pre);
2047 else if (sym->ts.type == BT_CLASS && CLASS_DATA (sym)->attr.dimension)
2049 tree target_expr;
2050 /* For a class array we need a descriptor for the selector. */
2051 gfc_conv_expr_descriptor (&se, e);
2052 /* Needed to get/set the _len component below. */
2053 target_expr = se.expr;
2055 /* Obtain a temporary class container for the result. */
2056 gfc_conv_class_to_class (&se, e, sym->ts, false, true, false, false);
2057 se.expr = build_fold_indirect_ref_loc (input_location, se.expr);
2059 /* Set the offset. */
2060 desc = gfc_class_data_get (se.expr);
2061 offset = gfc_index_zero_node;
2062 for (n = 0; n < e->rank; n++)
2064 dim = gfc_rank_cst[n];
2065 tmp = fold_build2_loc (input_location, MULT_EXPR,
2066 gfc_array_index_type,
2067 gfc_conv_descriptor_stride_get (desc, dim),
2068 gfc_conv_descriptor_lbound_get (desc, dim));
2069 offset = fold_build2_loc (input_location, MINUS_EXPR,
2070 gfc_array_index_type,
2071 offset, tmp);
2073 if (need_len_assign)
2075 if (e->symtree
2076 && DECL_LANG_SPECIFIC (e->symtree->n.sym->backend_decl)
2077 && GFC_DECL_SAVED_DESCRIPTOR (e->symtree->n.sym->backend_decl)
2078 && TREE_CODE (target_expr) != COMPONENT_REF)
2079 /* Use the original class descriptor stored in the saved
2080 descriptor to get the target_expr. */
2081 target_expr =
2082 GFC_DECL_SAVED_DESCRIPTOR (e->symtree->n.sym->backend_decl);
2083 else
2084 /* Strip the _data component from the target_expr. */
2085 target_expr = TREE_OPERAND (target_expr, 0);
2086 /* Add a reference to the _len comp to the target expr. */
2087 tmp = gfc_class_len_get (target_expr);
2088 /* Get the component-ref for the temp structure's _len comp. */
2089 charlen = gfc_class_len_get (se.expr);
2090 /* Add the assign to the beginning of the block... */
2091 gfc_add_modify (&se.pre, charlen,
2092 fold_convert (TREE_TYPE (charlen), tmp));
2093 /* and the oposite way at the end of the block, to hand changes
2094 on the string length back. */
2095 gfc_add_modify (&se.post, tmp,
2096 fold_convert (TREE_TYPE (tmp), charlen));
2097 /* Length assignment done, prevent adding it again below. */
2098 need_len_assign = false;
2100 gfc_conv_descriptor_offset_set (&se.pre, desc, offset);
2102 else if (sym->ts.type == BT_CLASS && e->ts.type == BT_CLASS
2103 && CLASS_DATA (e)->attr.dimension)
2105 /* This is bound to be a class array element. */
2106 gfc_conv_expr_reference (&se, e);
2107 /* Get the _vptr component of the class object. */
2108 tmp = gfc_get_vptr_from_expr (se.expr);
2109 /* Obtain a temporary class container for the result. */
2110 gfc_conv_derived_to_class (&se, e, sym->ts, tmp, false, false);
2111 se.expr = build_fold_indirect_ref_loc (input_location, se.expr);
2112 need_len_assign = false;
2114 else
2116 /* For BT_CLASS and BT_DERIVED, this boils down to a pointer assign,
2117 which has the string length included. For CHARACTERS it is still
2118 needed and will be done at the end of this routine. */
2119 gfc_conv_expr (&se, e);
2120 need_len_assign = need_len_assign && sym->ts.type == BT_CHARACTER;
2123 if (sym->ts.type == BT_CHARACTER
2124 && !sym->attr.select_type_temporary
2125 && VAR_P (sym->ts.u.cl->backend_decl)
2126 && se.string_length != sym->ts.u.cl->backend_decl)
2128 gfc_add_modify (&se.pre, sym->ts.u.cl->backend_decl,
2129 fold_convert (TREE_TYPE (sym->ts.u.cl->backend_decl),
2130 se.string_length));
2131 if (e->expr_type == EXPR_FUNCTION)
2133 tmp = gfc_call_free (sym->backend_decl);
2134 gfc_add_expr_to_block (&se.post, tmp);
2138 if (sym->ts.type == BT_CHARACTER && e->ts.type == BT_CHARACTER
2139 && POINTER_TYPE_P (TREE_TYPE (se.expr)))
2141 /* These are pointer types already. */
2142 tmp = fold_convert (TREE_TYPE (sym->backend_decl), se.expr);
2144 else
2146 tree ctree = gfc_get_class_from_expr (se.expr);
2147 tmp = TREE_TYPE (sym->backend_decl);
2149 /* F2018:19.5.1.6 "If a selector has the POINTER attribute,
2150 it shall be associated; the associate name is associated
2151 with the target of the pointer and does not have the
2152 POINTER attribute." */
2153 if (sym->ts.type == BT_CLASS
2154 && e->ts.type == BT_CLASS && e->rank == 0 && ctree
2155 && (!GFC_CLASS_TYPE_P (TREE_TYPE (se.expr))
2156 || CLASS_DATA (e)->attr.class_pointer))
2158 tree stmp;
2159 tree dtmp;
2161 se.expr = ctree;
2162 dtmp = TREE_TYPE (TREE_TYPE (sym->backend_decl));
2163 ctree = gfc_create_var (dtmp, "class");
2165 stmp = gfc_class_data_get (se.expr);
2166 /* Coarray scalar component expressions can emerge from
2167 the front end as array elements of the _data field. */
2168 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (stmp)))
2169 stmp = gfc_conv_descriptor_data_get (stmp);
2170 dtmp = gfc_class_data_get (ctree);
2171 stmp = fold_convert (TREE_TYPE (dtmp), stmp);
2172 gfc_add_modify (&se.pre, dtmp, stmp);
2173 stmp = gfc_class_vptr_get (se.expr);
2174 dtmp = gfc_class_vptr_get (ctree);
2175 stmp = fold_convert (TREE_TYPE (dtmp), stmp);
2176 gfc_add_modify (&se.pre, dtmp, stmp);
2177 if (UNLIMITED_POLY (sym))
2179 stmp = gfc_class_len_get (se.expr);
2180 dtmp = gfc_class_len_get (ctree);
2181 stmp = fold_convert (TREE_TYPE (dtmp), stmp);
2182 gfc_add_modify (&se.pre, dtmp, stmp);
2183 need_len_assign = false;
2185 se.expr = ctree;
2187 tmp = gfc_build_addr_expr (tmp, se.expr);
2190 gfc_add_modify (&se.pre, sym->backend_decl, tmp);
2192 gfc_add_init_cleanup (block, gfc_finish_block( &se.pre),
2193 gfc_finish_block (&se.post));
2196 /* Do a simple assignment. This is for scalar expressions, where we
2197 can simply use expression assignment. */
2198 else
2200 gfc_expr *lhs;
2201 tree res;
2202 gfc_se se;
2203 stmtblock_t final_block;
2205 gfc_init_se (&se, NULL);
2207 /* resolve.cc converts some associate names to allocatable so that
2208 allocation can take place automatically in gfc_trans_assignment.
2209 The frontend prevents them from being either allocated,
2210 deallocated or reallocated. */
2211 if (sym->ts.type == BT_DERIVED
2212 && sym->ts.u.derived->attr.alloc_comp)
2214 tmp = sym->backend_decl;
2215 tmp = gfc_nullify_alloc_comp (sym->ts.u.derived, tmp,
2216 sym->attr.dimension ? sym->as->rank : 0);
2217 gfc_add_expr_to_block (&se.pre, tmp);
2220 if (sym->attr.allocatable)
2222 tmp = sym->backend_decl;
2223 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (tmp)))
2224 tmp = gfc_conv_descriptor_data_get (tmp);
2225 gfc_add_modify (&se.pre, tmp, fold_convert (TREE_TYPE (tmp),
2226 null_pointer_node));
2229 lhs = gfc_lval_expr_from_sym (sym);
2230 lhs->must_finalize = 0;
2231 res = gfc_trans_assignment (lhs, e, false, true);
2232 gfc_add_expr_to_block (&se.pre, res);
2234 gfc_init_block (&final_block);
2236 if (sym->attr.associate_var
2237 && sym->ts.type == BT_DERIVED
2238 && sym->ts.u.derived->attr.defined_assign_comp
2239 && gfc_may_be_finalized (sym->ts)
2240 && e->expr_type == EXPR_FUNCTION)
2242 gfc_expr *ef;
2243 ef = gfc_lval_expr_from_sym (sym);
2244 gfc_add_finalizer_call (&final_block, ef);
2245 gfc_free_expr (ef);
2248 if (sym->ts.type == BT_DERIVED
2249 && sym->ts.u.derived->attr.alloc_comp)
2251 tmp = sym->backend_decl;
2252 tmp = gfc_deallocate_alloc_comp (sym->ts.u.derived,
2253 tmp, 0);
2254 gfc_add_expr_to_block (&final_block, tmp);
2257 tmp = sym->backend_decl;
2258 if (e->expr_type == EXPR_FUNCTION
2259 && sym->ts.type == BT_DERIVED
2260 && sym->ts.u.derived
2261 && sym->ts.u.derived->attr.pdt_type)
2263 tmp = gfc_deallocate_pdt_comp (sym->ts.u.derived, tmp,
2266 else if (e->expr_type == EXPR_FUNCTION
2267 && sym->ts.type == BT_CLASS
2268 && CLASS_DATA (sym)->ts.u.derived
2269 && CLASS_DATA (sym)->ts.u.derived->attr.pdt_type)
2271 tmp = gfc_class_data_get (tmp);
2272 tmp = gfc_deallocate_pdt_comp (CLASS_DATA (sym)->ts.u.derived,
2273 tmp, 0);
2275 else if (sym->attr.allocatable)
2277 tmp = sym->backend_decl;
2279 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (tmp)))
2280 tmp = gfc_conv_descriptor_data_get (tmp);
2282 /* A simple call to free suffices here. */
2283 tmp = gfc_call_free (tmp);
2285 /* Make sure that reallocation on assignment cannot occur. */
2286 sym->attr.allocatable = 0;
2288 else
2289 tmp = NULL_TREE;
2291 gfc_add_expr_to_block (&final_block, tmp);
2292 tmp = gfc_finish_block (&final_block);
2293 res = gfc_finish_block (&se.pre);
2294 gfc_add_init_cleanup (block, res, tmp);
2295 gfc_free_expr (lhs);
2298 /* Set the stringlength, when needed. */
2299 if (need_len_assign)
2301 gfc_se se;
2302 gfc_init_se (&se, NULL);
2303 if (e->symtree->n.sym->ts.type == BT_CHARACTER)
2305 /* Deferred strings are dealt with in the preceding. */
2306 gcc_assert (!e->symtree->n.sym->ts.deferred);
2307 tmp = e->symtree->n.sym->ts.u.cl->backend_decl;
2309 else if (e->symtree->n.sym->attr.function
2310 && e->symtree->n.sym == e->symtree->n.sym->result)
2312 tmp = gfc_get_fake_result_decl (e->symtree->n.sym, 0);
2313 tmp = gfc_class_len_get (tmp);
2315 else
2316 tmp = gfc_class_len_get (gfc_get_symbol_decl (e->symtree->n.sym));
2317 gfc_get_symbol_decl (sym);
2318 charlen = sym->ts.type == BT_CHARACTER ? sym->ts.u.cl->backend_decl
2319 : gfc_class_len_get (sym->backend_decl);
2320 /* Prevent adding a noop len= len. */
2321 if (tmp != charlen)
2323 gfc_add_modify (&se.pre, charlen,
2324 fold_convert (TREE_TYPE (charlen), tmp));
2325 gfc_add_init_cleanup (block, gfc_finish_block (&se.pre),
2326 gfc_finish_block (&se.post));
2332 /* Translate a BLOCK construct. This is basically what we would do for a
2333 procedure body. */
2335 tree
2336 gfc_trans_block_construct (gfc_code* code)
2338 gfc_namespace* ns;
2339 gfc_symbol* sym;
2340 gfc_wrapped_block block;
2341 tree exit_label;
2342 stmtblock_t body;
2343 gfc_association_list *ass;
2344 tree translated_body;
2346 ns = code->ext.block.ns;
2347 gcc_assert (ns);
2348 sym = ns->proc_name;
2349 gcc_assert (sym);
2351 /* Process local variables. */
2352 gcc_assert (!sym->tlink);
2353 sym->tlink = sym;
2354 gfc_process_block_locals (ns);
2356 /* Generate code including exit-label. */
2357 gfc_init_block (&body);
2358 exit_label = gfc_build_label_decl (NULL_TREE);
2359 code->exit_label = exit_label;
2361 finish_oacc_declare (ns, sym, true);
2363 translated_body = gfc_trans_code (ns->code);
2364 if (ns->omp_structured_block)
2365 translated_body = build1 (OMP_STRUCTURED_BLOCK, void_type_node,
2366 translated_body);
2367 gfc_add_expr_to_block (&body, translated_body);
2368 gfc_add_expr_to_block (&body, build1_v (LABEL_EXPR, exit_label));
2370 /* Finish everything. */
2371 gfc_start_wrapped_block (&block, gfc_finish_block (&body));
2372 gfc_trans_deferred_vars (sym, &block);
2373 for (ass = code->ext.block.assoc; ass; ass = ass->next)
2374 trans_associate_var (ass->st->n.sym, &block);
2376 return gfc_finish_wrapped_block (&block);
2379 /* Translate the simple DO construct in a C-style manner.
2380 This is where the loop variable has integer type and step +-1.
2381 Following code will generate infinite loop in case where TO is INT_MAX
2382 (for +1 step) or INT_MIN (for -1 step)
2384 We translate a do loop from:
2386 DO dovar = from, to, step
2387 body
2388 END DO
2392 [Evaluate loop bounds and step]
2393 dovar = from;
2394 for (;;)
2396 if (dovar > to)
2397 goto end_label;
2398 body;
2399 cycle_label:
2400 dovar += step;
2402 end_label:
2404 This helps the optimizers by avoiding the extra pre-header condition and
2405 we save a register as we just compare the updated IV (not a value in
2406 previous step). */
2408 static tree
2409 gfc_trans_simple_do (gfc_code * code, stmtblock_t *pblock, tree dovar,
2410 tree from, tree to, tree step, tree exit_cond)
2412 stmtblock_t body;
2413 tree type;
2414 tree cond;
2415 tree tmp;
2416 tree saved_dovar = NULL;
2417 tree cycle_label;
2418 tree exit_label;
2419 location_t loc;
2420 type = TREE_TYPE (dovar);
2421 bool is_step_positive = tree_int_cst_sgn (step) > 0;
2423 loc = gfc_get_location (&code->ext.iterator->start->where);
2425 /* Initialize the DO variable: dovar = from. */
2426 gfc_add_modify_loc (loc, pblock, dovar,
2427 fold_convert (TREE_TYPE (dovar), from));
2429 /* Save value for do-tinkering checking. */
2430 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
2432 saved_dovar = gfc_create_var (type, ".saved_dovar");
2433 gfc_add_modify_loc (loc, pblock, saved_dovar, dovar);
2436 /* Cycle and exit statements are implemented with gotos. */
2437 cycle_label = gfc_build_label_decl (NULL_TREE);
2438 exit_label = gfc_build_label_decl (NULL_TREE);
2440 /* Put the labels where they can be found later. See gfc_trans_do(). */
2441 code->cycle_label = cycle_label;
2442 code->exit_label = exit_label;
2444 /* Loop body. */
2445 gfc_start_block (&body);
2447 /* Exit the loop if there is an I/O result condition or error. */
2448 if (exit_cond)
2450 tmp = build1_v (GOTO_EXPR, exit_label);
2451 tmp = fold_build3_loc (loc, COND_EXPR, void_type_node,
2452 exit_cond, tmp,
2453 build_empty_stmt (loc));
2454 gfc_add_expr_to_block (&body, tmp);
2457 /* Evaluate the loop condition. */
2458 if (is_step_positive)
2459 cond = fold_build2_loc (loc, GT_EXPR, logical_type_node, dovar,
2460 fold_convert (type, to));
2461 else
2462 cond = fold_build2_loc (loc, LT_EXPR, logical_type_node, dovar,
2463 fold_convert (type, to));
2465 cond = gfc_evaluate_now_loc (loc, cond, &body);
2466 if (code->ext.iterator->annot.unroll && cond != error_mark_node)
2467 cond
2468 = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
2469 build_int_cst (integer_type_node, annot_expr_unroll_kind),
2470 build_int_cst (integer_type_node,
2471 code->ext.iterator->annot.unroll));
2473 if (code->ext.iterator->annot.ivdep && cond != error_mark_node)
2474 cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
2475 build_int_cst (integer_type_node, annot_expr_ivdep_kind),
2476 integer_zero_node);
2477 if (code->ext.iterator->annot.vector && cond != error_mark_node)
2478 cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
2479 build_int_cst (integer_type_node, annot_expr_vector_kind),
2480 integer_zero_node);
2481 if (code->ext.iterator->annot.novector && cond != error_mark_node)
2482 cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
2483 build_int_cst (integer_type_node, annot_expr_no_vector_kind),
2484 integer_zero_node);
2486 /* The loop exit. */
2487 tmp = fold_build1_loc (loc, GOTO_EXPR, void_type_node, exit_label);
2488 TREE_USED (exit_label) = 1;
2489 tmp = fold_build3_loc (loc, COND_EXPR, void_type_node,
2490 cond, tmp, build_empty_stmt (loc));
2491 gfc_add_expr_to_block (&body, tmp);
2493 /* Check whether the induction variable is equal to INT_MAX
2494 (respectively to INT_MIN). */
2495 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
2497 tree boundary = is_step_positive ? TYPE_MAX_VALUE (type)
2498 : TYPE_MIN_VALUE (type);
2500 tmp = fold_build2_loc (loc, EQ_EXPR, logical_type_node,
2501 dovar, boundary);
2502 gfc_trans_runtime_check (true, false, tmp, &body, &code->loc,
2503 "Loop iterates infinitely");
2506 /* Main loop body. */
2507 tmp = gfc_trans_code_cond (code->block->next, exit_cond);
2508 gfc_add_expr_to_block (&body, tmp);
2510 /* Label for cycle statements (if needed). */
2511 if (TREE_USED (cycle_label))
2513 tmp = build1_v (LABEL_EXPR, cycle_label);
2514 gfc_add_expr_to_block (&body, tmp);
2517 /* Check whether someone has modified the loop variable. */
2518 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
2520 tmp = fold_build2_loc (loc, NE_EXPR, logical_type_node,
2521 dovar, saved_dovar);
2522 gfc_trans_runtime_check (true, false, tmp, &body, &code->loc,
2523 "Loop variable has been modified");
2526 /* Increment the loop variable. */
2527 tmp = fold_build2_loc (loc, PLUS_EXPR, type, dovar, step);
2528 gfc_add_modify_loc (loc, &body, dovar, tmp);
2530 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
2531 gfc_add_modify_loc (loc, &body, saved_dovar, dovar);
2533 /* Finish the loop body. */
2534 tmp = gfc_finish_block (&body);
2535 tmp = fold_build1_loc (loc, LOOP_EXPR, void_type_node, tmp);
2537 gfc_add_expr_to_block (pblock, tmp);
2539 /* Add the exit label. */
2540 tmp = build1_v (LABEL_EXPR, exit_label);
2541 gfc_add_expr_to_block (pblock, tmp);
2543 return gfc_finish_block (pblock);
2546 /* Translate the DO construct. This obviously is one of the most
2547 important ones to get right with any compiler, but especially
2548 so for Fortran.
2550 We special case some loop forms as described in gfc_trans_simple_do.
2551 For other cases we implement them with a separate loop count,
2552 as described in the standard.
2554 We translate a do loop from:
2556 DO dovar = from, to, step
2557 body
2558 END DO
2562 [evaluate loop bounds and step]
2563 empty = (step > 0 ? to < from : to > from);
2564 countm1 = (to - from) / step;
2565 dovar = from;
2566 if (empty) goto exit_label;
2567 for (;;)
2569 body;
2570 cycle_label:
2571 dovar += step
2572 countm1t = countm1;
2573 countm1--;
2574 if (countm1t == 0) goto exit_label;
2576 exit_label:
2578 countm1 is an unsigned integer. It is equal to the loop count minus one,
2579 because the loop count itself can overflow. */
2581 tree
2582 gfc_trans_do (gfc_code * code, tree exit_cond)
2584 gfc_se se;
2585 tree dovar;
2586 tree saved_dovar = NULL;
2587 tree from;
2588 tree to;
2589 tree step;
2590 tree countm1;
2591 tree type;
2592 tree utype;
2593 tree cond;
2594 tree cycle_label;
2595 tree exit_label;
2596 tree tmp;
2597 stmtblock_t block;
2598 stmtblock_t body;
2599 location_t loc;
2601 gfc_start_block (&block);
2603 loc = gfc_get_location (&code->ext.iterator->start->where);
2605 /* Evaluate all the expressions in the iterator. */
2606 gfc_init_se (&se, NULL);
2607 gfc_conv_expr_lhs (&se, code->ext.iterator->var);
2608 gfc_add_block_to_block (&block, &se.pre);
2609 dovar = se.expr;
2610 type = TREE_TYPE (dovar);
2612 gfc_init_se (&se, NULL);
2613 gfc_conv_expr_val (&se, code->ext.iterator->start);
2614 gfc_add_block_to_block (&block, &se.pre);
2615 from = gfc_evaluate_now (se.expr, &block);
2617 gfc_init_se (&se, NULL);
2618 gfc_conv_expr_val (&se, code->ext.iterator->end);
2619 gfc_add_block_to_block (&block, &se.pre);
2620 to = gfc_evaluate_now (se.expr, &block);
2622 gfc_init_se (&se, NULL);
2623 gfc_conv_expr_val (&se, code->ext.iterator->step);
2624 gfc_add_block_to_block (&block, &se.pre);
2625 step = gfc_evaluate_now (se.expr, &block);
2627 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
2629 tmp = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, step,
2630 build_zero_cst (type));
2631 gfc_trans_runtime_check (true, false, tmp, &block, &code->loc,
2632 "DO step value is zero");
2635 /* Special case simple loops. */
2636 if (TREE_CODE (type) == INTEGER_TYPE
2637 && (integer_onep (step)
2638 || tree_int_cst_equal (step, integer_minus_one_node)))
2639 return gfc_trans_simple_do (code, &block, dovar, from, to, step,
2640 exit_cond);
2642 if (TREE_CODE (type) == INTEGER_TYPE)
2643 utype = unsigned_type_for (type);
2644 else
2645 utype = unsigned_type_for (gfc_array_index_type);
2646 countm1 = gfc_create_var (utype, "countm1");
2648 /* Cycle and exit statements are implemented with gotos. */
2649 cycle_label = gfc_build_label_decl (NULL_TREE);
2650 exit_label = gfc_build_label_decl (NULL_TREE);
2651 TREE_USED (exit_label) = 1;
2653 /* Put these labels where they can be found later. */
2654 code->cycle_label = cycle_label;
2655 code->exit_label = exit_label;
2657 /* Initialize the DO variable: dovar = from. */
2658 gfc_add_modify (&block, dovar, from);
2660 /* Save value for do-tinkering checking. */
2661 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
2663 saved_dovar = gfc_create_var (type, ".saved_dovar");
2664 gfc_add_modify_loc (loc, &block, saved_dovar, dovar);
2667 /* Initialize loop count and jump to exit label if the loop is empty.
2668 This code is executed before we enter the loop body. We generate:
2669 if (step > 0)
2671 countm1 = (to - from) / step;
2672 if (to < from)
2673 goto exit_label;
2675 else
2677 countm1 = (from - to) / -step;
2678 if (to > from)
2679 goto exit_label;
2683 if (TREE_CODE (type) == INTEGER_TYPE)
2685 tree pos, neg, tou, fromu, stepu, tmp2;
2687 /* The distance from FROM to TO cannot always be represented in a signed
2688 type, thus use unsigned arithmetic, also to avoid any undefined
2689 overflow issues. */
2690 tou = fold_convert (utype, to);
2691 fromu = fold_convert (utype, from);
2692 stepu = fold_convert (utype, step);
2694 /* For a positive step, when to < from, exit, otherwise compute
2695 countm1 = ((unsigned)to - (unsigned)from) / (unsigned)step */
2696 tmp = fold_build2_loc (loc, LT_EXPR, logical_type_node, to, from);
2697 tmp2 = fold_build2_loc (loc, TRUNC_DIV_EXPR, utype,
2698 fold_build2_loc (loc, MINUS_EXPR, utype,
2699 tou, fromu),
2700 stepu);
2701 pos = build2 (COMPOUND_EXPR, void_type_node,
2702 fold_build2 (MODIFY_EXPR, void_type_node,
2703 countm1, tmp2),
2704 build3_loc (loc, COND_EXPR, void_type_node,
2705 gfc_unlikely (tmp, PRED_FORTRAN_LOOP_PREHEADER),
2706 build1_loc (loc, GOTO_EXPR, void_type_node,
2707 exit_label), NULL_TREE));
2709 /* For a negative step, when to > from, exit, otherwise compute
2710 countm1 = ((unsigned)from - (unsigned)to) / -(unsigned)step */
2711 tmp = fold_build2_loc (loc, GT_EXPR, logical_type_node, to, from);
2712 tmp2 = fold_build2_loc (loc, TRUNC_DIV_EXPR, utype,
2713 fold_build2_loc (loc, MINUS_EXPR, utype,
2714 fromu, tou),
2715 fold_build1_loc (loc, NEGATE_EXPR, utype, stepu));
2716 neg = build2 (COMPOUND_EXPR, void_type_node,
2717 fold_build2 (MODIFY_EXPR, void_type_node,
2718 countm1, tmp2),
2719 build3_loc (loc, COND_EXPR, void_type_node,
2720 gfc_unlikely (tmp, PRED_FORTRAN_LOOP_PREHEADER),
2721 build1_loc (loc, GOTO_EXPR, void_type_node,
2722 exit_label), NULL_TREE));
2724 tmp = fold_build2_loc (loc, LT_EXPR, logical_type_node, step,
2725 build_int_cst (TREE_TYPE (step), 0));
2726 tmp = fold_build3_loc (loc, COND_EXPR, void_type_node, tmp, neg, pos);
2728 gfc_add_expr_to_block (&block, tmp);
2730 else
2732 tree pos_step;
2734 /* TODO: We could use the same width as the real type.
2735 This would probably cause more problems that it solves
2736 when we implement "long double" types. */
2738 tmp = fold_build2_loc (loc, MINUS_EXPR, type, to, from);
2739 tmp = fold_build2_loc (loc, RDIV_EXPR, type, tmp, step);
2740 tmp = fold_build1_loc (loc, FIX_TRUNC_EXPR, utype, tmp);
2741 gfc_add_modify (&block, countm1, tmp);
2743 /* We need a special check for empty loops:
2744 empty = (step > 0 ? to < from : to > from); */
2745 pos_step = fold_build2_loc (loc, GT_EXPR, logical_type_node, step,
2746 build_zero_cst (type));
2747 tmp = fold_build3_loc (loc, COND_EXPR, logical_type_node, pos_step,
2748 fold_build2_loc (loc, LT_EXPR,
2749 logical_type_node, to, from),
2750 fold_build2_loc (loc, GT_EXPR,
2751 logical_type_node, to, from));
2752 /* If the loop is empty, go directly to the exit label. */
2753 tmp = fold_build3_loc (loc, COND_EXPR, void_type_node, tmp,
2754 build1_v (GOTO_EXPR, exit_label),
2755 build_empty_stmt (input_location));
2756 gfc_add_expr_to_block (&block, tmp);
2759 /* Loop body. */
2760 gfc_start_block (&body);
2762 /* Main loop body. */
2763 tmp = gfc_trans_code_cond (code->block->next, exit_cond);
2764 gfc_add_expr_to_block (&body, tmp);
2766 /* Label for cycle statements (if needed). */
2767 if (TREE_USED (cycle_label))
2769 tmp = build1_v (LABEL_EXPR, cycle_label);
2770 gfc_add_expr_to_block (&body, tmp);
2773 /* Check whether someone has modified the loop variable. */
2774 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
2776 tmp = fold_build2_loc (loc, NE_EXPR, logical_type_node, dovar,
2777 saved_dovar);
2778 gfc_trans_runtime_check (true, false, tmp, &body, &code->loc,
2779 "Loop variable has been modified");
2782 /* Exit the loop if there is an I/O result condition or error. */
2783 if (exit_cond)
2785 tmp = build1_v (GOTO_EXPR, exit_label);
2786 tmp = fold_build3_loc (loc, COND_EXPR, void_type_node,
2787 exit_cond, tmp,
2788 build_empty_stmt (input_location));
2789 gfc_add_expr_to_block (&body, tmp);
2792 /* Increment the loop variable. */
2793 tmp = fold_build2_loc (loc, PLUS_EXPR, type, dovar, step);
2794 gfc_add_modify_loc (loc, &body, dovar, tmp);
2796 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
2797 gfc_add_modify_loc (loc, &body, saved_dovar, dovar);
2799 /* Initialize countm1t. */
2800 tree countm1t = gfc_create_var (utype, "countm1t");
2801 gfc_add_modify_loc (loc, &body, countm1t, countm1);
2803 /* Decrement the loop count. */
2804 tmp = fold_build2_loc (loc, MINUS_EXPR, utype, countm1,
2805 build_int_cst (utype, 1));
2806 gfc_add_modify_loc (loc, &body, countm1, tmp);
2808 /* End with the loop condition. Loop until countm1t == 0. */
2809 cond = fold_build2_loc (loc, EQ_EXPR, logical_type_node, countm1t,
2810 build_int_cst (utype, 0));
2811 if (code->ext.iterator->annot.unroll && cond != error_mark_node)
2812 cond
2813 = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
2814 build_int_cst (integer_type_node, annot_expr_unroll_kind),
2815 build_int_cst (integer_type_node,
2816 code->ext.iterator->annot.unroll));
2818 if (code->ext.iterator->annot.ivdep && cond != error_mark_node)
2819 cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
2820 build_int_cst (integer_type_node, annot_expr_ivdep_kind),
2821 integer_zero_node);
2822 if (code->ext.iterator->annot.vector && cond != error_mark_node)
2823 cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
2824 build_int_cst (integer_type_node, annot_expr_vector_kind),
2825 integer_zero_node);
2826 if (code->ext.iterator->annot.novector && cond != error_mark_node)
2827 cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
2828 build_int_cst (integer_type_node, annot_expr_no_vector_kind),
2829 integer_zero_node);
2831 tmp = fold_build1_loc (loc, GOTO_EXPR, void_type_node, exit_label);
2832 tmp = fold_build3_loc (loc, COND_EXPR, void_type_node,
2833 cond, tmp, build_empty_stmt (loc));
2834 gfc_add_expr_to_block (&body, tmp);
2836 /* End of loop body. */
2837 tmp = gfc_finish_block (&body);
2839 /* The for loop itself. */
2840 tmp = fold_build1_loc (loc, LOOP_EXPR, void_type_node, tmp);
2841 gfc_add_expr_to_block (&block, tmp);
2843 /* Add the exit label. */
2844 tmp = build1_v (LABEL_EXPR, exit_label);
2845 gfc_add_expr_to_block (&block, tmp);
2847 return gfc_finish_block (&block);
2851 /* Translate the DO WHILE construct.
2853 We translate
2855 DO WHILE (cond)
2856 body
2857 END DO
2861 for ( ; ; )
2863 pre_cond;
2864 if (! cond) goto exit_label;
2865 body;
2866 cycle_label:
2868 exit_label:
2870 Because the evaluation of the exit condition `cond' may have side
2871 effects, we can't do much for empty loop bodies. The backend optimizers
2872 should be smart enough to eliminate any dead loops. */
2874 tree
2875 gfc_trans_do_while (gfc_code * code)
2877 gfc_se cond;
2878 tree tmp;
2879 tree cycle_label;
2880 tree exit_label;
2881 stmtblock_t block;
2883 /* Everything we build here is part of the loop body. */
2884 gfc_start_block (&block);
2886 /* Cycle and exit statements are implemented with gotos. */
2887 cycle_label = gfc_build_label_decl (NULL_TREE);
2888 exit_label = gfc_build_label_decl (NULL_TREE);
2890 /* Put the labels where they can be found later. See gfc_trans_do(). */
2891 code->cycle_label = cycle_label;
2892 code->exit_label = exit_label;
2894 /* Create a GIMPLE version of the exit condition. */
2895 gfc_init_se (&cond, NULL);
2896 gfc_conv_expr_val (&cond, code->expr1);
2897 gfc_add_block_to_block (&block, &cond.pre);
2898 cond.expr = fold_build1_loc (gfc_get_location (&code->expr1->where),
2899 TRUTH_NOT_EXPR, TREE_TYPE (cond.expr),
2900 cond.expr);
2902 /* Build "IF (! cond) GOTO exit_label". */
2903 tmp = build1_v (GOTO_EXPR, exit_label);
2904 TREE_USED (exit_label) = 1;
2905 tmp = fold_build3_loc (gfc_get_location (&code->expr1->where), COND_EXPR,
2906 void_type_node, cond.expr, tmp,
2907 build_empty_stmt (gfc_get_location (
2908 &code->expr1->where)));
2909 gfc_add_expr_to_block (&block, tmp);
2911 /* The main body of the loop. */
2912 tmp = gfc_trans_code (code->block->next);
2913 gfc_add_expr_to_block (&block, tmp);
2915 /* Label for cycle statements (if needed). */
2916 if (TREE_USED (cycle_label))
2918 tmp = build1_v (LABEL_EXPR, cycle_label);
2919 gfc_add_expr_to_block (&block, tmp);
2922 /* End of loop body. */
2923 tmp = gfc_finish_block (&block);
2925 gfc_init_block (&block);
2926 /* Build the loop. */
2927 tmp = fold_build1_loc (gfc_get_location (&code->expr1->where), LOOP_EXPR,
2928 void_type_node, tmp);
2929 gfc_add_expr_to_block (&block, tmp);
2931 /* Add the exit label. */
2932 tmp = build1_v (LABEL_EXPR, exit_label);
2933 gfc_add_expr_to_block (&block, tmp);
2935 return gfc_finish_block (&block);
2939 /* Deal with the particular case of SELECT_TYPE, where the vtable
2940 addresses are used for the selection. Since these are not sorted,
2941 the selection has to be made by a series of if statements. */
2943 static tree
2944 gfc_trans_select_type_cases (gfc_code * code)
2946 gfc_code *c;
2947 gfc_case *cp;
2948 tree tmp;
2949 tree cond;
2950 tree low;
2951 tree high;
2952 gfc_se se;
2953 gfc_se cse;
2954 stmtblock_t block;
2955 stmtblock_t body;
2956 bool def = false;
2957 gfc_expr *e;
2958 gfc_start_block (&block);
2960 /* Calculate the switch expression. */
2961 gfc_init_se (&se, NULL);
2962 gfc_conv_expr_val (&se, code->expr1);
2963 gfc_add_block_to_block (&block, &se.pre);
2965 /* Generate an expression for the selector hash value, for
2966 use to resolve character cases. */
2967 e = gfc_copy_expr (code->expr1->value.function.actual->expr);
2968 gfc_add_hash_component (e);
2970 TREE_USED (code->exit_label) = 0;
2972 repeat:
2973 for (c = code->block; c; c = c->block)
2975 cp = c->ext.block.case_list;
2977 /* Assume it's the default case. */
2978 low = NULL_TREE;
2979 high = NULL_TREE;
2980 tmp = NULL_TREE;
2982 /* Put the default case at the end. */
2983 if ((!def && !cp->low) || (def && cp->low))
2984 continue;
2986 if (cp->low && (cp->ts.type == BT_CLASS
2987 || cp->ts.type == BT_DERIVED))
2989 gfc_init_se (&cse, NULL);
2990 gfc_conv_expr_val (&cse, cp->low);
2991 gfc_add_block_to_block (&block, &cse.pre);
2992 low = cse.expr;
2994 else if (cp->ts.type != BT_UNKNOWN)
2996 gcc_assert (cp->high);
2997 gfc_init_se (&cse, NULL);
2998 gfc_conv_expr_val (&cse, cp->high);
2999 gfc_add_block_to_block (&block, &cse.pre);
3000 high = cse.expr;
3003 gfc_init_block (&body);
3005 /* Add the statements for this case. */
3006 tmp = gfc_trans_code (c->next);
3007 gfc_add_expr_to_block (&body, tmp);
3009 /* Break to the end of the SELECT TYPE construct. The default
3010 case just falls through. */
3011 if (!def)
3013 TREE_USED (code->exit_label) = 1;
3014 tmp = build1_v (GOTO_EXPR, code->exit_label);
3015 gfc_add_expr_to_block (&body, tmp);
3018 tmp = gfc_finish_block (&body);
3020 if (low != NULL_TREE)
3022 /* Compare vtable pointers. */
3023 cond = fold_build2_loc (input_location, EQ_EXPR,
3024 TREE_TYPE (se.expr), se.expr, low);
3025 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
3026 cond, tmp,
3027 build_empty_stmt (input_location));
3029 else if (high != NULL_TREE)
3031 /* Compare hash values for character cases. */
3032 gfc_init_se (&cse, NULL);
3033 gfc_conv_expr_val (&cse, e);
3034 gfc_add_block_to_block (&block, &cse.pre);
3036 cond = fold_build2_loc (input_location, EQ_EXPR,
3037 TREE_TYPE (se.expr), high, cse.expr);
3038 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
3039 cond, tmp,
3040 build_empty_stmt (input_location));
3043 gfc_add_expr_to_block (&block, tmp);
3046 if (!def)
3048 def = true;
3049 goto repeat;
3052 gfc_free_expr (e);
3054 return gfc_finish_block (&block);
3058 /* Translate the SELECT CASE construct for INTEGER case expressions,
3059 without killing all potential optimizations. The problem is that
3060 Fortran allows unbounded cases, but the back-end does not, so we
3061 need to intercept those before we enter the equivalent SWITCH_EXPR
3062 we can build.
3064 For example, we translate this,
3066 SELECT CASE (expr)
3067 CASE (:100,101,105:115)
3068 block_1
3069 CASE (190:199,200:)
3070 block_2
3071 CASE (300)
3072 block_3
3073 CASE DEFAULT
3074 block_4
3075 END SELECT
3077 to the GENERIC equivalent,
3079 switch (expr)
3081 case (minimum value for typeof(expr) ... 100:
3082 case 101:
3083 case 105 ... 114:
3084 block1:
3085 goto end_label;
3087 case 200 ... (maximum value for typeof(expr):
3088 case 190 ... 199:
3089 block2;
3090 goto end_label;
3092 case 300:
3093 block_3;
3094 goto end_label;
3096 default:
3097 block_4;
3098 goto end_label;
3101 end_label: */
3103 static tree
3104 gfc_trans_integer_select (gfc_code * code)
3106 gfc_code *c;
3107 gfc_case *cp;
3108 tree end_label;
3109 tree tmp;
3110 gfc_se se;
3111 stmtblock_t block;
3112 stmtblock_t body;
3114 gfc_start_block (&block);
3116 /* Calculate the switch expression. */
3117 gfc_init_se (&se, NULL);
3118 gfc_conv_expr_val (&se, code->expr1);
3119 gfc_add_block_to_block (&block, &se.pre);
3121 end_label = gfc_build_label_decl (NULL_TREE);
3123 gfc_init_block (&body);
3125 for (c = code->block; c; c = c->block)
3127 for (cp = c->ext.block.case_list; cp; cp = cp->next)
3129 tree low, high;
3130 tree label;
3132 /* Assume it's the default case. */
3133 low = high = NULL_TREE;
3135 if (cp->low)
3137 low = gfc_conv_mpz_to_tree (cp->low->value.integer,
3138 cp->low->ts.kind);
3140 /* If there's only a lower bound, set the high bound to the
3141 maximum value of the case expression. */
3142 if (!cp->high)
3143 high = TYPE_MAX_VALUE (TREE_TYPE (se.expr));
3146 if (cp->high)
3148 /* Three cases are possible here:
3150 1) There is no lower bound, e.g. CASE (:N).
3151 2) There is a lower bound .NE. high bound, that is
3152 a case range, e.g. CASE (N:M) where M>N (we make
3153 sure that M>N during type resolution).
3154 3) There is a lower bound, and it has the same value
3155 as the high bound, e.g. CASE (N:N). This is our
3156 internal representation of CASE(N).
3158 In the first and second case, we need to set a value for
3159 high. In the third case, we don't because the GCC middle
3160 end represents a single case value by just letting high be
3161 a NULL_TREE. We can't do that because we need to be able
3162 to represent unbounded cases. */
3164 if (!cp->low
3165 || (mpz_cmp (cp->low->value.integer,
3166 cp->high->value.integer) != 0))
3167 high = gfc_conv_mpz_to_tree (cp->high->value.integer,
3168 cp->high->ts.kind);
3170 /* Unbounded case. */
3171 if (!cp->low)
3172 low = TYPE_MIN_VALUE (TREE_TYPE (se.expr));
3175 /* Build a label. */
3176 label = gfc_build_label_decl (NULL_TREE);
3178 /* Add this case label.
3179 Add parameter 'label', make it match GCC backend. */
3180 tmp = build_case_label (low, high, label);
3181 gfc_add_expr_to_block (&body, tmp);
3184 /* Add the statements for this case. */
3185 tmp = gfc_trans_code (c->next);
3186 gfc_add_expr_to_block (&body, tmp);
3188 /* Break to the end of the construct. */
3189 tmp = build1_v (GOTO_EXPR, end_label);
3190 gfc_add_expr_to_block (&body, tmp);
3193 tmp = gfc_finish_block (&body);
3194 tmp = fold_build2_loc (input_location, SWITCH_EXPR, NULL_TREE, se.expr, tmp);
3195 gfc_add_expr_to_block (&block, tmp);
3197 tmp = build1_v (LABEL_EXPR, end_label);
3198 gfc_add_expr_to_block (&block, tmp);
3200 return gfc_finish_block (&block);
3204 /* Translate the SELECT CASE construct for LOGICAL case expressions.
3206 There are only two cases possible here, even though the standard
3207 does allow three cases in a LOGICAL SELECT CASE construct: .TRUE.,
3208 .FALSE., and DEFAULT.
3210 We never generate more than two blocks here. Instead, we always
3211 try to eliminate the DEFAULT case. This way, we can translate this
3212 kind of SELECT construct to a simple
3214 if {} else {};
3216 expression in GENERIC. */
3218 static tree
3219 gfc_trans_logical_select (gfc_code * code)
3221 gfc_code *c;
3222 gfc_code *t, *f, *d;
3223 gfc_case *cp;
3224 gfc_se se;
3225 stmtblock_t block;
3227 /* Assume we don't have any cases at all. */
3228 t = f = d = NULL;
3230 /* Now see which ones we actually do have. We can have at most two
3231 cases in a single case list: one for .TRUE. and one for .FALSE.
3232 The default case is always separate. If the cases for .TRUE. and
3233 .FALSE. are in the same case list, the block for that case list
3234 always executed, and we don't generate code a COND_EXPR. */
3235 for (c = code->block; c; c = c->block)
3237 for (cp = c->ext.block.case_list; cp; cp = cp->next)
3239 if (cp->low)
3241 if (cp->low->value.logical == 0) /* .FALSE. */
3242 f = c;
3243 else /* if (cp->value.logical != 0), thus .TRUE. */
3244 t = c;
3246 else
3247 d = c;
3251 /* Start a new block. */
3252 gfc_start_block (&block);
3254 /* Calculate the switch expression. We always need to do this
3255 because it may have side effects. */
3256 gfc_init_se (&se, NULL);
3257 gfc_conv_expr_val (&se, code->expr1);
3258 gfc_add_block_to_block (&block, &se.pre);
3260 if (t == f && t != NULL)
3262 /* Cases for .TRUE. and .FALSE. are in the same block. Just
3263 translate the code for these cases, append it to the current
3264 block. */
3265 gfc_add_expr_to_block (&block, gfc_trans_code (t->next));
3267 else
3269 tree true_tree, false_tree, stmt;
3271 true_tree = build_empty_stmt (input_location);
3272 false_tree = build_empty_stmt (input_location);
3274 /* If we have a case for .TRUE. and for .FALSE., discard the default case.
3275 Otherwise, if .TRUE. or .FALSE. is missing and there is a default case,
3276 make the missing case the default case. */
3277 if (t != NULL && f != NULL)
3278 d = NULL;
3279 else if (d != NULL)
3281 if (t == NULL)
3282 t = d;
3283 else
3284 f = d;
3287 /* Translate the code for each of these blocks, and append it to
3288 the current block. */
3289 if (t != NULL)
3290 true_tree = gfc_trans_code (t->next);
3292 if (f != NULL)
3293 false_tree = gfc_trans_code (f->next);
3295 stmt = fold_build3_loc (input_location, COND_EXPR, void_type_node,
3296 se.expr, true_tree, false_tree);
3297 gfc_add_expr_to_block (&block, stmt);
3300 return gfc_finish_block (&block);
3304 /* The jump table types are stored in static variables to avoid
3305 constructing them from scratch every single time. */
3306 static GTY(()) tree select_struct[2];
3308 /* Translate the SELECT CASE construct for CHARACTER case expressions.
3309 Instead of generating compares and jumps, it is far simpler to
3310 generate a data structure describing the cases in order and call a
3311 library subroutine that locates the right case.
3312 This is particularly true because this is the only case where we
3313 might have to dispose of a temporary.
3314 The library subroutine returns a pointer to jump to or NULL if no
3315 branches are to be taken. */
3317 static tree
3318 gfc_trans_character_select (gfc_code *code)
3320 tree init, end_label, tmp, type, case_num, label, fndecl;
3321 stmtblock_t block, body;
3322 gfc_case *cp, *d;
3323 gfc_code *c;
3324 gfc_se se, expr1se;
3325 int n, k;
3326 vec<constructor_elt, va_gc> *inits = NULL;
3328 tree pchartype = gfc_get_pchar_type (code->expr1->ts.kind);
3330 /* The jump table types are stored in static variables to avoid
3331 constructing them from scratch every single time. */
3332 static tree ss_string1[2], ss_string1_len[2];
3333 static tree ss_string2[2], ss_string2_len[2];
3334 static tree ss_target[2];
3336 cp = code->block->ext.block.case_list;
3337 while (cp->left != NULL)
3338 cp = cp->left;
3340 /* Generate the body */
3341 gfc_start_block (&block);
3342 gfc_init_se (&expr1se, NULL);
3343 gfc_conv_expr_reference (&expr1se, code->expr1);
3345 gfc_add_block_to_block (&block, &expr1se.pre);
3347 end_label = gfc_build_label_decl (NULL_TREE);
3349 gfc_init_block (&body);
3351 /* Attempt to optimize length 1 selects. */
3352 if (integer_onep (expr1se.string_length))
3354 for (d = cp; d; d = d->right)
3356 gfc_charlen_t i;
3357 if (d->low)
3359 gcc_assert (d->low->expr_type == EXPR_CONSTANT
3360 && d->low->ts.type == BT_CHARACTER);
3361 if (d->low->value.character.length > 1)
3363 for (i = 1; i < d->low->value.character.length; i++)
3364 if (d->low->value.character.string[i] != ' ')
3365 break;
3366 if (i != d->low->value.character.length)
3368 if (optimize && d->high && i == 1)
3370 gcc_assert (d->high->expr_type == EXPR_CONSTANT
3371 && d->high->ts.type == BT_CHARACTER);
3372 if (d->high->value.character.length > 1
3373 && (d->low->value.character.string[0]
3374 == d->high->value.character.string[0])
3375 && d->high->value.character.string[1] != ' '
3376 && ((d->low->value.character.string[1] < ' ')
3377 == (d->high->value.character.string[1]
3378 < ' ')))
3379 continue;
3381 break;
3385 if (d->high)
3387 gcc_assert (d->high->expr_type == EXPR_CONSTANT
3388 && d->high->ts.type == BT_CHARACTER);
3389 if (d->high->value.character.length > 1)
3391 for (i = 1; i < d->high->value.character.length; i++)
3392 if (d->high->value.character.string[i] != ' ')
3393 break;
3394 if (i != d->high->value.character.length)
3395 break;
3399 if (d == NULL)
3401 tree ctype = gfc_get_char_type (code->expr1->ts.kind);
3403 for (c = code->block; c; c = c->block)
3405 for (cp = c->ext.block.case_list; cp; cp = cp->next)
3407 tree low, high;
3408 tree label;
3409 gfc_char_t r;
3411 /* Assume it's the default case. */
3412 low = high = NULL_TREE;
3414 if (cp->low)
3416 /* CASE ('ab') or CASE ('ab':'az') will never match
3417 any length 1 character. */
3418 if (cp->low->value.character.length > 1
3419 && cp->low->value.character.string[1] != ' ')
3420 continue;
3422 if (cp->low->value.character.length > 0)
3423 r = cp->low->value.character.string[0];
3424 else
3425 r = ' ';
3426 low = build_int_cst (ctype, r);
3428 /* If there's only a lower bound, set the high bound
3429 to the maximum value of the case expression. */
3430 if (!cp->high)
3431 high = TYPE_MAX_VALUE (ctype);
3434 if (cp->high)
3436 if (!cp->low
3437 || (cp->low->value.character.string[0]
3438 != cp->high->value.character.string[0]))
3440 if (cp->high->value.character.length > 0)
3441 r = cp->high->value.character.string[0];
3442 else
3443 r = ' ';
3444 high = build_int_cst (ctype, r);
3447 /* Unbounded case. */
3448 if (!cp->low)
3449 low = TYPE_MIN_VALUE (ctype);
3452 /* Build a label. */
3453 label = gfc_build_label_decl (NULL_TREE);
3455 /* Add this case label.
3456 Add parameter 'label', make it match GCC backend. */
3457 tmp = build_case_label (low, high, label);
3458 gfc_add_expr_to_block (&body, tmp);
3461 /* Add the statements for this case. */
3462 tmp = gfc_trans_code (c->next);
3463 gfc_add_expr_to_block (&body, tmp);
3465 /* Break to the end of the construct. */
3466 tmp = build1_v (GOTO_EXPR, end_label);
3467 gfc_add_expr_to_block (&body, tmp);
3470 tmp = gfc_string_to_single_character (expr1se.string_length,
3471 expr1se.expr,
3472 code->expr1->ts.kind);
3473 case_num = gfc_create_var (ctype, "case_num");
3474 gfc_add_modify (&block, case_num, tmp);
3476 gfc_add_block_to_block (&block, &expr1se.post);
3478 tmp = gfc_finish_block (&body);
3479 tmp = fold_build2_loc (input_location, SWITCH_EXPR, NULL_TREE,
3480 case_num, tmp);
3481 gfc_add_expr_to_block (&block, tmp);
3483 tmp = build1_v (LABEL_EXPR, end_label);
3484 gfc_add_expr_to_block (&block, tmp);
3486 return gfc_finish_block (&block);
3490 if (code->expr1->ts.kind == 1)
3491 k = 0;
3492 else if (code->expr1->ts.kind == 4)
3493 k = 1;
3494 else
3495 gcc_unreachable ();
3497 if (select_struct[k] == NULL)
3499 tree *chain = NULL;
3500 select_struct[k] = make_node (RECORD_TYPE);
3502 if (code->expr1->ts.kind == 1)
3503 TYPE_NAME (select_struct[k]) = get_identifier ("_jump_struct_char1");
3504 else if (code->expr1->ts.kind == 4)
3505 TYPE_NAME (select_struct[k]) = get_identifier ("_jump_struct_char4");
3506 else
3507 gcc_unreachable ();
3509 #undef ADD_FIELD
3510 #define ADD_FIELD(NAME, TYPE) \
3511 ss_##NAME[k] = gfc_add_field_to_struct (select_struct[k], \
3512 get_identifier (stringize(NAME)), \
3513 TYPE, \
3514 &chain)
3516 ADD_FIELD (string1, pchartype);
3517 ADD_FIELD (string1_len, gfc_charlen_type_node);
3519 ADD_FIELD (string2, pchartype);
3520 ADD_FIELD (string2_len, gfc_charlen_type_node);
3522 ADD_FIELD (target, integer_type_node);
3523 #undef ADD_FIELD
3525 gfc_finish_type (select_struct[k]);
3528 n = 0;
3529 for (d = cp; d; d = d->right)
3530 d->n = n++;
3532 for (c = code->block; c; c = c->block)
3534 for (d = c->ext.block.case_list; d; d = d->next)
3536 label = gfc_build_label_decl (NULL_TREE);
3537 tmp = build_case_label ((d->low == NULL && d->high == NULL)
3538 ? NULL
3539 : build_int_cst (integer_type_node, d->n),
3540 NULL, label);
3541 gfc_add_expr_to_block (&body, tmp);
3544 tmp = gfc_trans_code (c->next);
3545 gfc_add_expr_to_block (&body, tmp);
3547 tmp = build1_v (GOTO_EXPR, end_label);
3548 gfc_add_expr_to_block (&body, tmp);
3551 /* Generate the structure describing the branches */
3552 for (d = cp; d; d = d->right)
3554 vec<constructor_elt, va_gc> *node = NULL;
3556 gfc_init_se (&se, NULL);
3558 if (d->low == NULL)
3560 CONSTRUCTOR_APPEND_ELT (node, ss_string1[k], null_pointer_node);
3561 CONSTRUCTOR_APPEND_ELT (node, ss_string1_len[k], build_zero_cst (gfc_charlen_type_node));
3563 else
3565 gfc_conv_expr_reference (&se, d->low);
3567 CONSTRUCTOR_APPEND_ELT (node, ss_string1[k], se.expr);
3568 CONSTRUCTOR_APPEND_ELT (node, ss_string1_len[k], se.string_length);
3571 if (d->high == NULL)
3573 CONSTRUCTOR_APPEND_ELT (node, ss_string2[k], null_pointer_node);
3574 CONSTRUCTOR_APPEND_ELT (node, ss_string2_len[k], build_zero_cst (gfc_charlen_type_node));
3576 else
3578 gfc_init_se (&se, NULL);
3579 gfc_conv_expr_reference (&se, d->high);
3581 CONSTRUCTOR_APPEND_ELT (node, ss_string2[k], se.expr);
3582 CONSTRUCTOR_APPEND_ELT (node, ss_string2_len[k], se.string_length);
3585 CONSTRUCTOR_APPEND_ELT (node, ss_target[k],
3586 build_int_cst (integer_type_node, d->n));
3588 tmp = build_constructor (select_struct[k], node);
3589 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, tmp);
3592 type = build_array_type (select_struct[k],
3593 build_index_type (size_int (n-1)));
3595 init = build_constructor (type, inits);
3596 TREE_CONSTANT (init) = 1;
3597 TREE_STATIC (init) = 1;
3598 /* Create a static variable to hold the jump table. */
3599 tmp = gfc_create_var (type, "jumptable");
3600 TREE_CONSTANT (tmp) = 1;
3601 TREE_STATIC (tmp) = 1;
3602 TREE_READONLY (tmp) = 1;
3603 DECL_INITIAL (tmp) = init;
3604 init = tmp;
3606 /* Build the library call */
3607 init = gfc_build_addr_expr (pvoid_type_node, init);
3609 if (code->expr1->ts.kind == 1)
3610 fndecl = gfor_fndecl_select_string;
3611 else if (code->expr1->ts.kind == 4)
3612 fndecl = gfor_fndecl_select_string_char4;
3613 else
3614 gcc_unreachable ();
3616 tmp = build_call_expr_loc (input_location,
3617 fndecl, 4, init,
3618 build_int_cst (gfc_charlen_type_node, n),
3619 expr1se.expr, expr1se.string_length);
3620 case_num = gfc_create_var (integer_type_node, "case_num");
3621 gfc_add_modify (&block, case_num, tmp);
3623 gfc_add_block_to_block (&block, &expr1se.post);
3625 tmp = gfc_finish_block (&body);
3626 tmp = fold_build2_loc (input_location, SWITCH_EXPR, NULL_TREE,
3627 case_num, tmp);
3628 gfc_add_expr_to_block (&block, tmp);
3630 tmp = build1_v (LABEL_EXPR, end_label);
3631 gfc_add_expr_to_block (&block, tmp);
3633 return gfc_finish_block (&block);
3637 /* Translate the three variants of the SELECT CASE construct.
3639 SELECT CASEs with INTEGER case expressions can be translated to an
3640 equivalent GENERIC switch statement, and for LOGICAL case
3641 expressions we build one or two if-else compares.
3643 SELECT CASEs with CHARACTER case expressions are a whole different
3644 story, because they don't exist in GENERIC. So we sort them and
3645 do a binary search at runtime.
3647 Fortran has no BREAK statement, and it does not allow jumps from
3648 one case block to another. That makes things a lot easier for
3649 the optimizers. */
3651 tree
3652 gfc_trans_select (gfc_code * code)
3654 stmtblock_t block;
3655 tree body;
3656 tree exit_label;
3658 gcc_assert (code && code->expr1);
3659 gfc_init_block (&block);
3661 /* Build the exit label and hang it in. */
3662 exit_label = gfc_build_label_decl (NULL_TREE);
3663 code->exit_label = exit_label;
3665 /* Empty SELECT constructs are legal. */
3666 if (code->block == NULL)
3667 body = build_empty_stmt (input_location);
3669 /* Select the correct translation function. */
3670 else
3671 switch (code->expr1->ts.type)
3673 case BT_LOGICAL:
3674 body = gfc_trans_logical_select (code);
3675 break;
3677 case BT_INTEGER:
3678 body = gfc_trans_integer_select (code);
3679 break;
3681 case BT_CHARACTER:
3682 body = gfc_trans_character_select (code);
3683 break;
3685 default:
3686 gfc_internal_error ("gfc_trans_select(): Bad type for case expr.");
3687 /* Not reached */
3690 /* Build everything together. */
3691 gfc_add_expr_to_block (&block, body);
3692 gfc_add_expr_to_block (&block, build1_v (LABEL_EXPR, exit_label));
3694 return gfc_finish_block (&block);
3697 tree
3698 gfc_trans_select_type (gfc_code * code)
3700 stmtblock_t block;
3701 tree body;
3702 tree exit_label;
3704 gcc_assert (code && code->expr1);
3705 gfc_init_block (&block);
3707 /* Build the exit label and hang it in. */
3708 exit_label = gfc_build_label_decl (NULL_TREE);
3709 code->exit_label = exit_label;
3711 /* Empty SELECT constructs are legal. */
3712 if (code->block == NULL)
3713 body = build_empty_stmt (input_location);
3714 else
3715 body = gfc_trans_select_type_cases (code);
3717 /* Build everything together. */
3718 gfc_add_expr_to_block (&block, body);
3720 if (TREE_USED (exit_label))
3721 gfc_add_expr_to_block (&block, build1_v (LABEL_EXPR, exit_label));
3723 return gfc_finish_block (&block);
3727 static tree
3728 gfc_trans_select_rank_cases (gfc_code * code)
3730 gfc_code *c;
3731 gfc_case *cp;
3732 tree tmp;
3733 tree cond;
3734 tree low;
3735 tree rank;
3736 gfc_se se;
3737 gfc_se cse;
3738 stmtblock_t block;
3739 stmtblock_t body;
3740 bool def = false;
3742 gfc_start_block (&block);
3744 /* Calculate the switch expression. */
3745 gfc_init_se (&se, NULL);
3746 gfc_conv_expr_descriptor (&se, code->expr1);
3747 rank = gfc_conv_descriptor_rank (se.expr);
3748 rank = gfc_evaluate_now (rank, &block);
3749 symbol_attribute attr = gfc_expr_attr (code->expr1);
3750 if (!attr.pointer && !attr.allocatable)
3752 /* Special case for assumed-rank ('rank(*)', internally -1):
3753 rank = (rank == 0 || ubound[rank-1] != -1) ? rank : -1. */
3754 cond = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
3755 rank, build_int_cst (TREE_TYPE (rank), 0));
3756 tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
3757 fold_convert (gfc_array_index_type, rank),
3758 gfc_index_one_node);
3759 tmp = gfc_conv_descriptor_ubound_get (se.expr, tmp);
3760 tmp = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
3761 tmp, build_int_cst (TREE_TYPE (tmp), -1));
3762 cond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
3763 logical_type_node, cond, tmp);
3764 tmp = fold_build3_loc (input_location, COND_EXPR, TREE_TYPE (rank),
3765 cond, rank, build_int_cst (TREE_TYPE (rank), -1));
3766 rank = gfc_evaluate_now (tmp, &block);
3768 TREE_USED (code->exit_label) = 0;
3770 repeat:
3771 for (c = code->block; c; c = c->block)
3773 cp = c->ext.block.case_list;
3775 /* Assume it's the default case. */
3776 low = NULL_TREE;
3777 tmp = NULL_TREE;
3779 /* Put the default case at the end. */
3780 if ((!def && !cp->low) || (def && cp->low))
3781 continue;
3783 if (cp->low)
3785 gfc_init_se (&cse, NULL);
3786 gfc_conv_expr_val (&cse, cp->low);
3787 gfc_add_block_to_block (&block, &cse.pre);
3788 low = cse.expr;
3791 gfc_init_block (&body);
3793 /* Add the statements for this case. */
3794 tmp = gfc_trans_code (c->next);
3795 gfc_add_expr_to_block (&body, tmp);
3797 /* Break to the end of the SELECT RANK construct. The default
3798 case just falls through. */
3799 if (!def)
3801 TREE_USED (code->exit_label) = 1;
3802 tmp = build1_v (GOTO_EXPR, code->exit_label);
3803 gfc_add_expr_to_block (&body, tmp);
3806 tmp = gfc_finish_block (&body);
3808 if (low != NULL_TREE)
3810 cond = fold_build2_loc (input_location, EQ_EXPR,
3811 TREE_TYPE (rank), rank,
3812 fold_convert (TREE_TYPE (rank), low));
3813 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
3814 cond, tmp,
3815 build_empty_stmt (input_location));
3818 gfc_add_expr_to_block (&block, tmp);
3821 if (!def)
3823 def = true;
3824 goto repeat;
3827 return gfc_finish_block (&block);
3831 tree
3832 gfc_trans_select_rank (gfc_code * code)
3834 stmtblock_t block;
3835 tree body;
3836 tree exit_label;
3838 gcc_assert (code && code->expr1);
3839 gfc_init_block (&block);
3841 /* Build the exit label and hang it in. */
3842 exit_label = gfc_build_label_decl (NULL_TREE);
3843 code->exit_label = exit_label;
3845 /* Empty SELECT constructs are legal. */
3846 if (code->block == NULL)
3847 body = build_empty_stmt (input_location);
3848 else
3849 body = gfc_trans_select_rank_cases (code);
3851 /* Build everything together. */
3852 gfc_add_expr_to_block (&block, body);
3854 if (TREE_USED (exit_label))
3855 gfc_add_expr_to_block (&block, build1_v (LABEL_EXPR, exit_label));
3857 return gfc_finish_block (&block);
3861 /* Traversal function to substitute a replacement symtree if the symbol
3862 in the expression is the same as that passed. f == 2 signals that
3863 that variable itself is not to be checked - only the references.
3864 This group of functions is used when the variable expression in a
3865 FORALL assignment has internal references. For example:
3866 FORALL (i = 1:4) p(p(i)) = i
3867 The only recourse here is to store a copy of 'p' for the index
3868 expression. */
3870 static gfc_symtree *new_symtree;
3871 static gfc_symtree *old_symtree;
3873 static bool
3874 forall_replace (gfc_expr *expr, gfc_symbol *sym, int *f)
3876 if (expr->expr_type != EXPR_VARIABLE)
3877 return false;
3879 if (*f == 2)
3880 *f = 1;
3881 else if (expr->symtree->n.sym == sym)
3882 expr->symtree = new_symtree;
3884 return false;
3887 static void
3888 forall_replace_symtree (gfc_expr *e, gfc_symbol *sym, int f)
3890 gfc_traverse_expr (e, sym, forall_replace, f);
3893 static bool
3894 forall_restore (gfc_expr *expr,
3895 gfc_symbol *sym ATTRIBUTE_UNUSED,
3896 int *f ATTRIBUTE_UNUSED)
3898 if (expr->expr_type != EXPR_VARIABLE)
3899 return false;
3901 if (expr->symtree == new_symtree)
3902 expr->symtree = old_symtree;
3904 return false;
3907 static void
3908 forall_restore_symtree (gfc_expr *e)
3910 gfc_traverse_expr (e, NULL, forall_restore, 0);
3913 static void
3914 forall_make_variable_temp (gfc_code *c, stmtblock_t *pre, stmtblock_t *post)
3916 gfc_se tse;
3917 gfc_se rse;
3918 gfc_expr *e;
3919 gfc_symbol *new_sym;
3920 gfc_symbol *old_sym;
3921 gfc_symtree *root;
3922 tree tmp;
3924 /* Build a copy of the lvalue. */
3925 old_symtree = c->expr1->symtree;
3926 old_sym = old_symtree->n.sym;
3927 e = gfc_lval_expr_from_sym (old_sym);
3928 if (old_sym->attr.dimension)
3930 gfc_init_se (&tse, NULL);
3931 gfc_conv_subref_array_arg (&tse, e, 0, INTENT_IN, false);
3932 gfc_add_block_to_block (pre, &tse.pre);
3933 gfc_add_block_to_block (post, &tse.post);
3934 tse.expr = build_fold_indirect_ref_loc (input_location, tse.expr);
3936 if (c->expr1->ref->u.ar.type != AR_SECTION)
3938 /* Use the variable offset for the temporary. */
3939 tmp = gfc_conv_array_offset (old_sym->backend_decl);
3940 gfc_conv_descriptor_offset_set (pre, tse.expr, tmp);
3943 else
3945 gfc_init_se (&tse, NULL);
3946 gfc_init_se (&rse, NULL);
3947 gfc_conv_expr (&rse, e);
3948 if (e->ts.type == BT_CHARACTER)
3950 tse.string_length = rse.string_length;
3951 tmp = gfc_get_character_type_len (gfc_default_character_kind,
3952 tse.string_length);
3953 tse.expr = gfc_conv_string_tmp (&tse, build_pointer_type (tmp),
3954 rse.string_length);
3955 gfc_add_block_to_block (pre, &tse.pre);
3956 gfc_add_block_to_block (post, &tse.post);
3958 else
3960 tmp = gfc_typenode_for_spec (&e->ts);
3961 tse.expr = gfc_create_var (tmp, "temp");
3964 tmp = gfc_trans_scalar_assign (&tse, &rse, e->ts,
3965 e->expr_type == EXPR_VARIABLE, false);
3966 gfc_add_expr_to_block (pre, tmp);
3968 gfc_free_expr (e);
3970 /* Create a new symbol to represent the lvalue. */
3971 new_sym = gfc_new_symbol (old_sym->name, NULL);
3972 new_sym->ts = old_sym->ts;
3973 new_sym->attr.referenced = 1;
3974 new_sym->attr.temporary = 1;
3975 new_sym->attr.dimension = old_sym->attr.dimension;
3976 new_sym->attr.flavor = old_sym->attr.flavor;
3978 /* Use the temporary as the backend_decl. */
3979 new_sym->backend_decl = tse.expr;
3981 /* Create a fake symtree for it. */
3982 root = NULL;
3983 new_symtree = gfc_new_symtree (&root, old_sym->name);
3984 new_symtree->n.sym = new_sym;
3985 gcc_assert (new_symtree == root);
3987 /* Go through the expression reference replacing the old_symtree
3988 with the new. */
3989 forall_replace_symtree (c->expr1, old_sym, 2);
3991 /* Now we have made this temporary, we might as well use it for
3992 the right hand side. */
3993 forall_replace_symtree (c->expr2, old_sym, 1);
3997 /* Handles dependencies in forall assignments. */
3998 static int
3999 check_forall_dependencies (gfc_code *c, stmtblock_t *pre, stmtblock_t *post)
4001 gfc_ref *lref;
4002 gfc_ref *rref;
4003 int need_temp;
4004 gfc_symbol *lsym;
4006 lsym = c->expr1->symtree->n.sym;
4007 need_temp = gfc_check_dependency (c->expr1, c->expr2, 0);
4009 /* Now check for dependencies within the 'variable'
4010 expression itself. These are treated by making a complete
4011 copy of variable and changing all the references to it
4012 point to the copy instead. Note that the shallow copy of
4013 the variable will not suffice for derived types with
4014 pointer components. We therefore leave these to their
4015 own devices. Likewise for allocatable components. */
4016 if (lsym->ts.type == BT_DERIVED
4017 && (lsym->ts.u.derived->attr.pointer_comp
4018 || lsym->ts.u.derived->attr.alloc_comp))
4019 return need_temp;
4021 new_symtree = NULL;
4022 if (find_forall_index (c->expr1, lsym, 2))
4024 forall_make_variable_temp (c, pre, post);
4025 need_temp = 0;
4028 /* Substrings with dependencies are treated in the same
4029 way. */
4030 if (c->expr1->ts.type == BT_CHARACTER
4031 && c->expr1->ref
4032 && c->expr2->expr_type == EXPR_VARIABLE
4033 && lsym == c->expr2->symtree->n.sym)
4035 for (lref = c->expr1->ref; lref; lref = lref->next)
4036 if (lref->type == REF_SUBSTRING)
4037 break;
4038 for (rref = c->expr2->ref; rref; rref = rref->next)
4039 if (rref->type == REF_SUBSTRING)
4040 break;
4042 if (rref && lref
4043 && gfc_dep_compare_expr (rref->u.ss.start, lref->u.ss.start) < 0)
4045 forall_make_variable_temp (c, pre, post);
4046 need_temp = 0;
4049 return need_temp;
4053 static void
4054 cleanup_forall_symtrees (gfc_code *c)
4056 forall_restore_symtree (c->expr1);
4057 forall_restore_symtree (c->expr2);
4058 free (new_symtree->n.sym);
4059 free (new_symtree);
4063 /* Generate the loops for a FORALL block, specified by FORALL_TMP. BODY
4064 is the contents of the FORALL block/stmt to be iterated. MASK_FLAG
4065 indicates whether we should generate code to test the FORALLs mask
4066 array. OUTER is the loop header to be used for initializing mask
4067 indices.
4069 The generated loop format is:
4070 count = (end - start + step) / step
4071 loopvar = start
4072 while (1)
4074 if (count <=0 )
4075 goto end_of_loop
4076 <body>
4077 loopvar += step
4078 count --
4080 end_of_loop: */
4082 static tree
4083 gfc_trans_forall_loop (forall_info *forall_tmp, tree body,
4084 int mask_flag, stmtblock_t *outer)
4086 int n, nvar;
4087 tree tmp;
4088 tree cond;
4089 stmtblock_t block;
4090 tree exit_label;
4091 tree count;
4092 tree var, start, end, step;
4093 iter_info *iter;
4095 /* Initialize the mask index outside the FORALL nest. */
4096 if (mask_flag && forall_tmp->mask)
4097 gfc_add_modify (outer, forall_tmp->maskindex, gfc_index_zero_node);
4099 iter = forall_tmp->this_loop;
4100 nvar = forall_tmp->nvar;
4101 for (n = 0; n < nvar; n++)
4103 var = iter->var;
4104 start = iter->start;
4105 end = iter->end;
4106 step = iter->step;
4108 exit_label = gfc_build_label_decl (NULL_TREE);
4109 TREE_USED (exit_label) = 1;
4111 /* The loop counter. */
4112 count = gfc_create_var (TREE_TYPE (var), "count");
4114 /* The body of the loop. */
4115 gfc_init_block (&block);
4117 /* The exit condition. */
4118 cond = fold_build2_loc (input_location, LE_EXPR, logical_type_node,
4119 count, build_int_cst (TREE_TYPE (count), 0));
4121 /* PR 83064 means that we cannot use annot_expr_parallel_kind until
4122 the autoparallelizer can handle this. */
4123 if (forall_tmp->do_concurrent || iter->annot.ivdep)
4124 cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
4125 build_int_cst (integer_type_node,
4126 annot_expr_ivdep_kind),
4127 integer_zero_node);
4129 if (iter->annot.unroll && cond != error_mark_node)
4130 cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
4131 build_int_cst (integer_type_node,
4132 annot_expr_unroll_kind),
4133 build_int_cst (integer_type_node, iter->annot.unroll));
4135 if (iter->annot.vector && cond != error_mark_node)
4136 cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
4137 build_int_cst (integer_type_node,
4138 annot_expr_vector_kind),
4139 integer_zero_node);
4141 if (iter->annot.novector && cond != error_mark_node)
4142 cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
4143 build_int_cst (integer_type_node,
4144 annot_expr_no_vector_kind),
4145 integer_zero_node);
4147 tmp = build1_v (GOTO_EXPR, exit_label);
4148 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
4149 cond, tmp, build_empty_stmt (input_location));
4150 gfc_add_expr_to_block (&block, tmp);
4152 /* The main loop body. */
4153 gfc_add_expr_to_block (&block, body);
4155 /* Increment the loop variable. */
4156 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (var), var,
4157 step);
4158 gfc_add_modify (&block, var, tmp);
4160 /* Advance to the next mask element. Only do this for the
4161 innermost loop. */
4162 if (n == 0 && mask_flag && forall_tmp->mask)
4164 tree maskindex = forall_tmp->maskindex;
4165 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
4166 maskindex, gfc_index_one_node);
4167 gfc_add_modify (&block, maskindex, tmp);
4170 /* Decrement the loop counter. */
4171 tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (var), count,
4172 build_int_cst (TREE_TYPE (var), 1));
4173 gfc_add_modify (&block, count, tmp);
4175 body = gfc_finish_block (&block);
4177 /* Loop var initialization. */
4178 gfc_init_block (&block);
4179 gfc_add_modify (&block, var, start);
4182 /* Initialize the loop counter. */
4183 tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (var), step,
4184 start);
4185 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (var), end,
4186 tmp);
4187 tmp = fold_build2_loc (input_location, TRUNC_DIV_EXPR, TREE_TYPE (var),
4188 tmp, step);
4189 gfc_add_modify (&block, count, tmp);
4191 /* The loop expression. */
4192 tmp = build1_v (LOOP_EXPR, body);
4193 gfc_add_expr_to_block (&block, tmp);
4195 /* The exit label. */
4196 tmp = build1_v (LABEL_EXPR, exit_label);
4197 gfc_add_expr_to_block (&block, tmp);
4199 body = gfc_finish_block (&block);
4200 iter = iter->next;
4202 return body;
4206 /* Generate the body and loops according to MASK_FLAG. If MASK_FLAG
4207 is nonzero, the body is controlled by all masks in the forall nest.
4208 Otherwise, the innermost loop is not controlled by it's mask. This
4209 is used for initializing that mask. */
4211 static tree
4212 gfc_trans_nested_forall_loop (forall_info * nested_forall_info, tree body,
4213 int mask_flag)
4215 tree tmp;
4216 stmtblock_t header;
4217 forall_info *forall_tmp;
4218 tree mask, maskindex;
4220 gfc_start_block (&header);
4222 forall_tmp = nested_forall_info;
4223 while (forall_tmp != NULL)
4225 /* Generate body with masks' control. */
4226 if (mask_flag)
4228 mask = forall_tmp->mask;
4229 maskindex = forall_tmp->maskindex;
4231 /* If a mask was specified make the assignment conditional. */
4232 if (mask)
4234 tmp = gfc_build_array_ref (mask, maskindex, NULL);
4235 body = build3_v (COND_EXPR, tmp, body,
4236 build_empty_stmt (input_location));
4239 body = gfc_trans_forall_loop (forall_tmp, body, mask_flag, &header);
4240 forall_tmp = forall_tmp->prev_nest;
4241 mask_flag = 1;
4244 gfc_add_expr_to_block (&header, body);
4245 return gfc_finish_block (&header);
4249 /* Allocate data for holding a temporary array. Returns either a local
4250 temporary array or a pointer variable. */
4252 static tree
4253 gfc_do_allocate (tree bytesize, tree size, tree * pdata, stmtblock_t * pblock,
4254 tree elem_type)
4256 tree tmpvar;
4257 tree type;
4258 tree tmp;
4260 if (INTEGER_CST_P (size))
4261 tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
4262 size, gfc_index_one_node);
4263 else
4264 tmp = NULL_TREE;
4266 type = build_range_type (gfc_array_index_type, gfc_index_zero_node, tmp);
4267 type = build_array_type (elem_type, type);
4268 if (gfc_can_put_var_on_stack (bytesize) && INTEGER_CST_P (size))
4270 tmpvar = gfc_create_var (type, "temp");
4271 *pdata = NULL_TREE;
4273 else
4275 tmpvar = gfc_create_var (build_pointer_type (type), "temp");
4276 *pdata = convert (pvoid_type_node, tmpvar);
4278 tmp = gfc_call_malloc (pblock, TREE_TYPE (tmpvar), bytesize);
4279 gfc_add_modify (pblock, tmpvar, tmp);
4281 return tmpvar;
4285 /* Generate codes to copy the temporary to the actual lhs. */
4287 static tree
4288 generate_loop_for_temp_to_lhs (gfc_expr *expr, tree tmp1, tree count3,
4289 tree count1,
4290 gfc_ss *lss, gfc_ss *rss,
4291 tree wheremask, bool invert)
4293 stmtblock_t block, body1;
4294 gfc_loopinfo loop;
4295 gfc_se lse;
4296 gfc_se rse;
4297 tree tmp;
4298 tree wheremaskexpr;
4300 (void) rss; /* TODO: unused. */
4302 gfc_start_block (&block);
4304 gfc_init_se (&rse, NULL);
4305 gfc_init_se (&lse, NULL);
4307 if (lss == gfc_ss_terminator)
4309 gfc_init_block (&body1);
4310 gfc_conv_expr (&lse, expr);
4311 rse.expr = gfc_build_array_ref (tmp1, count1, NULL);
4313 else
4315 /* Initialize the loop. */
4316 gfc_init_loopinfo (&loop);
4318 /* We may need LSS to determine the shape of the expression. */
4319 gfc_add_ss_to_loop (&loop, lss);
4321 gfc_conv_ss_startstride (&loop);
4322 gfc_conv_loop_setup (&loop, &expr->where);
4324 gfc_mark_ss_chain_used (lss, 1);
4325 /* Start the loop body. */
4326 gfc_start_scalarized_body (&loop, &body1);
4328 /* Translate the expression. */
4329 gfc_copy_loopinfo_to_se (&lse, &loop);
4330 lse.ss = lss;
4331 gfc_conv_expr (&lse, expr);
4333 /* Form the expression of the temporary. */
4334 rse.expr = gfc_build_array_ref (tmp1, count1, NULL);
4337 /* Use the scalar assignment. */
4338 rse.string_length = lse.string_length;
4339 tmp = gfc_trans_scalar_assign (&lse, &rse, expr->ts,
4340 expr->expr_type == EXPR_VARIABLE, false);
4342 /* Form the mask expression according to the mask tree list. */
4343 if (wheremask)
4345 wheremaskexpr = gfc_build_array_ref (wheremask, count3, NULL);
4346 if (invert)
4347 wheremaskexpr = fold_build1_loc (input_location, TRUTH_NOT_EXPR,
4348 TREE_TYPE (wheremaskexpr),
4349 wheremaskexpr);
4350 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
4351 wheremaskexpr, tmp,
4352 build_empty_stmt (input_location));
4355 gfc_add_expr_to_block (&body1, tmp);
4357 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (count1),
4358 count1, gfc_index_one_node);
4359 gfc_add_modify (&body1, count1, tmp);
4361 if (lss == gfc_ss_terminator)
4362 gfc_add_block_to_block (&block, &body1);
4363 else
4365 /* Increment count3. */
4366 if (count3)
4368 tmp = fold_build2_loc (input_location, PLUS_EXPR,
4369 gfc_array_index_type,
4370 count3, gfc_index_one_node);
4371 gfc_add_modify (&body1, count3, tmp);
4374 /* Generate the copying loops. */
4375 gfc_trans_scalarizing_loops (&loop, &body1);
4377 gfc_add_block_to_block (&block, &loop.pre);
4378 gfc_add_block_to_block (&block, &loop.post);
4380 gfc_cleanup_loop (&loop);
4381 /* TODO: Reuse lss and rss when copying temp->lhs. Need to be careful
4382 as tree nodes in SS may not be valid in different scope. */
4385 tmp = gfc_finish_block (&block);
4386 return tmp;
4390 /* Generate codes to copy rhs to the temporary. TMP1 is the address of
4391 temporary, LSS and RSS are formed in function compute_inner_temp_size(),
4392 and should not be freed. WHEREMASK is the conditional execution mask
4393 whose sense may be inverted by INVERT. */
4395 static tree
4396 generate_loop_for_rhs_to_temp (gfc_expr *expr2, tree tmp1, tree count3,
4397 tree count1, gfc_ss *lss, gfc_ss *rss,
4398 tree wheremask, bool invert)
4400 stmtblock_t block, body1;
4401 gfc_loopinfo loop;
4402 gfc_se lse;
4403 gfc_se rse;
4404 tree tmp;
4405 tree wheremaskexpr;
4407 gfc_start_block (&block);
4409 gfc_init_se (&rse, NULL);
4410 gfc_init_se (&lse, NULL);
4412 if (lss == gfc_ss_terminator)
4414 gfc_init_block (&body1);
4415 gfc_conv_expr (&rse, expr2);
4416 lse.expr = gfc_build_array_ref (tmp1, count1, NULL);
4418 else
4420 /* Initialize the loop. */
4421 gfc_init_loopinfo (&loop);
4423 /* We may need LSS to determine the shape of the expression. */
4424 gfc_add_ss_to_loop (&loop, lss);
4425 gfc_add_ss_to_loop (&loop, rss);
4427 gfc_conv_ss_startstride (&loop);
4428 gfc_conv_loop_setup (&loop, &expr2->where);
4430 gfc_mark_ss_chain_used (rss, 1);
4431 /* Start the loop body. */
4432 gfc_start_scalarized_body (&loop, &body1);
4434 /* Translate the expression. */
4435 gfc_copy_loopinfo_to_se (&rse, &loop);
4436 rse.ss = rss;
4437 gfc_conv_expr (&rse, expr2);
4439 /* Form the expression of the temporary. */
4440 lse.expr = gfc_build_array_ref (tmp1, count1, NULL);
4443 /* Use the scalar assignment. */
4444 lse.string_length = rse.string_length;
4445 tmp = gfc_trans_scalar_assign (&lse, &rse, expr2->ts,
4446 expr2->expr_type == EXPR_VARIABLE, false);
4448 /* Form the mask expression according to the mask tree list. */
4449 if (wheremask)
4451 wheremaskexpr = gfc_build_array_ref (wheremask, count3, NULL);
4452 if (invert)
4453 wheremaskexpr = fold_build1_loc (input_location, TRUTH_NOT_EXPR,
4454 TREE_TYPE (wheremaskexpr),
4455 wheremaskexpr);
4456 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
4457 wheremaskexpr, tmp,
4458 build_empty_stmt (input_location));
4461 gfc_add_expr_to_block (&body1, tmp);
4463 if (lss == gfc_ss_terminator)
4465 gfc_add_block_to_block (&block, &body1);
4467 /* Increment count1. */
4468 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (count1),
4469 count1, gfc_index_one_node);
4470 gfc_add_modify (&block, count1, tmp);
4472 else
4474 /* Increment count1. */
4475 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
4476 count1, gfc_index_one_node);
4477 gfc_add_modify (&body1, count1, tmp);
4479 /* Increment count3. */
4480 if (count3)
4482 tmp = fold_build2_loc (input_location, PLUS_EXPR,
4483 gfc_array_index_type,
4484 count3, gfc_index_one_node);
4485 gfc_add_modify (&body1, count3, tmp);
4488 /* Generate the copying loops. */
4489 gfc_trans_scalarizing_loops (&loop, &body1);
4491 gfc_add_block_to_block (&block, &loop.pre);
4492 gfc_add_block_to_block (&block, &loop.post);
4494 gfc_cleanup_loop (&loop);
4495 /* TODO: Reuse lss and rss when copying temp->lhs. Need to be careful
4496 as tree nodes in SS may not be valid in different scope. */
4499 tmp = gfc_finish_block (&block);
4500 return tmp;
4504 /* Calculate the size of temporary needed in the assignment inside forall.
4505 LSS and RSS are filled in this function. */
4507 static tree
4508 compute_inner_temp_size (gfc_expr *expr1, gfc_expr *expr2,
4509 stmtblock_t * pblock,
4510 gfc_ss **lss, gfc_ss **rss)
4512 gfc_loopinfo loop;
4513 tree size;
4514 int i;
4515 int save_flag;
4516 tree tmp;
4518 *lss = gfc_walk_expr (expr1);
4519 *rss = NULL;
4521 size = gfc_index_one_node;
4522 if (*lss != gfc_ss_terminator)
4524 gfc_init_loopinfo (&loop);
4526 /* Walk the RHS of the expression. */
4527 *rss = gfc_walk_expr (expr2);
4528 if (*rss == gfc_ss_terminator)
4529 /* The rhs is scalar. Add a ss for the expression. */
4530 *rss = gfc_get_scalar_ss (gfc_ss_terminator, expr2);
4532 /* Associate the SS with the loop. */
4533 gfc_add_ss_to_loop (&loop, *lss);
4534 /* We don't actually need to add the rhs at this point, but it might
4535 make guessing the loop bounds a bit easier. */
4536 gfc_add_ss_to_loop (&loop, *rss);
4538 /* We only want the shape of the expression, not rest of the junk
4539 generated by the scalarizer. */
4540 loop.array_parameter = 1;
4542 /* Calculate the bounds of the scalarization. */
4543 save_flag = gfc_option.rtcheck;
4544 gfc_option.rtcheck &= ~GFC_RTCHECK_BOUNDS;
4545 gfc_conv_ss_startstride (&loop);
4546 gfc_option.rtcheck = save_flag;
4547 gfc_conv_loop_setup (&loop, &expr2->where);
4549 /* Figure out how many elements we need. */
4550 for (i = 0; i < loop.dimen; i++)
4552 tmp = fold_build2_loc (input_location, MINUS_EXPR,
4553 gfc_array_index_type,
4554 gfc_index_one_node, loop.from[i]);
4555 tmp = fold_build2_loc (input_location, PLUS_EXPR,
4556 gfc_array_index_type, tmp, loop.to[i]);
4557 size = fold_build2_loc (input_location, MULT_EXPR,
4558 gfc_array_index_type, size, tmp);
4560 gfc_add_block_to_block (pblock, &loop.pre);
4561 size = gfc_evaluate_now (size, pblock);
4562 gfc_add_block_to_block (pblock, &loop.post);
4564 /* TODO: write a function that cleans up a loopinfo without freeing
4565 the SS chains. Currently a NOP. */
4568 return size;
4572 /* Calculate the overall iterator number of the nested forall construct.
4573 This routine actually calculates the number of times the body of the
4574 nested forall specified by NESTED_FORALL_INFO is executed and multiplies
4575 that by the expression INNER_SIZE. The BLOCK argument specifies the
4576 block in which to calculate the result, and the optional INNER_SIZE_BODY
4577 argument contains any statements that need to executed (inside the loop)
4578 to initialize or calculate INNER_SIZE. */
4580 static tree
4581 compute_overall_iter_number (forall_info *nested_forall_info, tree inner_size,
4582 stmtblock_t *inner_size_body, stmtblock_t *block)
4584 forall_info *forall_tmp = nested_forall_info;
4585 tree tmp, number;
4586 stmtblock_t body;
4588 /* We can eliminate the innermost unconditional loops with constant
4589 array bounds. */
4590 if (INTEGER_CST_P (inner_size))
4592 while (forall_tmp
4593 && !forall_tmp->mask
4594 && INTEGER_CST_P (forall_tmp->size))
4596 inner_size = fold_build2_loc (input_location, MULT_EXPR,
4597 gfc_array_index_type,
4598 inner_size, forall_tmp->size);
4599 forall_tmp = forall_tmp->prev_nest;
4602 /* If there are no loops left, we have our constant result. */
4603 if (!forall_tmp)
4604 return inner_size;
4607 /* Otherwise, create a temporary variable to compute the result. */
4608 number = gfc_create_var (gfc_array_index_type, "num");
4609 gfc_add_modify (block, number, gfc_index_zero_node);
4611 gfc_start_block (&body);
4612 if (inner_size_body)
4613 gfc_add_block_to_block (&body, inner_size_body);
4614 if (forall_tmp)
4615 tmp = fold_build2_loc (input_location, PLUS_EXPR,
4616 gfc_array_index_type, number, inner_size);
4617 else
4618 tmp = inner_size;
4619 gfc_add_modify (&body, number, tmp);
4620 tmp = gfc_finish_block (&body);
4622 /* Generate loops. */
4623 if (forall_tmp != NULL)
4624 tmp = gfc_trans_nested_forall_loop (forall_tmp, tmp, 1);
4626 gfc_add_expr_to_block (block, tmp);
4628 return number;
4632 /* Allocate temporary for forall construct. SIZE is the size of temporary
4633 needed. PTEMP1 is returned for space free. */
4635 static tree
4636 allocate_temp_for_forall_nest_1 (tree type, tree size, stmtblock_t * block,
4637 tree * ptemp1)
4639 tree bytesize;
4640 tree unit;
4641 tree tmp;
4643 unit = fold_convert (gfc_array_index_type, TYPE_SIZE_UNIT (type));
4644 if (!integer_onep (unit))
4645 bytesize = fold_build2_loc (input_location, MULT_EXPR,
4646 gfc_array_index_type, size, unit);
4647 else
4648 bytesize = size;
4650 *ptemp1 = NULL;
4651 tmp = gfc_do_allocate (bytesize, size, ptemp1, block, type);
4653 if (*ptemp1)
4654 tmp = build_fold_indirect_ref_loc (input_location, tmp);
4655 return tmp;
4659 /* Allocate temporary for forall construct according to the information in
4660 nested_forall_info. INNER_SIZE is the size of temporary needed in the
4661 assignment inside forall. PTEMP1 is returned for space free. */
4663 static tree
4664 allocate_temp_for_forall_nest (forall_info * nested_forall_info, tree type,
4665 tree inner_size, stmtblock_t * inner_size_body,
4666 stmtblock_t * block, tree * ptemp1)
4668 tree size;
4670 /* Calculate the total size of temporary needed in forall construct. */
4671 size = compute_overall_iter_number (nested_forall_info, inner_size,
4672 inner_size_body, block);
4674 return allocate_temp_for_forall_nest_1 (type, size, block, ptemp1);
4678 /* Handle assignments inside forall which need temporary.
4680 forall (i=start:end:stride; maskexpr)
4681 e<i> = f<i>
4682 end forall
4683 (where e,f<i> are arbitrary expressions possibly involving i
4684 and there is a dependency between e<i> and f<i>)
4685 Translates to:
4686 masktmp(:) = maskexpr(:)
4688 maskindex = 0;
4689 count1 = 0;
4690 num = 0;
4691 for (i = start; i <= end; i += stride)
4692 num += SIZE (f<i>)
4693 count1 = 0;
4694 ALLOCATE (tmp(num))
4695 for (i = start; i <= end; i += stride)
4697 if (masktmp[maskindex++])
4698 tmp[count1++] = f<i>
4700 maskindex = 0;
4701 count1 = 0;
4702 for (i = start; i <= end; i += stride)
4704 if (masktmp[maskindex++])
4705 e<i> = tmp[count1++]
4707 DEALLOCATE (tmp)
4709 static void
4710 gfc_trans_assign_need_temp (gfc_expr * expr1, gfc_expr * expr2,
4711 tree wheremask, bool invert,
4712 forall_info * nested_forall_info,
4713 stmtblock_t * block)
4715 tree type;
4716 tree inner_size;
4717 gfc_ss *lss, *rss;
4718 tree count, count1;
4719 tree tmp, tmp1;
4720 tree ptemp1;
4721 stmtblock_t inner_size_body;
4723 /* Create vars. count1 is the current iterator number of the nested
4724 forall. */
4725 count1 = gfc_create_var (gfc_array_index_type, "count1");
4727 /* Count is the wheremask index. */
4728 if (wheremask)
4730 count = gfc_create_var (gfc_array_index_type, "count");
4731 gfc_add_modify (block, count, gfc_index_zero_node);
4733 else
4734 count = NULL;
4736 /* Initialize count1. */
4737 gfc_add_modify (block, count1, gfc_index_zero_node);
4739 /* Calculate the size of temporary needed in the assignment. Return loop, lss
4740 and rss which are used in function generate_loop_for_rhs_to_temp(). */
4741 /* The type of LHS. Used in function allocate_temp_for_forall_nest */
4742 if (expr1->ts.type == BT_CHARACTER)
4744 type = NULL;
4745 if (expr1->ref && expr1->ref->type == REF_SUBSTRING)
4747 gfc_se ssse;
4748 gfc_init_se (&ssse, NULL);
4749 gfc_conv_expr (&ssse, expr1);
4750 type = gfc_get_character_type_len (gfc_default_character_kind,
4751 ssse.string_length);
4753 else
4755 if (!expr1->ts.u.cl->backend_decl)
4757 gfc_se tse;
4758 gcc_assert (expr1->ts.u.cl->length);
4759 gfc_init_se (&tse, NULL);
4760 gfc_conv_expr (&tse, expr1->ts.u.cl->length);
4761 expr1->ts.u.cl->backend_decl = tse.expr;
4763 type = gfc_get_character_type_len (gfc_default_character_kind,
4764 expr1->ts.u.cl->backend_decl);
4767 else
4768 type = gfc_typenode_for_spec (&expr1->ts);
4770 gfc_init_block (&inner_size_body);
4771 inner_size = compute_inner_temp_size (expr1, expr2, &inner_size_body,
4772 &lss, &rss);
4774 /* Allocate temporary for nested forall construct according to the
4775 information in nested_forall_info and inner_size. */
4776 tmp1 = allocate_temp_for_forall_nest (nested_forall_info, type, inner_size,
4777 &inner_size_body, block, &ptemp1);
4779 /* Generate codes to copy rhs to the temporary . */
4780 tmp = generate_loop_for_rhs_to_temp (expr2, tmp1, count, count1, lss, rss,
4781 wheremask, invert);
4783 /* Generate body and loops according to the information in
4784 nested_forall_info. */
4785 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
4786 gfc_add_expr_to_block (block, tmp);
4788 /* Reset count1. */
4789 gfc_add_modify (block, count1, gfc_index_zero_node);
4791 /* Reset count. */
4792 if (wheremask)
4793 gfc_add_modify (block, count, gfc_index_zero_node);
4795 /* TODO: Second call to compute_inner_temp_size to initialize lss and
4796 rss; there must be a better way. */
4797 inner_size = compute_inner_temp_size (expr1, expr2, &inner_size_body,
4798 &lss, &rss);
4800 /* Generate codes to copy the temporary to lhs. */
4801 tmp = generate_loop_for_temp_to_lhs (expr1, tmp1, count, count1,
4802 lss, rss,
4803 wheremask, invert);
4805 /* Generate body and loops according to the information in
4806 nested_forall_info. */
4807 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
4808 gfc_add_expr_to_block (block, tmp);
4810 if (ptemp1)
4812 /* Free the temporary. */
4813 tmp = gfc_call_free (ptemp1);
4814 gfc_add_expr_to_block (block, tmp);
4819 /* Translate pointer assignment inside FORALL which need temporary. */
4821 static void
4822 gfc_trans_pointer_assign_need_temp (gfc_expr * expr1, gfc_expr * expr2,
4823 forall_info * nested_forall_info,
4824 stmtblock_t * block)
4826 tree type;
4827 tree inner_size;
4828 gfc_ss *lss, *rss;
4829 gfc_se lse;
4830 gfc_se rse;
4831 gfc_array_info *info;
4832 gfc_loopinfo loop;
4833 tree desc;
4834 tree parm;
4835 tree parmtype;
4836 stmtblock_t body;
4837 tree count;
4838 tree tmp, tmp1, ptemp1;
4840 count = gfc_create_var (gfc_array_index_type, "count");
4841 gfc_add_modify (block, count, gfc_index_zero_node);
4843 inner_size = gfc_index_one_node;
4844 lss = gfc_walk_expr (expr1);
4845 rss = gfc_walk_expr (expr2);
4846 if (lss == gfc_ss_terminator)
4848 type = gfc_typenode_for_spec (&expr1->ts);
4849 type = build_pointer_type (type);
4851 /* Allocate temporary for nested forall construct according to the
4852 information in nested_forall_info and inner_size. */
4853 tmp1 = allocate_temp_for_forall_nest (nested_forall_info, type,
4854 inner_size, NULL, block, &ptemp1);
4855 gfc_start_block (&body);
4856 gfc_init_se (&lse, NULL);
4857 lse.expr = gfc_build_array_ref (tmp1, count, NULL);
4858 gfc_init_se (&rse, NULL);
4859 rse.want_pointer = 1;
4860 gfc_conv_expr (&rse, expr2);
4861 gfc_add_block_to_block (&body, &rse.pre);
4862 gfc_add_modify (&body, lse.expr,
4863 fold_convert (TREE_TYPE (lse.expr), rse.expr));
4864 gfc_add_block_to_block (&body, &rse.post);
4866 /* Increment count. */
4867 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
4868 count, gfc_index_one_node);
4869 gfc_add_modify (&body, count, tmp);
4871 tmp = gfc_finish_block (&body);
4873 /* Generate body and loops according to the information in
4874 nested_forall_info. */
4875 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
4876 gfc_add_expr_to_block (block, tmp);
4878 /* Reset count. */
4879 gfc_add_modify (block, count, gfc_index_zero_node);
4881 gfc_start_block (&body);
4882 gfc_init_se (&lse, NULL);
4883 gfc_init_se (&rse, NULL);
4884 rse.expr = gfc_build_array_ref (tmp1, count, NULL);
4885 lse.want_pointer = 1;
4886 gfc_conv_expr (&lse, expr1);
4887 gfc_add_block_to_block (&body, &lse.pre);
4888 gfc_add_modify (&body, lse.expr, rse.expr);
4889 gfc_add_block_to_block (&body, &lse.post);
4890 /* Increment count. */
4891 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
4892 count, gfc_index_one_node);
4893 gfc_add_modify (&body, count, tmp);
4894 tmp = gfc_finish_block (&body);
4896 /* Generate body and loops according to the information in
4897 nested_forall_info. */
4898 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
4899 gfc_add_expr_to_block (block, tmp);
4901 else
4903 gfc_init_loopinfo (&loop);
4905 /* Associate the SS with the loop. */
4906 gfc_add_ss_to_loop (&loop, rss);
4908 /* Setup the scalarizing loops and bounds. */
4909 gfc_conv_ss_startstride (&loop);
4911 gfc_conv_loop_setup (&loop, &expr2->where);
4913 info = &rss->info->data.array;
4914 desc = info->descriptor;
4916 /* Make a new descriptor. */
4917 parmtype = gfc_get_element_type (TREE_TYPE (desc));
4918 parmtype = gfc_get_array_type_bounds (parmtype, loop.dimen, 0,
4919 loop.from, loop.to, 1,
4920 GFC_ARRAY_UNKNOWN, true);
4922 /* Allocate temporary for nested forall construct. */
4923 tmp1 = allocate_temp_for_forall_nest (nested_forall_info, parmtype,
4924 inner_size, NULL, block, &ptemp1);
4925 gfc_start_block (&body);
4926 gfc_init_se (&lse, NULL);
4927 lse.expr = gfc_build_array_ref (tmp1, count, NULL);
4928 lse.direct_byref = 1;
4929 gfc_conv_expr_descriptor (&lse, expr2);
4931 gfc_add_block_to_block (&body, &lse.pre);
4932 gfc_add_block_to_block (&body, &lse.post);
4934 /* Increment count. */
4935 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
4936 count, gfc_index_one_node);
4937 gfc_add_modify (&body, count, tmp);
4939 tmp = gfc_finish_block (&body);
4941 /* Generate body and loops according to the information in
4942 nested_forall_info. */
4943 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
4944 gfc_add_expr_to_block (block, tmp);
4946 /* Reset count. */
4947 gfc_add_modify (block, count, gfc_index_zero_node);
4949 parm = gfc_build_array_ref (tmp1, count, NULL);
4950 gfc_init_se (&lse, NULL);
4951 gfc_conv_expr_descriptor (&lse, expr1);
4952 gfc_add_modify (&lse.pre, lse.expr, parm);
4953 gfc_start_block (&body);
4954 gfc_add_block_to_block (&body, &lse.pre);
4955 gfc_add_block_to_block (&body, &lse.post);
4957 /* Increment count. */
4958 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
4959 count, gfc_index_one_node);
4960 gfc_add_modify (&body, count, tmp);
4962 tmp = gfc_finish_block (&body);
4964 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
4965 gfc_add_expr_to_block (block, tmp);
4967 /* Free the temporary. */
4968 if (ptemp1)
4970 tmp = gfc_call_free (ptemp1);
4971 gfc_add_expr_to_block (block, tmp);
4976 /* FORALL and WHERE statements are really nasty, especially when you nest
4977 them. All the rhs of a forall assignment must be evaluated before the
4978 actual assignments are performed. Presumably this also applies to all the
4979 assignments in an inner where statement. */
4981 /* Generate code for a FORALL statement. Any temporaries are allocated as a
4982 linear array, relying on the fact that we process in the same order in all
4983 loops.
4985 forall (i=start:end:stride; maskexpr)
4986 e<i> = f<i>
4987 g<i> = h<i>
4988 end forall
4989 (where e,f,g,h<i> are arbitrary expressions possibly involving i)
4990 Translates to:
4991 count = ((end + 1 - start) / stride)
4992 masktmp(:) = maskexpr(:)
4994 maskindex = 0;
4995 for (i = start; i <= end; i += stride)
4997 if (masktmp[maskindex++])
4998 e<i> = f<i>
5000 maskindex = 0;
5001 for (i = start; i <= end; i += stride)
5003 if (masktmp[maskindex++])
5004 g<i> = h<i>
5007 Note that this code only works when there are no dependencies.
5008 Forall loop with array assignments and data dependencies are a real pain,
5009 because the size of the temporary cannot always be determined before the
5010 loop is executed. This problem is compounded by the presence of nested
5011 FORALL constructs.
5014 static tree
5015 gfc_trans_forall_1 (gfc_code * code, forall_info * nested_forall_info)
5017 stmtblock_t pre;
5018 stmtblock_t post;
5019 stmtblock_t block;
5020 stmtblock_t body;
5021 tree *var;
5022 tree *start;
5023 tree *end;
5024 tree *step;
5025 gfc_expr **varexpr;
5026 tree tmp;
5027 tree assign;
5028 tree size;
5029 tree maskindex;
5030 tree mask;
5031 tree pmask;
5032 tree cycle_label = NULL_TREE;
5033 int n;
5034 int nvar;
5035 int need_temp;
5036 gfc_forall_iterator *fa;
5037 gfc_se se;
5038 gfc_code *c;
5039 gfc_saved_var *saved_vars;
5040 iter_info *this_forall;
5041 forall_info *info;
5042 bool need_mask;
5044 /* Do nothing if the mask is false. */
5045 if (code->expr1
5046 && code->expr1->expr_type == EXPR_CONSTANT
5047 && !code->expr1->value.logical)
5048 return build_empty_stmt (input_location);
5050 n = 0;
5051 /* Count the FORALL index number. */
5052 for (fa = code->ext.forall_iterator; fa; fa = fa->next)
5053 n++;
5054 nvar = n;
5056 /* Allocate the space for var, start, end, step, varexpr. */
5057 var = XCNEWVEC (tree, nvar);
5058 start = XCNEWVEC (tree, nvar);
5059 end = XCNEWVEC (tree, nvar);
5060 step = XCNEWVEC (tree, nvar);
5061 varexpr = XCNEWVEC (gfc_expr *, nvar);
5062 saved_vars = XCNEWVEC (gfc_saved_var, nvar);
5064 /* Allocate the space for info. */
5065 info = XCNEW (forall_info);
5067 gfc_start_block (&pre);
5068 gfc_init_block (&post);
5069 gfc_init_block (&block);
5071 n = 0;
5072 for (fa = code->ext.forall_iterator; fa; fa = fa->next)
5074 gfc_symbol *sym = fa->var->symtree->n.sym;
5076 /* Allocate space for this_forall. */
5077 this_forall = XCNEW (iter_info);
5079 /* Create a temporary variable for the FORALL index. */
5080 tmp = gfc_typenode_for_spec (&sym->ts);
5081 var[n] = gfc_create_var (tmp, sym->name);
5082 gfc_shadow_sym (sym, var[n], &saved_vars[n]);
5084 /* Record it in this_forall. */
5085 this_forall->var = var[n];
5087 /* Replace the index symbol's backend_decl with the temporary decl. */
5088 sym->backend_decl = var[n];
5090 /* Work out the start, end and stride for the loop. */
5091 gfc_init_se (&se, NULL);
5092 gfc_conv_expr_val (&se, fa->start);
5093 /* Record it in this_forall. */
5094 this_forall->start = se.expr;
5095 gfc_add_block_to_block (&block, &se.pre);
5096 start[n] = se.expr;
5098 gfc_init_se (&se, NULL);
5099 gfc_conv_expr_val (&se, fa->end);
5100 /* Record it in this_forall. */
5101 this_forall->end = se.expr;
5102 gfc_make_safe_expr (&se);
5103 gfc_add_block_to_block (&block, &se.pre);
5104 end[n] = se.expr;
5106 gfc_init_se (&se, NULL);
5107 gfc_conv_expr_val (&se, fa->stride);
5108 /* Record it in this_forall. */
5109 this_forall->step = se.expr;
5110 gfc_make_safe_expr (&se);
5111 gfc_add_block_to_block (&block, &se.pre);
5112 step[n] = se.expr;
5114 /* Copy loop annotations. */
5115 this_forall->annot = fa->annot;
5117 /* Set the NEXT field of this_forall to NULL. */
5118 this_forall->next = NULL;
5119 /* Link this_forall to the info construct. */
5120 if (info->this_loop)
5122 iter_info *iter_tmp = info->this_loop;
5123 while (iter_tmp->next != NULL)
5124 iter_tmp = iter_tmp->next;
5125 iter_tmp->next = this_forall;
5127 else
5128 info->this_loop = this_forall;
5130 n++;
5132 nvar = n;
5134 /* Calculate the size needed for the current forall level. */
5135 size = gfc_index_one_node;
5136 for (n = 0; n < nvar; n++)
5138 /* size = (end + step - start) / step. */
5139 tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (start[n]),
5140 step[n], start[n]);
5141 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (end[n]),
5142 end[n], tmp);
5143 tmp = fold_build2_loc (input_location, FLOOR_DIV_EXPR, TREE_TYPE (tmp),
5144 tmp, step[n]);
5145 tmp = convert (gfc_array_index_type, tmp);
5147 size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
5148 size, tmp);
5151 /* Record the nvar and size of current forall level. */
5152 info->nvar = nvar;
5153 info->size = size;
5155 if (code->expr1)
5157 /* If the mask is .true., consider the FORALL unconditional. */
5158 if (code->expr1->expr_type == EXPR_CONSTANT
5159 && code->expr1->value.logical)
5160 need_mask = false;
5161 else
5162 need_mask = true;
5164 else
5165 need_mask = false;
5167 /* First we need to allocate the mask. */
5168 if (need_mask)
5170 /* As the mask array can be very big, prefer compact boolean types. */
5171 tree mask_type = gfc_get_logical_type (gfc_logical_kinds[0].kind);
5172 mask = allocate_temp_for_forall_nest (nested_forall_info, mask_type,
5173 size, NULL, &block, &pmask);
5174 maskindex = gfc_create_var_np (gfc_array_index_type, "mi");
5176 /* Record them in the info structure. */
5177 info->maskindex = maskindex;
5178 info->mask = mask;
5180 else
5182 /* No mask was specified. */
5183 maskindex = NULL_TREE;
5184 mask = pmask = NULL_TREE;
5187 /* Link the current forall level to nested_forall_info. */
5188 info->prev_nest = nested_forall_info;
5189 nested_forall_info = info;
5191 /* Copy the mask into a temporary variable if required.
5192 For now we assume a mask temporary is needed. */
5193 if (need_mask)
5195 /* As the mask array can be very big, prefer compact boolean types. */
5196 tree mask_type = gfc_get_logical_type (gfc_logical_kinds[0].kind);
5198 gfc_add_modify (&block, maskindex, gfc_index_zero_node);
5200 /* Start of mask assignment loop body. */
5201 gfc_start_block (&body);
5203 /* Evaluate the mask expression. */
5204 gfc_init_se (&se, NULL);
5205 gfc_conv_expr_val (&se, code->expr1);
5206 gfc_add_block_to_block (&body, &se.pre);
5208 /* Store the mask. */
5209 se.expr = convert (mask_type, se.expr);
5211 tmp = gfc_build_array_ref (mask, maskindex, NULL);
5212 gfc_add_modify (&body, tmp, se.expr);
5214 /* Advance to the next mask element. */
5215 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
5216 maskindex, gfc_index_one_node);
5217 gfc_add_modify (&body, maskindex, tmp);
5219 /* Generate the loops. */
5220 tmp = gfc_finish_block (&body);
5221 tmp = gfc_trans_nested_forall_loop (info, tmp, 0);
5222 gfc_add_expr_to_block (&block, tmp);
5225 if (code->op == EXEC_DO_CONCURRENT)
5227 gfc_init_block (&body);
5228 cycle_label = gfc_build_label_decl (NULL_TREE);
5229 code->cycle_label = cycle_label;
5230 tmp = gfc_trans_code (code->block->next);
5231 gfc_add_expr_to_block (&body, tmp);
5233 if (TREE_USED (cycle_label))
5235 tmp = build1_v (LABEL_EXPR, cycle_label);
5236 gfc_add_expr_to_block (&body, tmp);
5239 tmp = gfc_finish_block (&body);
5240 nested_forall_info->do_concurrent = true;
5241 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
5242 gfc_add_expr_to_block (&block, tmp);
5243 goto done;
5246 c = code->block->next;
5248 /* TODO: loop merging in FORALL statements. */
5249 /* Now that we've got a copy of the mask, generate the assignment loops. */
5250 while (c)
5252 switch (c->op)
5254 case EXEC_ASSIGN:
5255 /* A scalar or array assignment. DO the simple check for
5256 lhs to rhs dependencies. These make a temporary for the
5257 rhs and form a second forall block to copy to variable. */
5258 need_temp = check_forall_dependencies(c, &pre, &post);
5260 /* Temporaries due to array assignment data dependencies introduce
5261 no end of problems. */
5262 if (need_temp || flag_test_forall_temp)
5263 gfc_trans_assign_need_temp (c->expr1, c->expr2, NULL, false,
5264 nested_forall_info, &block);
5265 else
5267 /* Use the normal assignment copying routines. */
5268 assign = gfc_trans_assignment (c->expr1, c->expr2, false, true);
5270 /* Generate body and loops. */
5271 tmp = gfc_trans_nested_forall_loop (nested_forall_info,
5272 assign, 1);
5273 gfc_add_expr_to_block (&block, tmp);
5276 /* Cleanup any temporary symtrees that have been made to deal
5277 with dependencies. */
5278 if (new_symtree)
5279 cleanup_forall_symtrees (c);
5281 break;
5283 case EXEC_WHERE:
5284 /* Translate WHERE or WHERE construct nested in FORALL. */
5285 gfc_trans_where_2 (c, NULL, false, nested_forall_info, &block);
5286 break;
5288 /* Pointer assignment inside FORALL. */
5289 case EXEC_POINTER_ASSIGN:
5290 need_temp = gfc_check_dependency (c->expr1, c->expr2, 0);
5291 /* Avoid cases where a temporary would never be needed and where
5292 the temp code is guaranteed to fail. */
5293 if (need_temp
5294 || (flag_test_forall_temp
5295 && c->expr2->expr_type != EXPR_CONSTANT
5296 && c->expr2->expr_type != EXPR_NULL))
5297 gfc_trans_pointer_assign_need_temp (c->expr1, c->expr2,
5298 nested_forall_info, &block);
5299 else
5301 /* Use the normal assignment copying routines. */
5302 assign = gfc_trans_pointer_assignment (c->expr1, c->expr2);
5304 /* Generate body and loops. */
5305 tmp = gfc_trans_nested_forall_loop (nested_forall_info,
5306 assign, 1);
5307 gfc_add_expr_to_block (&block, tmp);
5309 break;
5311 case EXEC_FORALL:
5312 tmp = gfc_trans_forall_1 (c, nested_forall_info);
5313 gfc_add_expr_to_block (&block, tmp);
5314 break;
5316 /* Explicit subroutine calls are prevented by the frontend but interface
5317 assignments can legitimately produce them. */
5318 case EXEC_ASSIGN_CALL:
5319 assign = gfc_trans_call (c, true, NULL_TREE, NULL_TREE, false);
5320 tmp = gfc_trans_nested_forall_loop (nested_forall_info, assign, 1);
5321 gfc_add_expr_to_block (&block, tmp);
5322 break;
5324 default:
5325 gcc_unreachable ();
5328 c = c->next;
5331 done:
5332 /* Restore the original index variables. */
5333 for (fa = code->ext.forall_iterator, n = 0; fa; fa = fa->next, n++)
5334 gfc_restore_sym (fa->var->symtree->n.sym, &saved_vars[n]);
5336 /* Free the space for var, start, end, step, varexpr. */
5337 free (var);
5338 free (start);
5339 free (end);
5340 free (step);
5341 free (varexpr);
5342 free (saved_vars);
5344 for (this_forall = info->this_loop; this_forall;)
5346 iter_info *next = this_forall->next;
5347 free (this_forall);
5348 this_forall = next;
5351 /* Free the space for this forall_info. */
5352 free (info);
5354 if (pmask)
5356 /* Free the temporary for the mask. */
5357 tmp = gfc_call_free (pmask);
5358 gfc_add_expr_to_block (&block, tmp);
5360 if (maskindex)
5361 pushdecl (maskindex);
5363 gfc_add_block_to_block (&pre, &block);
5364 gfc_add_block_to_block (&pre, &post);
5366 return gfc_finish_block (&pre);
5370 /* Translate the FORALL statement or construct. */
5372 tree gfc_trans_forall (gfc_code * code)
5374 return gfc_trans_forall_1 (code, NULL);
5378 /* Translate the DO CONCURRENT construct. */
5380 tree gfc_trans_do_concurrent (gfc_code * code)
5382 return gfc_trans_forall_1 (code, NULL);
5386 /* Evaluate the WHERE mask expression, copy its value to a temporary.
5387 If the WHERE construct is nested in FORALL, compute the overall temporary
5388 needed by the WHERE mask expression multiplied by the iterator number of
5389 the nested forall.
5390 ME is the WHERE mask expression.
5391 MASK is the current execution mask upon input, whose sense may or may
5392 not be inverted as specified by the INVERT argument.
5393 CMASK is the updated execution mask on output, or NULL if not required.
5394 PMASK is the pending execution mask on output, or NULL if not required.
5395 BLOCK is the block in which to place the condition evaluation loops. */
5397 static void
5398 gfc_evaluate_where_mask (gfc_expr * me, forall_info * nested_forall_info,
5399 tree mask, bool invert, tree cmask, tree pmask,
5400 tree mask_type, stmtblock_t * block)
5402 tree tmp, tmp1;
5403 gfc_ss *lss, *rss;
5404 gfc_loopinfo loop;
5405 stmtblock_t body, body1;
5406 tree count, cond, mtmp;
5407 gfc_se lse, rse;
5409 gfc_init_loopinfo (&loop);
5411 lss = gfc_walk_expr (me);
5412 rss = gfc_walk_expr (me);
5414 /* Variable to index the temporary. */
5415 count = gfc_create_var (gfc_array_index_type, "count");
5416 /* Initialize count. */
5417 gfc_add_modify (block, count, gfc_index_zero_node);
5419 gfc_start_block (&body);
5421 gfc_init_se (&rse, NULL);
5422 gfc_init_se (&lse, NULL);
5424 if (lss == gfc_ss_terminator)
5426 gfc_init_block (&body1);
5428 else
5430 /* Initialize the loop. */
5431 gfc_init_loopinfo (&loop);
5433 /* We may need LSS to determine the shape of the expression. */
5434 gfc_add_ss_to_loop (&loop, lss);
5435 gfc_add_ss_to_loop (&loop, rss);
5437 gfc_conv_ss_startstride (&loop);
5438 gfc_conv_loop_setup (&loop, &me->where);
5440 gfc_mark_ss_chain_used (rss, 1);
5441 /* Start the loop body. */
5442 gfc_start_scalarized_body (&loop, &body1);
5444 /* Translate the expression. */
5445 gfc_copy_loopinfo_to_se (&rse, &loop);
5446 rse.ss = rss;
5447 gfc_conv_expr (&rse, me);
5450 /* Variable to evaluate mask condition. */
5451 cond = gfc_create_var (mask_type, "cond");
5452 if (mask && (cmask || pmask))
5453 mtmp = gfc_create_var (mask_type, "mask");
5454 else mtmp = NULL_TREE;
5456 gfc_add_block_to_block (&body1, &lse.pre);
5457 gfc_add_block_to_block (&body1, &rse.pre);
5459 gfc_add_modify (&body1, cond, fold_convert (mask_type, rse.expr));
5461 if (mask && (cmask || pmask))
5463 tmp = gfc_build_array_ref (mask, count, NULL);
5464 if (invert)
5465 tmp = fold_build1_loc (input_location, TRUTH_NOT_EXPR, mask_type, tmp);
5466 gfc_add_modify (&body1, mtmp, tmp);
5469 if (cmask)
5471 tmp1 = gfc_build_array_ref (cmask, count, NULL);
5472 tmp = cond;
5473 if (mask)
5474 tmp = fold_build2_loc (input_location, TRUTH_AND_EXPR, mask_type,
5475 mtmp, tmp);
5476 gfc_add_modify (&body1, tmp1, tmp);
5479 if (pmask)
5481 tmp1 = gfc_build_array_ref (pmask, count, NULL);
5482 tmp = fold_build1_loc (input_location, TRUTH_NOT_EXPR, mask_type, cond);
5483 if (mask)
5484 tmp = fold_build2_loc (input_location, TRUTH_AND_EXPR, mask_type, mtmp,
5485 tmp);
5486 gfc_add_modify (&body1, tmp1, tmp);
5489 gfc_add_block_to_block (&body1, &lse.post);
5490 gfc_add_block_to_block (&body1, &rse.post);
5492 if (lss == gfc_ss_terminator)
5494 gfc_add_block_to_block (&body, &body1);
5496 else
5498 /* Increment count. */
5499 tmp1 = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
5500 count, gfc_index_one_node);
5501 gfc_add_modify (&body1, count, tmp1);
5503 /* Generate the copying loops. */
5504 gfc_trans_scalarizing_loops (&loop, &body1);
5506 gfc_add_block_to_block (&body, &loop.pre);
5507 gfc_add_block_to_block (&body, &loop.post);
5509 gfc_cleanup_loop (&loop);
5510 /* TODO: Reuse lss and rss when copying temp->lhs. Need to be careful
5511 as tree nodes in SS may not be valid in different scope. */
5514 tmp1 = gfc_finish_block (&body);
5515 /* If the WHERE construct is inside FORALL, fill the full temporary. */
5516 if (nested_forall_info != NULL)
5517 tmp1 = gfc_trans_nested_forall_loop (nested_forall_info, tmp1, 1);
5519 gfc_add_expr_to_block (block, tmp1);
5523 /* Translate an assignment statement in a WHERE statement or construct
5524 statement. The MASK expression is used to control which elements
5525 of EXPR1 shall be assigned. The sense of MASK is specified by
5526 INVERT. */
5528 static tree
5529 gfc_trans_where_assign (gfc_expr *expr1, gfc_expr *expr2,
5530 tree mask, bool invert,
5531 tree count1, tree count2,
5532 gfc_code *cnext)
5534 gfc_se lse;
5535 gfc_se rse;
5536 gfc_ss *lss;
5537 gfc_ss *lss_section;
5538 gfc_ss *rss;
5540 gfc_loopinfo loop;
5541 tree tmp;
5542 stmtblock_t block;
5543 stmtblock_t body;
5544 tree index, maskexpr;
5546 /* A defined assignment. */
5547 if (cnext && cnext->resolved_sym)
5548 return gfc_trans_call (cnext, true, mask, count1, invert);
5550 #if 0
5551 /* TODO: handle this special case.
5552 Special case a single function returning an array. */
5553 if (expr2->expr_type == EXPR_FUNCTION && expr2->rank > 0)
5555 tmp = gfc_trans_arrayfunc_assign (expr1, expr2);
5556 if (tmp)
5557 return tmp;
5559 #endif
5561 /* Assignment of the form lhs = rhs. */
5562 gfc_start_block (&block);
5564 gfc_init_se (&lse, NULL);
5565 gfc_init_se (&rse, NULL);
5567 /* Walk the lhs. */
5568 lss = gfc_walk_expr (expr1);
5569 rss = NULL;
5571 /* In each where-assign-stmt, the mask-expr and the variable being
5572 defined shall be arrays of the same shape. */
5573 gcc_assert (lss != gfc_ss_terminator);
5575 /* The assignment needs scalarization. */
5576 lss_section = lss;
5578 /* Find a non-scalar SS from the lhs. */
5579 while (lss_section != gfc_ss_terminator
5580 && lss_section->info->type != GFC_SS_SECTION)
5581 lss_section = lss_section->next;
5583 gcc_assert (lss_section != gfc_ss_terminator);
5585 /* Initialize the scalarizer. */
5586 gfc_init_loopinfo (&loop);
5588 /* Walk the rhs. */
5589 rss = gfc_walk_expr (expr2);
5590 if (rss == gfc_ss_terminator)
5592 /* The rhs is scalar. Add a ss for the expression. */
5593 rss = gfc_get_scalar_ss (gfc_ss_terminator, expr2);
5594 rss->info->where = 1;
5597 /* Associate the SS with the loop. */
5598 gfc_add_ss_to_loop (&loop, lss);
5599 gfc_add_ss_to_loop (&loop, rss);
5601 /* Calculate the bounds of the scalarization. */
5602 gfc_conv_ss_startstride (&loop);
5604 /* Resolve any data dependencies in the statement. */
5605 gfc_conv_resolve_dependencies (&loop, lss_section, rss);
5607 /* Setup the scalarizing loops. */
5608 gfc_conv_loop_setup (&loop, &expr2->where);
5610 /* Setup the gfc_se structures. */
5611 gfc_copy_loopinfo_to_se (&lse, &loop);
5612 gfc_copy_loopinfo_to_se (&rse, &loop);
5614 rse.ss = rss;
5615 gfc_mark_ss_chain_used (rss, 1);
5616 if (loop.temp_ss == NULL)
5618 lse.ss = lss;
5619 gfc_mark_ss_chain_used (lss, 1);
5621 else
5623 lse.ss = loop.temp_ss;
5624 gfc_mark_ss_chain_used (lss, 3);
5625 gfc_mark_ss_chain_used (loop.temp_ss, 3);
5628 /* Start the scalarized loop body. */
5629 gfc_start_scalarized_body (&loop, &body);
5631 /* Translate the expression. */
5632 gfc_conv_expr (&rse, expr2);
5633 if (lss != gfc_ss_terminator && loop.temp_ss != NULL)
5634 gfc_conv_tmp_array_ref (&lse);
5635 else
5636 gfc_conv_expr (&lse, expr1);
5638 /* Form the mask expression according to the mask. */
5639 index = count1;
5640 maskexpr = gfc_build_array_ref (mask, index, NULL);
5641 if (invert)
5642 maskexpr = fold_build1_loc (input_location, TRUTH_NOT_EXPR,
5643 TREE_TYPE (maskexpr), maskexpr);
5645 /* Use the scalar assignment as is. */
5646 tmp = gfc_trans_scalar_assign (&lse, &rse, expr1->ts,
5647 false, loop.temp_ss == NULL);
5649 tmp = build3_v (COND_EXPR, maskexpr, tmp, build_empty_stmt (input_location));
5651 gfc_add_expr_to_block (&body, tmp);
5653 if (lss == gfc_ss_terminator)
5655 /* Increment count1. */
5656 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
5657 count1, gfc_index_one_node);
5658 gfc_add_modify (&body, count1, tmp);
5660 /* Use the scalar assignment as is. */
5661 gfc_add_block_to_block (&block, &body);
5663 else
5665 gcc_assert (lse.ss == gfc_ss_terminator
5666 && rse.ss == gfc_ss_terminator);
5668 if (loop.temp_ss != NULL)
5670 /* Increment count1 before finish the main body of a scalarized
5671 expression. */
5672 tmp = fold_build2_loc (input_location, PLUS_EXPR,
5673 gfc_array_index_type, count1, gfc_index_one_node);
5674 gfc_add_modify (&body, count1, tmp);
5675 gfc_trans_scalarized_loop_boundary (&loop, &body);
5677 /* We need to copy the temporary to the actual lhs. */
5678 gfc_init_se (&lse, NULL);
5679 gfc_init_se (&rse, NULL);
5680 gfc_copy_loopinfo_to_se (&lse, &loop);
5681 gfc_copy_loopinfo_to_se (&rse, &loop);
5683 rse.ss = loop.temp_ss;
5684 lse.ss = lss;
5686 gfc_conv_tmp_array_ref (&rse);
5687 gfc_conv_expr (&lse, expr1);
5689 gcc_assert (lse.ss == gfc_ss_terminator
5690 && rse.ss == gfc_ss_terminator);
5692 /* Form the mask expression according to the mask tree list. */
5693 index = count2;
5694 maskexpr = gfc_build_array_ref (mask, index, NULL);
5695 if (invert)
5696 maskexpr = fold_build1_loc (input_location, TRUTH_NOT_EXPR,
5697 TREE_TYPE (maskexpr), maskexpr);
5699 /* Use the scalar assignment as is. */
5700 tmp = gfc_trans_scalar_assign (&lse, &rse, expr1->ts, false, true);
5701 tmp = build3_v (COND_EXPR, maskexpr, tmp,
5702 build_empty_stmt (input_location));
5703 gfc_add_expr_to_block (&body, tmp);
5705 /* Increment count2. */
5706 tmp = fold_build2_loc (input_location, PLUS_EXPR,
5707 gfc_array_index_type, count2,
5708 gfc_index_one_node);
5709 gfc_add_modify (&body, count2, tmp);
5711 else
5713 /* Increment count1. */
5714 tmp = fold_build2_loc (input_location, PLUS_EXPR,
5715 gfc_array_index_type, count1,
5716 gfc_index_one_node);
5717 gfc_add_modify (&body, count1, tmp);
5720 /* Generate the copying loops. */
5721 gfc_trans_scalarizing_loops (&loop, &body);
5723 /* Wrap the whole thing up. */
5724 gfc_add_block_to_block (&block, &loop.pre);
5725 gfc_add_block_to_block (&block, &loop.post);
5726 gfc_cleanup_loop (&loop);
5729 return gfc_finish_block (&block);
5733 /* Translate the WHERE construct or statement.
5734 This function can be called iteratively to translate the nested WHERE
5735 construct or statement.
5736 MASK is the control mask. */
5738 static void
5739 gfc_trans_where_2 (gfc_code * code, tree mask, bool invert,
5740 forall_info * nested_forall_info, stmtblock_t * block)
5742 stmtblock_t inner_size_body;
5743 tree inner_size, size;
5744 gfc_ss *lss, *rss;
5745 tree mask_type;
5746 gfc_expr *expr1;
5747 gfc_expr *expr2;
5748 gfc_code *cblock;
5749 gfc_code *cnext;
5750 tree tmp;
5751 tree cond;
5752 tree count1, count2;
5753 bool need_cmask;
5754 bool need_pmask;
5755 int need_temp;
5756 tree pcmask = NULL_TREE;
5757 tree ppmask = NULL_TREE;
5758 tree cmask = NULL_TREE;
5759 tree pmask = NULL_TREE;
5760 gfc_actual_arglist *arg;
5762 /* the WHERE statement or the WHERE construct statement. */
5763 cblock = code->block;
5765 /* As the mask array can be very big, prefer compact boolean types. */
5766 mask_type = gfc_get_logical_type (gfc_logical_kinds[0].kind);
5768 /* Determine which temporary masks are needed. */
5769 if (!cblock->block)
5771 /* One clause: No ELSEWHEREs. */
5772 need_cmask = (cblock->next != 0);
5773 need_pmask = false;
5775 else if (cblock->block->block)
5777 /* Three or more clauses: Conditional ELSEWHEREs. */
5778 need_cmask = true;
5779 need_pmask = true;
5781 else if (cblock->next)
5783 /* Two clauses, the first non-empty. */
5784 need_cmask = true;
5785 need_pmask = (mask != NULL_TREE
5786 && cblock->block->next != 0);
5788 else if (!cblock->block->next)
5790 /* Two clauses, both empty. */
5791 need_cmask = false;
5792 need_pmask = false;
5794 /* Two clauses, the first empty, the second non-empty. */
5795 else if (mask)
5797 need_cmask = (cblock->block->expr1 != 0);
5798 need_pmask = true;
5800 else
5802 need_cmask = true;
5803 need_pmask = false;
5806 if (need_cmask || need_pmask)
5808 /* Calculate the size of temporary needed by the mask-expr. */
5809 gfc_init_block (&inner_size_body);
5810 inner_size = compute_inner_temp_size (cblock->expr1, cblock->expr1,
5811 &inner_size_body, &lss, &rss);
5813 gfc_free_ss_chain (lss);
5814 gfc_free_ss_chain (rss);
5816 /* Calculate the total size of temporary needed. */
5817 size = compute_overall_iter_number (nested_forall_info, inner_size,
5818 &inner_size_body, block);
5820 /* Check whether the size is negative. */
5821 cond = fold_build2_loc (input_location, LE_EXPR, logical_type_node, size,
5822 gfc_index_zero_node);
5823 size = fold_build3_loc (input_location, COND_EXPR, gfc_array_index_type,
5824 cond, gfc_index_zero_node, size);
5825 size = gfc_evaluate_now (size, block);
5827 /* Allocate temporary for WHERE mask if needed. */
5828 if (need_cmask)
5829 cmask = allocate_temp_for_forall_nest_1 (mask_type, size, block,
5830 &pcmask);
5832 /* Allocate temporary for !mask if needed. */
5833 if (need_pmask)
5834 pmask = allocate_temp_for_forall_nest_1 (mask_type, size, block,
5835 &ppmask);
5838 while (cblock)
5840 /* Each time around this loop, the where clause is conditional
5841 on the value of mask and invert, which are updated at the
5842 bottom of the loop. */
5844 /* Has mask-expr. */
5845 if (cblock->expr1)
5847 /* Ensure that the WHERE mask will be evaluated exactly once.
5848 If there are no statements in this WHERE/ELSEWHERE clause,
5849 then we don't need to update the control mask (cmask).
5850 If this is the last clause of the WHERE construct, then
5851 we don't need to update the pending control mask (pmask). */
5852 if (mask)
5853 gfc_evaluate_where_mask (cblock->expr1, nested_forall_info,
5854 mask, invert,
5855 cblock->next ? cmask : NULL_TREE,
5856 cblock->block ? pmask : NULL_TREE,
5857 mask_type, block);
5858 else
5859 gfc_evaluate_where_mask (cblock->expr1, nested_forall_info,
5860 NULL_TREE, false,
5861 (cblock->next || cblock->block)
5862 ? cmask : NULL_TREE,
5863 NULL_TREE, mask_type, block);
5865 invert = false;
5867 /* It's a final elsewhere-stmt. No mask-expr is present. */
5868 else
5869 cmask = mask;
5871 /* The body of this where clause are controlled by cmask with
5872 sense specified by invert. */
5874 /* Get the assignment statement of a WHERE statement, or the first
5875 statement in where-body-construct of a WHERE construct. */
5876 cnext = cblock->next;
5877 while (cnext)
5879 switch (cnext->op)
5881 /* WHERE assignment statement. */
5882 case EXEC_ASSIGN_CALL:
5884 arg = cnext->ext.actual;
5885 expr1 = expr2 = NULL;
5886 for (; arg; arg = arg->next)
5888 if (!arg->expr)
5889 continue;
5890 if (expr1 == NULL)
5891 expr1 = arg->expr;
5892 else
5893 expr2 = arg->expr;
5895 goto evaluate;
5897 case EXEC_ASSIGN:
5898 expr1 = cnext->expr1;
5899 expr2 = cnext->expr2;
5900 evaluate:
5901 if (nested_forall_info != NULL)
5903 need_temp = gfc_check_dependency (expr1, expr2, 0);
5904 if ((need_temp || flag_test_forall_temp)
5905 && cnext->op != EXEC_ASSIGN_CALL)
5906 gfc_trans_assign_need_temp (expr1, expr2,
5907 cmask, invert,
5908 nested_forall_info, block);
5909 else
5911 /* Variables to control maskexpr. */
5912 count1 = gfc_create_var (gfc_array_index_type, "count1");
5913 count2 = gfc_create_var (gfc_array_index_type, "count2");
5914 gfc_add_modify (block, count1, gfc_index_zero_node);
5915 gfc_add_modify (block, count2, gfc_index_zero_node);
5917 tmp = gfc_trans_where_assign (expr1, expr2,
5918 cmask, invert,
5919 count1, count2,
5920 cnext);
5922 tmp = gfc_trans_nested_forall_loop (nested_forall_info,
5923 tmp, 1);
5924 gfc_add_expr_to_block (block, tmp);
5927 else
5929 /* Variables to control maskexpr. */
5930 count1 = gfc_create_var (gfc_array_index_type, "count1");
5931 count2 = gfc_create_var (gfc_array_index_type, "count2");
5932 gfc_add_modify (block, count1, gfc_index_zero_node);
5933 gfc_add_modify (block, count2, gfc_index_zero_node);
5935 tmp = gfc_trans_where_assign (expr1, expr2,
5936 cmask, invert,
5937 count1, count2,
5938 cnext);
5939 gfc_add_expr_to_block (block, tmp);
5942 break;
5944 /* WHERE or WHERE construct is part of a where-body-construct. */
5945 case EXEC_WHERE:
5946 gfc_trans_where_2 (cnext, cmask, invert,
5947 nested_forall_info, block);
5948 break;
5950 default:
5951 gcc_unreachable ();
5954 /* The next statement within the same where-body-construct. */
5955 cnext = cnext->next;
5957 /* The next masked-elsewhere-stmt, elsewhere-stmt, or end-where-stmt. */
5958 cblock = cblock->block;
5959 if (mask == NULL_TREE)
5961 /* If we're the initial WHERE, we can simply invert the sense
5962 of the current mask to obtain the "mask" for the remaining
5963 ELSEWHEREs. */
5964 invert = true;
5965 mask = cmask;
5967 else
5969 /* Otherwise, for nested WHERE's we need to use the pending mask. */
5970 invert = false;
5971 mask = pmask;
5975 /* If we allocated a pending mask array, deallocate it now. */
5976 if (ppmask)
5978 tmp = gfc_call_free (ppmask);
5979 gfc_add_expr_to_block (block, tmp);
5982 /* If we allocated a current mask array, deallocate it now. */
5983 if (pcmask)
5985 tmp = gfc_call_free (pcmask);
5986 gfc_add_expr_to_block (block, tmp);
5990 /* Translate a simple WHERE construct or statement without dependencies.
5991 CBLOCK is the "then" clause of the WHERE statement, where CBLOCK->EXPR
5992 is the mask condition, and EBLOCK if non-NULL is the "else" clause.
5993 Currently both CBLOCK and EBLOCK are restricted to single assignments. */
5995 static tree
5996 gfc_trans_where_3 (gfc_code * cblock, gfc_code * eblock)
5998 stmtblock_t block, body;
5999 gfc_expr *cond, *tdst, *tsrc, *edst, *esrc;
6000 tree tmp, cexpr, tstmt, estmt;
6001 gfc_ss *css, *tdss, *tsss;
6002 gfc_se cse, tdse, tsse, edse, esse;
6003 gfc_loopinfo loop;
6004 gfc_ss *edss = 0;
6005 gfc_ss *esss = 0;
6006 bool maybe_workshare = false;
6008 /* Allow the scalarizer to workshare simple where loops. */
6009 if ((ompws_flags & (OMPWS_WORKSHARE_FLAG | OMPWS_SCALARIZER_BODY))
6010 == OMPWS_WORKSHARE_FLAG)
6012 maybe_workshare = true;
6013 ompws_flags |= OMPWS_SCALARIZER_WS | OMPWS_SCALARIZER_BODY;
6016 cond = cblock->expr1;
6017 tdst = cblock->next->expr1;
6018 tsrc = cblock->next->expr2;
6019 edst = eblock ? eblock->next->expr1 : NULL;
6020 esrc = eblock ? eblock->next->expr2 : NULL;
6022 gfc_start_block (&block);
6023 gfc_init_loopinfo (&loop);
6025 /* Handle the condition. */
6026 gfc_init_se (&cse, NULL);
6027 css = gfc_walk_expr (cond);
6028 gfc_add_ss_to_loop (&loop, css);
6030 /* Handle the then-clause. */
6031 gfc_init_se (&tdse, NULL);
6032 gfc_init_se (&tsse, NULL);
6033 tdss = gfc_walk_expr (tdst);
6034 tsss = gfc_walk_expr (tsrc);
6035 if (tsss == gfc_ss_terminator)
6037 tsss = gfc_get_scalar_ss (gfc_ss_terminator, tsrc);
6038 tsss->info->where = 1;
6040 gfc_add_ss_to_loop (&loop, tdss);
6041 gfc_add_ss_to_loop (&loop, tsss);
6043 if (eblock)
6045 /* Handle the else clause. */
6046 gfc_init_se (&edse, NULL);
6047 gfc_init_se (&esse, NULL);
6048 edss = gfc_walk_expr (edst);
6049 esss = gfc_walk_expr (esrc);
6050 if (esss == gfc_ss_terminator)
6052 esss = gfc_get_scalar_ss (gfc_ss_terminator, esrc);
6053 esss->info->where = 1;
6055 gfc_add_ss_to_loop (&loop, edss);
6056 gfc_add_ss_to_loop (&loop, esss);
6059 gfc_conv_ss_startstride (&loop);
6060 gfc_conv_loop_setup (&loop, &tdst->where);
6062 gfc_mark_ss_chain_used (css, 1);
6063 gfc_mark_ss_chain_used (tdss, 1);
6064 gfc_mark_ss_chain_used (tsss, 1);
6065 if (eblock)
6067 gfc_mark_ss_chain_used (edss, 1);
6068 gfc_mark_ss_chain_used (esss, 1);
6071 gfc_start_scalarized_body (&loop, &body);
6073 gfc_copy_loopinfo_to_se (&cse, &loop);
6074 gfc_copy_loopinfo_to_se (&tdse, &loop);
6075 gfc_copy_loopinfo_to_se (&tsse, &loop);
6076 cse.ss = css;
6077 tdse.ss = tdss;
6078 tsse.ss = tsss;
6079 if (eblock)
6081 gfc_copy_loopinfo_to_se (&edse, &loop);
6082 gfc_copy_loopinfo_to_se (&esse, &loop);
6083 edse.ss = edss;
6084 esse.ss = esss;
6087 gfc_conv_expr (&cse, cond);
6088 gfc_add_block_to_block (&body, &cse.pre);
6089 cexpr = cse.expr;
6091 gfc_conv_expr (&tsse, tsrc);
6092 if (tdss != gfc_ss_terminator && loop.temp_ss != NULL)
6093 gfc_conv_tmp_array_ref (&tdse);
6094 else
6095 gfc_conv_expr (&tdse, tdst);
6097 if (eblock)
6099 gfc_conv_expr (&esse, esrc);
6100 if (edss != gfc_ss_terminator && loop.temp_ss != NULL)
6101 gfc_conv_tmp_array_ref (&edse);
6102 else
6103 gfc_conv_expr (&edse, edst);
6106 tstmt = gfc_trans_scalar_assign (&tdse, &tsse, tdst->ts, false, true);
6107 estmt = eblock ? gfc_trans_scalar_assign (&edse, &esse, edst->ts,
6108 false, true)
6109 : build_empty_stmt (input_location);
6110 tmp = build3_v (COND_EXPR, cexpr, tstmt, estmt);
6111 gfc_add_expr_to_block (&body, tmp);
6112 gfc_add_block_to_block (&body, &cse.post);
6114 if (maybe_workshare)
6115 ompws_flags &= ~OMPWS_SCALARIZER_BODY;
6116 gfc_trans_scalarizing_loops (&loop, &body);
6117 gfc_add_block_to_block (&block, &loop.pre);
6118 gfc_add_block_to_block (&block, &loop.post);
6119 gfc_cleanup_loop (&loop);
6121 return gfc_finish_block (&block);
6124 /* As the WHERE or WHERE construct statement can be nested, we call
6125 gfc_trans_where_2 to do the translation, and pass the initial
6126 NULL values for both the control mask and the pending control mask. */
6128 tree
6129 gfc_trans_where (gfc_code * code)
6131 stmtblock_t block;
6132 gfc_code *cblock;
6133 gfc_code *eblock;
6135 cblock = code->block;
6136 if (cblock->next
6137 && cblock->next->op == EXEC_ASSIGN
6138 && !cblock->next->next)
6140 eblock = cblock->block;
6141 if (!eblock)
6143 /* A simple "WHERE (cond) x = y" statement or block is
6144 dependence free if cond is not dependent upon writing x,
6145 and the source y is unaffected by the destination x. */
6146 if (!gfc_check_dependency (cblock->next->expr1,
6147 cblock->expr1, 0)
6148 && !gfc_check_dependency (cblock->next->expr1,
6149 cblock->next->expr2, 0))
6150 return gfc_trans_where_3 (cblock, NULL);
6152 else if (!eblock->expr1
6153 && !eblock->block
6154 && eblock->next
6155 && eblock->next->op == EXEC_ASSIGN
6156 && !eblock->next->next)
6158 /* A simple "WHERE (cond) x1 = y1 ELSEWHERE x2 = y2 ENDWHERE"
6159 block is dependence free if cond is not dependent on writes
6160 to x1 and x2, y1 is not dependent on writes to x2, and y2
6161 is not dependent on writes to x1, and both y's are not
6162 dependent upon their own x's. In addition to this, the
6163 final two dependency checks below exclude all but the same
6164 array reference if the where and elswhere destinations
6165 are the same. In short, this is VERY conservative and this
6166 is needed because the two loops, required by the standard
6167 are coalesced in gfc_trans_where_3. */
6168 if (!gfc_check_dependency (cblock->next->expr1,
6169 cblock->expr1, 0)
6170 && !gfc_check_dependency (eblock->next->expr1,
6171 cblock->expr1, 0)
6172 && !gfc_check_dependency (cblock->next->expr1,
6173 eblock->next->expr2, 1)
6174 && !gfc_check_dependency (eblock->next->expr1,
6175 cblock->next->expr2, 1)
6176 && !gfc_check_dependency (cblock->next->expr1,
6177 cblock->next->expr2, 1)
6178 && !gfc_check_dependency (eblock->next->expr1,
6179 eblock->next->expr2, 1)
6180 && !gfc_check_dependency (cblock->next->expr1,
6181 eblock->next->expr1, 0)
6182 && !gfc_check_dependency (eblock->next->expr1,
6183 cblock->next->expr1, 0))
6184 return gfc_trans_where_3 (cblock, eblock);
6188 gfc_start_block (&block);
6190 gfc_trans_where_2 (code, NULL, false, NULL, &block);
6192 return gfc_finish_block (&block);
6196 /* CYCLE a DO loop. The label decl has already been created by
6197 gfc_trans_do(), it's in TREE_PURPOSE (backend_decl) of the gfc_code
6198 node at the head of the loop. We must mark the label as used. */
6200 tree
6201 gfc_trans_cycle (gfc_code * code)
6203 tree cycle_label;
6205 cycle_label = code->ext.which_construct->cycle_label;
6206 gcc_assert (cycle_label);
6208 TREE_USED (cycle_label) = 1;
6209 return build1_v (GOTO_EXPR, cycle_label);
6213 /* EXIT a DO loop. Similar to CYCLE, but now the label is in
6214 TREE_VALUE (backend_decl) of the gfc_code node at the head of the
6215 loop. */
6217 tree
6218 gfc_trans_exit (gfc_code * code)
6220 tree exit_label;
6222 exit_label = code->ext.which_construct->exit_label;
6223 gcc_assert (exit_label);
6225 TREE_USED (exit_label) = 1;
6226 return build1_v (GOTO_EXPR, exit_label);
6230 /* Get the initializer expression for the code and expr of an allocate.
6231 When no initializer is needed return NULL. */
6233 static gfc_expr *
6234 allocate_get_initializer (gfc_code * code, gfc_expr * expr)
6236 if (!gfc_bt_struct (expr->ts.type) && expr->ts.type != BT_CLASS)
6237 return NULL;
6239 /* An explicit type was given in allocate ( T:: object). */
6240 if (code->ext.alloc.ts.type == BT_DERIVED
6241 && (code->ext.alloc.ts.u.derived->attr.alloc_comp
6242 || gfc_has_default_initializer (code->ext.alloc.ts.u.derived)))
6243 return gfc_default_initializer (&code->ext.alloc.ts);
6245 if (gfc_bt_struct (expr->ts.type)
6246 && (expr->ts.u.derived->attr.alloc_comp
6247 || gfc_has_default_initializer (expr->ts.u.derived)))
6248 return gfc_default_initializer (&expr->ts);
6250 if (expr->ts.type == BT_CLASS
6251 && (CLASS_DATA (expr)->ts.u.derived->attr.alloc_comp
6252 || gfc_has_default_initializer (CLASS_DATA (expr)->ts.u.derived)))
6253 return gfc_default_initializer (&CLASS_DATA (expr)->ts);
6255 return NULL;
6258 /* Translate the ALLOCATE statement. */
6260 tree
6261 gfc_trans_allocate (gfc_code * code, gfc_omp_namelist *omp_allocate)
6263 gfc_alloc *al;
6264 gfc_expr *expr, *e3rhs = NULL, *init_expr;
6265 gfc_se se, se_sz;
6266 tree tmp;
6267 tree parm;
6268 tree stat;
6269 tree errmsg;
6270 tree errlen;
6271 tree label_errmsg;
6272 tree label_finish;
6273 tree memsz;
6274 tree al_vptr, al_len;
6275 /* If an expr3 is present, then store the tree for accessing its
6276 _vptr, and _len components in the variables, respectively. The
6277 element size, i.e. _vptr%size, is stored in expr3_esize. Any of
6278 the trees may be the NULL_TREE indicating that this is not
6279 available for expr3's type. */
6280 tree expr3, expr3_vptr, expr3_len, expr3_esize;
6281 /* Classify what expr3 stores. */
6282 enum { E3_UNSET = 0, E3_SOURCE, E3_MOLD, E3_DESC } e3_is;
6283 stmtblock_t block;
6284 stmtblock_t post;
6285 stmtblock_t final_block;
6286 tree nelems;
6287 bool upoly_expr, tmp_expr3_len_flag = false, al_len_needs_set, is_coarray;
6288 bool needs_caf_sync, caf_refs_comp;
6289 bool e3_has_nodescriptor = false;
6290 gfc_symtree *newsym = NULL;
6291 symbol_attribute caf_attr;
6292 gfc_actual_arglist *param_list;
6294 if (!code->ext.alloc.list)
6295 return NULL_TREE;
6297 stat = tmp = memsz = al_vptr = al_len = NULL_TREE;
6298 expr3 = expr3_vptr = expr3_len = expr3_esize = NULL_TREE;
6299 label_errmsg = label_finish = errmsg = errlen = NULL_TREE;
6300 e3_is = E3_UNSET;
6301 is_coarray = needs_caf_sync = false;
6303 gfc_init_block (&block);
6304 gfc_init_block (&post);
6305 gfc_init_block (&final_block);
6307 /* STAT= (and maybe ERRMSG=) is present. */
6308 if (code->expr1)
6310 /* STAT=. */
6311 tree gfc_int4_type_node = gfc_get_int_type (4);
6312 stat = gfc_create_var (gfc_int4_type_node, "stat");
6314 /* ERRMSG= only makes sense with STAT=. */
6315 if (code->expr2)
6317 gfc_init_se (&se, NULL);
6318 se.want_pointer = 1;
6319 gfc_conv_expr_lhs (&se, code->expr2);
6320 errmsg = se.expr;
6321 errlen = se.string_length;
6323 else
6325 errmsg = null_pointer_node;
6326 errlen = build_int_cst (gfc_charlen_type_node, 0);
6329 /* GOTO destinations. */
6330 label_errmsg = gfc_build_label_decl (NULL_TREE);
6331 label_finish = gfc_build_label_decl (NULL_TREE);
6332 TREE_USED (label_finish) = 0;
6335 /* When an expr3 is present evaluate it only once. The standards prevent a
6336 dependency of expr3 on the objects in the allocate list. An expr3 can
6337 be pre-evaluated in all cases. One just has to make sure, to use the
6338 correct way, i.e., to get the descriptor or to get a reference
6339 expression. */
6340 if (code->expr3)
6342 bool vtab_needed = false, temp_var_needed = false,
6343 temp_obj_created = false;
6345 is_coarray = gfc_is_coarray (code->expr3);
6347 if (code->expr3->expr_type == EXPR_FUNCTION && !code->expr3->mold
6348 && (gfc_is_class_array_function (code->expr3)
6349 || gfc_is_alloc_class_scalar_function (code->expr3)))
6350 code->expr3->must_finalize = 1;
6352 /* Figure whether we need the vtab from expr3. */
6353 for (al = code->ext.alloc.list; !vtab_needed && al != NULL;
6354 al = al->next)
6355 vtab_needed = (al->expr->ts.type == BT_CLASS);
6357 gfc_init_se (&se, NULL);
6358 /* When expr3 is a variable, i.e., a very simple expression,
6359 then convert it once here. */
6360 if (code->expr3->expr_type == EXPR_VARIABLE
6361 || code->expr3->expr_type == EXPR_ARRAY
6362 || code->expr3->expr_type == EXPR_CONSTANT)
6364 if (!code->expr3->mold
6365 || code->expr3->ts.type == BT_CHARACTER
6366 || vtab_needed
6367 || code->ext.alloc.arr_spec_from_expr3)
6369 /* Convert expr3 to a tree. For all "simple" expression just
6370 get the descriptor or the reference, respectively, depending
6371 on the rank of the expr. */
6372 if (code->ext.alloc.arr_spec_from_expr3 || code->expr3->rank != 0)
6373 gfc_conv_expr_descriptor (&se, code->expr3);
6374 else
6376 gfc_conv_expr_reference (&se, code->expr3);
6378 /* gfc_conv_expr_reference wraps POINTER_PLUS_EXPR in a
6379 NOP_EXPR, which prevents gfortran from getting the vptr
6380 from the source=-expression. Remove the NOP_EXPR and go
6381 with the POINTER_PLUS_EXPR in this case. */
6382 if (code->expr3->ts.type == BT_CLASS
6383 && TREE_CODE (se.expr) == NOP_EXPR
6384 && (TREE_CODE (TREE_OPERAND (se.expr, 0))
6385 == POINTER_PLUS_EXPR
6386 || is_coarray))
6387 se.expr = TREE_OPERAND (se.expr, 0);
6389 /* Create a temp variable only for component refs to prevent
6390 having to go through the full deref-chain each time and to
6391 simplify computation of array properties. */
6392 temp_var_needed = TREE_CODE (se.expr) == COMPONENT_REF;
6395 else
6397 /* In all other cases evaluate the expr3. */
6398 symbol_attribute attr;
6399 /* Get the descriptor for all arrays, that are not allocatable or
6400 pointer, because the latter are descriptors already.
6401 The exception are function calls returning a class object:
6402 The descriptor is stored in their results _data component, which
6403 is easier to access, when first a temporary variable for the
6404 result is created and the descriptor retrieved from there. */
6405 attr = gfc_expr_attr (code->expr3);
6406 if (code->expr3->rank != 0
6407 && ((!attr.allocatable && !attr.pointer)
6408 || (code->expr3->expr_type == EXPR_FUNCTION
6409 && (code->expr3->ts.type != BT_CLASS
6410 || (code->expr3->value.function.isym
6411 && code->expr3->value.function.isym
6412 ->transformational)))))
6413 gfc_conv_expr_descriptor (&se, code->expr3);
6414 else
6415 gfc_conv_expr_reference (&se, code->expr3);
6416 if (code->expr3->ts.type == BT_CLASS)
6417 gfc_conv_class_to_class (&se, code->expr3,
6418 code->expr3->ts,
6419 false, true,
6420 false, false);
6421 temp_obj_created = temp_var_needed = !VAR_P (se.expr);
6423 gfc_add_block_to_block (&block, &se.pre);
6424 if (code->expr3->must_finalize)
6426 gfc_add_block_to_block (&final_block, &se.finalblock);
6427 gfc_add_block_to_block (&final_block, &se.post);
6429 else
6430 gfc_add_block_to_block (&post, &se.post);
6432 /* Special case when string in expr3 is zero. */
6433 if (code->expr3->ts.type == BT_CHARACTER
6434 && integer_zerop (se.string_length))
6436 gfc_init_se (&se, NULL);
6437 temp_var_needed = false;
6438 expr3_len = build_zero_cst (gfc_charlen_type_node);
6439 e3_is = E3_MOLD;
6441 /* Prevent aliasing, i.e., se.expr may be already a
6442 variable declaration. */
6443 else if (se.expr != NULL_TREE && temp_var_needed)
6445 tree var, desc;
6446 tmp = GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (se.expr)) || is_coarray ?
6447 se.expr
6448 : build_fold_indirect_ref_loc (input_location, se.expr);
6450 /* Get the array descriptor and prepare it to be assigned to the
6451 temporary variable var. For classes the array descriptor is
6452 in the _data component and the object goes into the
6453 GFC_DECL_SAVED_DESCRIPTOR. */
6454 if (code->expr3->ts.type == BT_CLASS
6455 && code->expr3->rank != 0)
6457 /* When an array_ref was in expr3, then the descriptor is the
6458 first operand. */
6459 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (tmp)) || is_coarray)
6461 desc = TREE_OPERAND (tmp, 0);
6463 else
6465 desc = tmp;
6466 tmp = gfc_class_data_get (tmp);
6468 if (code->ext.alloc.arr_spec_from_expr3)
6469 e3_is = E3_DESC;
6471 else
6472 desc = !is_coarray ? se.expr
6473 : TREE_OPERAND (TREE_OPERAND (se.expr, 0), 0);
6474 /* We need a regular (non-UID) symbol here, therefore give a
6475 prefix. */
6476 var = gfc_create_var (TREE_TYPE (tmp), "source");
6477 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (tmp)) || is_coarray)
6479 gfc_allocate_lang_decl (var);
6480 GFC_DECL_SAVED_DESCRIPTOR (var) = desc;
6482 gfc_add_modify_loc (input_location, &block, var, tmp);
6484 expr3 = var;
6485 if (se.string_length)
6486 /* Evaluate it assuming that it also is complicated like expr3. */
6487 expr3_len = gfc_evaluate_now (se.string_length, &block);
6489 else
6491 expr3 = se.expr;
6492 expr3_len = se.string_length;
6495 /* Deallocate any allocatable components in expressions that use a
6496 temporary object, i.e. are not a simple alias of to an EXPR_VARIABLE.
6497 E.g. temporaries of a function call need freeing of their components
6498 here. Explicit derived type allocation of class entities uses expr3
6499 to carry the default initializer. This must not be deallocated or
6500 finalized. */
6501 if ((code->expr3->ts.type == BT_DERIVED
6502 || code->expr3->ts.type == BT_CLASS)
6503 && (code->expr3->expr_type != EXPR_VARIABLE || temp_obj_created)
6504 && code->expr3->ts.u.derived->attr.alloc_comp
6505 && !code->expr3->must_finalize
6506 && !code->ext.alloc.expr3_not_explicit)
6508 tmp = gfc_deallocate_alloc_comp (code->expr3->ts.u.derived,
6509 expr3, code->expr3->rank);
6510 gfc_prepend_expr_to_block (&post, tmp);
6513 /* Store what the expr3 is to be used for. */
6514 if (e3_is == E3_UNSET)
6515 e3_is = expr3 != NULL_TREE ?
6516 (code->ext.alloc.arr_spec_from_expr3 ?
6517 E3_DESC
6518 : (code->expr3->mold ? E3_MOLD : E3_SOURCE))
6519 : E3_UNSET;
6521 /* Figure how to get the _vtab entry. This also obtains the tree
6522 expression for accessing the _len component, because only
6523 unlimited polymorphic objects, which are a subcategory of class
6524 types, have a _len component. */
6525 if (code->expr3->ts.type == BT_CLASS)
6527 gfc_expr *rhs;
6528 tmp = expr3 != NULL_TREE && POINTER_TYPE_P (TREE_TYPE (expr3)) ?
6529 build_fold_indirect_ref (expr3): expr3;
6530 /* Polymorphic SOURCE: VPTR must be determined at run time.
6531 expr3 may be a temporary array declaration, therefore check for
6532 GFC_CLASS_TYPE_P before trying to get the _vptr component. */
6533 if (tmp != NULL_TREE
6534 && (e3_is == E3_DESC
6535 || (GFC_CLASS_TYPE_P (TREE_TYPE (tmp))
6536 && (VAR_P (tmp) || !code->expr3->ref))
6537 || (VAR_P (tmp) && DECL_LANG_SPECIFIC (tmp))))
6538 tmp = gfc_class_vptr_get (expr3);
6539 else
6541 rhs = gfc_find_and_cut_at_last_class_ref (code->expr3);
6542 gfc_add_vptr_component (rhs);
6543 gfc_init_se (&se, NULL);
6544 se.want_pointer = 1;
6545 gfc_conv_expr (&se, rhs);
6546 tmp = se.expr;
6547 gfc_free_expr (rhs);
6549 /* Set the element size. */
6550 expr3_esize = gfc_vptr_size_get (tmp);
6551 if (vtab_needed)
6552 expr3_vptr = tmp;
6553 /* Initialize the ref to the _len component. */
6554 if (expr3_len == NULL_TREE && UNLIMITED_POLY (code->expr3))
6556 /* Same like for retrieving the _vptr. */
6557 if (expr3 != NULL_TREE && !code->expr3->ref)
6558 expr3_len = gfc_class_len_get (expr3);
6559 else
6561 rhs = gfc_find_and_cut_at_last_class_ref (code->expr3);
6562 gfc_add_len_component (rhs);
6563 gfc_init_se (&se, NULL);
6564 gfc_conv_expr (&se, rhs);
6565 expr3_len = se.expr;
6566 gfc_free_expr (rhs);
6570 else
6572 /* When the object to allocate is polymorphic type, then it
6573 needs its vtab set correctly, so deduce the required _vtab
6574 and _len from the source expression. */
6575 if (vtab_needed)
6577 /* VPTR is fixed at compile time. */
6578 gfc_symbol *vtab;
6580 vtab = gfc_find_vtab (&code->expr3->ts);
6581 gcc_assert (vtab);
6582 expr3_vptr = gfc_get_symbol_decl (vtab);
6583 expr3_vptr = gfc_build_addr_expr (NULL_TREE,
6584 expr3_vptr);
6586 /* _len component needs to be set, when ts is a character
6587 array. */
6588 if (expr3_len == NULL_TREE
6589 && code->expr3->ts.type == BT_CHARACTER)
6591 if (code->expr3->ts.u.cl
6592 && code->expr3->ts.u.cl->length)
6594 gfc_init_se (&se, NULL);
6595 gfc_conv_expr (&se, code->expr3->ts.u.cl->length);
6596 gfc_add_block_to_block (&block, &se.pre);
6597 expr3_len = gfc_evaluate_now (se.expr, &block);
6599 gcc_assert (expr3_len);
6601 /* For character arrays only the kind's size is needed, because
6602 the array mem_size is _len * (elem_size = kind_size).
6603 For all other get the element size in the normal way. */
6604 if (code->expr3->ts.type == BT_CHARACTER)
6605 expr3_esize = TYPE_SIZE_UNIT (
6606 gfc_get_char_type (code->expr3->ts.kind));
6607 else
6608 expr3_esize = TYPE_SIZE_UNIT (
6609 gfc_typenode_for_spec (&code->expr3->ts));
6611 gcc_assert (expr3_esize);
6612 expr3_esize = fold_convert (sizetype, expr3_esize);
6613 if (e3_is == E3_MOLD)
6614 /* The expr3 is no longer valid after this point. */
6615 expr3 = NULL_TREE;
6617 else if (code->ext.alloc.ts.type != BT_UNKNOWN)
6619 /* Compute the explicit typespec given only once for all objects
6620 to allocate. */
6621 if (code->ext.alloc.ts.type != BT_CHARACTER)
6622 expr3_esize = TYPE_SIZE_UNIT (
6623 gfc_typenode_for_spec (&code->ext.alloc.ts));
6624 else if (code->ext.alloc.ts.u.cl->length != NULL)
6626 gfc_expr *sz;
6627 sz = gfc_copy_expr (code->ext.alloc.ts.u.cl->length);
6628 gfc_init_se (&se_sz, NULL);
6629 gfc_conv_expr (&se_sz, sz);
6630 gfc_free_expr (sz);
6631 tmp = gfc_get_char_type (code->ext.alloc.ts.kind);
6632 tmp = TYPE_SIZE_UNIT (tmp);
6633 tmp = fold_convert (TREE_TYPE (se_sz.expr), tmp);
6634 gfc_add_block_to_block (&block, &se_sz.pre);
6635 expr3_esize = fold_build2_loc (input_location, MULT_EXPR,
6636 TREE_TYPE (se_sz.expr),
6637 tmp, se_sz.expr);
6638 expr3_esize = gfc_evaluate_now (expr3_esize, &block);
6640 else
6641 expr3_esize = NULL_TREE;
6644 /* The routine gfc_trans_assignment () already implements all
6645 techniques needed. Unfortunately we may have a temporary
6646 variable for the source= expression here. When that is the
6647 case convert this variable into a temporary gfc_expr of type
6648 EXPR_VARIABLE and used it as rhs for the assignment. The
6649 advantage is, that we get scalarizer support for free,
6650 don't have to take care about scalar to array treatment and
6651 will benefit of every enhancements gfc_trans_assignment ()
6652 gets.
6653 No need to check whether e3_is is E3_UNSET, because that is
6654 done by expr3 != NULL_TREE.
6655 Exclude variables since the following block does not handle
6656 array sections. In any case, there is no harm in sending
6657 variables to gfc_trans_assignment because there is no
6658 evaluation of variables. */
6659 if (code->expr3)
6661 if (code->expr3->expr_type != EXPR_VARIABLE
6662 && e3_is != E3_MOLD && expr3 != NULL_TREE
6663 && DECL_P (expr3) && DECL_ARTIFICIAL (expr3))
6665 /* Build a temporary symtree and symbol. Do not add it to the current
6666 namespace to prevent accidentaly modifying a colliding
6667 symbol's as. */
6668 newsym = XCNEW (gfc_symtree);
6669 /* The name of the symtree should be unique, because gfc_create_var ()
6670 took care about generating the identifier. */
6671 newsym->name
6672 = gfc_get_string ("%s", IDENTIFIER_POINTER (DECL_NAME (expr3)));
6673 newsym->n.sym = gfc_new_symbol (newsym->name, NULL);
6674 /* The backend_decl is known. It is expr3, which is inserted
6675 here. */
6676 newsym->n.sym->backend_decl = expr3;
6677 e3rhs = gfc_get_expr ();
6678 e3rhs->rank = code->expr3->rank;
6679 e3rhs->symtree = newsym;
6680 /* Mark the symbol referenced or gfc_trans_assignment will bug. */
6681 newsym->n.sym->attr.referenced = 1;
6682 e3rhs->expr_type = EXPR_VARIABLE;
6683 e3rhs->where = code->expr3->where;
6684 /* Set the symbols type, upto it was BT_UNKNOWN. */
6685 if (IS_CLASS_ARRAY (code->expr3)
6686 && code->expr3->expr_type == EXPR_FUNCTION
6687 && code->expr3->value.function.isym
6688 && code->expr3->value.function.isym->transformational)
6690 e3rhs->ts = CLASS_DATA (code->expr3)->ts;
6692 else if (code->expr3->ts.type == BT_CLASS
6693 && !GFC_CLASS_TYPE_P (TREE_TYPE (expr3)))
6694 e3rhs->ts = CLASS_DATA (code->expr3)->ts;
6695 else
6696 e3rhs->ts = code->expr3->ts;
6697 newsym->n.sym->ts = e3rhs->ts;
6698 /* Check whether the expr3 is array valued. */
6699 if (e3rhs->rank)
6701 gfc_array_spec *arr;
6702 arr = gfc_get_array_spec ();
6703 arr->rank = e3rhs->rank;
6704 arr->type = AS_DEFERRED;
6705 /* Set the dimension and pointer attribute for arrays
6706 to be on the safe side. */
6707 newsym->n.sym->attr.dimension = 1;
6708 newsym->n.sym->attr.pointer = 1;
6709 newsym->n.sym->as = arr;
6710 if (IS_CLASS_ARRAY (code->expr3)
6711 && code->expr3->expr_type == EXPR_FUNCTION
6712 && code->expr3->value.function.isym
6713 && code->expr3->value.function.isym->transformational)
6715 gfc_array_spec *tarr;
6716 tarr = gfc_get_array_spec ();
6717 *tarr = *arr;
6718 e3rhs->ts.u.derived->as = tarr;
6720 gfc_add_full_array_ref (e3rhs, arr);
6722 else if (POINTER_TYPE_P (TREE_TYPE (expr3)))
6723 newsym->n.sym->attr.pointer = 1;
6724 /* The string length is known, too. Set it for char arrays. */
6725 if (e3rhs->ts.type == BT_CHARACTER)
6726 newsym->n.sym->ts.u.cl->backend_decl = expr3_len;
6727 gfc_commit_symbol (newsym->n.sym);
6729 else
6730 e3rhs = gfc_copy_expr (code->expr3);
6732 // We need to propagate the bounds of the expr3 for source=/mold=.
6733 // However, for non-named arrays, the lbound has to be 1 and neither the
6734 // bound used inside the called function even when returning an
6735 // allocatable/pointer nor the zero used internally.
6736 if (e3_is == E3_DESC
6737 && code->expr3->expr_type != EXPR_VARIABLE)
6738 e3_has_nodescriptor = true;
6741 /* Loop over all objects to allocate. */
6742 for (al = code->ext.alloc.list; al != NULL; al = al->next)
6744 expr = gfc_copy_expr (al->expr);
6745 /* UNLIMITED_POLY () needs the _data component to be set, when
6746 expr is a unlimited polymorphic object. But the _data component
6747 has not been set yet, so check the derived type's attr for the
6748 unlimited polymorphic flag to be safe. */
6749 upoly_expr = UNLIMITED_POLY (expr)
6750 || (expr->ts.type == BT_DERIVED
6751 && expr->ts.u.derived->attr.unlimited_polymorphic);
6752 gfc_init_se (&se, NULL);
6754 /* For class types prepare the expressions to ref the _vptr
6755 and the _len component. The latter for unlimited polymorphic
6756 types only. */
6757 if (expr->ts.type == BT_CLASS)
6759 gfc_expr *expr_ref_vptr, *expr_ref_len;
6760 gfc_add_data_component (expr);
6761 /* Prep the vptr handle. */
6762 expr_ref_vptr = gfc_copy_expr (al->expr);
6763 gfc_add_vptr_component (expr_ref_vptr);
6764 se.want_pointer = 1;
6765 gfc_conv_expr (&se, expr_ref_vptr);
6766 al_vptr = se.expr;
6767 se.want_pointer = 0;
6768 gfc_free_expr (expr_ref_vptr);
6769 /* Allocated unlimited polymorphic objects always have a _len
6770 component. */
6771 if (upoly_expr)
6773 expr_ref_len = gfc_copy_expr (al->expr);
6774 gfc_add_len_component (expr_ref_len);
6775 gfc_conv_expr (&se, expr_ref_len);
6776 al_len = se.expr;
6777 gfc_free_expr (expr_ref_len);
6779 else
6780 /* In a loop ensure that all loop variable dependent variables
6781 are initialized at the same spot in all execution paths. */
6782 al_len = NULL_TREE;
6784 else
6785 al_vptr = al_len = NULL_TREE;
6787 se.want_pointer = 1;
6788 se.descriptor_only = 1;
6790 gfc_conv_expr (&se, expr);
6791 if (expr->ts.type == BT_CHARACTER && expr->ts.deferred)
6792 /* se.string_length now stores the .string_length variable of expr
6793 needed to allocate character(len=:) arrays. */
6794 al_len = se.string_length;
6796 al_len_needs_set = al_len != NULL_TREE;
6797 /* When allocating an array one cannot use much of the
6798 pre-evaluated expr3 expressions, because for most of them the
6799 scalarizer is needed which is not available in the pre-evaluation
6800 step. Therefore gfc_array_allocate () is responsible (and able)
6801 to handle the complete array allocation. Only the element size
6802 needs to be provided, which is done most of the time by the
6803 pre-evaluation step. */
6804 nelems = NULL_TREE;
6805 if (expr3_len && (code->expr3->ts.type == BT_CHARACTER
6806 || code->expr3->ts.type == BT_CLASS))
6808 /* When al is an array, then the element size for each element
6809 in the array is needed, which is the product of the len and
6810 esize for char arrays. For unlimited polymorphics len can be
6811 zero, therefore take the maximum of len and one. */
6812 tmp = fold_build2_loc (input_location, MAX_EXPR,
6813 TREE_TYPE (expr3_len),
6814 expr3_len, fold_convert (TREE_TYPE (expr3_len),
6815 integer_one_node));
6816 tmp = fold_build2_loc (input_location, MULT_EXPR,
6817 TREE_TYPE (expr3_esize), expr3_esize,
6818 fold_convert (TREE_TYPE (expr3_esize), tmp));
6820 else
6821 tmp = expr3_esize;
6823 gfc_omp_namelist *omp_alloc_item = NULL;
6824 if (omp_allocate)
6826 gfc_omp_namelist *n = NULL;
6827 gfc_omp_namelist *n_null = NULL;
6828 for (n = omp_allocate; n; n = n->next)
6830 if (n->sym == NULL)
6832 n_null = n;
6833 continue;
6835 if (expr->expr_type == EXPR_VARIABLE
6836 && expr->symtree->n.sym == n->sym)
6838 gfc_ref *ref;
6839 for (ref = expr->ref; ref; ref = ref->next)
6840 if (ref->type == REF_COMPONENT)
6841 break;
6842 if (ref == NULL)
6843 break;
6846 omp_alloc_item = n ? n : n_null;
6850 if (!gfc_array_allocate (&se, expr, stat, errmsg, errlen,
6851 label_finish, tmp, &nelems,
6852 e3rhs ? e3rhs : code->expr3,
6853 e3_is == E3_DESC ? expr3 : NULL_TREE,
6854 e3_has_nodescriptor, omp_alloc_item))
6856 /* A scalar or derived type. First compute the size to
6857 allocate.
6859 expr3_len is set when expr3 is an unlimited polymorphic
6860 object or a deferred length string. */
6861 if (expr3_len != NULL_TREE)
6863 tmp = fold_convert (TREE_TYPE (expr3_esize), expr3_len);
6864 tmp = fold_build2_loc (input_location, MULT_EXPR,
6865 TREE_TYPE (expr3_esize),
6866 expr3_esize, tmp);
6867 if (code->expr3->ts.type != BT_CLASS)
6868 /* expr3 is a deferred length string, i.e., we are
6869 done. */
6870 memsz = tmp;
6871 else
6873 /* For unlimited polymorphic enties build
6874 (len > 0) ? element_size * len : element_size
6875 to compute the number of bytes to allocate.
6876 This allows the allocation of unlimited polymorphic
6877 objects from an expr3 that is also unlimited
6878 polymorphic and stores a _len dependent object,
6879 e.g., a string. */
6880 memsz = fold_build2_loc (input_location, GT_EXPR,
6881 logical_type_node, expr3_len,
6882 build_zero_cst
6883 (TREE_TYPE (expr3_len)));
6884 memsz = fold_build3_loc (input_location, COND_EXPR,
6885 TREE_TYPE (expr3_esize),
6886 memsz, tmp, expr3_esize);
6889 else if (expr3_esize != NULL_TREE)
6890 /* Any other object in expr3 just needs element size in
6891 bytes. */
6892 memsz = expr3_esize;
6893 else if ((expr->ts.type == BT_CHARACTER && expr->ts.deferred)
6894 || (upoly_expr
6895 && code->ext.alloc.ts.type == BT_CHARACTER))
6897 /* Allocating deferred length char arrays need the length
6898 to allocate in the alloc_type_spec. But also unlimited
6899 polymorphic objects may be allocated as char arrays.
6900 Both are handled here. */
6901 gfc_init_se (&se_sz, NULL);
6902 gfc_conv_expr (&se_sz, code->ext.alloc.ts.u.cl->length);
6903 gfc_add_block_to_block (&se.pre, &se_sz.pre);
6904 se_sz.expr = gfc_evaluate_now (se_sz.expr, &se.pre);
6905 gfc_add_block_to_block (&se.pre, &se_sz.post);
6906 expr3_len = se_sz.expr;
6907 tmp_expr3_len_flag = true;
6908 tmp = TYPE_SIZE_UNIT (
6909 gfc_get_char_type (code->ext.alloc.ts.kind));
6910 memsz = fold_build2_loc (input_location, MULT_EXPR,
6911 TREE_TYPE (tmp),
6912 fold_convert (TREE_TYPE (tmp),
6913 expr3_len),
6914 tmp);
6916 else if (expr->ts.type == BT_CHARACTER)
6918 /* Compute the number of bytes needed to allocate a fixed
6919 length char array. */
6920 gcc_assert (se.string_length != NULL_TREE);
6921 tmp = TYPE_SIZE_UNIT (gfc_get_char_type (expr->ts.kind));
6922 memsz = fold_build2_loc (input_location, MULT_EXPR,
6923 TREE_TYPE (tmp), tmp,
6924 fold_convert (TREE_TYPE (tmp),
6925 se.string_length));
6927 else if (code->ext.alloc.ts.type != BT_UNKNOWN)
6928 /* Handle all types, where the alloc_type_spec is set. */
6929 memsz = TYPE_SIZE_UNIT (gfc_typenode_for_spec (&code->ext.alloc.ts));
6930 else
6931 /* Handle size computation of the type declared to alloc. */
6932 memsz = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (se.expr)));
6934 bool use_coarray_alloc
6935 = (flag_coarray == GFC_FCOARRAY_LIB
6936 && (caf_attr = gfc_caf_attr (expr, true, &caf_refs_comp))
6937 .codimension);
6938 tree omp_cond = NULL_TREE;
6939 tree omp_alt_alloc = NULL_TREE;
6940 tree succ_add_expr = NULL_TREE;
6941 if (!use_coarray_alloc && omp_alloc_item)
6943 tree align, alloc, sz;
6944 gfc_se se2;
6946 omp_cond = boolean_true_node;
6947 if (omp_alloc_item->u2.allocator)
6949 gfc_init_se (&se2, NULL);
6950 gfc_conv_expr (&se2, omp_alloc_item->u2.allocator);
6951 gfc_add_block_to_block (&se.pre, &se2.pre);
6952 alloc = gfc_evaluate_now (se2.expr, &se.pre);
6953 gfc_add_block_to_block (&se.pre, &se2.post);
6955 else
6956 alloc = build_zero_cst (ptr_type_node);
6957 tmp = TREE_TYPE (TREE_TYPE (se.expr));
6958 if (tmp == void_type_node)
6959 tmp = gfc_typenode_for_spec (&expr->ts, 0);
6960 if (omp_alloc_item->u.align)
6962 gfc_init_se (&se2, NULL);
6963 gfc_conv_expr (&se2, omp_alloc_item->u.align);
6964 gcc_assert (CONSTANT_CLASS_P (se2.expr)
6965 && se2.pre.head == NULL
6966 && se2.post.head == NULL);
6967 align = build_int_cst (size_type_node,
6968 MAX (tree_to_uhwi (se2.expr),
6969 TYPE_ALIGN_UNIT (tmp)));
6971 else
6972 align = build_int_cst (size_type_node, TYPE_ALIGN_UNIT (tmp));
6973 sz = fold_build2_loc (input_location, MAX_EXPR, size_type_node,
6974 fold_convert (size_type_node, memsz),
6975 build_int_cst (size_type_node, 1));
6976 omp_alt_alloc = builtin_decl_explicit (BUILT_IN_GOMP_ALLOC);
6977 DECL_ATTRIBUTES (omp_alt_alloc)
6978 = tree_cons (get_identifier ("omp allocator"),
6979 build_tree_list (NULL_TREE, alloc),
6980 DECL_ATTRIBUTES (omp_alt_alloc));
6981 omp_alt_alloc = build_call_expr (omp_alt_alloc, 3, align, sz, alloc);
6982 succ_add_expr = gfc_omp_call_add_alloc (se.expr);
6985 /* Store the caf-attributes for latter use. */
6986 if (use_coarray_alloc)
6988 /* Scalar allocatable components in coarray'ed derived types make
6989 it here and are treated now. */
6990 tree caf_decl, token;
6991 gfc_se caf_se;
6993 is_coarray = true;
6994 /* Set flag, to add synchronize after the allocate. */
6995 needs_caf_sync = needs_caf_sync
6996 || caf_attr.coarray_comp || !caf_refs_comp;
6998 gfc_init_se (&caf_se, NULL);
7000 caf_decl = gfc_get_tree_for_caf_expr (expr);
7001 gfc_get_caf_token_offset (&caf_se, &token, NULL, caf_decl,
7002 NULL_TREE, NULL);
7003 gfc_add_block_to_block (&se.pre, &caf_se.pre);
7004 gfc_allocate_allocatable (&se.pre, se.expr, memsz,
7005 gfc_build_addr_expr (NULL_TREE, token),
7006 NULL_TREE, NULL_TREE, NULL_TREE,
7007 label_finish, expr, 1);
7009 /* Allocate - for non-pointers with re-alloc checking. */
7010 else if (gfc_expr_attr (expr).allocatable)
7011 gfc_allocate_allocatable (&se.pre, se.expr, memsz,
7012 NULL_TREE, stat, errmsg, errlen,
7013 label_finish, expr, 0,
7014 omp_cond, omp_alt_alloc, succ_add_expr);
7015 else
7016 gfc_allocate_using_malloc (&se.pre, se.expr, memsz, stat,
7017 omp_cond, omp_alt_alloc, succ_add_expr);
7019 else
7021 /* Allocating coarrays needs a sync after the allocate executed.
7022 Set the flag to add the sync after all objects are allocated. */
7023 if (flag_coarray == GFC_FCOARRAY_LIB
7024 && (caf_attr = gfc_caf_attr (expr, true, &caf_refs_comp))
7025 .codimension)
7027 is_coarray = true;
7028 needs_caf_sync = needs_caf_sync
7029 || caf_attr.coarray_comp || !caf_refs_comp;
7032 if (expr->ts.type == BT_CHARACTER && al_len != NULL_TREE
7033 && expr3_len != NULL_TREE)
7035 /* Arrays need to have a _len set before the array
7036 descriptor is filled. */
7037 gfc_add_modify (&block, al_len,
7038 fold_convert (TREE_TYPE (al_len), expr3_len));
7039 /* Prevent setting the length twice. */
7040 al_len_needs_set = false;
7042 else if (expr->ts.type == BT_CHARACTER && al_len != NULL_TREE
7043 && code->ext.alloc.ts.u.cl->length)
7045 /* Cover the cases where a string length is explicitly
7046 specified by a type spec for deferred length character
7047 arrays or unlimited polymorphic objects without a
7048 source= or mold= expression. */
7049 gfc_init_se (&se_sz, NULL);
7050 gfc_conv_expr (&se_sz, code->ext.alloc.ts.u.cl->length);
7051 gfc_add_block_to_block (&block, &se_sz.pre);
7052 gfc_add_modify (&block, al_len,
7053 fold_convert (TREE_TYPE (al_len),
7054 se_sz.expr));
7055 al_len_needs_set = false;
7059 gfc_add_block_to_block (&block, &se.pre);
7061 /* Error checking -- Note: ERRMSG only makes sense with STAT. */
7062 if (code->expr1)
7064 tmp = build1_v (GOTO_EXPR, label_errmsg);
7065 parm = fold_build2_loc (input_location, NE_EXPR,
7066 logical_type_node, stat,
7067 build_int_cst (TREE_TYPE (stat), 0));
7068 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
7069 gfc_unlikely (parm, PRED_FORTRAN_FAIL_ALLOC),
7070 tmp, build_empty_stmt (input_location));
7071 gfc_add_expr_to_block (&block, tmp);
7074 /* Set the vptr only when no source= is set. When source= is set, then
7075 the trans_assignment below will set the vptr. */
7076 if (al_vptr != NULL_TREE && (!code->expr3 || code->expr3->mold))
7078 if (expr3_vptr != NULL_TREE)
7079 /* The vtab is already known, so just assign it. */
7080 gfc_add_modify (&block, al_vptr,
7081 fold_convert (TREE_TYPE (al_vptr), expr3_vptr));
7082 else
7084 /* VPTR is fixed at compile time. */
7085 gfc_symbol *vtab;
7086 gfc_typespec *ts;
7088 if (code->expr3)
7089 /* Although expr3 is pre-evaluated above, it may happen,
7090 that for arrays or in mold= cases the pre-evaluation
7091 was not successful. In these rare cases take the vtab
7092 from the typespec of expr3 here. */
7093 ts = &code->expr3->ts;
7094 else if (code->ext.alloc.ts.type == BT_DERIVED || upoly_expr)
7095 /* The alloc_type_spec gives the type to allocate or the
7096 al is unlimited polymorphic, which enforces the use of
7097 an alloc_type_spec that is not necessarily a BT_DERIVED. */
7098 ts = &code->ext.alloc.ts;
7099 else
7100 /* Prepare for setting the vtab as declared. */
7101 ts = &expr->ts;
7103 vtab = gfc_find_vtab (ts);
7104 gcc_assert (vtab);
7105 tmp = gfc_build_addr_expr (NULL_TREE,
7106 gfc_get_symbol_decl (vtab));
7107 gfc_add_modify (&block, al_vptr,
7108 fold_convert (TREE_TYPE (al_vptr), tmp));
7112 /* Add assignment for string length. */
7113 if (al_len != NULL_TREE && al_len_needs_set)
7115 if (expr3_len != NULL_TREE)
7117 gfc_add_modify (&block, al_len,
7118 fold_convert (TREE_TYPE (al_len),
7119 expr3_len));
7120 /* When tmp_expr3_len_flag is set, then expr3_len is
7121 abused to carry the length information from the
7122 alloc_type. Clear it to prevent setting incorrect len
7123 information in future loop iterations. */
7124 if (tmp_expr3_len_flag)
7125 /* No need to reset tmp_expr3_len_flag, because the
7126 presence of an expr3 cannot change within in the
7127 loop. */
7128 expr3_len = NULL_TREE;
7130 else if (code->ext.alloc.ts.type == BT_CHARACTER
7131 && code->ext.alloc.ts.u.cl->length)
7133 /* Cover the cases where a string length is explicitly
7134 specified by a type spec for deferred length character
7135 arrays or unlimited polymorphic objects without a
7136 source= or mold= expression. */
7137 if (expr3_esize == NULL_TREE || code->ext.alloc.ts.kind != 1)
7139 gfc_init_se (&se_sz, NULL);
7140 gfc_conv_expr (&se_sz, code->ext.alloc.ts.u.cl->length);
7141 gfc_add_block_to_block (&block, &se_sz.pre);
7142 gfc_add_modify (&block, al_len,
7143 fold_convert (TREE_TYPE (al_len),
7144 se_sz.expr));
7146 else
7147 gfc_add_modify (&block, al_len,
7148 fold_convert (TREE_TYPE (al_len),
7149 expr3_esize));
7151 else
7152 /* No length information needed, because type to allocate
7153 has no length. Set _len to 0. */
7154 gfc_add_modify (&block, al_len,
7155 fold_convert (TREE_TYPE (al_len),
7156 integer_zero_node));
7159 init_expr = NULL;
7160 if (code->expr3 && !code->expr3->mold && e3_is != E3_MOLD)
7162 /* Initialization via SOURCE block (or static default initializer).
7163 Switch off automatic reallocation since we have just done the
7164 ALLOCATE. */
7165 int realloc_lhs = flag_realloc_lhs;
7166 gfc_expr *init_expr = gfc_expr_to_initialize (expr);
7167 gfc_expr *rhs = e3rhs ? e3rhs : gfc_copy_expr (code->expr3);
7168 flag_realloc_lhs = 0;
7170 /* Set the symbol to be artificial so that the result is not finalized. */
7171 init_expr->symtree->n.sym->attr.artificial = 1;
7172 tmp = gfc_trans_assignment (init_expr, rhs, true, false, true,
7173 false);
7174 init_expr->symtree->n.sym->attr.artificial = 0;
7176 flag_realloc_lhs = realloc_lhs;
7177 /* Free the expression allocated for init_expr. */
7178 gfc_free_expr (init_expr);
7179 if (rhs != e3rhs)
7180 gfc_free_expr (rhs);
7181 gfc_add_expr_to_block (&block, tmp);
7183 /* Set KIND and LEN PDT components and allocate those that are
7184 parameterized. */
7185 else if (expr->ts.type == BT_DERIVED
7186 && expr->ts.u.derived->attr.pdt_type)
7188 if (code->expr3 && code->expr3->param_list)
7189 param_list = code->expr3->param_list;
7190 else if (expr->param_list)
7191 param_list = expr->param_list;
7192 else
7193 param_list = expr->symtree->n.sym->param_list;
7194 tmp = gfc_allocate_pdt_comp (expr->ts.u.derived, se.expr,
7195 expr->rank, param_list);
7196 gfc_add_expr_to_block (&block, tmp);
7198 /* Ditto for CLASS expressions. */
7199 else if (expr->ts.type == BT_CLASS
7200 && CLASS_DATA (expr)->ts.u.derived->attr.pdt_type)
7202 if (code->expr3 && code->expr3->param_list)
7203 param_list = code->expr3->param_list;
7204 else if (expr->param_list)
7205 param_list = expr->param_list;
7206 else
7207 param_list = expr->symtree->n.sym->param_list;
7208 tmp = gfc_allocate_pdt_comp (CLASS_DATA (expr)->ts.u.derived,
7209 se.expr, expr->rank, param_list);
7210 gfc_add_expr_to_block (&block, tmp);
7212 else if (code->expr3 && code->expr3->mold
7213 && code->expr3->ts.type == BT_CLASS)
7215 /* Use class_init_assign to initialize expr. */
7216 gfc_code *ini;
7217 ini = gfc_get_code (EXEC_INIT_ASSIGN);
7218 ini->expr1 = gfc_find_and_cut_at_last_class_ref (expr, true);
7219 tmp = gfc_trans_class_init_assign (ini);
7220 gfc_free_statements (ini);
7221 gfc_add_expr_to_block (&block, tmp);
7223 else if ((init_expr = allocate_get_initializer (code, expr)))
7225 /* Use class_init_assign to initialize expr. */
7226 gfc_code *ini;
7227 int realloc_lhs = flag_realloc_lhs;
7228 ini = gfc_get_code (EXEC_INIT_ASSIGN);
7229 ini->expr1 = gfc_expr_to_initialize (expr);
7230 ini->expr2 = init_expr;
7231 flag_realloc_lhs = 0;
7232 tmp= gfc_trans_init_assign (ini);
7233 flag_realloc_lhs = realloc_lhs;
7234 gfc_free_statements (ini);
7235 /* Init_expr is freeed by above free_statements, just need to null
7236 it here. */
7237 init_expr = NULL;
7238 gfc_add_expr_to_block (&block, tmp);
7241 /* Nullify all pointers in derived type coarrays. This registers a
7242 token for them which allows their allocation. */
7243 if (is_coarray)
7245 gfc_symbol *type = NULL;
7246 symbol_attribute caf_attr;
7247 int rank = 0;
7248 if (code->ext.alloc.ts.type == BT_DERIVED
7249 && code->ext.alloc.ts.u.derived->attr.pointer_comp)
7251 type = code->ext.alloc.ts.u.derived;
7252 rank = type->attr.dimension ? type->as->rank : 0;
7253 gfc_clear_attr (&caf_attr);
7255 else if (expr->ts.type == BT_DERIVED
7256 && expr->ts.u.derived->attr.pointer_comp)
7258 type = expr->ts.u.derived;
7259 rank = expr->rank;
7260 caf_attr = gfc_caf_attr (expr, true);
7263 /* Initialize the tokens of pointer components in derived type
7264 coarrays. */
7265 if (type)
7267 tmp = (caf_attr.codimension && !caf_attr.dimension)
7268 ? gfc_conv_descriptor_data_get (se.expr) : se.expr;
7269 tmp = gfc_nullify_alloc_comp (type, tmp, rank,
7270 GFC_STRUCTURE_CAF_MODE_IN_COARRAY);
7271 gfc_add_expr_to_block (&block, tmp);
7275 gfc_free_expr (expr);
7276 } // for-loop
7278 if (e3rhs)
7280 if (newsym)
7282 gfc_free_symbol (newsym->n.sym);
7283 XDELETE (newsym);
7285 gfc_free_expr (e3rhs);
7287 /* STAT. */
7288 if (code->expr1)
7290 tmp = build1_v (LABEL_EXPR, label_errmsg);
7291 gfc_add_expr_to_block (&block, tmp);
7294 /* ERRMSG - only useful if STAT is present. */
7295 if (code->expr1 && code->expr2)
7297 const char *msg = "Attempt to allocate an allocated object";
7298 const char *oommsg = "Insufficient virtual memory";
7299 tree slen, dlen, errmsg_str, oom_str, oom_loc;
7300 stmtblock_t errmsg_block;
7302 gfc_init_block (&errmsg_block);
7304 errmsg_str = gfc_create_var (pchar_type_node, "ERRMSG");
7305 gfc_add_modify (&errmsg_block, errmsg_str,
7306 gfc_build_addr_expr (pchar_type_node,
7307 gfc_build_localized_cstring_const (msg)));
7309 slen = build_int_cst (gfc_charlen_type_node, strlen (msg));
7310 dlen = gfc_get_expr_charlen (code->expr2);
7311 slen = fold_build2_loc (input_location, MIN_EXPR,
7312 TREE_TYPE (slen), dlen, slen);
7314 gfc_trans_string_copy (&errmsg_block, dlen, errmsg,
7315 code->expr2->ts.kind,
7316 slen, errmsg_str,
7317 gfc_default_character_kind);
7318 dlen = gfc_finish_block (&errmsg_block);
7320 tmp = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
7321 stat, build_int_cst (TREE_TYPE (stat),
7322 LIBERROR_ALLOCATION));
7324 tmp = build3_v (COND_EXPR, tmp,
7325 dlen, build_empty_stmt (input_location));
7327 gfc_add_expr_to_block (&block, tmp);
7329 oom_str = gfc_create_var (pchar_type_node, "OOMMSG");
7330 oom_loc = gfc_build_localized_cstring_const (oommsg);
7331 gfc_add_modify (&errmsg_block, oom_str,
7332 gfc_build_addr_expr (pchar_type_node, oom_loc));
7334 slen = build_int_cst (gfc_charlen_type_node, strlen (oommsg));
7335 dlen = gfc_get_expr_charlen (code->expr2);
7336 slen = fold_build2_loc (input_location, MIN_EXPR,
7337 TREE_TYPE (slen), dlen, slen);
7339 gfc_trans_string_copy (&errmsg_block, dlen, errmsg,
7340 code->expr2->ts.kind,
7341 slen, oom_str,
7342 gfc_default_character_kind);
7343 dlen = gfc_finish_block (&errmsg_block);
7345 tmp = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
7346 stat, build_int_cst (TREE_TYPE (stat),
7347 LIBERROR_NO_MEMORY));
7349 tmp = build3_v (COND_EXPR, tmp,
7350 dlen, build_empty_stmt (input_location));
7352 gfc_add_expr_to_block (&block, tmp);
7355 /* STAT block. */
7356 if (code->expr1)
7358 if (TREE_USED (label_finish))
7360 tmp = build1_v (LABEL_EXPR, label_finish);
7361 gfc_add_expr_to_block (&block, tmp);
7364 gfc_init_se (&se, NULL);
7365 gfc_conv_expr_lhs (&se, code->expr1);
7366 tmp = convert (TREE_TYPE (se.expr), stat);
7367 gfc_add_modify (&block, se.expr, tmp);
7370 if (needs_caf_sync)
7372 /* Add a sync all after the allocation has been executed. */
7373 tree zero_size = build_zero_cst (size_type_node);
7374 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sync_all,
7375 3, null_pointer_node, null_pointer_node,
7376 zero_size);
7377 gfc_add_expr_to_block (&post, tmp);
7380 gfc_add_block_to_block (&block, &se.post);
7381 gfc_add_block_to_block (&block, &post);
7382 if (code->expr3 && code->expr3->must_finalize)
7383 gfc_add_block_to_block (&block, &final_block);
7385 return gfc_finish_block (&block);
7389 /* Translate a DEALLOCATE statement. */
7391 tree
7392 gfc_trans_deallocate (gfc_code *code)
7394 gfc_se se;
7395 gfc_alloc *al;
7396 tree apstat, pstat, stat, errmsg, errlen, tmp;
7397 tree label_finish, label_errmsg;
7398 stmtblock_t block;
7400 pstat = apstat = stat = errmsg = errlen = tmp = NULL_TREE;
7401 label_finish = label_errmsg = NULL_TREE;
7403 gfc_start_block (&block);
7405 /* Count the number of failed deallocations. If deallocate() was
7406 called with STAT= , then set STAT to the count. If deallocate
7407 was called with ERRMSG, then set ERRMG to a string. */
7408 if (code->expr1)
7410 tree gfc_int4_type_node = gfc_get_int_type (4);
7412 stat = gfc_create_var (gfc_int4_type_node, "stat");
7413 pstat = gfc_build_addr_expr (NULL_TREE, stat);
7415 /* GOTO destinations. */
7416 label_errmsg = gfc_build_label_decl (NULL_TREE);
7417 label_finish = gfc_build_label_decl (NULL_TREE);
7418 TREE_USED (label_finish) = 0;
7421 /* Set ERRMSG - only needed if STAT is available. */
7422 if (code->expr1 && code->expr2)
7424 gfc_init_se (&se, NULL);
7425 se.want_pointer = 1;
7426 gfc_conv_expr_lhs (&se, code->expr2);
7427 errmsg = se.expr;
7428 errlen = se.string_length;
7431 for (al = code->ext.alloc.list; al != NULL; al = al->next)
7433 gfc_expr *expr = gfc_copy_expr (al->expr);
7434 bool is_coarray = false, is_coarray_array = false;
7435 int caf_mode = 0;
7437 gcc_assert (expr->expr_type == EXPR_VARIABLE);
7439 if (expr->ts.type == BT_CLASS)
7440 gfc_add_data_component (expr);
7442 gfc_init_se (&se, NULL);
7443 gfc_start_block (&se.pre);
7445 se.want_pointer = 1;
7446 se.descriptor_only = 1;
7447 gfc_conv_expr (&se, expr);
7449 /* Deallocate PDT components that are parameterized. */
7450 tmp = NULL;
7451 if (expr->ts.type == BT_DERIVED
7452 && expr->ts.u.derived->attr.pdt_type
7453 && expr->symtree->n.sym->param_list)
7454 tmp = gfc_deallocate_pdt_comp (expr->ts.u.derived, se.expr, expr->rank);
7455 else if (expr->ts.type == BT_CLASS
7456 && CLASS_DATA (expr)->ts.u.derived->attr.pdt_type
7457 && expr->symtree->n.sym->param_list)
7458 tmp = gfc_deallocate_pdt_comp (CLASS_DATA (expr)->ts.u.derived,
7459 se.expr, expr->rank);
7461 if (tmp)
7462 gfc_add_expr_to_block (&block, tmp);
7464 if (flag_coarray == GFC_FCOARRAY_LIB
7465 || flag_coarray == GFC_FCOARRAY_SINGLE)
7467 bool comp_ref;
7468 symbol_attribute caf_attr = gfc_caf_attr (expr, false, &comp_ref);
7469 if (caf_attr.codimension)
7471 is_coarray = true;
7472 is_coarray_array = caf_attr.dimension || !comp_ref
7473 || caf_attr.coarray_comp;
7475 if (flag_coarray == GFC_FCOARRAY_LIB)
7476 /* When the expression to deallocate is referencing a
7477 component, then only deallocate it, but do not
7478 deregister. */
7479 caf_mode = GFC_STRUCTURE_CAF_MODE_IN_COARRAY
7480 | (comp_ref && !caf_attr.coarray_comp
7481 ? GFC_STRUCTURE_CAF_MODE_DEALLOC_ONLY : 0);
7485 if (expr->rank || is_coarray_array)
7487 gfc_ref *ref;
7489 if (gfc_bt_struct (expr->ts.type)
7490 && expr->ts.u.derived->attr.alloc_comp
7491 && !gfc_is_finalizable (expr->ts.u.derived, NULL))
7493 gfc_ref *last = NULL;
7495 for (ref = expr->ref; ref; ref = ref->next)
7496 if (ref->type == REF_COMPONENT)
7497 last = ref;
7499 /* Do not deallocate the components of a derived type
7500 ultimate pointer component. */
7501 if (!(last && last->u.c.component->attr.pointer)
7502 && !(!last && expr->symtree->n.sym->attr.pointer))
7504 if (is_coarray && expr->rank == 0
7505 && (!last || !last->u.c.component->attr.dimension)
7506 && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (se.expr)))
7508 /* Add the ref to the data member only, when this is not
7509 a regular array or deallocate_alloc_comp will try to
7510 add another one. */
7511 tmp = gfc_conv_descriptor_data_get (se.expr);
7513 else
7514 tmp = se.expr;
7515 tmp = gfc_deallocate_alloc_comp (expr->ts.u.derived, tmp,
7516 expr->rank, caf_mode);
7517 gfc_add_expr_to_block (&se.pre, tmp);
7521 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (se.expr)))
7523 gfc_coarray_deregtype caf_dtype;
7525 if (is_coarray)
7526 caf_dtype = gfc_caf_is_dealloc_only (caf_mode)
7527 ? GFC_CAF_COARRAY_DEALLOCATE_ONLY
7528 : GFC_CAF_COARRAY_DEREGISTER;
7529 else
7530 caf_dtype = GFC_CAF_COARRAY_NOCOARRAY;
7531 tmp = gfc_deallocate_with_status (se.expr, pstat, errmsg, errlen,
7532 label_finish, false, expr,
7533 caf_dtype);
7534 gfc_add_expr_to_block (&se.pre, tmp);
7536 else if (TREE_CODE (se.expr) == COMPONENT_REF
7537 && TREE_CODE (TREE_TYPE (se.expr)) == ARRAY_TYPE
7538 && TREE_CODE (TREE_TYPE (TREE_TYPE (se.expr)))
7539 == RECORD_TYPE)
7541 /* class.cc(finalize_component) generates these, when a
7542 finalizable entity has a non-allocatable derived type array
7543 component, which has allocatable components. Obtain the
7544 derived type of the array and deallocate the allocatable
7545 components. */
7546 for (ref = expr->ref; ref; ref = ref->next)
7548 if (ref->u.c.component->attr.dimension
7549 && ref->u.c.component->ts.type == BT_DERIVED)
7550 break;
7553 if (ref && ref->u.c.component->ts.u.derived->attr.alloc_comp
7554 && !gfc_is_finalizable (ref->u.c.component->ts.u.derived,
7555 NULL))
7557 tmp = gfc_deallocate_alloc_comp
7558 (ref->u.c.component->ts.u.derived,
7559 se.expr, expr->rank);
7560 gfc_add_expr_to_block (&se.pre, tmp);
7564 if (al->expr->ts.type == BT_CLASS)
7566 gfc_reset_vptr (&se.pre, al->expr);
7567 if (UNLIMITED_POLY (al->expr)
7568 || (al->expr->ts.type == BT_DERIVED
7569 && al->expr->ts.u.derived->attr.unlimited_polymorphic))
7570 /* Clear _len, too. */
7571 gfc_reset_len (&se.pre, al->expr);
7574 else
7576 tmp = gfc_deallocate_scalar_with_status (se.expr, pstat, label_finish,
7577 false, al->expr,
7578 al->expr->ts, NULL_TREE,
7579 is_coarray);
7580 gfc_add_expr_to_block (&se.pre, tmp);
7582 /* Set to zero after deallocation. */
7583 tmp = fold_build2_loc (input_location, MODIFY_EXPR, void_type_node,
7584 se.expr,
7585 build_int_cst (TREE_TYPE (se.expr), 0));
7586 gfc_add_expr_to_block (&se.pre, tmp);
7588 if (al->expr->ts.type == BT_CLASS)
7590 gfc_reset_vptr (&se.pre, al->expr);
7591 if (UNLIMITED_POLY (al->expr)
7592 || (al->expr->ts.type == BT_DERIVED
7593 && al->expr->ts.u.derived->attr.unlimited_polymorphic))
7594 /* Clear _len, too. */
7595 gfc_reset_len (&se.pre, al->expr);
7599 if (code->expr1)
7601 tree cond;
7603 cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node, stat,
7604 build_int_cst (TREE_TYPE (stat), 0));
7605 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
7606 gfc_unlikely (cond, PRED_FORTRAN_FAIL_ALLOC),
7607 build1_v (GOTO_EXPR, label_errmsg),
7608 build_empty_stmt (input_location));
7609 gfc_add_expr_to_block (&se.pre, tmp);
7612 tmp = gfc_finish_block (&se.pre);
7613 gfc_add_expr_to_block (&block, tmp);
7614 gfc_free_expr (expr);
7617 if (code->expr1)
7619 tmp = build1_v (LABEL_EXPR, label_errmsg);
7620 gfc_add_expr_to_block (&block, tmp);
7623 /* Set ERRMSG - only needed if STAT is available. */
7624 if (code->expr1 && code->expr2)
7626 const char *msg = "Attempt to deallocate an unallocated object";
7627 stmtblock_t errmsg_block;
7628 tree errmsg_str, slen, dlen, cond;
7630 gfc_init_block (&errmsg_block);
7632 errmsg_str = gfc_create_var (pchar_type_node, "ERRMSG");
7633 gfc_add_modify (&errmsg_block, errmsg_str,
7634 gfc_build_addr_expr (pchar_type_node,
7635 gfc_build_localized_cstring_const (msg)));
7636 slen = build_int_cst (gfc_charlen_type_node, strlen (msg));
7637 dlen = gfc_get_expr_charlen (code->expr2);
7639 gfc_trans_string_copy (&errmsg_block, dlen, errmsg, code->expr2->ts.kind,
7640 slen, errmsg_str, gfc_default_character_kind);
7641 tmp = gfc_finish_block (&errmsg_block);
7643 cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node, stat,
7644 build_int_cst (TREE_TYPE (stat), 0));
7645 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
7646 gfc_unlikely (cond, PRED_FORTRAN_FAIL_ALLOC), tmp,
7647 build_empty_stmt (input_location));
7649 gfc_add_expr_to_block (&block, tmp);
7652 if (code->expr1 && TREE_USED (label_finish))
7654 tmp = build1_v (LABEL_EXPR, label_finish);
7655 gfc_add_expr_to_block (&block, tmp);
7658 /* Set STAT. */
7659 if (code->expr1)
7661 gfc_init_se (&se, NULL);
7662 gfc_conv_expr_lhs (&se, code->expr1);
7663 tmp = convert (TREE_TYPE (se.expr), stat);
7664 gfc_add_modify (&block, se.expr, tmp);
7667 return gfc_finish_block (&block);
7670 #include "gt-fortran-trans-stmt.h"