Use gather loads for strided accesses
[official-gcc.git] / gcc / fortran / trans-stmt.c
blobff6e5914319303432536d1fec855c3692f5c59ad
1 /* Statement translation -- generate GCC trees from gfc_code.
2 Copyright (C) 2002-2018 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 = build_int_cst (gfc_charlen_type_node, -1);
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, fold_convert (TREE_TYPE (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 (TREE_TYPE (sym->ts.u.cl->backend_decl),
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 if (e->expr_type == EXPR_FUNCTION
1638 && sym->ts.type == BT_DERIVED
1639 && sym->ts.u.derived
1640 && sym->ts.u.derived->attr.pdt_type)
1642 tmp = gfc_deallocate_pdt_comp (sym->ts.u.derived, se.expr,
1643 sym->as->rank);
1644 gfc_add_expr_to_block (&se.post, tmp);
1647 /* Done, register stuff as init / cleanup code. */
1648 gfc_add_init_cleanup (block, gfc_finish_block (&se.pre),
1649 gfc_finish_block (&se.post));
1652 /* Temporaries, arising from TYPE IS, just need the descriptor of class
1653 arrays to be assigned directly. */
1654 else if (class_target && sym->attr.dimension
1655 && (sym->ts.type == BT_DERIVED || unlimited))
1657 gfc_se se;
1659 gfc_init_se (&se, NULL);
1660 se.descriptor_only = 1;
1661 /* In a select type the (temporary) associate variable shall point to
1662 a standard fortran array (lower bound == 1), but conv_expr ()
1663 just maps to the input array in the class object, whose lbound may
1664 be arbitrary. conv_expr_descriptor solves this by inserting a
1665 temporary array descriptor. */
1666 gfc_conv_expr_descriptor (&se, e);
1668 gcc_assert (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (se.expr))
1669 || GFC_ARRAY_TYPE_P (TREE_TYPE (se.expr)));
1670 gcc_assert (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (sym->backend_decl)));
1672 if (GFC_ARRAY_TYPE_P (TREE_TYPE (se.expr)))
1674 if (INDIRECT_REF_P (se.expr))
1675 tmp = TREE_OPERAND (se.expr, 0);
1676 else
1677 tmp = se.expr;
1679 gfc_add_modify (&se.pre, sym->backend_decl,
1680 gfc_class_data_get (GFC_DECL_SAVED_DESCRIPTOR (tmp)));
1682 else
1683 gfc_add_modify (&se.pre, sym->backend_decl, se.expr);
1685 if (unlimited)
1687 /* Recover the dtype, which has been overwritten by the
1688 assignment from an unlimited polymorphic object. */
1689 tmp = gfc_conv_descriptor_dtype (sym->backend_decl);
1690 gfc_add_modify (&se.pre, tmp,
1691 gfc_get_dtype (TREE_TYPE (sym->backend_decl)));
1694 gfc_add_init_cleanup (block, gfc_finish_block (&se.pre),
1695 gfc_finish_block (&se.post));
1698 /* Do a scalar pointer assignment; this is for scalar variable targets. */
1699 else if (gfc_is_associate_pointer (sym))
1701 gfc_se se;
1703 gcc_assert (!sym->attr.dimension);
1705 gfc_init_se (&se, NULL);
1707 /* Class associate-names come this way because they are
1708 unconditionally associate pointers and the symbol is scalar. */
1709 if (sym->ts.type == BT_CLASS && CLASS_DATA (sym)->attr.dimension)
1711 tree target_expr;
1712 /* For a class array we need a descriptor for the selector. */
1713 gfc_conv_expr_descriptor (&se, e);
1714 /* Needed to get/set the _len component below. */
1715 target_expr = se.expr;
1717 /* Obtain a temporary class container for the result. */
1718 gfc_conv_class_to_class (&se, e, sym->ts, false, true, false, false);
1719 se.expr = build_fold_indirect_ref_loc (input_location, se.expr);
1721 /* Set the offset. */
1722 desc = gfc_class_data_get (se.expr);
1723 offset = gfc_index_zero_node;
1724 for (n = 0; n < e->rank; n++)
1726 dim = gfc_rank_cst[n];
1727 tmp = fold_build2_loc (input_location, MULT_EXPR,
1728 gfc_array_index_type,
1729 gfc_conv_descriptor_stride_get (desc, dim),
1730 gfc_conv_descriptor_lbound_get (desc, dim));
1731 offset = fold_build2_loc (input_location, MINUS_EXPR,
1732 gfc_array_index_type,
1733 offset, tmp);
1735 if (need_len_assign)
1737 if (e->symtree
1738 && DECL_LANG_SPECIFIC (e->symtree->n.sym->backend_decl)
1739 && GFC_DECL_SAVED_DESCRIPTOR (e->symtree->n.sym->backend_decl))
1740 /* Use the original class descriptor stored in the saved
1741 descriptor to get the target_expr. */
1742 target_expr =
1743 GFC_DECL_SAVED_DESCRIPTOR (e->symtree->n.sym->backend_decl);
1744 else
1745 /* Strip the _data component from the target_expr. */
1746 target_expr = TREE_OPERAND (target_expr, 0);
1747 /* Add a reference to the _len comp to the target expr. */
1748 tmp = gfc_class_len_get (target_expr);
1749 /* Get the component-ref for the temp structure's _len comp. */
1750 charlen = gfc_class_len_get (se.expr);
1751 /* Add the assign to the beginning of the block... */
1752 gfc_add_modify (&se.pre, charlen,
1753 fold_convert (TREE_TYPE (charlen), tmp));
1754 /* and the oposite way at the end of the block, to hand changes
1755 on the string length back. */
1756 gfc_add_modify (&se.post, tmp,
1757 fold_convert (TREE_TYPE (tmp), charlen));
1758 /* Length assignment done, prevent adding it again below. */
1759 need_len_assign = false;
1761 gfc_conv_descriptor_offset_set (&se.pre, desc, offset);
1763 else if (sym->ts.type == BT_CLASS && e->ts.type == BT_CLASS
1764 && CLASS_DATA (e)->attr.dimension)
1766 /* This is bound to be a class array element. */
1767 gfc_conv_expr_reference (&se, e);
1768 /* Get the _vptr component of the class object. */
1769 tmp = gfc_get_vptr_from_expr (se.expr);
1770 /* Obtain a temporary class container for the result. */
1771 gfc_conv_derived_to_class (&se, e, sym->ts, tmp, false, false);
1772 se.expr = build_fold_indirect_ref_loc (input_location, se.expr);
1774 else
1776 /* For BT_CLASS and BT_DERIVED, this boils down to a pointer assign,
1777 which has the string length included. For CHARACTERS it is still
1778 needed and will be done at the end of this routine. */
1779 gfc_conv_expr (&se, e);
1780 need_len_assign = need_len_assign && sym->ts.type == BT_CHARACTER;
1783 if (sym->ts.type == BT_CHARACTER
1784 && sym->ts.deferred
1785 && !sym->attr.select_type_temporary
1786 && VAR_P (sym->ts.u.cl->backend_decl)
1787 && se.string_length != sym->ts.u.cl->backend_decl)
1789 gfc_add_modify (&se.pre, sym->ts.u.cl->backend_decl,
1790 fold_convert (TREE_TYPE (sym->ts.u.cl->backend_decl),
1791 se.string_length));
1792 if (e->expr_type == EXPR_FUNCTION)
1794 tmp = gfc_call_free (sym->backend_decl);
1795 gfc_add_expr_to_block (&se.post, tmp);
1799 attr = gfc_expr_attr (e);
1800 if (sym->ts.type == BT_CHARACTER && e->ts.type == BT_CHARACTER
1801 && (attr.allocatable || attr.pointer || attr.dummy))
1803 /* These are pointer types already. */
1804 tmp = fold_convert (TREE_TYPE (sym->backend_decl), se.expr);
1806 else
1808 tmp = TREE_TYPE (sym->backend_decl);
1809 tmp = gfc_build_addr_expr (tmp, se.expr);
1812 gfc_add_modify (&se.pre, sym->backend_decl, tmp);
1814 gfc_add_init_cleanup (block, gfc_finish_block( &se.pre),
1815 gfc_finish_block (&se.post));
1818 /* Do a simple assignment. This is for scalar expressions, where we
1819 can simply use expression assignment. */
1820 else
1822 gfc_expr *lhs;
1823 tree res;
1825 lhs = gfc_lval_expr_from_sym (sym);
1826 res = gfc_trans_assignment (lhs, e, false, true);
1828 tmp = sym->backend_decl;
1829 if (e->expr_type == EXPR_FUNCTION
1830 && sym->ts.type == BT_DERIVED
1831 && sym->ts.u.derived
1832 && sym->ts.u.derived->attr.pdt_type)
1834 tmp = gfc_deallocate_pdt_comp (sym->ts.u.derived, tmp,
1837 else if (e->expr_type == EXPR_FUNCTION
1838 && sym->ts.type == BT_CLASS
1839 && CLASS_DATA (sym)->ts.u.derived
1840 && CLASS_DATA (sym)->ts.u.derived->attr.pdt_type)
1842 tmp = gfc_class_data_get (tmp);
1843 tmp = gfc_deallocate_pdt_comp (CLASS_DATA (sym)->ts.u.derived,
1844 tmp, 0);
1847 gfc_add_init_cleanup (block, res, tmp);
1850 /* Set the stringlength, when needed. */
1851 if (need_len_assign)
1853 gfc_se se;
1854 gfc_init_se (&se, NULL);
1855 if (e->symtree->n.sym->ts.type == BT_CHARACTER)
1857 /* Deferred strings are dealt with in the preceeding. */
1858 gcc_assert (!e->symtree->n.sym->ts.deferred);
1859 tmp = e->symtree->n.sym->ts.u.cl->backend_decl;
1861 else if (e->symtree->n.sym->attr.function
1862 && e->symtree->n.sym == e->symtree->n.sym->result)
1864 tmp = gfc_get_fake_result_decl (e->symtree->n.sym, 0);
1865 tmp = gfc_class_len_get (tmp);
1867 else
1868 tmp = gfc_class_len_get (gfc_get_symbol_decl (e->symtree->n.sym));
1869 gfc_get_symbol_decl (sym);
1870 charlen = sym->ts.type == BT_CHARACTER ? sym->ts.u.cl->backend_decl
1871 : gfc_class_len_get (sym->backend_decl);
1872 /* Prevent adding a noop len= len. */
1873 if (tmp != charlen)
1875 gfc_add_modify (&se.pre, charlen,
1876 fold_convert (TREE_TYPE (charlen), tmp));
1877 gfc_add_init_cleanup (block, gfc_finish_block (&se.pre),
1878 gfc_finish_block (&se.post));
1884 /* Translate a BLOCK construct. This is basically what we would do for a
1885 procedure body. */
1887 tree
1888 gfc_trans_block_construct (gfc_code* code)
1890 gfc_namespace* ns;
1891 gfc_symbol* sym;
1892 gfc_wrapped_block block;
1893 tree exit_label;
1894 stmtblock_t body;
1895 gfc_association_list *ass;
1897 ns = code->ext.block.ns;
1898 gcc_assert (ns);
1899 sym = ns->proc_name;
1900 gcc_assert (sym);
1902 /* Process local variables. */
1903 gcc_assert (!sym->tlink);
1904 sym->tlink = sym;
1905 gfc_process_block_locals (ns);
1907 /* Generate code including exit-label. */
1908 gfc_init_block (&body);
1909 exit_label = gfc_build_label_decl (NULL_TREE);
1910 code->exit_label = exit_label;
1912 finish_oacc_declare (ns, sym, true);
1914 gfc_add_expr_to_block (&body, gfc_trans_code (ns->code));
1915 gfc_add_expr_to_block (&body, build1_v (LABEL_EXPR, exit_label));
1917 /* Finish everything. */
1918 gfc_start_wrapped_block (&block, gfc_finish_block (&body));
1919 gfc_trans_deferred_vars (sym, &block);
1920 for (ass = code->ext.block.assoc; ass; ass = ass->next)
1921 trans_associate_var (ass->st->n.sym, &block);
1923 return gfc_finish_wrapped_block (&block);
1926 /* Translate the simple DO construct in a C-style manner.
1927 This is where the loop variable has integer type and step +-1.
1928 Following code will generate infinite loop in case where TO is INT_MAX
1929 (for +1 step) or INT_MIN (for -1 step)
1931 We translate a do loop from:
1933 DO dovar = from, to, step
1934 body
1935 END DO
1939 [Evaluate loop bounds and step]
1940 dovar = from;
1941 for (;;)
1943 if (dovar > to)
1944 goto end_label;
1945 body;
1946 cycle_label:
1947 dovar += step;
1949 end_label:
1951 This helps the optimizers by avoiding the extra pre-header condition and
1952 we save a register as we just compare the updated IV (not a value in
1953 previous step). */
1955 static tree
1956 gfc_trans_simple_do (gfc_code * code, stmtblock_t *pblock, tree dovar,
1957 tree from, tree to, tree step, tree exit_cond)
1959 stmtblock_t body;
1960 tree type;
1961 tree cond;
1962 tree tmp;
1963 tree saved_dovar = NULL;
1964 tree cycle_label;
1965 tree exit_label;
1966 location_t loc;
1967 type = TREE_TYPE (dovar);
1968 bool is_step_positive = tree_int_cst_sgn (step) > 0;
1970 loc = code->ext.iterator->start->where.lb->location;
1972 /* Initialize the DO variable: dovar = from. */
1973 gfc_add_modify_loc (loc, pblock, dovar,
1974 fold_convert (TREE_TYPE (dovar), from));
1976 /* Save value for do-tinkering checking. */
1977 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
1979 saved_dovar = gfc_create_var (type, ".saved_dovar");
1980 gfc_add_modify_loc (loc, pblock, saved_dovar, dovar);
1983 /* Cycle and exit statements are implemented with gotos. */
1984 cycle_label = gfc_build_label_decl (NULL_TREE);
1985 exit_label = gfc_build_label_decl (NULL_TREE);
1987 /* Put the labels where they can be found later. See gfc_trans_do(). */
1988 code->cycle_label = cycle_label;
1989 code->exit_label = exit_label;
1991 /* Loop body. */
1992 gfc_start_block (&body);
1994 /* Exit the loop if there is an I/O result condition or error. */
1995 if (exit_cond)
1997 tmp = build1_v (GOTO_EXPR, exit_label);
1998 tmp = fold_build3_loc (loc, COND_EXPR, void_type_node,
1999 exit_cond, tmp,
2000 build_empty_stmt (loc));
2001 gfc_add_expr_to_block (&body, tmp);
2004 /* Evaluate the loop condition. */
2005 if (is_step_positive)
2006 cond = fold_build2_loc (loc, GT_EXPR, logical_type_node, dovar,
2007 fold_convert (type, to));
2008 else
2009 cond = fold_build2_loc (loc, LT_EXPR, logical_type_node, dovar,
2010 fold_convert (type, to));
2012 cond = gfc_evaluate_now_loc (loc, cond, &body);
2013 if (code->ext.iterator->unroll && cond != error_mark_node)
2014 cond
2015 = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
2016 build_int_cst (integer_type_node, annot_expr_unroll_kind),
2017 build_int_cst (integer_type_node, code->ext.iterator->unroll));
2019 /* The loop exit. */
2020 tmp = fold_build1_loc (loc, GOTO_EXPR, void_type_node, exit_label);
2021 TREE_USED (exit_label) = 1;
2022 tmp = fold_build3_loc (loc, COND_EXPR, void_type_node,
2023 cond, tmp, build_empty_stmt (loc));
2024 gfc_add_expr_to_block (&body, tmp);
2026 /* Check whether the induction variable is equal to INT_MAX
2027 (respectively to INT_MIN). */
2028 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
2030 tree boundary = is_step_positive ? TYPE_MAX_VALUE (type)
2031 : TYPE_MIN_VALUE (type);
2033 tmp = fold_build2_loc (loc, EQ_EXPR, logical_type_node,
2034 dovar, boundary);
2035 gfc_trans_runtime_check (true, false, tmp, &body, &code->loc,
2036 "Loop iterates infinitely");
2039 /* Main loop body. */
2040 tmp = gfc_trans_code_cond (code->block->next, exit_cond);
2041 gfc_add_expr_to_block (&body, tmp);
2043 /* Label for cycle statements (if needed). */
2044 if (TREE_USED (cycle_label))
2046 tmp = build1_v (LABEL_EXPR, cycle_label);
2047 gfc_add_expr_to_block (&body, tmp);
2050 /* Check whether someone has modified the loop variable. */
2051 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
2053 tmp = fold_build2_loc (loc, NE_EXPR, logical_type_node,
2054 dovar, saved_dovar);
2055 gfc_trans_runtime_check (true, false, tmp, &body, &code->loc,
2056 "Loop variable has been modified");
2059 /* Increment the loop variable. */
2060 tmp = fold_build2_loc (loc, PLUS_EXPR, type, dovar, step);
2061 gfc_add_modify_loc (loc, &body, dovar, tmp);
2063 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
2064 gfc_add_modify_loc (loc, &body, saved_dovar, dovar);
2066 /* Finish the loop body. */
2067 tmp = gfc_finish_block (&body);
2068 tmp = fold_build1_loc (loc, LOOP_EXPR, void_type_node, tmp);
2070 gfc_add_expr_to_block (pblock, tmp);
2072 /* Add the exit label. */
2073 tmp = build1_v (LABEL_EXPR, exit_label);
2074 gfc_add_expr_to_block (pblock, tmp);
2076 return gfc_finish_block (pblock);
2079 /* Translate the DO construct. This obviously is one of the most
2080 important ones to get right with any compiler, but especially
2081 so for Fortran.
2083 We special case some loop forms as described in gfc_trans_simple_do.
2084 For other cases we implement them with a separate loop count,
2085 as described in the standard.
2087 We translate a do loop from:
2089 DO dovar = from, to, step
2090 body
2091 END DO
2095 [evaluate loop bounds and step]
2096 empty = (step > 0 ? to < from : to > from);
2097 countm1 = (to - from) / step;
2098 dovar = from;
2099 if (empty) goto exit_label;
2100 for (;;)
2102 body;
2103 cycle_label:
2104 dovar += step
2105 countm1t = countm1;
2106 countm1--;
2107 if (countm1t == 0) goto exit_label;
2109 exit_label:
2111 countm1 is an unsigned integer. It is equal to the loop count minus one,
2112 because the loop count itself can overflow. */
2114 tree
2115 gfc_trans_do (gfc_code * code, tree exit_cond)
2117 gfc_se se;
2118 tree dovar;
2119 tree saved_dovar = NULL;
2120 tree from;
2121 tree to;
2122 tree step;
2123 tree countm1;
2124 tree type;
2125 tree utype;
2126 tree cond;
2127 tree cycle_label;
2128 tree exit_label;
2129 tree tmp;
2130 stmtblock_t block;
2131 stmtblock_t body;
2132 location_t loc;
2134 gfc_start_block (&block);
2136 loc = code->ext.iterator->start->where.lb->location;
2138 /* Evaluate all the expressions in the iterator. */
2139 gfc_init_se (&se, NULL);
2140 gfc_conv_expr_lhs (&se, code->ext.iterator->var);
2141 gfc_add_block_to_block (&block, &se.pre);
2142 dovar = se.expr;
2143 type = TREE_TYPE (dovar);
2145 gfc_init_se (&se, NULL);
2146 gfc_conv_expr_val (&se, code->ext.iterator->start);
2147 gfc_add_block_to_block (&block, &se.pre);
2148 from = gfc_evaluate_now (se.expr, &block);
2150 gfc_init_se (&se, NULL);
2151 gfc_conv_expr_val (&se, code->ext.iterator->end);
2152 gfc_add_block_to_block (&block, &se.pre);
2153 to = gfc_evaluate_now (se.expr, &block);
2155 gfc_init_se (&se, NULL);
2156 gfc_conv_expr_val (&se, code->ext.iterator->step);
2157 gfc_add_block_to_block (&block, &se.pre);
2158 step = gfc_evaluate_now (se.expr, &block);
2160 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
2162 tmp = fold_build2_loc (input_location, EQ_EXPR, logical_type_node, step,
2163 build_zero_cst (type));
2164 gfc_trans_runtime_check (true, false, tmp, &block, &code->loc,
2165 "DO step value is zero");
2168 /* Special case simple loops. */
2169 if (TREE_CODE (type) == INTEGER_TYPE
2170 && (integer_onep (step)
2171 || tree_int_cst_equal (step, integer_minus_one_node)))
2172 return gfc_trans_simple_do (code, &block, dovar, from, to, step,
2173 exit_cond);
2175 if (TREE_CODE (type) == INTEGER_TYPE)
2176 utype = unsigned_type_for (type);
2177 else
2178 utype = unsigned_type_for (gfc_array_index_type);
2179 countm1 = gfc_create_var (utype, "countm1");
2181 /* Cycle and exit statements are implemented with gotos. */
2182 cycle_label = gfc_build_label_decl (NULL_TREE);
2183 exit_label = gfc_build_label_decl (NULL_TREE);
2184 TREE_USED (exit_label) = 1;
2186 /* Put these labels where they can be found later. */
2187 code->cycle_label = cycle_label;
2188 code->exit_label = exit_label;
2190 /* Initialize the DO variable: dovar = from. */
2191 gfc_add_modify (&block, dovar, from);
2193 /* Save value for do-tinkering checking. */
2194 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
2196 saved_dovar = gfc_create_var (type, ".saved_dovar");
2197 gfc_add_modify_loc (loc, &block, saved_dovar, dovar);
2200 /* Initialize loop count and jump to exit label if the loop is empty.
2201 This code is executed before we enter the loop body. We generate:
2202 if (step > 0)
2204 countm1 = (to - from) / step;
2205 if (to < from)
2206 goto exit_label;
2208 else
2210 countm1 = (from - to) / -step;
2211 if (to > from)
2212 goto exit_label;
2216 if (TREE_CODE (type) == INTEGER_TYPE)
2218 tree pos, neg, tou, fromu, stepu, tmp2;
2220 /* The distance from FROM to TO cannot always be represented in a signed
2221 type, thus use unsigned arithmetic, also to avoid any undefined
2222 overflow issues. */
2223 tou = fold_convert (utype, to);
2224 fromu = fold_convert (utype, from);
2225 stepu = fold_convert (utype, step);
2227 /* For a positive step, when to < from, exit, otherwise compute
2228 countm1 = ((unsigned)to - (unsigned)from) / (unsigned)step */
2229 tmp = fold_build2_loc (loc, LT_EXPR, logical_type_node, to, from);
2230 tmp2 = fold_build2_loc (loc, TRUNC_DIV_EXPR, utype,
2231 fold_build2_loc (loc, MINUS_EXPR, utype,
2232 tou, fromu),
2233 stepu);
2234 pos = build2 (COMPOUND_EXPR, void_type_node,
2235 fold_build2 (MODIFY_EXPR, void_type_node,
2236 countm1, tmp2),
2237 build3_loc (loc, COND_EXPR, void_type_node,
2238 gfc_unlikely (tmp, PRED_FORTRAN_LOOP_PREHEADER),
2239 build1_loc (loc, GOTO_EXPR, void_type_node,
2240 exit_label), NULL_TREE));
2242 /* For a negative step, when to > from, exit, otherwise compute
2243 countm1 = ((unsigned)from - (unsigned)to) / -(unsigned)step */
2244 tmp = fold_build2_loc (loc, GT_EXPR, logical_type_node, to, from);
2245 tmp2 = fold_build2_loc (loc, TRUNC_DIV_EXPR, utype,
2246 fold_build2_loc (loc, MINUS_EXPR, utype,
2247 fromu, tou),
2248 fold_build1_loc (loc, NEGATE_EXPR, utype, stepu));
2249 neg = build2 (COMPOUND_EXPR, void_type_node,
2250 fold_build2 (MODIFY_EXPR, void_type_node,
2251 countm1, tmp2),
2252 build3_loc (loc, COND_EXPR, void_type_node,
2253 gfc_unlikely (tmp, PRED_FORTRAN_LOOP_PREHEADER),
2254 build1_loc (loc, GOTO_EXPR, void_type_node,
2255 exit_label), NULL_TREE));
2257 tmp = fold_build2_loc (loc, LT_EXPR, logical_type_node, step,
2258 build_int_cst (TREE_TYPE (step), 0));
2259 tmp = fold_build3_loc (loc, COND_EXPR, void_type_node, tmp, neg, pos);
2261 gfc_add_expr_to_block (&block, tmp);
2263 else
2265 tree pos_step;
2267 /* TODO: We could use the same width as the real type.
2268 This would probably cause more problems that it solves
2269 when we implement "long double" types. */
2271 tmp = fold_build2_loc (loc, MINUS_EXPR, type, to, from);
2272 tmp = fold_build2_loc (loc, RDIV_EXPR, type, tmp, step);
2273 tmp = fold_build1_loc (loc, FIX_TRUNC_EXPR, utype, tmp);
2274 gfc_add_modify (&block, countm1, tmp);
2276 /* We need a special check for empty loops:
2277 empty = (step > 0 ? to < from : to > from); */
2278 pos_step = fold_build2_loc (loc, GT_EXPR, logical_type_node, step,
2279 build_zero_cst (type));
2280 tmp = fold_build3_loc (loc, COND_EXPR, logical_type_node, pos_step,
2281 fold_build2_loc (loc, LT_EXPR,
2282 logical_type_node, to, from),
2283 fold_build2_loc (loc, GT_EXPR,
2284 logical_type_node, to, from));
2285 /* If the loop is empty, go directly to the exit label. */
2286 tmp = fold_build3_loc (loc, COND_EXPR, void_type_node, tmp,
2287 build1_v (GOTO_EXPR, exit_label),
2288 build_empty_stmt (input_location));
2289 gfc_add_expr_to_block (&block, tmp);
2292 /* Loop body. */
2293 gfc_start_block (&body);
2295 /* Main loop body. */
2296 tmp = gfc_trans_code_cond (code->block->next, exit_cond);
2297 gfc_add_expr_to_block (&body, tmp);
2299 /* Label for cycle statements (if needed). */
2300 if (TREE_USED (cycle_label))
2302 tmp = build1_v (LABEL_EXPR, cycle_label);
2303 gfc_add_expr_to_block (&body, tmp);
2306 /* Check whether someone has modified the loop variable. */
2307 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
2309 tmp = fold_build2_loc (loc, NE_EXPR, logical_type_node, dovar,
2310 saved_dovar);
2311 gfc_trans_runtime_check (true, false, tmp, &body, &code->loc,
2312 "Loop variable has been modified");
2315 /* Exit the loop if there is an I/O result condition or error. */
2316 if (exit_cond)
2318 tmp = build1_v (GOTO_EXPR, exit_label);
2319 tmp = fold_build3_loc (loc, COND_EXPR, void_type_node,
2320 exit_cond, tmp,
2321 build_empty_stmt (input_location));
2322 gfc_add_expr_to_block (&body, tmp);
2325 /* Increment the loop variable. */
2326 tmp = fold_build2_loc (loc, PLUS_EXPR, type, dovar, step);
2327 gfc_add_modify_loc (loc, &body, dovar, tmp);
2329 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
2330 gfc_add_modify_loc (loc, &body, saved_dovar, dovar);
2332 /* Initialize countm1t. */
2333 tree countm1t = gfc_create_var (utype, "countm1t");
2334 gfc_add_modify_loc (loc, &body, countm1t, countm1);
2336 /* Decrement the loop count. */
2337 tmp = fold_build2_loc (loc, MINUS_EXPR, utype, countm1,
2338 build_int_cst (utype, 1));
2339 gfc_add_modify_loc (loc, &body, countm1, tmp);
2341 /* End with the loop condition. Loop until countm1t == 0. */
2342 cond = fold_build2_loc (loc, EQ_EXPR, logical_type_node, countm1t,
2343 build_int_cst (utype, 0));
2344 if (code->ext.iterator->unroll && cond != error_mark_node)
2345 cond
2346 = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
2347 build_int_cst (integer_type_node, annot_expr_unroll_kind),
2348 build_int_cst (integer_type_node, code->ext.iterator->unroll));
2349 tmp = fold_build1_loc (loc, GOTO_EXPR, void_type_node, exit_label);
2350 tmp = fold_build3_loc (loc, COND_EXPR, void_type_node,
2351 cond, tmp, build_empty_stmt (loc));
2352 gfc_add_expr_to_block (&body, tmp);
2354 /* End of loop body. */
2355 tmp = gfc_finish_block (&body);
2357 /* The for loop itself. */
2358 tmp = fold_build1_loc (loc, LOOP_EXPR, void_type_node, tmp);
2359 gfc_add_expr_to_block (&block, tmp);
2361 /* Add the exit label. */
2362 tmp = build1_v (LABEL_EXPR, exit_label);
2363 gfc_add_expr_to_block (&block, tmp);
2365 return gfc_finish_block (&block);
2369 /* Translate the DO WHILE construct.
2371 We translate
2373 DO WHILE (cond)
2374 body
2375 END DO
2379 for ( ; ; )
2381 pre_cond;
2382 if (! cond) goto exit_label;
2383 body;
2384 cycle_label:
2386 exit_label:
2388 Because the evaluation of the exit condition `cond' may have side
2389 effects, we can't do much for empty loop bodies. The backend optimizers
2390 should be smart enough to eliminate any dead loops. */
2392 tree
2393 gfc_trans_do_while (gfc_code * code)
2395 gfc_se cond;
2396 tree tmp;
2397 tree cycle_label;
2398 tree exit_label;
2399 stmtblock_t block;
2401 /* Everything we build here is part of the loop body. */
2402 gfc_start_block (&block);
2404 /* Cycle and exit statements are implemented with gotos. */
2405 cycle_label = gfc_build_label_decl (NULL_TREE);
2406 exit_label = gfc_build_label_decl (NULL_TREE);
2408 /* Put the labels where they can be found later. See gfc_trans_do(). */
2409 code->cycle_label = cycle_label;
2410 code->exit_label = exit_label;
2412 /* Create a GIMPLE version of the exit condition. */
2413 gfc_init_se (&cond, NULL);
2414 gfc_conv_expr_val (&cond, code->expr1);
2415 gfc_add_block_to_block (&block, &cond.pre);
2416 cond.expr = fold_build1_loc (code->expr1->where.lb->location,
2417 TRUTH_NOT_EXPR, TREE_TYPE (cond.expr), cond.expr);
2419 /* Build "IF (! cond) GOTO exit_label". */
2420 tmp = build1_v (GOTO_EXPR, exit_label);
2421 TREE_USED (exit_label) = 1;
2422 tmp = fold_build3_loc (code->expr1->where.lb->location, COND_EXPR,
2423 void_type_node, cond.expr, tmp,
2424 build_empty_stmt (code->expr1->where.lb->location));
2425 gfc_add_expr_to_block (&block, tmp);
2427 /* The main body of the loop. */
2428 tmp = gfc_trans_code (code->block->next);
2429 gfc_add_expr_to_block (&block, tmp);
2431 /* Label for cycle statements (if needed). */
2432 if (TREE_USED (cycle_label))
2434 tmp = build1_v (LABEL_EXPR, cycle_label);
2435 gfc_add_expr_to_block (&block, tmp);
2438 /* End of loop body. */
2439 tmp = gfc_finish_block (&block);
2441 gfc_init_block (&block);
2442 /* Build the loop. */
2443 tmp = fold_build1_loc (code->expr1->where.lb->location, LOOP_EXPR,
2444 void_type_node, tmp);
2445 gfc_add_expr_to_block (&block, tmp);
2447 /* Add the exit label. */
2448 tmp = build1_v (LABEL_EXPR, exit_label);
2449 gfc_add_expr_to_block (&block, tmp);
2451 return gfc_finish_block (&block);
2455 /* Deal with the particular case of SELECT_TYPE, where the vtable
2456 addresses are used for the selection. Since these are not sorted,
2457 the selection has to be made by a series of if statements. */
2459 static tree
2460 gfc_trans_select_type_cases (gfc_code * code)
2462 gfc_code *c;
2463 gfc_case *cp;
2464 tree tmp;
2465 tree cond;
2466 tree low;
2467 tree high;
2468 gfc_se se;
2469 gfc_se cse;
2470 stmtblock_t block;
2471 stmtblock_t body;
2472 bool def = false;
2473 gfc_expr *e;
2474 gfc_start_block (&block);
2476 /* Calculate the switch expression. */
2477 gfc_init_se (&se, NULL);
2478 gfc_conv_expr_val (&se, code->expr1);
2479 gfc_add_block_to_block (&block, &se.pre);
2481 /* Generate an expression for the selector hash value, for
2482 use to resolve character cases. */
2483 e = gfc_copy_expr (code->expr1->value.function.actual->expr);
2484 gfc_add_hash_component (e);
2486 TREE_USED (code->exit_label) = 0;
2488 repeat:
2489 for (c = code->block; c; c = c->block)
2491 cp = c->ext.block.case_list;
2493 /* Assume it's the default case. */
2494 low = NULL_TREE;
2495 high = NULL_TREE;
2496 tmp = NULL_TREE;
2498 /* Put the default case at the end. */
2499 if ((!def && !cp->low) || (def && cp->low))
2500 continue;
2502 if (cp->low && (cp->ts.type == BT_CLASS
2503 || cp->ts.type == BT_DERIVED))
2505 gfc_init_se (&cse, NULL);
2506 gfc_conv_expr_val (&cse, cp->low);
2507 gfc_add_block_to_block (&block, &cse.pre);
2508 low = cse.expr;
2510 else if (cp->ts.type != BT_UNKNOWN)
2512 gcc_assert (cp->high);
2513 gfc_init_se (&cse, NULL);
2514 gfc_conv_expr_val (&cse, cp->high);
2515 gfc_add_block_to_block (&block, &cse.pre);
2516 high = cse.expr;
2519 gfc_init_block (&body);
2521 /* Add the statements for this case. */
2522 tmp = gfc_trans_code (c->next);
2523 gfc_add_expr_to_block (&body, tmp);
2525 /* Break to the end of the SELECT TYPE construct. The default
2526 case just falls through. */
2527 if (!def)
2529 TREE_USED (code->exit_label) = 1;
2530 tmp = build1_v (GOTO_EXPR, code->exit_label);
2531 gfc_add_expr_to_block (&body, tmp);
2534 tmp = gfc_finish_block (&body);
2536 if (low != NULL_TREE)
2538 /* Compare vtable pointers. */
2539 cond = fold_build2_loc (input_location, EQ_EXPR,
2540 TREE_TYPE (se.expr), se.expr, low);
2541 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
2542 cond, tmp,
2543 build_empty_stmt (input_location));
2545 else if (high != NULL_TREE)
2547 /* Compare hash values for character cases. */
2548 gfc_init_se (&cse, NULL);
2549 gfc_conv_expr_val (&cse, e);
2550 gfc_add_block_to_block (&block, &cse.pre);
2552 cond = fold_build2_loc (input_location, EQ_EXPR,
2553 TREE_TYPE (se.expr), high, cse.expr);
2554 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
2555 cond, tmp,
2556 build_empty_stmt (input_location));
2559 gfc_add_expr_to_block (&block, tmp);
2562 if (!def)
2564 def = true;
2565 goto repeat;
2568 gfc_free_expr (e);
2570 return gfc_finish_block (&block);
2574 /* Translate the SELECT CASE construct for INTEGER case expressions,
2575 without killing all potential optimizations. The problem is that
2576 Fortran allows unbounded cases, but the back-end does not, so we
2577 need to intercept those before we enter the equivalent SWITCH_EXPR
2578 we can build.
2580 For example, we translate this,
2582 SELECT CASE (expr)
2583 CASE (:100,101,105:115)
2584 block_1
2585 CASE (190:199,200:)
2586 block_2
2587 CASE (300)
2588 block_3
2589 CASE DEFAULT
2590 block_4
2591 END SELECT
2593 to the GENERIC equivalent,
2595 switch (expr)
2597 case (minimum value for typeof(expr) ... 100:
2598 case 101:
2599 case 105 ... 114:
2600 block1:
2601 goto end_label;
2603 case 200 ... (maximum value for typeof(expr):
2604 case 190 ... 199:
2605 block2;
2606 goto end_label;
2608 case 300:
2609 block_3;
2610 goto end_label;
2612 default:
2613 block_4;
2614 goto end_label;
2617 end_label: */
2619 static tree
2620 gfc_trans_integer_select (gfc_code * code)
2622 gfc_code *c;
2623 gfc_case *cp;
2624 tree end_label;
2625 tree tmp;
2626 gfc_se se;
2627 stmtblock_t block;
2628 stmtblock_t body;
2630 gfc_start_block (&block);
2632 /* Calculate the switch expression. */
2633 gfc_init_se (&se, NULL);
2634 gfc_conv_expr_val (&se, code->expr1);
2635 gfc_add_block_to_block (&block, &se.pre);
2637 end_label = gfc_build_label_decl (NULL_TREE);
2639 gfc_init_block (&body);
2641 for (c = code->block; c; c = c->block)
2643 for (cp = c->ext.block.case_list; cp; cp = cp->next)
2645 tree low, high;
2646 tree label;
2648 /* Assume it's the default case. */
2649 low = high = NULL_TREE;
2651 if (cp->low)
2653 low = gfc_conv_mpz_to_tree (cp->low->value.integer,
2654 cp->low->ts.kind);
2656 /* If there's only a lower bound, set the high bound to the
2657 maximum value of the case expression. */
2658 if (!cp->high)
2659 high = TYPE_MAX_VALUE (TREE_TYPE (se.expr));
2662 if (cp->high)
2664 /* Three cases are possible here:
2666 1) There is no lower bound, e.g. CASE (:N).
2667 2) There is a lower bound .NE. high bound, that is
2668 a case range, e.g. CASE (N:M) where M>N (we make
2669 sure that M>N during type resolution).
2670 3) There is a lower bound, and it has the same value
2671 as the high bound, e.g. CASE (N:N). This is our
2672 internal representation of CASE(N).
2674 In the first and second case, we need to set a value for
2675 high. In the third case, we don't because the GCC middle
2676 end represents a single case value by just letting high be
2677 a NULL_TREE. We can't do that because we need to be able
2678 to represent unbounded cases. */
2680 if (!cp->low
2681 || (mpz_cmp (cp->low->value.integer,
2682 cp->high->value.integer) != 0))
2683 high = gfc_conv_mpz_to_tree (cp->high->value.integer,
2684 cp->high->ts.kind);
2686 /* Unbounded case. */
2687 if (!cp->low)
2688 low = TYPE_MIN_VALUE (TREE_TYPE (se.expr));
2691 /* Build a label. */
2692 label = gfc_build_label_decl (NULL_TREE);
2694 /* Add this case label.
2695 Add parameter 'label', make it match GCC backend. */
2696 tmp = build_case_label (low, high, label);
2697 gfc_add_expr_to_block (&body, tmp);
2700 /* Add the statements for this case. */
2701 tmp = gfc_trans_code (c->next);
2702 gfc_add_expr_to_block (&body, tmp);
2704 /* Break to the end of the construct. */
2705 tmp = build1_v (GOTO_EXPR, end_label);
2706 gfc_add_expr_to_block (&body, tmp);
2709 tmp = gfc_finish_block (&body);
2710 tmp = fold_build2_loc (input_location, SWITCH_EXPR, NULL_TREE, se.expr, tmp);
2711 gfc_add_expr_to_block (&block, tmp);
2713 tmp = build1_v (LABEL_EXPR, end_label);
2714 gfc_add_expr_to_block (&block, tmp);
2716 return gfc_finish_block (&block);
2720 /* Translate the SELECT CASE construct for LOGICAL case expressions.
2722 There are only two cases possible here, even though the standard
2723 does allow three cases in a LOGICAL SELECT CASE construct: .TRUE.,
2724 .FALSE., and DEFAULT.
2726 We never generate more than two blocks here. Instead, we always
2727 try to eliminate the DEFAULT case. This way, we can translate this
2728 kind of SELECT construct to a simple
2730 if {} else {};
2732 expression in GENERIC. */
2734 static tree
2735 gfc_trans_logical_select (gfc_code * code)
2737 gfc_code *c;
2738 gfc_code *t, *f, *d;
2739 gfc_case *cp;
2740 gfc_se se;
2741 stmtblock_t block;
2743 /* Assume we don't have any cases at all. */
2744 t = f = d = NULL;
2746 /* Now see which ones we actually do have. We can have at most two
2747 cases in a single case list: one for .TRUE. and one for .FALSE.
2748 The default case is always separate. If the cases for .TRUE. and
2749 .FALSE. are in the same case list, the block for that case list
2750 always executed, and we don't generate code a COND_EXPR. */
2751 for (c = code->block; c; c = c->block)
2753 for (cp = c->ext.block.case_list; cp; cp = cp->next)
2755 if (cp->low)
2757 if (cp->low->value.logical == 0) /* .FALSE. */
2758 f = c;
2759 else /* if (cp->value.logical != 0), thus .TRUE. */
2760 t = c;
2762 else
2763 d = c;
2767 /* Start a new block. */
2768 gfc_start_block (&block);
2770 /* Calculate the switch expression. We always need to do this
2771 because it may have side effects. */
2772 gfc_init_se (&se, NULL);
2773 gfc_conv_expr_val (&se, code->expr1);
2774 gfc_add_block_to_block (&block, &se.pre);
2776 if (t == f && t != NULL)
2778 /* Cases for .TRUE. and .FALSE. are in the same block. Just
2779 translate the code for these cases, append it to the current
2780 block. */
2781 gfc_add_expr_to_block (&block, gfc_trans_code (t->next));
2783 else
2785 tree true_tree, false_tree, stmt;
2787 true_tree = build_empty_stmt (input_location);
2788 false_tree = build_empty_stmt (input_location);
2790 /* If we have a case for .TRUE. and for .FALSE., discard the default case.
2791 Otherwise, if .TRUE. or .FALSE. is missing and there is a default case,
2792 make the missing case the default case. */
2793 if (t != NULL && f != NULL)
2794 d = NULL;
2795 else if (d != NULL)
2797 if (t == NULL)
2798 t = d;
2799 else
2800 f = d;
2803 /* Translate the code for each of these blocks, and append it to
2804 the current block. */
2805 if (t != NULL)
2806 true_tree = gfc_trans_code (t->next);
2808 if (f != NULL)
2809 false_tree = gfc_trans_code (f->next);
2811 stmt = fold_build3_loc (input_location, COND_EXPR, void_type_node,
2812 se.expr, true_tree, false_tree);
2813 gfc_add_expr_to_block (&block, stmt);
2816 return gfc_finish_block (&block);
2820 /* The jump table types are stored in static variables to avoid
2821 constructing them from scratch every single time. */
2822 static GTY(()) tree select_struct[2];
2824 /* Translate the SELECT CASE construct for CHARACTER case expressions.
2825 Instead of generating compares and jumps, it is far simpler to
2826 generate a data structure describing the cases in order and call a
2827 library subroutine that locates the right case.
2828 This is particularly true because this is the only case where we
2829 might have to dispose of a temporary.
2830 The library subroutine returns a pointer to jump to or NULL if no
2831 branches are to be taken. */
2833 static tree
2834 gfc_trans_character_select (gfc_code *code)
2836 tree init, end_label, tmp, type, case_num, label, fndecl;
2837 stmtblock_t block, body;
2838 gfc_case *cp, *d;
2839 gfc_code *c;
2840 gfc_se se, expr1se;
2841 int n, k;
2842 vec<constructor_elt, va_gc> *inits = NULL;
2844 tree pchartype = gfc_get_pchar_type (code->expr1->ts.kind);
2846 /* The jump table types are stored in static variables to avoid
2847 constructing them from scratch every single time. */
2848 static tree ss_string1[2], ss_string1_len[2];
2849 static tree ss_string2[2], ss_string2_len[2];
2850 static tree ss_target[2];
2852 cp = code->block->ext.block.case_list;
2853 while (cp->left != NULL)
2854 cp = cp->left;
2856 /* Generate the body */
2857 gfc_start_block (&block);
2858 gfc_init_se (&expr1se, NULL);
2859 gfc_conv_expr_reference (&expr1se, code->expr1);
2861 gfc_add_block_to_block (&block, &expr1se.pre);
2863 end_label = gfc_build_label_decl (NULL_TREE);
2865 gfc_init_block (&body);
2867 /* Attempt to optimize length 1 selects. */
2868 if (integer_onep (expr1se.string_length))
2870 for (d = cp; d; d = d->right)
2872 gfc_charlen_t i;
2873 if (d->low)
2875 gcc_assert (d->low->expr_type == EXPR_CONSTANT
2876 && d->low->ts.type == BT_CHARACTER);
2877 if (d->low->value.character.length > 1)
2879 for (i = 1; i < d->low->value.character.length; i++)
2880 if (d->low->value.character.string[i] != ' ')
2881 break;
2882 if (i != d->low->value.character.length)
2884 if (optimize && d->high && i == 1)
2886 gcc_assert (d->high->expr_type == EXPR_CONSTANT
2887 && d->high->ts.type == BT_CHARACTER);
2888 if (d->high->value.character.length > 1
2889 && (d->low->value.character.string[0]
2890 == d->high->value.character.string[0])
2891 && d->high->value.character.string[1] != ' '
2892 && ((d->low->value.character.string[1] < ' ')
2893 == (d->high->value.character.string[1]
2894 < ' ')))
2895 continue;
2897 break;
2901 if (d->high)
2903 gcc_assert (d->high->expr_type == EXPR_CONSTANT
2904 && d->high->ts.type == BT_CHARACTER);
2905 if (d->high->value.character.length > 1)
2907 for (i = 1; i < d->high->value.character.length; i++)
2908 if (d->high->value.character.string[i] != ' ')
2909 break;
2910 if (i != d->high->value.character.length)
2911 break;
2915 if (d == NULL)
2917 tree ctype = gfc_get_char_type (code->expr1->ts.kind);
2919 for (c = code->block; c; c = c->block)
2921 for (cp = c->ext.block.case_list; cp; cp = cp->next)
2923 tree low, high;
2924 tree label;
2925 gfc_char_t r;
2927 /* Assume it's the default case. */
2928 low = high = NULL_TREE;
2930 if (cp->low)
2932 /* CASE ('ab') or CASE ('ab':'az') will never match
2933 any length 1 character. */
2934 if (cp->low->value.character.length > 1
2935 && cp->low->value.character.string[1] != ' ')
2936 continue;
2938 if (cp->low->value.character.length > 0)
2939 r = cp->low->value.character.string[0];
2940 else
2941 r = ' ';
2942 low = build_int_cst (ctype, r);
2944 /* If there's only a lower bound, set the high bound
2945 to the maximum value of the case expression. */
2946 if (!cp->high)
2947 high = TYPE_MAX_VALUE (ctype);
2950 if (cp->high)
2952 if (!cp->low
2953 || (cp->low->value.character.string[0]
2954 != cp->high->value.character.string[0]))
2956 if (cp->high->value.character.length > 0)
2957 r = cp->high->value.character.string[0];
2958 else
2959 r = ' ';
2960 high = build_int_cst (ctype, r);
2963 /* Unbounded case. */
2964 if (!cp->low)
2965 low = TYPE_MIN_VALUE (ctype);
2968 /* Build a label. */
2969 label = gfc_build_label_decl (NULL_TREE);
2971 /* Add this case label.
2972 Add parameter 'label', make it match GCC backend. */
2973 tmp = build_case_label (low, high, label);
2974 gfc_add_expr_to_block (&body, tmp);
2977 /* Add the statements for this case. */
2978 tmp = gfc_trans_code (c->next);
2979 gfc_add_expr_to_block (&body, tmp);
2981 /* Break to the end of the construct. */
2982 tmp = build1_v (GOTO_EXPR, end_label);
2983 gfc_add_expr_to_block (&body, tmp);
2986 tmp = gfc_string_to_single_character (expr1se.string_length,
2987 expr1se.expr,
2988 code->expr1->ts.kind);
2989 case_num = gfc_create_var (ctype, "case_num");
2990 gfc_add_modify (&block, case_num, tmp);
2992 gfc_add_block_to_block (&block, &expr1se.post);
2994 tmp = gfc_finish_block (&body);
2995 tmp = fold_build2_loc (input_location, SWITCH_EXPR, NULL_TREE,
2996 case_num, tmp);
2997 gfc_add_expr_to_block (&block, tmp);
2999 tmp = build1_v (LABEL_EXPR, end_label);
3000 gfc_add_expr_to_block (&block, tmp);
3002 return gfc_finish_block (&block);
3006 if (code->expr1->ts.kind == 1)
3007 k = 0;
3008 else if (code->expr1->ts.kind == 4)
3009 k = 1;
3010 else
3011 gcc_unreachable ();
3013 if (select_struct[k] == NULL)
3015 tree *chain = NULL;
3016 select_struct[k] = make_node (RECORD_TYPE);
3018 if (code->expr1->ts.kind == 1)
3019 TYPE_NAME (select_struct[k]) = get_identifier ("_jump_struct_char1");
3020 else if (code->expr1->ts.kind == 4)
3021 TYPE_NAME (select_struct[k]) = get_identifier ("_jump_struct_char4");
3022 else
3023 gcc_unreachable ();
3025 #undef ADD_FIELD
3026 #define ADD_FIELD(NAME, TYPE) \
3027 ss_##NAME[k] = gfc_add_field_to_struct (select_struct[k], \
3028 get_identifier (stringize(NAME)), \
3029 TYPE, \
3030 &chain)
3032 ADD_FIELD (string1, pchartype);
3033 ADD_FIELD (string1_len, gfc_charlen_type_node);
3035 ADD_FIELD (string2, pchartype);
3036 ADD_FIELD (string2_len, gfc_charlen_type_node);
3038 ADD_FIELD (target, integer_type_node);
3039 #undef ADD_FIELD
3041 gfc_finish_type (select_struct[k]);
3044 n = 0;
3045 for (d = cp; d; d = d->right)
3046 d->n = n++;
3048 for (c = code->block; c; c = c->block)
3050 for (d = c->ext.block.case_list; d; d = d->next)
3052 label = gfc_build_label_decl (NULL_TREE);
3053 tmp = build_case_label ((d->low == NULL && d->high == NULL)
3054 ? NULL
3055 : build_int_cst (integer_type_node, d->n),
3056 NULL, label);
3057 gfc_add_expr_to_block (&body, tmp);
3060 tmp = gfc_trans_code (c->next);
3061 gfc_add_expr_to_block (&body, tmp);
3063 tmp = build1_v (GOTO_EXPR, end_label);
3064 gfc_add_expr_to_block (&body, tmp);
3067 /* Generate the structure describing the branches */
3068 for (d = cp; d; d = d->right)
3070 vec<constructor_elt, va_gc> *node = NULL;
3072 gfc_init_se (&se, NULL);
3074 if (d->low == NULL)
3076 CONSTRUCTOR_APPEND_ELT (node, ss_string1[k], null_pointer_node);
3077 CONSTRUCTOR_APPEND_ELT (node, ss_string1_len[k], build_zero_cst (gfc_charlen_type_node));
3079 else
3081 gfc_conv_expr_reference (&se, d->low);
3083 CONSTRUCTOR_APPEND_ELT (node, ss_string1[k], se.expr);
3084 CONSTRUCTOR_APPEND_ELT (node, ss_string1_len[k], se.string_length);
3087 if (d->high == NULL)
3089 CONSTRUCTOR_APPEND_ELT (node, ss_string2[k], null_pointer_node);
3090 CONSTRUCTOR_APPEND_ELT (node, ss_string2_len[k], build_zero_cst (gfc_charlen_type_node));
3092 else
3094 gfc_init_se (&se, NULL);
3095 gfc_conv_expr_reference (&se, d->high);
3097 CONSTRUCTOR_APPEND_ELT (node, ss_string2[k], se.expr);
3098 CONSTRUCTOR_APPEND_ELT (node, ss_string2_len[k], se.string_length);
3101 CONSTRUCTOR_APPEND_ELT (node, ss_target[k],
3102 build_int_cst (integer_type_node, d->n));
3104 tmp = build_constructor (select_struct[k], node);
3105 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, tmp);
3108 type = build_array_type (select_struct[k],
3109 build_index_type (size_int (n-1)));
3111 init = build_constructor (type, inits);
3112 TREE_CONSTANT (init) = 1;
3113 TREE_STATIC (init) = 1;
3114 /* Create a static variable to hold the jump table. */
3115 tmp = gfc_create_var (type, "jumptable");
3116 TREE_CONSTANT (tmp) = 1;
3117 TREE_STATIC (tmp) = 1;
3118 TREE_READONLY (tmp) = 1;
3119 DECL_INITIAL (tmp) = init;
3120 init = tmp;
3122 /* Build the library call */
3123 init = gfc_build_addr_expr (pvoid_type_node, init);
3125 if (code->expr1->ts.kind == 1)
3126 fndecl = gfor_fndecl_select_string;
3127 else if (code->expr1->ts.kind == 4)
3128 fndecl = gfor_fndecl_select_string_char4;
3129 else
3130 gcc_unreachable ();
3132 tmp = build_call_expr_loc (input_location,
3133 fndecl, 4, init,
3134 build_int_cst (gfc_charlen_type_node, n),
3135 expr1se.expr, expr1se.string_length);
3136 case_num = gfc_create_var (integer_type_node, "case_num");
3137 gfc_add_modify (&block, case_num, tmp);
3139 gfc_add_block_to_block (&block, &expr1se.post);
3141 tmp = gfc_finish_block (&body);
3142 tmp = fold_build2_loc (input_location, SWITCH_EXPR, NULL_TREE,
3143 case_num, tmp);
3144 gfc_add_expr_to_block (&block, tmp);
3146 tmp = build1_v (LABEL_EXPR, end_label);
3147 gfc_add_expr_to_block (&block, tmp);
3149 return gfc_finish_block (&block);
3153 /* Translate the three variants of the SELECT CASE construct.
3155 SELECT CASEs with INTEGER case expressions can be translated to an
3156 equivalent GENERIC switch statement, and for LOGICAL case
3157 expressions we build one or two if-else compares.
3159 SELECT CASEs with CHARACTER case expressions are a whole different
3160 story, because they don't exist in GENERIC. So we sort them and
3161 do a binary search at runtime.
3163 Fortran has no BREAK statement, and it does not allow jumps from
3164 one case block to another. That makes things a lot easier for
3165 the optimizers. */
3167 tree
3168 gfc_trans_select (gfc_code * code)
3170 stmtblock_t block;
3171 tree body;
3172 tree exit_label;
3174 gcc_assert (code && code->expr1);
3175 gfc_init_block (&block);
3177 /* Build the exit label and hang it in. */
3178 exit_label = gfc_build_label_decl (NULL_TREE);
3179 code->exit_label = exit_label;
3181 /* Empty SELECT constructs are legal. */
3182 if (code->block == NULL)
3183 body = build_empty_stmt (input_location);
3185 /* Select the correct translation function. */
3186 else
3187 switch (code->expr1->ts.type)
3189 case BT_LOGICAL:
3190 body = gfc_trans_logical_select (code);
3191 break;
3193 case BT_INTEGER:
3194 body = gfc_trans_integer_select (code);
3195 break;
3197 case BT_CHARACTER:
3198 body = gfc_trans_character_select (code);
3199 break;
3201 default:
3202 gfc_internal_error ("gfc_trans_select(): Bad type for case expr.");
3203 /* Not reached */
3206 /* Build everything together. */
3207 gfc_add_expr_to_block (&block, body);
3208 gfc_add_expr_to_block (&block, build1_v (LABEL_EXPR, exit_label));
3210 return gfc_finish_block (&block);
3213 tree
3214 gfc_trans_select_type (gfc_code * code)
3216 stmtblock_t block;
3217 tree body;
3218 tree exit_label;
3220 gcc_assert (code && code->expr1);
3221 gfc_init_block (&block);
3223 /* Build the exit label and hang it in. */
3224 exit_label = gfc_build_label_decl (NULL_TREE);
3225 code->exit_label = exit_label;
3227 /* Empty SELECT constructs are legal. */
3228 if (code->block == NULL)
3229 body = build_empty_stmt (input_location);
3230 else
3231 body = gfc_trans_select_type_cases (code);
3233 /* Build everything together. */
3234 gfc_add_expr_to_block (&block, body);
3236 if (TREE_USED (exit_label))
3237 gfc_add_expr_to_block (&block, build1_v (LABEL_EXPR, exit_label));
3239 return gfc_finish_block (&block);
3243 /* Traversal function to substitute a replacement symtree if the symbol
3244 in the expression is the same as that passed. f == 2 signals that
3245 that variable itself is not to be checked - only the references.
3246 This group of functions is used when the variable expression in a
3247 FORALL assignment has internal references. For example:
3248 FORALL (i = 1:4) p(p(i)) = i
3249 The only recourse here is to store a copy of 'p' for the index
3250 expression. */
3252 static gfc_symtree *new_symtree;
3253 static gfc_symtree *old_symtree;
3255 static bool
3256 forall_replace (gfc_expr *expr, gfc_symbol *sym, int *f)
3258 if (expr->expr_type != EXPR_VARIABLE)
3259 return false;
3261 if (*f == 2)
3262 *f = 1;
3263 else if (expr->symtree->n.sym == sym)
3264 expr->symtree = new_symtree;
3266 return false;
3269 static void
3270 forall_replace_symtree (gfc_expr *e, gfc_symbol *sym, int f)
3272 gfc_traverse_expr (e, sym, forall_replace, f);
3275 static bool
3276 forall_restore (gfc_expr *expr,
3277 gfc_symbol *sym ATTRIBUTE_UNUSED,
3278 int *f ATTRIBUTE_UNUSED)
3280 if (expr->expr_type != EXPR_VARIABLE)
3281 return false;
3283 if (expr->symtree == new_symtree)
3284 expr->symtree = old_symtree;
3286 return false;
3289 static void
3290 forall_restore_symtree (gfc_expr *e)
3292 gfc_traverse_expr (e, NULL, forall_restore, 0);
3295 static void
3296 forall_make_variable_temp (gfc_code *c, stmtblock_t *pre, stmtblock_t *post)
3298 gfc_se tse;
3299 gfc_se rse;
3300 gfc_expr *e;
3301 gfc_symbol *new_sym;
3302 gfc_symbol *old_sym;
3303 gfc_symtree *root;
3304 tree tmp;
3306 /* Build a copy of the lvalue. */
3307 old_symtree = c->expr1->symtree;
3308 old_sym = old_symtree->n.sym;
3309 e = gfc_lval_expr_from_sym (old_sym);
3310 if (old_sym->attr.dimension)
3312 gfc_init_se (&tse, NULL);
3313 gfc_conv_subref_array_arg (&tse, e, 0, INTENT_IN, false);
3314 gfc_add_block_to_block (pre, &tse.pre);
3315 gfc_add_block_to_block (post, &tse.post);
3316 tse.expr = build_fold_indirect_ref_loc (input_location, tse.expr);
3318 if (c->expr1->ref->u.ar.type != AR_SECTION)
3320 /* Use the variable offset for the temporary. */
3321 tmp = gfc_conv_array_offset (old_sym->backend_decl);
3322 gfc_conv_descriptor_offset_set (pre, tse.expr, tmp);
3325 else
3327 gfc_init_se (&tse, NULL);
3328 gfc_init_se (&rse, NULL);
3329 gfc_conv_expr (&rse, e);
3330 if (e->ts.type == BT_CHARACTER)
3332 tse.string_length = rse.string_length;
3333 tmp = gfc_get_character_type_len (gfc_default_character_kind,
3334 tse.string_length);
3335 tse.expr = gfc_conv_string_tmp (&tse, build_pointer_type (tmp),
3336 rse.string_length);
3337 gfc_add_block_to_block (pre, &tse.pre);
3338 gfc_add_block_to_block (post, &tse.post);
3340 else
3342 tmp = gfc_typenode_for_spec (&e->ts);
3343 tse.expr = gfc_create_var (tmp, "temp");
3346 tmp = gfc_trans_scalar_assign (&tse, &rse, e->ts,
3347 e->expr_type == EXPR_VARIABLE, false);
3348 gfc_add_expr_to_block (pre, tmp);
3350 gfc_free_expr (e);
3352 /* Create a new symbol to represent the lvalue. */
3353 new_sym = gfc_new_symbol (old_sym->name, NULL);
3354 new_sym->ts = old_sym->ts;
3355 new_sym->attr.referenced = 1;
3356 new_sym->attr.temporary = 1;
3357 new_sym->attr.dimension = old_sym->attr.dimension;
3358 new_sym->attr.flavor = old_sym->attr.flavor;
3360 /* Use the temporary as the backend_decl. */
3361 new_sym->backend_decl = tse.expr;
3363 /* Create a fake symtree for it. */
3364 root = NULL;
3365 new_symtree = gfc_new_symtree (&root, old_sym->name);
3366 new_symtree->n.sym = new_sym;
3367 gcc_assert (new_symtree == root);
3369 /* Go through the expression reference replacing the old_symtree
3370 with the new. */
3371 forall_replace_symtree (c->expr1, old_sym, 2);
3373 /* Now we have made this temporary, we might as well use it for
3374 the right hand side. */
3375 forall_replace_symtree (c->expr2, old_sym, 1);
3379 /* Handles dependencies in forall assignments. */
3380 static int
3381 check_forall_dependencies (gfc_code *c, stmtblock_t *pre, stmtblock_t *post)
3383 gfc_ref *lref;
3384 gfc_ref *rref;
3385 int need_temp;
3386 gfc_symbol *lsym;
3388 lsym = c->expr1->symtree->n.sym;
3389 need_temp = gfc_check_dependency (c->expr1, c->expr2, 0);
3391 /* Now check for dependencies within the 'variable'
3392 expression itself. These are treated by making a complete
3393 copy of variable and changing all the references to it
3394 point to the copy instead. Note that the shallow copy of
3395 the variable will not suffice for derived types with
3396 pointer components. We therefore leave these to their
3397 own devices. */
3398 if (lsym->ts.type == BT_DERIVED
3399 && lsym->ts.u.derived->attr.pointer_comp)
3400 return need_temp;
3402 new_symtree = NULL;
3403 if (find_forall_index (c->expr1, lsym, 2))
3405 forall_make_variable_temp (c, pre, post);
3406 need_temp = 0;
3409 /* Substrings with dependencies are treated in the same
3410 way. */
3411 if (c->expr1->ts.type == BT_CHARACTER
3412 && c->expr1->ref
3413 && c->expr2->expr_type == EXPR_VARIABLE
3414 && lsym == c->expr2->symtree->n.sym)
3416 for (lref = c->expr1->ref; lref; lref = lref->next)
3417 if (lref->type == REF_SUBSTRING)
3418 break;
3419 for (rref = c->expr2->ref; rref; rref = rref->next)
3420 if (rref->type == REF_SUBSTRING)
3421 break;
3423 if (rref && lref
3424 && gfc_dep_compare_expr (rref->u.ss.start, lref->u.ss.start) < 0)
3426 forall_make_variable_temp (c, pre, post);
3427 need_temp = 0;
3430 return need_temp;
3434 static void
3435 cleanup_forall_symtrees (gfc_code *c)
3437 forall_restore_symtree (c->expr1);
3438 forall_restore_symtree (c->expr2);
3439 free (new_symtree->n.sym);
3440 free (new_symtree);
3444 /* Generate the loops for a FORALL block, specified by FORALL_TMP. BODY
3445 is the contents of the FORALL block/stmt to be iterated. MASK_FLAG
3446 indicates whether we should generate code to test the FORALLs mask
3447 array. OUTER is the loop header to be used for initializing mask
3448 indices.
3450 The generated loop format is:
3451 count = (end - start + step) / step
3452 loopvar = start
3453 while (1)
3455 if (count <=0 )
3456 goto end_of_loop
3457 <body>
3458 loopvar += step
3459 count --
3461 end_of_loop: */
3463 static tree
3464 gfc_trans_forall_loop (forall_info *forall_tmp, tree body,
3465 int mask_flag, stmtblock_t *outer)
3467 int n, nvar;
3468 tree tmp;
3469 tree cond;
3470 stmtblock_t block;
3471 tree exit_label;
3472 tree count;
3473 tree var, start, end, step;
3474 iter_info *iter;
3476 /* Initialize the mask index outside the FORALL nest. */
3477 if (mask_flag && forall_tmp->mask)
3478 gfc_add_modify (outer, forall_tmp->maskindex, gfc_index_zero_node);
3480 iter = forall_tmp->this_loop;
3481 nvar = forall_tmp->nvar;
3482 for (n = 0; n < nvar; n++)
3484 var = iter->var;
3485 start = iter->start;
3486 end = iter->end;
3487 step = iter->step;
3489 exit_label = gfc_build_label_decl (NULL_TREE);
3490 TREE_USED (exit_label) = 1;
3492 /* The loop counter. */
3493 count = gfc_create_var (TREE_TYPE (var), "count");
3495 /* The body of the loop. */
3496 gfc_init_block (&block);
3498 /* The exit condition. */
3499 cond = fold_build2_loc (input_location, LE_EXPR, logical_type_node,
3500 count, build_int_cst (TREE_TYPE (count), 0));
3501 if (forall_tmp->do_concurrent)
3502 cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
3503 build_int_cst (integer_type_node,
3504 annot_expr_parallel_kind),
3505 integer_zero_node);
3507 tmp = build1_v (GOTO_EXPR, exit_label);
3508 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
3509 cond, tmp, build_empty_stmt (input_location));
3510 gfc_add_expr_to_block (&block, tmp);
3512 /* The main loop body. */
3513 gfc_add_expr_to_block (&block, body);
3515 /* Increment the loop variable. */
3516 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (var), var,
3517 step);
3518 gfc_add_modify (&block, var, tmp);
3520 /* Advance to the next mask element. Only do this for the
3521 innermost loop. */
3522 if (n == 0 && mask_flag && forall_tmp->mask)
3524 tree maskindex = forall_tmp->maskindex;
3525 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
3526 maskindex, gfc_index_one_node);
3527 gfc_add_modify (&block, maskindex, tmp);
3530 /* Decrement the loop counter. */
3531 tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (var), count,
3532 build_int_cst (TREE_TYPE (var), 1));
3533 gfc_add_modify (&block, count, tmp);
3535 body = gfc_finish_block (&block);
3537 /* Loop var initialization. */
3538 gfc_init_block (&block);
3539 gfc_add_modify (&block, var, start);
3542 /* Initialize the loop counter. */
3543 tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (var), step,
3544 start);
3545 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (var), end,
3546 tmp);
3547 tmp = fold_build2_loc (input_location, TRUNC_DIV_EXPR, TREE_TYPE (var),
3548 tmp, step);
3549 gfc_add_modify (&block, count, tmp);
3551 /* The loop expression. */
3552 tmp = build1_v (LOOP_EXPR, body);
3553 gfc_add_expr_to_block (&block, tmp);
3555 /* The exit label. */
3556 tmp = build1_v (LABEL_EXPR, exit_label);
3557 gfc_add_expr_to_block (&block, tmp);
3559 body = gfc_finish_block (&block);
3560 iter = iter->next;
3562 return body;
3566 /* Generate the body and loops according to MASK_FLAG. If MASK_FLAG
3567 is nonzero, the body is controlled by all masks in the forall nest.
3568 Otherwise, the innermost loop is not controlled by it's mask. This
3569 is used for initializing that mask. */
3571 static tree
3572 gfc_trans_nested_forall_loop (forall_info * nested_forall_info, tree body,
3573 int mask_flag)
3575 tree tmp;
3576 stmtblock_t header;
3577 forall_info *forall_tmp;
3578 tree mask, maskindex;
3580 gfc_start_block (&header);
3582 forall_tmp = nested_forall_info;
3583 while (forall_tmp != NULL)
3585 /* Generate body with masks' control. */
3586 if (mask_flag)
3588 mask = forall_tmp->mask;
3589 maskindex = forall_tmp->maskindex;
3591 /* If a mask was specified make the assignment conditional. */
3592 if (mask)
3594 tmp = gfc_build_array_ref (mask, maskindex, NULL);
3595 body = build3_v (COND_EXPR, tmp, body,
3596 build_empty_stmt (input_location));
3599 body = gfc_trans_forall_loop (forall_tmp, body, mask_flag, &header);
3600 forall_tmp = forall_tmp->prev_nest;
3601 mask_flag = 1;
3604 gfc_add_expr_to_block (&header, body);
3605 return gfc_finish_block (&header);
3609 /* Allocate data for holding a temporary array. Returns either a local
3610 temporary array or a pointer variable. */
3612 static tree
3613 gfc_do_allocate (tree bytesize, tree size, tree * pdata, stmtblock_t * pblock,
3614 tree elem_type)
3616 tree tmpvar;
3617 tree type;
3618 tree tmp;
3620 if (INTEGER_CST_P (size))
3621 tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
3622 size, gfc_index_one_node);
3623 else
3624 tmp = NULL_TREE;
3626 type = build_range_type (gfc_array_index_type, gfc_index_zero_node, tmp);
3627 type = build_array_type (elem_type, type);
3628 if (gfc_can_put_var_on_stack (bytesize) && INTEGER_CST_P (size))
3630 tmpvar = gfc_create_var (type, "temp");
3631 *pdata = NULL_TREE;
3633 else
3635 tmpvar = gfc_create_var (build_pointer_type (type), "temp");
3636 *pdata = convert (pvoid_type_node, tmpvar);
3638 tmp = gfc_call_malloc (pblock, TREE_TYPE (tmpvar), bytesize);
3639 gfc_add_modify (pblock, tmpvar, tmp);
3641 return tmpvar;
3645 /* Generate codes to copy the temporary to the actual lhs. */
3647 static tree
3648 generate_loop_for_temp_to_lhs (gfc_expr *expr, tree tmp1, tree count3,
3649 tree count1,
3650 gfc_ss *lss, gfc_ss *rss,
3651 tree wheremask, bool invert)
3653 stmtblock_t block, body1;
3654 gfc_loopinfo loop;
3655 gfc_se lse;
3656 gfc_se rse;
3657 tree tmp;
3658 tree wheremaskexpr;
3660 (void) rss; /* TODO: unused. */
3662 gfc_start_block (&block);
3664 gfc_init_se (&rse, NULL);
3665 gfc_init_se (&lse, NULL);
3667 if (lss == gfc_ss_terminator)
3669 gfc_init_block (&body1);
3670 gfc_conv_expr (&lse, expr);
3671 rse.expr = gfc_build_array_ref (tmp1, count1, NULL);
3673 else
3675 /* Initialize the loop. */
3676 gfc_init_loopinfo (&loop);
3678 /* We may need LSS to determine the shape of the expression. */
3679 gfc_add_ss_to_loop (&loop, lss);
3681 gfc_conv_ss_startstride (&loop);
3682 gfc_conv_loop_setup (&loop, &expr->where);
3684 gfc_mark_ss_chain_used (lss, 1);
3685 /* Start the loop body. */
3686 gfc_start_scalarized_body (&loop, &body1);
3688 /* Translate the expression. */
3689 gfc_copy_loopinfo_to_se (&lse, &loop);
3690 lse.ss = lss;
3691 gfc_conv_expr (&lse, expr);
3693 /* Form the expression of the temporary. */
3694 rse.expr = gfc_build_array_ref (tmp1, count1, NULL);
3697 /* Use the scalar assignment. */
3698 rse.string_length = lse.string_length;
3699 tmp = gfc_trans_scalar_assign (&lse, &rse, expr->ts,
3700 expr->expr_type == EXPR_VARIABLE, false);
3702 /* Form the mask expression according to the mask tree list. */
3703 if (wheremask)
3705 wheremaskexpr = gfc_build_array_ref (wheremask, count3, NULL);
3706 if (invert)
3707 wheremaskexpr = fold_build1_loc (input_location, TRUTH_NOT_EXPR,
3708 TREE_TYPE (wheremaskexpr),
3709 wheremaskexpr);
3710 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
3711 wheremaskexpr, tmp,
3712 build_empty_stmt (input_location));
3715 gfc_add_expr_to_block (&body1, tmp);
3717 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (count1),
3718 count1, gfc_index_one_node);
3719 gfc_add_modify (&body1, count1, tmp);
3721 if (lss == gfc_ss_terminator)
3722 gfc_add_block_to_block (&block, &body1);
3723 else
3725 /* Increment count3. */
3726 if (count3)
3728 tmp = fold_build2_loc (input_location, PLUS_EXPR,
3729 gfc_array_index_type,
3730 count3, gfc_index_one_node);
3731 gfc_add_modify (&body1, count3, tmp);
3734 /* Generate the copying loops. */
3735 gfc_trans_scalarizing_loops (&loop, &body1);
3737 gfc_add_block_to_block (&block, &loop.pre);
3738 gfc_add_block_to_block (&block, &loop.post);
3740 gfc_cleanup_loop (&loop);
3741 /* TODO: Reuse lss and rss when copying temp->lhs. Need to be careful
3742 as tree nodes in SS may not be valid in different scope. */
3745 tmp = gfc_finish_block (&block);
3746 return tmp;
3750 /* Generate codes to copy rhs to the temporary. TMP1 is the address of
3751 temporary, LSS and RSS are formed in function compute_inner_temp_size(),
3752 and should not be freed. WHEREMASK is the conditional execution mask
3753 whose sense may be inverted by INVERT. */
3755 static tree
3756 generate_loop_for_rhs_to_temp (gfc_expr *expr2, tree tmp1, tree count3,
3757 tree count1, gfc_ss *lss, gfc_ss *rss,
3758 tree wheremask, bool invert)
3760 stmtblock_t block, body1;
3761 gfc_loopinfo loop;
3762 gfc_se lse;
3763 gfc_se rse;
3764 tree tmp;
3765 tree wheremaskexpr;
3767 gfc_start_block (&block);
3769 gfc_init_se (&rse, NULL);
3770 gfc_init_se (&lse, NULL);
3772 if (lss == gfc_ss_terminator)
3774 gfc_init_block (&body1);
3775 gfc_conv_expr (&rse, expr2);
3776 lse.expr = gfc_build_array_ref (tmp1, count1, NULL);
3778 else
3780 /* Initialize the loop. */
3781 gfc_init_loopinfo (&loop);
3783 /* We may need LSS to determine the shape of the expression. */
3784 gfc_add_ss_to_loop (&loop, lss);
3785 gfc_add_ss_to_loop (&loop, rss);
3787 gfc_conv_ss_startstride (&loop);
3788 gfc_conv_loop_setup (&loop, &expr2->where);
3790 gfc_mark_ss_chain_used (rss, 1);
3791 /* Start the loop body. */
3792 gfc_start_scalarized_body (&loop, &body1);
3794 /* Translate the expression. */
3795 gfc_copy_loopinfo_to_se (&rse, &loop);
3796 rse.ss = rss;
3797 gfc_conv_expr (&rse, expr2);
3799 /* Form the expression of the temporary. */
3800 lse.expr = gfc_build_array_ref (tmp1, count1, NULL);
3803 /* Use the scalar assignment. */
3804 lse.string_length = rse.string_length;
3805 tmp = gfc_trans_scalar_assign (&lse, &rse, expr2->ts,
3806 expr2->expr_type == EXPR_VARIABLE, false);
3808 /* Form the mask expression according to the mask tree list. */
3809 if (wheremask)
3811 wheremaskexpr = gfc_build_array_ref (wheremask, count3, NULL);
3812 if (invert)
3813 wheremaskexpr = fold_build1_loc (input_location, TRUTH_NOT_EXPR,
3814 TREE_TYPE (wheremaskexpr),
3815 wheremaskexpr);
3816 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
3817 wheremaskexpr, tmp,
3818 build_empty_stmt (input_location));
3821 gfc_add_expr_to_block (&body1, tmp);
3823 if (lss == gfc_ss_terminator)
3825 gfc_add_block_to_block (&block, &body1);
3827 /* Increment count1. */
3828 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (count1),
3829 count1, gfc_index_one_node);
3830 gfc_add_modify (&block, count1, tmp);
3832 else
3834 /* Increment count1. */
3835 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
3836 count1, gfc_index_one_node);
3837 gfc_add_modify (&body1, count1, tmp);
3839 /* Increment count3. */
3840 if (count3)
3842 tmp = fold_build2_loc (input_location, PLUS_EXPR,
3843 gfc_array_index_type,
3844 count3, gfc_index_one_node);
3845 gfc_add_modify (&body1, count3, tmp);
3848 /* Generate the copying loops. */
3849 gfc_trans_scalarizing_loops (&loop, &body1);
3851 gfc_add_block_to_block (&block, &loop.pre);
3852 gfc_add_block_to_block (&block, &loop.post);
3854 gfc_cleanup_loop (&loop);
3855 /* TODO: Reuse lss and rss when copying temp->lhs. Need to be careful
3856 as tree nodes in SS may not be valid in different scope. */
3859 tmp = gfc_finish_block (&block);
3860 return tmp;
3864 /* Calculate the size of temporary needed in the assignment inside forall.
3865 LSS and RSS are filled in this function. */
3867 static tree
3868 compute_inner_temp_size (gfc_expr *expr1, gfc_expr *expr2,
3869 stmtblock_t * pblock,
3870 gfc_ss **lss, gfc_ss **rss)
3872 gfc_loopinfo loop;
3873 tree size;
3874 int i;
3875 int save_flag;
3876 tree tmp;
3878 *lss = gfc_walk_expr (expr1);
3879 *rss = NULL;
3881 size = gfc_index_one_node;
3882 if (*lss != gfc_ss_terminator)
3884 gfc_init_loopinfo (&loop);
3886 /* Walk the RHS of the expression. */
3887 *rss = gfc_walk_expr (expr2);
3888 if (*rss == gfc_ss_terminator)
3889 /* The rhs is scalar. Add a ss for the expression. */
3890 *rss = gfc_get_scalar_ss (gfc_ss_terminator, expr2);
3892 /* Associate the SS with the loop. */
3893 gfc_add_ss_to_loop (&loop, *lss);
3894 /* We don't actually need to add the rhs at this point, but it might
3895 make guessing the loop bounds a bit easier. */
3896 gfc_add_ss_to_loop (&loop, *rss);
3898 /* We only want the shape of the expression, not rest of the junk
3899 generated by the scalarizer. */
3900 loop.array_parameter = 1;
3902 /* Calculate the bounds of the scalarization. */
3903 save_flag = gfc_option.rtcheck;
3904 gfc_option.rtcheck &= ~GFC_RTCHECK_BOUNDS;
3905 gfc_conv_ss_startstride (&loop);
3906 gfc_option.rtcheck = save_flag;
3907 gfc_conv_loop_setup (&loop, &expr2->where);
3909 /* Figure out how many elements we need. */
3910 for (i = 0; i < loop.dimen; i++)
3912 tmp = fold_build2_loc (input_location, MINUS_EXPR,
3913 gfc_array_index_type,
3914 gfc_index_one_node, loop.from[i]);
3915 tmp = fold_build2_loc (input_location, PLUS_EXPR,
3916 gfc_array_index_type, tmp, loop.to[i]);
3917 size = fold_build2_loc (input_location, MULT_EXPR,
3918 gfc_array_index_type, size, tmp);
3920 gfc_add_block_to_block (pblock, &loop.pre);
3921 size = gfc_evaluate_now (size, pblock);
3922 gfc_add_block_to_block (pblock, &loop.post);
3924 /* TODO: write a function that cleans up a loopinfo without freeing
3925 the SS chains. Currently a NOP. */
3928 return size;
3932 /* Calculate the overall iterator number of the nested forall construct.
3933 This routine actually calculates the number of times the body of the
3934 nested forall specified by NESTED_FORALL_INFO is executed and multiplies
3935 that by the expression INNER_SIZE. The BLOCK argument specifies the
3936 block in which to calculate the result, and the optional INNER_SIZE_BODY
3937 argument contains any statements that need to executed (inside the loop)
3938 to initialize or calculate INNER_SIZE. */
3940 static tree
3941 compute_overall_iter_number (forall_info *nested_forall_info, tree inner_size,
3942 stmtblock_t *inner_size_body, stmtblock_t *block)
3944 forall_info *forall_tmp = nested_forall_info;
3945 tree tmp, number;
3946 stmtblock_t body;
3948 /* We can eliminate the innermost unconditional loops with constant
3949 array bounds. */
3950 if (INTEGER_CST_P (inner_size))
3952 while (forall_tmp
3953 && !forall_tmp->mask
3954 && INTEGER_CST_P (forall_tmp->size))
3956 inner_size = fold_build2_loc (input_location, MULT_EXPR,
3957 gfc_array_index_type,
3958 inner_size, forall_tmp->size);
3959 forall_tmp = forall_tmp->prev_nest;
3962 /* If there are no loops left, we have our constant result. */
3963 if (!forall_tmp)
3964 return inner_size;
3967 /* Otherwise, create a temporary variable to compute the result. */
3968 number = gfc_create_var (gfc_array_index_type, "num");
3969 gfc_add_modify (block, number, gfc_index_zero_node);
3971 gfc_start_block (&body);
3972 if (inner_size_body)
3973 gfc_add_block_to_block (&body, inner_size_body);
3974 if (forall_tmp)
3975 tmp = fold_build2_loc (input_location, PLUS_EXPR,
3976 gfc_array_index_type, number, inner_size);
3977 else
3978 tmp = inner_size;
3979 gfc_add_modify (&body, number, tmp);
3980 tmp = gfc_finish_block (&body);
3982 /* Generate loops. */
3983 if (forall_tmp != NULL)
3984 tmp = gfc_trans_nested_forall_loop (forall_tmp, tmp, 1);
3986 gfc_add_expr_to_block (block, tmp);
3988 return number;
3992 /* Allocate temporary for forall construct. SIZE is the size of temporary
3993 needed. PTEMP1 is returned for space free. */
3995 static tree
3996 allocate_temp_for_forall_nest_1 (tree type, tree size, stmtblock_t * block,
3997 tree * ptemp1)
3999 tree bytesize;
4000 tree unit;
4001 tree tmp;
4003 unit = fold_convert (gfc_array_index_type, TYPE_SIZE_UNIT (type));
4004 if (!integer_onep (unit))
4005 bytesize = fold_build2_loc (input_location, MULT_EXPR,
4006 gfc_array_index_type, size, unit);
4007 else
4008 bytesize = size;
4010 *ptemp1 = NULL;
4011 tmp = gfc_do_allocate (bytesize, size, ptemp1, block, type);
4013 if (*ptemp1)
4014 tmp = build_fold_indirect_ref_loc (input_location, tmp);
4015 return tmp;
4019 /* Allocate temporary for forall construct according to the information in
4020 nested_forall_info. INNER_SIZE is the size of temporary needed in the
4021 assignment inside forall. PTEMP1 is returned for space free. */
4023 static tree
4024 allocate_temp_for_forall_nest (forall_info * nested_forall_info, tree type,
4025 tree inner_size, stmtblock_t * inner_size_body,
4026 stmtblock_t * block, tree * ptemp1)
4028 tree size;
4030 /* Calculate the total size of temporary needed in forall construct. */
4031 size = compute_overall_iter_number (nested_forall_info, inner_size,
4032 inner_size_body, block);
4034 return allocate_temp_for_forall_nest_1 (type, size, block, ptemp1);
4038 /* Handle assignments inside forall which need temporary.
4040 forall (i=start:end:stride; maskexpr)
4041 e<i> = f<i>
4042 end forall
4043 (where e,f<i> are arbitrary expressions possibly involving i
4044 and there is a dependency between e<i> and f<i>)
4045 Translates to:
4046 masktmp(:) = maskexpr(:)
4048 maskindex = 0;
4049 count1 = 0;
4050 num = 0;
4051 for (i = start; i <= end; i += stride)
4052 num += SIZE (f<i>)
4053 count1 = 0;
4054 ALLOCATE (tmp(num))
4055 for (i = start; i <= end; i += stride)
4057 if (masktmp[maskindex++])
4058 tmp[count1++] = f<i>
4060 maskindex = 0;
4061 count1 = 0;
4062 for (i = start; i <= end; i += stride)
4064 if (masktmp[maskindex++])
4065 e<i> = tmp[count1++]
4067 DEALLOCATE (tmp)
4069 static void
4070 gfc_trans_assign_need_temp (gfc_expr * expr1, gfc_expr * expr2,
4071 tree wheremask, bool invert,
4072 forall_info * nested_forall_info,
4073 stmtblock_t * block)
4075 tree type;
4076 tree inner_size;
4077 gfc_ss *lss, *rss;
4078 tree count, count1;
4079 tree tmp, tmp1;
4080 tree ptemp1;
4081 stmtblock_t inner_size_body;
4083 /* Create vars. count1 is the current iterator number of the nested
4084 forall. */
4085 count1 = gfc_create_var (gfc_array_index_type, "count1");
4087 /* Count is the wheremask index. */
4088 if (wheremask)
4090 count = gfc_create_var (gfc_array_index_type, "count");
4091 gfc_add_modify (block, count, gfc_index_zero_node);
4093 else
4094 count = NULL;
4096 /* Initialize count1. */
4097 gfc_add_modify (block, count1, gfc_index_zero_node);
4099 /* Calculate the size of temporary needed in the assignment. Return loop, lss
4100 and rss which are used in function generate_loop_for_rhs_to_temp(). */
4101 /* The type of LHS. Used in function allocate_temp_for_forall_nest */
4102 if (expr1->ts.type == BT_CHARACTER)
4104 type = NULL;
4105 if (expr1->ref && expr1->ref->type == REF_SUBSTRING)
4107 gfc_se ssse;
4108 gfc_init_se (&ssse, NULL);
4109 gfc_conv_expr (&ssse, expr1);
4110 type = gfc_get_character_type_len (gfc_default_character_kind,
4111 ssse.string_length);
4113 else
4115 if (!expr1->ts.u.cl->backend_decl)
4117 gfc_se tse;
4118 gcc_assert (expr1->ts.u.cl->length);
4119 gfc_init_se (&tse, NULL);
4120 gfc_conv_expr (&tse, expr1->ts.u.cl->length);
4121 expr1->ts.u.cl->backend_decl = tse.expr;
4123 type = gfc_get_character_type_len (gfc_default_character_kind,
4124 expr1->ts.u.cl->backend_decl);
4127 else
4128 type = gfc_typenode_for_spec (&expr1->ts);
4130 gfc_init_block (&inner_size_body);
4131 inner_size = compute_inner_temp_size (expr1, expr2, &inner_size_body,
4132 &lss, &rss);
4134 /* Allocate temporary for nested forall construct according to the
4135 information in nested_forall_info and inner_size. */
4136 tmp1 = allocate_temp_for_forall_nest (nested_forall_info, type, inner_size,
4137 &inner_size_body, block, &ptemp1);
4139 /* Generate codes to copy rhs to the temporary . */
4140 tmp = generate_loop_for_rhs_to_temp (expr2, tmp1, count, count1, lss, rss,
4141 wheremask, invert);
4143 /* Generate body and loops according to the information in
4144 nested_forall_info. */
4145 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
4146 gfc_add_expr_to_block (block, tmp);
4148 /* Reset count1. */
4149 gfc_add_modify (block, count1, gfc_index_zero_node);
4151 /* Reset count. */
4152 if (wheremask)
4153 gfc_add_modify (block, count, gfc_index_zero_node);
4155 /* TODO: Second call to compute_inner_temp_size to initialize lss and
4156 rss; there must be a better way. */
4157 inner_size = compute_inner_temp_size (expr1, expr2, &inner_size_body,
4158 &lss, &rss);
4160 /* Generate codes to copy the temporary to lhs. */
4161 tmp = generate_loop_for_temp_to_lhs (expr1, tmp1, count, count1,
4162 lss, rss,
4163 wheremask, invert);
4165 /* Generate body and loops according to the information in
4166 nested_forall_info. */
4167 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
4168 gfc_add_expr_to_block (block, tmp);
4170 if (ptemp1)
4172 /* Free the temporary. */
4173 tmp = gfc_call_free (ptemp1);
4174 gfc_add_expr_to_block (block, tmp);
4179 /* Translate pointer assignment inside FORALL which need temporary. */
4181 static void
4182 gfc_trans_pointer_assign_need_temp (gfc_expr * expr1, gfc_expr * expr2,
4183 forall_info * nested_forall_info,
4184 stmtblock_t * block)
4186 tree type;
4187 tree inner_size;
4188 gfc_ss *lss, *rss;
4189 gfc_se lse;
4190 gfc_se rse;
4191 gfc_array_info *info;
4192 gfc_loopinfo loop;
4193 tree desc;
4194 tree parm;
4195 tree parmtype;
4196 stmtblock_t body;
4197 tree count;
4198 tree tmp, tmp1, ptemp1;
4200 count = gfc_create_var (gfc_array_index_type, "count");
4201 gfc_add_modify (block, count, gfc_index_zero_node);
4203 inner_size = gfc_index_one_node;
4204 lss = gfc_walk_expr (expr1);
4205 rss = gfc_walk_expr (expr2);
4206 if (lss == gfc_ss_terminator)
4208 type = gfc_typenode_for_spec (&expr1->ts);
4209 type = build_pointer_type (type);
4211 /* Allocate temporary for nested forall construct according to the
4212 information in nested_forall_info and inner_size. */
4213 tmp1 = allocate_temp_for_forall_nest (nested_forall_info, type,
4214 inner_size, NULL, block, &ptemp1);
4215 gfc_start_block (&body);
4216 gfc_init_se (&lse, NULL);
4217 lse.expr = gfc_build_array_ref (tmp1, count, NULL);
4218 gfc_init_se (&rse, NULL);
4219 rse.want_pointer = 1;
4220 gfc_conv_expr (&rse, expr2);
4221 gfc_add_block_to_block (&body, &rse.pre);
4222 gfc_add_modify (&body, lse.expr,
4223 fold_convert (TREE_TYPE (lse.expr), rse.expr));
4224 gfc_add_block_to_block (&body, &rse.post);
4226 /* Increment count. */
4227 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
4228 count, gfc_index_one_node);
4229 gfc_add_modify (&body, count, tmp);
4231 tmp = gfc_finish_block (&body);
4233 /* Generate body and loops according to the information in
4234 nested_forall_info. */
4235 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
4236 gfc_add_expr_to_block (block, tmp);
4238 /* Reset count. */
4239 gfc_add_modify (block, count, gfc_index_zero_node);
4241 gfc_start_block (&body);
4242 gfc_init_se (&lse, NULL);
4243 gfc_init_se (&rse, NULL);
4244 rse.expr = gfc_build_array_ref (tmp1, count, NULL);
4245 lse.want_pointer = 1;
4246 gfc_conv_expr (&lse, expr1);
4247 gfc_add_block_to_block (&body, &lse.pre);
4248 gfc_add_modify (&body, lse.expr, rse.expr);
4249 gfc_add_block_to_block (&body, &lse.post);
4250 /* Increment count. */
4251 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
4252 count, gfc_index_one_node);
4253 gfc_add_modify (&body, count, tmp);
4254 tmp = gfc_finish_block (&body);
4256 /* Generate body and loops according to the information in
4257 nested_forall_info. */
4258 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
4259 gfc_add_expr_to_block (block, tmp);
4261 else
4263 gfc_init_loopinfo (&loop);
4265 /* Associate the SS with the loop. */
4266 gfc_add_ss_to_loop (&loop, rss);
4268 /* Setup the scalarizing loops and bounds. */
4269 gfc_conv_ss_startstride (&loop);
4271 gfc_conv_loop_setup (&loop, &expr2->where);
4273 info = &rss->info->data.array;
4274 desc = info->descriptor;
4276 /* Make a new descriptor. */
4277 parmtype = gfc_get_element_type (TREE_TYPE (desc));
4278 parmtype = gfc_get_array_type_bounds (parmtype, loop.dimen, 0,
4279 loop.from, loop.to, 1,
4280 GFC_ARRAY_UNKNOWN, true);
4282 /* Allocate temporary for nested forall construct. */
4283 tmp1 = allocate_temp_for_forall_nest (nested_forall_info, parmtype,
4284 inner_size, NULL, block, &ptemp1);
4285 gfc_start_block (&body);
4286 gfc_init_se (&lse, NULL);
4287 lse.expr = gfc_build_array_ref (tmp1, count, NULL);
4288 lse.direct_byref = 1;
4289 gfc_conv_expr_descriptor (&lse, expr2);
4291 gfc_add_block_to_block (&body, &lse.pre);
4292 gfc_add_block_to_block (&body, &lse.post);
4294 /* Increment count. */
4295 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
4296 count, gfc_index_one_node);
4297 gfc_add_modify (&body, count, tmp);
4299 tmp = gfc_finish_block (&body);
4301 /* Generate body and loops according to the information in
4302 nested_forall_info. */
4303 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
4304 gfc_add_expr_to_block (block, tmp);
4306 /* Reset count. */
4307 gfc_add_modify (block, count, gfc_index_zero_node);
4309 parm = gfc_build_array_ref (tmp1, count, NULL);
4310 gfc_init_se (&lse, NULL);
4311 gfc_conv_expr_descriptor (&lse, expr1);
4312 gfc_add_modify (&lse.pre, lse.expr, parm);
4313 gfc_start_block (&body);
4314 gfc_add_block_to_block (&body, &lse.pre);
4315 gfc_add_block_to_block (&body, &lse.post);
4317 /* Increment count. */
4318 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
4319 count, gfc_index_one_node);
4320 gfc_add_modify (&body, count, tmp);
4322 tmp = gfc_finish_block (&body);
4324 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
4325 gfc_add_expr_to_block (block, tmp);
4327 /* Free the temporary. */
4328 if (ptemp1)
4330 tmp = gfc_call_free (ptemp1);
4331 gfc_add_expr_to_block (block, tmp);
4336 /* FORALL and WHERE statements are really nasty, especially when you nest
4337 them. All the rhs of a forall assignment must be evaluated before the
4338 actual assignments are performed. Presumably this also applies to all the
4339 assignments in an inner where statement. */
4341 /* Generate code for a FORALL statement. Any temporaries are allocated as a
4342 linear array, relying on the fact that we process in the same order in all
4343 loops.
4345 forall (i=start:end:stride; maskexpr)
4346 e<i> = f<i>
4347 g<i> = h<i>
4348 end forall
4349 (where e,f,g,h<i> are arbitrary expressions possibly involving i)
4350 Translates to:
4351 count = ((end + 1 - start) / stride)
4352 masktmp(:) = maskexpr(:)
4354 maskindex = 0;
4355 for (i = start; i <= end; i += stride)
4357 if (masktmp[maskindex++])
4358 e<i> = f<i>
4360 maskindex = 0;
4361 for (i = start; i <= end; i += stride)
4363 if (masktmp[maskindex++])
4364 g<i> = h<i>
4367 Note that this code only works when there are no dependencies.
4368 Forall loop with array assignments and data dependencies are a real pain,
4369 because the size of the temporary cannot always be determined before the
4370 loop is executed. This problem is compounded by the presence of nested
4371 FORALL constructs.
4374 static tree
4375 gfc_trans_forall_1 (gfc_code * code, forall_info * nested_forall_info)
4377 stmtblock_t pre;
4378 stmtblock_t post;
4379 stmtblock_t block;
4380 stmtblock_t body;
4381 tree *var;
4382 tree *start;
4383 tree *end;
4384 tree *step;
4385 gfc_expr **varexpr;
4386 tree tmp;
4387 tree assign;
4388 tree size;
4389 tree maskindex;
4390 tree mask;
4391 tree pmask;
4392 tree cycle_label = NULL_TREE;
4393 int n;
4394 int nvar;
4395 int need_temp;
4396 gfc_forall_iterator *fa;
4397 gfc_se se;
4398 gfc_code *c;
4399 gfc_saved_var *saved_vars;
4400 iter_info *this_forall;
4401 forall_info *info;
4402 bool need_mask;
4404 /* Do nothing if the mask is false. */
4405 if (code->expr1
4406 && code->expr1->expr_type == EXPR_CONSTANT
4407 && !code->expr1->value.logical)
4408 return build_empty_stmt (input_location);
4410 n = 0;
4411 /* Count the FORALL index number. */
4412 for (fa = code->ext.forall_iterator; fa; fa = fa->next)
4413 n++;
4414 nvar = n;
4416 /* Allocate the space for var, start, end, step, varexpr. */
4417 var = XCNEWVEC (tree, nvar);
4418 start = XCNEWVEC (tree, nvar);
4419 end = XCNEWVEC (tree, nvar);
4420 step = XCNEWVEC (tree, nvar);
4421 varexpr = XCNEWVEC (gfc_expr *, nvar);
4422 saved_vars = XCNEWVEC (gfc_saved_var, nvar);
4424 /* Allocate the space for info. */
4425 info = XCNEW (forall_info);
4427 gfc_start_block (&pre);
4428 gfc_init_block (&post);
4429 gfc_init_block (&block);
4431 n = 0;
4432 for (fa = code->ext.forall_iterator; fa; fa = fa->next)
4434 gfc_symbol *sym = fa->var->symtree->n.sym;
4436 /* Allocate space for this_forall. */
4437 this_forall = XCNEW (iter_info);
4439 /* Create a temporary variable for the FORALL index. */
4440 tmp = gfc_typenode_for_spec (&sym->ts);
4441 var[n] = gfc_create_var (tmp, sym->name);
4442 gfc_shadow_sym (sym, var[n], &saved_vars[n]);
4444 /* Record it in this_forall. */
4445 this_forall->var = var[n];
4447 /* Replace the index symbol's backend_decl with the temporary decl. */
4448 sym->backend_decl = var[n];
4450 /* Work out the start, end and stride for the loop. */
4451 gfc_init_se (&se, NULL);
4452 gfc_conv_expr_val (&se, fa->start);
4453 /* Record it in this_forall. */
4454 this_forall->start = se.expr;
4455 gfc_add_block_to_block (&block, &se.pre);
4456 start[n] = se.expr;
4458 gfc_init_se (&se, NULL);
4459 gfc_conv_expr_val (&se, fa->end);
4460 /* Record it in this_forall. */
4461 this_forall->end = se.expr;
4462 gfc_make_safe_expr (&se);
4463 gfc_add_block_to_block (&block, &se.pre);
4464 end[n] = se.expr;
4466 gfc_init_se (&se, NULL);
4467 gfc_conv_expr_val (&se, fa->stride);
4468 /* Record it in this_forall. */
4469 this_forall->step = se.expr;
4470 gfc_make_safe_expr (&se);
4471 gfc_add_block_to_block (&block, &se.pre);
4472 step[n] = se.expr;
4474 /* Set the NEXT field of this_forall to NULL. */
4475 this_forall->next = NULL;
4476 /* Link this_forall to the info construct. */
4477 if (info->this_loop)
4479 iter_info *iter_tmp = info->this_loop;
4480 while (iter_tmp->next != NULL)
4481 iter_tmp = iter_tmp->next;
4482 iter_tmp->next = this_forall;
4484 else
4485 info->this_loop = this_forall;
4487 n++;
4489 nvar = n;
4491 /* Calculate the size needed for the current forall level. */
4492 size = gfc_index_one_node;
4493 for (n = 0; n < nvar; n++)
4495 /* size = (end + step - start) / step. */
4496 tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (start[n]),
4497 step[n], start[n]);
4498 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (end[n]),
4499 end[n], tmp);
4500 tmp = fold_build2_loc (input_location, FLOOR_DIV_EXPR, TREE_TYPE (tmp),
4501 tmp, step[n]);
4502 tmp = convert (gfc_array_index_type, tmp);
4504 size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
4505 size, tmp);
4508 /* Record the nvar and size of current forall level. */
4509 info->nvar = nvar;
4510 info->size = size;
4512 if (code->expr1)
4514 /* If the mask is .true., consider the FORALL unconditional. */
4515 if (code->expr1->expr_type == EXPR_CONSTANT
4516 && code->expr1->value.logical)
4517 need_mask = false;
4518 else
4519 need_mask = true;
4521 else
4522 need_mask = false;
4524 /* First we need to allocate the mask. */
4525 if (need_mask)
4527 /* As the mask array can be very big, prefer compact boolean types. */
4528 tree mask_type = gfc_get_logical_type (gfc_logical_kinds[0].kind);
4529 mask = allocate_temp_for_forall_nest (nested_forall_info, mask_type,
4530 size, NULL, &block, &pmask);
4531 maskindex = gfc_create_var_np (gfc_array_index_type, "mi");
4533 /* Record them in the info structure. */
4534 info->maskindex = maskindex;
4535 info->mask = mask;
4537 else
4539 /* No mask was specified. */
4540 maskindex = NULL_TREE;
4541 mask = pmask = NULL_TREE;
4544 /* Link the current forall level to nested_forall_info. */
4545 info->prev_nest = nested_forall_info;
4546 nested_forall_info = info;
4548 /* Copy the mask into a temporary variable if required.
4549 For now we assume a mask temporary is needed. */
4550 if (need_mask)
4552 /* As the mask array can be very big, prefer compact boolean types. */
4553 tree mask_type = gfc_get_logical_type (gfc_logical_kinds[0].kind);
4555 gfc_add_modify (&block, maskindex, gfc_index_zero_node);
4557 /* Start of mask assignment loop body. */
4558 gfc_start_block (&body);
4560 /* Evaluate the mask expression. */
4561 gfc_init_se (&se, NULL);
4562 gfc_conv_expr_val (&se, code->expr1);
4563 gfc_add_block_to_block (&body, &se.pre);
4565 /* Store the mask. */
4566 se.expr = convert (mask_type, se.expr);
4568 tmp = gfc_build_array_ref (mask, maskindex, NULL);
4569 gfc_add_modify (&body, tmp, se.expr);
4571 /* Advance to the next mask element. */
4572 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
4573 maskindex, gfc_index_one_node);
4574 gfc_add_modify (&body, maskindex, tmp);
4576 /* Generate the loops. */
4577 tmp = gfc_finish_block (&body);
4578 tmp = gfc_trans_nested_forall_loop (info, tmp, 0);
4579 gfc_add_expr_to_block (&block, tmp);
4582 if (code->op == EXEC_DO_CONCURRENT)
4584 gfc_init_block (&body);
4585 cycle_label = gfc_build_label_decl (NULL_TREE);
4586 code->cycle_label = cycle_label;
4587 tmp = gfc_trans_code (code->block->next);
4588 gfc_add_expr_to_block (&body, tmp);
4590 if (TREE_USED (cycle_label))
4592 tmp = build1_v (LABEL_EXPR, cycle_label);
4593 gfc_add_expr_to_block (&body, tmp);
4596 tmp = gfc_finish_block (&body);
4597 nested_forall_info->do_concurrent = true;
4598 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
4599 gfc_add_expr_to_block (&block, tmp);
4600 goto done;
4603 c = code->block->next;
4605 /* TODO: loop merging in FORALL statements. */
4606 /* Now that we've got a copy of the mask, generate the assignment loops. */
4607 while (c)
4609 switch (c->op)
4611 case EXEC_ASSIGN:
4612 /* A scalar or array assignment. DO the simple check for
4613 lhs to rhs dependencies. These make a temporary for the
4614 rhs and form a second forall block to copy to variable. */
4615 need_temp = check_forall_dependencies(c, &pre, &post);
4617 /* Temporaries due to array assignment data dependencies introduce
4618 no end of problems. */
4619 if (need_temp || flag_test_forall_temp)
4620 gfc_trans_assign_need_temp (c->expr1, c->expr2, NULL, false,
4621 nested_forall_info, &block);
4622 else
4624 /* Use the normal assignment copying routines. */
4625 assign = gfc_trans_assignment (c->expr1, c->expr2, false, true);
4627 /* Generate body and loops. */
4628 tmp = gfc_trans_nested_forall_loop (nested_forall_info,
4629 assign, 1);
4630 gfc_add_expr_to_block (&block, tmp);
4633 /* Cleanup any temporary symtrees that have been made to deal
4634 with dependencies. */
4635 if (new_symtree)
4636 cleanup_forall_symtrees (c);
4638 break;
4640 case EXEC_WHERE:
4641 /* Translate WHERE or WHERE construct nested in FORALL. */
4642 gfc_trans_where_2 (c, NULL, false, nested_forall_info, &block);
4643 break;
4645 /* Pointer assignment inside FORALL. */
4646 case EXEC_POINTER_ASSIGN:
4647 need_temp = gfc_check_dependency (c->expr1, c->expr2, 0);
4648 /* Avoid cases where a temporary would never be needed and where
4649 the temp code is guaranteed to fail. */
4650 if (need_temp
4651 || (flag_test_forall_temp
4652 && c->expr2->expr_type != EXPR_CONSTANT
4653 && c->expr2->expr_type != EXPR_NULL))
4654 gfc_trans_pointer_assign_need_temp (c->expr1, c->expr2,
4655 nested_forall_info, &block);
4656 else
4658 /* Use the normal assignment copying routines. */
4659 assign = gfc_trans_pointer_assignment (c->expr1, c->expr2);
4661 /* Generate body and loops. */
4662 tmp = gfc_trans_nested_forall_loop (nested_forall_info,
4663 assign, 1);
4664 gfc_add_expr_to_block (&block, tmp);
4666 break;
4668 case EXEC_FORALL:
4669 tmp = gfc_trans_forall_1 (c, nested_forall_info);
4670 gfc_add_expr_to_block (&block, tmp);
4671 break;
4673 /* Explicit subroutine calls are prevented by the frontend but interface
4674 assignments can legitimately produce them. */
4675 case EXEC_ASSIGN_CALL:
4676 assign = gfc_trans_call (c, true, NULL_TREE, NULL_TREE, false);
4677 tmp = gfc_trans_nested_forall_loop (nested_forall_info, assign, 1);
4678 gfc_add_expr_to_block (&block, tmp);
4679 break;
4681 default:
4682 gcc_unreachable ();
4685 c = c->next;
4688 done:
4689 /* Restore the original index variables. */
4690 for (fa = code->ext.forall_iterator, n = 0; fa; fa = fa->next, n++)
4691 gfc_restore_sym (fa->var->symtree->n.sym, &saved_vars[n]);
4693 /* Free the space for var, start, end, step, varexpr. */
4694 free (var);
4695 free (start);
4696 free (end);
4697 free (step);
4698 free (varexpr);
4699 free (saved_vars);
4701 for (this_forall = info->this_loop; this_forall;)
4703 iter_info *next = this_forall->next;
4704 free (this_forall);
4705 this_forall = next;
4708 /* Free the space for this forall_info. */
4709 free (info);
4711 if (pmask)
4713 /* Free the temporary for the mask. */
4714 tmp = gfc_call_free (pmask);
4715 gfc_add_expr_to_block (&block, tmp);
4717 if (maskindex)
4718 pushdecl (maskindex);
4720 gfc_add_block_to_block (&pre, &block);
4721 gfc_add_block_to_block (&pre, &post);
4723 return gfc_finish_block (&pre);
4727 /* Translate the FORALL statement or construct. */
4729 tree gfc_trans_forall (gfc_code * code)
4731 return gfc_trans_forall_1 (code, NULL);
4735 /* Translate the DO CONCURRENT construct. */
4737 tree gfc_trans_do_concurrent (gfc_code * code)
4739 return gfc_trans_forall_1 (code, NULL);
4743 /* Evaluate the WHERE mask expression, copy its value to a temporary.
4744 If the WHERE construct is nested in FORALL, compute the overall temporary
4745 needed by the WHERE mask expression multiplied by the iterator number of
4746 the nested forall.
4747 ME is the WHERE mask expression.
4748 MASK is the current execution mask upon input, whose sense may or may
4749 not be inverted as specified by the INVERT argument.
4750 CMASK is the updated execution mask on output, or NULL if not required.
4751 PMASK is the pending execution mask on output, or NULL if not required.
4752 BLOCK is the block in which to place the condition evaluation loops. */
4754 static void
4755 gfc_evaluate_where_mask (gfc_expr * me, forall_info * nested_forall_info,
4756 tree mask, bool invert, tree cmask, tree pmask,
4757 tree mask_type, stmtblock_t * block)
4759 tree tmp, tmp1;
4760 gfc_ss *lss, *rss;
4761 gfc_loopinfo loop;
4762 stmtblock_t body, body1;
4763 tree count, cond, mtmp;
4764 gfc_se lse, rse;
4766 gfc_init_loopinfo (&loop);
4768 lss = gfc_walk_expr (me);
4769 rss = gfc_walk_expr (me);
4771 /* Variable to index the temporary. */
4772 count = gfc_create_var (gfc_array_index_type, "count");
4773 /* Initialize count. */
4774 gfc_add_modify (block, count, gfc_index_zero_node);
4776 gfc_start_block (&body);
4778 gfc_init_se (&rse, NULL);
4779 gfc_init_se (&lse, NULL);
4781 if (lss == gfc_ss_terminator)
4783 gfc_init_block (&body1);
4785 else
4787 /* Initialize the loop. */
4788 gfc_init_loopinfo (&loop);
4790 /* We may need LSS to determine the shape of the expression. */
4791 gfc_add_ss_to_loop (&loop, lss);
4792 gfc_add_ss_to_loop (&loop, rss);
4794 gfc_conv_ss_startstride (&loop);
4795 gfc_conv_loop_setup (&loop, &me->where);
4797 gfc_mark_ss_chain_used (rss, 1);
4798 /* Start the loop body. */
4799 gfc_start_scalarized_body (&loop, &body1);
4801 /* Translate the expression. */
4802 gfc_copy_loopinfo_to_se (&rse, &loop);
4803 rse.ss = rss;
4804 gfc_conv_expr (&rse, me);
4807 /* Variable to evaluate mask condition. */
4808 cond = gfc_create_var (mask_type, "cond");
4809 if (mask && (cmask || pmask))
4810 mtmp = gfc_create_var (mask_type, "mask");
4811 else mtmp = NULL_TREE;
4813 gfc_add_block_to_block (&body1, &lse.pre);
4814 gfc_add_block_to_block (&body1, &rse.pre);
4816 gfc_add_modify (&body1, cond, fold_convert (mask_type, rse.expr));
4818 if (mask && (cmask || pmask))
4820 tmp = gfc_build_array_ref (mask, count, NULL);
4821 if (invert)
4822 tmp = fold_build1_loc (input_location, TRUTH_NOT_EXPR, mask_type, tmp);
4823 gfc_add_modify (&body1, mtmp, tmp);
4826 if (cmask)
4828 tmp1 = gfc_build_array_ref (cmask, count, NULL);
4829 tmp = cond;
4830 if (mask)
4831 tmp = fold_build2_loc (input_location, TRUTH_AND_EXPR, mask_type,
4832 mtmp, tmp);
4833 gfc_add_modify (&body1, tmp1, tmp);
4836 if (pmask)
4838 tmp1 = gfc_build_array_ref (pmask, count, NULL);
4839 tmp = fold_build1_loc (input_location, TRUTH_NOT_EXPR, mask_type, cond);
4840 if (mask)
4841 tmp = fold_build2_loc (input_location, TRUTH_AND_EXPR, mask_type, mtmp,
4842 tmp);
4843 gfc_add_modify (&body1, tmp1, tmp);
4846 gfc_add_block_to_block (&body1, &lse.post);
4847 gfc_add_block_to_block (&body1, &rse.post);
4849 if (lss == gfc_ss_terminator)
4851 gfc_add_block_to_block (&body, &body1);
4853 else
4855 /* Increment count. */
4856 tmp1 = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
4857 count, gfc_index_one_node);
4858 gfc_add_modify (&body1, count, tmp1);
4860 /* Generate the copying loops. */
4861 gfc_trans_scalarizing_loops (&loop, &body1);
4863 gfc_add_block_to_block (&body, &loop.pre);
4864 gfc_add_block_to_block (&body, &loop.post);
4866 gfc_cleanup_loop (&loop);
4867 /* TODO: Reuse lss and rss when copying temp->lhs. Need to be careful
4868 as tree nodes in SS may not be valid in different scope. */
4871 tmp1 = gfc_finish_block (&body);
4872 /* If the WHERE construct is inside FORALL, fill the full temporary. */
4873 if (nested_forall_info != NULL)
4874 tmp1 = gfc_trans_nested_forall_loop (nested_forall_info, tmp1, 1);
4876 gfc_add_expr_to_block (block, tmp1);
4880 /* Translate an assignment statement in a WHERE statement or construct
4881 statement. The MASK expression is used to control which elements
4882 of EXPR1 shall be assigned. The sense of MASK is specified by
4883 INVERT. */
4885 static tree
4886 gfc_trans_where_assign (gfc_expr *expr1, gfc_expr *expr2,
4887 tree mask, bool invert,
4888 tree count1, tree count2,
4889 gfc_code *cnext)
4891 gfc_se lse;
4892 gfc_se rse;
4893 gfc_ss *lss;
4894 gfc_ss *lss_section;
4895 gfc_ss *rss;
4897 gfc_loopinfo loop;
4898 tree tmp;
4899 stmtblock_t block;
4900 stmtblock_t body;
4901 tree index, maskexpr;
4903 /* A defined assignment. */
4904 if (cnext && cnext->resolved_sym)
4905 return gfc_trans_call (cnext, true, mask, count1, invert);
4907 #if 0
4908 /* TODO: handle this special case.
4909 Special case a single function returning an array. */
4910 if (expr2->expr_type == EXPR_FUNCTION && expr2->rank > 0)
4912 tmp = gfc_trans_arrayfunc_assign (expr1, expr2);
4913 if (tmp)
4914 return tmp;
4916 #endif
4918 /* Assignment of the form lhs = rhs. */
4919 gfc_start_block (&block);
4921 gfc_init_se (&lse, NULL);
4922 gfc_init_se (&rse, NULL);
4924 /* Walk the lhs. */
4925 lss = gfc_walk_expr (expr1);
4926 rss = NULL;
4928 /* In each where-assign-stmt, the mask-expr and the variable being
4929 defined shall be arrays of the same shape. */
4930 gcc_assert (lss != gfc_ss_terminator);
4932 /* The assignment needs scalarization. */
4933 lss_section = lss;
4935 /* Find a non-scalar SS from the lhs. */
4936 while (lss_section != gfc_ss_terminator
4937 && lss_section->info->type != GFC_SS_SECTION)
4938 lss_section = lss_section->next;
4940 gcc_assert (lss_section != gfc_ss_terminator);
4942 /* Initialize the scalarizer. */
4943 gfc_init_loopinfo (&loop);
4945 /* Walk the rhs. */
4946 rss = gfc_walk_expr (expr2);
4947 if (rss == gfc_ss_terminator)
4949 /* The rhs is scalar. Add a ss for the expression. */
4950 rss = gfc_get_scalar_ss (gfc_ss_terminator, expr2);
4951 rss->info->where = 1;
4954 /* Associate the SS with the loop. */
4955 gfc_add_ss_to_loop (&loop, lss);
4956 gfc_add_ss_to_loop (&loop, rss);
4958 /* Calculate the bounds of the scalarization. */
4959 gfc_conv_ss_startstride (&loop);
4961 /* Resolve any data dependencies in the statement. */
4962 gfc_conv_resolve_dependencies (&loop, lss_section, rss);
4964 /* Setup the scalarizing loops. */
4965 gfc_conv_loop_setup (&loop, &expr2->where);
4967 /* Setup the gfc_se structures. */
4968 gfc_copy_loopinfo_to_se (&lse, &loop);
4969 gfc_copy_loopinfo_to_se (&rse, &loop);
4971 rse.ss = rss;
4972 gfc_mark_ss_chain_used (rss, 1);
4973 if (loop.temp_ss == NULL)
4975 lse.ss = lss;
4976 gfc_mark_ss_chain_used (lss, 1);
4978 else
4980 lse.ss = loop.temp_ss;
4981 gfc_mark_ss_chain_used (lss, 3);
4982 gfc_mark_ss_chain_used (loop.temp_ss, 3);
4985 /* Start the scalarized loop body. */
4986 gfc_start_scalarized_body (&loop, &body);
4988 /* Translate the expression. */
4989 gfc_conv_expr (&rse, expr2);
4990 if (lss != gfc_ss_terminator && loop.temp_ss != NULL)
4991 gfc_conv_tmp_array_ref (&lse);
4992 else
4993 gfc_conv_expr (&lse, expr1);
4995 /* Form the mask expression according to the mask. */
4996 index = count1;
4997 maskexpr = gfc_build_array_ref (mask, index, NULL);
4998 if (invert)
4999 maskexpr = fold_build1_loc (input_location, TRUTH_NOT_EXPR,
5000 TREE_TYPE (maskexpr), maskexpr);
5002 /* Use the scalar assignment as is. */
5003 tmp = gfc_trans_scalar_assign (&lse, &rse, expr1->ts,
5004 false, loop.temp_ss == NULL);
5006 tmp = build3_v (COND_EXPR, maskexpr, tmp, build_empty_stmt (input_location));
5008 gfc_add_expr_to_block (&body, tmp);
5010 if (lss == gfc_ss_terminator)
5012 /* Increment count1. */
5013 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
5014 count1, gfc_index_one_node);
5015 gfc_add_modify (&body, count1, tmp);
5017 /* Use the scalar assignment as is. */
5018 gfc_add_block_to_block (&block, &body);
5020 else
5022 gcc_assert (lse.ss == gfc_ss_terminator
5023 && rse.ss == gfc_ss_terminator);
5025 if (loop.temp_ss != NULL)
5027 /* Increment count1 before finish the main body of a scalarized
5028 expression. */
5029 tmp = fold_build2_loc (input_location, PLUS_EXPR,
5030 gfc_array_index_type, count1, gfc_index_one_node);
5031 gfc_add_modify (&body, count1, tmp);
5032 gfc_trans_scalarized_loop_boundary (&loop, &body);
5034 /* We need to copy the temporary to the actual lhs. */
5035 gfc_init_se (&lse, NULL);
5036 gfc_init_se (&rse, NULL);
5037 gfc_copy_loopinfo_to_se (&lse, &loop);
5038 gfc_copy_loopinfo_to_se (&rse, &loop);
5040 rse.ss = loop.temp_ss;
5041 lse.ss = lss;
5043 gfc_conv_tmp_array_ref (&rse);
5044 gfc_conv_expr (&lse, expr1);
5046 gcc_assert (lse.ss == gfc_ss_terminator
5047 && rse.ss == gfc_ss_terminator);
5049 /* Form the mask expression according to the mask tree list. */
5050 index = count2;
5051 maskexpr = gfc_build_array_ref (mask, index, NULL);
5052 if (invert)
5053 maskexpr = fold_build1_loc (input_location, TRUTH_NOT_EXPR,
5054 TREE_TYPE (maskexpr), maskexpr);
5056 /* Use the scalar assignment as is. */
5057 tmp = gfc_trans_scalar_assign (&lse, &rse, expr1->ts, false, true);
5058 tmp = build3_v (COND_EXPR, maskexpr, tmp,
5059 build_empty_stmt (input_location));
5060 gfc_add_expr_to_block (&body, tmp);
5062 /* Increment count2. */
5063 tmp = fold_build2_loc (input_location, PLUS_EXPR,
5064 gfc_array_index_type, count2,
5065 gfc_index_one_node);
5066 gfc_add_modify (&body, count2, tmp);
5068 else
5070 /* Increment count1. */
5071 tmp = fold_build2_loc (input_location, PLUS_EXPR,
5072 gfc_array_index_type, count1,
5073 gfc_index_one_node);
5074 gfc_add_modify (&body, count1, tmp);
5077 /* Generate the copying loops. */
5078 gfc_trans_scalarizing_loops (&loop, &body);
5080 /* Wrap the whole thing up. */
5081 gfc_add_block_to_block (&block, &loop.pre);
5082 gfc_add_block_to_block (&block, &loop.post);
5083 gfc_cleanup_loop (&loop);
5086 return gfc_finish_block (&block);
5090 /* Translate the WHERE construct or statement.
5091 This function can be called iteratively to translate the nested WHERE
5092 construct or statement.
5093 MASK is the control mask. */
5095 static void
5096 gfc_trans_where_2 (gfc_code * code, tree mask, bool invert,
5097 forall_info * nested_forall_info, stmtblock_t * block)
5099 stmtblock_t inner_size_body;
5100 tree inner_size, size;
5101 gfc_ss *lss, *rss;
5102 tree mask_type;
5103 gfc_expr *expr1;
5104 gfc_expr *expr2;
5105 gfc_code *cblock;
5106 gfc_code *cnext;
5107 tree tmp;
5108 tree cond;
5109 tree count1, count2;
5110 bool need_cmask;
5111 bool need_pmask;
5112 int need_temp;
5113 tree pcmask = NULL_TREE;
5114 tree ppmask = NULL_TREE;
5115 tree cmask = NULL_TREE;
5116 tree pmask = NULL_TREE;
5117 gfc_actual_arglist *arg;
5119 /* the WHERE statement or the WHERE construct statement. */
5120 cblock = code->block;
5122 /* As the mask array can be very big, prefer compact boolean types. */
5123 mask_type = gfc_get_logical_type (gfc_logical_kinds[0].kind);
5125 /* Determine which temporary masks are needed. */
5126 if (!cblock->block)
5128 /* One clause: No ELSEWHEREs. */
5129 need_cmask = (cblock->next != 0);
5130 need_pmask = false;
5132 else if (cblock->block->block)
5134 /* Three or more clauses: Conditional ELSEWHEREs. */
5135 need_cmask = true;
5136 need_pmask = true;
5138 else if (cblock->next)
5140 /* Two clauses, the first non-empty. */
5141 need_cmask = true;
5142 need_pmask = (mask != NULL_TREE
5143 && cblock->block->next != 0);
5145 else if (!cblock->block->next)
5147 /* Two clauses, both empty. */
5148 need_cmask = false;
5149 need_pmask = false;
5151 /* Two clauses, the first empty, the second non-empty. */
5152 else if (mask)
5154 need_cmask = (cblock->block->expr1 != 0);
5155 need_pmask = true;
5157 else
5159 need_cmask = true;
5160 need_pmask = false;
5163 if (need_cmask || need_pmask)
5165 /* Calculate the size of temporary needed by the mask-expr. */
5166 gfc_init_block (&inner_size_body);
5167 inner_size = compute_inner_temp_size (cblock->expr1, cblock->expr1,
5168 &inner_size_body, &lss, &rss);
5170 gfc_free_ss_chain (lss);
5171 gfc_free_ss_chain (rss);
5173 /* Calculate the total size of temporary needed. */
5174 size = compute_overall_iter_number (nested_forall_info, inner_size,
5175 &inner_size_body, block);
5177 /* Check whether the size is negative. */
5178 cond = fold_build2_loc (input_location, LE_EXPR, logical_type_node, size,
5179 gfc_index_zero_node);
5180 size = fold_build3_loc (input_location, COND_EXPR, gfc_array_index_type,
5181 cond, gfc_index_zero_node, size);
5182 size = gfc_evaluate_now (size, block);
5184 /* Allocate temporary for WHERE mask if needed. */
5185 if (need_cmask)
5186 cmask = allocate_temp_for_forall_nest_1 (mask_type, size, block,
5187 &pcmask);
5189 /* Allocate temporary for !mask if needed. */
5190 if (need_pmask)
5191 pmask = allocate_temp_for_forall_nest_1 (mask_type, size, block,
5192 &ppmask);
5195 while (cblock)
5197 /* Each time around this loop, the where clause is conditional
5198 on the value of mask and invert, which are updated at the
5199 bottom of the loop. */
5201 /* Has mask-expr. */
5202 if (cblock->expr1)
5204 /* Ensure that the WHERE mask will be evaluated exactly once.
5205 If there are no statements in this WHERE/ELSEWHERE clause,
5206 then we don't need to update the control mask (cmask).
5207 If this is the last clause of the WHERE construct, then
5208 we don't need to update the pending control mask (pmask). */
5209 if (mask)
5210 gfc_evaluate_where_mask (cblock->expr1, nested_forall_info,
5211 mask, invert,
5212 cblock->next ? cmask : NULL_TREE,
5213 cblock->block ? pmask : NULL_TREE,
5214 mask_type, block);
5215 else
5216 gfc_evaluate_where_mask (cblock->expr1, nested_forall_info,
5217 NULL_TREE, false,
5218 (cblock->next || cblock->block)
5219 ? cmask : NULL_TREE,
5220 NULL_TREE, mask_type, block);
5222 invert = false;
5224 /* It's a final elsewhere-stmt. No mask-expr is present. */
5225 else
5226 cmask = mask;
5228 /* The body of this where clause are controlled by cmask with
5229 sense specified by invert. */
5231 /* Get the assignment statement of a WHERE statement, or the first
5232 statement in where-body-construct of a WHERE construct. */
5233 cnext = cblock->next;
5234 while (cnext)
5236 switch (cnext->op)
5238 /* WHERE assignment statement. */
5239 case EXEC_ASSIGN_CALL:
5241 arg = cnext->ext.actual;
5242 expr1 = expr2 = NULL;
5243 for (; arg; arg = arg->next)
5245 if (!arg->expr)
5246 continue;
5247 if (expr1 == NULL)
5248 expr1 = arg->expr;
5249 else
5250 expr2 = arg->expr;
5252 goto evaluate;
5254 case EXEC_ASSIGN:
5255 expr1 = cnext->expr1;
5256 expr2 = cnext->expr2;
5257 evaluate:
5258 if (nested_forall_info != NULL)
5260 need_temp = gfc_check_dependency (expr1, expr2, 0);
5261 if ((need_temp || flag_test_forall_temp)
5262 && cnext->op != EXEC_ASSIGN_CALL)
5263 gfc_trans_assign_need_temp (expr1, expr2,
5264 cmask, invert,
5265 nested_forall_info, block);
5266 else
5268 /* Variables to control maskexpr. */
5269 count1 = gfc_create_var (gfc_array_index_type, "count1");
5270 count2 = gfc_create_var (gfc_array_index_type, "count2");
5271 gfc_add_modify (block, count1, gfc_index_zero_node);
5272 gfc_add_modify (block, count2, gfc_index_zero_node);
5274 tmp = gfc_trans_where_assign (expr1, expr2,
5275 cmask, invert,
5276 count1, count2,
5277 cnext);
5279 tmp = gfc_trans_nested_forall_loop (nested_forall_info,
5280 tmp, 1);
5281 gfc_add_expr_to_block (block, tmp);
5284 else
5286 /* Variables to control maskexpr. */
5287 count1 = gfc_create_var (gfc_array_index_type, "count1");
5288 count2 = gfc_create_var (gfc_array_index_type, "count2");
5289 gfc_add_modify (block, count1, gfc_index_zero_node);
5290 gfc_add_modify (block, count2, gfc_index_zero_node);
5292 tmp = gfc_trans_where_assign (expr1, expr2,
5293 cmask, invert,
5294 count1, count2,
5295 cnext);
5296 gfc_add_expr_to_block (block, tmp);
5299 break;
5301 /* WHERE or WHERE construct is part of a where-body-construct. */
5302 case EXEC_WHERE:
5303 gfc_trans_where_2 (cnext, cmask, invert,
5304 nested_forall_info, block);
5305 break;
5307 default:
5308 gcc_unreachable ();
5311 /* The next statement within the same where-body-construct. */
5312 cnext = cnext->next;
5314 /* The next masked-elsewhere-stmt, elsewhere-stmt, or end-where-stmt. */
5315 cblock = cblock->block;
5316 if (mask == NULL_TREE)
5318 /* If we're the initial WHERE, we can simply invert the sense
5319 of the current mask to obtain the "mask" for the remaining
5320 ELSEWHEREs. */
5321 invert = true;
5322 mask = cmask;
5324 else
5326 /* Otherwise, for nested WHERE's we need to use the pending mask. */
5327 invert = false;
5328 mask = pmask;
5332 /* If we allocated a pending mask array, deallocate it now. */
5333 if (ppmask)
5335 tmp = gfc_call_free (ppmask);
5336 gfc_add_expr_to_block (block, tmp);
5339 /* If we allocated a current mask array, deallocate it now. */
5340 if (pcmask)
5342 tmp = gfc_call_free (pcmask);
5343 gfc_add_expr_to_block (block, tmp);
5347 /* Translate a simple WHERE construct or statement without dependencies.
5348 CBLOCK is the "then" clause of the WHERE statement, where CBLOCK->EXPR
5349 is the mask condition, and EBLOCK if non-NULL is the "else" clause.
5350 Currently both CBLOCK and EBLOCK are restricted to single assignments. */
5352 static tree
5353 gfc_trans_where_3 (gfc_code * cblock, gfc_code * eblock)
5355 stmtblock_t block, body;
5356 gfc_expr *cond, *tdst, *tsrc, *edst, *esrc;
5357 tree tmp, cexpr, tstmt, estmt;
5358 gfc_ss *css, *tdss, *tsss;
5359 gfc_se cse, tdse, tsse, edse, esse;
5360 gfc_loopinfo loop;
5361 gfc_ss *edss = 0;
5362 gfc_ss *esss = 0;
5363 bool maybe_workshare = false;
5365 /* Allow the scalarizer to workshare simple where loops. */
5366 if ((ompws_flags & (OMPWS_WORKSHARE_FLAG | OMPWS_SCALARIZER_BODY))
5367 == OMPWS_WORKSHARE_FLAG)
5369 maybe_workshare = true;
5370 ompws_flags |= OMPWS_SCALARIZER_WS | OMPWS_SCALARIZER_BODY;
5373 cond = cblock->expr1;
5374 tdst = cblock->next->expr1;
5375 tsrc = cblock->next->expr2;
5376 edst = eblock ? eblock->next->expr1 : NULL;
5377 esrc = eblock ? eblock->next->expr2 : NULL;
5379 gfc_start_block (&block);
5380 gfc_init_loopinfo (&loop);
5382 /* Handle the condition. */
5383 gfc_init_se (&cse, NULL);
5384 css = gfc_walk_expr (cond);
5385 gfc_add_ss_to_loop (&loop, css);
5387 /* Handle the then-clause. */
5388 gfc_init_se (&tdse, NULL);
5389 gfc_init_se (&tsse, NULL);
5390 tdss = gfc_walk_expr (tdst);
5391 tsss = gfc_walk_expr (tsrc);
5392 if (tsss == gfc_ss_terminator)
5394 tsss = gfc_get_scalar_ss (gfc_ss_terminator, tsrc);
5395 tsss->info->where = 1;
5397 gfc_add_ss_to_loop (&loop, tdss);
5398 gfc_add_ss_to_loop (&loop, tsss);
5400 if (eblock)
5402 /* Handle the else clause. */
5403 gfc_init_se (&edse, NULL);
5404 gfc_init_se (&esse, NULL);
5405 edss = gfc_walk_expr (edst);
5406 esss = gfc_walk_expr (esrc);
5407 if (esss == gfc_ss_terminator)
5409 esss = gfc_get_scalar_ss (gfc_ss_terminator, esrc);
5410 esss->info->where = 1;
5412 gfc_add_ss_to_loop (&loop, edss);
5413 gfc_add_ss_to_loop (&loop, esss);
5416 gfc_conv_ss_startstride (&loop);
5417 gfc_conv_loop_setup (&loop, &tdst->where);
5419 gfc_mark_ss_chain_used (css, 1);
5420 gfc_mark_ss_chain_used (tdss, 1);
5421 gfc_mark_ss_chain_used (tsss, 1);
5422 if (eblock)
5424 gfc_mark_ss_chain_used (edss, 1);
5425 gfc_mark_ss_chain_used (esss, 1);
5428 gfc_start_scalarized_body (&loop, &body);
5430 gfc_copy_loopinfo_to_se (&cse, &loop);
5431 gfc_copy_loopinfo_to_se (&tdse, &loop);
5432 gfc_copy_loopinfo_to_se (&tsse, &loop);
5433 cse.ss = css;
5434 tdse.ss = tdss;
5435 tsse.ss = tsss;
5436 if (eblock)
5438 gfc_copy_loopinfo_to_se (&edse, &loop);
5439 gfc_copy_loopinfo_to_se (&esse, &loop);
5440 edse.ss = edss;
5441 esse.ss = esss;
5444 gfc_conv_expr (&cse, cond);
5445 gfc_add_block_to_block (&body, &cse.pre);
5446 cexpr = cse.expr;
5448 gfc_conv_expr (&tsse, tsrc);
5449 if (tdss != gfc_ss_terminator && loop.temp_ss != NULL)
5450 gfc_conv_tmp_array_ref (&tdse);
5451 else
5452 gfc_conv_expr (&tdse, tdst);
5454 if (eblock)
5456 gfc_conv_expr (&esse, esrc);
5457 if (edss != gfc_ss_terminator && loop.temp_ss != NULL)
5458 gfc_conv_tmp_array_ref (&edse);
5459 else
5460 gfc_conv_expr (&edse, edst);
5463 tstmt = gfc_trans_scalar_assign (&tdse, &tsse, tdst->ts, false, true);
5464 estmt = eblock ? gfc_trans_scalar_assign (&edse, &esse, edst->ts,
5465 false, true)
5466 : build_empty_stmt (input_location);
5467 tmp = build3_v (COND_EXPR, cexpr, tstmt, estmt);
5468 gfc_add_expr_to_block (&body, tmp);
5469 gfc_add_block_to_block (&body, &cse.post);
5471 if (maybe_workshare)
5472 ompws_flags &= ~OMPWS_SCALARIZER_BODY;
5473 gfc_trans_scalarizing_loops (&loop, &body);
5474 gfc_add_block_to_block (&block, &loop.pre);
5475 gfc_add_block_to_block (&block, &loop.post);
5476 gfc_cleanup_loop (&loop);
5478 return gfc_finish_block (&block);
5481 /* As the WHERE or WHERE construct statement can be nested, we call
5482 gfc_trans_where_2 to do the translation, and pass the initial
5483 NULL values for both the control mask and the pending control mask. */
5485 tree
5486 gfc_trans_where (gfc_code * code)
5488 stmtblock_t block;
5489 gfc_code *cblock;
5490 gfc_code *eblock;
5492 cblock = code->block;
5493 if (cblock->next
5494 && cblock->next->op == EXEC_ASSIGN
5495 && !cblock->next->next)
5497 eblock = cblock->block;
5498 if (!eblock)
5500 /* A simple "WHERE (cond) x = y" statement or block is
5501 dependence free if cond is not dependent upon writing x,
5502 and the source y is unaffected by the destination x. */
5503 if (!gfc_check_dependency (cblock->next->expr1,
5504 cblock->expr1, 0)
5505 && !gfc_check_dependency (cblock->next->expr1,
5506 cblock->next->expr2, 0))
5507 return gfc_trans_where_3 (cblock, NULL);
5509 else if (!eblock->expr1
5510 && !eblock->block
5511 && eblock->next
5512 && eblock->next->op == EXEC_ASSIGN
5513 && !eblock->next->next)
5515 /* A simple "WHERE (cond) x1 = y1 ELSEWHERE x2 = y2 ENDWHERE"
5516 block is dependence free if cond is not dependent on writes
5517 to x1 and x2, y1 is not dependent on writes to x2, and y2
5518 is not dependent on writes to x1, and both y's are not
5519 dependent upon their own x's. In addition to this, the
5520 final two dependency checks below exclude all but the same
5521 array reference if the where and elswhere destinations
5522 are the same. In short, this is VERY conservative and this
5523 is needed because the two loops, required by the standard
5524 are coalesced in gfc_trans_where_3. */
5525 if (!gfc_check_dependency (cblock->next->expr1,
5526 cblock->expr1, 0)
5527 && !gfc_check_dependency (eblock->next->expr1,
5528 cblock->expr1, 0)
5529 && !gfc_check_dependency (cblock->next->expr1,
5530 eblock->next->expr2, 1)
5531 && !gfc_check_dependency (eblock->next->expr1,
5532 cblock->next->expr2, 1)
5533 && !gfc_check_dependency (cblock->next->expr1,
5534 cblock->next->expr2, 1)
5535 && !gfc_check_dependency (eblock->next->expr1,
5536 eblock->next->expr2, 1)
5537 && !gfc_check_dependency (cblock->next->expr1,
5538 eblock->next->expr1, 0)
5539 && !gfc_check_dependency (eblock->next->expr1,
5540 cblock->next->expr1, 0))
5541 return gfc_trans_where_3 (cblock, eblock);
5545 gfc_start_block (&block);
5547 gfc_trans_where_2 (code, NULL, false, NULL, &block);
5549 return gfc_finish_block (&block);
5553 /* CYCLE a DO loop. The label decl has already been created by
5554 gfc_trans_do(), it's in TREE_PURPOSE (backend_decl) of the gfc_code
5555 node at the head of the loop. We must mark the label as used. */
5557 tree
5558 gfc_trans_cycle (gfc_code * code)
5560 tree cycle_label;
5562 cycle_label = code->ext.which_construct->cycle_label;
5563 gcc_assert (cycle_label);
5565 TREE_USED (cycle_label) = 1;
5566 return build1_v (GOTO_EXPR, cycle_label);
5570 /* EXIT a DO loop. Similar to CYCLE, but now the label is in
5571 TREE_VALUE (backend_decl) of the gfc_code node at the head of the
5572 loop. */
5574 tree
5575 gfc_trans_exit (gfc_code * code)
5577 tree exit_label;
5579 exit_label = code->ext.which_construct->exit_label;
5580 gcc_assert (exit_label);
5582 TREE_USED (exit_label) = 1;
5583 return build1_v (GOTO_EXPR, exit_label);
5587 /* Get the initializer expression for the code and expr of an allocate.
5588 When no initializer is needed return NULL. */
5590 static gfc_expr *
5591 allocate_get_initializer (gfc_code * code, gfc_expr * expr)
5593 if (!gfc_bt_struct (expr->ts.type) && expr->ts.type != BT_CLASS)
5594 return NULL;
5596 /* An explicit type was given in allocate ( T:: object). */
5597 if (code->ext.alloc.ts.type == BT_DERIVED
5598 && (code->ext.alloc.ts.u.derived->attr.alloc_comp
5599 || gfc_has_default_initializer (code->ext.alloc.ts.u.derived)))
5600 return gfc_default_initializer (&code->ext.alloc.ts);
5602 if (gfc_bt_struct (expr->ts.type)
5603 && (expr->ts.u.derived->attr.alloc_comp
5604 || gfc_has_default_initializer (expr->ts.u.derived)))
5605 return gfc_default_initializer (&expr->ts);
5607 if (expr->ts.type == BT_CLASS
5608 && (CLASS_DATA (expr)->ts.u.derived->attr.alloc_comp
5609 || gfc_has_default_initializer (CLASS_DATA (expr)->ts.u.derived)))
5610 return gfc_default_initializer (&CLASS_DATA (expr)->ts);
5612 return NULL;
5615 /* Translate the ALLOCATE statement. */
5617 tree
5618 gfc_trans_allocate (gfc_code * code)
5620 gfc_alloc *al;
5621 gfc_expr *expr, *e3rhs = NULL, *init_expr;
5622 gfc_se se, se_sz;
5623 tree tmp;
5624 tree parm;
5625 tree stat;
5626 tree errmsg;
5627 tree errlen;
5628 tree label_errmsg;
5629 tree label_finish;
5630 tree memsz;
5631 tree al_vptr, al_len;
5632 /* If an expr3 is present, then store the tree for accessing its
5633 _vptr, and _len components in the variables, respectively. The
5634 element size, i.e. _vptr%size, is stored in expr3_esize. Any of
5635 the trees may be the NULL_TREE indicating that this is not
5636 available for expr3's type. */
5637 tree expr3, expr3_vptr, expr3_len, expr3_esize;
5638 /* Classify what expr3 stores. */
5639 enum { E3_UNSET = 0, E3_SOURCE, E3_MOLD, E3_DESC } e3_is;
5640 stmtblock_t block;
5641 stmtblock_t post;
5642 tree nelems;
5643 bool upoly_expr, tmp_expr3_len_flag = false, al_len_needs_set, is_coarray;
5644 bool needs_caf_sync, caf_refs_comp;
5645 gfc_symtree *newsym = NULL;
5646 symbol_attribute caf_attr;
5647 gfc_actual_arglist *param_list;
5649 if (!code->ext.alloc.list)
5650 return NULL_TREE;
5652 stat = tmp = memsz = al_vptr = al_len = NULL_TREE;
5653 expr3 = expr3_vptr = expr3_len = expr3_esize = NULL_TREE;
5654 label_errmsg = label_finish = errmsg = errlen = NULL_TREE;
5655 e3_is = E3_UNSET;
5656 is_coarray = needs_caf_sync = false;
5658 gfc_init_block (&block);
5659 gfc_init_block (&post);
5661 /* STAT= (and maybe ERRMSG=) is present. */
5662 if (code->expr1)
5664 /* STAT=. */
5665 tree gfc_int4_type_node = gfc_get_int_type (4);
5666 stat = gfc_create_var (gfc_int4_type_node, "stat");
5668 /* ERRMSG= only makes sense with STAT=. */
5669 if (code->expr2)
5671 gfc_init_se (&se, NULL);
5672 se.want_pointer = 1;
5673 gfc_conv_expr_lhs (&se, code->expr2);
5674 errmsg = se.expr;
5675 errlen = se.string_length;
5677 else
5679 errmsg = null_pointer_node;
5680 errlen = build_int_cst (gfc_charlen_type_node, 0);
5683 /* GOTO destinations. */
5684 label_errmsg = gfc_build_label_decl (NULL_TREE);
5685 label_finish = gfc_build_label_decl (NULL_TREE);
5686 TREE_USED (label_finish) = 0;
5689 /* When an expr3 is present evaluate it only once. The standards prevent a
5690 dependency of expr3 on the objects in the allocate list. An expr3 can
5691 be pre-evaluated in all cases. One just has to make sure, to use the
5692 correct way, i.e., to get the descriptor or to get a reference
5693 expression. */
5694 if (code->expr3)
5696 bool vtab_needed = false, temp_var_needed = false,
5697 temp_obj_created = false;
5699 is_coarray = gfc_is_coarray (code->expr3);
5701 /* Figure whether we need the vtab from expr3. */
5702 for (al = code->ext.alloc.list; !vtab_needed && al != NULL;
5703 al = al->next)
5704 vtab_needed = (al->expr->ts.type == BT_CLASS);
5706 gfc_init_se (&se, NULL);
5707 /* When expr3 is a variable, i.e., a very simple expression,
5708 then convert it once here. */
5709 if (code->expr3->expr_type == EXPR_VARIABLE
5710 || code->expr3->expr_type == EXPR_ARRAY
5711 || code->expr3->expr_type == EXPR_CONSTANT)
5713 if (!code->expr3->mold
5714 || code->expr3->ts.type == BT_CHARACTER
5715 || vtab_needed
5716 || code->ext.alloc.arr_spec_from_expr3)
5718 /* Convert expr3 to a tree. For all "simple" expression just
5719 get the descriptor or the reference, respectively, depending
5720 on the rank of the expr. */
5721 if (code->ext.alloc.arr_spec_from_expr3 || code->expr3->rank != 0)
5722 gfc_conv_expr_descriptor (&se, code->expr3);
5723 else
5725 gfc_conv_expr_reference (&se, code->expr3);
5727 /* gfc_conv_expr_reference wraps POINTER_PLUS_EXPR in a
5728 NOP_EXPR, which prevents gfortran from getting the vptr
5729 from the source=-expression. Remove the NOP_EXPR and go
5730 with the POINTER_PLUS_EXPR in this case. */
5731 if (code->expr3->ts.type == BT_CLASS
5732 && TREE_CODE (se.expr) == NOP_EXPR
5733 && (TREE_CODE (TREE_OPERAND (se.expr, 0))
5734 == POINTER_PLUS_EXPR
5735 || is_coarray))
5736 se.expr = TREE_OPERAND (se.expr, 0);
5738 /* Create a temp variable only for component refs to prevent
5739 having to go through the full deref-chain each time and to
5740 simplfy computation of array properties. */
5741 temp_var_needed = TREE_CODE (se.expr) == COMPONENT_REF;
5744 else
5746 /* In all other cases evaluate the expr3. */
5747 symbol_attribute attr;
5748 /* Get the descriptor for all arrays, that are not allocatable or
5749 pointer, because the latter are descriptors already.
5750 The exception are function calls returning a class object:
5751 The descriptor is stored in their results _data component, which
5752 is easier to access, when first a temporary variable for the
5753 result is created and the descriptor retrieved from there. */
5754 attr = gfc_expr_attr (code->expr3);
5755 if (code->expr3->rank != 0
5756 && ((!attr.allocatable && !attr.pointer)
5757 || (code->expr3->expr_type == EXPR_FUNCTION
5758 && (code->expr3->ts.type != BT_CLASS
5759 || (code->expr3->value.function.isym
5760 && code->expr3->value.function.isym
5761 ->transformational)))))
5762 gfc_conv_expr_descriptor (&se, code->expr3);
5763 else
5764 gfc_conv_expr_reference (&se, code->expr3);
5765 if (code->expr3->ts.type == BT_CLASS)
5766 gfc_conv_class_to_class (&se, code->expr3,
5767 code->expr3->ts,
5768 false, true,
5769 false, false);
5770 temp_obj_created = temp_var_needed = !VAR_P (se.expr);
5772 gfc_add_block_to_block (&block, &se.pre);
5773 gfc_add_block_to_block (&post, &se.post);
5775 /* Special case when string in expr3 is zero. */
5776 if (code->expr3->ts.type == BT_CHARACTER
5777 && integer_zerop (se.string_length))
5779 gfc_init_se (&se, NULL);
5780 temp_var_needed = false;
5781 expr3_len = build_zero_cst (gfc_charlen_type_node);
5782 e3_is = E3_MOLD;
5784 /* Prevent aliasing, i.e., se.expr may be already a
5785 variable declaration. */
5786 else if (se.expr != NULL_TREE && temp_var_needed)
5788 tree var, desc;
5789 tmp = GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (se.expr)) || is_coarray ?
5790 se.expr
5791 : build_fold_indirect_ref_loc (input_location, se.expr);
5793 /* Get the array descriptor and prepare it to be assigned to the
5794 temporary variable var. For classes the array descriptor is
5795 in the _data component and the object goes into the
5796 GFC_DECL_SAVED_DESCRIPTOR. */
5797 if (code->expr3->ts.type == BT_CLASS
5798 && code->expr3->rank != 0)
5800 /* When an array_ref was in expr3, then the descriptor is the
5801 first operand. */
5802 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (tmp)) || is_coarray)
5804 desc = TREE_OPERAND (tmp, 0);
5806 else
5808 desc = tmp;
5809 tmp = gfc_class_data_get (tmp);
5811 if (code->ext.alloc.arr_spec_from_expr3)
5812 e3_is = E3_DESC;
5814 else
5815 desc = !is_coarray ? se.expr
5816 : TREE_OPERAND (TREE_OPERAND (se.expr, 0), 0);
5817 /* We need a regular (non-UID) symbol here, therefore give a
5818 prefix. */
5819 var = gfc_create_var (TREE_TYPE (tmp), "source");
5820 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (tmp)) || is_coarray)
5822 gfc_allocate_lang_decl (var);
5823 GFC_DECL_SAVED_DESCRIPTOR (var) = desc;
5825 gfc_add_modify_loc (input_location, &block, var, tmp);
5827 expr3 = var;
5828 if (se.string_length)
5829 /* Evaluate it assuming that it also is complicated like expr3. */
5830 expr3_len = gfc_evaluate_now (se.string_length, &block);
5832 else
5834 expr3 = se.expr;
5835 expr3_len = se.string_length;
5838 /* Deallocate any allocatable components in expressions that use a
5839 temporary object, i.e. are not a simple alias of to an EXPR_VARIABLE.
5840 E.g. temporaries of a function call need freeing of their components
5841 here. */
5842 if ((code->expr3->ts.type == BT_DERIVED
5843 || code->expr3->ts.type == BT_CLASS)
5844 && (code->expr3->expr_type != EXPR_VARIABLE || temp_obj_created)
5845 && code->expr3->ts.u.derived->attr.alloc_comp)
5847 tmp = gfc_deallocate_alloc_comp (code->expr3->ts.u.derived,
5848 expr3, code->expr3->rank);
5849 gfc_prepend_expr_to_block (&post, tmp);
5852 /* Store what the expr3 is to be used for. */
5853 if (e3_is == E3_UNSET)
5854 e3_is = expr3 != NULL_TREE ?
5855 (code->ext.alloc.arr_spec_from_expr3 ?
5856 E3_DESC
5857 : (code->expr3->mold ? E3_MOLD : E3_SOURCE))
5858 : E3_UNSET;
5860 /* Figure how to get the _vtab entry. This also obtains the tree
5861 expression for accessing the _len component, because only
5862 unlimited polymorphic objects, which are a subcategory of class
5863 types, have a _len component. */
5864 if (code->expr3->ts.type == BT_CLASS)
5866 gfc_expr *rhs;
5867 tmp = expr3 != NULL_TREE && POINTER_TYPE_P (TREE_TYPE (expr3)) ?
5868 build_fold_indirect_ref (expr3): expr3;
5869 /* Polymorphic SOURCE: VPTR must be determined at run time.
5870 expr3 may be a temporary array declaration, therefore check for
5871 GFC_CLASS_TYPE_P before trying to get the _vptr component. */
5872 if (tmp != NULL_TREE
5873 && (e3_is == E3_DESC
5874 || (GFC_CLASS_TYPE_P (TREE_TYPE (tmp))
5875 && (VAR_P (tmp) || !code->expr3->ref))
5876 || (VAR_P (tmp) && DECL_LANG_SPECIFIC (tmp))))
5877 tmp = gfc_class_vptr_get (expr3);
5878 else
5880 rhs = gfc_find_and_cut_at_last_class_ref (code->expr3);
5881 gfc_add_vptr_component (rhs);
5882 gfc_init_se (&se, NULL);
5883 se.want_pointer = 1;
5884 gfc_conv_expr (&se, rhs);
5885 tmp = se.expr;
5886 gfc_free_expr (rhs);
5888 /* Set the element size. */
5889 expr3_esize = gfc_vptr_size_get (tmp);
5890 if (vtab_needed)
5891 expr3_vptr = tmp;
5892 /* Initialize the ref to the _len component. */
5893 if (expr3_len == NULL_TREE && UNLIMITED_POLY (code->expr3))
5895 /* Same like for retrieving the _vptr. */
5896 if (expr3 != NULL_TREE && !code->expr3->ref)
5897 expr3_len = gfc_class_len_get (expr3);
5898 else
5900 rhs = gfc_find_and_cut_at_last_class_ref (code->expr3);
5901 gfc_add_len_component (rhs);
5902 gfc_init_se (&se, NULL);
5903 gfc_conv_expr (&se, rhs);
5904 expr3_len = se.expr;
5905 gfc_free_expr (rhs);
5909 else
5911 /* When the object to allocate is polymorphic type, then it
5912 needs its vtab set correctly, so deduce the required _vtab
5913 and _len from the source expression. */
5914 if (vtab_needed)
5916 /* VPTR is fixed at compile time. */
5917 gfc_symbol *vtab;
5919 vtab = gfc_find_vtab (&code->expr3->ts);
5920 gcc_assert (vtab);
5921 expr3_vptr = gfc_get_symbol_decl (vtab);
5922 expr3_vptr = gfc_build_addr_expr (NULL_TREE,
5923 expr3_vptr);
5925 /* _len component needs to be set, when ts is a character
5926 array. */
5927 if (expr3_len == NULL_TREE
5928 && code->expr3->ts.type == BT_CHARACTER)
5930 if (code->expr3->ts.u.cl
5931 && code->expr3->ts.u.cl->length)
5933 gfc_init_se (&se, NULL);
5934 gfc_conv_expr (&se, code->expr3->ts.u.cl->length);
5935 gfc_add_block_to_block (&block, &se.pre);
5936 expr3_len = gfc_evaluate_now (se.expr, &block);
5938 gcc_assert (expr3_len);
5940 /* For character arrays only the kind's size is needed, because
5941 the array mem_size is _len * (elem_size = kind_size).
5942 For all other get the element size in the normal way. */
5943 if (code->expr3->ts.type == BT_CHARACTER)
5944 expr3_esize = TYPE_SIZE_UNIT (
5945 gfc_get_char_type (code->expr3->ts.kind));
5946 else
5947 expr3_esize = TYPE_SIZE_UNIT (
5948 gfc_typenode_for_spec (&code->expr3->ts));
5950 gcc_assert (expr3_esize);
5951 expr3_esize = fold_convert (sizetype, expr3_esize);
5952 if (e3_is == E3_MOLD)
5953 /* The expr3 is no longer valid after this point. */
5954 expr3 = NULL_TREE;
5956 else if (code->ext.alloc.ts.type != BT_UNKNOWN)
5958 /* Compute the explicit typespec given only once for all objects
5959 to allocate. */
5960 if (code->ext.alloc.ts.type != BT_CHARACTER)
5961 expr3_esize = TYPE_SIZE_UNIT (
5962 gfc_typenode_for_spec (&code->ext.alloc.ts));
5963 else if (code->ext.alloc.ts.u.cl->length != NULL)
5965 gfc_expr *sz;
5966 sz = gfc_copy_expr (code->ext.alloc.ts.u.cl->length);
5967 gfc_init_se (&se_sz, NULL);
5968 gfc_conv_expr (&se_sz, sz);
5969 gfc_free_expr (sz);
5970 tmp = gfc_get_char_type (code->ext.alloc.ts.kind);
5971 tmp = TYPE_SIZE_UNIT (tmp);
5972 tmp = fold_convert (TREE_TYPE (se_sz.expr), tmp);
5973 gfc_add_block_to_block (&block, &se_sz.pre);
5974 expr3_esize = fold_build2_loc (input_location, MULT_EXPR,
5975 TREE_TYPE (se_sz.expr),
5976 tmp, se_sz.expr);
5977 expr3_esize = gfc_evaluate_now (expr3_esize, &block);
5979 else
5980 expr3_esize = NULL_TREE;
5983 /* The routine gfc_trans_assignment () already implements all
5984 techniques needed. Unfortunately we may have a temporary
5985 variable for the source= expression here. When that is the
5986 case convert this variable into a temporary gfc_expr of type
5987 EXPR_VARIABLE and used it as rhs for the assignment. The
5988 advantage is, that we get scalarizer support for free,
5989 don't have to take care about scalar to array treatment and
5990 will benefit of every enhancements gfc_trans_assignment ()
5991 gets.
5992 No need to check whether e3_is is E3_UNSET, because that is
5993 done by expr3 != NULL_TREE.
5994 Exclude variables since the following block does not handle
5995 array sections. In any case, there is no harm in sending
5996 variables to gfc_trans_assignment because there is no
5997 evaluation of variables. */
5998 if (code->expr3)
6000 if (code->expr3->expr_type != EXPR_VARIABLE
6001 && e3_is != E3_MOLD && expr3 != NULL_TREE
6002 && DECL_P (expr3) && DECL_ARTIFICIAL (expr3))
6004 /* Build a temporary symtree and symbol. Do not add it to the current
6005 namespace to prevent accidently modifying a colliding
6006 symbol's as. */
6007 newsym = XCNEW (gfc_symtree);
6008 /* The name of the symtree should be unique, because gfc_create_var ()
6009 took care about generating the identifier. */
6010 newsym->name
6011 = gfc_get_string ("%s", IDENTIFIER_POINTER (DECL_NAME (expr3)));
6012 newsym->n.sym = gfc_new_symbol (newsym->name, NULL);
6013 /* The backend_decl is known. It is expr3, which is inserted
6014 here. */
6015 newsym->n.sym->backend_decl = expr3;
6016 e3rhs = gfc_get_expr ();
6017 e3rhs->rank = code->expr3->rank;
6018 e3rhs->symtree = newsym;
6019 /* Mark the symbol referenced or gfc_trans_assignment will bug. */
6020 newsym->n.sym->attr.referenced = 1;
6021 e3rhs->expr_type = EXPR_VARIABLE;
6022 e3rhs->where = code->expr3->where;
6023 /* Set the symbols type, upto it was BT_UNKNOWN. */
6024 if (IS_CLASS_ARRAY (code->expr3)
6025 && code->expr3->expr_type == EXPR_FUNCTION
6026 && code->expr3->value.function.isym
6027 && code->expr3->value.function.isym->transformational)
6029 e3rhs->ts = CLASS_DATA (code->expr3)->ts;
6031 else if (code->expr3->ts.type == BT_CLASS
6032 && !GFC_CLASS_TYPE_P (TREE_TYPE (expr3)))
6033 e3rhs->ts = CLASS_DATA (code->expr3)->ts;
6034 else
6035 e3rhs->ts = code->expr3->ts;
6036 newsym->n.sym->ts = e3rhs->ts;
6037 /* Check whether the expr3 is array valued. */
6038 if (e3rhs->rank)
6040 gfc_array_spec *arr;
6041 arr = gfc_get_array_spec ();
6042 arr->rank = e3rhs->rank;
6043 arr->type = AS_DEFERRED;
6044 /* Set the dimension and pointer attribute for arrays
6045 to be on the safe side. */
6046 newsym->n.sym->attr.dimension = 1;
6047 newsym->n.sym->attr.pointer = 1;
6048 newsym->n.sym->as = arr;
6049 if (IS_CLASS_ARRAY (code->expr3)
6050 && code->expr3->expr_type == EXPR_FUNCTION
6051 && code->expr3->value.function.isym
6052 && code->expr3->value.function.isym->transformational)
6054 gfc_array_spec *tarr;
6055 tarr = gfc_get_array_spec ();
6056 *tarr = *arr;
6057 e3rhs->ts.u.derived->as = tarr;
6059 gfc_add_full_array_ref (e3rhs, arr);
6061 else if (POINTER_TYPE_P (TREE_TYPE (expr3)))
6062 newsym->n.sym->attr.pointer = 1;
6063 /* The string length is known, too. Set it for char arrays. */
6064 if (e3rhs->ts.type == BT_CHARACTER)
6065 newsym->n.sym->ts.u.cl->backend_decl = expr3_len;
6066 gfc_commit_symbol (newsym->n.sym);
6068 else
6069 e3rhs = gfc_copy_expr (code->expr3);
6072 /* Loop over all objects to allocate. */
6073 for (al = code->ext.alloc.list; al != NULL; al = al->next)
6075 expr = gfc_copy_expr (al->expr);
6076 /* UNLIMITED_POLY () needs the _data component to be set, when
6077 expr is a unlimited polymorphic object. But the _data component
6078 has not been set yet, so check the derived type's attr for the
6079 unlimited polymorphic flag to be safe. */
6080 upoly_expr = UNLIMITED_POLY (expr)
6081 || (expr->ts.type == BT_DERIVED
6082 && expr->ts.u.derived->attr.unlimited_polymorphic);
6083 gfc_init_se (&se, NULL);
6085 /* For class types prepare the expressions to ref the _vptr
6086 and the _len component. The latter for unlimited polymorphic
6087 types only. */
6088 if (expr->ts.type == BT_CLASS)
6090 gfc_expr *expr_ref_vptr, *expr_ref_len;
6091 gfc_add_data_component (expr);
6092 /* Prep the vptr handle. */
6093 expr_ref_vptr = gfc_copy_expr (al->expr);
6094 gfc_add_vptr_component (expr_ref_vptr);
6095 se.want_pointer = 1;
6096 gfc_conv_expr (&se, expr_ref_vptr);
6097 al_vptr = se.expr;
6098 se.want_pointer = 0;
6099 gfc_free_expr (expr_ref_vptr);
6100 /* Allocated unlimited polymorphic objects always have a _len
6101 component. */
6102 if (upoly_expr)
6104 expr_ref_len = gfc_copy_expr (al->expr);
6105 gfc_add_len_component (expr_ref_len);
6106 gfc_conv_expr (&se, expr_ref_len);
6107 al_len = se.expr;
6108 gfc_free_expr (expr_ref_len);
6110 else
6111 /* In a loop ensure that all loop variable dependent variables
6112 are initialized at the same spot in all execution paths. */
6113 al_len = NULL_TREE;
6115 else
6116 al_vptr = al_len = NULL_TREE;
6118 se.want_pointer = 1;
6119 se.descriptor_only = 1;
6121 gfc_conv_expr (&se, expr);
6122 if (expr->ts.type == BT_CHARACTER && expr->ts.deferred)
6123 /* se.string_length now stores the .string_length variable of expr
6124 needed to allocate character(len=:) arrays. */
6125 al_len = se.string_length;
6127 al_len_needs_set = al_len != NULL_TREE;
6128 /* When allocating an array one can not use much of the
6129 pre-evaluated expr3 expressions, because for most of them the
6130 scalarizer is needed which is not available in the pre-evaluation
6131 step. Therefore gfc_array_allocate () is responsible (and able)
6132 to handle the complete array allocation. Only the element size
6133 needs to be provided, which is done most of the time by the
6134 pre-evaluation step. */
6135 nelems = NULL_TREE;
6136 if (expr3_len && (code->expr3->ts.type == BT_CHARACTER
6137 || code->expr3->ts.type == BT_CLASS))
6139 /* When al is an array, then the element size for each element
6140 in the array is needed, which is the product of the len and
6141 esize for char arrays. For unlimited polymorphics len can be
6142 zero, therefore take the maximum of len and one. */
6143 tmp = fold_build2_loc (input_location, MAX_EXPR,
6144 TREE_TYPE (expr3_len),
6145 expr3_len, fold_convert (TREE_TYPE (expr3_len),
6146 integer_one_node));
6147 tmp = fold_build2_loc (input_location, MULT_EXPR,
6148 TREE_TYPE (expr3_esize), expr3_esize,
6149 fold_convert (TREE_TYPE (expr3_esize), tmp));
6151 else
6152 tmp = expr3_esize;
6153 if (!gfc_array_allocate (&se, expr, stat, errmsg, errlen,
6154 label_finish, tmp, &nelems,
6155 e3rhs ? e3rhs : code->expr3,
6156 e3_is == E3_DESC ? expr3 : NULL_TREE,
6157 code->expr3 != NULL && e3_is == E3_DESC
6158 && code->expr3->expr_type == EXPR_ARRAY))
6160 /* A scalar or derived type. First compute the size to
6161 allocate.
6163 expr3_len is set when expr3 is an unlimited polymorphic
6164 object or a deferred length string. */
6165 if (expr3_len != NULL_TREE)
6167 tmp = fold_convert (TREE_TYPE (expr3_esize), expr3_len);
6168 tmp = fold_build2_loc (input_location, MULT_EXPR,
6169 TREE_TYPE (expr3_esize),
6170 expr3_esize, tmp);
6171 if (code->expr3->ts.type != BT_CLASS)
6172 /* expr3 is a deferred length string, i.e., we are
6173 done. */
6174 memsz = tmp;
6175 else
6177 /* For unlimited polymorphic enties build
6178 (len > 0) ? element_size * len : element_size
6179 to compute the number of bytes to allocate.
6180 This allows the allocation of unlimited polymorphic
6181 objects from an expr3 that is also unlimited
6182 polymorphic and stores a _len dependent object,
6183 e.g., a string. */
6184 memsz = fold_build2_loc (input_location, GT_EXPR,
6185 logical_type_node, expr3_len,
6186 build_zero_cst
6187 (TREE_TYPE (expr3_len)));
6188 memsz = fold_build3_loc (input_location, COND_EXPR,
6189 TREE_TYPE (expr3_esize),
6190 memsz, tmp, expr3_esize);
6193 else if (expr3_esize != NULL_TREE)
6194 /* Any other object in expr3 just needs element size in
6195 bytes. */
6196 memsz = expr3_esize;
6197 else if ((expr->ts.type == BT_CHARACTER && expr->ts.deferred)
6198 || (upoly_expr
6199 && code->ext.alloc.ts.type == BT_CHARACTER))
6201 /* Allocating deferred length char arrays need the length
6202 to allocate in the alloc_type_spec. But also unlimited
6203 polymorphic objects may be allocated as char arrays.
6204 Both are handled here. */
6205 gfc_init_se (&se_sz, NULL);
6206 gfc_conv_expr (&se_sz, code->ext.alloc.ts.u.cl->length);
6207 gfc_add_block_to_block (&se.pre, &se_sz.pre);
6208 se_sz.expr = gfc_evaluate_now (se_sz.expr, &se.pre);
6209 gfc_add_block_to_block (&se.pre, &se_sz.post);
6210 expr3_len = se_sz.expr;
6211 tmp_expr3_len_flag = true;
6212 tmp = TYPE_SIZE_UNIT (
6213 gfc_get_char_type (code->ext.alloc.ts.kind));
6214 memsz = fold_build2_loc (input_location, MULT_EXPR,
6215 TREE_TYPE (tmp),
6216 fold_convert (TREE_TYPE (tmp),
6217 expr3_len),
6218 tmp);
6220 else if (expr->ts.type == BT_CHARACTER)
6222 /* Compute the number of bytes needed to allocate a fixed
6223 length char array. */
6224 gcc_assert (se.string_length != NULL_TREE);
6225 tmp = TYPE_SIZE_UNIT (gfc_get_char_type (expr->ts.kind));
6226 memsz = fold_build2_loc (input_location, MULT_EXPR,
6227 TREE_TYPE (tmp), tmp,
6228 fold_convert (TREE_TYPE (tmp),
6229 se.string_length));
6231 else if (code->ext.alloc.ts.type != BT_UNKNOWN)
6232 /* Handle all types, where the alloc_type_spec is set. */
6233 memsz = TYPE_SIZE_UNIT (gfc_typenode_for_spec (&code->ext.alloc.ts));
6234 else
6235 /* Handle size computation of the type declared to alloc. */
6236 memsz = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (se.expr)));
6238 /* Store the caf-attributes for latter use. */
6239 if (flag_coarray == GFC_FCOARRAY_LIB
6240 && (caf_attr = gfc_caf_attr (expr, true, &caf_refs_comp))
6241 .codimension)
6243 /* Scalar allocatable components in coarray'ed derived types make
6244 it here and are treated now. */
6245 tree caf_decl, token;
6246 gfc_se caf_se;
6248 is_coarray = true;
6249 /* Set flag, to add synchronize after the allocate. */
6250 needs_caf_sync = needs_caf_sync
6251 || caf_attr.coarray_comp || !caf_refs_comp;
6253 gfc_init_se (&caf_se, NULL);
6255 caf_decl = gfc_get_tree_for_caf_expr (expr);
6256 gfc_get_caf_token_offset (&caf_se, &token, NULL, caf_decl,
6257 NULL_TREE, NULL);
6258 gfc_add_block_to_block (&se.pre, &caf_se.pre);
6259 gfc_allocate_allocatable (&se.pre, se.expr, memsz,
6260 gfc_build_addr_expr (NULL_TREE, token),
6261 NULL_TREE, NULL_TREE, NULL_TREE,
6262 label_finish, expr, 1);
6264 /* Allocate - for non-pointers with re-alloc checking. */
6265 else if (gfc_expr_attr (expr).allocatable)
6266 gfc_allocate_allocatable (&se.pre, se.expr, memsz,
6267 NULL_TREE, stat, errmsg, errlen,
6268 label_finish, expr, 0);
6269 else
6270 gfc_allocate_using_malloc (&se.pre, se.expr, memsz, stat);
6272 else
6274 /* Allocating coarrays needs a sync after the allocate executed.
6275 Set the flag to add the sync after all objects are allocated. */
6276 if (flag_coarray == GFC_FCOARRAY_LIB
6277 && (caf_attr = gfc_caf_attr (expr, true, &caf_refs_comp))
6278 .codimension)
6280 is_coarray = true;
6281 needs_caf_sync = needs_caf_sync
6282 || caf_attr.coarray_comp || !caf_refs_comp;
6285 if (expr->ts.type == BT_CHARACTER && al_len != NULL_TREE
6286 && expr3_len != NULL_TREE)
6288 /* Arrays need to have a _len set before the array
6289 descriptor is filled. */
6290 gfc_add_modify (&block, al_len,
6291 fold_convert (TREE_TYPE (al_len), expr3_len));
6292 /* Prevent setting the length twice. */
6293 al_len_needs_set = false;
6295 else if (expr->ts.type == BT_CHARACTER && al_len != NULL_TREE
6296 && code->ext.alloc.ts.u.cl->length)
6298 /* Cover the cases where a string length is explicitly
6299 specified by a type spec for deferred length character
6300 arrays or unlimited polymorphic objects without a
6301 source= or mold= expression. */
6302 gfc_init_se (&se_sz, NULL);
6303 gfc_conv_expr (&se_sz, code->ext.alloc.ts.u.cl->length);
6304 gfc_add_block_to_block (&block, &se_sz.pre);
6305 gfc_add_modify (&block, al_len,
6306 fold_convert (TREE_TYPE (al_len),
6307 se_sz.expr));
6308 al_len_needs_set = false;
6312 gfc_add_block_to_block (&block, &se.pre);
6314 /* Error checking -- Note: ERRMSG only makes sense with STAT. */
6315 if (code->expr1)
6317 tmp = build1_v (GOTO_EXPR, label_errmsg);
6318 parm = fold_build2_loc (input_location, NE_EXPR,
6319 logical_type_node, stat,
6320 build_int_cst (TREE_TYPE (stat), 0));
6321 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
6322 gfc_unlikely (parm, PRED_FORTRAN_FAIL_ALLOC),
6323 tmp, build_empty_stmt (input_location));
6324 gfc_add_expr_to_block (&block, tmp);
6327 /* Set the vptr only when no source= is set. When source= is set, then
6328 the trans_assignment below will set the vptr. */
6329 if (al_vptr != NULL_TREE && (!code->expr3 || code->expr3->mold))
6331 if (expr3_vptr != NULL_TREE)
6332 /* The vtab is already known, so just assign it. */
6333 gfc_add_modify (&block, al_vptr,
6334 fold_convert (TREE_TYPE (al_vptr), expr3_vptr));
6335 else
6337 /* VPTR is fixed at compile time. */
6338 gfc_symbol *vtab;
6339 gfc_typespec *ts;
6341 if (code->expr3)
6342 /* Although expr3 is pre-evaluated above, it may happen,
6343 that for arrays or in mold= cases the pre-evaluation
6344 was not successful. In these rare cases take the vtab
6345 from the typespec of expr3 here. */
6346 ts = &code->expr3->ts;
6347 else if (code->ext.alloc.ts.type == BT_DERIVED || upoly_expr)
6348 /* The alloc_type_spec gives the type to allocate or the
6349 al is unlimited polymorphic, which enforces the use of
6350 an alloc_type_spec that is not necessarily a BT_DERIVED. */
6351 ts = &code->ext.alloc.ts;
6352 else
6353 /* Prepare for setting the vtab as declared. */
6354 ts = &expr->ts;
6356 vtab = gfc_find_vtab (ts);
6357 gcc_assert (vtab);
6358 tmp = gfc_build_addr_expr (NULL_TREE,
6359 gfc_get_symbol_decl (vtab));
6360 gfc_add_modify (&block, al_vptr,
6361 fold_convert (TREE_TYPE (al_vptr), tmp));
6365 /* Add assignment for string length. */
6366 if (al_len != NULL_TREE && al_len_needs_set)
6368 if (expr3_len != NULL_TREE)
6370 gfc_add_modify (&block, al_len,
6371 fold_convert (TREE_TYPE (al_len),
6372 expr3_len));
6373 /* When tmp_expr3_len_flag is set, then expr3_len is
6374 abused to carry the length information from the
6375 alloc_type. Clear it to prevent setting incorrect len
6376 information in future loop iterations. */
6377 if (tmp_expr3_len_flag)
6378 /* No need to reset tmp_expr3_len_flag, because the
6379 presence of an expr3 can not change within in the
6380 loop. */
6381 expr3_len = NULL_TREE;
6383 else if (code->ext.alloc.ts.type == BT_CHARACTER
6384 && code->ext.alloc.ts.u.cl->length)
6386 /* Cover the cases where a string length is explicitly
6387 specified by a type spec for deferred length character
6388 arrays or unlimited polymorphic objects without a
6389 source= or mold= expression. */
6390 if (expr3_esize == NULL_TREE || code->ext.alloc.ts.kind != 1)
6392 gfc_init_se (&se_sz, NULL);
6393 gfc_conv_expr (&se_sz, code->ext.alloc.ts.u.cl->length);
6394 gfc_add_block_to_block (&block, &se_sz.pre);
6395 gfc_add_modify (&block, al_len,
6396 fold_convert (TREE_TYPE (al_len),
6397 se_sz.expr));
6399 else
6400 gfc_add_modify (&block, al_len,
6401 fold_convert (TREE_TYPE (al_len),
6402 expr3_esize));
6404 else
6405 /* No length information needed, because type to allocate
6406 has no length. Set _len to 0. */
6407 gfc_add_modify (&block, al_len,
6408 fold_convert (TREE_TYPE (al_len),
6409 integer_zero_node));
6412 init_expr = NULL;
6413 if (code->expr3 && !code->expr3->mold && e3_is != E3_MOLD)
6415 /* Initialization via SOURCE block (or static default initializer).
6416 Switch off automatic reallocation since we have just done the
6417 ALLOCATE. */
6418 int realloc_lhs = flag_realloc_lhs;
6419 gfc_expr *init_expr = gfc_expr_to_initialize (expr);
6420 gfc_expr *rhs = e3rhs ? e3rhs : gfc_copy_expr (code->expr3);
6421 flag_realloc_lhs = 0;
6422 tmp = gfc_trans_assignment (init_expr, rhs, false, false, true,
6423 false);
6424 flag_realloc_lhs = realloc_lhs;
6425 /* Free the expression allocated for init_expr. */
6426 gfc_free_expr (init_expr);
6427 if (rhs != e3rhs)
6428 gfc_free_expr (rhs);
6429 gfc_add_expr_to_block (&block, tmp);
6431 /* Set KIND and LEN PDT components and allocate those that are
6432 parameterized. */
6433 else if (expr->ts.type == BT_DERIVED
6434 && expr->ts.u.derived->attr.pdt_type)
6436 if (code->expr3 && code->expr3->param_list)
6437 param_list = code->expr3->param_list;
6438 else if (expr->param_list)
6439 param_list = expr->param_list;
6440 else
6441 param_list = expr->symtree->n.sym->param_list;
6442 tmp = gfc_allocate_pdt_comp (expr->ts.u.derived, se.expr,
6443 expr->rank, param_list);
6444 gfc_add_expr_to_block (&block, tmp);
6446 /* Ditto for CLASS expressions. */
6447 else if (expr->ts.type == BT_CLASS
6448 && CLASS_DATA (expr)->ts.u.derived->attr.pdt_type)
6450 if (code->expr3 && code->expr3->param_list)
6451 param_list = code->expr3->param_list;
6452 else if (expr->param_list)
6453 param_list = expr->param_list;
6454 else
6455 param_list = expr->symtree->n.sym->param_list;
6456 tmp = gfc_allocate_pdt_comp (CLASS_DATA (expr)->ts.u.derived,
6457 se.expr, expr->rank, param_list);
6458 gfc_add_expr_to_block (&block, tmp);
6460 else if (code->expr3 && code->expr3->mold
6461 && code->expr3->ts.type == BT_CLASS)
6463 /* Use class_init_assign to initialize expr. */
6464 gfc_code *ini;
6465 ini = gfc_get_code (EXEC_INIT_ASSIGN);
6466 ini->expr1 = gfc_find_and_cut_at_last_class_ref (expr);
6467 tmp = gfc_trans_class_init_assign (ini);
6468 gfc_free_statements (ini);
6469 gfc_add_expr_to_block (&block, tmp);
6471 else if ((init_expr = allocate_get_initializer (code, expr)))
6473 /* Use class_init_assign to initialize expr. */
6474 gfc_code *ini;
6475 int realloc_lhs = flag_realloc_lhs;
6476 ini = gfc_get_code (EXEC_INIT_ASSIGN);
6477 ini->expr1 = gfc_expr_to_initialize (expr);
6478 ini->expr2 = init_expr;
6479 flag_realloc_lhs = 0;
6480 tmp= gfc_trans_init_assign (ini);
6481 flag_realloc_lhs = realloc_lhs;
6482 gfc_free_statements (ini);
6483 /* Init_expr is freeed by above free_statements, just need to null
6484 it here. */
6485 init_expr = NULL;
6486 gfc_add_expr_to_block (&block, tmp);
6489 /* Nullify all pointers in derived type coarrays. This registers a
6490 token for them which allows their allocation. */
6491 if (is_coarray)
6493 gfc_symbol *type = NULL;
6494 symbol_attribute caf_attr;
6495 int rank = 0;
6496 if (code->ext.alloc.ts.type == BT_DERIVED
6497 && code->ext.alloc.ts.u.derived->attr.pointer_comp)
6499 type = code->ext.alloc.ts.u.derived;
6500 rank = type->attr.dimension ? type->as->rank : 0;
6501 gfc_clear_attr (&caf_attr);
6503 else if (expr->ts.type == BT_DERIVED
6504 && expr->ts.u.derived->attr.pointer_comp)
6506 type = expr->ts.u.derived;
6507 rank = expr->rank;
6508 caf_attr = gfc_caf_attr (expr, true);
6511 /* Initialize the tokens of pointer components in derived type
6512 coarrays. */
6513 if (type)
6515 tmp = (caf_attr.codimension && !caf_attr.dimension)
6516 ? gfc_conv_descriptor_data_get (se.expr) : se.expr;
6517 tmp = gfc_nullify_alloc_comp (type, tmp, rank,
6518 GFC_STRUCTURE_CAF_MODE_IN_COARRAY);
6519 gfc_add_expr_to_block (&block, tmp);
6523 gfc_free_expr (expr);
6524 } // for-loop
6526 if (e3rhs)
6528 if (newsym)
6530 gfc_free_symbol (newsym->n.sym);
6531 XDELETE (newsym);
6533 gfc_free_expr (e3rhs);
6535 /* STAT. */
6536 if (code->expr1)
6538 tmp = build1_v (LABEL_EXPR, label_errmsg);
6539 gfc_add_expr_to_block (&block, tmp);
6542 /* ERRMSG - only useful if STAT is present. */
6543 if (code->expr1 && code->expr2)
6545 const char *msg = "Attempt to allocate an allocated object";
6546 tree slen, dlen, errmsg_str;
6547 stmtblock_t errmsg_block;
6549 gfc_init_block (&errmsg_block);
6551 errmsg_str = gfc_create_var (pchar_type_node, "ERRMSG");
6552 gfc_add_modify (&errmsg_block, errmsg_str,
6553 gfc_build_addr_expr (pchar_type_node,
6554 gfc_build_localized_cstring_const (msg)));
6556 slen = build_int_cst (gfc_charlen_type_node, strlen (msg));
6557 dlen = gfc_get_expr_charlen (code->expr2);
6558 slen = fold_build2_loc (input_location, MIN_EXPR,
6559 TREE_TYPE (slen), dlen, slen);
6561 gfc_trans_string_copy (&errmsg_block, dlen, errmsg,
6562 code->expr2->ts.kind,
6563 slen, errmsg_str,
6564 gfc_default_character_kind);
6565 dlen = gfc_finish_block (&errmsg_block);
6567 tmp = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
6568 stat, build_int_cst (TREE_TYPE (stat), 0));
6570 tmp = build3_v (COND_EXPR, tmp,
6571 dlen, build_empty_stmt (input_location));
6573 gfc_add_expr_to_block (&block, tmp);
6576 /* STAT block. */
6577 if (code->expr1)
6579 if (TREE_USED (label_finish))
6581 tmp = build1_v (LABEL_EXPR, label_finish);
6582 gfc_add_expr_to_block (&block, tmp);
6585 gfc_init_se (&se, NULL);
6586 gfc_conv_expr_lhs (&se, code->expr1);
6587 tmp = convert (TREE_TYPE (se.expr), stat);
6588 gfc_add_modify (&block, se.expr, tmp);
6591 if (needs_caf_sync)
6593 /* Add a sync all after the allocation has been executed. */
6594 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sync_all,
6595 3, null_pointer_node, null_pointer_node,
6596 integer_zero_node);
6597 gfc_add_expr_to_block (&post, tmp);
6600 gfc_add_block_to_block (&block, &se.post);
6601 gfc_add_block_to_block (&block, &post);
6603 return gfc_finish_block (&block);
6607 /* Translate a DEALLOCATE statement. */
6609 tree
6610 gfc_trans_deallocate (gfc_code *code)
6612 gfc_se se;
6613 gfc_alloc *al;
6614 tree apstat, pstat, stat, errmsg, errlen, tmp;
6615 tree label_finish, label_errmsg;
6616 stmtblock_t block;
6618 pstat = apstat = stat = errmsg = errlen = tmp = NULL_TREE;
6619 label_finish = label_errmsg = NULL_TREE;
6621 gfc_start_block (&block);
6623 /* Count the number of failed deallocations. If deallocate() was
6624 called with STAT= , then set STAT to the count. If deallocate
6625 was called with ERRMSG, then set ERRMG to a string. */
6626 if (code->expr1)
6628 tree gfc_int4_type_node = gfc_get_int_type (4);
6630 stat = gfc_create_var (gfc_int4_type_node, "stat");
6631 pstat = gfc_build_addr_expr (NULL_TREE, stat);
6633 /* GOTO destinations. */
6634 label_errmsg = gfc_build_label_decl (NULL_TREE);
6635 label_finish = gfc_build_label_decl (NULL_TREE);
6636 TREE_USED (label_finish) = 0;
6639 /* Set ERRMSG - only needed if STAT is available. */
6640 if (code->expr1 && code->expr2)
6642 gfc_init_se (&se, NULL);
6643 se.want_pointer = 1;
6644 gfc_conv_expr_lhs (&se, code->expr2);
6645 errmsg = se.expr;
6646 errlen = se.string_length;
6649 for (al = code->ext.alloc.list; al != NULL; al = al->next)
6651 gfc_expr *expr = gfc_copy_expr (al->expr);
6652 bool is_coarray = false, is_coarray_array = false;
6653 int caf_mode = 0;
6655 gcc_assert (expr->expr_type == EXPR_VARIABLE);
6657 if (expr->ts.type == BT_CLASS)
6658 gfc_add_data_component (expr);
6660 gfc_init_se (&se, NULL);
6661 gfc_start_block (&se.pre);
6663 se.want_pointer = 1;
6664 se.descriptor_only = 1;
6665 gfc_conv_expr (&se, expr);
6667 /* Deallocate PDT components that are parameterized. */
6668 tmp = NULL;
6669 if (expr->ts.type == BT_DERIVED
6670 && expr->ts.u.derived->attr.pdt_type
6671 && expr->symtree->n.sym->param_list)
6672 tmp = gfc_deallocate_pdt_comp (expr->ts.u.derived, se.expr, expr->rank);
6673 else if (expr->ts.type == BT_CLASS
6674 && CLASS_DATA (expr)->ts.u.derived->attr.pdt_type
6675 && expr->symtree->n.sym->param_list)
6676 tmp = gfc_deallocate_pdt_comp (CLASS_DATA (expr)->ts.u.derived,
6677 se.expr, expr->rank);
6679 if (tmp)
6680 gfc_add_expr_to_block (&block, tmp);
6682 if (flag_coarray == GFC_FCOARRAY_LIB
6683 || flag_coarray == GFC_FCOARRAY_SINGLE)
6685 bool comp_ref;
6686 symbol_attribute caf_attr = gfc_caf_attr (expr, false, &comp_ref);
6687 if (caf_attr.codimension)
6689 is_coarray = true;
6690 is_coarray_array = caf_attr.dimension || !comp_ref
6691 || caf_attr.coarray_comp;
6693 if (flag_coarray == GFC_FCOARRAY_LIB)
6694 /* When the expression to deallocate is referencing a
6695 component, then only deallocate it, but do not
6696 deregister. */
6697 caf_mode = GFC_STRUCTURE_CAF_MODE_IN_COARRAY
6698 | (comp_ref && !caf_attr.coarray_comp
6699 ? GFC_STRUCTURE_CAF_MODE_DEALLOC_ONLY : 0);
6703 if (expr->rank || is_coarray_array)
6705 gfc_ref *ref;
6707 if (gfc_bt_struct (expr->ts.type)
6708 && expr->ts.u.derived->attr.alloc_comp
6709 && !gfc_is_finalizable (expr->ts.u.derived, NULL))
6711 gfc_ref *last = NULL;
6713 for (ref = expr->ref; ref; ref = ref->next)
6714 if (ref->type == REF_COMPONENT)
6715 last = ref;
6717 /* Do not deallocate the components of a derived type
6718 ultimate pointer component. */
6719 if (!(last && last->u.c.component->attr.pointer)
6720 && !(!last && expr->symtree->n.sym->attr.pointer))
6722 if (is_coarray && expr->rank == 0
6723 && (!last || !last->u.c.component->attr.dimension)
6724 && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (se.expr)))
6726 /* Add the ref to the data member only, when this is not
6727 a regular array or deallocate_alloc_comp will try to
6728 add another one. */
6729 tmp = gfc_conv_descriptor_data_get (se.expr);
6731 else
6732 tmp = se.expr;
6733 tmp = gfc_deallocate_alloc_comp (expr->ts.u.derived, tmp,
6734 expr->rank, caf_mode);
6735 gfc_add_expr_to_block (&se.pre, tmp);
6739 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (se.expr)))
6741 gfc_coarray_deregtype caf_dtype;
6743 if (is_coarray)
6744 caf_dtype = gfc_caf_is_dealloc_only (caf_mode)
6745 ? GFC_CAF_COARRAY_DEALLOCATE_ONLY
6746 : GFC_CAF_COARRAY_DEREGISTER;
6747 else
6748 caf_dtype = GFC_CAF_COARRAY_NOCOARRAY;
6749 tmp = gfc_deallocate_with_status (se.expr, pstat, errmsg, errlen,
6750 label_finish, false, expr,
6751 caf_dtype);
6752 gfc_add_expr_to_block (&se.pre, tmp);
6754 else if (TREE_CODE (se.expr) == COMPONENT_REF
6755 && TREE_CODE (TREE_TYPE (se.expr)) == ARRAY_TYPE
6756 && TREE_CODE (TREE_TYPE (TREE_TYPE (se.expr)))
6757 == RECORD_TYPE)
6759 /* class.c(finalize_component) generates these, when a
6760 finalizable entity has a non-allocatable derived type array
6761 component, which has allocatable components. Obtain the
6762 derived type of the array and deallocate the allocatable
6763 components. */
6764 for (ref = expr->ref; ref; ref = ref->next)
6766 if (ref->u.c.component->attr.dimension
6767 && ref->u.c.component->ts.type == BT_DERIVED)
6768 break;
6771 if (ref && ref->u.c.component->ts.u.derived->attr.alloc_comp
6772 && !gfc_is_finalizable (ref->u.c.component->ts.u.derived,
6773 NULL))
6775 tmp = gfc_deallocate_alloc_comp
6776 (ref->u.c.component->ts.u.derived,
6777 se.expr, expr->rank);
6778 gfc_add_expr_to_block (&se.pre, tmp);
6782 if (al->expr->ts.type == BT_CLASS)
6784 gfc_reset_vptr (&se.pre, al->expr);
6785 if (UNLIMITED_POLY (al->expr)
6786 || (al->expr->ts.type == BT_DERIVED
6787 && al->expr->ts.u.derived->attr.unlimited_polymorphic))
6788 /* Clear _len, too. */
6789 gfc_reset_len (&se.pre, al->expr);
6792 else
6794 tmp = gfc_deallocate_scalar_with_status (se.expr, pstat, label_finish,
6795 false, al->expr,
6796 al->expr->ts, is_coarray);
6797 gfc_add_expr_to_block (&se.pre, tmp);
6799 /* Set to zero after deallocation. */
6800 tmp = fold_build2_loc (input_location, MODIFY_EXPR, void_type_node,
6801 se.expr,
6802 build_int_cst (TREE_TYPE (se.expr), 0));
6803 gfc_add_expr_to_block (&se.pre, tmp);
6805 if (al->expr->ts.type == BT_CLASS)
6807 gfc_reset_vptr (&se.pre, al->expr);
6808 if (UNLIMITED_POLY (al->expr)
6809 || (al->expr->ts.type == BT_DERIVED
6810 && al->expr->ts.u.derived->attr.unlimited_polymorphic))
6811 /* Clear _len, too. */
6812 gfc_reset_len (&se.pre, al->expr);
6816 if (code->expr1)
6818 tree cond;
6820 cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node, stat,
6821 build_int_cst (TREE_TYPE (stat), 0));
6822 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
6823 gfc_unlikely (cond, PRED_FORTRAN_FAIL_ALLOC),
6824 build1_v (GOTO_EXPR, label_errmsg),
6825 build_empty_stmt (input_location));
6826 gfc_add_expr_to_block (&se.pre, tmp);
6829 tmp = gfc_finish_block (&se.pre);
6830 gfc_add_expr_to_block (&block, tmp);
6831 gfc_free_expr (expr);
6834 if (code->expr1)
6836 tmp = build1_v (LABEL_EXPR, label_errmsg);
6837 gfc_add_expr_to_block (&block, tmp);
6840 /* Set ERRMSG - only needed if STAT is available. */
6841 if (code->expr1 && code->expr2)
6843 const char *msg = "Attempt to deallocate an unallocated object";
6844 stmtblock_t errmsg_block;
6845 tree errmsg_str, slen, dlen, cond;
6847 gfc_init_block (&errmsg_block);
6849 errmsg_str = gfc_create_var (pchar_type_node, "ERRMSG");
6850 gfc_add_modify (&errmsg_block, errmsg_str,
6851 gfc_build_addr_expr (pchar_type_node,
6852 gfc_build_localized_cstring_const (msg)));
6853 slen = build_int_cst (gfc_charlen_type_node, strlen (msg));
6854 dlen = gfc_get_expr_charlen (code->expr2);
6856 gfc_trans_string_copy (&errmsg_block, dlen, errmsg, code->expr2->ts.kind,
6857 slen, errmsg_str, gfc_default_character_kind);
6858 tmp = gfc_finish_block (&errmsg_block);
6860 cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node, stat,
6861 build_int_cst (TREE_TYPE (stat), 0));
6862 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
6863 gfc_unlikely (cond, PRED_FORTRAN_FAIL_ALLOC), tmp,
6864 build_empty_stmt (input_location));
6866 gfc_add_expr_to_block (&block, tmp);
6869 if (code->expr1 && TREE_USED (label_finish))
6871 tmp = build1_v (LABEL_EXPR, label_finish);
6872 gfc_add_expr_to_block (&block, tmp);
6875 /* Set STAT. */
6876 if (code->expr1)
6878 gfc_init_se (&se, NULL);
6879 gfc_conv_expr_lhs (&se, code->expr1);
6880 tmp = convert (TREE_TYPE (se.expr), stat);
6881 gfc_add_modify (&block, se.expr, tmp);
6884 return gfc_finish_block (&block);
6887 #include "gt-fortran-trans-stmt.h"