* doc/extend.texi (Loop-Specific Pragmas): Document pragma GCC unroll.
[official-gcc.git] / gcc / fortran / trans-stmt.c
blobe6569e020365b21585bff9d4f267769cba019df7
1 /* Statement translation -- generate GCC trees from gfc_code.
2 Copyright (C) 2002-2017 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 struct iter_info *next;
46 iter_info;
48 typedef struct forall_info
50 iter_info *this_loop;
51 tree mask;
52 tree maskindex;
53 int nvar;
54 tree size;
55 struct forall_info *prev_nest;
56 bool do_concurrent;
58 forall_info;
60 static void gfc_trans_where_2 (gfc_code *, tree, bool,
61 forall_info *, stmtblock_t *);
63 /* Translate a F95 label number to a LABEL_EXPR. */
65 tree
66 gfc_trans_label_here (gfc_code * code)
68 return build1_v (LABEL_EXPR, gfc_get_label_decl (code->here));
72 /* Given a variable expression which has been ASSIGNed to, find the decl
73 containing the auxiliary variables. For variables in common blocks this
74 is a field_decl. */
76 void
77 gfc_conv_label_variable (gfc_se * se, gfc_expr * expr)
79 gcc_assert (expr->symtree->n.sym->attr.assign == 1);
80 gfc_conv_expr (se, expr);
81 /* Deals with variable in common block. Get the field declaration. */
82 if (TREE_CODE (se->expr) == COMPONENT_REF)
83 se->expr = TREE_OPERAND (se->expr, 1);
84 /* Deals with dummy argument. Get the parameter declaration. */
85 else if (TREE_CODE (se->expr) == INDIRECT_REF)
86 se->expr = TREE_OPERAND (se->expr, 0);
89 /* Translate a label assignment statement. */
91 tree
92 gfc_trans_label_assign (gfc_code * code)
94 tree label_tree;
95 gfc_se se;
96 tree len;
97 tree addr;
98 tree len_tree;
99 int label_len;
101 /* Start a new block. */
102 gfc_init_se (&se, NULL);
103 gfc_start_block (&se.pre);
104 gfc_conv_label_variable (&se, code->expr1);
106 len = GFC_DECL_STRING_LEN (se.expr);
107 addr = GFC_DECL_ASSIGN_ADDR (se.expr);
109 label_tree = gfc_get_label_decl (code->label1);
111 if (code->label1->defined == ST_LABEL_TARGET
112 || code->label1->defined == ST_LABEL_DO_TARGET)
114 label_tree = gfc_build_addr_expr (pvoid_type_node, label_tree);
115 len_tree = integer_minus_one_node;
117 else
119 gfc_expr *format = code->label1->format;
121 label_len = format->value.character.length;
122 len_tree = build_int_cst (gfc_charlen_type_node, label_len);
123 label_tree = gfc_build_wide_string_const (format->ts.kind, label_len + 1,
124 format->value.character.string);
125 label_tree = gfc_build_addr_expr (pvoid_type_node, label_tree);
128 gfc_add_modify (&se.pre, len, len_tree);
129 gfc_add_modify (&se.pre, addr, label_tree);
131 return gfc_finish_block (&se.pre);
134 /* Translate a GOTO statement. */
136 tree
137 gfc_trans_goto (gfc_code * code)
139 locus loc = code->loc;
140 tree assigned_goto;
141 tree target;
142 tree tmp;
143 gfc_se se;
145 if (code->label1 != NULL)
146 return build1_v (GOTO_EXPR, gfc_get_label_decl (code->label1));
148 /* ASSIGNED GOTO. */
149 gfc_init_se (&se, NULL);
150 gfc_start_block (&se.pre);
151 gfc_conv_label_variable (&se, code->expr1);
152 tmp = GFC_DECL_STRING_LEN (se.expr);
153 tmp = fold_build2_loc (input_location, NE_EXPR, logical_type_node, tmp,
154 build_int_cst (TREE_TYPE (tmp), -1));
155 gfc_trans_runtime_check (true, false, tmp, &se.pre, &loc,
156 "Assigned label is not a target label");
158 assigned_goto = GFC_DECL_ASSIGN_ADDR (se.expr);
160 /* We're going to ignore a label list. It does not really change the
161 statement's semantics (because it is just a further restriction on
162 what's legal code); before, we were comparing label addresses here, but
163 that's a very fragile business and may break with optimization. So
164 just ignore it. */
166 target = fold_build1_loc (input_location, GOTO_EXPR, void_type_node,
167 assigned_goto);
168 gfc_add_expr_to_block (&se.pre, target);
169 return gfc_finish_block (&se.pre);
173 /* Translate an ENTRY statement. Just adds a label for this entry point. */
174 tree
175 gfc_trans_entry (gfc_code * code)
177 return build1_v (LABEL_EXPR, code->ext.entry->label);
181 /* Replace a gfc_ss structure by another both in the gfc_se struct
182 and the gfc_loopinfo struct. This is used in gfc_conv_elemental_dependencies
183 to replace a variable ss by the corresponding temporary. */
185 static void
186 replace_ss (gfc_se *se, gfc_ss *old_ss, gfc_ss *new_ss)
188 gfc_ss **sess, **loopss;
190 /* The old_ss is a ss for a single variable. */
191 gcc_assert (old_ss->info->type == GFC_SS_SECTION);
193 for (sess = &(se->ss); *sess != gfc_ss_terminator; sess = &((*sess)->next))
194 if (*sess == old_ss)
195 break;
196 gcc_assert (*sess != gfc_ss_terminator);
198 *sess = new_ss;
199 new_ss->next = old_ss->next;
202 for (loopss = &(se->loop->ss); *loopss != gfc_ss_terminator;
203 loopss = &((*loopss)->loop_chain))
204 if (*loopss == old_ss)
205 break;
206 gcc_assert (*loopss != gfc_ss_terminator);
208 *loopss = new_ss;
209 new_ss->loop_chain = old_ss->loop_chain;
210 new_ss->loop = old_ss->loop;
212 gfc_free_ss (old_ss);
216 /* Check for dependencies between INTENT(IN) and INTENT(OUT) arguments of
217 elemental subroutines. Make temporaries for output arguments if any such
218 dependencies are found. Output arguments are chosen because internal_unpack
219 can be used, as is, to copy the result back to the variable. */
220 static void
221 gfc_conv_elemental_dependencies (gfc_se * se, gfc_se * loopse,
222 gfc_symbol * sym, gfc_actual_arglist * arg,
223 gfc_dep_check check_variable)
225 gfc_actual_arglist *arg0;
226 gfc_expr *e;
227 gfc_formal_arglist *formal;
228 gfc_se parmse;
229 gfc_ss *ss;
230 gfc_symbol *fsym;
231 tree data;
232 tree size;
233 tree tmp;
235 if (loopse->ss == NULL)
236 return;
238 ss = loopse->ss;
239 arg0 = arg;
240 formal = gfc_sym_get_dummy_args (sym);
242 /* Loop over all the arguments testing for dependencies. */
243 for (; arg != NULL; arg = arg->next, formal = formal ? formal->next : NULL)
245 e = arg->expr;
246 if (e == NULL)
247 continue;
249 /* Obtain the info structure for the current argument. */
250 for (ss = loopse->ss; ss && ss != gfc_ss_terminator; ss = ss->next)
251 if (ss->info->expr == e)
252 break;
254 /* If there is a dependency, create a temporary and use it
255 instead of the variable. */
256 fsym = formal ? formal->sym : NULL;
257 if (e->expr_type == EXPR_VARIABLE
258 && e->rank && fsym
259 && fsym->attr.intent != INTENT_IN
260 && gfc_check_fncall_dependency (e, fsym->attr.intent,
261 sym, arg0, check_variable))
263 tree initial, temptype;
264 stmtblock_t temp_post;
265 gfc_ss *tmp_ss;
267 tmp_ss = gfc_get_array_ss (gfc_ss_terminator, NULL, ss->dimen,
268 GFC_SS_SECTION);
269 gfc_mark_ss_chain_used (tmp_ss, 1);
270 tmp_ss->info->expr = ss->info->expr;
271 replace_ss (loopse, ss, tmp_ss);
273 /* Obtain the argument descriptor for unpacking. */
274 gfc_init_se (&parmse, NULL);
275 parmse.want_pointer = 1;
276 gfc_conv_expr_descriptor (&parmse, e);
277 gfc_add_block_to_block (&se->pre, &parmse.pre);
279 /* If we've got INTENT(INOUT) or a derived type with INTENT(OUT),
280 initialize the array temporary with a copy of the values. */
281 if (fsym->attr.intent == INTENT_INOUT
282 || (fsym->ts.type ==BT_DERIVED
283 && fsym->attr.intent == INTENT_OUT))
284 initial = parmse.expr;
285 /* For class expressions, we always initialize with the copy of
286 the values. */
287 else if (e->ts.type == BT_CLASS)
288 initial = parmse.expr;
289 else
290 initial = NULL_TREE;
292 if (e->ts.type != BT_CLASS)
294 /* Find the type of the temporary to create; we don't use the type
295 of e itself as this breaks for subcomponent-references in e
296 (where the type of e is that of the final reference, but
297 parmse.expr's type corresponds to the full derived-type). */
298 /* TODO: Fix this somehow so we don't need a temporary of the whole
299 array but instead only the components referenced. */
300 temptype = TREE_TYPE (parmse.expr); /* Pointer to descriptor. */
301 gcc_assert (TREE_CODE (temptype) == POINTER_TYPE);
302 temptype = TREE_TYPE (temptype);
303 temptype = gfc_get_element_type (temptype);
306 else
307 /* For class arrays signal that the size of the dynamic type has to
308 be obtained from the vtable, using the 'initial' expression. */
309 temptype = NULL_TREE;
311 /* Generate the temporary. Cleaning up the temporary should be the
312 very last thing done, so we add the code to a new block and add it
313 to se->post as last instructions. */
314 size = gfc_create_var (gfc_array_index_type, NULL);
315 data = gfc_create_var (pvoid_type_node, NULL);
316 gfc_init_block (&temp_post);
317 tmp = gfc_trans_create_temp_array (&se->pre, &temp_post, tmp_ss,
318 temptype, initial, false, true,
319 false, &arg->expr->where);
320 gfc_add_modify (&se->pre, size, tmp);
321 tmp = fold_convert (pvoid_type_node, tmp_ss->info->data.array.data);
322 gfc_add_modify (&se->pre, data, tmp);
324 /* Update other ss' delta. */
325 gfc_set_delta (loopse->loop);
327 /* Copy the result back using unpack..... */
328 if (e->ts.type != BT_CLASS)
329 tmp = build_call_expr_loc (input_location,
330 gfor_fndecl_in_unpack, 2, parmse.expr, data);
331 else
333 /* ... except for class results where the copy is
334 unconditional. */
335 tmp = build_fold_indirect_ref_loc (input_location, parmse.expr);
336 tmp = gfc_conv_descriptor_data_get (tmp);
337 tmp = build_call_expr_loc (input_location,
338 builtin_decl_explicit (BUILT_IN_MEMCPY),
339 3, tmp, data,
340 fold_convert (size_type_node, size));
342 gfc_add_expr_to_block (&se->post, tmp);
344 /* parmse.pre is already added above. */
345 gfc_add_block_to_block (&se->post, &parmse.post);
346 gfc_add_block_to_block (&se->post, &temp_post);
352 /* Get the interface symbol for the procedure corresponding to the given call.
353 We can't get the procedure symbol directly as we have to handle the case
354 of (deferred) type-bound procedures. */
356 static gfc_symbol *
357 get_proc_ifc_for_call (gfc_code *c)
359 gfc_symbol *sym;
361 gcc_assert (c->op == EXEC_ASSIGN_CALL || c->op == EXEC_CALL);
363 sym = gfc_get_proc_ifc_for_expr (c->expr1);
365 /* Fall back/last resort try. */
366 if (sym == NULL)
367 sym = c->resolved_sym;
369 return sym;
373 /* Translate the CALL statement. Builds a call to an F95 subroutine. */
375 tree
376 gfc_trans_call (gfc_code * code, bool dependency_check,
377 tree mask, tree count1, bool invert)
379 gfc_se se;
380 gfc_ss * ss;
381 int has_alternate_specifier;
382 gfc_dep_check check_variable;
383 tree index = NULL_TREE;
384 tree maskexpr = NULL_TREE;
385 tree tmp;
387 /* A CALL starts a new block because the actual arguments may have to
388 be evaluated first. */
389 gfc_init_se (&se, NULL);
390 gfc_start_block (&se.pre);
392 gcc_assert (code->resolved_sym);
394 ss = gfc_ss_terminator;
395 if (code->resolved_sym->attr.elemental)
396 ss = gfc_walk_elemental_function_args (ss, code->ext.actual,
397 get_proc_ifc_for_call (code),
398 GFC_SS_REFERENCE);
400 /* Is not an elemental subroutine call with array valued arguments. */
401 if (ss == gfc_ss_terminator)
404 /* Translate the call. */
405 has_alternate_specifier
406 = gfc_conv_procedure_call (&se, code->resolved_sym, code->ext.actual,
407 code->expr1, NULL);
409 /* A subroutine without side-effect, by definition, does nothing! */
410 TREE_SIDE_EFFECTS (se.expr) = 1;
412 /* Chain the pieces together and return the block. */
413 if (has_alternate_specifier)
415 gfc_code *select_code;
416 gfc_symbol *sym;
417 select_code = code->next;
418 gcc_assert(select_code->op == EXEC_SELECT);
419 sym = select_code->expr1->symtree->n.sym;
420 se.expr = convert (gfc_typenode_for_spec (&sym->ts), se.expr);
421 if (sym->backend_decl == NULL)
422 sym->backend_decl = gfc_get_symbol_decl (sym);
423 gfc_add_modify (&se.pre, sym->backend_decl, se.expr);
425 else
426 gfc_add_expr_to_block (&se.pre, se.expr);
428 gfc_add_block_to_block (&se.pre, &se.post);
431 else
433 /* An elemental subroutine call with array valued arguments has
434 to be scalarized. */
435 gfc_loopinfo loop;
436 stmtblock_t body;
437 stmtblock_t block;
438 gfc_se loopse;
439 gfc_se depse;
441 /* gfc_walk_elemental_function_args renders the ss chain in the
442 reverse order to the actual argument order. */
443 ss = gfc_reverse_ss (ss);
445 /* Initialize the loop. */
446 gfc_init_se (&loopse, NULL);
447 gfc_init_loopinfo (&loop);
448 gfc_add_ss_to_loop (&loop, ss);
450 gfc_conv_ss_startstride (&loop);
451 /* TODO: gfc_conv_loop_setup generates a temporary for vector
452 subscripts. This could be prevented in the elemental case
453 as temporaries are handled separatedly
454 (below in gfc_conv_elemental_dependencies). */
455 if (code->expr1)
456 gfc_conv_loop_setup (&loop, &code->expr1->where);
457 else
458 gfc_conv_loop_setup (&loop, &code->loc);
460 gfc_mark_ss_chain_used (ss, 1);
462 /* Convert the arguments, checking for dependencies. */
463 gfc_copy_loopinfo_to_se (&loopse, &loop);
464 loopse.ss = ss;
466 /* For operator assignment, do dependency checking. */
467 if (dependency_check)
468 check_variable = ELEM_CHECK_VARIABLE;
469 else
470 check_variable = ELEM_DONT_CHECK_VARIABLE;
472 gfc_init_se (&depse, NULL);
473 gfc_conv_elemental_dependencies (&depse, &loopse, code->resolved_sym,
474 code->ext.actual, check_variable);
476 gfc_add_block_to_block (&loop.pre, &depse.pre);
477 gfc_add_block_to_block (&loop.post, &depse.post);
479 /* Generate the loop body. */
480 gfc_start_scalarized_body (&loop, &body);
481 gfc_init_block (&block);
483 if (mask && count1)
485 /* Form the mask expression according to the mask. */
486 index = count1;
487 maskexpr = gfc_build_array_ref (mask, index, NULL);
488 if (invert)
489 maskexpr = fold_build1_loc (input_location, TRUTH_NOT_EXPR,
490 TREE_TYPE (maskexpr), maskexpr);
493 /* Add the subroutine call to the block. */
494 gfc_conv_procedure_call (&loopse, code->resolved_sym,
495 code->ext.actual, code->expr1,
496 NULL);
498 if (mask && count1)
500 tmp = build3_v (COND_EXPR, maskexpr, loopse.expr,
501 build_empty_stmt (input_location));
502 gfc_add_expr_to_block (&loopse.pre, tmp);
503 tmp = fold_build2_loc (input_location, PLUS_EXPR,
504 gfc_array_index_type,
505 count1, gfc_index_one_node);
506 gfc_add_modify (&loopse.pre, count1, tmp);
508 else
509 gfc_add_expr_to_block (&loopse.pre, loopse.expr);
511 gfc_add_block_to_block (&block, &loopse.pre);
512 gfc_add_block_to_block (&block, &loopse.post);
514 /* Finish up the loop block and the loop. */
515 gfc_add_expr_to_block (&body, gfc_finish_block (&block));
516 gfc_trans_scalarizing_loops (&loop, &body);
517 gfc_add_block_to_block (&se.pre, &loop.pre);
518 gfc_add_block_to_block (&se.pre, &loop.post);
519 gfc_add_block_to_block (&se.pre, &se.post);
520 gfc_cleanup_loop (&loop);
523 return gfc_finish_block (&se.pre);
527 /* Translate the RETURN statement. */
529 tree
530 gfc_trans_return (gfc_code * code)
532 if (code->expr1)
534 gfc_se se;
535 tree tmp;
536 tree result;
538 /* If code->expr is not NULL, this return statement must appear
539 in a subroutine and current_fake_result_decl has already
540 been generated. */
542 result = gfc_get_fake_result_decl (NULL, 0);
543 if (!result)
545 gfc_warning (0,
546 "An alternate return at %L without a * dummy argument",
547 &code->expr1->where);
548 return gfc_generate_return ();
551 /* Start a new block for this statement. */
552 gfc_init_se (&se, NULL);
553 gfc_start_block (&se.pre);
555 gfc_conv_expr (&se, code->expr1);
557 /* Note that the actually returned expression is a simple value and
558 does not depend on any pointers or such; thus we can clean-up with
559 se.post before returning. */
560 tmp = fold_build2_loc (input_location, MODIFY_EXPR, TREE_TYPE (result),
561 result, fold_convert (TREE_TYPE (result),
562 se.expr));
563 gfc_add_expr_to_block (&se.pre, tmp);
564 gfc_add_block_to_block (&se.pre, &se.post);
566 tmp = gfc_generate_return ();
567 gfc_add_expr_to_block (&se.pre, tmp);
568 return gfc_finish_block (&se.pre);
571 return gfc_generate_return ();
575 /* Translate the PAUSE statement. We have to translate this statement
576 to a runtime library call. */
578 tree
579 gfc_trans_pause (gfc_code * code)
581 tree gfc_int4_type_node = gfc_get_int_type (4);
582 gfc_se se;
583 tree tmp;
585 /* Start a new block for this statement. */
586 gfc_init_se (&se, NULL);
587 gfc_start_block (&se.pre);
590 if (code->expr1 == NULL)
592 tmp = build_int_cst (gfc_int4_type_node, 0);
593 tmp = build_call_expr_loc (input_location,
594 gfor_fndecl_pause_string, 2,
595 build_int_cst (pchar_type_node, 0), tmp);
597 else if (code->expr1->ts.type == BT_INTEGER)
599 gfc_conv_expr (&se, code->expr1);
600 tmp = build_call_expr_loc (input_location,
601 gfor_fndecl_pause_numeric, 1,
602 fold_convert (gfc_int4_type_node, se.expr));
604 else
606 gfc_conv_expr_reference (&se, code->expr1);
607 tmp = build_call_expr_loc (input_location,
608 gfor_fndecl_pause_string, 2,
609 se.expr, se.string_length);
612 gfc_add_expr_to_block (&se.pre, tmp);
614 gfc_add_block_to_block (&se.pre, &se.post);
616 return gfc_finish_block (&se.pre);
620 /* Translate the STOP statement. We have to translate this statement
621 to a runtime library call. */
623 tree
624 gfc_trans_stop (gfc_code *code, bool error_stop)
626 tree gfc_int4_type_node = gfc_get_int_type (4);
627 gfc_se se;
628 tree tmp;
630 /* Start a new block for this statement. */
631 gfc_init_se (&se, NULL);
632 gfc_start_block (&se.pre);
634 if (code->expr1 == NULL)
636 tmp = build_int_cst (gfc_int4_type_node, 0);
637 tmp = build_call_expr_loc (input_location,
638 error_stop
639 ? (flag_coarray == GFC_FCOARRAY_LIB
640 ? gfor_fndecl_caf_error_stop_str
641 : gfor_fndecl_error_stop_string)
642 : (flag_coarray == GFC_FCOARRAY_LIB
643 ? gfor_fndecl_caf_stop_str
644 : gfor_fndecl_stop_string),
645 2, build_int_cst (pchar_type_node, 0), tmp);
647 else if (code->expr1->ts.type == BT_INTEGER)
649 gfc_conv_expr (&se, code->expr1);
650 tmp = build_call_expr_loc (input_location,
651 error_stop
652 ? (flag_coarray == GFC_FCOARRAY_LIB
653 ? gfor_fndecl_caf_error_stop
654 : gfor_fndecl_error_stop_numeric)
655 : (flag_coarray == GFC_FCOARRAY_LIB
656 ? gfor_fndecl_caf_stop_numeric
657 : gfor_fndecl_stop_numeric), 1,
658 fold_convert (gfc_int4_type_node, se.expr));
660 else
662 gfc_conv_expr_reference (&se, code->expr1);
663 tmp = build_call_expr_loc (input_location,
664 error_stop
665 ? (flag_coarray == GFC_FCOARRAY_LIB
666 ? gfor_fndecl_caf_error_stop_str
667 : gfor_fndecl_error_stop_string)
668 : (flag_coarray == GFC_FCOARRAY_LIB
669 ? gfor_fndecl_caf_stop_str
670 : gfor_fndecl_stop_string),
671 2, se.expr, se.string_length);
674 gfc_add_expr_to_block (&se.pre, tmp);
676 gfc_add_block_to_block (&se.pre, &se.post);
678 return gfc_finish_block (&se.pre);
681 /* Translate the FAIL IMAGE statement. */
683 tree
684 gfc_trans_fail_image (gfc_code *code ATTRIBUTE_UNUSED)
686 if (flag_coarray == GFC_FCOARRAY_LIB)
687 return build_call_expr_loc (input_location,
688 gfor_fndecl_caf_fail_image, 1,
689 build_int_cst (pchar_type_node, 0));
690 else
692 const char *name = gfc_get_string (PREFIX ("exit_i%d"), 4);
693 gfc_symbol *exsym = gfc_get_intrinsic_sub_symbol (name);
694 tree tmp = gfc_get_symbol_decl (exsym);
695 return build_call_expr_loc (input_location, tmp, 1, integer_zero_node);
700 tree
701 gfc_trans_lock_unlock (gfc_code *code, gfc_exec_op op)
703 gfc_se se, argse;
704 tree stat = NULL_TREE, stat2 = NULL_TREE;
705 tree lock_acquired = NULL_TREE, lock_acquired2 = NULL_TREE;
707 /* Short cut: For single images without STAT= or LOCK_ACQUIRED
708 return early. (ERRMSG= is always untouched for -fcoarray=single.) */
709 if (!code->expr2 && !code->expr4 && flag_coarray != GFC_FCOARRAY_LIB)
710 return NULL_TREE;
712 if (code->expr2)
714 gcc_assert (code->expr2->expr_type == EXPR_VARIABLE);
715 gfc_init_se (&argse, NULL);
716 gfc_conv_expr_val (&argse, code->expr2);
717 stat = argse.expr;
719 else if (flag_coarray == GFC_FCOARRAY_LIB)
720 stat = null_pointer_node;
722 if (code->expr4)
724 gcc_assert (code->expr4->expr_type == EXPR_VARIABLE);
725 gfc_init_se (&argse, NULL);
726 gfc_conv_expr_val (&argse, code->expr4);
727 lock_acquired = argse.expr;
729 else if (flag_coarray == GFC_FCOARRAY_LIB)
730 lock_acquired = null_pointer_node;
732 gfc_start_block (&se.pre);
733 if (flag_coarray == GFC_FCOARRAY_LIB)
735 tree tmp, token, image_index, errmsg, errmsg_len;
736 tree index = size_zero_node;
737 tree caf_decl = gfc_get_tree_for_caf_expr (code->expr1);
739 if (code->expr1->symtree->n.sym->ts.type != BT_DERIVED
740 || code->expr1->symtree->n.sym->ts.u.derived->from_intmod
741 != INTMOD_ISO_FORTRAN_ENV
742 || code->expr1->symtree->n.sym->ts.u.derived->intmod_sym_id
743 != ISOFORTRAN_LOCK_TYPE)
745 gfc_error ("Sorry, the lock component of derived type at %L is not "
746 "yet supported", &code->expr1->where);
747 return NULL_TREE;
750 gfc_get_caf_token_offset (&se, &token, NULL, caf_decl, NULL_TREE,
751 code->expr1);
753 if (gfc_is_coindexed (code->expr1))
754 image_index = gfc_caf_get_image_index (&se.pre, code->expr1, caf_decl);
755 else
756 image_index = integer_zero_node;
758 /* For arrays, obtain the array index. */
759 if (gfc_expr_attr (code->expr1).dimension)
761 tree desc, tmp, extent, lbound, ubound;
762 gfc_array_ref *ar, ar2;
763 int i;
765 /* TODO: Extend this, once DT components are supported. */
766 ar = &code->expr1->ref->u.ar;
767 ar2 = *ar;
768 memset (ar, '\0', sizeof (*ar));
769 ar->as = ar2.as;
770 ar->type = AR_FULL;
772 gfc_init_se (&argse, NULL);
773 argse.descriptor_only = 1;
774 gfc_conv_expr_descriptor (&argse, code->expr1);
775 gfc_add_block_to_block (&se.pre, &argse.pre);
776 desc = argse.expr;
777 *ar = ar2;
779 extent = integer_one_node;
780 for (i = 0; i < ar->dimen; i++)
782 gfc_init_se (&argse, NULL);
783 gfc_conv_expr_type (&argse, ar->start[i], integer_type_node);
784 gfc_add_block_to_block (&argse.pre, &argse.pre);
785 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[i]);
786 tmp = fold_build2_loc (input_location, MINUS_EXPR,
787 integer_type_node, argse.expr,
788 fold_convert(integer_type_node, lbound));
789 tmp = fold_build2_loc (input_location, MULT_EXPR,
790 integer_type_node, extent, tmp);
791 index = fold_build2_loc (input_location, PLUS_EXPR,
792 integer_type_node, index, tmp);
793 if (i < ar->dimen - 1)
795 ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[i]);
796 tmp = gfc_conv_array_extent_dim (lbound, ubound, NULL);
797 tmp = fold_convert (integer_type_node, tmp);
798 extent = fold_build2_loc (input_location, MULT_EXPR,
799 integer_type_node, extent, tmp);
804 /* errmsg. */
805 if (code->expr3)
807 gfc_init_se (&argse, NULL);
808 argse.want_pointer = 1;
809 gfc_conv_expr (&argse, code->expr3);
810 gfc_add_block_to_block (&se.pre, &argse.pre);
811 errmsg = argse.expr;
812 errmsg_len = fold_convert (integer_type_node, argse.string_length);
814 else
816 errmsg = null_pointer_node;
817 errmsg_len = integer_zero_node;
820 if (stat != null_pointer_node && TREE_TYPE (stat) != integer_type_node)
822 stat2 = stat;
823 stat = gfc_create_var (integer_type_node, "stat");
826 if (lock_acquired != null_pointer_node
827 && TREE_TYPE (lock_acquired) != integer_type_node)
829 lock_acquired2 = lock_acquired;
830 lock_acquired = gfc_create_var (integer_type_node, "acquired");
833 if (op == EXEC_LOCK)
834 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_lock, 7,
835 token, index, image_index,
836 lock_acquired != null_pointer_node
837 ? gfc_build_addr_expr (NULL, lock_acquired)
838 : lock_acquired,
839 stat != null_pointer_node
840 ? gfc_build_addr_expr (NULL, stat) : stat,
841 errmsg, errmsg_len);
842 else
843 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_unlock, 6,
844 token, index, image_index,
845 stat != null_pointer_node
846 ? gfc_build_addr_expr (NULL, stat) : stat,
847 errmsg, errmsg_len);
848 gfc_add_expr_to_block (&se.pre, tmp);
850 /* It guarantees memory consistency within the same segment */
851 tmp = gfc_build_string_const (strlen ("memory")+1, "memory"),
852 tmp = build5_loc (input_location, ASM_EXPR, void_type_node,
853 gfc_build_string_const (1, ""), NULL_TREE, NULL_TREE,
854 tree_cons (NULL_TREE, tmp, NULL_TREE), NULL_TREE);
855 ASM_VOLATILE_P (tmp) = 1;
857 gfc_add_expr_to_block (&se.pre, tmp);
859 if (stat2 != NULL_TREE)
860 gfc_add_modify (&se.pre, stat2,
861 fold_convert (TREE_TYPE (stat2), stat));
863 if (lock_acquired2 != NULL_TREE)
864 gfc_add_modify (&se.pre, lock_acquired2,
865 fold_convert (TREE_TYPE (lock_acquired2),
866 lock_acquired));
868 return gfc_finish_block (&se.pre);
871 if (stat != NULL_TREE)
872 gfc_add_modify (&se.pre, stat, build_int_cst (TREE_TYPE (stat), 0));
874 if (lock_acquired != NULL_TREE)
875 gfc_add_modify (&se.pre, lock_acquired,
876 fold_convert (TREE_TYPE (lock_acquired),
877 boolean_true_node));
879 return gfc_finish_block (&se.pre);
882 tree
883 gfc_trans_event_post_wait (gfc_code *code, gfc_exec_op op)
885 gfc_se se, argse;
886 tree stat = NULL_TREE, stat2 = NULL_TREE;
887 tree until_count = NULL_TREE;
889 if (code->expr2)
891 gcc_assert (code->expr2->expr_type == EXPR_VARIABLE);
892 gfc_init_se (&argse, NULL);
893 gfc_conv_expr_val (&argse, code->expr2);
894 stat = argse.expr;
896 else if (flag_coarray == GFC_FCOARRAY_LIB)
897 stat = null_pointer_node;
899 if (code->expr4)
901 gfc_init_se (&argse, NULL);
902 gfc_conv_expr_val (&argse, code->expr4);
903 until_count = fold_convert (integer_type_node, argse.expr);
905 else
906 until_count = integer_one_node;
908 if (flag_coarray != GFC_FCOARRAY_LIB)
910 gfc_start_block (&se.pre);
911 gfc_init_se (&argse, NULL);
912 gfc_conv_expr_val (&argse, code->expr1);
914 if (op == EXEC_EVENT_POST)
915 gfc_add_modify (&se.pre, argse.expr,
916 fold_build2_loc (input_location, PLUS_EXPR,
917 TREE_TYPE (argse.expr), argse.expr,
918 build_int_cst (TREE_TYPE (argse.expr), 1)));
919 else
920 gfc_add_modify (&se.pre, argse.expr,
921 fold_build2_loc (input_location, MINUS_EXPR,
922 TREE_TYPE (argse.expr), argse.expr,
923 fold_convert (TREE_TYPE (argse.expr),
924 until_count)));
925 if (stat != NULL_TREE)
926 gfc_add_modify (&se.pre, stat, build_int_cst (TREE_TYPE (stat), 0));
928 return gfc_finish_block (&se.pre);
931 gfc_start_block (&se.pre);
932 tree tmp, token, image_index, errmsg, errmsg_len;
933 tree index = size_zero_node;
934 tree caf_decl = gfc_get_tree_for_caf_expr (code->expr1);
936 if (code->expr1->symtree->n.sym->ts.type != BT_DERIVED
937 || code->expr1->symtree->n.sym->ts.u.derived->from_intmod
938 != INTMOD_ISO_FORTRAN_ENV
939 || code->expr1->symtree->n.sym->ts.u.derived->intmod_sym_id
940 != ISOFORTRAN_EVENT_TYPE)
942 gfc_error ("Sorry, the event component of derived type at %L is not "
943 "yet supported", &code->expr1->where);
944 return NULL_TREE;
947 gfc_init_se (&argse, NULL);
948 gfc_get_caf_token_offset (&argse, &token, NULL, caf_decl, NULL_TREE,
949 code->expr1);
950 gfc_add_block_to_block (&se.pre, &argse.pre);
952 if (gfc_is_coindexed (code->expr1))
953 image_index = gfc_caf_get_image_index (&se.pre, code->expr1, caf_decl);
954 else
955 image_index = integer_zero_node;
957 /* For arrays, obtain the array index. */
958 if (gfc_expr_attr (code->expr1).dimension)
960 tree desc, tmp, extent, lbound, ubound;
961 gfc_array_ref *ar, ar2;
962 int i;
964 /* TODO: Extend this, once DT components are supported. */
965 ar = &code->expr1->ref->u.ar;
966 ar2 = *ar;
967 memset (ar, '\0', sizeof (*ar));
968 ar->as = ar2.as;
969 ar->type = AR_FULL;
971 gfc_init_se (&argse, NULL);
972 argse.descriptor_only = 1;
973 gfc_conv_expr_descriptor (&argse, code->expr1);
974 gfc_add_block_to_block (&se.pre, &argse.pre);
975 desc = argse.expr;
976 *ar = ar2;
978 extent = integer_one_node;
979 for (i = 0; i < ar->dimen; i++)
981 gfc_init_se (&argse, NULL);
982 gfc_conv_expr_type (&argse, ar->start[i], integer_type_node);
983 gfc_add_block_to_block (&argse.pre, &argse.pre);
984 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[i]);
985 tmp = fold_build2_loc (input_location, MINUS_EXPR,
986 integer_type_node, argse.expr,
987 fold_convert(integer_type_node, lbound));
988 tmp = fold_build2_loc (input_location, MULT_EXPR,
989 integer_type_node, extent, tmp);
990 index = fold_build2_loc (input_location, PLUS_EXPR,
991 integer_type_node, index, tmp);
992 if (i < ar->dimen - 1)
994 ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[i]);
995 tmp = gfc_conv_array_extent_dim (lbound, ubound, NULL);
996 tmp = fold_convert (integer_type_node, tmp);
997 extent = fold_build2_loc (input_location, MULT_EXPR,
998 integer_type_node, extent, tmp);
1003 /* errmsg. */
1004 if (code->expr3)
1006 gfc_init_se (&argse, NULL);
1007 argse.want_pointer = 1;
1008 gfc_conv_expr (&argse, code->expr3);
1009 gfc_add_block_to_block (&se.pre, &argse.pre);
1010 errmsg = argse.expr;
1011 errmsg_len = fold_convert (integer_type_node, argse.string_length);
1013 else
1015 errmsg = null_pointer_node;
1016 errmsg_len = integer_zero_node;
1019 if (stat != null_pointer_node && TREE_TYPE (stat) != integer_type_node)
1021 stat2 = stat;
1022 stat = gfc_create_var (integer_type_node, "stat");
1025 if (op == EXEC_EVENT_POST)
1026 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_event_post, 6,
1027 token, index, image_index,
1028 stat != null_pointer_node
1029 ? gfc_build_addr_expr (NULL, stat) : stat,
1030 errmsg, errmsg_len);
1031 else
1032 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_event_wait, 6,
1033 token, index, until_count,
1034 stat != null_pointer_node
1035 ? gfc_build_addr_expr (NULL, stat) : stat,
1036 errmsg, errmsg_len);
1037 gfc_add_expr_to_block (&se.pre, tmp);
1039 /* It guarantees memory consistency within the same segment */
1040 tmp = gfc_build_string_const (strlen ("memory")+1, "memory"),
1041 tmp = build5_loc (input_location, ASM_EXPR, void_type_node,
1042 gfc_build_string_const (1, ""), NULL_TREE, NULL_TREE,
1043 tree_cons (NULL_TREE, tmp, NULL_TREE), NULL_TREE);
1044 ASM_VOLATILE_P (tmp) = 1;
1045 gfc_add_expr_to_block (&se.pre, tmp);
1047 if (stat2 != NULL_TREE)
1048 gfc_add_modify (&se.pre, stat2, fold_convert (TREE_TYPE (stat2), stat));
1050 return gfc_finish_block (&se.pre);
1053 tree
1054 gfc_trans_sync (gfc_code *code, gfc_exec_op type)
1056 gfc_se se, argse;
1057 tree tmp;
1058 tree images = NULL_TREE, stat = NULL_TREE,
1059 errmsg = NULL_TREE, errmsglen = NULL_TREE;
1061 /* Short cut: For single images without bound checking or without STAT=,
1062 return early. (ERRMSG= is always untouched for -fcoarray=single.) */
1063 if (!code->expr2 && !(gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
1064 && flag_coarray != GFC_FCOARRAY_LIB)
1065 return NULL_TREE;
1067 gfc_init_se (&se, NULL);
1068 gfc_start_block (&se.pre);
1070 if (code->expr1 && code->expr1->rank == 0)
1072 gfc_init_se (&argse, NULL);
1073 gfc_conv_expr_val (&argse, code->expr1);
1074 images = argse.expr;
1077 if (code->expr2)
1079 gcc_assert (code->expr2->expr_type == EXPR_VARIABLE);
1080 gfc_init_se (&argse, NULL);
1081 gfc_conv_expr_val (&argse, code->expr2);
1082 stat = argse.expr;
1084 else
1085 stat = null_pointer_node;
1087 if (code->expr3 && flag_coarray == GFC_FCOARRAY_LIB)
1089 gcc_assert (code->expr3->expr_type == EXPR_VARIABLE);
1090 gfc_init_se (&argse, NULL);
1091 argse.want_pointer = 1;
1092 gfc_conv_expr (&argse, code->expr3);
1093 gfc_conv_string_parameter (&argse);
1094 errmsg = gfc_build_addr_expr (NULL, argse.expr);
1095 errmsglen = argse.string_length;
1097 else if (flag_coarray == GFC_FCOARRAY_LIB)
1099 errmsg = null_pointer_node;
1100 errmsglen = build_int_cst (integer_type_node, 0);
1103 /* Check SYNC IMAGES(imageset) for valid image index.
1104 FIXME: Add a check for image-set arrays. */
1105 if (code->expr1 && (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
1106 && code->expr1->rank == 0)
1108 tree cond;
1109 if (flag_coarray != GFC_FCOARRAY_LIB)
1110 cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
1111 images, build_int_cst (TREE_TYPE (images), 1));
1112 else
1114 tree cond2;
1115 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_num_images,
1116 2, integer_zero_node,
1117 build_int_cst (integer_type_node, -1));
1118 cond = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
1119 images, tmp);
1120 cond2 = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
1121 images,
1122 build_int_cst (TREE_TYPE (images), 1));
1123 cond = fold_build2_loc (input_location, TRUTH_OR_EXPR,
1124 logical_type_node, cond, cond2);
1126 gfc_trans_runtime_check (true, false, cond, &se.pre,
1127 &code->expr1->where, "Invalid image number "
1128 "%d in SYNC IMAGES",
1129 fold_convert (integer_type_node, images));
1132 /* Per F2008, 8.5.1, a SYNC MEMORY is implied by calling the
1133 image control statements SYNC IMAGES and SYNC ALL. */
1134 if (flag_coarray == GFC_FCOARRAY_LIB)
1136 tmp = gfc_build_string_const (strlen ("memory")+1, "memory"),
1137 tmp = build5_loc (input_location, ASM_EXPR, void_type_node,
1138 gfc_build_string_const (1, ""), NULL_TREE, NULL_TREE,
1139 tree_cons (NULL_TREE, tmp, NULL_TREE), NULL_TREE);
1140 ASM_VOLATILE_P (tmp) = 1;
1141 gfc_add_expr_to_block (&se.pre, tmp);
1144 if (flag_coarray != GFC_FCOARRAY_LIB)
1146 /* Set STAT to zero. */
1147 if (code->expr2)
1148 gfc_add_modify (&se.pre, stat, build_int_cst (TREE_TYPE (stat), 0));
1150 else if (type == EXEC_SYNC_ALL || type == EXEC_SYNC_MEMORY)
1152 /* SYNC ALL => stat == null_pointer_node
1153 SYNC ALL(stat=s) => stat has an integer type
1155 If "stat" has the wrong integer type, use a temp variable of
1156 the right type and later cast the result back into "stat". */
1157 if (stat == null_pointer_node || TREE_TYPE (stat) == integer_type_node)
1159 if (TREE_TYPE (stat) == integer_type_node)
1160 stat = gfc_build_addr_expr (NULL, stat);
1162 if(type == EXEC_SYNC_MEMORY)
1163 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sync_memory,
1164 3, stat, errmsg, errmsglen);
1165 else
1166 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sync_all,
1167 3, stat, errmsg, errmsglen);
1169 gfc_add_expr_to_block (&se.pre, tmp);
1171 else
1173 tree tmp_stat = gfc_create_var (integer_type_node, "stat");
1175 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sync_all,
1176 3, gfc_build_addr_expr (NULL, tmp_stat),
1177 errmsg, errmsglen);
1178 gfc_add_expr_to_block (&se.pre, tmp);
1180 gfc_add_modify (&se.pre, stat,
1181 fold_convert (TREE_TYPE (stat), tmp_stat));
1184 else
1186 tree len;
1188 gcc_assert (type == EXEC_SYNC_IMAGES);
1190 if (!code->expr1)
1192 len = build_int_cst (integer_type_node, -1);
1193 images = null_pointer_node;
1195 else if (code->expr1->rank == 0)
1197 len = build_int_cst (integer_type_node, 1);
1198 images = gfc_build_addr_expr (NULL_TREE, images);
1200 else
1202 /* FIXME. */
1203 if (code->expr1->ts.kind != gfc_c_int_kind)
1204 gfc_fatal_error ("Sorry, only support for integer kind %d "
1205 "implemented for image-set at %L",
1206 gfc_c_int_kind, &code->expr1->where);
1208 gfc_conv_array_parameter (&se, code->expr1, true, NULL, NULL, &len);
1209 images = se.expr;
1211 tmp = gfc_typenode_for_spec (&code->expr1->ts);
1212 if (GFC_ARRAY_TYPE_P (tmp) || GFC_DESCRIPTOR_TYPE_P (tmp))
1213 tmp = gfc_get_element_type (tmp);
1215 len = fold_build2_loc (input_location, TRUNC_DIV_EXPR,
1216 TREE_TYPE (len), len,
1217 fold_convert (TREE_TYPE (len),
1218 TYPE_SIZE_UNIT (tmp)));
1219 len = fold_convert (integer_type_node, len);
1222 /* SYNC IMAGES(imgs) => stat == null_pointer_node
1223 SYNC IMAGES(imgs,stat=s) => stat has an integer type
1225 If "stat" has the wrong integer type, use a temp variable of
1226 the right type and later cast the result back into "stat". */
1227 if (stat == null_pointer_node || TREE_TYPE (stat) == integer_type_node)
1229 if (TREE_TYPE (stat) == integer_type_node)
1230 stat = gfc_build_addr_expr (NULL, stat);
1232 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sync_images,
1233 5, fold_convert (integer_type_node, len),
1234 images, stat, errmsg, errmsglen);
1235 gfc_add_expr_to_block (&se.pre, tmp);
1237 else
1239 tree tmp_stat = gfc_create_var (integer_type_node, "stat");
1241 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sync_images,
1242 5, fold_convert (integer_type_node, len),
1243 images, gfc_build_addr_expr (NULL, tmp_stat),
1244 errmsg, errmsglen);
1245 gfc_add_expr_to_block (&se.pre, tmp);
1247 gfc_add_modify (&se.pre, stat,
1248 fold_convert (TREE_TYPE (stat), tmp_stat));
1252 return gfc_finish_block (&se.pre);
1256 /* Generate GENERIC for the IF construct. This function also deals with
1257 the simple IF statement, because the front end translates the IF
1258 statement into an IF construct.
1260 We translate:
1262 IF (cond) THEN
1263 then_clause
1264 ELSEIF (cond2)
1265 elseif_clause
1266 ELSE
1267 else_clause
1268 ENDIF
1270 into:
1272 pre_cond_s;
1273 if (cond_s)
1275 then_clause;
1277 else
1279 pre_cond_s
1280 if (cond_s)
1282 elseif_clause
1284 else
1286 else_clause;
1290 where COND_S is the simplified version of the predicate. PRE_COND_S
1291 are the pre side-effects produced by the translation of the
1292 conditional.
1293 We need to build the chain recursively otherwise we run into
1294 problems with folding incomplete statements. */
1296 static tree
1297 gfc_trans_if_1 (gfc_code * code)
1299 gfc_se if_se;
1300 tree stmt, elsestmt;
1301 locus saved_loc;
1302 location_t loc;
1304 /* Check for an unconditional ELSE clause. */
1305 if (!code->expr1)
1306 return gfc_trans_code (code->next);
1308 /* Initialize a statement builder for each block. Puts in NULL_TREEs. */
1309 gfc_init_se (&if_se, NULL);
1310 gfc_start_block (&if_se.pre);
1312 /* Calculate the IF condition expression. */
1313 if (code->expr1->where.lb)
1315 gfc_save_backend_locus (&saved_loc);
1316 gfc_set_backend_locus (&code->expr1->where);
1319 gfc_conv_expr_val (&if_se, code->expr1);
1321 if (code->expr1->where.lb)
1322 gfc_restore_backend_locus (&saved_loc);
1324 /* Translate the THEN clause. */
1325 stmt = gfc_trans_code (code->next);
1327 /* Translate the ELSE clause. */
1328 if (code->block)
1329 elsestmt = gfc_trans_if_1 (code->block);
1330 else
1331 elsestmt = build_empty_stmt (input_location);
1333 /* Build the condition expression and add it to the condition block. */
1334 loc = code->expr1->where.lb ? code->expr1->where.lb->location : input_location;
1335 stmt = fold_build3_loc (loc, COND_EXPR, void_type_node, if_se.expr, stmt,
1336 elsestmt);
1338 gfc_add_expr_to_block (&if_se.pre, stmt);
1340 /* Finish off this statement. */
1341 return gfc_finish_block (&if_se.pre);
1344 tree
1345 gfc_trans_if (gfc_code * code)
1347 stmtblock_t body;
1348 tree exit_label;
1350 /* Create exit label so it is available for trans'ing the body code. */
1351 exit_label = gfc_build_label_decl (NULL_TREE);
1352 code->exit_label = exit_label;
1354 /* Translate the actual code in code->block. */
1355 gfc_init_block (&body);
1356 gfc_add_expr_to_block (&body, gfc_trans_if_1 (code->block));
1358 /* Add exit label. */
1359 gfc_add_expr_to_block (&body, build1_v (LABEL_EXPR, exit_label));
1361 return gfc_finish_block (&body);
1365 /* Translate an arithmetic IF expression.
1367 IF (cond) label1, label2, label3 translates to
1369 if (cond <= 0)
1371 if (cond < 0)
1372 goto label1;
1373 else // cond == 0
1374 goto label2;
1376 else // cond > 0
1377 goto label3;
1379 An optimized version can be generated in case of equal labels.
1380 E.g., if label1 is equal to label2, we can translate it to
1382 if (cond <= 0)
1383 goto label1;
1384 else
1385 goto label3;
1388 tree
1389 gfc_trans_arithmetic_if (gfc_code * code)
1391 gfc_se se;
1392 tree tmp;
1393 tree branch1;
1394 tree branch2;
1395 tree zero;
1397 /* Start a new block. */
1398 gfc_init_se (&se, NULL);
1399 gfc_start_block (&se.pre);
1401 /* Pre-evaluate COND. */
1402 gfc_conv_expr_val (&se, code->expr1);
1403 se.expr = gfc_evaluate_now (se.expr, &se.pre);
1405 /* Build something to compare with. */
1406 zero = gfc_build_const (TREE_TYPE (se.expr), integer_zero_node);
1408 if (code->label1->value != code->label2->value)
1410 /* If (cond < 0) take branch1 else take branch2.
1411 First build jumps to the COND .LT. 0 and the COND .EQ. 0 cases. */
1412 branch1 = build1_v (GOTO_EXPR, gfc_get_label_decl (code->label1));
1413 branch2 = build1_v (GOTO_EXPR, gfc_get_label_decl (code->label2));
1415 if (code->label1->value != code->label3->value)
1416 tmp = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
1417 se.expr, zero);
1418 else
1419 tmp = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
1420 se.expr, zero);
1422 branch1 = fold_build3_loc (input_location, COND_EXPR, void_type_node,
1423 tmp, branch1, branch2);
1425 else
1426 branch1 = build1_v (GOTO_EXPR, gfc_get_label_decl (code->label1));
1428 if (code->label1->value != code->label3->value
1429 && code->label2->value != code->label3->value)
1431 /* if (cond <= 0) take branch1 else take branch2. */
1432 branch2 = build1_v (GOTO_EXPR, gfc_get_label_decl (code->label3));
1433 tmp = fold_build2_loc (input_location, LE_EXPR, logical_type_node,
1434 se.expr, zero);
1435 branch1 = fold_build3_loc (input_location, COND_EXPR, void_type_node,
1436 tmp, branch1, branch2);
1439 /* Append the COND_EXPR to the evaluation of COND, and return. */
1440 gfc_add_expr_to_block (&se.pre, branch1);
1441 return gfc_finish_block (&se.pre);
1445 /* Translate a CRITICAL block. */
1446 tree
1447 gfc_trans_critical (gfc_code *code)
1449 stmtblock_t block;
1450 tree tmp, token = NULL_TREE;
1452 gfc_start_block (&block);
1454 if (flag_coarray == GFC_FCOARRAY_LIB)
1456 token = gfc_get_symbol_decl (code->resolved_sym);
1457 token = GFC_TYPE_ARRAY_CAF_TOKEN (TREE_TYPE (token));
1458 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_lock, 7,
1459 token, integer_zero_node, integer_one_node,
1460 null_pointer_node, null_pointer_node,
1461 null_pointer_node, integer_zero_node);
1462 gfc_add_expr_to_block (&block, tmp);
1464 /* It guarantees memory consistency within the same segment */
1465 tmp = gfc_build_string_const (strlen ("memory")+1, "memory"),
1466 tmp = build5_loc (input_location, ASM_EXPR, void_type_node,
1467 gfc_build_string_const (1, ""),
1468 NULL_TREE, NULL_TREE,
1469 tree_cons (NULL_TREE, tmp, NULL_TREE),
1470 NULL_TREE);
1471 ASM_VOLATILE_P (tmp) = 1;
1473 gfc_add_expr_to_block (&block, tmp);
1476 tmp = gfc_trans_code (code->block->next);
1477 gfc_add_expr_to_block (&block, tmp);
1479 if (flag_coarray == GFC_FCOARRAY_LIB)
1481 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_unlock, 6,
1482 token, integer_zero_node, integer_one_node,
1483 null_pointer_node, null_pointer_node,
1484 integer_zero_node);
1485 gfc_add_expr_to_block (&block, tmp);
1487 /* It guarantees memory consistency within the same segment */
1488 tmp = gfc_build_string_const (strlen ("memory")+1, "memory"),
1489 tmp = build5_loc (input_location, ASM_EXPR, void_type_node,
1490 gfc_build_string_const (1, ""),
1491 NULL_TREE, NULL_TREE,
1492 tree_cons (NULL_TREE, tmp, NULL_TREE),
1493 NULL_TREE);
1494 ASM_VOLATILE_P (tmp) = 1;
1496 gfc_add_expr_to_block (&block, tmp);
1499 return gfc_finish_block (&block);
1503 /* Return true, when the class has a _len component. */
1505 static bool
1506 class_has_len_component (gfc_symbol *sym)
1508 gfc_component *comp = sym->ts.u.derived->components;
1509 while (comp)
1511 if (strcmp (comp->name, "_len") == 0)
1512 return true;
1513 comp = comp->next;
1515 return false;
1519 /* Do proper initialization for ASSOCIATE names. */
1521 static void
1522 trans_associate_var (gfc_symbol *sym, gfc_wrapped_block *block)
1524 gfc_expr *e;
1525 tree tmp;
1526 bool class_target;
1527 bool unlimited;
1528 tree desc;
1529 tree offset;
1530 tree dim;
1531 int n;
1532 tree charlen;
1533 bool need_len_assign;
1534 bool whole_array = true;
1535 gfc_ref *ref;
1536 symbol_attribute attr;
1538 gcc_assert (sym->assoc);
1539 e = sym->assoc->target;
1541 class_target = (e->expr_type == EXPR_VARIABLE)
1542 && (gfc_is_class_scalar_expr (e)
1543 || gfc_is_class_array_ref (e, NULL));
1545 unlimited = UNLIMITED_POLY (e);
1547 for (ref = e->ref; ref; ref = ref->next)
1548 if (ref->type == REF_ARRAY
1549 && ref->u.ar.type == AR_FULL
1550 && ref->next)
1552 whole_array = false;
1553 break;
1556 /* Assignments to the string length need to be generated, when
1557 ( sym is a char array or
1558 sym has a _len component)
1559 and the associated expression is unlimited polymorphic, which is
1560 not (yet) correctly in 'unlimited', because for an already associated
1561 BT_DERIVED the u-poly flag is not set, i.e.,
1562 __tmp_CHARACTER_0_1 => w => arg
1563 ^ generated temp ^ from code, the w does not have the u-poly
1564 flag set, where UNLIMITED_POLY(e) expects it. */
1565 need_len_assign = ((unlimited || (e->ts.type == BT_DERIVED
1566 && e->ts.u.derived->attr.unlimited_polymorphic))
1567 && (sym->ts.type == BT_CHARACTER
1568 || ((sym->ts.type == BT_CLASS || sym->ts.type == BT_DERIVED)
1569 && class_has_len_component (sym))));
1570 /* Do a `pointer assignment' with updated descriptor (or assign descriptor
1571 to array temporary) for arrays with either unknown shape or if associating
1572 to a variable. */
1573 if (sym->attr.dimension && !class_target
1574 && (sym->as->type == AS_DEFERRED || sym->assoc->variable))
1576 gfc_se se;
1577 tree desc;
1578 bool cst_array_ctor;
1580 desc = sym->backend_decl;
1581 cst_array_ctor = e->expr_type == EXPR_ARRAY
1582 && gfc_constant_array_constructor_p (e->value.constructor);
1584 /* If association is to an expression, evaluate it and create temporary.
1585 Otherwise, get descriptor of target for pointer assignment. */
1586 gfc_init_se (&se, NULL);
1587 if (sym->assoc->variable || cst_array_ctor)
1589 se.direct_byref = 1;
1590 se.use_offset = 1;
1591 se.expr = desc;
1594 gfc_conv_expr_descriptor (&se, e);
1596 if (sym->ts.type == BT_CHARACTER
1597 && sym->ts.deferred
1598 && !sym->attr.select_type_temporary
1599 && VAR_P (sym->ts.u.cl->backend_decl)
1600 && se.string_length != sym->ts.u.cl->backend_decl)
1602 gfc_add_modify (&se.pre, sym->ts.u.cl->backend_decl,
1603 fold_convert (gfc_charlen_type_node,
1604 se.string_length));
1607 /* If we didn't already do the pointer assignment, set associate-name
1608 descriptor to the one generated for the temporary. */
1609 if ((!sym->assoc->variable && !cst_array_ctor)
1610 || !whole_array)
1612 int dim;
1614 if (whole_array)
1615 gfc_add_modify (&se.pre, desc, se.expr);
1617 /* The generated descriptor has lower bound zero (as array
1618 temporary), shift bounds so we get lower bounds of 1. */
1619 for (dim = 0; dim < e->rank; ++dim)
1620 gfc_conv_shift_descriptor_lbound (&se.pre, desc,
1621 dim, gfc_index_one_node);
1624 /* If this is a subreference array pointer associate name use the
1625 associate variable element size for the value of 'span'. */
1626 if (sym->attr.subref_array_pointer)
1628 gcc_assert (e->expr_type == EXPR_VARIABLE);
1629 tmp = e->symtree->n.sym->ts.type == BT_CLASS
1630 ? gfc_class_data_get (e->symtree->n.sym->backend_decl)
1631 : e->symtree->n.sym->backend_decl;
1632 tmp = gfc_get_element_type (TREE_TYPE (tmp));
1633 tmp = fold_convert (gfc_array_index_type, size_in_bytes (tmp));
1634 gfc_conv_descriptor_span_set (&se.pre, desc, tmp);
1637 /* Done, register stuff as init / cleanup code. */
1638 gfc_add_init_cleanup (block, gfc_finish_block (&se.pre),
1639 gfc_finish_block (&se.post));
1642 /* Temporaries, arising from TYPE IS, just need the descriptor of class
1643 arrays to be assigned directly. */
1644 else if (class_target && sym->attr.dimension
1645 && (sym->ts.type == BT_DERIVED || unlimited))
1647 gfc_se se;
1649 gfc_init_se (&se, NULL);
1650 se.descriptor_only = 1;
1651 /* In a select type the (temporary) associate variable shall point to
1652 a standard fortran array (lower bound == 1), but conv_expr ()
1653 just maps to the input array in the class object, whose lbound may
1654 be arbitrary. conv_expr_descriptor solves this by inserting a
1655 temporary array descriptor. */
1656 gfc_conv_expr_descriptor (&se, e);
1658 gcc_assert (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (se.expr))
1659 || GFC_ARRAY_TYPE_P (TREE_TYPE (se.expr)));
1660 gcc_assert (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (sym->backend_decl)));
1662 if (GFC_ARRAY_TYPE_P (TREE_TYPE (se.expr)))
1664 if (INDIRECT_REF_P (se.expr))
1665 tmp = TREE_OPERAND (se.expr, 0);
1666 else
1667 tmp = se.expr;
1669 gfc_add_modify (&se.pre, sym->backend_decl,
1670 gfc_class_data_get (GFC_DECL_SAVED_DESCRIPTOR (tmp)));
1672 else
1673 gfc_add_modify (&se.pre, sym->backend_decl, se.expr);
1675 if (unlimited)
1677 /* Recover the dtype, which has been overwritten by the
1678 assignment from an unlimited polymorphic object. */
1679 tmp = gfc_conv_descriptor_dtype (sym->backend_decl);
1680 gfc_add_modify (&se.pre, tmp,
1681 gfc_get_dtype (TREE_TYPE (sym->backend_decl)));
1684 gfc_add_init_cleanup (block, gfc_finish_block (&se.pre),
1685 gfc_finish_block (&se.post));
1688 /* Do a scalar pointer assignment; this is for scalar variable targets. */
1689 else if (gfc_is_associate_pointer (sym))
1691 gfc_se se;
1693 gcc_assert (!sym->attr.dimension);
1695 gfc_init_se (&se, NULL);
1697 /* Class associate-names come this way because they are
1698 unconditionally associate pointers and the symbol is scalar. */
1699 if (sym->ts.type == BT_CLASS && CLASS_DATA (sym)->attr.dimension)
1701 tree target_expr;
1702 /* For a class array we need a descriptor for the selector. */
1703 gfc_conv_expr_descriptor (&se, e);
1704 /* Needed to get/set the _len component below. */
1705 target_expr = se.expr;
1707 /* Obtain a temporary class container for the result. */
1708 gfc_conv_class_to_class (&se, e, sym->ts, false, true, false, false);
1709 se.expr = build_fold_indirect_ref_loc (input_location, se.expr);
1711 /* Set the offset. */
1712 desc = gfc_class_data_get (se.expr);
1713 offset = gfc_index_zero_node;
1714 for (n = 0; n < e->rank; n++)
1716 dim = gfc_rank_cst[n];
1717 tmp = fold_build2_loc (input_location, MULT_EXPR,
1718 gfc_array_index_type,
1719 gfc_conv_descriptor_stride_get (desc, dim),
1720 gfc_conv_descriptor_lbound_get (desc, dim));
1721 offset = fold_build2_loc (input_location, MINUS_EXPR,
1722 gfc_array_index_type,
1723 offset, tmp);
1725 if (need_len_assign)
1727 if (e->symtree
1728 && DECL_LANG_SPECIFIC (e->symtree->n.sym->backend_decl)
1729 && GFC_DECL_SAVED_DESCRIPTOR (e->symtree->n.sym->backend_decl))
1730 /* Use the original class descriptor stored in the saved
1731 descriptor to get the target_expr. */
1732 target_expr =
1733 GFC_DECL_SAVED_DESCRIPTOR (e->symtree->n.sym->backend_decl);
1734 else
1735 /* Strip the _data component from the target_expr. */
1736 target_expr = TREE_OPERAND (target_expr, 0);
1737 /* Add a reference to the _len comp to the target expr. */
1738 tmp = gfc_class_len_get (target_expr);
1739 /* Get the component-ref for the temp structure's _len comp. */
1740 charlen = gfc_class_len_get (se.expr);
1741 /* Add the assign to the beginning of the block... */
1742 gfc_add_modify (&se.pre, charlen,
1743 fold_convert (TREE_TYPE (charlen), tmp));
1744 /* and the oposite way at the end of the block, to hand changes
1745 on the string length back. */
1746 gfc_add_modify (&se.post, tmp,
1747 fold_convert (TREE_TYPE (tmp), charlen));
1748 /* Length assignment done, prevent adding it again below. */
1749 need_len_assign = false;
1751 gfc_conv_descriptor_offset_set (&se.pre, desc, offset);
1753 else if (sym->ts.type == BT_CLASS && e->ts.type == BT_CLASS
1754 && CLASS_DATA (e)->attr.dimension)
1756 /* This is bound to be a class array element. */
1757 gfc_conv_expr_reference (&se, e);
1758 /* Get the _vptr component of the class object. */
1759 tmp = gfc_get_vptr_from_expr (se.expr);
1760 /* Obtain a temporary class container for the result. */
1761 gfc_conv_derived_to_class (&se, e, sym->ts, tmp, false, false);
1762 se.expr = build_fold_indirect_ref_loc (input_location, se.expr);
1764 else
1766 /* For BT_CLASS and BT_DERIVED, this boils down to a pointer assign,
1767 which has the string length included. For CHARACTERS it is still
1768 needed and will be done at the end of this routine. */
1769 gfc_conv_expr (&se, e);
1770 need_len_assign = need_len_assign && sym->ts.type == BT_CHARACTER;
1773 if (sym->ts.type == BT_CHARACTER
1774 && sym->ts.deferred
1775 && !sym->attr.select_type_temporary
1776 && VAR_P (sym->ts.u.cl->backend_decl)
1777 && se.string_length != sym->ts.u.cl->backend_decl)
1779 gfc_add_modify (&se.pre, sym->ts.u.cl->backend_decl,
1780 fold_convert (gfc_charlen_type_node,
1781 se.string_length));
1782 if (e->expr_type == EXPR_FUNCTION)
1784 tmp = gfc_call_free (sym->backend_decl);
1785 gfc_add_expr_to_block (&se.post, tmp);
1789 attr = gfc_expr_attr (e);
1790 if (sym->ts.type == BT_CHARACTER && e->ts.type == BT_CHARACTER
1791 && (attr.allocatable || attr.pointer || attr.dummy))
1793 /* These are pointer types already. */
1794 tmp = fold_convert (TREE_TYPE (sym->backend_decl), se.expr);
1796 else
1798 tmp = TREE_TYPE (sym->backend_decl);
1799 tmp = gfc_build_addr_expr (tmp, se.expr);
1802 gfc_add_modify (&se.pre, sym->backend_decl, tmp);
1804 gfc_add_init_cleanup (block, gfc_finish_block( &se.pre),
1805 gfc_finish_block (&se.post));
1808 /* Do a simple assignment. This is for scalar expressions, where we
1809 can simply use expression assignment. */
1810 else
1812 gfc_expr *lhs;
1814 lhs = gfc_lval_expr_from_sym (sym);
1815 tmp = gfc_trans_assignment (lhs, e, false, true);
1816 gfc_add_init_cleanup (block, tmp, NULL_TREE);
1819 /* Set the stringlength, when needed. */
1820 if (need_len_assign)
1822 gfc_se se;
1823 gfc_init_se (&se, NULL);
1824 if (e->symtree->n.sym->ts.type == BT_CHARACTER)
1826 /* Deferred strings are dealt with in the preceeding. */
1827 gcc_assert (!e->symtree->n.sym->ts.deferred);
1828 tmp = e->symtree->n.sym->ts.u.cl->backend_decl;
1830 else if (e->symtree->n.sym->attr.function
1831 && e->symtree->n.sym == e->symtree->n.sym->result)
1833 tmp = gfc_get_fake_result_decl (e->symtree->n.sym, 0);
1834 tmp = gfc_class_len_get (tmp);
1836 else
1837 tmp = gfc_class_len_get (gfc_get_symbol_decl (e->symtree->n.sym));
1838 gfc_get_symbol_decl (sym);
1839 charlen = sym->ts.type == BT_CHARACTER ? sym->ts.u.cl->backend_decl
1840 : gfc_class_len_get (sym->backend_decl);
1841 /* Prevent adding a noop len= len. */
1842 if (tmp != charlen)
1844 gfc_add_modify (&se.pre, charlen,
1845 fold_convert (TREE_TYPE (charlen), tmp));
1846 gfc_add_init_cleanup (block, gfc_finish_block (&se.pre),
1847 gfc_finish_block (&se.post));
1853 /* Translate a BLOCK construct. This is basically what we would do for a
1854 procedure body. */
1856 tree
1857 gfc_trans_block_construct (gfc_code* code)
1859 gfc_namespace* ns;
1860 gfc_symbol* sym;
1861 gfc_wrapped_block block;
1862 tree exit_label;
1863 stmtblock_t body;
1864 gfc_association_list *ass;
1866 ns = code->ext.block.ns;
1867 gcc_assert (ns);
1868 sym = ns->proc_name;
1869 gcc_assert (sym);
1871 /* Process local variables. */
1872 gcc_assert (!sym->tlink);
1873 sym->tlink = sym;
1874 gfc_process_block_locals (ns);
1876 /* Generate code including exit-label. */
1877 gfc_init_block (&body);
1878 exit_label = gfc_build_label_decl (NULL_TREE);
1879 code->exit_label = exit_label;
1881 finish_oacc_declare (ns, sym, true);
1883 gfc_add_expr_to_block (&body, gfc_trans_code (ns->code));
1884 gfc_add_expr_to_block (&body, build1_v (LABEL_EXPR, exit_label));
1886 /* Finish everything. */
1887 gfc_start_wrapped_block (&block, gfc_finish_block (&body));
1888 gfc_trans_deferred_vars (sym, &block);
1889 for (ass = code->ext.block.assoc; ass; ass = ass->next)
1890 trans_associate_var (ass->st->n.sym, &block);
1892 return gfc_finish_wrapped_block (&block);
1895 /* Translate the simple DO construct in a C-style manner.
1896 This is where the loop variable has integer type and step +-1.
1897 Following code will generate infinite loop in case where TO is INT_MAX
1898 (for +1 step) or INT_MIN (for -1 step)
1900 We translate a do loop from:
1902 DO dovar = from, to, step
1903 body
1904 END DO
1908 [Evaluate loop bounds and step]
1909 dovar = from;
1910 for (;;)
1912 if (dovar > to)
1913 goto end_label;
1914 body;
1915 cycle_label:
1916 dovar += step;
1918 end_label:
1920 This helps the optimizers by avoiding the extra pre-header condition and
1921 we save a register as we just compare the updated IV (not a value in
1922 previous step). */
1924 static tree
1925 gfc_trans_simple_do (gfc_code * code, stmtblock_t *pblock, tree dovar,
1926 tree from, tree to, tree step, tree exit_cond)
1928 stmtblock_t body;
1929 tree type;
1930 tree cond;
1931 tree tmp;
1932 tree saved_dovar = NULL;
1933 tree cycle_label;
1934 tree exit_label;
1935 location_t loc;
1936 type = TREE_TYPE (dovar);
1937 bool is_step_positive = tree_int_cst_sgn (step) > 0;
1939 loc = code->ext.iterator->start->where.lb->location;
1941 /* Initialize the DO variable: dovar = from. */
1942 gfc_add_modify_loc (loc, pblock, dovar,
1943 fold_convert (TREE_TYPE (dovar), from));
1945 /* Save value for do-tinkering checking. */
1946 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
1948 saved_dovar = gfc_create_var (type, ".saved_dovar");
1949 gfc_add_modify_loc (loc, pblock, saved_dovar, dovar);
1952 /* Cycle and exit statements are implemented with gotos. */
1953 cycle_label = gfc_build_label_decl (NULL_TREE);
1954 exit_label = gfc_build_label_decl (NULL_TREE);
1956 /* Put the labels where they can be found later. See gfc_trans_do(). */
1957 code->cycle_label = cycle_label;
1958 code->exit_label = exit_label;
1960 /* Loop body. */
1961 gfc_start_block (&body);
1963 /* Exit the loop if there is an I/O result condition or error. */
1964 if (exit_cond)
1966 tmp = build1_v (GOTO_EXPR, exit_label);
1967 tmp = fold_build3_loc (loc, COND_EXPR, void_type_node,
1968 exit_cond, tmp,
1969 build_empty_stmt (loc));
1970 gfc_add_expr_to_block (&body, tmp);
1973 /* Evaluate the loop condition. */
1974 if (is_step_positive)
1975 cond = fold_build2_loc (loc, GT_EXPR, logical_type_node, dovar,
1976 fold_convert (type, to));
1977 else
1978 cond = fold_build2_loc (loc, LT_EXPR, logical_type_node, dovar,
1979 fold_convert (type, to));
1981 cond = gfc_evaluate_now_loc (loc, cond, &body);
1982 if (code->ext.iterator->unroll && cond != error_mark_node)
1983 cond
1984 = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
1985 build_int_cst (integer_type_node, annot_expr_unroll_kind),
1986 build_int_cst (integer_type_node, code->ext.iterator->unroll));
1988 /* The loop exit. */
1989 tmp = fold_build1_loc (loc, GOTO_EXPR, void_type_node, exit_label);
1990 TREE_USED (exit_label) = 1;
1991 tmp = fold_build3_loc (loc, COND_EXPR, void_type_node,
1992 cond, tmp, build_empty_stmt (loc));
1993 gfc_add_expr_to_block (&body, tmp);
1995 /* Check whether the induction variable is equal to INT_MAX
1996 (respectively to INT_MIN). */
1997 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
1999 tree boundary = is_step_positive ? TYPE_MAX_VALUE (type)
2000 : TYPE_MIN_VALUE (type);
2002 tmp = fold_build2_loc (loc, EQ_EXPR, logical_type_node,
2003 dovar, boundary);
2004 gfc_trans_runtime_check (true, false, tmp, &body, &code->loc,
2005 "Loop iterates infinitely");
2008 /* Main loop body. */
2009 tmp = gfc_trans_code_cond (code->block->next, exit_cond);
2010 gfc_add_expr_to_block (&body, tmp);
2012 /* Label for cycle statements (if needed). */
2013 if (TREE_USED (cycle_label))
2015 tmp = build1_v (LABEL_EXPR, cycle_label);
2016 gfc_add_expr_to_block (&body, tmp);
2019 /* Check whether someone has modified the loop variable. */
2020 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
2022 tmp = fold_build2_loc (loc, NE_EXPR, logical_type_node,
2023 dovar, saved_dovar);
2024 gfc_trans_runtime_check (true, false, tmp, &body, &code->loc,
2025 "Loop variable has been modified");
2028 /* Increment the loop variable. */
2029 tmp = fold_build2_loc (loc, PLUS_EXPR, type, dovar, step);
2030 gfc_add_modify_loc (loc, &body, dovar, tmp);
2032 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
2033 gfc_add_modify_loc (loc, &body, saved_dovar, dovar);
2035 /* Finish the loop body. */
2036 tmp = gfc_finish_block (&body);
2037 tmp = fold_build1_loc (loc, LOOP_EXPR, void_type_node, tmp);
2039 gfc_add_expr_to_block (pblock, tmp);
2041 /* Add the exit label. */
2042 tmp = build1_v (LABEL_EXPR, exit_label);
2043 gfc_add_expr_to_block (pblock, tmp);
2045 return gfc_finish_block (pblock);
2048 /* Translate the DO construct. This obviously is one of the most
2049 important ones to get right with any compiler, but especially
2050 so for Fortran.
2052 We special case some loop forms as described in gfc_trans_simple_do.
2053 For other cases we implement them with a separate loop count,
2054 as described in the standard.
2056 We translate a do loop from:
2058 DO dovar = from, to, step
2059 body
2060 END DO
2064 [evaluate loop bounds and step]
2065 empty = (step > 0 ? to < from : to > from);
2066 countm1 = (to - from) / step;
2067 dovar = from;
2068 if (empty) goto exit_label;
2069 for (;;)
2071 body;
2072 cycle_label:
2073 dovar += step
2074 countm1t = countm1;
2075 countm1--;
2076 if (countm1t == 0) goto exit_label;
2078 exit_label:
2080 countm1 is an unsigned integer. It is equal to the loop count minus one,
2081 because the loop count itself can overflow. */
2083 tree
2084 gfc_trans_do (gfc_code * code, tree exit_cond)
2086 gfc_se se;
2087 tree dovar;
2088 tree saved_dovar = NULL;
2089 tree from;
2090 tree to;
2091 tree step;
2092 tree countm1;
2093 tree type;
2094 tree utype;
2095 tree cond;
2096 tree cycle_label;
2097 tree exit_label;
2098 tree tmp;
2099 stmtblock_t block;
2100 stmtblock_t body;
2101 location_t loc;
2103 gfc_start_block (&block);
2105 loc = code->ext.iterator->start->where.lb->location;
2107 /* Evaluate all the expressions in the iterator. */
2108 gfc_init_se (&se, NULL);
2109 gfc_conv_expr_lhs (&se, code->ext.iterator->var);
2110 gfc_add_block_to_block (&block, &se.pre);
2111 dovar = se.expr;
2112 type = TREE_TYPE (dovar);
2114 gfc_init_se (&se, NULL);
2115 gfc_conv_expr_val (&se, code->ext.iterator->start);
2116 gfc_add_block_to_block (&block, &se.pre);
2117 from = gfc_evaluate_now (se.expr, &block);
2119 gfc_init_se (&se, NULL);
2120 gfc_conv_expr_val (&se, code->ext.iterator->end);
2121 gfc_add_block_to_block (&block, &se.pre);
2122 to = gfc_evaluate_now (se.expr, &block);
2124 gfc_init_se (&se, NULL);
2125 gfc_conv_expr_val (&se, code->ext.iterator->step);
2126 gfc_add_block_to_block (&block, &se.pre);
2127 step = gfc_evaluate_now (se.expr, &block);
2129 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
2131 tmp = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, step,
2132 build_zero_cst (type));
2133 gfc_trans_runtime_check (true, false, tmp, &block, &code->loc,
2134 "DO step value is zero");
2137 /* Special case simple loops. */
2138 if (TREE_CODE (type) == INTEGER_TYPE
2139 && (integer_onep (step)
2140 || tree_int_cst_equal (step, integer_minus_one_node)))
2141 return gfc_trans_simple_do (code, &block, dovar, from, to, step,
2142 exit_cond);
2144 if (TREE_CODE (type) == INTEGER_TYPE)
2145 utype = unsigned_type_for (type);
2146 else
2147 utype = unsigned_type_for (gfc_array_index_type);
2148 countm1 = gfc_create_var (utype, "countm1");
2150 /* Cycle and exit statements are implemented with gotos. */
2151 cycle_label = gfc_build_label_decl (NULL_TREE);
2152 exit_label = gfc_build_label_decl (NULL_TREE);
2153 TREE_USED (exit_label) = 1;
2155 /* Put these labels where they can be found later. */
2156 code->cycle_label = cycle_label;
2157 code->exit_label = exit_label;
2159 /* Initialize the DO variable: dovar = from. */
2160 gfc_add_modify (&block, dovar, from);
2162 /* Save value for do-tinkering checking. */
2163 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
2165 saved_dovar = gfc_create_var (type, ".saved_dovar");
2166 gfc_add_modify_loc (loc, &block, saved_dovar, dovar);
2169 /* Initialize loop count and jump to exit label if the loop is empty.
2170 This code is executed before we enter the loop body. We generate:
2171 if (step > 0)
2173 countm1 = (to - from) / step;
2174 if (to < from)
2175 goto exit_label;
2177 else
2179 countm1 = (from - to) / -step;
2180 if (to > from)
2181 goto exit_label;
2185 if (TREE_CODE (type) == INTEGER_TYPE)
2187 tree pos, neg, tou, fromu, stepu, tmp2;
2189 /* The distance from FROM to TO cannot always be represented in a signed
2190 type, thus use unsigned arithmetic, also to avoid any undefined
2191 overflow issues. */
2192 tou = fold_convert (utype, to);
2193 fromu = fold_convert (utype, from);
2194 stepu = fold_convert (utype, step);
2196 /* For a positive step, when to < from, exit, otherwise compute
2197 countm1 = ((unsigned)to - (unsigned)from) / (unsigned)step */
2198 tmp = fold_build2_loc (loc, LT_EXPR, logical_type_node, to, from);
2199 tmp2 = fold_build2_loc (loc, TRUNC_DIV_EXPR, utype,
2200 fold_build2_loc (loc, MINUS_EXPR, utype,
2201 tou, fromu),
2202 stepu);
2203 pos = build2 (COMPOUND_EXPR, void_type_node,
2204 fold_build2 (MODIFY_EXPR, void_type_node,
2205 countm1, tmp2),
2206 build3_loc (loc, COND_EXPR, void_type_node,
2207 gfc_unlikely (tmp, PRED_FORTRAN_LOOP_PREHEADER),
2208 build1_loc (loc, GOTO_EXPR, void_type_node,
2209 exit_label), NULL_TREE));
2211 /* For a negative step, when to > from, exit, otherwise compute
2212 countm1 = ((unsigned)from - (unsigned)to) / -(unsigned)step */
2213 tmp = fold_build2_loc (loc, GT_EXPR, logical_type_node, to, from);
2214 tmp2 = fold_build2_loc (loc, TRUNC_DIV_EXPR, utype,
2215 fold_build2_loc (loc, MINUS_EXPR, utype,
2216 fromu, tou),
2217 fold_build1_loc (loc, NEGATE_EXPR, utype, stepu));
2218 neg = build2 (COMPOUND_EXPR, void_type_node,
2219 fold_build2 (MODIFY_EXPR, void_type_node,
2220 countm1, tmp2),
2221 build3_loc (loc, COND_EXPR, void_type_node,
2222 gfc_unlikely (tmp, PRED_FORTRAN_LOOP_PREHEADER),
2223 build1_loc (loc, GOTO_EXPR, void_type_node,
2224 exit_label), NULL_TREE));
2226 tmp = fold_build2_loc (loc, LT_EXPR, logical_type_node, step,
2227 build_int_cst (TREE_TYPE (step), 0));
2228 tmp = fold_build3_loc (loc, COND_EXPR, void_type_node, tmp, neg, pos);
2230 gfc_add_expr_to_block (&block, tmp);
2232 else
2234 tree pos_step;
2236 /* TODO: We could use the same width as the real type.
2237 This would probably cause more problems that it solves
2238 when we implement "long double" types. */
2240 tmp = fold_build2_loc (loc, MINUS_EXPR, type, to, from);
2241 tmp = fold_build2_loc (loc, RDIV_EXPR, type, tmp, step);
2242 tmp = fold_build1_loc (loc, FIX_TRUNC_EXPR, utype, tmp);
2243 gfc_add_modify (&block, countm1, tmp);
2245 /* We need a special check for empty loops:
2246 empty = (step > 0 ? to < from : to > from); */
2247 pos_step = fold_build2_loc (loc, GT_EXPR, logical_type_node, step,
2248 build_zero_cst (type));
2249 tmp = fold_build3_loc (loc, COND_EXPR, logical_type_node, pos_step,
2250 fold_build2_loc (loc, LT_EXPR,
2251 logical_type_node, to, from),
2252 fold_build2_loc (loc, GT_EXPR,
2253 logical_type_node, to, from));
2254 /* If the loop is empty, go directly to the exit label. */
2255 tmp = fold_build3_loc (loc, COND_EXPR, void_type_node, tmp,
2256 build1_v (GOTO_EXPR, exit_label),
2257 build_empty_stmt (input_location));
2258 gfc_add_expr_to_block (&block, tmp);
2261 /* Loop body. */
2262 gfc_start_block (&body);
2264 /* Main loop body. */
2265 tmp = gfc_trans_code_cond (code->block->next, exit_cond);
2266 gfc_add_expr_to_block (&body, tmp);
2268 /* Label for cycle statements (if needed). */
2269 if (TREE_USED (cycle_label))
2271 tmp = build1_v (LABEL_EXPR, cycle_label);
2272 gfc_add_expr_to_block (&body, tmp);
2275 /* Check whether someone has modified the loop variable. */
2276 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
2278 tmp = fold_build2_loc (loc, NE_EXPR, logical_type_node, dovar,
2279 saved_dovar);
2280 gfc_trans_runtime_check (true, false, tmp, &body, &code->loc,
2281 "Loop variable has been modified");
2284 /* Exit the loop if there is an I/O result condition or error. */
2285 if (exit_cond)
2287 tmp = build1_v (GOTO_EXPR, exit_label);
2288 tmp = fold_build3_loc (loc, COND_EXPR, void_type_node,
2289 exit_cond, tmp,
2290 build_empty_stmt (input_location));
2291 gfc_add_expr_to_block (&body, tmp);
2294 /* Increment the loop variable. */
2295 tmp = fold_build2_loc (loc, PLUS_EXPR, type, dovar, step);
2296 gfc_add_modify_loc (loc, &body, dovar, tmp);
2298 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
2299 gfc_add_modify_loc (loc, &body, saved_dovar, dovar);
2301 /* Initialize countm1t. */
2302 tree countm1t = gfc_create_var (utype, "countm1t");
2303 gfc_add_modify_loc (loc, &body, countm1t, countm1);
2305 /* Decrement the loop count. */
2306 tmp = fold_build2_loc (loc, MINUS_EXPR, utype, countm1,
2307 build_int_cst (utype, 1));
2308 gfc_add_modify_loc (loc, &body, countm1, tmp);
2310 /* End with the loop condition. Loop until countm1t == 0. */
2311 cond = fold_build2_loc (loc, EQ_EXPR, logical_type_node, countm1t,
2312 build_int_cst (utype, 0));
2313 if (code->ext.iterator->unroll && cond != error_mark_node)
2314 cond
2315 = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
2316 build_int_cst (integer_type_node, annot_expr_unroll_kind),
2317 build_int_cst (integer_type_node, code->ext.iterator->unroll));
2318 tmp = fold_build1_loc (loc, GOTO_EXPR, void_type_node, exit_label);
2319 tmp = fold_build3_loc (loc, COND_EXPR, void_type_node,
2320 cond, tmp, build_empty_stmt (loc));
2321 gfc_add_expr_to_block (&body, tmp);
2323 /* End of loop body. */
2324 tmp = gfc_finish_block (&body);
2326 /* The for loop itself. */
2327 tmp = fold_build1_loc (loc, LOOP_EXPR, void_type_node, tmp);
2328 gfc_add_expr_to_block (&block, tmp);
2330 /* Add the exit label. */
2331 tmp = build1_v (LABEL_EXPR, exit_label);
2332 gfc_add_expr_to_block (&block, tmp);
2334 return gfc_finish_block (&block);
2338 /* Translate the DO WHILE construct.
2340 We translate
2342 DO WHILE (cond)
2343 body
2344 END DO
2348 for ( ; ; )
2350 pre_cond;
2351 if (! cond) goto exit_label;
2352 body;
2353 cycle_label:
2355 exit_label:
2357 Because the evaluation of the exit condition `cond' may have side
2358 effects, we can't do much for empty loop bodies. The backend optimizers
2359 should be smart enough to eliminate any dead loops. */
2361 tree
2362 gfc_trans_do_while (gfc_code * code)
2364 gfc_se cond;
2365 tree tmp;
2366 tree cycle_label;
2367 tree exit_label;
2368 stmtblock_t block;
2370 /* Everything we build here is part of the loop body. */
2371 gfc_start_block (&block);
2373 /* Cycle and exit statements are implemented with gotos. */
2374 cycle_label = gfc_build_label_decl (NULL_TREE);
2375 exit_label = gfc_build_label_decl (NULL_TREE);
2377 /* Put the labels where they can be found later. See gfc_trans_do(). */
2378 code->cycle_label = cycle_label;
2379 code->exit_label = exit_label;
2381 /* Create a GIMPLE version of the exit condition. */
2382 gfc_init_se (&cond, NULL);
2383 gfc_conv_expr_val (&cond, code->expr1);
2384 gfc_add_block_to_block (&block, &cond.pre);
2385 cond.expr = fold_build1_loc (code->expr1->where.lb->location,
2386 TRUTH_NOT_EXPR, TREE_TYPE (cond.expr), cond.expr);
2388 /* Build "IF (! cond) GOTO exit_label". */
2389 tmp = build1_v (GOTO_EXPR, exit_label);
2390 TREE_USED (exit_label) = 1;
2391 tmp = fold_build3_loc (code->expr1->where.lb->location, COND_EXPR,
2392 void_type_node, cond.expr, tmp,
2393 build_empty_stmt (code->expr1->where.lb->location));
2394 gfc_add_expr_to_block (&block, tmp);
2396 /* The main body of the loop. */
2397 tmp = gfc_trans_code (code->block->next);
2398 gfc_add_expr_to_block (&block, tmp);
2400 /* Label for cycle statements (if needed). */
2401 if (TREE_USED (cycle_label))
2403 tmp = build1_v (LABEL_EXPR, cycle_label);
2404 gfc_add_expr_to_block (&block, tmp);
2407 /* End of loop body. */
2408 tmp = gfc_finish_block (&block);
2410 gfc_init_block (&block);
2411 /* Build the loop. */
2412 tmp = fold_build1_loc (code->expr1->where.lb->location, LOOP_EXPR,
2413 void_type_node, tmp);
2414 gfc_add_expr_to_block (&block, tmp);
2416 /* Add the exit label. */
2417 tmp = build1_v (LABEL_EXPR, exit_label);
2418 gfc_add_expr_to_block (&block, tmp);
2420 return gfc_finish_block (&block);
2424 /* Deal with the particular case of SELECT_TYPE, where the vtable
2425 addresses are used for the selection. Since these are not sorted,
2426 the selection has to be made by a series of if statements. */
2428 static tree
2429 gfc_trans_select_type_cases (gfc_code * code)
2431 gfc_code *c;
2432 gfc_case *cp;
2433 tree tmp;
2434 tree cond;
2435 tree low;
2436 tree high;
2437 gfc_se se;
2438 gfc_se cse;
2439 stmtblock_t block;
2440 stmtblock_t body;
2441 bool def = false;
2442 gfc_expr *e;
2443 gfc_start_block (&block);
2445 /* Calculate the switch expression. */
2446 gfc_init_se (&se, NULL);
2447 gfc_conv_expr_val (&se, code->expr1);
2448 gfc_add_block_to_block (&block, &se.pre);
2450 /* Generate an expression for the selector hash value, for
2451 use to resolve character cases. */
2452 e = gfc_copy_expr (code->expr1->value.function.actual->expr);
2453 gfc_add_hash_component (e);
2455 TREE_USED (code->exit_label) = 0;
2457 repeat:
2458 for (c = code->block; c; c = c->block)
2460 cp = c->ext.block.case_list;
2462 /* Assume it's the default case. */
2463 low = NULL_TREE;
2464 high = NULL_TREE;
2465 tmp = NULL_TREE;
2467 /* Put the default case at the end. */
2468 if ((!def && !cp->low) || (def && cp->low))
2469 continue;
2471 if (cp->low && (cp->ts.type == BT_CLASS
2472 || cp->ts.type == BT_DERIVED))
2474 gfc_init_se (&cse, NULL);
2475 gfc_conv_expr_val (&cse, cp->low);
2476 gfc_add_block_to_block (&block, &cse.pre);
2477 low = cse.expr;
2479 else if (cp->ts.type != BT_UNKNOWN)
2481 gcc_assert (cp->high);
2482 gfc_init_se (&cse, NULL);
2483 gfc_conv_expr_val (&cse, cp->high);
2484 gfc_add_block_to_block (&block, &cse.pre);
2485 high = cse.expr;
2488 gfc_init_block (&body);
2490 /* Add the statements for this case. */
2491 tmp = gfc_trans_code (c->next);
2492 gfc_add_expr_to_block (&body, tmp);
2494 /* Break to the end of the SELECT TYPE construct. The default
2495 case just falls through. */
2496 if (!def)
2498 TREE_USED (code->exit_label) = 1;
2499 tmp = build1_v (GOTO_EXPR, code->exit_label);
2500 gfc_add_expr_to_block (&body, tmp);
2503 tmp = gfc_finish_block (&body);
2505 if (low != NULL_TREE)
2507 /* Compare vtable pointers. */
2508 cond = fold_build2_loc (input_location, EQ_EXPR,
2509 TREE_TYPE (se.expr), se.expr, low);
2510 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
2511 cond, tmp,
2512 build_empty_stmt (input_location));
2514 else if (high != NULL_TREE)
2516 /* Compare hash values for character cases. */
2517 gfc_init_se (&cse, NULL);
2518 gfc_conv_expr_val (&cse, e);
2519 gfc_add_block_to_block (&block, &cse.pre);
2521 cond = fold_build2_loc (input_location, EQ_EXPR,
2522 TREE_TYPE (se.expr), high, cse.expr);
2523 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
2524 cond, tmp,
2525 build_empty_stmt (input_location));
2528 gfc_add_expr_to_block (&block, tmp);
2531 if (!def)
2533 def = true;
2534 goto repeat;
2537 gfc_free_expr (e);
2539 return gfc_finish_block (&block);
2543 /* Translate the SELECT CASE construct for INTEGER case expressions,
2544 without killing all potential optimizations. The problem is that
2545 Fortran allows unbounded cases, but the back-end does not, so we
2546 need to intercept those before we enter the equivalent SWITCH_EXPR
2547 we can build.
2549 For example, we translate this,
2551 SELECT CASE (expr)
2552 CASE (:100,101,105:115)
2553 block_1
2554 CASE (190:199,200:)
2555 block_2
2556 CASE (300)
2557 block_3
2558 CASE DEFAULT
2559 block_4
2560 END SELECT
2562 to the GENERIC equivalent,
2564 switch (expr)
2566 case (minimum value for typeof(expr) ... 100:
2567 case 101:
2568 case 105 ... 114:
2569 block1:
2570 goto end_label;
2572 case 200 ... (maximum value for typeof(expr):
2573 case 190 ... 199:
2574 block2;
2575 goto end_label;
2577 case 300:
2578 block_3;
2579 goto end_label;
2581 default:
2582 block_4;
2583 goto end_label;
2586 end_label: */
2588 static tree
2589 gfc_trans_integer_select (gfc_code * code)
2591 gfc_code *c;
2592 gfc_case *cp;
2593 tree end_label;
2594 tree tmp;
2595 gfc_se se;
2596 stmtblock_t block;
2597 stmtblock_t body;
2599 gfc_start_block (&block);
2601 /* Calculate the switch expression. */
2602 gfc_init_se (&se, NULL);
2603 gfc_conv_expr_val (&se, code->expr1);
2604 gfc_add_block_to_block (&block, &se.pre);
2606 end_label = gfc_build_label_decl (NULL_TREE);
2608 gfc_init_block (&body);
2610 for (c = code->block; c; c = c->block)
2612 for (cp = c->ext.block.case_list; cp; cp = cp->next)
2614 tree low, high;
2615 tree label;
2617 /* Assume it's the default case. */
2618 low = high = NULL_TREE;
2620 if (cp->low)
2622 low = gfc_conv_mpz_to_tree (cp->low->value.integer,
2623 cp->low->ts.kind);
2625 /* If there's only a lower bound, set the high bound to the
2626 maximum value of the case expression. */
2627 if (!cp->high)
2628 high = TYPE_MAX_VALUE (TREE_TYPE (se.expr));
2631 if (cp->high)
2633 /* Three cases are possible here:
2635 1) There is no lower bound, e.g. CASE (:N).
2636 2) There is a lower bound .NE. high bound, that is
2637 a case range, e.g. CASE (N:M) where M>N (we make
2638 sure that M>N during type resolution).
2639 3) There is a lower bound, and it has the same value
2640 as the high bound, e.g. CASE (N:N). This is our
2641 internal representation of CASE(N).
2643 In the first and second case, we need to set a value for
2644 high. In the third case, we don't because the GCC middle
2645 end represents a single case value by just letting high be
2646 a NULL_TREE. We can't do that because we need to be able
2647 to represent unbounded cases. */
2649 if (!cp->low
2650 || (mpz_cmp (cp->low->value.integer,
2651 cp->high->value.integer) != 0))
2652 high = gfc_conv_mpz_to_tree (cp->high->value.integer,
2653 cp->high->ts.kind);
2655 /* Unbounded case. */
2656 if (!cp->low)
2657 low = TYPE_MIN_VALUE (TREE_TYPE (se.expr));
2660 /* Build a label. */
2661 label = gfc_build_label_decl (NULL_TREE);
2663 /* Add this case label.
2664 Add parameter 'label', make it match GCC backend. */
2665 tmp = build_case_label (low, high, label);
2666 gfc_add_expr_to_block (&body, tmp);
2669 /* Add the statements for this case. */
2670 tmp = gfc_trans_code (c->next);
2671 gfc_add_expr_to_block (&body, tmp);
2673 /* Break to the end of the construct. */
2674 tmp = build1_v (GOTO_EXPR, end_label);
2675 gfc_add_expr_to_block (&body, tmp);
2678 tmp = gfc_finish_block (&body);
2679 tmp = fold_build2_loc (input_location, SWITCH_EXPR, NULL_TREE, se.expr, tmp);
2680 gfc_add_expr_to_block (&block, tmp);
2682 tmp = build1_v (LABEL_EXPR, end_label);
2683 gfc_add_expr_to_block (&block, tmp);
2685 return gfc_finish_block (&block);
2689 /* Translate the SELECT CASE construct for LOGICAL case expressions.
2691 There are only two cases possible here, even though the standard
2692 does allow three cases in a LOGICAL SELECT CASE construct: .TRUE.,
2693 .FALSE., and DEFAULT.
2695 We never generate more than two blocks here. Instead, we always
2696 try to eliminate the DEFAULT case. This way, we can translate this
2697 kind of SELECT construct to a simple
2699 if {} else {};
2701 expression in GENERIC. */
2703 static tree
2704 gfc_trans_logical_select (gfc_code * code)
2706 gfc_code *c;
2707 gfc_code *t, *f, *d;
2708 gfc_case *cp;
2709 gfc_se se;
2710 stmtblock_t block;
2712 /* Assume we don't have any cases at all. */
2713 t = f = d = NULL;
2715 /* Now see which ones we actually do have. We can have at most two
2716 cases in a single case list: one for .TRUE. and one for .FALSE.
2717 The default case is always separate. If the cases for .TRUE. and
2718 .FALSE. are in the same case list, the block for that case list
2719 always executed, and we don't generate code a COND_EXPR. */
2720 for (c = code->block; c; c = c->block)
2722 for (cp = c->ext.block.case_list; cp; cp = cp->next)
2724 if (cp->low)
2726 if (cp->low->value.logical == 0) /* .FALSE. */
2727 f = c;
2728 else /* if (cp->value.logical != 0), thus .TRUE. */
2729 t = c;
2731 else
2732 d = c;
2736 /* Start a new block. */
2737 gfc_start_block (&block);
2739 /* Calculate the switch expression. We always need to do this
2740 because it may have side effects. */
2741 gfc_init_se (&se, NULL);
2742 gfc_conv_expr_val (&se, code->expr1);
2743 gfc_add_block_to_block (&block, &se.pre);
2745 if (t == f && t != NULL)
2747 /* Cases for .TRUE. and .FALSE. are in the same block. Just
2748 translate the code for these cases, append it to the current
2749 block. */
2750 gfc_add_expr_to_block (&block, gfc_trans_code (t->next));
2752 else
2754 tree true_tree, false_tree, stmt;
2756 true_tree = build_empty_stmt (input_location);
2757 false_tree = build_empty_stmt (input_location);
2759 /* If we have a case for .TRUE. and for .FALSE., discard the default case.
2760 Otherwise, if .TRUE. or .FALSE. is missing and there is a default case,
2761 make the missing case the default case. */
2762 if (t != NULL && f != NULL)
2763 d = NULL;
2764 else if (d != NULL)
2766 if (t == NULL)
2767 t = d;
2768 else
2769 f = d;
2772 /* Translate the code for each of these blocks, and append it to
2773 the current block. */
2774 if (t != NULL)
2775 true_tree = gfc_trans_code (t->next);
2777 if (f != NULL)
2778 false_tree = gfc_trans_code (f->next);
2780 stmt = fold_build3_loc (input_location, COND_EXPR, void_type_node,
2781 se.expr, true_tree, false_tree);
2782 gfc_add_expr_to_block (&block, stmt);
2785 return gfc_finish_block (&block);
2789 /* The jump table types are stored in static variables to avoid
2790 constructing them from scratch every single time. */
2791 static GTY(()) tree select_struct[2];
2793 /* Translate the SELECT CASE construct for CHARACTER case expressions.
2794 Instead of generating compares and jumps, it is far simpler to
2795 generate a data structure describing the cases in order and call a
2796 library subroutine that locates the right case.
2797 This is particularly true because this is the only case where we
2798 might have to dispose of a temporary.
2799 The library subroutine returns a pointer to jump to or NULL if no
2800 branches are to be taken. */
2802 static tree
2803 gfc_trans_character_select (gfc_code *code)
2805 tree init, end_label, tmp, type, case_num, label, fndecl;
2806 stmtblock_t block, body;
2807 gfc_case *cp, *d;
2808 gfc_code *c;
2809 gfc_se se, expr1se;
2810 int n, k;
2811 vec<constructor_elt, va_gc> *inits = NULL;
2813 tree pchartype = gfc_get_pchar_type (code->expr1->ts.kind);
2815 /* The jump table types are stored in static variables to avoid
2816 constructing them from scratch every single time. */
2817 static tree ss_string1[2], ss_string1_len[2];
2818 static tree ss_string2[2], ss_string2_len[2];
2819 static tree ss_target[2];
2821 cp = code->block->ext.block.case_list;
2822 while (cp->left != NULL)
2823 cp = cp->left;
2825 /* Generate the body */
2826 gfc_start_block (&block);
2827 gfc_init_se (&expr1se, NULL);
2828 gfc_conv_expr_reference (&expr1se, code->expr1);
2830 gfc_add_block_to_block (&block, &expr1se.pre);
2832 end_label = gfc_build_label_decl (NULL_TREE);
2834 gfc_init_block (&body);
2836 /* Attempt to optimize length 1 selects. */
2837 if (integer_onep (expr1se.string_length))
2839 for (d = cp; d; d = d->right)
2841 int i;
2842 if (d->low)
2844 gcc_assert (d->low->expr_type == EXPR_CONSTANT
2845 && d->low->ts.type == BT_CHARACTER);
2846 if (d->low->value.character.length > 1)
2848 for (i = 1; i < d->low->value.character.length; i++)
2849 if (d->low->value.character.string[i] != ' ')
2850 break;
2851 if (i != d->low->value.character.length)
2853 if (optimize && d->high && i == 1)
2855 gcc_assert (d->high->expr_type == EXPR_CONSTANT
2856 && d->high->ts.type == BT_CHARACTER);
2857 if (d->high->value.character.length > 1
2858 && (d->low->value.character.string[0]
2859 == d->high->value.character.string[0])
2860 && d->high->value.character.string[1] != ' '
2861 && ((d->low->value.character.string[1] < ' ')
2862 == (d->high->value.character.string[1]
2863 < ' ')))
2864 continue;
2866 break;
2870 if (d->high)
2872 gcc_assert (d->high->expr_type == EXPR_CONSTANT
2873 && d->high->ts.type == BT_CHARACTER);
2874 if (d->high->value.character.length > 1)
2876 for (i = 1; i < d->high->value.character.length; i++)
2877 if (d->high->value.character.string[i] != ' ')
2878 break;
2879 if (i != d->high->value.character.length)
2880 break;
2884 if (d == NULL)
2886 tree ctype = gfc_get_char_type (code->expr1->ts.kind);
2888 for (c = code->block; c; c = c->block)
2890 for (cp = c->ext.block.case_list; cp; cp = cp->next)
2892 tree low, high;
2893 tree label;
2894 gfc_char_t r;
2896 /* Assume it's the default case. */
2897 low = high = NULL_TREE;
2899 if (cp->low)
2901 /* CASE ('ab') or CASE ('ab':'az') will never match
2902 any length 1 character. */
2903 if (cp->low->value.character.length > 1
2904 && cp->low->value.character.string[1] != ' ')
2905 continue;
2907 if (cp->low->value.character.length > 0)
2908 r = cp->low->value.character.string[0];
2909 else
2910 r = ' ';
2911 low = build_int_cst (ctype, r);
2913 /* If there's only a lower bound, set the high bound
2914 to the maximum value of the case expression. */
2915 if (!cp->high)
2916 high = TYPE_MAX_VALUE (ctype);
2919 if (cp->high)
2921 if (!cp->low
2922 || (cp->low->value.character.string[0]
2923 != cp->high->value.character.string[0]))
2925 if (cp->high->value.character.length > 0)
2926 r = cp->high->value.character.string[0];
2927 else
2928 r = ' ';
2929 high = build_int_cst (ctype, r);
2932 /* Unbounded case. */
2933 if (!cp->low)
2934 low = TYPE_MIN_VALUE (ctype);
2937 /* Build a label. */
2938 label = gfc_build_label_decl (NULL_TREE);
2940 /* Add this case label.
2941 Add parameter 'label', make it match GCC backend. */
2942 tmp = build_case_label (low, high, label);
2943 gfc_add_expr_to_block (&body, tmp);
2946 /* Add the statements for this case. */
2947 tmp = gfc_trans_code (c->next);
2948 gfc_add_expr_to_block (&body, tmp);
2950 /* Break to the end of the construct. */
2951 tmp = build1_v (GOTO_EXPR, end_label);
2952 gfc_add_expr_to_block (&body, tmp);
2955 tmp = gfc_string_to_single_character (expr1se.string_length,
2956 expr1se.expr,
2957 code->expr1->ts.kind);
2958 case_num = gfc_create_var (ctype, "case_num");
2959 gfc_add_modify (&block, case_num, tmp);
2961 gfc_add_block_to_block (&block, &expr1se.post);
2963 tmp = gfc_finish_block (&body);
2964 tmp = fold_build2_loc (input_location, SWITCH_EXPR, NULL_TREE,
2965 case_num, tmp);
2966 gfc_add_expr_to_block (&block, tmp);
2968 tmp = build1_v (LABEL_EXPR, end_label);
2969 gfc_add_expr_to_block (&block, tmp);
2971 return gfc_finish_block (&block);
2975 if (code->expr1->ts.kind == 1)
2976 k = 0;
2977 else if (code->expr1->ts.kind == 4)
2978 k = 1;
2979 else
2980 gcc_unreachable ();
2982 if (select_struct[k] == NULL)
2984 tree *chain = NULL;
2985 select_struct[k] = make_node (RECORD_TYPE);
2987 if (code->expr1->ts.kind == 1)
2988 TYPE_NAME (select_struct[k]) = get_identifier ("_jump_struct_char1");
2989 else if (code->expr1->ts.kind == 4)
2990 TYPE_NAME (select_struct[k]) = get_identifier ("_jump_struct_char4");
2991 else
2992 gcc_unreachable ();
2994 #undef ADD_FIELD
2995 #define ADD_FIELD(NAME, TYPE) \
2996 ss_##NAME[k] = gfc_add_field_to_struct (select_struct[k], \
2997 get_identifier (stringize(NAME)), \
2998 TYPE, \
2999 &chain)
3001 ADD_FIELD (string1, pchartype);
3002 ADD_FIELD (string1_len, gfc_charlen_type_node);
3004 ADD_FIELD (string2, pchartype);
3005 ADD_FIELD (string2_len, gfc_charlen_type_node);
3007 ADD_FIELD (target, integer_type_node);
3008 #undef ADD_FIELD
3010 gfc_finish_type (select_struct[k]);
3013 n = 0;
3014 for (d = cp; d; d = d->right)
3015 d->n = n++;
3017 for (c = code->block; c; c = c->block)
3019 for (d = c->ext.block.case_list; d; d = d->next)
3021 label = gfc_build_label_decl (NULL_TREE);
3022 tmp = build_case_label ((d->low == NULL && d->high == NULL)
3023 ? NULL
3024 : build_int_cst (integer_type_node, d->n),
3025 NULL, label);
3026 gfc_add_expr_to_block (&body, tmp);
3029 tmp = gfc_trans_code (c->next);
3030 gfc_add_expr_to_block (&body, tmp);
3032 tmp = build1_v (GOTO_EXPR, end_label);
3033 gfc_add_expr_to_block (&body, tmp);
3036 /* Generate the structure describing the branches */
3037 for (d = cp; d; d = d->right)
3039 vec<constructor_elt, va_gc> *node = NULL;
3041 gfc_init_se (&se, NULL);
3043 if (d->low == NULL)
3045 CONSTRUCTOR_APPEND_ELT (node, ss_string1[k], null_pointer_node);
3046 CONSTRUCTOR_APPEND_ELT (node, ss_string1_len[k], integer_zero_node);
3048 else
3050 gfc_conv_expr_reference (&se, d->low);
3052 CONSTRUCTOR_APPEND_ELT (node, ss_string1[k], se.expr);
3053 CONSTRUCTOR_APPEND_ELT (node, ss_string1_len[k], se.string_length);
3056 if (d->high == NULL)
3058 CONSTRUCTOR_APPEND_ELT (node, ss_string2[k], null_pointer_node);
3059 CONSTRUCTOR_APPEND_ELT (node, ss_string2_len[k], integer_zero_node);
3061 else
3063 gfc_init_se (&se, NULL);
3064 gfc_conv_expr_reference (&se, d->high);
3066 CONSTRUCTOR_APPEND_ELT (node, ss_string2[k], se.expr);
3067 CONSTRUCTOR_APPEND_ELT (node, ss_string2_len[k], se.string_length);
3070 CONSTRUCTOR_APPEND_ELT (node, ss_target[k],
3071 build_int_cst (integer_type_node, d->n));
3073 tmp = build_constructor (select_struct[k], node);
3074 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, tmp);
3077 type = build_array_type (select_struct[k],
3078 build_index_type (size_int (n-1)));
3080 init = build_constructor (type, inits);
3081 TREE_CONSTANT (init) = 1;
3082 TREE_STATIC (init) = 1;
3083 /* Create a static variable to hold the jump table. */
3084 tmp = gfc_create_var (type, "jumptable");
3085 TREE_CONSTANT (tmp) = 1;
3086 TREE_STATIC (tmp) = 1;
3087 TREE_READONLY (tmp) = 1;
3088 DECL_INITIAL (tmp) = init;
3089 init = tmp;
3091 /* Build the library call */
3092 init = gfc_build_addr_expr (pvoid_type_node, init);
3094 if (code->expr1->ts.kind == 1)
3095 fndecl = gfor_fndecl_select_string;
3096 else if (code->expr1->ts.kind == 4)
3097 fndecl = gfor_fndecl_select_string_char4;
3098 else
3099 gcc_unreachable ();
3101 tmp = build_call_expr_loc (input_location,
3102 fndecl, 4, init,
3103 build_int_cst (gfc_charlen_type_node, n),
3104 expr1se.expr, expr1se.string_length);
3105 case_num = gfc_create_var (integer_type_node, "case_num");
3106 gfc_add_modify (&block, case_num, tmp);
3108 gfc_add_block_to_block (&block, &expr1se.post);
3110 tmp = gfc_finish_block (&body);
3111 tmp = fold_build2_loc (input_location, SWITCH_EXPR, NULL_TREE,
3112 case_num, tmp);
3113 gfc_add_expr_to_block (&block, tmp);
3115 tmp = build1_v (LABEL_EXPR, end_label);
3116 gfc_add_expr_to_block (&block, tmp);
3118 return gfc_finish_block (&block);
3122 /* Translate the three variants of the SELECT CASE construct.
3124 SELECT CASEs with INTEGER case expressions can be translated to an
3125 equivalent GENERIC switch statement, and for LOGICAL case
3126 expressions we build one or two if-else compares.
3128 SELECT CASEs with CHARACTER case expressions are a whole different
3129 story, because they don't exist in GENERIC. So we sort them and
3130 do a binary search at runtime.
3132 Fortran has no BREAK statement, and it does not allow jumps from
3133 one case block to another. That makes things a lot easier for
3134 the optimizers. */
3136 tree
3137 gfc_trans_select (gfc_code * code)
3139 stmtblock_t block;
3140 tree body;
3141 tree exit_label;
3143 gcc_assert (code && code->expr1);
3144 gfc_init_block (&block);
3146 /* Build the exit label and hang it in. */
3147 exit_label = gfc_build_label_decl (NULL_TREE);
3148 code->exit_label = exit_label;
3150 /* Empty SELECT constructs are legal. */
3151 if (code->block == NULL)
3152 body = build_empty_stmt (input_location);
3154 /* Select the correct translation function. */
3155 else
3156 switch (code->expr1->ts.type)
3158 case BT_LOGICAL:
3159 body = gfc_trans_logical_select (code);
3160 break;
3162 case BT_INTEGER:
3163 body = gfc_trans_integer_select (code);
3164 break;
3166 case BT_CHARACTER:
3167 body = gfc_trans_character_select (code);
3168 break;
3170 default:
3171 gfc_internal_error ("gfc_trans_select(): Bad type for case expr.");
3172 /* Not reached */
3175 /* Build everything together. */
3176 gfc_add_expr_to_block (&block, body);
3177 gfc_add_expr_to_block (&block, build1_v (LABEL_EXPR, exit_label));
3179 return gfc_finish_block (&block);
3182 tree
3183 gfc_trans_select_type (gfc_code * code)
3185 stmtblock_t block;
3186 tree body;
3187 tree exit_label;
3189 gcc_assert (code && code->expr1);
3190 gfc_init_block (&block);
3192 /* Build the exit label and hang it in. */
3193 exit_label = gfc_build_label_decl (NULL_TREE);
3194 code->exit_label = exit_label;
3196 /* Empty SELECT constructs are legal. */
3197 if (code->block == NULL)
3198 body = build_empty_stmt (input_location);
3199 else
3200 body = gfc_trans_select_type_cases (code);
3202 /* Build everything together. */
3203 gfc_add_expr_to_block (&block, body);
3205 if (TREE_USED (exit_label))
3206 gfc_add_expr_to_block (&block, build1_v (LABEL_EXPR, exit_label));
3208 return gfc_finish_block (&block);
3212 /* Traversal function to substitute a replacement symtree if the symbol
3213 in the expression is the same as that passed. f == 2 signals that
3214 that variable itself is not to be checked - only the references.
3215 This group of functions is used when the variable expression in a
3216 FORALL assignment has internal references. For example:
3217 FORALL (i = 1:4) p(p(i)) = i
3218 The only recourse here is to store a copy of 'p' for the index
3219 expression. */
3221 static gfc_symtree *new_symtree;
3222 static gfc_symtree *old_symtree;
3224 static bool
3225 forall_replace (gfc_expr *expr, gfc_symbol *sym, int *f)
3227 if (expr->expr_type != EXPR_VARIABLE)
3228 return false;
3230 if (*f == 2)
3231 *f = 1;
3232 else if (expr->symtree->n.sym == sym)
3233 expr->symtree = new_symtree;
3235 return false;
3238 static void
3239 forall_replace_symtree (gfc_expr *e, gfc_symbol *sym, int f)
3241 gfc_traverse_expr (e, sym, forall_replace, f);
3244 static bool
3245 forall_restore (gfc_expr *expr,
3246 gfc_symbol *sym ATTRIBUTE_UNUSED,
3247 int *f ATTRIBUTE_UNUSED)
3249 if (expr->expr_type != EXPR_VARIABLE)
3250 return false;
3252 if (expr->symtree == new_symtree)
3253 expr->symtree = old_symtree;
3255 return false;
3258 static void
3259 forall_restore_symtree (gfc_expr *e)
3261 gfc_traverse_expr (e, NULL, forall_restore, 0);
3264 static void
3265 forall_make_variable_temp (gfc_code *c, stmtblock_t *pre, stmtblock_t *post)
3267 gfc_se tse;
3268 gfc_se rse;
3269 gfc_expr *e;
3270 gfc_symbol *new_sym;
3271 gfc_symbol *old_sym;
3272 gfc_symtree *root;
3273 tree tmp;
3275 /* Build a copy of the lvalue. */
3276 old_symtree = c->expr1->symtree;
3277 old_sym = old_symtree->n.sym;
3278 e = gfc_lval_expr_from_sym (old_sym);
3279 if (old_sym->attr.dimension)
3281 gfc_init_se (&tse, NULL);
3282 gfc_conv_subref_array_arg (&tse, e, 0, INTENT_IN, false);
3283 gfc_add_block_to_block (pre, &tse.pre);
3284 gfc_add_block_to_block (post, &tse.post);
3285 tse.expr = build_fold_indirect_ref_loc (input_location, tse.expr);
3287 if (c->expr1->ref->u.ar.type != AR_SECTION)
3289 /* Use the variable offset for the temporary. */
3290 tmp = gfc_conv_array_offset (old_sym->backend_decl);
3291 gfc_conv_descriptor_offset_set (pre, tse.expr, tmp);
3294 else
3296 gfc_init_se (&tse, NULL);
3297 gfc_init_se (&rse, NULL);
3298 gfc_conv_expr (&rse, e);
3299 if (e->ts.type == BT_CHARACTER)
3301 tse.string_length = rse.string_length;
3302 tmp = gfc_get_character_type_len (gfc_default_character_kind,
3303 tse.string_length);
3304 tse.expr = gfc_conv_string_tmp (&tse, build_pointer_type (tmp),
3305 rse.string_length);
3306 gfc_add_block_to_block (pre, &tse.pre);
3307 gfc_add_block_to_block (post, &tse.post);
3309 else
3311 tmp = gfc_typenode_for_spec (&e->ts);
3312 tse.expr = gfc_create_var (tmp, "temp");
3315 tmp = gfc_trans_scalar_assign (&tse, &rse, e->ts,
3316 e->expr_type == EXPR_VARIABLE, false);
3317 gfc_add_expr_to_block (pre, tmp);
3319 gfc_free_expr (e);
3321 /* Create a new symbol to represent the lvalue. */
3322 new_sym = gfc_new_symbol (old_sym->name, NULL);
3323 new_sym->ts = old_sym->ts;
3324 new_sym->attr.referenced = 1;
3325 new_sym->attr.temporary = 1;
3326 new_sym->attr.dimension = old_sym->attr.dimension;
3327 new_sym->attr.flavor = old_sym->attr.flavor;
3329 /* Use the temporary as the backend_decl. */
3330 new_sym->backend_decl = tse.expr;
3332 /* Create a fake symtree for it. */
3333 root = NULL;
3334 new_symtree = gfc_new_symtree (&root, old_sym->name);
3335 new_symtree->n.sym = new_sym;
3336 gcc_assert (new_symtree == root);
3338 /* Go through the expression reference replacing the old_symtree
3339 with the new. */
3340 forall_replace_symtree (c->expr1, old_sym, 2);
3342 /* Now we have made this temporary, we might as well use it for
3343 the right hand side. */
3344 forall_replace_symtree (c->expr2, old_sym, 1);
3348 /* Handles dependencies in forall assignments. */
3349 static int
3350 check_forall_dependencies (gfc_code *c, stmtblock_t *pre, stmtblock_t *post)
3352 gfc_ref *lref;
3353 gfc_ref *rref;
3354 int need_temp;
3355 gfc_symbol *lsym;
3357 lsym = c->expr1->symtree->n.sym;
3358 need_temp = gfc_check_dependency (c->expr1, c->expr2, 0);
3360 /* Now check for dependencies within the 'variable'
3361 expression itself. These are treated by making a complete
3362 copy of variable and changing all the references to it
3363 point to the copy instead. Note that the shallow copy of
3364 the variable will not suffice for derived types with
3365 pointer components. We therefore leave these to their
3366 own devices. */
3367 if (lsym->ts.type == BT_DERIVED
3368 && lsym->ts.u.derived->attr.pointer_comp)
3369 return need_temp;
3371 new_symtree = NULL;
3372 if (find_forall_index (c->expr1, lsym, 2))
3374 forall_make_variable_temp (c, pre, post);
3375 need_temp = 0;
3378 /* Substrings with dependencies are treated in the same
3379 way. */
3380 if (c->expr1->ts.type == BT_CHARACTER
3381 && c->expr1->ref
3382 && c->expr2->expr_type == EXPR_VARIABLE
3383 && lsym == c->expr2->symtree->n.sym)
3385 for (lref = c->expr1->ref; lref; lref = lref->next)
3386 if (lref->type == REF_SUBSTRING)
3387 break;
3388 for (rref = c->expr2->ref; rref; rref = rref->next)
3389 if (rref->type == REF_SUBSTRING)
3390 break;
3392 if (rref && lref
3393 && gfc_dep_compare_expr (rref->u.ss.start, lref->u.ss.start) < 0)
3395 forall_make_variable_temp (c, pre, post);
3396 need_temp = 0;
3399 return need_temp;
3403 static void
3404 cleanup_forall_symtrees (gfc_code *c)
3406 forall_restore_symtree (c->expr1);
3407 forall_restore_symtree (c->expr2);
3408 free (new_symtree->n.sym);
3409 free (new_symtree);
3413 /* Generate the loops for a FORALL block, specified by FORALL_TMP. BODY
3414 is the contents of the FORALL block/stmt to be iterated. MASK_FLAG
3415 indicates whether we should generate code to test the FORALLs mask
3416 array. OUTER is the loop header to be used for initializing mask
3417 indices.
3419 The generated loop format is:
3420 count = (end - start + step) / step
3421 loopvar = start
3422 while (1)
3424 if (count <=0 )
3425 goto end_of_loop
3426 <body>
3427 loopvar += step
3428 count --
3430 end_of_loop: */
3432 static tree
3433 gfc_trans_forall_loop (forall_info *forall_tmp, tree body,
3434 int mask_flag, stmtblock_t *outer)
3436 int n, nvar;
3437 tree tmp;
3438 tree cond;
3439 stmtblock_t block;
3440 tree exit_label;
3441 tree count;
3442 tree var, start, end, step;
3443 iter_info *iter;
3445 /* Initialize the mask index outside the FORALL nest. */
3446 if (mask_flag && forall_tmp->mask)
3447 gfc_add_modify (outer, forall_tmp->maskindex, gfc_index_zero_node);
3449 iter = forall_tmp->this_loop;
3450 nvar = forall_tmp->nvar;
3451 for (n = 0; n < nvar; n++)
3453 var = iter->var;
3454 start = iter->start;
3455 end = iter->end;
3456 step = iter->step;
3458 exit_label = gfc_build_label_decl (NULL_TREE);
3459 TREE_USED (exit_label) = 1;
3461 /* The loop counter. */
3462 count = gfc_create_var (TREE_TYPE (var), "count");
3464 /* The body of the loop. */
3465 gfc_init_block (&block);
3467 /* The exit condition. */
3468 cond = fold_build2_loc (input_location, LE_EXPR, logical_type_node,
3469 count, build_int_cst (TREE_TYPE (count), 0));
3470 if (forall_tmp->do_concurrent)
3471 cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
3472 build_int_cst (integer_type_node,
3473 annot_expr_parallel_kind),
3474 integer_zero_node);
3476 tmp = build1_v (GOTO_EXPR, exit_label);
3477 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
3478 cond, tmp, build_empty_stmt (input_location));
3479 gfc_add_expr_to_block (&block, tmp);
3481 /* The main loop body. */
3482 gfc_add_expr_to_block (&block, body);
3484 /* Increment the loop variable. */
3485 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (var), var,
3486 step);
3487 gfc_add_modify (&block, var, tmp);
3489 /* Advance to the next mask element. Only do this for the
3490 innermost loop. */
3491 if (n == 0 && mask_flag && forall_tmp->mask)
3493 tree maskindex = forall_tmp->maskindex;
3494 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
3495 maskindex, gfc_index_one_node);
3496 gfc_add_modify (&block, maskindex, tmp);
3499 /* Decrement the loop counter. */
3500 tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (var), count,
3501 build_int_cst (TREE_TYPE (var), 1));
3502 gfc_add_modify (&block, count, tmp);
3504 body = gfc_finish_block (&block);
3506 /* Loop var initialization. */
3507 gfc_init_block (&block);
3508 gfc_add_modify (&block, var, start);
3511 /* Initialize the loop counter. */
3512 tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (var), step,
3513 start);
3514 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (var), end,
3515 tmp);
3516 tmp = fold_build2_loc (input_location, TRUNC_DIV_EXPR, TREE_TYPE (var),
3517 tmp, step);
3518 gfc_add_modify (&block, count, tmp);
3520 /* The loop expression. */
3521 tmp = build1_v (LOOP_EXPR, body);
3522 gfc_add_expr_to_block (&block, tmp);
3524 /* The exit label. */
3525 tmp = build1_v (LABEL_EXPR, exit_label);
3526 gfc_add_expr_to_block (&block, tmp);
3528 body = gfc_finish_block (&block);
3529 iter = iter->next;
3531 return body;
3535 /* Generate the body and loops according to MASK_FLAG. If MASK_FLAG
3536 is nonzero, the body is controlled by all masks in the forall nest.
3537 Otherwise, the innermost loop is not controlled by it's mask. This
3538 is used for initializing that mask. */
3540 static tree
3541 gfc_trans_nested_forall_loop (forall_info * nested_forall_info, tree body,
3542 int mask_flag)
3544 tree tmp;
3545 stmtblock_t header;
3546 forall_info *forall_tmp;
3547 tree mask, maskindex;
3549 gfc_start_block (&header);
3551 forall_tmp = nested_forall_info;
3552 while (forall_tmp != NULL)
3554 /* Generate body with masks' control. */
3555 if (mask_flag)
3557 mask = forall_tmp->mask;
3558 maskindex = forall_tmp->maskindex;
3560 /* If a mask was specified make the assignment conditional. */
3561 if (mask)
3563 tmp = gfc_build_array_ref (mask, maskindex, NULL);
3564 body = build3_v (COND_EXPR, tmp, body,
3565 build_empty_stmt (input_location));
3568 body = gfc_trans_forall_loop (forall_tmp, body, mask_flag, &header);
3569 forall_tmp = forall_tmp->prev_nest;
3570 mask_flag = 1;
3573 gfc_add_expr_to_block (&header, body);
3574 return gfc_finish_block (&header);
3578 /* Allocate data for holding a temporary array. Returns either a local
3579 temporary array or a pointer variable. */
3581 static tree
3582 gfc_do_allocate (tree bytesize, tree size, tree * pdata, stmtblock_t * pblock,
3583 tree elem_type)
3585 tree tmpvar;
3586 tree type;
3587 tree tmp;
3589 if (INTEGER_CST_P (size))
3590 tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
3591 size, gfc_index_one_node);
3592 else
3593 tmp = NULL_TREE;
3595 type = build_range_type (gfc_array_index_type, gfc_index_zero_node, tmp);
3596 type = build_array_type (elem_type, type);
3597 if (gfc_can_put_var_on_stack (bytesize) && INTEGER_CST_P (size))
3599 tmpvar = gfc_create_var (type, "temp");
3600 *pdata = NULL_TREE;
3602 else
3604 tmpvar = gfc_create_var (build_pointer_type (type), "temp");
3605 *pdata = convert (pvoid_type_node, tmpvar);
3607 tmp = gfc_call_malloc (pblock, TREE_TYPE (tmpvar), bytesize);
3608 gfc_add_modify (pblock, tmpvar, tmp);
3610 return tmpvar;
3614 /* Generate codes to copy the temporary to the actual lhs. */
3616 static tree
3617 generate_loop_for_temp_to_lhs (gfc_expr *expr, tree tmp1, tree count3,
3618 tree count1,
3619 gfc_ss *lss, gfc_ss *rss,
3620 tree wheremask, bool invert)
3622 stmtblock_t block, body1;
3623 gfc_loopinfo loop;
3624 gfc_se lse;
3625 gfc_se rse;
3626 tree tmp;
3627 tree wheremaskexpr;
3629 (void) rss; /* TODO: unused. */
3631 gfc_start_block (&block);
3633 gfc_init_se (&rse, NULL);
3634 gfc_init_se (&lse, NULL);
3636 if (lss == gfc_ss_terminator)
3638 gfc_init_block (&body1);
3639 gfc_conv_expr (&lse, expr);
3640 rse.expr = gfc_build_array_ref (tmp1, count1, NULL);
3642 else
3644 /* Initialize the loop. */
3645 gfc_init_loopinfo (&loop);
3647 /* We may need LSS to determine the shape of the expression. */
3648 gfc_add_ss_to_loop (&loop, lss);
3650 gfc_conv_ss_startstride (&loop);
3651 gfc_conv_loop_setup (&loop, &expr->where);
3653 gfc_mark_ss_chain_used (lss, 1);
3654 /* Start the loop body. */
3655 gfc_start_scalarized_body (&loop, &body1);
3657 /* Translate the expression. */
3658 gfc_copy_loopinfo_to_se (&lse, &loop);
3659 lse.ss = lss;
3660 gfc_conv_expr (&lse, expr);
3662 /* Form the expression of the temporary. */
3663 rse.expr = gfc_build_array_ref (tmp1, count1, NULL);
3666 /* Use the scalar assignment. */
3667 rse.string_length = lse.string_length;
3668 tmp = gfc_trans_scalar_assign (&lse, &rse, expr->ts,
3669 expr->expr_type == EXPR_VARIABLE, false);
3671 /* Form the mask expression according to the mask tree list. */
3672 if (wheremask)
3674 wheremaskexpr = gfc_build_array_ref (wheremask, count3, NULL);
3675 if (invert)
3676 wheremaskexpr = fold_build1_loc (input_location, TRUTH_NOT_EXPR,
3677 TREE_TYPE (wheremaskexpr),
3678 wheremaskexpr);
3679 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
3680 wheremaskexpr, tmp,
3681 build_empty_stmt (input_location));
3684 gfc_add_expr_to_block (&body1, tmp);
3686 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (count1),
3687 count1, gfc_index_one_node);
3688 gfc_add_modify (&body1, count1, tmp);
3690 if (lss == gfc_ss_terminator)
3691 gfc_add_block_to_block (&block, &body1);
3692 else
3694 /* Increment count3. */
3695 if (count3)
3697 tmp = fold_build2_loc (input_location, PLUS_EXPR,
3698 gfc_array_index_type,
3699 count3, gfc_index_one_node);
3700 gfc_add_modify (&body1, count3, tmp);
3703 /* Generate the copying loops. */
3704 gfc_trans_scalarizing_loops (&loop, &body1);
3706 gfc_add_block_to_block (&block, &loop.pre);
3707 gfc_add_block_to_block (&block, &loop.post);
3709 gfc_cleanup_loop (&loop);
3710 /* TODO: Reuse lss and rss when copying temp->lhs. Need to be careful
3711 as tree nodes in SS may not be valid in different scope. */
3714 tmp = gfc_finish_block (&block);
3715 return tmp;
3719 /* Generate codes to copy rhs to the temporary. TMP1 is the address of
3720 temporary, LSS and RSS are formed in function compute_inner_temp_size(),
3721 and should not be freed. WHEREMASK is the conditional execution mask
3722 whose sense may be inverted by INVERT. */
3724 static tree
3725 generate_loop_for_rhs_to_temp (gfc_expr *expr2, tree tmp1, tree count3,
3726 tree count1, gfc_ss *lss, gfc_ss *rss,
3727 tree wheremask, bool invert)
3729 stmtblock_t block, body1;
3730 gfc_loopinfo loop;
3731 gfc_se lse;
3732 gfc_se rse;
3733 tree tmp;
3734 tree wheremaskexpr;
3736 gfc_start_block (&block);
3738 gfc_init_se (&rse, NULL);
3739 gfc_init_se (&lse, NULL);
3741 if (lss == gfc_ss_terminator)
3743 gfc_init_block (&body1);
3744 gfc_conv_expr (&rse, expr2);
3745 lse.expr = gfc_build_array_ref (tmp1, count1, NULL);
3747 else
3749 /* Initialize the loop. */
3750 gfc_init_loopinfo (&loop);
3752 /* We may need LSS to determine the shape of the expression. */
3753 gfc_add_ss_to_loop (&loop, lss);
3754 gfc_add_ss_to_loop (&loop, rss);
3756 gfc_conv_ss_startstride (&loop);
3757 gfc_conv_loop_setup (&loop, &expr2->where);
3759 gfc_mark_ss_chain_used (rss, 1);
3760 /* Start the loop body. */
3761 gfc_start_scalarized_body (&loop, &body1);
3763 /* Translate the expression. */
3764 gfc_copy_loopinfo_to_se (&rse, &loop);
3765 rse.ss = rss;
3766 gfc_conv_expr (&rse, expr2);
3768 /* Form the expression of the temporary. */
3769 lse.expr = gfc_build_array_ref (tmp1, count1, NULL);
3772 /* Use the scalar assignment. */
3773 lse.string_length = rse.string_length;
3774 tmp = gfc_trans_scalar_assign (&lse, &rse, expr2->ts,
3775 expr2->expr_type == EXPR_VARIABLE, false);
3777 /* Form the mask expression according to the mask tree list. */
3778 if (wheremask)
3780 wheremaskexpr = gfc_build_array_ref (wheremask, count3, NULL);
3781 if (invert)
3782 wheremaskexpr = fold_build1_loc (input_location, TRUTH_NOT_EXPR,
3783 TREE_TYPE (wheremaskexpr),
3784 wheremaskexpr);
3785 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
3786 wheremaskexpr, tmp,
3787 build_empty_stmt (input_location));
3790 gfc_add_expr_to_block (&body1, tmp);
3792 if (lss == gfc_ss_terminator)
3794 gfc_add_block_to_block (&block, &body1);
3796 /* Increment count1. */
3797 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (count1),
3798 count1, gfc_index_one_node);
3799 gfc_add_modify (&block, count1, tmp);
3801 else
3803 /* Increment count1. */
3804 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
3805 count1, gfc_index_one_node);
3806 gfc_add_modify (&body1, count1, tmp);
3808 /* Increment count3. */
3809 if (count3)
3811 tmp = fold_build2_loc (input_location, PLUS_EXPR,
3812 gfc_array_index_type,
3813 count3, gfc_index_one_node);
3814 gfc_add_modify (&body1, count3, tmp);
3817 /* Generate the copying loops. */
3818 gfc_trans_scalarizing_loops (&loop, &body1);
3820 gfc_add_block_to_block (&block, &loop.pre);
3821 gfc_add_block_to_block (&block, &loop.post);
3823 gfc_cleanup_loop (&loop);
3824 /* TODO: Reuse lss and rss when copying temp->lhs. Need to be careful
3825 as tree nodes in SS may not be valid in different scope. */
3828 tmp = gfc_finish_block (&block);
3829 return tmp;
3833 /* Calculate the size of temporary needed in the assignment inside forall.
3834 LSS and RSS are filled in this function. */
3836 static tree
3837 compute_inner_temp_size (gfc_expr *expr1, gfc_expr *expr2,
3838 stmtblock_t * pblock,
3839 gfc_ss **lss, gfc_ss **rss)
3841 gfc_loopinfo loop;
3842 tree size;
3843 int i;
3844 int save_flag;
3845 tree tmp;
3847 *lss = gfc_walk_expr (expr1);
3848 *rss = NULL;
3850 size = gfc_index_one_node;
3851 if (*lss != gfc_ss_terminator)
3853 gfc_init_loopinfo (&loop);
3855 /* Walk the RHS of the expression. */
3856 *rss = gfc_walk_expr (expr2);
3857 if (*rss == gfc_ss_terminator)
3858 /* The rhs is scalar. Add a ss for the expression. */
3859 *rss = gfc_get_scalar_ss (gfc_ss_terminator, expr2);
3861 /* Associate the SS with the loop. */
3862 gfc_add_ss_to_loop (&loop, *lss);
3863 /* We don't actually need to add the rhs at this point, but it might
3864 make guessing the loop bounds a bit easier. */
3865 gfc_add_ss_to_loop (&loop, *rss);
3867 /* We only want the shape of the expression, not rest of the junk
3868 generated by the scalarizer. */
3869 loop.array_parameter = 1;
3871 /* Calculate the bounds of the scalarization. */
3872 save_flag = gfc_option.rtcheck;
3873 gfc_option.rtcheck &= ~GFC_RTCHECK_BOUNDS;
3874 gfc_conv_ss_startstride (&loop);
3875 gfc_option.rtcheck = save_flag;
3876 gfc_conv_loop_setup (&loop, &expr2->where);
3878 /* Figure out how many elements we need. */
3879 for (i = 0; i < loop.dimen; i++)
3881 tmp = fold_build2_loc (input_location, MINUS_EXPR,
3882 gfc_array_index_type,
3883 gfc_index_one_node, loop.from[i]);
3884 tmp = fold_build2_loc (input_location, PLUS_EXPR,
3885 gfc_array_index_type, tmp, loop.to[i]);
3886 size = fold_build2_loc (input_location, MULT_EXPR,
3887 gfc_array_index_type, size, tmp);
3889 gfc_add_block_to_block (pblock, &loop.pre);
3890 size = gfc_evaluate_now (size, pblock);
3891 gfc_add_block_to_block (pblock, &loop.post);
3893 /* TODO: write a function that cleans up a loopinfo without freeing
3894 the SS chains. Currently a NOP. */
3897 return size;
3901 /* Calculate the overall iterator number of the nested forall construct.
3902 This routine actually calculates the number of times the body of the
3903 nested forall specified by NESTED_FORALL_INFO is executed and multiplies
3904 that by the expression INNER_SIZE. The BLOCK argument specifies the
3905 block in which to calculate the result, and the optional INNER_SIZE_BODY
3906 argument contains any statements that need to executed (inside the loop)
3907 to initialize or calculate INNER_SIZE. */
3909 static tree
3910 compute_overall_iter_number (forall_info *nested_forall_info, tree inner_size,
3911 stmtblock_t *inner_size_body, stmtblock_t *block)
3913 forall_info *forall_tmp = nested_forall_info;
3914 tree tmp, number;
3915 stmtblock_t body;
3917 /* We can eliminate the innermost unconditional loops with constant
3918 array bounds. */
3919 if (INTEGER_CST_P (inner_size))
3921 while (forall_tmp
3922 && !forall_tmp->mask
3923 && INTEGER_CST_P (forall_tmp->size))
3925 inner_size = fold_build2_loc (input_location, MULT_EXPR,
3926 gfc_array_index_type,
3927 inner_size, forall_tmp->size);
3928 forall_tmp = forall_tmp->prev_nest;
3931 /* If there are no loops left, we have our constant result. */
3932 if (!forall_tmp)
3933 return inner_size;
3936 /* Otherwise, create a temporary variable to compute the result. */
3937 number = gfc_create_var (gfc_array_index_type, "num");
3938 gfc_add_modify (block, number, gfc_index_zero_node);
3940 gfc_start_block (&body);
3941 if (inner_size_body)
3942 gfc_add_block_to_block (&body, inner_size_body);
3943 if (forall_tmp)
3944 tmp = fold_build2_loc (input_location, PLUS_EXPR,
3945 gfc_array_index_type, number, inner_size);
3946 else
3947 tmp = inner_size;
3948 gfc_add_modify (&body, number, tmp);
3949 tmp = gfc_finish_block (&body);
3951 /* Generate loops. */
3952 if (forall_tmp != NULL)
3953 tmp = gfc_trans_nested_forall_loop (forall_tmp, tmp, 1);
3955 gfc_add_expr_to_block (block, tmp);
3957 return number;
3961 /* Allocate temporary for forall construct. SIZE is the size of temporary
3962 needed. PTEMP1 is returned for space free. */
3964 static tree
3965 allocate_temp_for_forall_nest_1 (tree type, tree size, stmtblock_t * block,
3966 tree * ptemp1)
3968 tree bytesize;
3969 tree unit;
3970 tree tmp;
3972 unit = fold_convert (gfc_array_index_type, TYPE_SIZE_UNIT (type));
3973 if (!integer_onep (unit))
3974 bytesize = fold_build2_loc (input_location, MULT_EXPR,
3975 gfc_array_index_type, size, unit);
3976 else
3977 bytesize = size;
3979 *ptemp1 = NULL;
3980 tmp = gfc_do_allocate (bytesize, size, ptemp1, block, type);
3982 if (*ptemp1)
3983 tmp = build_fold_indirect_ref_loc (input_location, tmp);
3984 return tmp;
3988 /* Allocate temporary for forall construct according to the information in
3989 nested_forall_info. INNER_SIZE is the size of temporary needed in the
3990 assignment inside forall. PTEMP1 is returned for space free. */
3992 static tree
3993 allocate_temp_for_forall_nest (forall_info * nested_forall_info, tree type,
3994 tree inner_size, stmtblock_t * inner_size_body,
3995 stmtblock_t * block, tree * ptemp1)
3997 tree size;
3999 /* Calculate the total size of temporary needed in forall construct. */
4000 size = compute_overall_iter_number (nested_forall_info, inner_size,
4001 inner_size_body, block);
4003 return allocate_temp_for_forall_nest_1 (type, size, block, ptemp1);
4007 /* Handle assignments inside forall which need temporary.
4009 forall (i=start:end:stride; maskexpr)
4010 e<i> = f<i>
4011 end forall
4012 (where e,f<i> are arbitrary expressions possibly involving i
4013 and there is a dependency between e<i> and f<i>)
4014 Translates to:
4015 masktmp(:) = maskexpr(:)
4017 maskindex = 0;
4018 count1 = 0;
4019 num = 0;
4020 for (i = start; i <= end; i += stride)
4021 num += SIZE (f<i>)
4022 count1 = 0;
4023 ALLOCATE (tmp(num))
4024 for (i = start; i <= end; i += stride)
4026 if (masktmp[maskindex++])
4027 tmp[count1++] = f<i>
4029 maskindex = 0;
4030 count1 = 0;
4031 for (i = start; i <= end; i += stride)
4033 if (masktmp[maskindex++])
4034 e<i> = tmp[count1++]
4036 DEALLOCATE (tmp)
4038 static void
4039 gfc_trans_assign_need_temp (gfc_expr * expr1, gfc_expr * expr2,
4040 tree wheremask, bool invert,
4041 forall_info * nested_forall_info,
4042 stmtblock_t * block)
4044 tree type;
4045 tree inner_size;
4046 gfc_ss *lss, *rss;
4047 tree count, count1;
4048 tree tmp, tmp1;
4049 tree ptemp1;
4050 stmtblock_t inner_size_body;
4052 /* Create vars. count1 is the current iterator number of the nested
4053 forall. */
4054 count1 = gfc_create_var (gfc_array_index_type, "count1");
4056 /* Count is the wheremask index. */
4057 if (wheremask)
4059 count = gfc_create_var (gfc_array_index_type, "count");
4060 gfc_add_modify (block, count, gfc_index_zero_node);
4062 else
4063 count = NULL;
4065 /* Initialize count1. */
4066 gfc_add_modify (block, count1, gfc_index_zero_node);
4068 /* Calculate the size of temporary needed in the assignment. Return loop, lss
4069 and rss which are used in function generate_loop_for_rhs_to_temp(). */
4070 /* The type of LHS. Used in function allocate_temp_for_forall_nest */
4071 if (expr1->ts.type == BT_CHARACTER)
4073 type = NULL;
4074 if (expr1->ref && expr1->ref->type == REF_SUBSTRING)
4076 gfc_se ssse;
4077 gfc_init_se (&ssse, NULL);
4078 gfc_conv_expr (&ssse, expr1);
4079 type = gfc_get_character_type_len (gfc_default_character_kind,
4080 ssse.string_length);
4082 else
4084 if (!expr1->ts.u.cl->backend_decl)
4086 gfc_se tse;
4087 gcc_assert (expr1->ts.u.cl->length);
4088 gfc_init_se (&tse, NULL);
4089 gfc_conv_expr (&tse, expr1->ts.u.cl->length);
4090 expr1->ts.u.cl->backend_decl = tse.expr;
4092 type = gfc_get_character_type_len (gfc_default_character_kind,
4093 expr1->ts.u.cl->backend_decl);
4096 else
4097 type = gfc_typenode_for_spec (&expr1->ts);
4099 gfc_init_block (&inner_size_body);
4100 inner_size = compute_inner_temp_size (expr1, expr2, &inner_size_body,
4101 &lss, &rss);
4103 /* Allocate temporary for nested forall construct according to the
4104 information in nested_forall_info and inner_size. */
4105 tmp1 = allocate_temp_for_forall_nest (nested_forall_info, type, inner_size,
4106 &inner_size_body, block, &ptemp1);
4108 /* Generate codes to copy rhs to the temporary . */
4109 tmp = generate_loop_for_rhs_to_temp (expr2, tmp1, count, count1, lss, rss,
4110 wheremask, invert);
4112 /* Generate body and loops according to the information in
4113 nested_forall_info. */
4114 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
4115 gfc_add_expr_to_block (block, tmp);
4117 /* Reset count1. */
4118 gfc_add_modify (block, count1, gfc_index_zero_node);
4120 /* Reset count. */
4121 if (wheremask)
4122 gfc_add_modify (block, count, gfc_index_zero_node);
4124 /* TODO: Second call to compute_inner_temp_size to initialize lss and
4125 rss; there must be a better way. */
4126 inner_size = compute_inner_temp_size (expr1, expr2, &inner_size_body,
4127 &lss, &rss);
4129 /* Generate codes to copy the temporary to lhs. */
4130 tmp = generate_loop_for_temp_to_lhs (expr1, tmp1, count, count1,
4131 lss, rss,
4132 wheremask, invert);
4134 /* Generate body and loops according to the information in
4135 nested_forall_info. */
4136 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
4137 gfc_add_expr_to_block (block, tmp);
4139 if (ptemp1)
4141 /* Free the temporary. */
4142 tmp = gfc_call_free (ptemp1);
4143 gfc_add_expr_to_block (block, tmp);
4148 /* Translate pointer assignment inside FORALL which need temporary. */
4150 static void
4151 gfc_trans_pointer_assign_need_temp (gfc_expr * expr1, gfc_expr * expr2,
4152 forall_info * nested_forall_info,
4153 stmtblock_t * block)
4155 tree type;
4156 tree inner_size;
4157 gfc_ss *lss, *rss;
4158 gfc_se lse;
4159 gfc_se rse;
4160 gfc_array_info *info;
4161 gfc_loopinfo loop;
4162 tree desc;
4163 tree parm;
4164 tree parmtype;
4165 stmtblock_t body;
4166 tree count;
4167 tree tmp, tmp1, ptemp1;
4169 count = gfc_create_var (gfc_array_index_type, "count");
4170 gfc_add_modify (block, count, gfc_index_zero_node);
4172 inner_size = gfc_index_one_node;
4173 lss = gfc_walk_expr (expr1);
4174 rss = gfc_walk_expr (expr2);
4175 if (lss == gfc_ss_terminator)
4177 type = gfc_typenode_for_spec (&expr1->ts);
4178 type = build_pointer_type (type);
4180 /* Allocate temporary for nested forall construct according to the
4181 information in nested_forall_info and inner_size. */
4182 tmp1 = allocate_temp_for_forall_nest (nested_forall_info, type,
4183 inner_size, NULL, block, &ptemp1);
4184 gfc_start_block (&body);
4185 gfc_init_se (&lse, NULL);
4186 lse.expr = gfc_build_array_ref (tmp1, count, NULL);
4187 gfc_init_se (&rse, NULL);
4188 rse.want_pointer = 1;
4189 gfc_conv_expr (&rse, expr2);
4190 gfc_add_block_to_block (&body, &rse.pre);
4191 gfc_add_modify (&body, lse.expr,
4192 fold_convert (TREE_TYPE (lse.expr), rse.expr));
4193 gfc_add_block_to_block (&body, &rse.post);
4195 /* Increment count. */
4196 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
4197 count, gfc_index_one_node);
4198 gfc_add_modify (&body, count, tmp);
4200 tmp = gfc_finish_block (&body);
4202 /* Generate body and loops according to the information in
4203 nested_forall_info. */
4204 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
4205 gfc_add_expr_to_block (block, tmp);
4207 /* Reset count. */
4208 gfc_add_modify (block, count, gfc_index_zero_node);
4210 gfc_start_block (&body);
4211 gfc_init_se (&lse, NULL);
4212 gfc_init_se (&rse, NULL);
4213 rse.expr = gfc_build_array_ref (tmp1, count, NULL);
4214 lse.want_pointer = 1;
4215 gfc_conv_expr (&lse, expr1);
4216 gfc_add_block_to_block (&body, &lse.pre);
4217 gfc_add_modify (&body, lse.expr, rse.expr);
4218 gfc_add_block_to_block (&body, &lse.post);
4219 /* Increment count. */
4220 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
4221 count, gfc_index_one_node);
4222 gfc_add_modify (&body, count, tmp);
4223 tmp = gfc_finish_block (&body);
4225 /* Generate body and loops according to the information in
4226 nested_forall_info. */
4227 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
4228 gfc_add_expr_to_block (block, tmp);
4230 else
4232 gfc_init_loopinfo (&loop);
4234 /* Associate the SS with the loop. */
4235 gfc_add_ss_to_loop (&loop, rss);
4237 /* Setup the scalarizing loops and bounds. */
4238 gfc_conv_ss_startstride (&loop);
4240 gfc_conv_loop_setup (&loop, &expr2->where);
4242 info = &rss->info->data.array;
4243 desc = info->descriptor;
4245 /* Make a new descriptor. */
4246 parmtype = gfc_get_element_type (TREE_TYPE (desc));
4247 parmtype = gfc_get_array_type_bounds (parmtype, loop.dimen, 0,
4248 loop.from, loop.to, 1,
4249 GFC_ARRAY_UNKNOWN, true);
4251 /* Allocate temporary for nested forall construct. */
4252 tmp1 = allocate_temp_for_forall_nest (nested_forall_info, parmtype,
4253 inner_size, NULL, block, &ptemp1);
4254 gfc_start_block (&body);
4255 gfc_init_se (&lse, NULL);
4256 lse.expr = gfc_build_array_ref (tmp1, count, NULL);
4257 lse.direct_byref = 1;
4258 gfc_conv_expr_descriptor (&lse, expr2);
4260 gfc_add_block_to_block (&body, &lse.pre);
4261 gfc_add_block_to_block (&body, &lse.post);
4263 /* Increment count. */
4264 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
4265 count, gfc_index_one_node);
4266 gfc_add_modify (&body, count, tmp);
4268 tmp = gfc_finish_block (&body);
4270 /* Generate body and loops according to the information in
4271 nested_forall_info. */
4272 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
4273 gfc_add_expr_to_block (block, tmp);
4275 /* Reset count. */
4276 gfc_add_modify (block, count, gfc_index_zero_node);
4278 parm = gfc_build_array_ref (tmp1, count, NULL);
4279 gfc_init_se (&lse, NULL);
4280 gfc_conv_expr_descriptor (&lse, expr1);
4281 gfc_add_modify (&lse.pre, lse.expr, parm);
4282 gfc_start_block (&body);
4283 gfc_add_block_to_block (&body, &lse.pre);
4284 gfc_add_block_to_block (&body, &lse.post);
4286 /* Increment count. */
4287 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
4288 count, gfc_index_one_node);
4289 gfc_add_modify (&body, count, tmp);
4291 tmp = gfc_finish_block (&body);
4293 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
4294 gfc_add_expr_to_block (block, tmp);
4296 /* Free the temporary. */
4297 if (ptemp1)
4299 tmp = gfc_call_free (ptemp1);
4300 gfc_add_expr_to_block (block, tmp);
4305 /* FORALL and WHERE statements are really nasty, especially when you nest
4306 them. All the rhs of a forall assignment must be evaluated before the
4307 actual assignments are performed. Presumably this also applies to all the
4308 assignments in an inner where statement. */
4310 /* Generate code for a FORALL statement. Any temporaries are allocated as a
4311 linear array, relying on the fact that we process in the same order in all
4312 loops.
4314 forall (i=start:end:stride; maskexpr)
4315 e<i> = f<i>
4316 g<i> = h<i>
4317 end forall
4318 (where e,f,g,h<i> are arbitrary expressions possibly involving i)
4319 Translates to:
4320 count = ((end + 1 - start) / stride)
4321 masktmp(:) = maskexpr(:)
4323 maskindex = 0;
4324 for (i = start; i <= end; i += stride)
4326 if (masktmp[maskindex++])
4327 e<i> = f<i>
4329 maskindex = 0;
4330 for (i = start; i <= end; i += stride)
4332 if (masktmp[maskindex++])
4333 g<i> = h<i>
4336 Note that this code only works when there are no dependencies.
4337 Forall loop with array assignments and data dependencies are a real pain,
4338 because the size of the temporary cannot always be determined before the
4339 loop is executed. This problem is compounded by the presence of nested
4340 FORALL constructs.
4343 static tree
4344 gfc_trans_forall_1 (gfc_code * code, forall_info * nested_forall_info)
4346 stmtblock_t pre;
4347 stmtblock_t post;
4348 stmtblock_t block;
4349 stmtblock_t body;
4350 tree *var;
4351 tree *start;
4352 tree *end;
4353 tree *step;
4354 gfc_expr **varexpr;
4355 tree tmp;
4356 tree assign;
4357 tree size;
4358 tree maskindex;
4359 tree mask;
4360 tree pmask;
4361 tree cycle_label = NULL_TREE;
4362 int n;
4363 int nvar;
4364 int need_temp;
4365 gfc_forall_iterator *fa;
4366 gfc_se se;
4367 gfc_code *c;
4368 gfc_saved_var *saved_vars;
4369 iter_info *this_forall;
4370 forall_info *info;
4371 bool need_mask;
4373 /* Do nothing if the mask is false. */
4374 if (code->expr1
4375 && code->expr1->expr_type == EXPR_CONSTANT
4376 && !code->expr1->value.logical)
4377 return build_empty_stmt (input_location);
4379 n = 0;
4380 /* Count the FORALL index number. */
4381 for (fa = code->ext.forall_iterator; fa; fa = fa->next)
4382 n++;
4383 nvar = n;
4385 /* Allocate the space for var, start, end, step, varexpr. */
4386 var = XCNEWVEC (tree, nvar);
4387 start = XCNEWVEC (tree, nvar);
4388 end = XCNEWVEC (tree, nvar);
4389 step = XCNEWVEC (tree, nvar);
4390 varexpr = XCNEWVEC (gfc_expr *, nvar);
4391 saved_vars = XCNEWVEC (gfc_saved_var, nvar);
4393 /* Allocate the space for info. */
4394 info = XCNEW (forall_info);
4396 gfc_start_block (&pre);
4397 gfc_init_block (&post);
4398 gfc_init_block (&block);
4400 n = 0;
4401 for (fa = code->ext.forall_iterator; fa; fa = fa->next)
4403 gfc_symbol *sym = fa->var->symtree->n.sym;
4405 /* Allocate space for this_forall. */
4406 this_forall = XCNEW (iter_info);
4408 /* Create a temporary variable for the FORALL index. */
4409 tmp = gfc_typenode_for_spec (&sym->ts);
4410 var[n] = gfc_create_var (tmp, sym->name);
4411 gfc_shadow_sym (sym, var[n], &saved_vars[n]);
4413 /* Record it in this_forall. */
4414 this_forall->var = var[n];
4416 /* Replace the index symbol's backend_decl with the temporary decl. */
4417 sym->backend_decl = var[n];
4419 /* Work out the start, end and stride for the loop. */
4420 gfc_init_se (&se, NULL);
4421 gfc_conv_expr_val (&se, fa->start);
4422 /* Record it in this_forall. */
4423 this_forall->start = se.expr;
4424 gfc_add_block_to_block (&block, &se.pre);
4425 start[n] = se.expr;
4427 gfc_init_se (&se, NULL);
4428 gfc_conv_expr_val (&se, fa->end);
4429 /* Record it in this_forall. */
4430 this_forall->end = se.expr;
4431 gfc_make_safe_expr (&se);
4432 gfc_add_block_to_block (&block, &se.pre);
4433 end[n] = se.expr;
4435 gfc_init_se (&se, NULL);
4436 gfc_conv_expr_val (&se, fa->stride);
4437 /* Record it in this_forall. */
4438 this_forall->step = se.expr;
4439 gfc_make_safe_expr (&se);
4440 gfc_add_block_to_block (&block, &se.pre);
4441 step[n] = se.expr;
4443 /* Set the NEXT field of this_forall to NULL. */
4444 this_forall->next = NULL;
4445 /* Link this_forall to the info construct. */
4446 if (info->this_loop)
4448 iter_info *iter_tmp = info->this_loop;
4449 while (iter_tmp->next != NULL)
4450 iter_tmp = iter_tmp->next;
4451 iter_tmp->next = this_forall;
4453 else
4454 info->this_loop = this_forall;
4456 n++;
4458 nvar = n;
4460 /* Calculate the size needed for the current forall level. */
4461 size = gfc_index_one_node;
4462 for (n = 0; n < nvar; n++)
4464 /* size = (end + step - start) / step. */
4465 tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (start[n]),
4466 step[n], start[n]);
4467 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (end[n]),
4468 end[n], tmp);
4469 tmp = fold_build2_loc (input_location, FLOOR_DIV_EXPR, TREE_TYPE (tmp),
4470 tmp, step[n]);
4471 tmp = convert (gfc_array_index_type, tmp);
4473 size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
4474 size, tmp);
4477 /* Record the nvar and size of current forall level. */
4478 info->nvar = nvar;
4479 info->size = size;
4481 if (code->expr1)
4483 /* If the mask is .true., consider the FORALL unconditional. */
4484 if (code->expr1->expr_type == EXPR_CONSTANT
4485 && code->expr1->value.logical)
4486 need_mask = false;
4487 else
4488 need_mask = true;
4490 else
4491 need_mask = false;
4493 /* First we need to allocate the mask. */
4494 if (need_mask)
4496 /* As the mask array can be very big, prefer compact boolean types. */
4497 tree mask_type = gfc_get_logical_type (gfc_logical_kinds[0].kind);
4498 mask = allocate_temp_for_forall_nest (nested_forall_info, mask_type,
4499 size, NULL, &block, &pmask);
4500 maskindex = gfc_create_var_np (gfc_array_index_type, "mi");
4502 /* Record them in the info structure. */
4503 info->maskindex = maskindex;
4504 info->mask = mask;
4506 else
4508 /* No mask was specified. */
4509 maskindex = NULL_TREE;
4510 mask = pmask = NULL_TREE;
4513 /* Link the current forall level to nested_forall_info. */
4514 info->prev_nest = nested_forall_info;
4515 nested_forall_info = info;
4517 /* Copy the mask into a temporary variable if required.
4518 For now we assume a mask temporary is needed. */
4519 if (need_mask)
4521 /* As the mask array can be very big, prefer compact boolean types. */
4522 tree mask_type = gfc_get_logical_type (gfc_logical_kinds[0].kind);
4524 gfc_add_modify (&block, maskindex, gfc_index_zero_node);
4526 /* Start of mask assignment loop body. */
4527 gfc_start_block (&body);
4529 /* Evaluate the mask expression. */
4530 gfc_init_se (&se, NULL);
4531 gfc_conv_expr_val (&se, code->expr1);
4532 gfc_add_block_to_block (&body, &se.pre);
4534 /* Store the mask. */
4535 se.expr = convert (mask_type, se.expr);
4537 tmp = gfc_build_array_ref (mask, maskindex, NULL);
4538 gfc_add_modify (&body, tmp, se.expr);
4540 /* Advance to the next mask element. */
4541 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
4542 maskindex, gfc_index_one_node);
4543 gfc_add_modify (&body, maskindex, tmp);
4545 /* Generate the loops. */
4546 tmp = gfc_finish_block (&body);
4547 tmp = gfc_trans_nested_forall_loop (info, tmp, 0);
4548 gfc_add_expr_to_block (&block, tmp);
4551 if (code->op == EXEC_DO_CONCURRENT)
4553 gfc_init_block (&body);
4554 cycle_label = gfc_build_label_decl (NULL_TREE);
4555 code->cycle_label = cycle_label;
4556 tmp = gfc_trans_code (code->block->next);
4557 gfc_add_expr_to_block (&body, tmp);
4559 if (TREE_USED (cycle_label))
4561 tmp = build1_v (LABEL_EXPR, cycle_label);
4562 gfc_add_expr_to_block (&body, tmp);
4565 tmp = gfc_finish_block (&body);
4566 nested_forall_info->do_concurrent = true;
4567 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
4568 gfc_add_expr_to_block (&block, tmp);
4569 goto done;
4572 c = code->block->next;
4574 /* TODO: loop merging in FORALL statements. */
4575 /* Now that we've got a copy of the mask, generate the assignment loops. */
4576 while (c)
4578 switch (c->op)
4580 case EXEC_ASSIGN:
4581 /* A scalar or array assignment. DO the simple check for
4582 lhs to rhs dependencies. These make a temporary for the
4583 rhs and form a second forall block to copy to variable. */
4584 need_temp = check_forall_dependencies(c, &pre, &post);
4586 /* Temporaries due to array assignment data dependencies introduce
4587 no end of problems. */
4588 if (need_temp || flag_test_forall_temp)
4589 gfc_trans_assign_need_temp (c->expr1, c->expr2, NULL, false,
4590 nested_forall_info, &block);
4591 else
4593 /* Use the normal assignment copying routines. */
4594 assign = gfc_trans_assignment (c->expr1, c->expr2, false, true);
4596 /* Generate body and loops. */
4597 tmp = gfc_trans_nested_forall_loop (nested_forall_info,
4598 assign, 1);
4599 gfc_add_expr_to_block (&block, tmp);
4602 /* Cleanup any temporary symtrees that have been made to deal
4603 with dependencies. */
4604 if (new_symtree)
4605 cleanup_forall_symtrees (c);
4607 break;
4609 case EXEC_WHERE:
4610 /* Translate WHERE or WHERE construct nested in FORALL. */
4611 gfc_trans_where_2 (c, NULL, false, nested_forall_info, &block);
4612 break;
4614 /* Pointer assignment inside FORALL. */
4615 case EXEC_POINTER_ASSIGN:
4616 need_temp = gfc_check_dependency (c->expr1, c->expr2, 0);
4617 /* Avoid cases where a temporary would never be needed and where
4618 the temp code is guaranteed to fail. */
4619 if (need_temp
4620 || (flag_test_forall_temp
4621 && c->expr2->expr_type != EXPR_CONSTANT
4622 && c->expr2->expr_type != EXPR_NULL))
4623 gfc_trans_pointer_assign_need_temp (c->expr1, c->expr2,
4624 nested_forall_info, &block);
4625 else
4627 /* Use the normal assignment copying routines. */
4628 assign = gfc_trans_pointer_assignment (c->expr1, c->expr2);
4630 /* Generate body and loops. */
4631 tmp = gfc_trans_nested_forall_loop (nested_forall_info,
4632 assign, 1);
4633 gfc_add_expr_to_block (&block, tmp);
4635 break;
4637 case EXEC_FORALL:
4638 tmp = gfc_trans_forall_1 (c, nested_forall_info);
4639 gfc_add_expr_to_block (&block, tmp);
4640 break;
4642 /* Explicit subroutine calls are prevented by the frontend but interface
4643 assignments can legitimately produce them. */
4644 case EXEC_ASSIGN_CALL:
4645 assign = gfc_trans_call (c, true, NULL_TREE, NULL_TREE, false);
4646 tmp = gfc_trans_nested_forall_loop (nested_forall_info, assign, 1);
4647 gfc_add_expr_to_block (&block, tmp);
4648 break;
4650 default:
4651 gcc_unreachable ();
4654 c = c->next;
4657 done:
4658 /* Restore the original index variables. */
4659 for (fa = code->ext.forall_iterator, n = 0; fa; fa = fa->next, n++)
4660 gfc_restore_sym (fa->var->symtree->n.sym, &saved_vars[n]);
4662 /* Free the space for var, start, end, step, varexpr. */
4663 free (var);
4664 free (start);
4665 free (end);
4666 free (step);
4667 free (varexpr);
4668 free (saved_vars);
4670 for (this_forall = info->this_loop; this_forall;)
4672 iter_info *next = this_forall->next;
4673 free (this_forall);
4674 this_forall = next;
4677 /* Free the space for this forall_info. */
4678 free (info);
4680 if (pmask)
4682 /* Free the temporary for the mask. */
4683 tmp = gfc_call_free (pmask);
4684 gfc_add_expr_to_block (&block, tmp);
4686 if (maskindex)
4687 pushdecl (maskindex);
4689 gfc_add_block_to_block (&pre, &block);
4690 gfc_add_block_to_block (&pre, &post);
4692 return gfc_finish_block (&pre);
4696 /* Translate the FORALL statement or construct. */
4698 tree gfc_trans_forall (gfc_code * code)
4700 return gfc_trans_forall_1 (code, NULL);
4704 /* Translate the DO CONCURRENT construct. */
4706 tree gfc_trans_do_concurrent (gfc_code * code)
4708 return gfc_trans_forall_1 (code, NULL);
4712 /* Evaluate the WHERE mask expression, copy its value to a temporary.
4713 If the WHERE construct is nested in FORALL, compute the overall temporary
4714 needed by the WHERE mask expression multiplied by the iterator number of
4715 the nested forall.
4716 ME is the WHERE mask expression.
4717 MASK is the current execution mask upon input, whose sense may or may
4718 not be inverted as specified by the INVERT argument.
4719 CMASK is the updated execution mask on output, or NULL if not required.
4720 PMASK is the pending execution mask on output, or NULL if not required.
4721 BLOCK is the block in which to place the condition evaluation loops. */
4723 static void
4724 gfc_evaluate_where_mask (gfc_expr * me, forall_info * nested_forall_info,
4725 tree mask, bool invert, tree cmask, tree pmask,
4726 tree mask_type, stmtblock_t * block)
4728 tree tmp, tmp1;
4729 gfc_ss *lss, *rss;
4730 gfc_loopinfo loop;
4731 stmtblock_t body, body1;
4732 tree count, cond, mtmp;
4733 gfc_se lse, rse;
4735 gfc_init_loopinfo (&loop);
4737 lss = gfc_walk_expr (me);
4738 rss = gfc_walk_expr (me);
4740 /* Variable to index the temporary. */
4741 count = gfc_create_var (gfc_array_index_type, "count");
4742 /* Initialize count. */
4743 gfc_add_modify (block, count, gfc_index_zero_node);
4745 gfc_start_block (&body);
4747 gfc_init_se (&rse, NULL);
4748 gfc_init_se (&lse, NULL);
4750 if (lss == gfc_ss_terminator)
4752 gfc_init_block (&body1);
4754 else
4756 /* Initialize the loop. */
4757 gfc_init_loopinfo (&loop);
4759 /* We may need LSS to determine the shape of the expression. */
4760 gfc_add_ss_to_loop (&loop, lss);
4761 gfc_add_ss_to_loop (&loop, rss);
4763 gfc_conv_ss_startstride (&loop);
4764 gfc_conv_loop_setup (&loop, &me->where);
4766 gfc_mark_ss_chain_used (rss, 1);
4767 /* Start the loop body. */
4768 gfc_start_scalarized_body (&loop, &body1);
4770 /* Translate the expression. */
4771 gfc_copy_loopinfo_to_se (&rse, &loop);
4772 rse.ss = rss;
4773 gfc_conv_expr (&rse, me);
4776 /* Variable to evaluate mask condition. */
4777 cond = gfc_create_var (mask_type, "cond");
4778 if (mask && (cmask || pmask))
4779 mtmp = gfc_create_var (mask_type, "mask");
4780 else mtmp = NULL_TREE;
4782 gfc_add_block_to_block (&body1, &lse.pre);
4783 gfc_add_block_to_block (&body1, &rse.pre);
4785 gfc_add_modify (&body1, cond, fold_convert (mask_type, rse.expr));
4787 if (mask && (cmask || pmask))
4789 tmp = gfc_build_array_ref (mask, count, NULL);
4790 if (invert)
4791 tmp = fold_build1_loc (input_location, TRUTH_NOT_EXPR, mask_type, tmp);
4792 gfc_add_modify (&body1, mtmp, tmp);
4795 if (cmask)
4797 tmp1 = gfc_build_array_ref (cmask, count, NULL);
4798 tmp = cond;
4799 if (mask)
4800 tmp = fold_build2_loc (input_location, TRUTH_AND_EXPR, mask_type,
4801 mtmp, tmp);
4802 gfc_add_modify (&body1, tmp1, tmp);
4805 if (pmask)
4807 tmp1 = gfc_build_array_ref (pmask, count, NULL);
4808 tmp = fold_build1_loc (input_location, TRUTH_NOT_EXPR, mask_type, cond);
4809 if (mask)
4810 tmp = fold_build2_loc (input_location, TRUTH_AND_EXPR, mask_type, mtmp,
4811 tmp);
4812 gfc_add_modify (&body1, tmp1, tmp);
4815 gfc_add_block_to_block (&body1, &lse.post);
4816 gfc_add_block_to_block (&body1, &rse.post);
4818 if (lss == gfc_ss_terminator)
4820 gfc_add_block_to_block (&body, &body1);
4822 else
4824 /* Increment count. */
4825 tmp1 = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
4826 count, gfc_index_one_node);
4827 gfc_add_modify (&body1, count, tmp1);
4829 /* Generate the copying loops. */
4830 gfc_trans_scalarizing_loops (&loop, &body1);
4832 gfc_add_block_to_block (&body, &loop.pre);
4833 gfc_add_block_to_block (&body, &loop.post);
4835 gfc_cleanup_loop (&loop);
4836 /* TODO: Reuse lss and rss when copying temp->lhs. Need to be careful
4837 as tree nodes in SS may not be valid in different scope. */
4840 tmp1 = gfc_finish_block (&body);
4841 /* If the WHERE construct is inside FORALL, fill the full temporary. */
4842 if (nested_forall_info != NULL)
4843 tmp1 = gfc_trans_nested_forall_loop (nested_forall_info, tmp1, 1);
4845 gfc_add_expr_to_block (block, tmp1);
4849 /* Translate an assignment statement in a WHERE statement or construct
4850 statement. The MASK expression is used to control which elements
4851 of EXPR1 shall be assigned. The sense of MASK is specified by
4852 INVERT. */
4854 static tree
4855 gfc_trans_where_assign (gfc_expr *expr1, gfc_expr *expr2,
4856 tree mask, bool invert,
4857 tree count1, tree count2,
4858 gfc_code *cnext)
4860 gfc_se lse;
4861 gfc_se rse;
4862 gfc_ss *lss;
4863 gfc_ss *lss_section;
4864 gfc_ss *rss;
4866 gfc_loopinfo loop;
4867 tree tmp;
4868 stmtblock_t block;
4869 stmtblock_t body;
4870 tree index, maskexpr;
4872 /* A defined assignment. */
4873 if (cnext && cnext->resolved_sym)
4874 return gfc_trans_call (cnext, true, mask, count1, invert);
4876 #if 0
4877 /* TODO: handle this special case.
4878 Special case a single function returning an array. */
4879 if (expr2->expr_type == EXPR_FUNCTION && expr2->rank > 0)
4881 tmp = gfc_trans_arrayfunc_assign (expr1, expr2);
4882 if (tmp)
4883 return tmp;
4885 #endif
4887 /* Assignment of the form lhs = rhs. */
4888 gfc_start_block (&block);
4890 gfc_init_se (&lse, NULL);
4891 gfc_init_se (&rse, NULL);
4893 /* Walk the lhs. */
4894 lss = gfc_walk_expr (expr1);
4895 rss = NULL;
4897 /* In each where-assign-stmt, the mask-expr and the variable being
4898 defined shall be arrays of the same shape. */
4899 gcc_assert (lss != gfc_ss_terminator);
4901 /* The assignment needs scalarization. */
4902 lss_section = lss;
4904 /* Find a non-scalar SS from the lhs. */
4905 while (lss_section != gfc_ss_terminator
4906 && lss_section->info->type != GFC_SS_SECTION)
4907 lss_section = lss_section->next;
4909 gcc_assert (lss_section != gfc_ss_terminator);
4911 /* Initialize the scalarizer. */
4912 gfc_init_loopinfo (&loop);
4914 /* Walk the rhs. */
4915 rss = gfc_walk_expr (expr2);
4916 if (rss == gfc_ss_terminator)
4918 /* The rhs is scalar. Add a ss for the expression. */
4919 rss = gfc_get_scalar_ss (gfc_ss_terminator, expr2);
4920 rss->info->where = 1;
4923 /* Associate the SS with the loop. */
4924 gfc_add_ss_to_loop (&loop, lss);
4925 gfc_add_ss_to_loop (&loop, rss);
4927 /* Calculate the bounds of the scalarization. */
4928 gfc_conv_ss_startstride (&loop);
4930 /* Resolve any data dependencies in the statement. */
4931 gfc_conv_resolve_dependencies (&loop, lss_section, rss);
4933 /* Setup the scalarizing loops. */
4934 gfc_conv_loop_setup (&loop, &expr2->where);
4936 /* Setup the gfc_se structures. */
4937 gfc_copy_loopinfo_to_se (&lse, &loop);
4938 gfc_copy_loopinfo_to_se (&rse, &loop);
4940 rse.ss = rss;
4941 gfc_mark_ss_chain_used (rss, 1);
4942 if (loop.temp_ss == NULL)
4944 lse.ss = lss;
4945 gfc_mark_ss_chain_used (lss, 1);
4947 else
4949 lse.ss = loop.temp_ss;
4950 gfc_mark_ss_chain_used (lss, 3);
4951 gfc_mark_ss_chain_used (loop.temp_ss, 3);
4954 /* Start the scalarized loop body. */
4955 gfc_start_scalarized_body (&loop, &body);
4957 /* Translate the expression. */
4958 gfc_conv_expr (&rse, expr2);
4959 if (lss != gfc_ss_terminator && loop.temp_ss != NULL)
4960 gfc_conv_tmp_array_ref (&lse);
4961 else
4962 gfc_conv_expr (&lse, expr1);
4964 /* Form the mask expression according to the mask. */
4965 index = count1;
4966 maskexpr = gfc_build_array_ref (mask, index, NULL);
4967 if (invert)
4968 maskexpr = fold_build1_loc (input_location, TRUTH_NOT_EXPR,
4969 TREE_TYPE (maskexpr), maskexpr);
4971 /* Use the scalar assignment as is. */
4972 tmp = gfc_trans_scalar_assign (&lse, &rse, expr1->ts,
4973 false, loop.temp_ss == NULL);
4975 tmp = build3_v (COND_EXPR, maskexpr, tmp, build_empty_stmt (input_location));
4977 gfc_add_expr_to_block (&body, tmp);
4979 if (lss == gfc_ss_terminator)
4981 /* Increment count1. */
4982 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
4983 count1, gfc_index_one_node);
4984 gfc_add_modify (&body, count1, tmp);
4986 /* Use the scalar assignment as is. */
4987 gfc_add_block_to_block (&block, &body);
4989 else
4991 gcc_assert (lse.ss == gfc_ss_terminator
4992 && rse.ss == gfc_ss_terminator);
4994 if (loop.temp_ss != NULL)
4996 /* Increment count1 before finish the main body of a scalarized
4997 expression. */
4998 tmp = fold_build2_loc (input_location, PLUS_EXPR,
4999 gfc_array_index_type, count1, gfc_index_one_node);
5000 gfc_add_modify (&body, count1, tmp);
5001 gfc_trans_scalarized_loop_boundary (&loop, &body);
5003 /* We need to copy the temporary to the actual lhs. */
5004 gfc_init_se (&lse, NULL);
5005 gfc_init_se (&rse, NULL);
5006 gfc_copy_loopinfo_to_se (&lse, &loop);
5007 gfc_copy_loopinfo_to_se (&rse, &loop);
5009 rse.ss = loop.temp_ss;
5010 lse.ss = lss;
5012 gfc_conv_tmp_array_ref (&rse);
5013 gfc_conv_expr (&lse, expr1);
5015 gcc_assert (lse.ss == gfc_ss_terminator
5016 && rse.ss == gfc_ss_terminator);
5018 /* Form the mask expression according to the mask tree list. */
5019 index = count2;
5020 maskexpr = gfc_build_array_ref (mask, index, NULL);
5021 if (invert)
5022 maskexpr = fold_build1_loc (input_location, TRUTH_NOT_EXPR,
5023 TREE_TYPE (maskexpr), maskexpr);
5025 /* Use the scalar assignment as is. */
5026 tmp = gfc_trans_scalar_assign (&lse, &rse, expr1->ts, false, true);
5027 tmp = build3_v (COND_EXPR, maskexpr, tmp,
5028 build_empty_stmt (input_location));
5029 gfc_add_expr_to_block (&body, tmp);
5031 /* Increment count2. */
5032 tmp = fold_build2_loc (input_location, PLUS_EXPR,
5033 gfc_array_index_type, count2,
5034 gfc_index_one_node);
5035 gfc_add_modify (&body, count2, tmp);
5037 else
5039 /* Increment count1. */
5040 tmp = fold_build2_loc (input_location, PLUS_EXPR,
5041 gfc_array_index_type, count1,
5042 gfc_index_one_node);
5043 gfc_add_modify (&body, count1, tmp);
5046 /* Generate the copying loops. */
5047 gfc_trans_scalarizing_loops (&loop, &body);
5049 /* Wrap the whole thing up. */
5050 gfc_add_block_to_block (&block, &loop.pre);
5051 gfc_add_block_to_block (&block, &loop.post);
5052 gfc_cleanup_loop (&loop);
5055 return gfc_finish_block (&block);
5059 /* Translate the WHERE construct or statement.
5060 This function can be called iteratively to translate the nested WHERE
5061 construct or statement.
5062 MASK is the control mask. */
5064 static void
5065 gfc_trans_where_2 (gfc_code * code, tree mask, bool invert,
5066 forall_info * nested_forall_info, stmtblock_t * block)
5068 stmtblock_t inner_size_body;
5069 tree inner_size, size;
5070 gfc_ss *lss, *rss;
5071 tree mask_type;
5072 gfc_expr *expr1;
5073 gfc_expr *expr2;
5074 gfc_code *cblock;
5075 gfc_code *cnext;
5076 tree tmp;
5077 tree cond;
5078 tree count1, count2;
5079 bool need_cmask;
5080 bool need_pmask;
5081 int need_temp;
5082 tree pcmask = NULL_TREE;
5083 tree ppmask = NULL_TREE;
5084 tree cmask = NULL_TREE;
5085 tree pmask = NULL_TREE;
5086 gfc_actual_arglist *arg;
5088 /* the WHERE statement or the WHERE construct statement. */
5089 cblock = code->block;
5091 /* As the mask array can be very big, prefer compact boolean types. */
5092 mask_type = gfc_get_logical_type (gfc_logical_kinds[0].kind);
5094 /* Determine which temporary masks are needed. */
5095 if (!cblock->block)
5097 /* One clause: No ELSEWHEREs. */
5098 need_cmask = (cblock->next != 0);
5099 need_pmask = false;
5101 else if (cblock->block->block)
5103 /* Three or more clauses: Conditional ELSEWHEREs. */
5104 need_cmask = true;
5105 need_pmask = true;
5107 else if (cblock->next)
5109 /* Two clauses, the first non-empty. */
5110 need_cmask = true;
5111 need_pmask = (mask != NULL_TREE
5112 && cblock->block->next != 0);
5114 else if (!cblock->block->next)
5116 /* Two clauses, both empty. */
5117 need_cmask = false;
5118 need_pmask = false;
5120 /* Two clauses, the first empty, the second non-empty. */
5121 else if (mask)
5123 need_cmask = (cblock->block->expr1 != 0);
5124 need_pmask = true;
5126 else
5128 need_cmask = true;
5129 need_pmask = false;
5132 if (need_cmask || need_pmask)
5134 /* Calculate the size of temporary needed by the mask-expr. */
5135 gfc_init_block (&inner_size_body);
5136 inner_size = compute_inner_temp_size (cblock->expr1, cblock->expr1,
5137 &inner_size_body, &lss, &rss);
5139 gfc_free_ss_chain (lss);
5140 gfc_free_ss_chain (rss);
5142 /* Calculate the total size of temporary needed. */
5143 size = compute_overall_iter_number (nested_forall_info, inner_size,
5144 &inner_size_body, block);
5146 /* Check whether the size is negative. */
5147 cond = fold_build2_loc (input_location, LE_EXPR, logical_type_node, size,
5148 gfc_index_zero_node);
5149 size = fold_build3_loc (input_location, COND_EXPR, gfc_array_index_type,
5150 cond, gfc_index_zero_node, size);
5151 size = gfc_evaluate_now (size, block);
5153 /* Allocate temporary for WHERE mask if needed. */
5154 if (need_cmask)
5155 cmask = allocate_temp_for_forall_nest_1 (mask_type, size, block,
5156 &pcmask);
5158 /* Allocate temporary for !mask if needed. */
5159 if (need_pmask)
5160 pmask = allocate_temp_for_forall_nest_1 (mask_type, size, block,
5161 &ppmask);
5164 while (cblock)
5166 /* Each time around this loop, the where clause is conditional
5167 on the value of mask and invert, which are updated at the
5168 bottom of the loop. */
5170 /* Has mask-expr. */
5171 if (cblock->expr1)
5173 /* Ensure that the WHERE mask will be evaluated exactly once.
5174 If there are no statements in this WHERE/ELSEWHERE clause,
5175 then we don't need to update the control mask (cmask).
5176 If this is the last clause of the WHERE construct, then
5177 we don't need to update the pending control mask (pmask). */
5178 if (mask)
5179 gfc_evaluate_where_mask (cblock->expr1, nested_forall_info,
5180 mask, invert,
5181 cblock->next ? cmask : NULL_TREE,
5182 cblock->block ? pmask : NULL_TREE,
5183 mask_type, block);
5184 else
5185 gfc_evaluate_where_mask (cblock->expr1, nested_forall_info,
5186 NULL_TREE, false,
5187 (cblock->next || cblock->block)
5188 ? cmask : NULL_TREE,
5189 NULL_TREE, mask_type, block);
5191 invert = false;
5193 /* It's a final elsewhere-stmt. No mask-expr is present. */
5194 else
5195 cmask = mask;
5197 /* The body of this where clause are controlled by cmask with
5198 sense specified by invert. */
5200 /* Get the assignment statement of a WHERE statement, or the first
5201 statement in where-body-construct of a WHERE construct. */
5202 cnext = cblock->next;
5203 while (cnext)
5205 switch (cnext->op)
5207 /* WHERE assignment statement. */
5208 case EXEC_ASSIGN_CALL:
5210 arg = cnext->ext.actual;
5211 expr1 = expr2 = NULL;
5212 for (; arg; arg = arg->next)
5214 if (!arg->expr)
5215 continue;
5216 if (expr1 == NULL)
5217 expr1 = arg->expr;
5218 else
5219 expr2 = arg->expr;
5221 goto evaluate;
5223 case EXEC_ASSIGN:
5224 expr1 = cnext->expr1;
5225 expr2 = cnext->expr2;
5226 evaluate:
5227 if (nested_forall_info != NULL)
5229 need_temp = gfc_check_dependency (expr1, expr2, 0);
5230 if ((need_temp || flag_test_forall_temp)
5231 && cnext->op != EXEC_ASSIGN_CALL)
5232 gfc_trans_assign_need_temp (expr1, expr2,
5233 cmask, invert,
5234 nested_forall_info, block);
5235 else
5237 /* Variables to control maskexpr. */
5238 count1 = gfc_create_var (gfc_array_index_type, "count1");
5239 count2 = gfc_create_var (gfc_array_index_type, "count2");
5240 gfc_add_modify (block, count1, gfc_index_zero_node);
5241 gfc_add_modify (block, count2, gfc_index_zero_node);
5243 tmp = gfc_trans_where_assign (expr1, expr2,
5244 cmask, invert,
5245 count1, count2,
5246 cnext);
5248 tmp = gfc_trans_nested_forall_loop (nested_forall_info,
5249 tmp, 1);
5250 gfc_add_expr_to_block (block, tmp);
5253 else
5255 /* Variables to control maskexpr. */
5256 count1 = gfc_create_var (gfc_array_index_type, "count1");
5257 count2 = gfc_create_var (gfc_array_index_type, "count2");
5258 gfc_add_modify (block, count1, gfc_index_zero_node);
5259 gfc_add_modify (block, count2, gfc_index_zero_node);
5261 tmp = gfc_trans_where_assign (expr1, expr2,
5262 cmask, invert,
5263 count1, count2,
5264 cnext);
5265 gfc_add_expr_to_block (block, tmp);
5268 break;
5270 /* WHERE or WHERE construct is part of a where-body-construct. */
5271 case EXEC_WHERE:
5272 gfc_trans_where_2 (cnext, cmask, invert,
5273 nested_forall_info, block);
5274 break;
5276 default:
5277 gcc_unreachable ();
5280 /* The next statement within the same where-body-construct. */
5281 cnext = cnext->next;
5283 /* The next masked-elsewhere-stmt, elsewhere-stmt, or end-where-stmt. */
5284 cblock = cblock->block;
5285 if (mask == NULL_TREE)
5287 /* If we're the initial WHERE, we can simply invert the sense
5288 of the current mask to obtain the "mask" for the remaining
5289 ELSEWHEREs. */
5290 invert = true;
5291 mask = cmask;
5293 else
5295 /* Otherwise, for nested WHERE's we need to use the pending mask. */
5296 invert = false;
5297 mask = pmask;
5301 /* If we allocated a pending mask array, deallocate it now. */
5302 if (ppmask)
5304 tmp = gfc_call_free (ppmask);
5305 gfc_add_expr_to_block (block, tmp);
5308 /* If we allocated a current mask array, deallocate it now. */
5309 if (pcmask)
5311 tmp = gfc_call_free (pcmask);
5312 gfc_add_expr_to_block (block, tmp);
5316 /* Translate a simple WHERE construct or statement without dependencies.
5317 CBLOCK is the "then" clause of the WHERE statement, where CBLOCK->EXPR
5318 is the mask condition, and EBLOCK if non-NULL is the "else" clause.
5319 Currently both CBLOCK and EBLOCK are restricted to single assignments. */
5321 static tree
5322 gfc_trans_where_3 (gfc_code * cblock, gfc_code * eblock)
5324 stmtblock_t block, body;
5325 gfc_expr *cond, *tdst, *tsrc, *edst, *esrc;
5326 tree tmp, cexpr, tstmt, estmt;
5327 gfc_ss *css, *tdss, *tsss;
5328 gfc_se cse, tdse, tsse, edse, esse;
5329 gfc_loopinfo loop;
5330 gfc_ss *edss = 0;
5331 gfc_ss *esss = 0;
5332 bool maybe_workshare = false;
5334 /* Allow the scalarizer to workshare simple where loops. */
5335 if ((ompws_flags & (OMPWS_WORKSHARE_FLAG | OMPWS_SCALARIZER_BODY))
5336 == OMPWS_WORKSHARE_FLAG)
5338 maybe_workshare = true;
5339 ompws_flags |= OMPWS_SCALARIZER_WS | OMPWS_SCALARIZER_BODY;
5342 cond = cblock->expr1;
5343 tdst = cblock->next->expr1;
5344 tsrc = cblock->next->expr2;
5345 edst = eblock ? eblock->next->expr1 : NULL;
5346 esrc = eblock ? eblock->next->expr2 : NULL;
5348 gfc_start_block (&block);
5349 gfc_init_loopinfo (&loop);
5351 /* Handle the condition. */
5352 gfc_init_se (&cse, NULL);
5353 css = gfc_walk_expr (cond);
5354 gfc_add_ss_to_loop (&loop, css);
5356 /* Handle the then-clause. */
5357 gfc_init_se (&tdse, NULL);
5358 gfc_init_se (&tsse, NULL);
5359 tdss = gfc_walk_expr (tdst);
5360 tsss = gfc_walk_expr (tsrc);
5361 if (tsss == gfc_ss_terminator)
5363 tsss = gfc_get_scalar_ss (gfc_ss_terminator, tsrc);
5364 tsss->info->where = 1;
5366 gfc_add_ss_to_loop (&loop, tdss);
5367 gfc_add_ss_to_loop (&loop, tsss);
5369 if (eblock)
5371 /* Handle the else clause. */
5372 gfc_init_se (&edse, NULL);
5373 gfc_init_se (&esse, NULL);
5374 edss = gfc_walk_expr (edst);
5375 esss = gfc_walk_expr (esrc);
5376 if (esss == gfc_ss_terminator)
5378 esss = gfc_get_scalar_ss (gfc_ss_terminator, esrc);
5379 esss->info->where = 1;
5381 gfc_add_ss_to_loop (&loop, edss);
5382 gfc_add_ss_to_loop (&loop, esss);
5385 gfc_conv_ss_startstride (&loop);
5386 gfc_conv_loop_setup (&loop, &tdst->where);
5388 gfc_mark_ss_chain_used (css, 1);
5389 gfc_mark_ss_chain_used (tdss, 1);
5390 gfc_mark_ss_chain_used (tsss, 1);
5391 if (eblock)
5393 gfc_mark_ss_chain_used (edss, 1);
5394 gfc_mark_ss_chain_used (esss, 1);
5397 gfc_start_scalarized_body (&loop, &body);
5399 gfc_copy_loopinfo_to_se (&cse, &loop);
5400 gfc_copy_loopinfo_to_se (&tdse, &loop);
5401 gfc_copy_loopinfo_to_se (&tsse, &loop);
5402 cse.ss = css;
5403 tdse.ss = tdss;
5404 tsse.ss = tsss;
5405 if (eblock)
5407 gfc_copy_loopinfo_to_se (&edse, &loop);
5408 gfc_copy_loopinfo_to_se (&esse, &loop);
5409 edse.ss = edss;
5410 esse.ss = esss;
5413 gfc_conv_expr (&cse, cond);
5414 gfc_add_block_to_block (&body, &cse.pre);
5415 cexpr = cse.expr;
5417 gfc_conv_expr (&tsse, tsrc);
5418 if (tdss != gfc_ss_terminator && loop.temp_ss != NULL)
5419 gfc_conv_tmp_array_ref (&tdse);
5420 else
5421 gfc_conv_expr (&tdse, tdst);
5423 if (eblock)
5425 gfc_conv_expr (&esse, esrc);
5426 if (edss != gfc_ss_terminator && loop.temp_ss != NULL)
5427 gfc_conv_tmp_array_ref (&edse);
5428 else
5429 gfc_conv_expr (&edse, edst);
5432 tstmt = gfc_trans_scalar_assign (&tdse, &tsse, tdst->ts, false, true);
5433 estmt = eblock ? gfc_trans_scalar_assign (&edse, &esse, edst->ts,
5434 false, true)
5435 : build_empty_stmt (input_location);
5436 tmp = build3_v (COND_EXPR, cexpr, tstmt, estmt);
5437 gfc_add_expr_to_block (&body, tmp);
5438 gfc_add_block_to_block (&body, &cse.post);
5440 if (maybe_workshare)
5441 ompws_flags &= ~OMPWS_SCALARIZER_BODY;
5442 gfc_trans_scalarizing_loops (&loop, &body);
5443 gfc_add_block_to_block (&block, &loop.pre);
5444 gfc_add_block_to_block (&block, &loop.post);
5445 gfc_cleanup_loop (&loop);
5447 return gfc_finish_block (&block);
5450 /* As the WHERE or WHERE construct statement can be nested, we call
5451 gfc_trans_where_2 to do the translation, and pass the initial
5452 NULL values for both the control mask and the pending control mask. */
5454 tree
5455 gfc_trans_where (gfc_code * code)
5457 stmtblock_t block;
5458 gfc_code *cblock;
5459 gfc_code *eblock;
5461 cblock = code->block;
5462 if (cblock->next
5463 && cblock->next->op == EXEC_ASSIGN
5464 && !cblock->next->next)
5466 eblock = cblock->block;
5467 if (!eblock)
5469 /* A simple "WHERE (cond) x = y" statement or block is
5470 dependence free if cond is not dependent upon writing x,
5471 and the source y is unaffected by the destination x. */
5472 if (!gfc_check_dependency (cblock->next->expr1,
5473 cblock->expr1, 0)
5474 && !gfc_check_dependency (cblock->next->expr1,
5475 cblock->next->expr2, 0))
5476 return gfc_trans_where_3 (cblock, NULL);
5478 else if (!eblock->expr1
5479 && !eblock->block
5480 && eblock->next
5481 && eblock->next->op == EXEC_ASSIGN
5482 && !eblock->next->next)
5484 /* A simple "WHERE (cond) x1 = y1 ELSEWHERE x2 = y2 ENDWHERE"
5485 block is dependence free if cond is not dependent on writes
5486 to x1 and x2, y1 is not dependent on writes to x2, and y2
5487 is not dependent on writes to x1, and both y's are not
5488 dependent upon their own x's. In addition to this, the
5489 final two dependency checks below exclude all but the same
5490 array reference if the where and elswhere destinations
5491 are the same. In short, this is VERY conservative and this
5492 is needed because the two loops, required by the standard
5493 are coalesced in gfc_trans_where_3. */
5494 if (!gfc_check_dependency (cblock->next->expr1,
5495 cblock->expr1, 0)
5496 && !gfc_check_dependency (eblock->next->expr1,
5497 cblock->expr1, 0)
5498 && !gfc_check_dependency (cblock->next->expr1,
5499 eblock->next->expr2, 1)
5500 && !gfc_check_dependency (eblock->next->expr1,
5501 cblock->next->expr2, 1)
5502 && !gfc_check_dependency (cblock->next->expr1,
5503 cblock->next->expr2, 1)
5504 && !gfc_check_dependency (eblock->next->expr1,
5505 eblock->next->expr2, 1)
5506 && !gfc_check_dependency (cblock->next->expr1,
5507 eblock->next->expr1, 0)
5508 && !gfc_check_dependency (eblock->next->expr1,
5509 cblock->next->expr1, 0))
5510 return gfc_trans_where_3 (cblock, eblock);
5514 gfc_start_block (&block);
5516 gfc_trans_where_2 (code, NULL, false, NULL, &block);
5518 return gfc_finish_block (&block);
5522 /* CYCLE a DO loop. The label decl has already been created by
5523 gfc_trans_do(), it's in TREE_PURPOSE (backend_decl) of the gfc_code
5524 node at the head of the loop. We must mark the label as used. */
5526 tree
5527 gfc_trans_cycle (gfc_code * code)
5529 tree cycle_label;
5531 cycle_label = code->ext.which_construct->cycle_label;
5532 gcc_assert (cycle_label);
5534 TREE_USED (cycle_label) = 1;
5535 return build1_v (GOTO_EXPR, cycle_label);
5539 /* EXIT a DO loop. Similar to CYCLE, but now the label is in
5540 TREE_VALUE (backend_decl) of the gfc_code node at the head of the
5541 loop. */
5543 tree
5544 gfc_trans_exit (gfc_code * code)
5546 tree exit_label;
5548 exit_label = code->ext.which_construct->exit_label;
5549 gcc_assert (exit_label);
5551 TREE_USED (exit_label) = 1;
5552 return build1_v (GOTO_EXPR, exit_label);
5556 /* Get the initializer expression for the code and expr of an allocate.
5557 When no initializer is needed return NULL. */
5559 static gfc_expr *
5560 allocate_get_initializer (gfc_code * code, gfc_expr * expr)
5562 if (!gfc_bt_struct (expr->ts.type) && expr->ts.type != BT_CLASS)
5563 return NULL;
5565 /* An explicit type was given in allocate ( T:: object). */
5566 if (code->ext.alloc.ts.type == BT_DERIVED
5567 && (code->ext.alloc.ts.u.derived->attr.alloc_comp
5568 || gfc_has_default_initializer (code->ext.alloc.ts.u.derived)))
5569 return gfc_default_initializer (&code->ext.alloc.ts);
5571 if (gfc_bt_struct (expr->ts.type)
5572 && (expr->ts.u.derived->attr.alloc_comp
5573 || gfc_has_default_initializer (expr->ts.u.derived)))
5574 return gfc_default_initializer (&expr->ts);
5576 if (expr->ts.type == BT_CLASS
5577 && (CLASS_DATA (expr)->ts.u.derived->attr.alloc_comp
5578 || gfc_has_default_initializer (CLASS_DATA (expr)->ts.u.derived)))
5579 return gfc_default_initializer (&CLASS_DATA (expr)->ts);
5581 return NULL;
5584 /* Translate the ALLOCATE statement. */
5586 tree
5587 gfc_trans_allocate (gfc_code * code)
5589 gfc_alloc *al;
5590 gfc_expr *expr, *e3rhs = NULL, *init_expr;
5591 gfc_se se, se_sz;
5592 tree tmp;
5593 tree parm;
5594 tree stat;
5595 tree errmsg;
5596 tree errlen;
5597 tree label_errmsg;
5598 tree label_finish;
5599 tree memsz;
5600 tree al_vptr, al_len;
5601 /* If an expr3 is present, then store the tree for accessing its
5602 _vptr, and _len components in the variables, respectively. The
5603 element size, i.e. _vptr%size, is stored in expr3_esize. Any of
5604 the trees may be the NULL_TREE indicating that this is not
5605 available for expr3's type. */
5606 tree expr3, expr3_vptr, expr3_len, expr3_esize;
5607 /* Classify what expr3 stores. */
5608 enum { E3_UNSET = 0, E3_SOURCE, E3_MOLD, E3_DESC } e3_is;
5609 stmtblock_t block;
5610 stmtblock_t post;
5611 tree nelems;
5612 bool upoly_expr, tmp_expr3_len_flag = false, al_len_needs_set, is_coarray;
5613 bool needs_caf_sync, caf_refs_comp;
5614 gfc_symtree *newsym = NULL;
5615 symbol_attribute caf_attr;
5616 gfc_actual_arglist *param_list;
5618 if (!code->ext.alloc.list)
5619 return NULL_TREE;
5621 stat = tmp = memsz = al_vptr = al_len = NULL_TREE;
5622 expr3 = expr3_vptr = expr3_len = expr3_esize = NULL_TREE;
5623 label_errmsg = label_finish = errmsg = errlen = NULL_TREE;
5624 e3_is = E3_UNSET;
5625 is_coarray = needs_caf_sync = false;
5627 gfc_init_block (&block);
5628 gfc_init_block (&post);
5630 /* STAT= (and maybe ERRMSG=) is present. */
5631 if (code->expr1)
5633 /* STAT=. */
5634 tree gfc_int4_type_node = gfc_get_int_type (4);
5635 stat = gfc_create_var (gfc_int4_type_node, "stat");
5637 /* ERRMSG= only makes sense with STAT=. */
5638 if (code->expr2)
5640 gfc_init_se (&se, NULL);
5641 se.want_pointer = 1;
5642 gfc_conv_expr_lhs (&se, code->expr2);
5643 errmsg = se.expr;
5644 errlen = se.string_length;
5646 else
5648 errmsg = null_pointer_node;
5649 errlen = build_int_cst (gfc_charlen_type_node, 0);
5652 /* GOTO destinations. */
5653 label_errmsg = gfc_build_label_decl (NULL_TREE);
5654 label_finish = gfc_build_label_decl (NULL_TREE);
5655 TREE_USED (label_finish) = 0;
5658 /* When an expr3 is present evaluate it only once. The standards prevent a
5659 dependency of expr3 on the objects in the allocate list. An expr3 can
5660 be pre-evaluated in all cases. One just has to make sure, to use the
5661 correct way, i.e., to get the descriptor or to get a reference
5662 expression. */
5663 if (code->expr3)
5665 bool vtab_needed = false, temp_var_needed = false,
5666 temp_obj_created = false;
5668 is_coarray = gfc_is_coarray (code->expr3);
5670 /* Figure whether we need the vtab from expr3. */
5671 for (al = code->ext.alloc.list; !vtab_needed && al != NULL;
5672 al = al->next)
5673 vtab_needed = (al->expr->ts.type == BT_CLASS);
5675 gfc_init_se (&se, NULL);
5676 /* When expr3 is a variable, i.e., a very simple expression,
5677 then convert it once here. */
5678 if (code->expr3->expr_type == EXPR_VARIABLE
5679 || code->expr3->expr_type == EXPR_ARRAY
5680 || code->expr3->expr_type == EXPR_CONSTANT)
5682 if (!code->expr3->mold
5683 || code->expr3->ts.type == BT_CHARACTER
5684 || vtab_needed
5685 || code->ext.alloc.arr_spec_from_expr3)
5687 /* Convert expr3 to a tree. For all "simple" expression just
5688 get the descriptor or the reference, respectively, depending
5689 on the rank of the expr. */
5690 if (code->ext.alloc.arr_spec_from_expr3 || code->expr3->rank != 0)
5691 gfc_conv_expr_descriptor (&se, code->expr3);
5692 else
5694 gfc_conv_expr_reference (&se, code->expr3);
5696 /* gfc_conv_expr_reference wraps POINTER_PLUS_EXPR in a
5697 NOP_EXPR, which prevents gfortran from getting the vptr
5698 from the source=-expression. Remove the NOP_EXPR and go
5699 with the POINTER_PLUS_EXPR in this case. */
5700 if (code->expr3->ts.type == BT_CLASS
5701 && TREE_CODE (se.expr) == NOP_EXPR
5702 && (TREE_CODE (TREE_OPERAND (se.expr, 0))
5703 == POINTER_PLUS_EXPR
5704 || is_coarray))
5705 se.expr = TREE_OPERAND (se.expr, 0);
5707 /* Create a temp variable only for component refs to prevent
5708 having to go through the full deref-chain each time and to
5709 simplfy computation of array properties. */
5710 temp_var_needed = TREE_CODE (se.expr) == COMPONENT_REF;
5713 else
5715 /* In all other cases evaluate the expr3. */
5716 symbol_attribute attr;
5717 /* Get the descriptor for all arrays, that are not allocatable or
5718 pointer, because the latter are descriptors already.
5719 The exception are function calls returning a class object:
5720 The descriptor is stored in their results _data component, which
5721 is easier to access, when first a temporary variable for the
5722 result is created and the descriptor retrieved from there. */
5723 attr = gfc_expr_attr (code->expr3);
5724 if (code->expr3->rank != 0
5725 && ((!attr.allocatable && !attr.pointer)
5726 || (code->expr3->expr_type == EXPR_FUNCTION
5727 && (code->expr3->ts.type != BT_CLASS
5728 || (code->expr3->value.function.isym
5729 && code->expr3->value.function.isym
5730 ->transformational)))))
5731 gfc_conv_expr_descriptor (&se, code->expr3);
5732 else
5733 gfc_conv_expr_reference (&se, code->expr3);
5734 if (code->expr3->ts.type == BT_CLASS)
5735 gfc_conv_class_to_class (&se, code->expr3,
5736 code->expr3->ts,
5737 false, true,
5738 false, false);
5739 temp_obj_created = temp_var_needed = !VAR_P (se.expr);
5741 gfc_add_block_to_block (&block, &se.pre);
5742 gfc_add_block_to_block (&post, &se.post);
5744 /* Special case when string in expr3 is zero. */
5745 if (code->expr3->ts.type == BT_CHARACTER
5746 && integer_zerop (se.string_length))
5748 gfc_init_se (&se, NULL);
5749 temp_var_needed = false;
5750 expr3_len = integer_zero_node;
5751 e3_is = E3_MOLD;
5753 /* Prevent aliasing, i.e., se.expr may be already a
5754 variable declaration. */
5755 else if (se.expr != NULL_TREE && temp_var_needed)
5757 tree var, desc;
5758 tmp = GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (se.expr)) || is_coarray ?
5759 se.expr
5760 : build_fold_indirect_ref_loc (input_location, se.expr);
5762 /* Get the array descriptor and prepare it to be assigned to the
5763 temporary variable var. For classes the array descriptor is
5764 in the _data component and the object goes into the
5765 GFC_DECL_SAVED_DESCRIPTOR. */
5766 if (code->expr3->ts.type == BT_CLASS
5767 && code->expr3->rank != 0)
5769 /* When an array_ref was in expr3, then the descriptor is the
5770 first operand. */
5771 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (tmp)) || is_coarray)
5773 desc = TREE_OPERAND (tmp, 0);
5775 else
5777 desc = tmp;
5778 tmp = gfc_class_data_get (tmp);
5780 if (code->ext.alloc.arr_spec_from_expr3)
5781 e3_is = E3_DESC;
5783 else
5784 desc = !is_coarray ? se.expr
5785 : TREE_OPERAND (TREE_OPERAND (se.expr, 0), 0);
5786 /* We need a regular (non-UID) symbol here, therefore give a
5787 prefix. */
5788 var = gfc_create_var (TREE_TYPE (tmp), "source");
5789 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (tmp)) || is_coarray)
5791 gfc_allocate_lang_decl (var);
5792 GFC_DECL_SAVED_DESCRIPTOR (var) = desc;
5794 gfc_add_modify_loc (input_location, &block, var, tmp);
5796 expr3 = var;
5797 if (se.string_length)
5798 /* Evaluate it assuming that it also is complicated like expr3. */
5799 expr3_len = gfc_evaluate_now (se.string_length, &block);
5801 else
5803 expr3 = se.expr;
5804 expr3_len = se.string_length;
5807 /* Deallocate any allocatable components in expressions that use a
5808 temporary object, i.e. are not a simple alias of to an EXPR_VARIABLE.
5809 E.g. temporaries of a function call need freeing of their components
5810 here. */
5811 if ((code->expr3->ts.type == BT_DERIVED
5812 || code->expr3->ts.type == BT_CLASS)
5813 && (code->expr3->expr_type != EXPR_VARIABLE || temp_obj_created)
5814 && code->expr3->ts.u.derived->attr.alloc_comp)
5816 tmp = gfc_deallocate_alloc_comp (code->expr3->ts.u.derived,
5817 expr3, code->expr3->rank);
5818 gfc_prepend_expr_to_block (&post, tmp);
5821 /* Store what the expr3 is to be used for. */
5822 if (e3_is == E3_UNSET)
5823 e3_is = expr3 != NULL_TREE ?
5824 (code->ext.alloc.arr_spec_from_expr3 ?
5825 E3_DESC
5826 : (code->expr3->mold ? E3_MOLD : E3_SOURCE))
5827 : E3_UNSET;
5829 /* Figure how to get the _vtab entry. This also obtains the tree
5830 expression for accessing the _len component, because only
5831 unlimited polymorphic objects, which are a subcategory of class
5832 types, have a _len component. */
5833 if (code->expr3->ts.type == BT_CLASS)
5835 gfc_expr *rhs;
5836 tmp = expr3 != NULL_TREE && POINTER_TYPE_P (TREE_TYPE (expr3)) ?
5837 build_fold_indirect_ref (expr3): expr3;
5838 /* Polymorphic SOURCE: VPTR must be determined at run time.
5839 expr3 may be a temporary array declaration, therefore check for
5840 GFC_CLASS_TYPE_P before trying to get the _vptr component. */
5841 if (tmp != NULL_TREE
5842 && (e3_is == E3_DESC
5843 || (GFC_CLASS_TYPE_P (TREE_TYPE (tmp))
5844 && (VAR_P (tmp) || !code->expr3->ref))
5845 || (VAR_P (tmp) && DECL_LANG_SPECIFIC (tmp))))
5846 tmp = gfc_class_vptr_get (expr3);
5847 else
5849 rhs = gfc_find_and_cut_at_last_class_ref (code->expr3);
5850 gfc_add_vptr_component (rhs);
5851 gfc_init_se (&se, NULL);
5852 se.want_pointer = 1;
5853 gfc_conv_expr (&se, rhs);
5854 tmp = se.expr;
5855 gfc_free_expr (rhs);
5857 /* Set the element size. */
5858 expr3_esize = gfc_vptr_size_get (tmp);
5859 if (vtab_needed)
5860 expr3_vptr = tmp;
5861 /* Initialize the ref to the _len component. */
5862 if (expr3_len == NULL_TREE && UNLIMITED_POLY (code->expr3))
5864 /* Same like for retrieving the _vptr. */
5865 if (expr3 != NULL_TREE && !code->expr3->ref)
5866 expr3_len = gfc_class_len_get (expr3);
5867 else
5869 rhs = gfc_find_and_cut_at_last_class_ref (code->expr3);
5870 gfc_add_len_component (rhs);
5871 gfc_init_se (&se, NULL);
5872 gfc_conv_expr (&se, rhs);
5873 expr3_len = se.expr;
5874 gfc_free_expr (rhs);
5878 else
5880 /* When the object to allocate is polymorphic type, then it
5881 needs its vtab set correctly, so deduce the required _vtab
5882 and _len from the source expression. */
5883 if (vtab_needed)
5885 /* VPTR is fixed at compile time. */
5886 gfc_symbol *vtab;
5888 vtab = gfc_find_vtab (&code->expr3->ts);
5889 gcc_assert (vtab);
5890 expr3_vptr = gfc_get_symbol_decl (vtab);
5891 expr3_vptr = gfc_build_addr_expr (NULL_TREE,
5892 expr3_vptr);
5894 /* _len component needs to be set, when ts is a character
5895 array. */
5896 if (expr3_len == NULL_TREE
5897 && code->expr3->ts.type == BT_CHARACTER)
5899 if (code->expr3->ts.u.cl
5900 && code->expr3->ts.u.cl->length)
5902 gfc_init_se (&se, NULL);
5903 gfc_conv_expr (&se, code->expr3->ts.u.cl->length);
5904 gfc_add_block_to_block (&block, &se.pre);
5905 expr3_len = gfc_evaluate_now (se.expr, &block);
5907 gcc_assert (expr3_len);
5909 /* For character arrays only the kind's size is needed, because
5910 the array mem_size is _len * (elem_size = kind_size).
5911 For all other get the element size in the normal way. */
5912 if (code->expr3->ts.type == BT_CHARACTER)
5913 expr3_esize = TYPE_SIZE_UNIT (
5914 gfc_get_char_type (code->expr3->ts.kind));
5915 else
5916 expr3_esize = TYPE_SIZE_UNIT (
5917 gfc_typenode_for_spec (&code->expr3->ts));
5919 gcc_assert (expr3_esize);
5920 expr3_esize = fold_convert (sizetype, expr3_esize);
5921 if (e3_is == E3_MOLD)
5922 /* The expr3 is no longer valid after this point. */
5923 expr3 = NULL_TREE;
5925 else if (code->ext.alloc.ts.type != BT_UNKNOWN)
5927 /* Compute the explicit typespec given only once for all objects
5928 to allocate. */
5929 if (code->ext.alloc.ts.type != BT_CHARACTER)
5930 expr3_esize = TYPE_SIZE_UNIT (
5931 gfc_typenode_for_spec (&code->ext.alloc.ts));
5932 else if (code->ext.alloc.ts.u.cl->length != NULL)
5934 gfc_expr *sz;
5935 sz = gfc_copy_expr (code->ext.alloc.ts.u.cl->length);
5936 gfc_init_se (&se_sz, NULL);
5937 gfc_conv_expr (&se_sz, sz);
5938 gfc_free_expr (sz);
5939 tmp = gfc_get_char_type (code->ext.alloc.ts.kind);
5940 tmp = TYPE_SIZE_UNIT (tmp);
5941 tmp = fold_convert (TREE_TYPE (se_sz.expr), tmp);
5942 gfc_add_block_to_block (&block, &se_sz.pre);
5943 expr3_esize = fold_build2_loc (input_location, MULT_EXPR,
5944 TREE_TYPE (se_sz.expr),
5945 tmp, se_sz.expr);
5946 expr3_esize = gfc_evaluate_now (expr3_esize, &block);
5948 else
5949 expr3_esize = NULL_TREE;
5952 /* The routine gfc_trans_assignment () already implements all
5953 techniques needed. Unfortunately we may have a temporary
5954 variable for the source= expression here. When that is the
5955 case convert this variable into a temporary gfc_expr of type
5956 EXPR_VARIABLE and used it as rhs for the assignment. The
5957 advantage is, that we get scalarizer support for free,
5958 don't have to take care about scalar to array treatment and
5959 will benefit of every enhancements gfc_trans_assignment ()
5960 gets.
5961 No need to check whether e3_is is E3_UNSET, because that is
5962 done by expr3 != NULL_TREE.
5963 Exclude variables since the following block does not handle
5964 array sections. In any case, there is no harm in sending
5965 variables to gfc_trans_assignment because there is no
5966 evaluation of variables. */
5967 if (code->expr3)
5969 if (code->expr3->expr_type != EXPR_VARIABLE
5970 && e3_is != E3_MOLD && expr3 != NULL_TREE
5971 && DECL_P (expr3) && DECL_ARTIFICIAL (expr3))
5973 /* Build a temporary symtree and symbol. Do not add it to the current
5974 namespace to prevent accidently modifying a colliding
5975 symbol's as. */
5976 newsym = XCNEW (gfc_symtree);
5977 /* The name of the symtree should be unique, because gfc_create_var ()
5978 took care about generating the identifier. */
5979 newsym->name
5980 = gfc_get_string ("%s", IDENTIFIER_POINTER (DECL_NAME (expr3)));
5981 newsym->n.sym = gfc_new_symbol (newsym->name, NULL);
5982 /* The backend_decl is known. It is expr3, which is inserted
5983 here. */
5984 newsym->n.sym->backend_decl = expr3;
5985 e3rhs = gfc_get_expr ();
5986 e3rhs->rank = code->expr3->rank;
5987 e3rhs->symtree = newsym;
5988 /* Mark the symbol referenced or gfc_trans_assignment will bug. */
5989 newsym->n.sym->attr.referenced = 1;
5990 e3rhs->expr_type = EXPR_VARIABLE;
5991 e3rhs->where = code->expr3->where;
5992 /* Set the symbols type, upto it was BT_UNKNOWN. */
5993 if (IS_CLASS_ARRAY (code->expr3)
5994 && code->expr3->expr_type == EXPR_FUNCTION
5995 && code->expr3->value.function.isym
5996 && code->expr3->value.function.isym->transformational)
5998 e3rhs->ts = CLASS_DATA (code->expr3)->ts;
6000 else if (code->expr3->ts.type == BT_CLASS
6001 && !GFC_CLASS_TYPE_P (TREE_TYPE (expr3)))
6002 e3rhs->ts = CLASS_DATA (code->expr3)->ts;
6003 else
6004 e3rhs->ts = code->expr3->ts;
6005 newsym->n.sym->ts = e3rhs->ts;
6006 /* Check whether the expr3 is array valued. */
6007 if (e3rhs->rank)
6009 gfc_array_spec *arr;
6010 arr = gfc_get_array_spec ();
6011 arr->rank = e3rhs->rank;
6012 arr->type = AS_DEFERRED;
6013 /* Set the dimension and pointer attribute for arrays
6014 to be on the safe side. */
6015 newsym->n.sym->attr.dimension = 1;
6016 newsym->n.sym->attr.pointer = 1;
6017 newsym->n.sym->as = arr;
6018 if (IS_CLASS_ARRAY (code->expr3)
6019 && code->expr3->expr_type == EXPR_FUNCTION
6020 && code->expr3->value.function.isym
6021 && code->expr3->value.function.isym->transformational)
6023 gfc_array_spec *tarr;
6024 tarr = gfc_get_array_spec ();
6025 *tarr = *arr;
6026 e3rhs->ts.u.derived->as = tarr;
6028 gfc_add_full_array_ref (e3rhs, arr);
6030 else if (POINTER_TYPE_P (TREE_TYPE (expr3)))
6031 newsym->n.sym->attr.pointer = 1;
6032 /* The string length is known, too. Set it for char arrays. */
6033 if (e3rhs->ts.type == BT_CHARACTER)
6034 newsym->n.sym->ts.u.cl->backend_decl = expr3_len;
6035 gfc_commit_symbol (newsym->n.sym);
6037 else
6038 e3rhs = gfc_copy_expr (code->expr3);
6041 /* Loop over all objects to allocate. */
6042 for (al = code->ext.alloc.list; al != NULL; al = al->next)
6044 expr = gfc_copy_expr (al->expr);
6045 /* UNLIMITED_POLY () needs the _data component to be set, when
6046 expr is a unlimited polymorphic object. But the _data component
6047 has not been set yet, so check the derived type's attr for the
6048 unlimited polymorphic flag to be safe. */
6049 upoly_expr = UNLIMITED_POLY (expr)
6050 || (expr->ts.type == BT_DERIVED
6051 && expr->ts.u.derived->attr.unlimited_polymorphic);
6052 gfc_init_se (&se, NULL);
6054 /* For class types prepare the expressions to ref the _vptr
6055 and the _len component. The latter for unlimited polymorphic
6056 types only. */
6057 if (expr->ts.type == BT_CLASS)
6059 gfc_expr *expr_ref_vptr, *expr_ref_len;
6060 gfc_add_data_component (expr);
6061 /* Prep the vptr handle. */
6062 expr_ref_vptr = gfc_copy_expr (al->expr);
6063 gfc_add_vptr_component (expr_ref_vptr);
6064 se.want_pointer = 1;
6065 gfc_conv_expr (&se, expr_ref_vptr);
6066 al_vptr = se.expr;
6067 se.want_pointer = 0;
6068 gfc_free_expr (expr_ref_vptr);
6069 /* Allocated unlimited polymorphic objects always have a _len
6070 component. */
6071 if (upoly_expr)
6073 expr_ref_len = gfc_copy_expr (al->expr);
6074 gfc_add_len_component (expr_ref_len);
6075 gfc_conv_expr (&se, expr_ref_len);
6076 al_len = se.expr;
6077 gfc_free_expr (expr_ref_len);
6079 else
6080 /* In a loop ensure that all loop variable dependent variables
6081 are initialized at the same spot in all execution paths. */
6082 al_len = NULL_TREE;
6084 else
6085 al_vptr = al_len = NULL_TREE;
6087 se.want_pointer = 1;
6088 se.descriptor_only = 1;
6090 gfc_conv_expr (&se, expr);
6091 if (expr->ts.type == BT_CHARACTER && expr->ts.deferred)
6092 /* se.string_length now stores the .string_length variable of expr
6093 needed to allocate character(len=:) arrays. */
6094 al_len = se.string_length;
6096 al_len_needs_set = al_len != NULL_TREE;
6097 /* When allocating an array one can not use much of the
6098 pre-evaluated expr3 expressions, because for most of them the
6099 scalarizer is needed which is not available in the pre-evaluation
6100 step. Therefore gfc_array_allocate () is responsible (and able)
6101 to handle the complete array allocation. Only the element size
6102 needs to be provided, which is done most of the time by the
6103 pre-evaluation step. */
6104 nelems = NULL_TREE;
6105 if (expr3_len && (code->expr3->ts.type == BT_CHARACTER
6106 || code->expr3->ts.type == BT_CLASS))
6108 /* When al is an array, then the element size for each element
6109 in the array is needed, which is the product of the len and
6110 esize for char arrays. For unlimited polymorphics len can be
6111 zero, therefore take the maximum of len and one. */
6112 tmp = fold_build2_loc (input_location, MAX_EXPR,
6113 TREE_TYPE (expr3_len),
6114 expr3_len, fold_convert (TREE_TYPE (expr3_len),
6115 integer_one_node));
6116 tmp = fold_build2_loc (input_location, MULT_EXPR,
6117 TREE_TYPE (expr3_esize), expr3_esize,
6118 fold_convert (TREE_TYPE (expr3_esize), tmp));
6120 else
6121 tmp = expr3_esize;
6122 if (!gfc_array_allocate (&se, expr, stat, errmsg, errlen,
6123 label_finish, tmp, &nelems,
6124 e3rhs ? e3rhs : code->expr3,
6125 e3_is == E3_DESC ? expr3 : NULL_TREE,
6126 code->expr3 != NULL && e3_is == E3_DESC
6127 && code->expr3->expr_type == EXPR_ARRAY))
6129 /* A scalar or derived type. First compute the size to
6130 allocate.
6132 expr3_len is set when expr3 is an unlimited polymorphic
6133 object or a deferred length string. */
6134 if (expr3_len != NULL_TREE)
6136 tmp = fold_convert (TREE_TYPE (expr3_esize), expr3_len);
6137 tmp = fold_build2_loc (input_location, MULT_EXPR,
6138 TREE_TYPE (expr3_esize),
6139 expr3_esize, tmp);
6140 if (code->expr3->ts.type != BT_CLASS)
6141 /* expr3 is a deferred length string, i.e., we are
6142 done. */
6143 memsz = tmp;
6144 else
6146 /* For unlimited polymorphic enties build
6147 (len > 0) ? element_size * len : element_size
6148 to compute the number of bytes to allocate.
6149 This allows the allocation of unlimited polymorphic
6150 objects from an expr3 that is also unlimited
6151 polymorphic and stores a _len dependent object,
6152 e.g., a string. */
6153 memsz = fold_build2_loc (input_location, GT_EXPR,
6154 logical_type_node, expr3_len,
6155 integer_zero_node);
6156 memsz = fold_build3_loc (input_location, COND_EXPR,
6157 TREE_TYPE (expr3_esize),
6158 memsz, tmp, expr3_esize);
6161 else if (expr3_esize != NULL_TREE)
6162 /* Any other object in expr3 just needs element size in
6163 bytes. */
6164 memsz = expr3_esize;
6165 else if ((expr->ts.type == BT_CHARACTER && expr->ts.deferred)
6166 || (upoly_expr
6167 && code->ext.alloc.ts.type == BT_CHARACTER))
6169 /* Allocating deferred length char arrays need the length
6170 to allocate in the alloc_type_spec. But also unlimited
6171 polymorphic objects may be allocated as char arrays.
6172 Both are handled here. */
6173 gfc_init_se (&se_sz, NULL);
6174 gfc_conv_expr (&se_sz, code->ext.alloc.ts.u.cl->length);
6175 gfc_add_block_to_block (&se.pre, &se_sz.pre);
6176 se_sz.expr = gfc_evaluate_now (se_sz.expr, &se.pre);
6177 gfc_add_block_to_block (&se.pre, &se_sz.post);
6178 expr3_len = se_sz.expr;
6179 tmp_expr3_len_flag = true;
6180 tmp = TYPE_SIZE_UNIT (
6181 gfc_get_char_type (code->ext.alloc.ts.kind));
6182 memsz = fold_build2_loc (input_location, MULT_EXPR,
6183 TREE_TYPE (tmp),
6184 fold_convert (TREE_TYPE (tmp),
6185 expr3_len),
6186 tmp);
6188 else if (expr->ts.type == BT_CHARACTER)
6190 /* Compute the number of bytes needed to allocate a fixed
6191 length char array. */
6192 gcc_assert (se.string_length != NULL_TREE);
6193 tmp = TYPE_SIZE_UNIT (gfc_get_char_type (expr->ts.kind));
6194 memsz = fold_build2_loc (input_location, MULT_EXPR,
6195 TREE_TYPE (tmp), tmp,
6196 fold_convert (TREE_TYPE (tmp),
6197 se.string_length));
6199 else if (code->ext.alloc.ts.type != BT_UNKNOWN)
6200 /* Handle all types, where the alloc_type_spec is set. */
6201 memsz = TYPE_SIZE_UNIT (gfc_typenode_for_spec (&code->ext.alloc.ts));
6202 else
6203 /* Handle size computation of the type declared to alloc. */
6204 memsz = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (se.expr)));
6206 /* Store the caf-attributes for latter use. */
6207 if (flag_coarray == GFC_FCOARRAY_LIB
6208 && (caf_attr = gfc_caf_attr (expr, true, &caf_refs_comp))
6209 .codimension)
6211 /* Scalar allocatable components in coarray'ed derived types make
6212 it here and are treated now. */
6213 tree caf_decl, token;
6214 gfc_se caf_se;
6216 is_coarray = true;
6217 /* Set flag, to add synchronize after the allocate. */
6218 needs_caf_sync = needs_caf_sync
6219 || caf_attr.coarray_comp || !caf_refs_comp;
6221 gfc_init_se (&caf_se, NULL);
6223 caf_decl = gfc_get_tree_for_caf_expr (expr);
6224 gfc_get_caf_token_offset (&caf_se, &token, NULL, caf_decl,
6225 NULL_TREE, NULL);
6226 gfc_add_block_to_block (&se.pre, &caf_se.pre);
6227 gfc_allocate_allocatable (&se.pre, se.expr, memsz,
6228 gfc_build_addr_expr (NULL_TREE, token),
6229 NULL_TREE, NULL_TREE, NULL_TREE,
6230 label_finish, expr, 1);
6232 /* Allocate - for non-pointers with re-alloc checking. */
6233 else if (gfc_expr_attr (expr).allocatable)
6234 gfc_allocate_allocatable (&se.pre, se.expr, memsz,
6235 NULL_TREE, stat, errmsg, errlen,
6236 label_finish, expr, 0);
6237 else
6238 gfc_allocate_using_malloc (&se.pre, se.expr, memsz, stat);
6240 else
6242 /* Allocating coarrays needs a sync after the allocate executed.
6243 Set the flag to add the sync after all objects are allocated. */
6244 if (flag_coarray == GFC_FCOARRAY_LIB
6245 && (caf_attr = gfc_caf_attr (expr, true, &caf_refs_comp))
6246 .codimension)
6248 is_coarray = true;
6249 needs_caf_sync = needs_caf_sync
6250 || caf_attr.coarray_comp || !caf_refs_comp;
6253 if (expr->ts.type == BT_CHARACTER && al_len != NULL_TREE
6254 && expr3_len != NULL_TREE)
6256 /* Arrays need to have a _len set before the array
6257 descriptor is filled. */
6258 gfc_add_modify (&block, al_len,
6259 fold_convert (TREE_TYPE (al_len), expr3_len));
6260 /* Prevent setting the length twice. */
6261 al_len_needs_set = false;
6263 else if (expr->ts.type == BT_CHARACTER && al_len != NULL_TREE
6264 && code->ext.alloc.ts.u.cl->length)
6266 /* Cover the cases where a string length is explicitly
6267 specified by a type spec for deferred length character
6268 arrays or unlimited polymorphic objects without a
6269 source= or mold= expression. */
6270 gfc_init_se (&se_sz, NULL);
6271 gfc_conv_expr (&se_sz, code->ext.alloc.ts.u.cl->length);
6272 gfc_add_block_to_block (&block, &se_sz.pre);
6273 gfc_add_modify (&block, al_len,
6274 fold_convert (TREE_TYPE (al_len),
6275 se_sz.expr));
6276 al_len_needs_set = false;
6280 gfc_add_block_to_block (&block, &se.pre);
6282 /* Error checking -- Note: ERRMSG only makes sense with STAT. */
6283 if (code->expr1)
6285 tmp = build1_v (GOTO_EXPR, label_errmsg);
6286 parm = fold_build2_loc (input_location, NE_EXPR,
6287 logical_type_node, stat,
6288 build_int_cst (TREE_TYPE (stat), 0));
6289 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
6290 gfc_unlikely (parm, PRED_FORTRAN_FAIL_ALLOC),
6291 tmp, build_empty_stmt (input_location));
6292 gfc_add_expr_to_block (&block, tmp);
6295 /* Set the vptr only when no source= is set. When source= is set, then
6296 the trans_assignment below will set the vptr. */
6297 if (al_vptr != NULL_TREE && (!code->expr3 || code->expr3->mold))
6299 if (expr3_vptr != NULL_TREE)
6300 /* The vtab is already known, so just assign it. */
6301 gfc_add_modify (&block, al_vptr,
6302 fold_convert (TREE_TYPE (al_vptr), expr3_vptr));
6303 else
6305 /* VPTR is fixed at compile time. */
6306 gfc_symbol *vtab;
6307 gfc_typespec *ts;
6309 if (code->expr3)
6310 /* Although expr3 is pre-evaluated above, it may happen,
6311 that for arrays or in mold= cases the pre-evaluation
6312 was not successful. In these rare cases take the vtab
6313 from the typespec of expr3 here. */
6314 ts = &code->expr3->ts;
6315 else if (code->ext.alloc.ts.type == BT_DERIVED || upoly_expr)
6316 /* The alloc_type_spec gives the type to allocate or the
6317 al is unlimited polymorphic, which enforces the use of
6318 an alloc_type_spec that is not necessarily a BT_DERIVED. */
6319 ts = &code->ext.alloc.ts;
6320 else
6321 /* Prepare for setting the vtab as declared. */
6322 ts = &expr->ts;
6324 vtab = gfc_find_vtab (ts);
6325 gcc_assert (vtab);
6326 tmp = gfc_build_addr_expr (NULL_TREE,
6327 gfc_get_symbol_decl (vtab));
6328 gfc_add_modify (&block, al_vptr,
6329 fold_convert (TREE_TYPE (al_vptr), tmp));
6333 /* Add assignment for string length. */
6334 if (al_len != NULL_TREE && al_len_needs_set)
6336 if (expr3_len != NULL_TREE)
6338 gfc_add_modify (&block, al_len,
6339 fold_convert (TREE_TYPE (al_len),
6340 expr3_len));
6341 /* When tmp_expr3_len_flag is set, then expr3_len is
6342 abused to carry the length information from the
6343 alloc_type. Clear it to prevent setting incorrect len
6344 information in future loop iterations. */
6345 if (tmp_expr3_len_flag)
6346 /* No need to reset tmp_expr3_len_flag, because the
6347 presence of an expr3 can not change within in the
6348 loop. */
6349 expr3_len = NULL_TREE;
6351 else if (code->ext.alloc.ts.type == BT_CHARACTER
6352 && code->ext.alloc.ts.u.cl->length)
6354 /* Cover the cases where a string length is explicitly
6355 specified by a type spec for deferred length character
6356 arrays or unlimited polymorphic objects without a
6357 source= or mold= expression. */
6358 if (expr3_esize == NULL_TREE || code->ext.alloc.ts.kind != 1)
6360 gfc_init_se (&se_sz, NULL);
6361 gfc_conv_expr (&se_sz, code->ext.alloc.ts.u.cl->length);
6362 gfc_add_block_to_block (&block, &se_sz.pre);
6363 gfc_add_modify (&block, al_len,
6364 fold_convert (TREE_TYPE (al_len),
6365 se_sz.expr));
6367 else
6368 gfc_add_modify (&block, al_len,
6369 fold_convert (TREE_TYPE (al_len),
6370 expr3_esize));
6372 else
6373 /* No length information needed, because type to allocate
6374 has no length. Set _len to 0. */
6375 gfc_add_modify (&block, al_len,
6376 fold_convert (TREE_TYPE (al_len),
6377 integer_zero_node));
6380 init_expr = NULL;
6381 if (code->expr3 && !code->expr3->mold && e3_is != E3_MOLD)
6383 /* Initialization via SOURCE block (or static default initializer).
6384 Switch off automatic reallocation since we have just done the
6385 ALLOCATE. */
6386 int realloc_lhs = flag_realloc_lhs;
6387 gfc_expr *init_expr = gfc_expr_to_initialize (expr);
6388 gfc_expr *rhs = e3rhs ? e3rhs : gfc_copy_expr (code->expr3);
6389 flag_realloc_lhs = 0;
6390 tmp = gfc_trans_assignment (init_expr, rhs, false, false, true,
6391 false);
6392 flag_realloc_lhs = realloc_lhs;
6393 /* Free the expression allocated for init_expr. */
6394 gfc_free_expr (init_expr);
6395 if (rhs != e3rhs)
6396 gfc_free_expr (rhs);
6397 gfc_add_expr_to_block (&block, tmp);
6399 /* Set KIND and LEN PDT components and allocate those that are
6400 parameterized. */
6401 else if (expr->ts.type == BT_DERIVED
6402 && expr->ts.u.derived->attr.pdt_type)
6404 if (code->expr3 && code->expr3->param_list)
6405 param_list = code->expr3->param_list;
6406 else if (expr->param_list)
6407 param_list = expr->param_list;
6408 else
6409 param_list = expr->symtree->n.sym->param_list;
6410 tmp = gfc_allocate_pdt_comp (expr->ts.u.derived, se.expr,
6411 expr->rank, param_list);
6412 gfc_add_expr_to_block (&block, tmp);
6414 /* Ditto for CLASS expressions. */
6415 else if (expr->ts.type == BT_CLASS
6416 && CLASS_DATA (expr)->ts.u.derived->attr.pdt_type)
6418 if (code->expr3 && code->expr3->param_list)
6419 param_list = code->expr3->param_list;
6420 else if (expr->param_list)
6421 param_list = expr->param_list;
6422 else
6423 param_list = expr->symtree->n.sym->param_list;
6424 tmp = gfc_allocate_pdt_comp (CLASS_DATA (expr)->ts.u.derived,
6425 se.expr, expr->rank, param_list);
6426 gfc_add_expr_to_block (&block, tmp);
6428 else if (code->expr3 && code->expr3->mold
6429 && code->expr3->ts.type == BT_CLASS)
6431 /* Use class_init_assign to initialize expr. */
6432 gfc_code *ini;
6433 ini = gfc_get_code (EXEC_INIT_ASSIGN);
6434 ini->expr1 = gfc_find_and_cut_at_last_class_ref (expr);
6435 tmp = gfc_trans_class_init_assign (ini);
6436 gfc_free_statements (ini);
6437 gfc_add_expr_to_block (&block, tmp);
6439 else if ((init_expr = allocate_get_initializer (code, expr)))
6441 /* Use class_init_assign to initialize expr. */
6442 gfc_code *ini;
6443 int realloc_lhs = flag_realloc_lhs;
6444 ini = gfc_get_code (EXEC_INIT_ASSIGN);
6445 ini->expr1 = gfc_expr_to_initialize (expr);
6446 ini->expr2 = init_expr;
6447 flag_realloc_lhs = 0;
6448 tmp= gfc_trans_init_assign (ini);
6449 flag_realloc_lhs = realloc_lhs;
6450 gfc_free_statements (ini);
6451 /* Init_expr is freeed by above free_statements, just need to null
6452 it here. */
6453 init_expr = NULL;
6454 gfc_add_expr_to_block (&block, tmp);
6457 /* Nullify all pointers in derived type coarrays. This registers a
6458 token for them which allows their allocation. */
6459 if (is_coarray)
6461 gfc_symbol *type = NULL;
6462 symbol_attribute caf_attr;
6463 int rank = 0;
6464 if (code->ext.alloc.ts.type == BT_DERIVED
6465 && code->ext.alloc.ts.u.derived->attr.pointer_comp)
6467 type = code->ext.alloc.ts.u.derived;
6468 rank = type->attr.dimension ? type->as->rank : 0;
6469 gfc_clear_attr (&caf_attr);
6471 else if (expr->ts.type == BT_DERIVED
6472 && expr->ts.u.derived->attr.pointer_comp)
6474 type = expr->ts.u.derived;
6475 rank = expr->rank;
6476 caf_attr = gfc_caf_attr (expr, true);
6479 /* Initialize the tokens of pointer components in derived type
6480 coarrays. */
6481 if (type)
6483 tmp = (caf_attr.codimension && !caf_attr.dimension)
6484 ? gfc_conv_descriptor_data_get (se.expr) : se.expr;
6485 tmp = gfc_nullify_alloc_comp (type, tmp, rank,
6486 GFC_STRUCTURE_CAF_MODE_IN_COARRAY);
6487 gfc_add_expr_to_block (&block, tmp);
6491 gfc_free_expr (expr);
6492 } // for-loop
6494 if (e3rhs)
6496 if (newsym)
6498 gfc_free_symbol (newsym->n.sym);
6499 XDELETE (newsym);
6501 gfc_free_expr (e3rhs);
6503 /* STAT. */
6504 if (code->expr1)
6506 tmp = build1_v (LABEL_EXPR, label_errmsg);
6507 gfc_add_expr_to_block (&block, tmp);
6510 /* ERRMSG - only useful if STAT is present. */
6511 if (code->expr1 && code->expr2)
6513 const char *msg = "Attempt to allocate an allocated object";
6514 tree slen, dlen, errmsg_str;
6515 stmtblock_t errmsg_block;
6517 gfc_init_block (&errmsg_block);
6519 errmsg_str = gfc_create_var (pchar_type_node, "ERRMSG");
6520 gfc_add_modify (&errmsg_block, errmsg_str,
6521 gfc_build_addr_expr (pchar_type_node,
6522 gfc_build_localized_cstring_const (msg)));
6524 slen = build_int_cst (gfc_charlen_type_node, ((int) strlen (msg)));
6525 dlen = gfc_get_expr_charlen (code->expr2);
6526 slen = fold_build2_loc (input_location, MIN_EXPR,
6527 TREE_TYPE (slen), dlen, slen);
6529 gfc_trans_string_copy (&errmsg_block, dlen, errmsg,
6530 code->expr2->ts.kind,
6531 slen, errmsg_str,
6532 gfc_default_character_kind);
6533 dlen = gfc_finish_block (&errmsg_block);
6535 tmp = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
6536 stat, build_int_cst (TREE_TYPE (stat), 0));
6538 tmp = build3_v (COND_EXPR, tmp,
6539 dlen, build_empty_stmt (input_location));
6541 gfc_add_expr_to_block (&block, tmp);
6544 /* STAT block. */
6545 if (code->expr1)
6547 if (TREE_USED (label_finish))
6549 tmp = build1_v (LABEL_EXPR, label_finish);
6550 gfc_add_expr_to_block (&block, tmp);
6553 gfc_init_se (&se, NULL);
6554 gfc_conv_expr_lhs (&se, code->expr1);
6555 tmp = convert (TREE_TYPE (se.expr), stat);
6556 gfc_add_modify (&block, se.expr, tmp);
6559 if (needs_caf_sync)
6561 /* Add a sync all after the allocation has been executed. */
6562 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sync_all,
6563 3, null_pointer_node, null_pointer_node,
6564 integer_zero_node);
6565 gfc_add_expr_to_block (&post, tmp);
6568 gfc_add_block_to_block (&block, &se.post);
6569 gfc_add_block_to_block (&block, &post);
6571 return gfc_finish_block (&block);
6575 /* Translate a DEALLOCATE statement. */
6577 tree
6578 gfc_trans_deallocate (gfc_code *code)
6580 gfc_se se;
6581 gfc_alloc *al;
6582 tree apstat, pstat, stat, errmsg, errlen, tmp;
6583 tree label_finish, label_errmsg;
6584 stmtblock_t block;
6586 pstat = apstat = stat = errmsg = errlen = tmp = NULL_TREE;
6587 label_finish = label_errmsg = NULL_TREE;
6589 gfc_start_block (&block);
6591 /* Count the number of failed deallocations. If deallocate() was
6592 called with STAT= , then set STAT to the count. If deallocate
6593 was called with ERRMSG, then set ERRMG to a string. */
6594 if (code->expr1)
6596 tree gfc_int4_type_node = gfc_get_int_type (4);
6598 stat = gfc_create_var (gfc_int4_type_node, "stat");
6599 pstat = gfc_build_addr_expr (NULL_TREE, stat);
6601 /* GOTO destinations. */
6602 label_errmsg = gfc_build_label_decl (NULL_TREE);
6603 label_finish = gfc_build_label_decl (NULL_TREE);
6604 TREE_USED (label_finish) = 0;
6607 /* Set ERRMSG - only needed if STAT is available. */
6608 if (code->expr1 && code->expr2)
6610 gfc_init_se (&se, NULL);
6611 se.want_pointer = 1;
6612 gfc_conv_expr_lhs (&se, code->expr2);
6613 errmsg = se.expr;
6614 errlen = se.string_length;
6617 for (al = code->ext.alloc.list; al != NULL; al = al->next)
6619 gfc_expr *expr = gfc_copy_expr (al->expr);
6620 bool is_coarray = false, is_coarray_array = false;
6621 int caf_mode = 0;
6623 gcc_assert (expr->expr_type == EXPR_VARIABLE);
6625 if (expr->ts.type == BT_CLASS)
6626 gfc_add_data_component (expr);
6628 gfc_init_se (&se, NULL);
6629 gfc_start_block (&se.pre);
6631 se.want_pointer = 1;
6632 se.descriptor_only = 1;
6633 gfc_conv_expr (&se, expr);
6635 /* Deallocate PDT components that are parameterized. */
6636 tmp = NULL;
6637 if (expr->ts.type == BT_DERIVED
6638 && expr->ts.u.derived->attr.pdt_type
6639 && expr->symtree->n.sym->param_list)
6640 tmp = gfc_deallocate_pdt_comp (expr->ts.u.derived, se.expr, expr->rank);
6641 else if (expr->ts.type == BT_CLASS
6642 && CLASS_DATA (expr)->ts.u.derived->attr.pdt_type
6643 && expr->symtree->n.sym->param_list)
6644 tmp = gfc_deallocate_pdt_comp (CLASS_DATA (expr)->ts.u.derived,
6645 se.expr, expr->rank);
6647 if (tmp)
6648 gfc_add_expr_to_block (&block, tmp);
6650 if (flag_coarray == GFC_FCOARRAY_LIB
6651 || flag_coarray == GFC_FCOARRAY_SINGLE)
6653 bool comp_ref;
6654 symbol_attribute caf_attr = gfc_caf_attr (expr, false, &comp_ref);
6655 if (caf_attr.codimension)
6657 is_coarray = true;
6658 is_coarray_array = caf_attr.dimension || !comp_ref
6659 || caf_attr.coarray_comp;
6661 if (flag_coarray == GFC_FCOARRAY_LIB)
6662 /* When the expression to deallocate is referencing a
6663 component, then only deallocate it, but do not
6664 deregister. */
6665 caf_mode = GFC_STRUCTURE_CAF_MODE_IN_COARRAY
6666 | (comp_ref && !caf_attr.coarray_comp
6667 ? GFC_STRUCTURE_CAF_MODE_DEALLOC_ONLY : 0);
6671 if (expr->rank || is_coarray_array)
6673 gfc_ref *ref;
6675 if (gfc_bt_struct (expr->ts.type)
6676 && expr->ts.u.derived->attr.alloc_comp
6677 && !gfc_is_finalizable (expr->ts.u.derived, NULL))
6679 gfc_ref *last = NULL;
6681 for (ref = expr->ref; ref; ref = ref->next)
6682 if (ref->type == REF_COMPONENT)
6683 last = ref;
6685 /* Do not deallocate the components of a derived type
6686 ultimate pointer component. */
6687 if (!(last && last->u.c.component->attr.pointer)
6688 && !(!last && expr->symtree->n.sym->attr.pointer))
6690 if (is_coarray && expr->rank == 0
6691 && (!last || !last->u.c.component->attr.dimension)
6692 && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (se.expr)))
6694 /* Add the ref to the data member only, when this is not
6695 a regular array or deallocate_alloc_comp will try to
6696 add another one. */
6697 tmp = gfc_conv_descriptor_data_get (se.expr);
6699 else
6700 tmp = se.expr;
6701 tmp = gfc_deallocate_alloc_comp (expr->ts.u.derived, tmp,
6702 expr->rank, caf_mode);
6703 gfc_add_expr_to_block (&se.pre, tmp);
6707 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (se.expr)))
6709 gfc_coarray_deregtype caf_dtype;
6711 if (is_coarray)
6712 caf_dtype = gfc_caf_is_dealloc_only (caf_mode)
6713 ? GFC_CAF_COARRAY_DEALLOCATE_ONLY
6714 : GFC_CAF_COARRAY_DEREGISTER;
6715 else
6716 caf_dtype = GFC_CAF_COARRAY_NOCOARRAY;
6717 tmp = gfc_deallocate_with_status (se.expr, pstat, errmsg, errlen,
6718 label_finish, false, expr,
6719 caf_dtype);
6720 gfc_add_expr_to_block (&se.pre, tmp);
6722 else if (TREE_CODE (se.expr) == COMPONENT_REF
6723 && TREE_CODE (TREE_TYPE (se.expr)) == ARRAY_TYPE
6724 && TREE_CODE (TREE_TYPE (TREE_TYPE (se.expr)))
6725 == RECORD_TYPE)
6727 /* class.c(finalize_component) generates these, when a
6728 finalizable entity has a non-allocatable derived type array
6729 component, which has allocatable components. Obtain the
6730 derived type of the array and deallocate the allocatable
6731 components. */
6732 for (ref = expr->ref; ref; ref = ref->next)
6734 if (ref->u.c.component->attr.dimension
6735 && ref->u.c.component->ts.type == BT_DERIVED)
6736 break;
6739 if (ref && ref->u.c.component->ts.u.derived->attr.alloc_comp
6740 && !gfc_is_finalizable (ref->u.c.component->ts.u.derived,
6741 NULL))
6743 tmp = gfc_deallocate_alloc_comp
6744 (ref->u.c.component->ts.u.derived,
6745 se.expr, expr->rank);
6746 gfc_add_expr_to_block (&se.pre, tmp);
6750 if (al->expr->ts.type == BT_CLASS)
6752 gfc_reset_vptr (&se.pre, al->expr);
6753 if (UNLIMITED_POLY (al->expr)
6754 || (al->expr->ts.type == BT_DERIVED
6755 && al->expr->ts.u.derived->attr.unlimited_polymorphic))
6756 /* Clear _len, too. */
6757 gfc_reset_len (&se.pre, al->expr);
6760 else
6762 tmp = gfc_deallocate_scalar_with_status (se.expr, pstat, label_finish,
6763 false, al->expr,
6764 al->expr->ts, is_coarray);
6765 gfc_add_expr_to_block (&se.pre, tmp);
6767 /* Set to zero after deallocation. */
6768 tmp = fold_build2_loc (input_location, MODIFY_EXPR, void_type_node,
6769 se.expr,
6770 build_int_cst (TREE_TYPE (se.expr), 0));
6771 gfc_add_expr_to_block (&se.pre, tmp);
6773 if (al->expr->ts.type == BT_CLASS)
6775 gfc_reset_vptr (&se.pre, al->expr);
6776 if (UNLIMITED_POLY (al->expr)
6777 || (al->expr->ts.type == BT_DERIVED
6778 && al->expr->ts.u.derived->attr.unlimited_polymorphic))
6779 /* Clear _len, too. */
6780 gfc_reset_len (&se.pre, al->expr);
6784 if (code->expr1)
6786 tree cond;
6788 cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node, stat,
6789 build_int_cst (TREE_TYPE (stat), 0));
6790 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
6791 gfc_unlikely (cond, PRED_FORTRAN_FAIL_ALLOC),
6792 build1_v (GOTO_EXPR, label_errmsg),
6793 build_empty_stmt (input_location));
6794 gfc_add_expr_to_block (&se.pre, tmp);
6797 tmp = gfc_finish_block (&se.pre);
6798 gfc_add_expr_to_block (&block, tmp);
6799 gfc_free_expr (expr);
6802 if (code->expr1)
6804 tmp = build1_v (LABEL_EXPR, label_errmsg);
6805 gfc_add_expr_to_block (&block, tmp);
6808 /* Set ERRMSG - only needed if STAT is available. */
6809 if (code->expr1 && code->expr2)
6811 const char *msg = "Attempt to deallocate an unallocated object";
6812 stmtblock_t errmsg_block;
6813 tree errmsg_str, slen, dlen, cond;
6815 gfc_init_block (&errmsg_block);
6817 errmsg_str = gfc_create_var (pchar_type_node, "ERRMSG");
6818 gfc_add_modify (&errmsg_block, errmsg_str,
6819 gfc_build_addr_expr (pchar_type_node,
6820 gfc_build_localized_cstring_const (msg)));
6821 slen = build_int_cst (gfc_charlen_type_node, ((int) strlen (msg)));
6822 dlen = gfc_get_expr_charlen (code->expr2);
6824 gfc_trans_string_copy (&errmsg_block, dlen, errmsg, code->expr2->ts.kind,
6825 slen, errmsg_str, gfc_default_character_kind);
6826 tmp = gfc_finish_block (&errmsg_block);
6828 cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node, stat,
6829 build_int_cst (TREE_TYPE (stat), 0));
6830 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
6831 gfc_unlikely (cond, PRED_FORTRAN_FAIL_ALLOC), tmp,
6832 build_empty_stmt (input_location));
6834 gfc_add_expr_to_block (&block, tmp);
6837 if (code->expr1 && TREE_USED (label_finish))
6839 tmp = build1_v (LABEL_EXPR, label_finish);
6840 gfc_add_expr_to_block (&block, tmp);
6843 /* Set STAT. */
6844 if (code->expr1)
6846 gfc_init_se (&se, NULL);
6847 gfc_conv_expr_lhs (&se, code->expr1);
6848 tmp = convert (TREE_TYPE (se.expr), stat);
6849 gfc_add_modify (&block, se.expr, tmp);
6852 return gfc_finish_block (&block);
6855 #include "gt-fortran-trans-stmt.h"