PR target/60504
[official-gcc.git] / gcc / fortran / trans-stmt.c
blob1a9068c0f466a36eb928b34f1607766515f952e8
1 /* Statement translation -- generate GCC trees from gfc_code.
2 Copyright (C) 2002-2014 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 "tree.h"
27 #include "stringpool.h"
28 #include "gfortran.h"
29 #include "flags.h"
30 #include "trans.h"
31 #include "trans-stmt.h"
32 #include "trans-types.h"
33 #include "trans-array.h"
34 #include "trans-const.h"
35 #include "arith.h"
36 #include "dependency.h"
37 #include "ggc.h"
39 typedef struct iter_info
41 tree var;
42 tree start;
43 tree end;
44 tree step;
45 struct iter_info *next;
47 iter_info;
49 typedef struct forall_info
51 iter_info *this_loop;
52 tree mask;
53 tree maskindex;
54 int nvar;
55 tree size;
56 struct forall_info *prev_nest;
57 bool do_concurrent;
59 forall_info;
61 static void gfc_trans_where_2 (gfc_code *, tree, bool,
62 forall_info *, stmtblock_t *);
64 /* Translate a F95 label number to a LABEL_EXPR. */
66 tree
67 gfc_trans_label_here (gfc_code * code)
69 return build1_v (LABEL_EXPR, gfc_get_label_decl (code->here));
73 /* Given a variable expression which has been ASSIGNed to, find the decl
74 containing the auxiliary variables. For variables in common blocks this
75 is a field_decl. */
77 void
78 gfc_conv_label_variable (gfc_se * se, gfc_expr * expr)
80 gcc_assert (expr->symtree->n.sym->attr.assign == 1);
81 gfc_conv_expr (se, expr);
82 /* Deals with variable in common block. Get the field declaration. */
83 if (TREE_CODE (se->expr) == COMPONENT_REF)
84 se->expr = TREE_OPERAND (se->expr, 1);
85 /* Deals with dummy argument. Get the parameter declaration. */
86 else if (TREE_CODE (se->expr) == INDIRECT_REF)
87 se->expr = TREE_OPERAND (se->expr, 0);
90 /* Translate a label assignment statement. */
92 tree
93 gfc_trans_label_assign (gfc_code * code)
95 tree label_tree;
96 gfc_se se;
97 tree len;
98 tree addr;
99 tree len_tree;
100 int label_len;
102 /* Start a new block. */
103 gfc_init_se (&se, NULL);
104 gfc_start_block (&se.pre);
105 gfc_conv_label_variable (&se, code->expr1);
107 len = GFC_DECL_STRING_LEN (se.expr);
108 addr = GFC_DECL_ASSIGN_ADDR (se.expr);
110 label_tree = gfc_get_label_decl (code->label1);
112 if (code->label1->defined == ST_LABEL_TARGET
113 || code->label1->defined == ST_LABEL_DO_TARGET)
115 label_tree = gfc_build_addr_expr (pvoid_type_node, label_tree);
116 len_tree = integer_minus_one_node;
118 else
120 gfc_expr *format = code->label1->format;
122 label_len = format->value.character.length;
123 len_tree = build_int_cst (gfc_charlen_type_node, label_len);
124 label_tree = gfc_build_wide_string_const (format->ts.kind, label_len + 1,
125 format->value.character.string);
126 label_tree = gfc_build_addr_expr (pvoid_type_node, label_tree);
129 gfc_add_modify (&se.pre, len, len_tree);
130 gfc_add_modify (&se.pre, addr, label_tree);
132 return gfc_finish_block (&se.pre);
135 /* Translate a GOTO statement. */
137 tree
138 gfc_trans_goto (gfc_code * code)
140 locus loc = code->loc;
141 tree assigned_goto;
142 tree target;
143 tree tmp;
144 gfc_se se;
146 if (code->label1 != NULL)
147 return build1_v (GOTO_EXPR, gfc_get_label_decl (code->label1));
149 /* ASSIGNED GOTO. */
150 gfc_init_se (&se, NULL);
151 gfc_start_block (&se.pre);
152 gfc_conv_label_variable (&se, code->expr1);
153 tmp = GFC_DECL_STRING_LEN (se.expr);
154 tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, tmp,
155 build_int_cst (TREE_TYPE (tmp), -1));
156 gfc_trans_runtime_check (true, false, tmp, &se.pre, &loc,
157 "Assigned label is not a target label");
159 assigned_goto = GFC_DECL_ASSIGN_ADDR (se.expr);
161 /* We're going to ignore a label list. It does not really change the
162 statement's semantics (because it is just a further restriction on
163 what's legal code); before, we were comparing label addresses here, but
164 that's a very fragile business and may break with optimization. So
165 just ignore it. */
167 target = fold_build1_loc (input_location, GOTO_EXPR, void_type_node,
168 assigned_goto);
169 gfc_add_expr_to_block (&se.pre, target);
170 return gfc_finish_block (&se.pre);
174 /* Translate an ENTRY statement. Just adds a label for this entry point. */
175 tree
176 gfc_trans_entry (gfc_code * code)
178 return build1_v (LABEL_EXPR, code->ext.entry->label);
182 /* Replace a gfc_ss structure by another both in the gfc_se struct
183 and the gfc_loopinfo struct. This is used in gfc_conv_elemental_dependencies
184 to replace a variable ss by the corresponding temporary. */
186 static void
187 replace_ss (gfc_se *se, gfc_ss *old_ss, gfc_ss *new_ss)
189 gfc_ss **sess, **loopss;
191 /* The old_ss is a ss for a single variable. */
192 gcc_assert (old_ss->info->type == GFC_SS_SECTION);
194 for (sess = &(se->ss); *sess != gfc_ss_terminator; sess = &((*sess)->next))
195 if (*sess == old_ss)
196 break;
197 gcc_assert (*sess != gfc_ss_terminator);
199 *sess = new_ss;
200 new_ss->next = old_ss->next;
203 for (loopss = &(se->loop->ss); *loopss != gfc_ss_terminator;
204 loopss = &((*loopss)->loop_chain))
205 if (*loopss == old_ss)
206 break;
207 gcc_assert (*loopss != gfc_ss_terminator);
209 *loopss = new_ss;
210 new_ss->loop_chain = old_ss->loop_chain;
211 new_ss->loop = old_ss->loop;
213 gfc_free_ss (old_ss);
217 /* Check for dependencies between INTENT(IN) and INTENT(OUT) arguments of
218 elemental subroutines. Make temporaries for output arguments if any such
219 dependencies are found. Output arguments are chosen because internal_unpack
220 can be used, as is, to copy the result back to the variable. */
221 static void
222 gfc_conv_elemental_dependencies (gfc_se * se, gfc_se * loopse,
223 gfc_symbol * sym, gfc_actual_arglist * arg,
224 gfc_dep_check check_variable)
226 gfc_actual_arglist *arg0;
227 gfc_expr *e;
228 gfc_formal_arglist *formal;
229 gfc_se parmse;
230 gfc_ss *ss;
231 gfc_symbol *fsym;
232 tree data;
233 tree size;
234 tree tmp;
236 if (loopse->ss == NULL)
237 return;
239 ss = loopse->ss;
240 arg0 = arg;
241 formal = gfc_sym_get_dummy_args (sym);
243 /* Loop over all the arguments testing for dependencies. */
244 for (; arg != NULL; arg = arg->next, formal = formal ? formal->next : NULL)
246 e = arg->expr;
247 if (e == NULL)
248 continue;
250 /* Obtain the info structure for the current argument. */
251 for (ss = loopse->ss; ss && ss != gfc_ss_terminator; ss = ss->next)
252 if (ss->info->expr == e)
253 break;
255 /* If there is a dependency, create a temporary and use it
256 instead of the variable. */
257 fsym = formal ? formal->sym : NULL;
258 if (e->expr_type == EXPR_VARIABLE
259 && e->rank && fsym
260 && fsym->attr.intent != INTENT_IN
261 && gfc_check_fncall_dependency (e, fsym->attr.intent,
262 sym, arg0, check_variable))
264 tree initial, temptype;
265 stmtblock_t temp_post;
266 gfc_ss *tmp_ss;
268 tmp_ss = gfc_get_array_ss (gfc_ss_terminator, NULL, ss->dimen,
269 GFC_SS_SECTION);
270 gfc_mark_ss_chain_used (tmp_ss, 1);
271 tmp_ss->info->expr = ss->info->expr;
272 replace_ss (loopse, ss, tmp_ss);
274 /* Obtain the argument descriptor for unpacking. */
275 gfc_init_se (&parmse, NULL);
276 parmse.want_pointer = 1;
277 gfc_conv_expr_descriptor (&parmse, e);
278 gfc_add_block_to_block (&se->pre, &parmse.pre);
280 /* If we've got INTENT(INOUT) or a derived type with INTENT(OUT),
281 initialize the array temporary with a copy of the values. */
282 if (fsym->attr.intent == INTENT_INOUT
283 || (fsym->ts.type ==BT_DERIVED
284 && fsym->attr.intent == INTENT_OUT))
285 initial = parmse.expr;
286 /* For class expressions, we always initialize with the copy of
287 the values. */
288 else if (e->ts.type == BT_CLASS)
289 initial = parmse.expr;
290 else
291 initial = NULL_TREE;
293 if (e->ts.type != BT_CLASS)
295 /* Find the type of the temporary to create; we don't use the type
296 of e itself as this breaks for subcomponent-references in e
297 (where the type of e is that of the final reference, but
298 parmse.expr's type corresponds to the full derived-type). */
299 /* TODO: Fix this somehow so we don't need a temporary of the whole
300 array but instead only the components referenced. */
301 temptype = TREE_TYPE (parmse.expr); /* Pointer to descriptor. */
302 gcc_assert (TREE_CODE (temptype) == POINTER_TYPE);
303 temptype = TREE_TYPE (temptype);
304 temptype = gfc_get_element_type (temptype);
307 else
308 /* For class arrays signal that the size of the dynamic type has to
309 be obtained from the vtable, using the 'initial' expression. */
310 temptype = NULL_TREE;
312 /* Generate the temporary. Cleaning up the temporary should be the
313 very last thing done, so we add the code to a new block and add it
314 to se->post as last instructions. */
315 size = gfc_create_var (gfc_array_index_type, NULL);
316 data = gfc_create_var (pvoid_type_node, NULL);
317 gfc_init_block (&temp_post);
318 tmp = gfc_trans_create_temp_array (&se->pre, &temp_post, tmp_ss,
319 temptype, initial, false, true,
320 false, &arg->expr->where);
321 gfc_add_modify (&se->pre, size, tmp);
322 tmp = fold_convert (pvoid_type_node, tmp_ss->info->data.array.data);
323 gfc_add_modify (&se->pre, data, tmp);
325 /* Update other ss' delta. */
326 gfc_set_delta (loopse->loop);
328 /* Copy the result back using unpack..... */
329 if (e->ts.type != BT_CLASS)
330 tmp = build_call_expr_loc (input_location,
331 gfor_fndecl_in_unpack, 2, parmse.expr, data);
332 else
334 /* ... except for class results where the copy is
335 unconditional. */
336 tmp = build_fold_indirect_ref_loc (input_location, parmse.expr);
337 tmp = gfc_conv_descriptor_data_get (tmp);
338 tmp = build_call_expr_loc (input_location,
339 builtin_decl_explicit (BUILT_IN_MEMCPY),
340 3, tmp, data,
341 fold_convert (size_type_node, size));
343 gfc_add_expr_to_block (&se->post, tmp);
345 /* parmse.pre is already added above. */
346 gfc_add_block_to_block (&se->post, &parmse.post);
347 gfc_add_block_to_block (&se->post, &temp_post);
353 /* Get the interface symbol for the procedure corresponding to the given call.
354 We can't get the procedure symbol directly as we have to handle the case
355 of (deferred) type-bound procedures. */
357 static gfc_symbol *
358 get_proc_ifc_for_call (gfc_code *c)
360 gfc_symbol *sym;
362 gcc_assert (c->op == EXEC_ASSIGN_CALL || c->op == EXEC_CALL);
364 sym = gfc_get_proc_ifc_for_expr (c->expr1);
366 /* Fall back/last resort try. */
367 if (sym == NULL)
368 sym = c->resolved_sym;
370 return sym;
374 /* Translate the CALL statement. Builds a call to an F95 subroutine. */
376 tree
377 gfc_trans_call (gfc_code * code, bool dependency_check,
378 tree mask, tree count1, bool invert)
380 gfc_se se;
381 gfc_ss * ss;
382 int has_alternate_specifier;
383 gfc_dep_check check_variable;
384 tree index = NULL_TREE;
385 tree maskexpr = NULL_TREE;
386 tree tmp;
388 /* A CALL starts a new block because the actual arguments may have to
389 be evaluated first. */
390 gfc_init_se (&se, NULL);
391 gfc_start_block (&se.pre);
393 gcc_assert (code->resolved_sym);
395 ss = gfc_ss_terminator;
396 if (code->resolved_sym->attr.elemental)
397 ss = gfc_walk_elemental_function_args (ss, code->ext.actual,
398 get_proc_ifc_for_call (code),
399 GFC_SS_REFERENCE);
401 /* Is not an elemental subroutine call with array valued arguments. */
402 if (ss == gfc_ss_terminator)
405 /* Translate the call. */
406 has_alternate_specifier
407 = gfc_conv_procedure_call (&se, code->resolved_sym, code->ext.actual,
408 code->expr1, NULL);
410 /* A subroutine without side-effect, by definition, does nothing! */
411 TREE_SIDE_EFFECTS (se.expr) = 1;
413 /* Chain the pieces together and return the block. */
414 if (has_alternate_specifier)
416 gfc_code *select_code;
417 gfc_symbol *sym;
418 select_code = code->next;
419 gcc_assert(select_code->op == EXEC_SELECT);
420 sym = select_code->expr1->symtree->n.sym;
421 se.expr = convert (gfc_typenode_for_spec (&sym->ts), se.expr);
422 if (sym->backend_decl == NULL)
423 sym->backend_decl = gfc_get_symbol_decl (sym);
424 gfc_add_modify (&se.pre, sym->backend_decl, se.expr);
426 else
427 gfc_add_expr_to_block (&se.pre, se.expr);
429 gfc_add_block_to_block (&se.pre, &se.post);
432 else
434 /* An elemental subroutine call with array valued arguments has
435 to be scalarized. */
436 gfc_loopinfo loop;
437 stmtblock_t body;
438 stmtblock_t block;
439 gfc_se loopse;
440 gfc_se depse;
442 /* gfc_walk_elemental_function_args renders the ss chain in the
443 reverse order to the actual argument order. */
444 ss = gfc_reverse_ss (ss);
446 /* Initialize the loop. */
447 gfc_init_se (&loopse, NULL);
448 gfc_init_loopinfo (&loop);
449 gfc_add_ss_to_loop (&loop, ss);
451 gfc_conv_ss_startstride (&loop);
452 /* TODO: gfc_conv_loop_setup generates a temporary for vector
453 subscripts. This could be prevented in the elemental case
454 as temporaries are handled separatedly
455 (below in gfc_conv_elemental_dependencies). */
456 gfc_conv_loop_setup (&loop, &code->expr1->where);
457 gfc_mark_ss_chain_used (ss, 1);
459 /* Convert the arguments, checking for dependencies. */
460 gfc_copy_loopinfo_to_se (&loopse, &loop);
461 loopse.ss = ss;
463 /* For operator assignment, do dependency checking. */
464 if (dependency_check)
465 check_variable = ELEM_CHECK_VARIABLE;
466 else
467 check_variable = ELEM_DONT_CHECK_VARIABLE;
469 gfc_init_se (&depse, NULL);
470 gfc_conv_elemental_dependencies (&depse, &loopse, code->resolved_sym,
471 code->ext.actual, check_variable);
473 gfc_add_block_to_block (&loop.pre, &depse.pre);
474 gfc_add_block_to_block (&loop.post, &depse.post);
476 /* Generate the loop body. */
477 gfc_start_scalarized_body (&loop, &body);
478 gfc_init_block (&block);
480 if (mask && count1)
482 /* Form the mask expression according to the mask. */
483 index = count1;
484 maskexpr = gfc_build_array_ref (mask, index, NULL);
485 if (invert)
486 maskexpr = fold_build1_loc (input_location, TRUTH_NOT_EXPR,
487 TREE_TYPE (maskexpr), maskexpr);
490 /* Add the subroutine call to the block. */
491 gfc_conv_procedure_call (&loopse, code->resolved_sym,
492 code->ext.actual, code->expr1,
493 NULL);
495 if (mask && count1)
497 tmp = build3_v (COND_EXPR, maskexpr, loopse.expr,
498 build_empty_stmt (input_location));
499 gfc_add_expr_to_block (&loopse.pre, tmp);
500 tmp = fold_build2_loc (input_location, PLUS_EXPR,
501 gfc_array_index_type,
502 count1, gfc_index_one_node);
503 gfc_add_modify (&loopse.pre, count1, tmp);
505 else
506 gfc_add_expr_to_block (&loopse.pre, loopse.expr);
508 gfc_add_block_to_block (&block, &loopse.pre);
509 gfc_add_block_to_block (&block, &loopse.post);
511 /* Finish up the loop block and the loop. */
512 gfc_add_expr_to_block (&body, gfc_finish_block (&block));
513 gfc_trans_scalarizing_loops (&loop, &body);
514 gfc_add_block_to_block (&se.pre, &loop.pre);
515 gfc_add_block_to_block (&se.pre, &loop.post);
516 gfc_add_block_to_block (&se.pre, &se.post);
517 gfc_cleanup_loop (&loop);
520 return gfc_finish_block (&se.pre);
524 /* Translate the RETURN statement. */
526 tree
527 gfc_trans_return (gfc_code * code)
529 if (code->expr1)
531 gfc_se se;
532 tree tmp;
533 tree result;
535 /* If code->expr is not NULL, this return statement must appear
536 in a subroutine and current_fake_result_decl has already
537 been generated. */
539 result = gfc_get_fake_result_decl (NULL, 0);
540 if (!result)
542 gfc_warning ("An alternate return at %L without a * dummy argument",
543 &code->expr1->where);
544 return gfc_generate_return ();
547 /* Start a new block for this statement. */
548 gfc_init_se (&se, NULL);
549 gfc_start_block (&se.pre);
551 gfc_conv_expr (&se, code->expr1);
553 /* Note that the actually returned expression is a simple value and
554 does not depend on any pointers or such; thus we can clean-up with
555 se.post before returning. */
556 tmp = fold_build2_loc (input_location, MODIFY_EXPR, TREE_TYPE (result),
557 result, fold_convert (TREE_TYPE (result),
558 se.expr));
559 gfc_add_expr_to_block (&se.pre, tmp);
560 gfc_add_block_to_block (&se.pre, &se.post);
562 tmp = gfc_generate_return ();
563 gfc_add_expr_to_block (&se.pre, tmp);
564 return gfc_finish_block (&se.pre);
567 return gfc_generate_return ();
571 /* Translate the PAUSE statement. We have to translate this statement
572 to a runtime library call. */
574 tree
575 gfc_trans_pause (gfc_code * code)
577 tree gfc_int4_type_node = gfc_get_int_type (4);
578 gfc_se se;
579 tree tmp;
581 /* Start a new block for this statement. */
582 gfc_init_se (&se, NULL);
583 gfc_start_block (&se.pre);
586 if (code->expr1 == NULL)
588 tmp = build_int_cst (gfc_int4_type_node, 0);
589 tmp = build_call_expr_loc (input_location,
590 gfor_fndecl_pause_string, 2,
591 build_int_cst (pchar_type_node, 0), tmp);
593 else if (code->expr1->ts.type == BT_INTEGER)
595 gfc_conv_expr (&se, code->expr1);
596 tmp = build_call_expr_loc (input_location,
597 gfor_fndecl_pause_numeric, 1,
598 fold_convert (gfc_int4_type_node, se.expr));
600 else
602 gfc_conv_expr_reference (&se, code->expr1);
603 tmp = build_call_expr_loc (input_location,
604 gfor_fndecl_pause_string, 2,
605 se.expr, se.string_length);
608 gfc_add_expr_to_block (&se.pre, tmp);
610 gfc_add_block_to_block (&se.pre, &se.post);
612 return gfc_finish_block (&se.pre);
616 /* Translate the STOP statement. We have to translate this statement
617 to a runtime library call. */
619 tree
620 gfc_trans_stop (gfc_code *code, bool error_stop)
622 tree gfc_int4_type_node = gfc_get_int_type (4);
623 gfc_se se;
624 tree tmp;
626 /* Start a new block for this statement. */
627 gfc_init_se (&se, NULL);
628 gfc_start_block (&se.pre);
630 if (gfc_option.coarray == GFC_FCOARRAY_LIB && !error_stop)
632 /* Per F2008, 8.5.1 STOP implies a SYNC MEMORY. */
633 tmp = builtin_decl_explicit (BUILT_IN_SYNC_SYNCHRONIZE);
634 tmp = build_call_expr_loc (input_location, tmp, 0);
635 gfc_add_expr_to_block (&se.pre, tmp);
637 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_finalize, 0);
638 gfc_add_expr_to_block (&se.pre, tmp);
641 if (code->expr1 == NULL)
643 tmp = build_int_cst (gfc_int4_type_node, 0);
644 tmp = build_call_expr_loc (input_location,
645 error_stop
646 ? (gfc_option.coarray == GFC_FCOARRAY_LIB
647 ? gfor_fndecl_caf_error_stop_str
648 : gfor_fndecl_error_stop_string)
649 : gfor_fndecl_stop_string,
650 2, build_int_cst (pchar_type_node, 0), tmp);
652 else if (code->expr1->ts.type == BT_INTEGER)
654 gfc_conv_expr (&se, code->expr1);
655 tmp = build_call_expr_loc (input_location,
656 error_stop
657 ? (gfc_option.coarray == GFC_FCOARRAY_LIB
658 ? gfor_fndecl_caf_error_stop
659 : gfor_fndecl_error_stop_numeric)
660 : gfor_fndecl_stop_numeric_f08, 1,
661 fold_convert (gfc_int4_type_node, se.expr));
663 else
665 gfc_conv_expr_reference (&se, code->expr1);
666 tmp = build_call_expr_loc (input_location,
667 error_stop
668 ? (gfc_option.coarray == GFC_FCOARRAY_LIB
669 ? gfor_fndecl_caf_error_stop_str
670 : gfor_fndecl_error_stop_string)
671 : gfor_fndecl_stop_string,
672 2, se.expr, se.string_length);
675 gfc_add_expr_to_block (&se.pre, tmp);
677 gfc_add_block_to_block (&se.pre, &se.post);
679 return gfc_finish_block (&se.pre);
683 tree
684 gfc_trans_lock_unlock (gfc_code *code, gfc_exec_op type ATTRIBUTE_UNUSED)
686 gfc_se se, argse;
687 tree stat = NULL_TREE, lock_acquired = NULL_TREE;
689 /* Short cut: For single images without STAT= or LOCK_ACQUIRED
690 return early. (ERRMSG= is always untouched for -fcoarray=single.) */
691 if (!code->expr2 && !code->expr4 && gfc_option.coarray != GFC_FCOARRAY_LIB)
692 return NULL_TREE;
694 gfc_init_se (&se, NULL);
695 gfc_start_block (&se.pre);
697 if (code->expr2)
699 gcc_assert (code->expr2->expr_type == EXPR_VARIABLE);
700 gfc_init_se (&argse, NULL);
701 gfc_conv_expr_val (&argse, code->expr2);
702 stat = argse.expr;
705 if (code->expr4)
707 gcc_assert (code->expr4->expr_type == EXPR_VARIABLE);
708 gfc_init_se (&argse, NULL);
709 gfc_conv_expr_val (&argse, code->expr4);
710 lock_acquired = argse.expr;
713 if (stat != NULL_TREE)
714 gfc_add_modify (&se.pre, stat, build_int_cst (TREE_TYPE (stat), 0));
716 if (lock_acquired != NULL_TREE)
717 gfc_add_modify (&se.pre, lock_acquired,
718 fold_convert (TREE_TYPE (lock_acquired),
719 boolean_true_node));
721 return gfc_finish_block (&se.pre);
725 tree
726 gfc_trans_sync (gfc_code *code, gfc_exec_op type)
728 gfc_se se, argse;
729 tree tmp;
730 tree images = NULL_TREE, stat = NULL_TREE,
731 errmsg = NULL_TREE, errmsglen = NULL_TREE;
733 /* Short cut: For single images without bound checking or without STAT=,
734 return early. (ERRMSG= is always untouched for -fcoarray=single.) */
735 if (!code->expr2 && !(gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
736 && gfc_option.coarray != GFC_FCOARRAY_LIB)
737 return NULL_TREE;
739 gfc_init_se (&se, NULL);
740 gfc_start_block (&se.pre);
742 if (code->expr1 && code->expr1->rank == 0)
744 gfc_init_se (&argse, NULL);
745 gfc_conv_expr_val (&argse, code->expr1);
746 images = argse.expr;
749 if (code->expr2)
751 gcc_assert (code->expr2->expr_type == EXPR_VARIABLE);
752 gfc_init_se (&argse, NULL);
753 gfc_conv_expr_val (&argse, code->expr2);
754 stat = argse.expr;
756 else
757 stat = null_pointer_node;
759 if (code->expr3 && gfc_option.coarray == GFC_FCOARRAY_LIB
760 && type != EXEC_SYNC_MEMORY)
762 gcc_assert (code->expr3->expr_type == EXPR_VARIABLE);
763 gfc_init_se (&argse, NULL);
764 gfc_conv_expr (&argse, code->expr3);
765 gfc_conv_string_parameter (&argse);
766 errmsg = gfc_build_addr_expr (NULL, argse.expr);
767 errmsglen = argse.string_length;
769 else if (gfc_option.coarray == GFC_FCOARRAY_LIB && type != EXEC_SYNC_MEMORY)
771 errmsg = null_pointer_node;
772 errmsglen = build_int_cst (integer_type_node, 0);
775 /* Check SYNC IMAGES(imageset) for valid image index.
776 FIXME: Add a check for image-set arrays. */
777 if (code->expr1 && (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
778 && code->expr1->rank == 0)
780 tree cond;
781 if (gfc_option.coarray != GFC_FCOARRAY_LIB)
782 cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
783 images, build_int_cst (TREE_TYPE (images), 1));
784 else
786 tree cond2;
787 cond = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
788 images, gfort_gvar_caf_num_images);
789 cond2 = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
790 images,
791 build_int_cst (TREE_TYPE (images), 1));
792 cond = fold_build2_loc (input_location, TRUTH_OR_EXPR,
793 boolean_type_node, cond, cond2);
795 gfc_trans_runtime_check (true, false, cond, &se.pre,
796 &code->expr1->where, "Invalid image number "
797 "%d in SYNC IMAGES",
798 fold_convert (integer_type_node, images));
801 /* Per F2008, 8.5.1, a SYNC MEMORY is implied by calling the
802 image control statements SYNC IMAGES and SYNC ALL. */
803 if (gfc_option.coarray == GFC_FCOARRAY_LIB)
805 tmp = builtin_decl_explicit (BUILT_IN_SYNC_SYNCHRONIZE);
806 tmp = build_call_expr_loc (input_location, tmp, 0);
807 gfc_add_expr_to_block (&se.pre, tmp);
810 if (gfc_option.coarray != GFC_FCOARRAY_LIB || type == EXEC_SYNC_MEMORY)
812 /* Set STAT to zero. */
813 if (code->expr2)
814 gfc_add_modify (&se.pre, stat, build_int_cst (TREE_TYPE (stat), 0));
816 else if (type == EXEC_SYNC_ALL)
818 /* SYNC ALL => stat == null_pointer_node
819 SYNC ALL(stat=s) => stat has an integer type
821 If "stat" has the wrong integer type, use a temp variable of
822 the right type and later cast the result back into "stat". */
823 if (stat == null_pointer_node || TREE_TYPE (stat) == integer_type_node)
825 if (TREE_TYPE (stat) == integer_type_node)
826 stat = gfc_build_addr_expr (NULL, stat);
828 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sync_all,
829 3, stat, errmsg, errmsglen);
830 gfc_add_expr_to_block (&se.pre, tmp);
832 else
834 tree tmp_stat = gfc_create_var (integer_type_node, "stat");
836 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sync_all,
837 3, gfc_build_addr_expr (NULL, tmp_stat),
838 errmsg, errmsglen);
839 gfc_add_expr_to_block (&se.pre, tmp);
841 gfc_add_modify (&se.pre, stat,
842 fold_convert (TREE_TYPE (stat), tmp_stat));
845 else
847 tree len;
849 gcc_assert (type == EXEC_SYNC_IMAGES);
851 if (!code->expr1)
853 len = build_int_cst (integer_type_node, -1);
854 images = null_pointer_node;
856 else if (code->expr1->rank == 0)
858 len = build_int_cst (integer_type_node, 1);
859 images = gfc_build_addr_expr (NULL_TREE, images);
861 else
863 /* FIXME. */
864 if (code->expr1->ts.kind != gfc_c_int_kind)
865 gfc_fatal_error ("Sorry, only support for integer kind %d "
866 "implemented for image-set at %L",
867 gfc_c_int_kind, &code->expr1->where);
869 gfc_conv_array_parameter (&se, code->expr1, true, NULL, NULL, &len);
870 images = se.expr;
872 tmp = gfc_typenode_for_spec (&code->expr1->ts);
873 if (GFC_ARRAY_TYPE_P (tmp) || GFC_DESCRIPTOR_TYPE_P (tmp))
874 tmp = gfc_get_element_type (tmp);
876 len = fold_build2_loc (input_location, TRUNC_DIV_EXPR,
877 TREE_TYPE (len), len,
878 fold_convert (TREE_TYPE (len),
879 TYPE_SIZE_UNIT (tmp)));
880 len = fold_convert (integer_type_node, len);
883 /* SYNC IMAGES(imgs) => stat == null_pointer_node
884 SYNC IMAGES(imgs,stat=s) => stat has an integer type
886 If "stat" has the wrong integer type, use a temp variable of
887 the right type and later cast the result back into "stat". */
888 if (stat == null_pointer_node || TREE_TYPE (stat) == integer_type_node)
890 if (TREE_TYPE (stat) == integer_type_node)
891 stat = gfc_build_addr_expr (NULL, stat);
893 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sync_images,
894 5, fold_convert (integer_type_node, len),
895 images, stat, errmsg, errmsglen);
896 gfc_add_expr_to_block (&se.pre, tmp);
898 else
900 tree tmp_stat = gfc_create_var (integer_type_node, "stat");
902 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sync_images,
903 5, fold_convert (integer_type_node, len),
904 images, gfc_build_addr_expr (NULL, tmp_stat),
905 errmsg, errmsglen);
906 gfc_add_expr_to_block (&se.pre, tmp);
908 gfc_add_modify (&se.pre, stat,
909 fold_convert (TREE_TYPE (stat), tmp_stat));
913 return gfc_finish_block (&se.pre);
917 /* Generate GENERIC for the IF construct. This function also deals with
918 the simple IF statement, because the front end translates the IF
919 statement into an IF construct.
921 We translate:
923 IF (cond) THEN
924 then_clause
925 ELSEIF (cond2)
926 elseif_clause
927 ELSE
928 else_clause
929 ENDIF
931 into:
933 pre_cond_s;
934 if (cond_s)
936 then_clause;
938 else
940 pre_cond_s
941 if (cond_s)
943 elseif_clause
945 else
947 else_clause;
951 where COND_S is the simplified version of the predicate. PRE_COND_S
952 are the pre side-effects produced by the translation of the
953 conditional.
954 We need to build the chain recursively otherwise we run into
955 problems with folding incomplete statements. */
957 static tree
958 gfc_trans_if_1 (gfc_code * code)
960 gfc_se if_se;
961 tree stmt, elsestmt;
962 locus saved_loc;
963 location_t loc;
965 /* Check for an unconditional ELSE clause. */
966 if (!code->expr1)
967 return gfc_trans_code (code->next);
969 /* Initialize a statement builder for each block. Puts in NULL_TREEs. */
970 gfc_init_se (&if_se, NULL);
971 gfc_start_block (&if_se.pre);
973 /* Calculate the IF condition expression. */
974 if (code->expr1->where.lb)
976 gfc_save_backend_locus (&saved_loc);
977 gfc_set_backend_locus (&code->expr1->where);
980 gfc_conv_expr_val (&if_se, code->expr1);
982 if (code->expr1->where.lb)
983 gfc_restore_backend_locus (&saved_loc);
985 /* Translate the THEN clause. */
986 stmt = gfc_trans_code (code->next);
988 /* Translate the ELSE clause. */
989 if (code->block)
990 elsestmt = gfc_trans_if_1 (code->block);
991 else
992 elsestmt = build_empty_stmt (input_location);
994 /* Build the condition expression and add it to the condition block. */
995 loc = code->expr1->where.lb ? code->expr1->where.lb->location : input_location;
996 stmt = fold_build3_loc (loc, COND_EXPR, void_type_node, if_se.expr, stmt,
997 elsestmt);
999 gfc_add_expr_to_block (&if_se.pre, stmt);
1001 /* Finish off this statement. */
1002 return gfc_finish_block (&if_se.pre);
1005 tree
1006 gfc_trans_if (gfc_code * code)
1008 stmtblock_t body;
1009 tree exit_label;
1011 /* Create exit label so it is available for trans'ing the body code. */
1012 exit_label = gfc_build_label_decl (NULL_TREE);
1013 code->exit_label = exit_label;
1015 /* Translate the actual code in code->block. */
1016 gfc_init_block (&body);
1017 gfc_add_expr_to_block (&body, gfc_trans_if_1 (code->block));
1019 /* Add exit label. */
1020 gfc_add_expr_to_block (&body, build1_v (LABEL_EXPR, exit_label));
1022 return gfc_finish_block (&body);
1026 /* Translate an arithmetic IF expression.
1028 IF (cond) label1, label2, label3 translates to
1030 if (cond <= 0)
1032 if (cond < 0)
1033 goto label1;
1034 else // cond == 0
1035 goto label2;
1037 else // cond > 0
1038 goto label3;
1040 An optimized version can be generated in case of equal labels.
1041 E.g., if label1 is equal to label2, we can translate it to
1043 if (cond <= 0)
1044 goto label1;
1045 else
1046 goto label3;
1049 tree
1050 gfc_trans_arithmetic_if (gfc_code * code)
1052 gfc_se se;
1053 tree tmp;
1054 tree branch1;
1055 tree branch2;
1056 tree zero;
1058 /* Start a new block. */
1059 gfc_init_se (&se, NULL);
1060 gfc_start_block (&se.pre);
1062 /* Pre-evaluate COND. */
1063 gfc_conv_expr_val (&se, code->expr1);
1064 se.expr = gfc_evaluate_now (se.expr, &se.pre);
1066 /* Build something to compare with. */
1067 zero = gfc_build_const (TREE_TYPE (se.expr), integer_zero_node);
1069 if (code->label1->value != code->label2->value)
1071 /* If (cond < 0) take branch1 else take branch2.
1072 First build jumps to the COND .LT. 0 and the COND .EQ. 0 cases. */
1073 branch1 = build1_v (GOTO_EXPR, gfc_get_label_decl (code->label1));
1074 branch2 = build1_v (GOTO_EXPR, gfc_get_label_decl (code->label2));
1076 if (code->label1->value != code->label3->value)
1077 tmp = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
1078 se.expr, zero);
1079 else
1080 tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
1081 se.expr, zero);
1083 branch1 = fold_build3_loc (input_location, COND_EXPR, void_type_node,
1084 tmp, branch1, branch2);
1086 else
1087 branch1 = build1_v (GOTO_EXPR, gfc_get_label_decl (code->label1));
1089 if (code->label1->value != code->label3->value
1090 && code->label2->value != code->label3->value)
1092 /* if (cond <= 0) take branch1 else take branch2. */
1093 branch2 = build1_v (GOTO_EXPR, gfc_get_label_decl (code->label3));
1094 tmp = fold_build2_loc (input_location, LE_EXPR, boolean_type_node,
1095 se.expr, zero);
1096 branch1 = fold_build3_loc (input_location, COND_EXPR, void_type_node,
1097 tmp, branch1, branch2);
1100 /* Append the COND_EXPR to the evaluation of COND, and return. */
1101 gfc_add_expr_to_block (&se.pre, branch1);
1102 return gfc_finish_block (&se.pre);
1106 /* Translate a CRITICAL block. */
1107 tree
1108 gfc_trans_critical (gfc_code *code)
1110 stmtblock_t block;
1111 tree tmp;
1113 gfc_start_block (&block);
1115 if (gfc_option.coarray == GFC_FCOARRAY_LIB)
1117 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_critical, 0);
1118 gfc_add_expr_to_block (&block, tmp);
1121 tmp = gfc_trans_code (code->block->next);
1122 gfc_add_expr_to_block (&block, tmp);
1124 if (gfc_option.coarray == GFC_FCOARRAY_LIB)
1126 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_end_critical,
1128 gfc_add_expr_to_block (&block, tmp);
1132 return gfc_finish_block (&block);
1136 /* Do proper initialization for ASSOCIATE names. */
1138 static void
1139 trans_associate_var (gfc_symbol *sym, gfc_wrapped_block *block)
1141 gfc_expr *e;
1142 tree tmp;
1143 bool class_target;
1144 bool unlimited;
1145 tree desc;
1146 tree offset;
1147 tree dim;
1148 int n;
1150 gcc_assert (sym->assoc);
1151 e = sym->assoc->target;
1153 class_target = (e->expr_type == EXPR_VARIABLE)
1154 && (gfc_is_class_scalar_expr (e)
1155 || gfc_is_class_array_ref (e, NULL));
1157 unlimited = UNLIMITED_POLY (e);
1159 /* Do a `pointer assignment' with updated descriptor (or assign descriptor
1160 to array temporary) for arrays with either unknown shape or if associating
1161 to a variable. */
1162 if (sym->attr.dimension && !class_target
1163 && (sym->as->type == AS_DEFERRED || sym->assoc->variable))
1165 gfc_se se;
1166 tree desc;
1168 desc = sym->backend_decl;
1170 /* If association is to an expression, evaluate it and create temporary.
1171 Otherwise, get descriptor of target for pointer assignment. */
1172 gfc_init_se (&se, NULL);
1173 if (sym->assoc->variable)
1175 se.direct_byref = 1;
1176 se.expr = desc;
1178 gfc_conv_expr_descriptor (&se, e);
1180 /* If we didn't already do the pointer assignment, set associate-name
1181 descriptor to the one generated for the temporary. */
1182 if (!sym->assoc->variable)
1184 int dim;
1186 gfc_add_modify (&se.pre, desc, se.expr);
1188 /* The generated descriptor has lower bound zero (as array
1189 temporary), shift bounds so we get lower bounds of 1. */
1190 for (dim = 0; dim < e->rank; ++dim)
1191 gfc_conv_shift_descriptor_lbound (&se.pre, desc,
1192 dim, gfc_index_one_node);
1195 /* If this is a subreference array pointer associate name use the
1196 associate variable element size for the value of 'span'. */
1197 if (sym->attr.subref_array_pointer)
1199 gcc_assert (e->expr_type == EXPR_VARIABLE);
1200 tmp = e->symtree->n.sym->backend_decl;
1201 tmp = gfc_get_element_type (TREE_TYPE (tmp));
1202 tmp = fold_convert (gfc_array_index_type, size_in_bytes (tmp));
1203 gfc_add_modify (&se.pre, GFC_DECL_SPAN(desc), tmp);
1206 /* Done, register stuff as init / cleanup code. */
1207 gfc_add_init_cleanup (block, gfc_finish_block (&se.pre),
1208 gfc_finish_block (&se.post));
1211 /* Temporaries, arising from TYPE IS, just need the descriptor of class
1212 arrays to be assigned directly. */
1213 else if (class_target && sym->attr.dimension
1214 && (sym->ts.type == BT_DERIVED || unlimited))
1216 gfc_se se;
1218 gfc_init_se (&se, NULL);
1219 se.descriptor_only = 1;
1220 gfc_conv_expr (&se, e);
1222 gcc_assert (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (se.expr)));
1223 gcc_assert (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (sym->backend_decl)));
1225 gfc_add_modify (&se.pre, sym->backend_decl, se.expr);
1227 if (unlimited)
1229 /* Recover the dtype, which has been overwritten by the
1230 assignment from an unlimited polymorphic object. */
1231 tmp = gfc_conv_descriptor_dtype (sym->backend_decl);
1232 gfc_add_modify (&se.pre, tmp,
1233 gfc_get_dtype (TREE_TYPE (sym->backend_decl)));
1236 gfc_add_init_cleanup (block, gfc_finish_block( &se.pre),
1237 gfc_finish_block (&se.post));
1240 /* Do a scalar pointer assignment; this is for scalar variable targets. */
1241 else if (gfc_is_associate_pointer (sym))
1243 gfc_se se;
1245 gcc_assert (!sym->attr.dimension);
1247 gfc_init_se (&se, NULL);
1249 /* Class associate-names come this way because they are
1250 unconditionally associate pointers and the symbol is scalar. */
1251 if (sym->ts.type == BT_CLASS && CLASS_DATA (sym)->attr.dimension)
1253 /* For a class array we need a descriptor for the selector. */
1254 gfc_conv_expr_descriptor (&se, e);
1256 /* Obtain a temporary class container for the result. */
1257 gfc_conv_class_to_class (&se, e, sym->ts, false, true, false, false);
1258 se.expr = build_fold_indirect_ref_loc (input_location, se.expr);
1260 /* Set the offset. */
1261 desc = gfc_class_data_get (se.expr);
1262 offset = gfc_index_zero_node;
1263 for (n = 0; n < e->rank; n++)
1265 dim = gfc_rank_cst[n];
1266 tmp = fold_build2_loc (input_location, MULT_EXPR,
1267 gfc_array_index_type,
1268 gfc_conv_descriptor_stride_get (desc, dim),
1269 gfc_conv_descriptor_lbound_get (desc, dim));
1270 offset = fold_build2_loc (input_location, MINUS_EXPR,
1271 gfc_array_index_type,
1272 offset, tmp);
1274 gfc_conv_descriptor_offset_set (&se.pre, desc, offset);
1276 else if (sym->ts.type == BT_CLASS && e->ts.type == BT_CLASS
1277 && CLASS_DATA (e)->attr.dimension)
1279 /* This is bound to be a class array element. */
1280 gfc_conv_expr_reference (&se, e);
1281 /* Get the _vptr component of the class object. */
1282 tmp = gfc_get_vptr_from_expr (se.expr);
1283 /* Obtain a temporary class container for the result. */
1284 gfc_conv_derived_to_class (&se, e, sym->ts, tmp, false, false);
1285 se.expr = build_fold_indirect_ref_loc (input_location, se.expr);
1287 else
1288 gfc_conv_expr (&se, e);
1290 tmp = TREE_TYPE (sym->backend_decl);
1291 tmp = gfc_build_addr_expr (tmp, se.expr);
1292 gfc_add_modify (&se.pre, sym->backend_decl, tmp);
1294 gfc_add_init_cleanup (block, gfc_finish_block( &se.pre),
1295 gfc_finish_block (&se.post));
1298 /* Do a simple assignment. This is for scalar expressions, where we
1299 can simply use expression assignment. */
1300 else
1302 gfc_expr *lhs;
1304 lhs = gfc_lval_expr_from_sym (sym);
1305 tmp = gfc_trans_assignment (lhs, e, false, true);
1306 gfc_add_init_cleanup (block, tmp, NULL_TREE);
1309 /* Set the stringlength from the vtable size. */
1310 if (sym->ts.type == BT_CHARACTER && sym->attr.select_type_temporary)
1312 tree charlen;
1313 gfc_se se;
1314 gfc_init_se (&se, NULL);
1315 gcc_assert (UNLIMITED_POLY (e->symtree->n.sym));
1316 tmp = gfc_get_symbol_decl (e->symtree->n.sym);
1317 tmp = gfc_vtable_size_get (tmp);
1318 gfc_get_symbol_decl (sym);
1319 charlen = sym->ts.u.cl->backend_decl;
1320 gfc_add_modify (&se.pre, charlen,
1321 fold_convert (TREE_TYPE (charlen), tmp));
1322 gfc_add_init_cleanup (block, gfc_finish_block( &se.pre),
1323 gfc_finish_block (&se.post));
1328 /* Translate a BLOCK construct. This is basically what we would do for a
1329 procedure body. */
1331 tree
1332 gfc_trans_block_construct (gfc_code* code)
1334 gfc_namespace* ns;
1335 gfc_symbol* sym;
1336 gfc_wrapped_block block;
1337 tree exit_label;
1338 stmtblock_t body;
1339 gfc_association_list *ass;
1341 ns = code->ext.block.ns;
1342 gcc_assert (ns);
1343 sym = ns->proc_name;
1344 gcc_assert (sym);
1346 /* Process local variables. */
1347 gcc_assert (!sym->tlink);
1348 sym->tlink = sym;
1349 gfc_process_block_locals (ns);
1351 /* Generate code including exit-label. */
1352 gfc_init_block (&body);
1353 exit_label = gfc_build_label_decl (NULL_TREE);
1354 code->exit_label = exit_label;
1355 gfc_add_expr_to_block (&body, gfc_trans_code (ns->code));
1356 gfc_add_expr_to_block (&body, build1_v (LABEL_EXPR, exit_label));
1358 /* Finish everything. */
1359 gfc_start_wrapped_block (&block, gfc_finish_block (&body));
1360 gfc_trans_deferred_vars (sym, &block);
1361 for (ass = code->ext.block.assoc; ass; ass = ass->next)
1362 trans_associate_var (ass->st->n.sym, &block);
1364 return gfc_finish_wrapped_block (&block);
1368 /* Translate the simple DO construct. This is where the loop variable has
1369 integer type and step +-1. We can't use this in the general case
1370 because integer overflow and floating point errors could give incorrect
1371 results.
1372 We translate a do loop from:
1374 DO dovar = from, to, step
1375 body
1376 END DO
1380 [Evaluate loop bounds and step]
1381 dovar = from;
1382 if ((step > 0) ? (dovar <= to) : (dovar => to))
1384 for (;;)
1386 body;
1387 cycle_label:
1388 cond = (dovar == to);
1389 dovar += step;
1390 if (cond) goto end_label;
1393 end_label:
1395 This helps the optimizers by avoiding the extra induction variable
1396 used in the general case. */
1398 static tree
1399 gfc_trans_simple_do (gfc_code * code, stmtblock_t *pblock, tree dovar,
1400 tree from, tree to, tree step, tree exit_cond)
1402 stmtblock_t body;
1403 tree type;
1404 tree cond;
1405 tree tmp;
1406 tree saved_dovar = NULL;
1407 tree cycle_label;
1408 tree exit_label;
1409 location_t loc;
1411 type = TREE_TYPE (dovar);
1413 loc = code->ext.iterator->start->where.lb->location;
1415 /* Initialize the DO variable: dovar = from. */
1416 gfc_add_modify_loc (loc, pblock, dovar,
1417 fold_convert (TREE_TYPE(dovar), from));
1419 /* Save value for do-tinkering checking. */
1420 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
1422 saved_dovar = gfc_create_var (type, ".saved_dovar");
1423 gfc_add_modify_loc (loc, pblock, saved_dovar, dovar);
1426 /* Cycle and exit statements are implemented with gotos. */
1427 cycle_label = gfc_build_label_decl (NULL_TREE);
1428 exit_label = gfc_build_label_decl (NULL_TREE);
1430 /* Put the labels where they can be found later. See gfc_trans_do(). */
1431 code->cycle_label = cycle_label;
1432 code->exit_label = exit_label;
1434 /* Loop body. */
1435 gfc_start_block (&body);
1437 /* Main loop body. */
1438 tmp = gfc_trans_code_cond (code->block->next, exit_cond);
1439 gfc_add_expr_to_block (&body, tmp);
1441 /* Label for cycle statements (if needed). */
1442 if (TREE_USED (cycle_label))
1444 tmp = build1_v (LABEL_EXPR, cycle_label);
1445 gfc_add_expr_to_block (&body, tmp);
1448 /* Check whether someone has modified the loop variable. */
1449 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
1451 tmp = fold_build2_loc (loc, NE_EXPR, boolean_type_node,
1452 dovar, saved_dovar);
1453 gfc_trans_runtime_check (true, false, tmp, &body, &code->loc,
1454 "Loop variable has been modified");
1457 /* Exit the loop if there is an I/O result condition or error. */
1458 if (exit_cond)
1460 tmp = build1_v (GOTO_EXPR, exit_label);
1461 tmp = fold_build3_loc (loc, COND_EXPR, void_type_node,
1462 exit_cond, tmp,
1463 build_empty_stmt (loc));
1464 gfc_add_expr_to_block (&body, tmp);
1467 /* Evaluate the loop condition. */
1468 cond = fold_build2_loc (loc, EQ_EXPR, boolean_type_node, dovar,
1469 to);
1470 cond = gfc_evaluate_now_loc (loc, cond, &body);
1472 /* Increment the loop variable. */
1473 tmp = fold_build2_loc (loc, PLUS_EXPR, type, dovar, step);
1474 gfc_add_modify_loc (loc, &body, dovar, tmp);
1476 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
1477 gfc_add_modify_loc (loc, &body, saved_dovar, dovar);
1479 /* The loop exit. */
1480 tmp = fold_build1_loc (loc, GOTO_EXPR, void_type_node, exit_label);
1481 TREE_USED (exit_label) = 1;
1482 tmp = fold_build3_loc (loc, COND_EXPR, void_type_node,
1483 cond, tmp, build_empty_stmt (loc));
1484 gfc_add_expr_to_block (&body, tmp);
1486 /* Finish the loop body. */
1487 tmp = gfc_finish_block (&body);
1488 tmp = fold_build1_loc (loc, LOOP_EXPR, void_type_node, tmp);
1490 /* Only execute the loop if the number of iterations is positive. */
1491 if (tree_int_cst_sgn (step) > 0)
1492 cond = fold_build2_loc (loc, LE_EXPR, boolean_type_node, dovar,
1493 to);
1494 else
1495 cond = fold_build2_loc (loc, GE_EXPR, boolean_type_node, dovar,
1496 to);
1497 tmp = fold_build3_loc (loc, COND_EXPR, void_type_node, cond, tmp,
1498 build_empty_stmt (loc));
1499 gfc_add_expr_to_block (pblock, tmp);
1501 /* Add the exit label. */
1502 tmp = build1_v (LABEL_EXPR, exit_label);
1503 gfc_add_expr_to_block (pblock, tmp);
1505 return gfc_finish_block (pblock);
1508 /* Translate the DO construct. This obviously is one of the most
1509 important ones to get right with any compiler, but especially
1510 so for Fortran.
1512 We special case some loop forms as described in gfc_trans_simple_do.
1513 For other cases we implement them with a separate loop count,
1514 as described in the standard.
1516 We translate a do loop from:
1518 DO dovar = from, to, step
1519 body
1520 END DO
1524 [evaluate loop bounds and step]
1525 empty = (step > 0 ? to < from : to > from);
1526 countm1 = (to - from) / step;
1527 dovar = from;
1528 if (empty) goto exit_label;
1529 for (;;)
1531 body;
1532 cycle_label:
1533 dovar += step
1534 countm1t = countm1;
1535 countm1--;
1536 if (countm1t == 0) goto exit_label;
1538 exit_label:
1540 countm1 is an unsigned integer. It is equal to the loop count minus one,
1541 because the loop count itself can overflow. */
1543 tree
1544 gfc_trans_do (gfc_code * code, tree exit_cond)
1546 gfc_se se;
1547 tree dovar;
1548 tree saved_dovar = NULL;
1549 tree from;
1550 tree to;
1551 tree step;
1552 tree countm1;
1553 tree type;
1554 tree utype;
1555 tree cond;
1556 tree cycle_label;
1557 tree exit_label;
1558 tree tmp;
1559 stmtblock_t block;
1560 stmtblock_t body;
1561 location_t loc;
1563 gfc_start_block (&block);
1565 loc = code->ext.iterator->start->where.lb->location;
1567 /* Evaluate all the expressions in the iterator. */
1568 gfc_init_se (&se, NULL);
1569 gfc_conv_expr_lhs (&se, code->ext.iterator->var);
1570 gfc_add_block_to_block (&block, &se.pre);
1571 dovar = se.expr;
1572 type = TREE_TYPE (dovar);
1574 gfc_init_se (&se, NULL);
1575 gfc_conv_expr_val (&se, code->ext.iterator->start);
1576 gfc_add_block_to_block (&block, &se.pre);
1577 from = gfc_evaluate_now (se.expr, &block);
1579 gfc_init_se (&se, NULL);
1580 gfc_conv_expr_val (&se, code->ext.iterator->end);
1581 gfc_add_block_to_block (&block, &se.pre);
1582 to = gfc_evaluate_now (se.expr, &block);
1584 gfc_init_se (&se, NULL);
1585 gfc_conv_expr_val (&se, code->ext.iterator->step);
1586 gfc_add_block_to_block (&block, &se.pre);
1587 step = gfc_evaluate_now (se.expr, &block);
1589 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
1591 tmp = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, step,
1592 build_zero_cst (type));
1593 gfc_trans_runtime_check (true, false, tmp, &block, &code->loc,
1594 "DO step value is zero");
1597 /* Special case simple loops. */
1598 if (TREE_CODE (type) == INTEGER_TYPE
1599 && (integer_onep (step)
1600 || tree_int_cst_equal (step, integer_minus_one_node)))
1601 return gfc_trans_simple_do (code, &block, dovar, from, to, step, exit_cond);
1604 if (TREE_CODE (type) == INTEGER_TYPE)
1605 utype = unsigned_type_for (type);
1606 else
1607 utype = unsigned_type_for (gfc_array_index_type);
1608 countm1 = gfc_create_var (utype, "countm1");
1610 /* Cycle and exit statements are implemented with gotos. */
1611 cycle_label = gfc_build_label_decl (NULL_TREE);
1612 exit_label = gfc_build_label_decl (NULL_TREE);
1613 TREE_USED (exit_label) = 1;
1615 /* Put these labels where they can be found later. */
1616 code->cycle_label = cycle_label;
1617 code->exit_label = exit_label;
1619 /* Initialize the DO variable: dovar = from. */
1620 gfc_add_modify (&block, dovar, from);
1622 /* Save value for do-tinkering checking. */
1623 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
1625 saved_dovar = gfc_create_var (type, ".saved_dovar");
1626 gfc_add_modify_loc (loc, &block, saved_dovar, dovar);
1629 /* Initialize loop count and jump to exit label if the loop is empty.
1630 This code is executed before we enter the loop body. We generate:
1631 if (step > 0)
1633 if (to < from)
1634 goto exit_label;
1635 countm1 = (to - from) / step;
1637 else
1639 if (to > from)
1640 goto exit_label;
1641 countm1 = (from - to) / -step;
1645 if (TREE_CODE (type) == INTEGER_TYPE)
1647 tree pos, neg, tou, fromu, stepu, tmp2;
1649 /* The distance from FROM to TO cannot always be represented in a signed
1650 type, thus use unsigned arithmetic, also to avoid any undefined
1651 overflow issues. */
1652 tou = fold_convert (utype, to);
1653 fromu = fold_convert (utype, from);
1654 stepu = fold_convert (utype, step);
1656 /* For a positive step, when to < from, exit, otherwise compute
1657 countm1 = ((unsigned)to - (unsigned)from) / (unsigned)step */
1658 tmp = fold_build2_loc (loc, LT_EXPR, boolean_type_node, to, from);
1659 tmp2 = fold_build2_loc (loc, TRUNC_DIV_EXPR, utype,
1660 fold_build2_loc (loc, MINUS_EXPR, utype,
1661 tou, fromu),
1662 stepu);
1663 pos = fold_build3_loc (loc, COND_EXPR, void_type_node, tmp,
1664 fold_build1_loc (loc, GOTO_EXPR, void_type_node,
1665 exit_label),
1666 fold_build2 (MODIFY_EXPR, void_type_node,
1667 countm1, tmp2));
1669 /* For a negative step, when to > from, exit, otherwise compute
1670 countm1 = ((unsigned)from - (unsigned)to) / -(unsigned)step */
1671 tmp = fold_build2_loc (loc, GT_EXPR, boolean_type_node, to, from);
1672 tmp2 = fold_build2_loc (loc, TRUNC_DIV_EXPR, utype,
1673 fold_build2_loc (loc, MINUS_EXPR, utype,
1674 fromu, tou),
1675 fold_build1_loc (loc, NEGATE_EXPR, utype, stepu));
1676 neg = fold_build3_loc (loc, COND_EXPR, void_type_node, tmp,
1677 fold_build1_loc (loc, GOTO_EXPR, void_type_node,
1678 exit_label),
1679 fold_build2 (MODIFY_EXPR, void_type_node,
1680 countm1, tmp2));
1682 tmp = fold_build2_loc (loc, LT_EXPR, boolean_type_node, step,
1683 build_int_cst (TREE_TYPE (step), 0));
1684 tmp = fold_build3_loc (loc, COND_EXPR, void_type_node, tmp, neg, pos);
1686 gfc_add_expr_to_block (&block, tmp);
1688 else
1690 tree pos_step;
1692 /* TODO: We could use the same width as the real type.
1693 This would probably cause more problems that it solves
1694 when we implement "long double" types. */
1696 tmp = fold_build2_loc (loc, MINUS_EXPR, type, to, from);
1697 tmp = fold_build2_loc (loc, RDIV_EXPR, type, tmp, step);
1698 tmp = fold_build1_loc (loc, FIX_TRUNC_EXPR, utype, tmp);
1699 gfc_add_modify (&block, countm1, tmp);
1701 /* We need a special check for empty loops:
1702 empty = (step > 0 ? to < from : to > from); */
1703 pos_step = fold_build2_loc (loc, GT_EXPR, boolean_type_node, step,
1704 build_zero_cst (type));
1705 tmp = fold_build3_loc (loc, COND_EXPR, boolean_type_node, pos_step,
1706 fold_build2_loc (loc, LT_EXPR,
1707 boolean_type_node, to, from),
1708 fold_build2_loc (loc, GT_EXPR,
1709 boolean_type_node, to, from));
1710 /* If the loop is empty, go directly to the exit label. */
1711 tmp = fold_build3_loc (loc, COND_EXPR, void_type_node, tmp,
1712 build1_v (GOTO_EXPR, exit_label),
1713 build_empty_stmt (input_location));
1714 gfc_add_expr_to_block (&block, tmp);
1717 /* Loop body. */
1718 gfc_start_block (&body);
1720 /* Main loop body. */
1721 tmp = gfc_trans_code_cond (code->block->next, exit_cond);
1722 gfc_add_expr_to_block (&body, tmp);
1724 /* Label for cycle statements (if needed). */
1725 if (TREE_USED (cycle_label))
1727 tmp = build1_v (LABEL_EXPR, cycle_label);
1728 gfc_add_expr_to_block (&body, tmp);
1731 /* Check whether someone has modified the loop variable. */
1732 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
1734 tmp = fold_build2_loc (loc, NE_EXPR, boolean_type_node, dovar,
1735 saved_dovar);
1736 gfc_trans_runtime_check (true, false, tmp, &body, &code->loc,
1737 "Loop variable has been modified");
1740 /* Exit the loop if there is an I/O result condition or error. */
1741 if (exit_cond)
1743 tmp = build1_v (GOTO_EXPR, exit_label);
1744 tmp = fold_build3_loc (loc, COND_EXPR, void_type_node,
1745 exit_cond, tmp,
1746 build_empty_stmt (input_location));
1747 gfc_add_expr_to_block (&body, tmp);
1750 /* Increment the loop variable. */
1751 tmp = fold_build2_loc (loc, PLUS_EXPR, type, dovar, step);
1752 gfc_add_modify_loc (loc, &body, dovar, tmp);
1754 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
1755 gfc_add_modify_loc (loc, &body, saved_dovar, dovar);
1757 /* Initialize countm1t. */
1758 tree countm1t = gfc_create_var (utype, "countm1t");
1759 gfc_add_modify_loc (loc, &body, countm1t, countm1);
1761 /* Decrement the loop count. */
1762 tmp = fold_build2_loc (loc, MINUS_EXPR, utype, countm1,
1763 build_int_cst (utype, 1));
1764 gfc_add_modify_loc (loc, &body, countm1, tmp);
1766 /* End with the loop condition. Loop until countm1t == 0. */
1767 cond = fold_build2_loc (loc, EQ_EXPR, boolean_type_node, countm1t,
1768 build_int_cst (utype, 0));
1769 tmp = fold_build1_loc (loc, GOTO_EXPR, void_type_node, exit_label);
1770 tmp = fold_build3_loc (loc, COND_EXPR, void_type_node,
1771 cond, tmp, build_empty_stmt (loc));
1772 gfc_add_expr_to_block (&body, tmp);
1774 /* End of loop body. */
1775 tmp = gfc_finish_block (&body);
1777 /* The for loop itself. */
1778 tmp = fold_build1_loc (loc, LOOP_EXPR, void_type_node, tmp);
1779 gfc_add_expr_to_block (&block, tmp);
1781 /* Add the exit label. */
1782 tmp = build1_v (LABEL_EXPR, exit_label);
1783 gfc_add_expr_to_block (&block, tmp);
1785 return gfc_finish_block (&block);
1789 /* Translate the DO WHILE construct.
1791 We translate
1793 DO WHILE (cond)
1794 body
1795 END DO
1799 for ( ; ; )
1801 pre_cond;
1802 if (! cond) goto exit_label;
1803 body;
1804 cycle_label:
1806 exit_label:
1808 Because the evaluation of the exit condition `cond' may have side
1809 effects, we can't do much for empty loop bodies. The backend optimizers
1810 should be smart enough to eliminate any dead loops. */
1812 tree
1813 gfc_trans_do_while (gfc_code * code)
1815 gfc_se cond;
1816 tree tmp;
1817 tree cycle_label;
1818 tree exit_label;
1819 stmtblock_t block;
1821 /* Everything we build here is part of the loop body. */
1822 gfc_start_block (&block);
1824 /* Cycle and exit statements are implemented with gotos. */
1825 cycle_label = gfc_build_label_decl (NULL_TREE);
1826 exit_label = gfc_build_label_decl (NULL_TREE);
1828 /* Put the labels where they can be found later. See gfc_trans_do(). */
1829 code->cycle_label = cycle_label;
1830 code->exit_label = exit_label;
1832 /* Create a GIMPLE version of the exit condition. */
1833 gfc_init_se (&cond, NULL);
1834 gfc_conv_expr_val (&cond, code->expr1);
1835 gfc_add_block_to_block (&block, &cond.pre);
1836 cond.expr = fold_build1_loc (code->expr1->where.lb->location,
1837 TRUTH_NOT_EXPR, TREE_TYPE (cond.expr), cond.expr);
1839 /* Build "IF (! cond) GOTO exit_label". */
1840 tmp = build1_v (GOTO_EXPR, exit_label);
1841 TREE_USED (exit_label) = 1;
1842 tmp = fold_build3_loc (code->expr1->where.lb->location, COND_EXPR,
1843 void_type_node, cond.expr, tmp,
1844 build_empty_stmt (code->expr1->where.lb->location));
1845 gfc_add_expr_to_block (&block, tmp);
1847 /* The main body of the loop. */
1848 tmp = gfc_trans_code (code->block->next);
1849 gfc_add_expr_to_block (&block, tmp);
1851 /* Label for cycle statements (if needed). */
1852 if (TREE_USED (cycle_label))
1854 tmp = build1_v (LABEL_EXPR, cycle_label);
1855 gfc_add_expr_to_block (&block, tmp);
1858 /* End of loop body. */
1859 tmp = gfc_finish_block (&block);
1861 gfc_init_block (&block);
1862 /* Build the loop. */
1863 tmp = fold_build1_loc (code->expr1->where.lb->location, LOOP_EXPR,
1864 void_type_node, tmp);
1865 gfc_add_expr_to_block (&block, tmp);
1867 /* Add the exit label. */
1868 tmp = build1_v (LABEL_EXPR, exit_label);
1869 gfc_add_expr_to_block (&block, tmp);
1871 return gfc_finish_block (&block);
1875 /* Translate the SELECT CASE construct for INTEGER case expressions,
1876 without killing all potential optimizations. The problem is that
1877 Fortran allows unbounded cases, but the back-end does not, so we
1878 need to intercept those before we enter the equivalent SWITCH_EXPR
1879 we can build.
1881 For example, we translate this,
1883 SELECT CASE (expr)
1884 CASE (:100,101,105:115)
1885 block_1
1886 CASE (190:199,200:)
1887 block_2
1888 CASE (300)
1889 block_3
1890 CASE DEFAULT
1891 block_4
1892 END SELECT
1894 to the GENERIC equivalent,
1896 switch (expr)
1898 case (minimum value for typeof(expr) ... 100:
1899 case 101:
1900 case 105 ... 114:
1901 block1:
1902 goto end_label;
1904 case 200 ... (maximum value for typeof(expr):
1905 case 190 ... 199:
1906 block2;
1907 goto end_label;
1909 case 300:
1910 block_3;
1911 goto end_label;
1913 default:
1914 block_4;
1915 goto end_label;
1918 end_label: */
1920 static tree
1921 gfc_trans_integer_select (gfc_code * code)
1923 gfc_code *c;
1924 gfc_case *cp;
1925 tree end_label;
1926 tree tmp;
1927 gfc_se se;
1928 stmtblock_t block;
1929 stmtblock_t body;
1931 gfc_start_block (&block);
1933 /* Calculate the switch expression. */
1934 gfc_init_se (&se, NULL);
1935 gfc_conv_expr_val (&se, code->expr1);
1936 gfc_add_block_to_block (&block, &se.pre);
1938 end_label = gfc_build_label_decl (NULL_TREE);
1940 gfc_init_block (&body);
1942 for (c = code->block; c; c = c->block)
1944 for (cp = c->ext.block.case_list; cp; cp = cp->next)
1946 tree low, high;
1947 tree label;
1949 /* Assume it's the default case. */
1950 low = high = NULL_TREE;
1952 if (cp->low)
1954 low = gfc_conv_mpz_to_tree (cp->low->value.integer,
1955 cp->low->ts.kind);
1957 /* If there's only a lower bound, set the high bound to the
1958 maximum value of the case expression. */
1959 if (!cp->high)
1960 high = TYPE_MAX_VALUE (TREE_TYPE (se.expr));
1963 if (cp->high)
1965 /* Three cases are possible here:
1967 1) There is no lower bound, e.g. CASE (:N).
1968 2) There is a lower bound .NE. high bound, that is
1969 a case range, e.g. CASE (N:M) where M>N (we make
1970 sure that M>N during type resolution).
1971 3) There is a lower bound, and it has the same value
1972 as the high bound, e.g. CASE (N:N). This is our
1973 internal representation of CASE(N).
1975 In the first and second case, we need to set a value for
1976 high. In the third case, we don't because the GCC middle
1977 end represents a single case value by just letting high be
1978 a NULL_TREE. We can't do that because we need to be able
1979 to represent unbounded cases. */
1981 if (!cp->low
1982 || (cp->low
1983 && mpz_cmp (cp->low->value.integer,
1984 cp->high->value.integer) != 0))
1985 high = gfc_conv_mpz_to_tree (cp->high->value.integer,
1986 cp->high->ts.kind);
1988 /* Unbounded case. */
1989 if (!cp->low)
1990 low = TYPE_MIN_VALUE (TREE_TYPE (se.expr));
1993 /* Build a label. */
1994 label = gfc_build_label_decl (NULL_TREE);
1996 /* Add this case label.
1997 Add parameter 'label', make it match GCC backend. */
1998 tmp = build_case_label (low, high, label);
1999 gfc_add_expr_to_block (&body, tmp);
2002 /* Add the statements for this case. */
2003 tmp = gfc_trans_code (c->next);
2004 gfc_add_expr_to_block (&body, tmp);
2006 /* Break to the end of the construct. */
2007 tmp = build1_v (GOTO_EXPR, end_label);
2008 gfc_add_expr_to_block (&body, tmp);
2011 tmp = gfc_finish_block (&body);
2012 tmp = fold_build3_loc (input_location, SWITCH_EXPR, NULL_TREE,
2013 se.expr, tmp, NULL_TREE);
2014 gfc_add_expr_to_block (&block, tmp);
2016 tmp = build1_v (LABEL_EXPR, end_label);
2017 gfc_add_expr_to_block (&block, tmp);
2019 return gfc_finish_block (&block);
2023 /* Translate the SELECT CASE construct for LOGICAL case expressions.
2025 There are only two cases possible here, even though the standard
2026 does allow three cases in a LOGICAL SELECT CASE construct: .TRUE.,
2027 .FALSE., and DEFAULT.
2029 We never generate more than two blocks here. Instead, we always
2030 try to eliminate the DEFAULT case. This way, we can translate this
2031 kind of SELECT construct to a simple
2033 if {} else {};
2035 expression in GENERIC. */
2037 static tree
2038 gfc_trans_logical_select (gfc_code * code)
2040 gfc_code *c;
2041 gfc_code *t, *f, *d;
2042 gfc_case *cp;
2043 gfc_se se;
2044 stmtblock_t block;
2046 /* Assume we don't have any cases at all. */
2047 t = f = d = NULL;
2049 /* Now see which ones we actually do have. We can have at most two
2050 cases in a single case list: one for .TRUE. and one for .FALSE.
2051 The default case is always separate. If the cases for .TRUE. and
2052 .FALSE. are in the same case list, the block for that case list
2053 always executed, and we don't generate code a COND_EXPR. */
2054 for (c = code->block; c; c = c->block)
2056 for (cp = c->ext.block.case_list; cp; cp = cp->next)
2058 if (cp->low)
2060 if (cp->low->value.logical == 0) /* .FALSE. */
2061 f = c;
2062 else /* if (cp->value.logical != 0), thus .TRUE. */
2063 t = c;
2065 else
2066 d = c;
2070 /* Start a new block. */
2071 gfc_start_block (&block);
2073 /* Calculate the switch expression. We always need to do this
2074 because it may have side effects. */
2075 gfc_init_se (&se, NULL);
2076 gfc_conv_expr_val (&se, code->expr1);
2077 gfc_add_block_to_block (&block, &se.pre);
2079 if (t == f && t != NULL)
2081 /* Cases for .TRUE. and .FALSE. are in the same block. Just
2082 translate the code for these cases, append it to the current
2083 block. */
2084 gfc_add_expr_to_block (&block, gfc_trans_code (t->next));
2086 else
2088 tree true_tree, false_tree, stmt;
2090 true_tree = build_empty_stmt (input_location);
2091 false_tree = build_empty_stmt (input_location);
2093 /* If we have a case for .TRUE. and for .FALSE., discard the default case.
2094 Otherwise, if .TRUE. or .FALSE. is missing and there is a default case,
2095 make the missing case the default case. */
2096 if (t != NULL && f != NULL)
2097 d = NULL;
2098 else if (d != NULL)
2100 if (t == NULL)
2101 t = d;
2102 else
2103 f = d;
2106 /* Translate the code for each of these blocks, and append it to
2107 the current block. */
2108 if (t != NULL)
2109 true_tree = gfc_trans_code (t->next);
2111 if (f != NULL)
2112 false_tree = gfc_trans_code (f->next);
2114 stmt = fold_build3_loc (input_location, COND_EXPR, void_type_node,
2115 se.expr, true_tree, false_tree);
2116 gfc_add_expr_to_block (&block, stmt);
2119 return gfc_finish_block (&block);
2123 /* The jump table types are stored in static variables to avoid
2124 constructing them from scratch every single time. */
2125 static GTY(()) tree select_struct[2];
2127 /* Translate the SELECT CASE construct for CHARACTER case expressions.
2128 Instead of generating compares and jumps, it is far simpler to
2129 generate a data structure describing the cases in order and call a
2130 library subroutine that locates the right case.
2131 This is particularly true because this is the only case where we
2132 might have to dispose of a temporary.
2133 The library subroutine returns a pointer to jump to or NULL if no
2134 branches are to be taken. */
2136 static tree
2137 gfc_trans_character_select (gfc_code *code)
2139 tree init, end_label, tmp, type, case_num, label, fndecl;
2140 stmtblock_t block, body;
2141 gfc_case *cp, *d;
2142 gfc_code *c;
2143 gfc_se se, expr1se;
2144 int n, k;
2145 vec<constructor_elt, va_gc> *inits = NULL;
2147 tree pchartype = gfc_get_pchar_type (code->expr1->ts.kind);
2149 /* The jump table types are stored in static variables to avoid
2150 constructing them from scratch every single time. */
2151 static tree ss_string1[2], ss_string1_len[2];
2152 static tree ss_string2[2], ss_string2_len[2];
2153 static tree ss_target[2];
2155 cp = code->block->ext.block.case_list;
2156 while (cp->left != NULL)
2157 cp = cp->left;
2159 /* Generate the body */
2160 gfc_start_block (&block);
2161 gfc_init_se (&expr1se, NULL);
2162 gfc_conv_expr_reference (&expr1se, code->expr1);
2164 gfc_add_block_to_block (&block, &expr1se.pre);
2166 end_label = gfc_build_label_decl (NULL_TREE);
2168 gfc_init_block (&body);
2170 /* Attempt to optimize length 1 selects. */
2171 if (integer_onep (expr1se.string_length))
2173 for (d = cp; d; d = d->right)
2175 int i;
2176 if (d->low)
2178 gcc_assert (d->low->expr_type == EXPR_CONSTANT
2179 && d->low->ts.type == BT_CHARACTER);
2180 if (d->low->value.character.length > 1)
2182 for (i = 1; i < d->low->value.character.length; i++)
2183 if (d->low->value.character.string[i] != ' ')
2184 break;
2185 if (i != d->low->value.character.length)
2187 if (optimize && d->high && i == 1)
2189 gcc_assert (d->high->expr_type == EXPR_CONSTANT
2190 && d->high->ts.type == BT_CHARACTER);
2191 if (d->high->value.character.length > 1
2192 && (d->low->value.character.string[0]
2193 == d->high->value.character.string[0])
2194 && d->high->value.character.string[1] != ' '
2195 && ((d->low->value.character.string[1] < ' ')
2196 == (d->high->value.character.string[1]
2197 < ' ')))
2198 continue;
2200 break;
2204 if (d->high)
2206 gcc_assert (d->high->expr_type == EXPR_CONSTANT
2207 && d->high->ts.type == BT_CHARACTER);
2208 if (d->high->value.character.length > 1)
2210 for (i = 1; i < d->high->value.character.length; i++)
2211 if (d->high->value.character.string[i] != ' ')
2212 break;
2213 if (i != d->high->value.character.length)
2214 break;
2218 if (d == NULL)
2220 tree ctype = gfc_get_char_type (code->expr1->ts.kind);
2222 for (c = code->block; c; c = c->block)
2224 for (cp = c->ext.block.case_list; cp; cp = cp->next)
2226 tree low, high;
2227 tree label;
2228 gfc_char_t r;
2230 /* Assume it's the default case. */
2231 low = high = NULL_TREE;
2233 if (cp->low)
2235 /* CASE ('ab') or CASE ('ab':'az') will never match
2236 any length 1 character. */
2237 if (cp->low->value.character.length > 1
2238 && cp->low->value.character.string[1] != ' ')
2239 continue;
2241 if (cp->low->value.character.length > 0)
2242 r = cp->low->value.character.string[0];
2243 else
2244 r = ' ';
2245 low = build_int_cst (ctype, r);
2247 /* If there's only a lower bound, set the high bound
2248 to the maximum value of the case expression. */
2249 if (!cp->high)
2250 high = TYPE_MAX_VALUE (ctype);
2253 if (cp->high)
2255 if (!cp->low
2256 || (cp->low->value.character.string[0]
2257 != cp->high->value.character.string[0]))
2259 if (cp->high->value.character.length > 0)
2260 r = cp->high->value.character.string[0];
2261 else
2262 r = ' ';
2263 high = build_int_cst (ctype, r);
2266 /* Unbounded case. */
2267 if (!cp->low)
2268 low = TYPE_MIN_VALUE (ctype);
2271 /* Build a label. */
2272 label = gfc_build_label_decl (NULL_TREE);
2274 /* Add this case label.
2275 Add parameter 'label', make it match GCC backend. */
2276 tmp = build_case_label (low, high, label);
2277 gfc_add_expr_to_block (&body, tmp);
2280 /* Add the statements for this case. */
2281 tmp = gfc_trans_code (c->next);
2282 gfc_add_expr_to_block (&body, tmp);
2284 /* Break to the end of the construct. */
2285 tmp = build1_v (GOTO_EXPR, end_label);
2286 gfc_add_expr_to_block (&body, tmp);
2289 tmp = gfc_string_to_single_character (expr1se.string_length,
2290 expr1se.expr,
2291 code->expr1->ts.kind);
2292 case_num = gfc_create_var (ctype, "case_num");
2293 gfc_add_modify (&block, case_num, tmp);
2295 gfc_add_block_to_block (&block, &expr1se.post);
2297 tmp = gfc_finish_block (&body);
2298 tmp = fold_build3_loc (input_location, SWITCH_EXPR, NULL_TREE,
2299 case_num, tmp, NULL_TREE);
2300 gfc_add_expr_to_block (&block, tmp);
2302 tmp = build1_v (LABEL_EXPR, end_label);
2303 gfc_add_expr_to_block (&block, tmp);
2305 return gfc_finish_block (&block);
2309 if (code->expr1->ts.kind == 1)
2310 k = 0;
2311 else if (code->expr1->ts.kind == 4)
2312 k = 1;
2313 else
2314 gcc_unreachable ();
2316 if (select_struct[k] == NULL)
2318 tree *chain = NULL;
2319 select_struct[k] = make_node (RECORD_TYPE);
2321 if (code->expr1->ts.kind == 1)
2322 TYPE_NAME (select_struct[k]) = get_identifier ("_jump_struct_char1");
2323 else if (code->expr1->ts.kind == 4)
2324 TYPE_NAME (select_struct[k]) = get_identifier ("_jump_struct_char4");
2325 else
2326 gcc_unreachable ();
2328 #undef ADD_FIELD
2329 #define ADD_FIELD(NAME, TYPE) \
2330 ss_##NAME[k] = gfc_add_field_to_struct (select_struct[k], \
2331 get_identifier (stringize(NAME)), \
2332 TYPE, \
2333 &chain)
2335 ADD_FIELD (string1, pchartype);
2336 ADD_FIELD (string1_len, gfc_charlen_type_node);
2338 ADD_FIELD (string2, pchartype);
2339 ADD_FIELD (string2_len, gfc_charlen_type_node);
2341 ADD_FIELD (target, integer_type_node);
2342 #undef ADD_FIELD
2344 gfc_finish_type (select_struct[k]);
2347 n = 0;
2348 for (d = cp; d; d = d->right)
2349 d->n = n++;
2351 for (c = code->block; c; c = c->block)
2353 for (d = c->ext.block.case_list; d; d = d->next)
2355 label = gfc_build_label_decl (NULL_TREE);
2356 tmp = build_case_label ((d->low == NULL && d->high == NULL)
2357 ? NULL
2358 : build_int_cst (integer_type_node, d->n),
2359 NULL, label);
2360 gfc_add_expr_to_block (&body, tmp);
2363 tmp = gfc_trans_code (c->next);
2364 gfc_add_expr_to_block (&body, tmp);
2366 tmp = build1_v (GOTO_EXPR, end_label);
2367 gfc_add_expr_to_block (&body, tmp);
2370 /* Generate the structure describing the branches */
2371 for (d = cp; d; d = d->right)
2373 vec<constructor_elt, va_gc> *node = NULL;
2375 gfc_init_se (&se, NULL);
2377 if (d->low == NULL)
2379 CONSTRUCTOR_APPEND_ELT (node, ss_string1[k], null_pointer_node);
2380 CONSTRUCTOR_APPEND_ELT (node, ss_string1_len[k], integer_zero_node);
2382 else
2384 gfc_conv_expr_reference (&se, d->low);
2386 CONSTRUCTOR_APPEND_ELT (node, ss_string1[k], se.expr);
2387 CONSTRUCTOR_APPEND_ELT (node, ss_string1_len[k], se.string_length);
2390 if (d->high == NULL)
2392 CONSTRUCTOR_APPEND_ELT (node, ss_string2[k], null_pointer_node);
2393 CONSTRUCTOR_APPEND_ELT (node, ss_string2_len[k], integer_zero_node);
2395 else
2397 gfc_init_se (&se, NULL);
2398 gfc_conv_expr_reference (&se, d->high);
2400 CONSTRUCTOR_APPEND_ELT (node, ss_string2[k], se.expr);
2401 CONSTRUCTOR_APPEND_ELT (node, ss_string2_len[k], se.string_length);
2404 CONSTRUCTOR_APPEND_ELT (node, ss_target[k],
2405 build_int_cst (integer_type_node, d->n));
2407 tmp = build_constructor (select_struct[k], node);
2408 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, tmp);
2411 type = build_array_type (select_struct[k],
2412 build_index_type (size_int (n-1)));
2414 init = build_constructor (type, inits);
2415 TREE_CONSTANT (init) = 1;
2416 TREE_STATIC (init) = 1;
2417 /* Create a static variable to hold the jump table. */
2418 tmp = gfc_create_var (type, "jumptable");
2419 TREE_CONSTANT (tmp) = 1;
2420 TREE_STATIC (tmp) = 1;
2421 TREE_READONLY (tmp) = 1;
2422 DECL_INITIAL (tmp) = init;
2423 init = tmp;
2425 /* Build the library call */
2426 init = gfc_build_addr_expr (pvoid_type_node, init);
2428 if (code->expr1->ts.kind == 1)
2429 fndecl = gfor_fndecl_select_string;
2430 else if (code->expr1->ts.kind == 4)
2431 fndecl = gfor_fndecl_select_string_char4;
2432 else
2433 gcc_unreachable ();
2435 tmp = build_call_expr_loc (input_location,
2436 fndecl, 4, init,
2437 build_int_cst (gfc_charlen_type_node, n),
2438 expr1se.expr, expr1se.string_length);
2439 case_num = gfc_create_var (integer_type_node, "case_num");
2440 gfc_add_modify (&block, case_num, tmp);
2442 gfc_add_block_to_block (&block, &expr1se.post);
2444 tmp = gfc_finish_block (&body);
2445 tmp = fold_build3_loc (input_location, SWITCH_EXPR, NULL_TREE,
2446 case_num, tmp, NULL_TREE);
2447 gfc_add_expr_to_block (&block, tmp);
2449 tmp = build1_v (LABEL_EXPR, end_label);
2450 gfc_add_expr_to_block (&block, tmp);
2452 return gfc_finish_block (&block);
2456 /* Translate the three variants of the SELECT CASE construct.
2458 SELECT CASEs with INTEGER case expressions can be translated to an
2459 equivalent GENERIC switch statement, and for LOGICAL case
2460 expressions we build one or two if-else compares.
2462 SELECT CASEs with CHARACTER case expressions are a whole different
2463 story, because they don't exist in GENERIC. So we sort them and
2464 do a binary search at runtime.
2466 Fortran has no BREAK statement, and it does not allow jumps from
2467 one case block to another. That makes things a lot easier for
2468 the optimizers. */
2470 tree
2471 gfc_trans_select (gfc_code * code)
2473 stmtblock_t block;
2474 tree body;
2475 tree exit_label;
2477 gcc_assert (code && code->expr1);
2478 gfc_init_block (&block);
2480 /* Build the exit label and hang it in. */
2481 exit_label = gfc_build_label_decl (NULL_TREE);
2482 code->exit_label = exit_label;
2484 /* Empty SELECT constructs are legal. */
2485 if (code->block == NULL)
2486 body = build_empty_stmt (input_location);
2488 /* Select the correct translation function. */
2489 else
2490 switch (code->expr1->ts.type)
2492 case BT_LOGICAL:
2493 body = gfc_trans_logical_select (code);
2494 break;
2496 case BT_INTEGER:
2497 body = gfc_trans_integer_select (code);
2498 break;
2500 case BT_CHARACTER:
2501 body = gfc_trans_character_select (code);
2502 break;
2504 default:
2505 gfc_internal_error ("gfc_trans_select(): Bad type for case expr.");
2506 /* Not reached */
2509 /* Build everything together. */
2510 gfc_add_expr_to_block (&block, body);
2511 gfc_add_expr_to_block (&block, build1_v (LABEL_EXPR, exit_label));
2513 return gfc_finish_block (&block);
2517 /* Traversal function to substitute a replacement symtree if the symbol
2518 in the expression is the same as that passed. f == 2 signals that
2519 that variable itself is not to be checked - only the references.
2520 This group of functions is used when the variable expression in a
2521 FORALL assignment has internal references. For example:
2522 FORALL (i = 1:4) p(p(i)) = i
2523 The only recourse here is to store a copy of 'p' for the index
2524 expression. */
2526 static gfc_symtree *new_symtree;
2527 static gfc_symtree *old_symtree;
2529 static bool
2530 forall_replace (gfc_expr *expr, gfc_symbol *sym, int *f)
2532 if (expr->expr_type != EXPR_VARIABLE)
2533 return false;
2535 if (*f == 2)
2536 *f = 1;
2537 else if (expr->symtree->n.sym == sym)
2538 expr->symtree = new_symtree;
2540 return false;
2543 static void
2544 forall_replace_symtree (gfc_expr *e, gfc_symbol *sym, int f)
2546 gfc_traverse_expr (e, sym, forall_replace, f);
2549 static bool
2550 forall_restore (gfc_expr *expr,
2551 gfc_symbol *sym ATTRIBUTE_UNUSED,
2552 int *f ATTRIBUTE_UNUSED)
2554 if (expr->expr_type != EXPR_VARIABLE)
2555 return false;
2557 if (expr->symtree == new_symtree)
2558 expr->symtree = old_symtree;
2560 return false;
2563 static void
2564 forall_restore_symtree (gfc_expr *e)
2566 gfc_traverse_expr (e, NULL, forall_restore, 0);
2569 static void
2570 forall_make_variable_temp (gfc_code *c, stmtblock_t *pre, stmtblock_t *post)
2572 gfc_se tse;
2573 gfc_se rse;
2574 gfc_expr *e;
2575 gfc_symbol *new_sym;
2576 gfc_symbol *old_sym;
2577 gfc_symtree *root;
2578 tree tmp;
2580 /* Build a copy of the lvalue. */
2581 old_symtree = c->expr1->symtree;
2582 old_sym = old_symtree->n.sym;
2583 e = gfc_lval_expr_from_sym (old_sym);
2584 if (old_sym->attr.dimension)
2586 gfc_init_se (&tse, NULL);
2587 gfc_conv_subref_array_arg (&tse, e, 0, INTENT_IN, false);
2588 gfc_add_block_to_block (pre, &tse.pre);
2589 gfc_add_block_to_block (post, &tse.post);
2590 tse.expr = build_fold_indirect_ref_loc (input_location, tse.expr);
2592 if (e->ts.type != BT_CHARACTER)
2594 /* Use the variable offset for the temporary. */
2595 tmp = gfc_conv_array_offset (old_sym->backend_decl);
2596 gfc_conv_descriptor_offset_set (pre, tse.expr, tmp);
2599 else
2601 gfc_init_se (&tse, NULL);
2602 gfc_init_se (&rse, NULL);
2603 gfc_conv_expr (&rse, e);
2604 if (e->ts.type == BT_CHARACTER)
2606 tse.string_length = rse.string_length;
2607 tmp = gfc_get_character_type_len (gfc_default_character_kind,
2608 tse.string_length);
2609 tse.expr = gfc_conv_string_tmp (&tse, build_pointer_type (tmp),
2610 rse.string_length);
2611 gfc_add_block_to_block (pre, &tse.pre);
2612 gfc_add_block_to_block (post, &tse.post);
2614 else
2616 tmp = gfc_typenode_for_spec (&e->ts);
2617 tse.expr = gfc_create_var (tmp, "temp");
2620 tmp = gfc_trans_scalar_assign (&tse, &rse, e->ts, true,
2621 e->expr_type == EXPR_VARIABLE, true);
2622 gfc_add_expr_to_block (pre, tmp);
2624 gfc_free_expr (e);
2626 /* Create a new symbol to represent the lvalue. */
2627 new_sym = gfc_new_symbol (old_sym->name, NULL);
2628 new_sym->ts = old_sym->ts;
2629 new_sym->attr.referenced = 1;
2630 new_sym->attr.temporary = 1;
2631 new_sym->attr.dimension = old_sym->attr.dimension;
2632 new_sym->attr.flavor = old_sym->attr.flavor;
2634 /* Use the temporary as the backend_decl. */
2635 new_sym->backend_decl = tse.expr;
2637 /* Create a fake symtree for it. */
2638 root = NULL;
2639 new_symtree = gfc_new_symtree (&root, old_sym->name);
2640 new_symtree->n.sym = new_sym;
2641 gcc_assert (new_symtree == root);
2643 /* Go through the expression reference replacing the old_symtree
2644 with the new. */
2645 forall_replace_symtree (c->expr1, old_sym, 2);
2647 /* Now we have made this temporary, we might as well use it for
2648 the right hand side. */
2649 forall_replace_symtree (c->expr2, old_sym, 1);
2653 /* Handles dependencies in forall assignments. */
2654 static int
2655 check_forall_dependencies (gfc_code *c, stmtblock_t *pre, stmtblock_t *post)
2657 gfc_ref *lref;
2658 gfc_ref *rref;
2659 int need_temp;
2660 gfc_symbol *lsym;
2662 lsym = c->expr1->symtree->n.sym;
2663 need_temp = gfc_check_dependency (c->expr1, c->expr2, 0);
2665 /* Now check for dependencies within the 'variable'
2666 expression itself. These are treated by making a complete
2667 copy of variable and changing all the references to it
2668 point to the copy instead. Note that the shallow copy of
2669 the variable will not suffice for derived types with
2670 pointer components. We therefore leave these to their
2671 own devices. */
2672 if (lsym->ts.type == BT_DERIVED
2673 && lsym->ts.u.derived->attr.pointer_comp)
2674 return need_temp;
2676 new_symtree = NULL;
2677 if (find_forall_index (c->expr1, lsym, 2))
2679 forall_make_variable_temp (c, pre, post);
2680 need_temp = 0;
2683 /* Substrings with dependencies are treated in the same
2684 way. */
2685 if (c->expr1->ts.type == BT_CHARACTER
2686 && c->expr1->ref
2687 && c->expr2->expr_type == EXPR_VARIABLE
2688 && lsym == c->expr2->symtree->n.sym)
2690 for (lref = c->expr1->ref; lref; lref = lref->next)
2691 if (lref->type == REF_SUBSTRING)
2692 break;
2693 for (rref = c->expr2->ref; rref; rref = rref->next)
2694 if (rref->type == REF_SUBSTRING)
2695 break;
2697 if (rref && lref
2698 && gfc_dep_compare_expr (rref->u.ss.start, lref->u.ss.start) < 0)
2700 forall_make_variable_temp (c, pre, post);
2701 need_temp = 0;
2704 return need_temp;
2708 static void
2709 cleanup_forall_symtrees (gfc_code *c)
2711 forall_restore_symtree (c->expr1);
2712 forall_restore_symtree (c->expr2);
2713 free (new_symtree->n.sym);
2714 free (new_symtree);
2718 /* Generate the loops for a FORALL block, specified by FORALL_TMP. BODY
2719 is the contents of the FORALL block/stmt to be iterated. MASK_FLAG
2720 indicates whether we should generate code to test the FORALLs mask
2721 array. OUTER is the loop header to be used for initializing mask
2722 indices.
2724 The generated loop format is:
2725 count = (end - start + step) / step
2726 loopvar = start
2727 while (1)
2729 if (count <=0 )
2730 goto end_of_loop
2731 <body>
2732 loopvar += step
2733 count --
2735 end_of_loop: */
2737 static tree
2738 gfc_trans_forall_loop (forall_info *forall_tmp, tree body,
2739 int mask_flag, stmtblock_t *outer)
2741 int n, nvar;
2742 tree tmp;
2743 tree cond;
2744 stmtblock_t block;
2745 tree exit_label;
2746 tree count;
2747 tree var, start, end, step;
2748 iter_info *iter;
2750 /* Initialize the mask index outside the FORALL nest. */
2751 if (mask_flag && forall_tmp->mask)
2752 gfc_add_modify (outer, forall_tmp->maskindex, gfc_index_zero_node);
2754 iter = forall_tmp->this_loop;
2755 nvar = forall_tmp->nvar;
2756 for (n = 0; n < nvar; n++)
2758 var = iter->var;
2759 start = iter->start;
2760 end = iter->end;
2761 step = iter->step;
2763 exit_label = gfc_build_label_decl (NULL_TREE);
2764 TREE_USED (exit_label) = 1;
2766 /* The loop counter. */
2767 count = gfc_create_var (TREE_TYPE (var), "count");
2769 /* The body of the loop. */
2770 gfc_init_block (&block);
2772 /* The exit condition. */
2773 cond = fold_build2_loc (input_location, LE_EXPR, boolean_type_node,
2774 count, build_int_cst (TREE_TYPE (count), 0));
2775 if (forall_tmp->do_concurrent)
2776 cond = build2 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
2777 build_int_cst (integer_type_node,
2778 annot_expr_ivdep_kind));
2780 tmp = build1_v (GOTO_EXPR, exit_label);
2781 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
2782 cond, tmp, build_empty_stmt (input_location));
2783 gfc_add_expr_to_block (&block, tmp);
2785 /* The main loop body. */
2786 gfc_add_expr_to_block (&block, body);
2788 /* Increment the loop variable. */
2789 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (var), var,
2790 step);
2791 gfc_add_modify (&block, var, tmp);
2793 /* Advance to the next mask element. Only do this for the
2794 innermost loop. */
2795 if (n == 0 && mask_flag && forall_tmp->mask)
2797 tree maskindex = forall_tmp->maskindex;
2798 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
2799 maskindex, gfc_index_one_node);
2800 gfc_add_modify (&block, maskindex, tmp);
2803 /* Decrement the loop counter. */
2804 tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (var), count,
2805 build_int_cst (TREE_TYPE (var), 1));
2806 gfc_add_modify (&block, count, tmp);
2808 body = gfc_finish_block (&block);
2810 /* Loop var initialization. */
2811 gfc_init_block (&block);
2812 gfc_add_modify (&block, var, start);
2815 /* Initialize the loop counter. */
2816 tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (var), step,
2817 start);
2818 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (var), end,
2819 tmp);
2820 tmp = fold_build2_loc (input_location, TRUNC_DIV_EXPR, TREE_TYPE (var),
2821 tmp, step);
2822 gfc_add_modify (&block, count, tmp);
2824 /* The loop expression. */
2825 tmp = build1_v (LOOP_EXPR, body);
2826 gfc_add_expr_to_block (&block, tmp);
2828 /* The exit label. */
2829 tmp = build1_v (LABEL_EXPR, exit_label);
2830 gfc_add_expr_to_block (&block, tmp);
2832 body = gfc_finish_block (&block);
2833 iter = iter->next;
2835 return body;
2839 /* Generate the body and loops according to MASK_FLAG. If MASK_FLAG
2840 is nonzero, the body is controlled by all masks in the forall nest.
2841 Otherwise, the innermost loop is not controlled by it's mask. This
2842 is used for initializing that mask. */
2844 static tree
2845 gfc_trans_nested_forall_loop (forall_info * nested_forall_info, tree body,
2846 int mask_flag)
2848 tree tmp;
2849 stmtblock_t header;
2850 forall_info *forall_tmp;
2851 tree mask, maskindex;
2853 gfc_start_block (&header);
2855 forall_tmp = nested_forall_info;
2856 while (forall_tmp != NULL)
2858 /* Generate body with masks' control. */
2859 if (mask_flag)
2861 mask = forall_tmp->mask;
2862 maskindex = forall_tmp->maskindex;
2864 /* If a mask was specified make the assignment conditional. */
2865 if (mask)
2867 tmp = gfc_build_array_ref (mask, maskindex, NULL);
2868 body = build3_v (COND_EXPR, tmp, body,
2869 build_empty_stmt (input_location));
2872 body = gfc_trans_forall_loop (forall_tmp, body, mask_flag, &header);
2873 forall_tmp = forall_tmp->prev_nest;
2874 mask_flag = 1;
2877 gfc_add_expr_to_block (&header, body);
2878 return gfc_finish_block (&header);
2882 /* Allocate data for holding a temporary array. Returns either a local
2883 temporary array or a pointer variable. */
2885 static tree
2886 gfc_do_allocate (tree bytesize, tree size, tree * pdata, stmtblock_t * pblock,
2887 tree elem_type)
2889 tree tmpvar;
2890 tree type;
2891 tree tmp;
2893 if (INTEGER_CST_P (size))
2894 tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
2895 size, gfc_index_one_node);
2896 else
2897 tmp = NULL_TREE;
2899 type = build_range_type (gfc_array_index_type, gfc_index_zero_node, tmp);
2900 type = build_array_type (elem_type, type);
2901 if (gfc_can_put_var_on_stack (bytesize))
2903 gcc_assert (INTEGER_CST_P (size));
2904 tmpvar = gfc_create_var (type, "temp");
2905 *pdata = NULL_TREE;
2907 else
2909 tmpvar = gfc_create_var (build_pointer_type (type), "temp");
2910 *pdata = convert (pvoid_type_node, tmpvar);
2912 tmp = gfc_call_malloc (pblock, TREE_TYPE (tmpvar), bytesize);
2913 gfc_add_modify (pblock, tmpvar, tmp);
2915 return tmpvar;
2919 /* Generate codes to copy the temporary to the actual lhs. */
2921 static tree
2922 generate_loop_for_temp_to_lhs (gfc_expr *expr, tree tmp1, tree count3,
2923 tree count1, tree wheremask, bool invert)
2925 gfc_ss *lss;
2926 gfc_se lse, rse;
2927 stmtblock_t block, body;
2928 gfc_loopinfo loop1;
2929 tree tmp;
2930 tree wheremaskexpr;
2932 /* Walk the lhs. */
2933 lss = gfc_walk_expr (expr);
2935 if (lss == gfc_ss_terminator)
2937 gfc_start_block (&block);
2939 gfc_init_se (&lse, NULL);
2941 /* Translate the expression. */
2942 gfc_conv_expr (&lse, expr);
2944 /* Form the expression for the temporary. */
2945 tmp = gfc_build_array_ref (tmp1, count1, NULL);
2947 /* Use the scalar assignment as is. */
2948 gfc_add_block_to_block (&block, &lse.pre);
2949 gfc_add_modify (&block, lse.expr, tmp);
2950 gfc_add_block_to_block (&block, &lse.post);
2952 /* Increment the count1. */
2953 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (count1),
2954 count1, gfc_index_one_node);
2955 gfc_add_modify (&block, count1, tmp);
2957 tmp = gfc_finish_block (&block);
2959 else
2961 gfc_start_block (&block);
2963 gfc_init_loopinfo (&loop1);
2964 gfc_init_se (&rse, NULL);
2965 gfc_init_se (&lse, NULL);
2967 /* Associate the lss with the loop. */
2968 gfc_add_ss_to_loop (&loop1, lss);
2970 /* Calculate the bounds of the scalarization. */
2971 gfc_conv_ss_startstride (&loop1);
2972 /* Setup the scalarizing loops. */
2973 gfc_conv_loop_setup (&loop1, &expr->where);
2975 gfc_mark_ss_chain_used (lss, 1);
2977 /* Start the scalarized loop body. */
2978 gfc_start_scalarized_body (&loop1, &body);
2980 /* Setup the gfc_se structures. */
2981 gfc_copy_loopinfo_to_se (&lse, &loop1);
2982 lse.ss = lss;
2984 /* Form the expression of the temporary. */
2985 if (lss != gfc_ss_terminator)
2986 rse.expr = gfc_build_array_ref (tmp1, count1, NULL);
2987 /* Translate expr. */
2988 gfc_conv_expr (&lse, expr);
2990 /* Use the scalar assignment. */
2991 rse.string_length = lse.string_length;
2992 tmp = gfc_trans_scalar_assign (&lse, &rse, expr->ts, false, true, true);
2994 /* Form the mask expression according to the mask tree list. */
2995 if (wheremask)
2997 wheremaskexpr = gfc_build_array_ref (wheremask, count3, NULL);
2998 if (invert)
2999 wheremaskexpr = fold_build1_loc (input_location, TRUTH_NOT_EXPR,
3000 TREE_TYPE (wheremaskexpr),
3001 wheremaskexpr);
3002 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
3003 wheremaskexpr, tmp,
3004 build_empty_stmt (input_location));
3007 gfc_add_expr_to_block (&body, tmp);
3009 /* Increment count1. */
3010 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
3011 count1, gfc_index_one_node);
3012 gfc_add_modify (&body, count1, tmp);
3014 /* Increment count3. */
3015 if (count3)
3017 tmp = fold_build2_loc (input_location, PLUS_EXPR,
3018 gfc_array_index_type, count3,
3019 gfc_index_one_node);
3020 gfc_add_modify (&body, count3, tmp);
3023 /* Generate the copying loops. */
3024 gfc_trans_scalarizing_loops (&loop1, &body);
3025 gfc_add_block_to_block (&block, &loop1.pre);
3026 gfc_add_block_to_block (&block, &loop1.post);
3027 gfc_cleanup_loop (&loop1);
3029 tmp = gfc_finish_block (&block);
3031 return tmp;
3035 /* Generate codes to copy rhs to the temporary. TMP1 is the address of
3036 temporary, LSS and RSS are formed in function compute_inner_temp_size(),
3037 and should not be freed. WHEREMASK is the conditional execution mask
3038 whose sense may be inverted by INVERT. */
3040 static tree
3041 generate_loop_for_rhs_to_temp (gfc_expr *expr2, tree tmp1, tree count3,
3042 tree count1, gfc_ss *lss, gfc_ss *rss,
3043 tree wheremask, bool invert)
3045 stmtblock_t block, body1;
3046 gfc_loopinfo loop;
3047 gfc_se lse;
3048 gfc_se rse;
3049 tree tmp;
3050 tree wheremaskexpr;
3052 gfc_start_block (&block);
3054 gfc_init_se (&rse, NULL);
3055 gfc_init_se (&lse, NULL);
3057 if (lss == gfc_ss_terminator)
3059 gfc_init_block (&body1);
3060 gfc_conv_expr (&rse, expr2);
3061 lse.expr = gfc_build_array_ref (tmp1, count1, NULL);
3063 else
3065 /* Initialize the loop. */
3066 gfc_init_loopinfo (&loop);
3068 /* We may need LSS to determine the shape of the expression. */
3069 gfc_add_ss_to_loop (&loop, lss);
3070 gfc_add_ss_to_loop (&loop, rss);
3072 gfc_conv_ss_startstride (&loop);
3073 gfc_conv_loop_setup (&loop, &expr2->where);
3075 gfc_mark_ss_chain_used (rss, 1);
3076 /* Start the loop body. */
3077 gfc_start_scalarized_body (&loop, &body1);
3079 /* Translate the expression. */
3080 gfc_copy_loopinfo_to_se (&rse, &loop);
3081 rse.ss = rss;
3082 gfc_conv_expr (&rse, expr2);
3084 /* Form the expression of the temporary. */
3085 lse.expr = gfc_build_array_ref (tmp1, count1, NULL);
3088 /* Use the scalar assignment. */
3089 lse.string_length = rse.string_length;
3090 tmp = gfc_trans_scalar_assign (&lse, &rse, expr2->ts, true,
3091 expr2->expr_type == EXPR_VARIABLE, true);
3093 /* Form the mask expression according to the mask tree list. */
3094 if (wheremask)
3096 wheremaskexpr = gfc_build_array_ref (wheremask, count3, NULL);
3097 if (invert)
3098 wheremaskexpr = fold_build1_loc (input_location, TRUTH_NOT_EXPR,
3099 TREE_TYPE (wheremaskexpr),
3100 wheremaskexpr);
3101 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
3102 wheremaskexpr, tmp,
3103 build_empty_stmt (input_location));
3106 gfc_add_expr_to_block (&body1, tmp);
3108 if (lss == gfc_ss_terminator)
3110 gfc_add_block_to_block (&block, &body1);
3112 /* Increment count1. */
3113 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (count1),
3114 count1, gfc_index_one_node);
3115 gfc_add_modify (&block, count1, tmp);
3117 else
3119 /* Increment count1. */
3120 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
3121 count1, gfc_index_one_node);
3122 gfc_add_modify (&body1, count1, tmp);
3124 /* Increment count3. */
3125 if (count3)
3127 tmp = fold_build2_loc (input_location, PLUS_EXPR,
3128 gfc_array_index_type,
3129 count3, gfc_index_one_node);
3130 gfc_add_modify (&body1, count3, tmp);
3133 /* Generate the copying loops. */
3134 gfc_trans_scalarizing_loops (&loop, &body1);
3136 gfc_add_block_to_block (&block, &loop.pre);
3137 gfc_add_block_to_block (&block, &loop.post);
3139 gfc_cleanup_loop (&loop);
3140 /* TODO: Reuse lss and rss when copying temp->lhs. Need to be careful
3141 as tree nodes in SS may not be valid in different scope. */
3144 tmp = gfc_finish_block (&block);
3145 return tmp;
3149 /* Calculate the size of temporary needed in the assignment inside forall.
3150 LSS and RSS are filled in this function. */
3152 static tree
3153 compute_inner_temp_size (gfc_expr *expr1, gfc_expr *expr2,
3154 stmtblock_t * pblock,
3155 gfc_ss **lss, gfc_ss **rss)
3157 gfc_loopinfo loop;
3158 tree size;
3159 int i;
3160 int save_flag;
3161 tree tmp;
3163 *lss = gfc_walk_expr (expr1);
3164 *rss = NULL;
3166 size = gfc_index_one_node;
3167 if (*lss != gfc_ss_terminator)
3169 gfc_init_loopinfo (&loop);
3171 /* Walk the RHS of the expression. */
3172 *rss = gfc_walk_expr (expr2);
3173 if (*rss == gfc_ss_terminator)
3174 /* The rhs is scalar. Add a ss for the expression. */
3175 *rss = gfc_get_scalar_ss (gfc_ss_terminator, expr2);
3177 /* Associate the SS with the loop. */
3178 gfc_add_ss_to_loop (&loop, *lss);
3179 /* We don't actually need to add the rhs at this point, but it might
3180 make guessing the loop bounds a bit easier. */
3181 gfc_add_ss_to_loop (&loop, *rss);
3183 /* We only want the shape of the expression, not rest of the junk
3184 generated by the scalarizer. */
3185 loop.array_parameter = 1;
3187 /* Calculate the bounds of the scalarization. */
3188 save_flag = gfc_option.rtcheck;
3189 gfc_option.rtcheck &= ~GFC_RTCHECK_BOUNDS;
3190 gfc_conv_ss_startstride (&loop);
3191 gfc_option.rtcheck = save_flag;
3192 gfc_conv_loop_setup (&loop, &expr2->where);
3194 /* Figure out how many elements we need. */
3195 for (i = 0; i < loop.dimen; i++)
3197 tmp = fold_build2_loc (input_location, MINUS_EXPR,
3198 gfc_array_index_type,
3199 gfc_index_one_node, loop.from[i]);
3200 tmp = fold_build2_loc (input_location, PLUS_EXPR,
3201 gfc_array_index_type, tmp, loop.to[i]);
3202 size = fold_build2_loc (input_location, MULT_EXPR,
3203 gfc_array_index_type, size, tmp);
3205 gfc_add_block_to_block (pblock, &loop.pre);
3206 size = gfc_evaluate_now (size, pblock);
3207 gfc_add_block_to_block (pblock, &loop.post);
3209 /* TODO: write a function that cleans up a loopinfo without freeing
3210 the SS chains. Currently a NOP. */
3213 return size;
3217 /* Calculate the overall iterator number of the nested forall construct.
3218 This routine actually calculates the number of times the body of the
3219 nested forall specified by NESTED_FORALL_INFO is executed and multiplies
3220 that by the expression INNER_SIZE. The BLOCK argument specifies the
3221 block in which to calculate the result, and the optional INNER_SIZE_BODY
3222 argument contains any statements that need to executed (inside the loop)
3223 to initialize or calculate INNER_SIZE. */
3225 static tree
3226 compute_overall_iter_number (forall_info *nested_forall_info, tree inner_size,
3227 stmtblock_t *inner_size_body, stmtblock_t *block)
3229 forall_info *forall_tmp = nested_forall_info;
3230 tree tmp, number;
3231 stmtblock_t body;
3233 /* We can eliminate the innermost unconditional loops with constant
3234 array bounds. */
3235 if (INTEGER_CST_P (inner_size))
3237 while (forall_tmp
3238 && !forall_tmp->mask
3239 && INTEGER_CST_P (forall_tmp->size))
3241 inner_size = fold_build2_loc (input_location, MULT_EXPR,
3242 gfc_array_index_type,
3243 inner_size, forall_tmp->size);
3244 forall_tmp = forall_tmp->prev_nest;
3247 /* If there are no loops left, we have our constant result. */
3248 if (!forall_tmp)
3249 return inner_size;
3252 /* Otherwise, create a temporary variable to compute the result. */
3253 number = gfc_create_var (gfc_array_index_type, "num");
3254 gfc_add_modify (block, number, gfc_index_zero_node);
3256 gfc_start_block (&body);
3257 if (inner_size_body)
3258 gfc_add_block_to_block (&body, inner_size_body);
3259 if (forall_tmp)
3260 tmp = fold_build2_loc (input_location, PLUS_EXPR,
3261 gfc_array_index_type, number, inner_size);
3262 else
3263 tmp = inner_size;
3264 gfc_add_modify (&body, number, tmp);
3265 tmp = gfc_finish_block (&body);
3267 /* Generate loops. */
3268 if (forall_tmp != NULL)
3269 tmp = gfc_trans_nested_forall_loop (forall_tmp, tmp, 1);
3271 gfc_add_expr_to_block (block, tmp);
3273 return number;
3277 /* Allocate temporary for forall construct. SIZE is the size of temporary
3278 needed. PTEMP1 is returned for space free. */
3280 static tree
3281 allocate_temp_for_forall_nest_1 (tree type, tree size, stmtblock_t * block,
3282 tree * ptemp1)
3284 tree bytesize;
3285 tree unit;
3286 tree tmp;
3288 unit = fold_convert (gfc_array_index_type, TYPE_SIZE_UNIT (type));
3289 if (!integer_onep (unit))
3290 bytesize = fold_build2_loc (input_location, MULT_EXPR,
3291 gfc_array_index_type, size, unit);
3292 else
3293 bytesize = size;
3295 *ptemp1 = NULL;
3296 tmp = gfc_do_allocate (bytesize, size, ptemp1, block, type);
3298 if (*ptemp1)
3299 tmp = build_fold_indirect_ref_loc (input_location, tmp);
3300 return tmp;
3304 /* Allocate temporary for forall construct according to the information in
3305 nested_forall_info. INNER_SIZE is the size of temporary needed in the
3306 assignment inside forall. PTEMP1 is returned for space free. */
3308 static tree
3309 allocate_temp_for_forall_nest (forall_info * nested_forall_info, tree type,
3310 tree inner_size, stmtblock_t * inner_size_body,
3311 stmtblock_t * block, tree * ptemp1)
3313 tree size;
3315 /* Calculate the total size of temporary needed in forall construct. */
3316 size = compute_overall_iter_number (nested_forall_info, inner_size,
3317 inner_size_body, block);
3319 return allocate_temp_for_forall_nest_1 (type, size, block, ptemp1);
3323 /* Handle assignments inside forall which need temporary.
3325 forall (i=start:end:stride; maskexpr)
3326 e<i> = f<i>
3327 end forall
3328 (where e,f<i> are arbitrary expressions possibly involving i
3329 and there is a dependency between e<i> and f<i>)
3330 Translates to:
3331 masktmp(:) = maskexpr(:)
3333 maskindex = 0;
3334 count1 = 0;
3335 num = 0;
3336 for (i = start; i <= end; i += stride)
3337 num += SIZE (f<i>)
3338 count1 = 0;
3339 ALLOCATE (tmp(num))
3340 for (i = start; i <= end; i += stride)
3342 if (masktmp[maskindex++])
3343 tmp[count1++] = f<i>
3345 maskindex = 0;
3346 count1 = 0;
3347 for (i = start; i <= end; i += stride)
3349 if (masktmp[maskindex++])
3350 e<i> = tmp[count1++]
3352 DEALLOCATE (tmp)
3354 static void
3355 gfc_trans_assign_need_temp (gfc_expr * expr1, gfc_expr * expr2,
3356 tree wheremask, bool invert,
3357 forall_info * nested_forall_info,
3358 stmtblock_t * block)
3360 tree type;
3361 tree inner_size;
3362 gfc_ss *lss, *rss;
3363 tree count, count1;
3364 tree tmp, tmp1;
3365 tree ptemp1;
3366 stmtblock_t inner_size_body;
3368 /* Create vars. count1 is the current iterator number of the nested
3369 forall. */
3370 count1 = gfc_create_var (gfc_array_index_type, "count1");
3372 /* Count is the wheremask index. */
3373 if (wheremask)
3375 count = gfc_create_var (gfc_array_index_type, "count");
3376 gfc_add_modify (block, count, gfc_index_zero_node);
3378 else
3379 count = NULL;
3381 /* Initialize count1. */
3382 gfc_add_modify (block, count1, gfc_index_zero_node);
3384 /* Calculate the size of temporary needed in the assignment. Return loop, lss
3385 and rss which are used in function generate_loop_for_rhs_to_temp(). */
3386 gfc_init_block (&inner_size_body);
3387 inner_size = compute_inner_temp_size (expr1, expr2, &inner_size_body,
3388 &lss, &rss);
3390 /* The type of LHS. Used in function allocate_temp_for_forall_nest */
3391 if (expr1->ts.type == BT_CHARACTER && expr1->ts.u.cl->length)
3393 if (!expr1->ts.u.cl->backend_decl)
3395 gfc_se tse;
3396 gfc_init_se (&tse, NULL);
3397 gfc_conv_expr (&tse, expr1->ts.u.cl->length);
3398 expr1->ts.u.cl->backend_decl = tse.expr;
3400 type = gfc_get_character_type_len (gfc_default_character_kind,
3401 expr1->ts.u.cl->backend_decl);
3403 else
3404 type = gfc_typenode_for_spec (&expr1->ts);
3406 /* Allocate temporary for nested forall construct according to the
3407 information in nested_forall_info and inner_size. */
3408 tmp1 = allocate_temp_for_forall_nest (nested_forall_info, type, inner_size,
3409 &inner_size_body, block, &ptemp1);
3411 /* Generate codes to copy rhs to the temporary . */
3412 tmp = generate_loop_for_rhs_to_temp (expr2, tmp1, count, count1, lss, rss,
3413 wheremask, invert);
3415 /* Generate body and loops according to the information in
3416 nested_forall_info. */
3417 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
3418 gfc_add_expr_to_block (block, tmp);
3420 /* Reset count1. */
3421 gfc_add_modify (block, count1, gfc_index_zero_node);
3423 /* Reset count. */
3424 if (wheremask)
3425 gfc_add_modify (block, count, gfc_index_zero_node);
3427 /* Generate codes to copy the temporary to lhs. */
3428 tmp = generate_loop_for_temp_to_lhs (expr1, tmp1, count, count1,
3429 wheremask, invert);
3431 /* Generate body and loops according to the information in
3432 nested_forall_info. */
3433 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
3434 gfc_add_expr_to_block (block, tmp);
3436 if (ptemp1)
3438 /* Free the temporary. */
3439 tmp = gfc_call_free (ptemp1);
3440 gfc_add_expr_to_block (block, tmp);
3445 /* Translate pointer assignment inside FORALL which need temporary. */
3447 static void
3448 gfc_trans_pointer_assign_need_temp (gfc_expr * expr1, gfc_expr * expr2,
3449 forall_info * nested_forall_info,
3450 stmtblock_t * block)
3452 tree type;
3453 tree inner_size;
3454 gfc_ss *lss, *rss;
3455 gfc_se lse;
3456 gfc_se rse;
3457 gfc_array_info *info;
3458 gfc_loopinfo loop;
3459 tree desc;
3460 tree parm;
3461 tree parmtype;
3462 stmtblock_t body;
3463 tree count;
3464 tree tmp, tmp1, ptemp1;
3466 count = gfc_create_var (gfc_array_index_type, "count");
3467 gfc_add_modify (block, count, gfc_index_zero_node);
3469 inner_size = gfc_index_one_node;
3470 lss = gfc_walk_expr (expr1);
3471 rss = gfc_walk_expr (expr2);
3472 if (lss == gfc_ss_terminator)
3474 type = gfc_typenode_for_spec (&expr1->ts);
3475 type = build_pointer_type (type);
3477 /* Allocate temporary for nested forall construct according to the
3478 information in nested_forall_info and inner_size. */
3479 tmp1 = allocate_temp_for_forall_nest (nested_forall_info, type,
3480 inner_size, NULL, block, &ptemp1);
3481 gfc_start_block (&body);
3482 gfc_init_se (&lse, NULL);
3483 lse.expr = gfc_build_array_ref (tmp1, count, NULL);
3484 gfc_init_se (&rse, NULL);
3485 rse.want_pointer = 1;
3486 gfc_conv_expr (&rse, expr2);
3487 gfc_add_block_to_block (&body, &rse.pre);
3488 gfc_add_modify (&body, lse.expr,
3489 fold_convert (TREE_TYPE (lse.expr), rse.expr));
3490 gfc_add_block_to_block (&body, &rse.post);
3492 /* Increment count. */
3493 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
3494 count, gfc_index_one_node);
3495 gfc_add_modify (&body, count, tmp);
3497 tmp = gfc_finish_block (&body);
3499 /* Generate body and loops according to the information in
3500 nested_forall_info. */
3501 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
3502 gfc_add_expr_to_block (block, tmp);
3504 /* Reset count. */
3505 gfc_add_modify (block, count, gfc_index_zero_node);
3507 gfc_start_block (&body);
3508 gfc_init_se (&lse, NULL);
3509 gfc_init_se (&rse, NULL);
3510 rse.expr = gfc_build_array_ref (tmp1, count, NULL);
3511 lse.want_pointer = 1;
3512 gfc_conv_expr (&lse, expr1);
3513 gfc_add_block_to_block (&body, &lse.pre);
3514 gfc_add_modify (&body, lse.expr, rse.expr);
3515 gfc_add_block_to_block (&body, &lse.post);
3516 /* Increment count. */
3517 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
3518 count, gfc_index_one_node);
3519 gfc_add_modify (&body, count, tmp);
3520 tmp = gfc_finish_block (&body);
3522 /* Generate body and loops according to the information in
3523 nested_forall_info. */
3524 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
3525 gfc_add_expr_to_block (block, tmp);
3527 else
3529 gfc_init_loopinfo (&loop);
3531 /* Associate the SS with the loop. */
3532 gfc_add_ss_to_loop (&loop, rss);
3534 /* Setup the scalarizing loops and bounds. */
3535 gfc_conv_ss_startstride (&loop);
3537 gfc_conv_loop_setup (&loop, &expr2->where);
3539 info = &rss->info->data.array;
3540 desc = info->descriptor;
3542 /* Make a new descriptor. */
3543 parmtype = gfc_get_element_type (TREE_TYPE (desc));
3544 parmtype = gfc_get_array_type_bounds (parmtype, loop.dimen, 0,
3545 loop.from, loop.to, 1,
3546 GFC_ARRAY_UNKNOWN, true);
3548 /* Allocate temporary for nested forall construct. */
3549 tmp1 = allocate_temp_for_forall_nest (nested_forall_info, parmtype,
3550 inner_size, NULL, block, &ptemp1);
3551 gfc_start_block (&body);
3552 gfc_init_se (&lse, NULL);
3553 lse.expr = gfc_build_array_ref (tmp1, count, NULL);
3554 lse.direct_byref = 1;
3555 gfc_conv_expr_descriptor (&lse, expr2);
3557 gfc_add_block_to_block (&body, &lse.pre);
3558 gfc_add_block_to_block (&body, &lse.post);
3560 /* Increment count. */
3561 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
3562 count, gfc_index_one_node);
3563 gfc_add_modify (&body, count, tmp);
3565 tmp = gfc_finish_block (&body);
3567 /* Generate body and loops according to the information in
3568 nested_forall_info. */
3569 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
3570 gfc_add_expr_to_block (block, tmp);
3572 /* Reset count. */
3573 gfc_add_modify (block, count, gfc_index_zero_node);
3575 parm = gfc_build_array_ref (tmp1, count, NULL);
3576 gfc_init_se (&lse, NULL);
3577 gfc_conv_expr_descriptor (&lse, expr1);
3578 gfc_add_modify (&lse.pre, lse.expr, parm);
3579 gfc_start_block (&body);
3580 gfc_add_block_to_block (&body, &lse.pre);
3581 gfc_add_block_to_block (&body, &lse.post);
3583 /* Increment count. */
3584 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
3585 count, gfc_index_one_node);
3586 gfc_add_modify (&body, count, tmp);
3588 tmp = gfc_finish_block (&body);
3590 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
3591 gfc_add_expr_to_block (block, tmp);
3593 /* Free the temporary. */
3594 if (ptemp1)
3596 tmp = gfc_call_free (ptemp1);
3597 gfc_add_expr_to_block (block, tmp);
3602 /* FORALL and WHERE statements are really nasty, especially when you nest
3603 them. All the rhs of a forall assignment must be evaluated before the
3604 actual assignments are performed. Presumably this also applies to all the
3605 assignments in an inner where statement. */
3607 /* Generate code for a FORALL statement. Any temporaries are allocated as a
3608 linear array, relying on the fact that we process in the same order in all
3609 loops.
3611 forall (i=start:end:stride; maskexpr)
3612 e<i> = f<i>
3613 g<i> = h<i>
3614 end forall
3615 (where e,f,g,h<i> are arbitrary expressions possibly involving i)
3616 Translates to:
3617 count = ((end + 1 - start) / stride)
3618 masktmp(:) = maskexpr(:)
3620 maskindex = 0;
3621 for (i = start; i <= end; i += stride)
3623 if (masktmp[maskindex++])
3624 e<i> = f<i>
3626 maskindex = 0;
3627 for (i = start; i <= end; i += stride)
3629 if (masktmp[maskindex++])
3630 g<i> = h<i>
3633 Note that this code only works when there are no dependencies.
3634 Forall loop with array assignments and data dependencies are a real pain,
3635 because the size of the temporary cannot always be determined before the
3636 loop is executed. This problem is compounded by the presence of nested
3637 FORALL constructs.
3640 static tree
3641 gfc_trans_forall_1 (gfc_code * code, forall_info * nested_forall_info)
3643 stmtblock_t pre;
3644 stmtblock_t post;
3645 stmtblock_t block;
3646 stmtblock_t body;
3647 tree *var;
3648 tree *start;
3649 tree *end;
3650 tree *step;
3651 gfc_expr **varexpr;
3652 tree tmp;
3653 tree assign;
3654 tree size;
3655 tree maskindex;
3656 tree mask;
3657 tree pmask;
3658 tree cycle_label = NULL_TREE;
3659 int n;
3660 int nvar;
3661 int need_temp;
3662 gfc_forall_iterator *fa;
3663 gfc_se se;
3664 gfc_code *c;
3665 gfc_saved_var *saved_vars;
3666 iter_info *this_forall;
3667 forall_info *info;
3668 bool need_mask;
3670 /* Do nothing if the mask is false. */
3671 if (code->expr1
3672 && code->expr1->expr_type == EXPR_CONSTANT
3673 && !code->expr1->value.logical)
3674 return build_empty_stmt (input_location);
3676 n = 0;
3677 /* Count the FORALL index number. */
3678 for (fa = code->ext.forall_iterator; fa; fa = fa->next)
3679 n++;
3680 nvar = n;
3682 /* Allocate the space for var, start, end, step, varexpr. */
3683 var = XCNEWVEC (tree, nvar);
3684 start = XCNEWVEC (tree, nvar);
3685 end = XCNEWVEC (tree, nvar);
3686 step = XCNEWVEC (tree, nvar);
3687 varexpr = XCNEWVEC (gfc_expr *, nvar);
3688 saved_vars = XCNEWVEC (gfc_saved_var, nvar);
3690 /* Allocate the space for info. */
3691 info = XCNEW (forall_info);
3693 gfc_start_block (&pre);
3694 gfc_init_block (&post);
3695 gfc_init_block (&block);
3697 n = 0;
3698 for (fa = code->ext.forall_iterator; fa; fa = fa->next)
3700 gfc_symbol *sym = fa->var->symtree->n.sym;
3702 /* Allocate space for this_forall. */
3703 this_forall = XCNEW (iter_info);
3705 /* Create a temporary variable for the FORALL index. */
3706 tmp = gfc_typenode_for_spec (&sym->ts);
3707 var[n] = gfc_create_var (tmp, sym->name);
3708 gfc_shadow_sym (sym, var[n], &saved_vars[n]);
3710 /* Record it in this_forall. */
3711 this_forall->var = var[n];
3713 /* Replace the index symbol's backend_decl with the temporary decl. */
3714 sym->backend_decl = var[n];
3716 /* Work out the start, end and stride for the loop. */
3717 gfc_init_se (&se, NULL);
3718 gfc_conv_expr_val (&se, fa->start);
3719 /* Record it in this_forall. */
3720 this_forall->start = se.expr;
3721 gfc_add_block_to_block (&block, &se.pre);
3722 start[n] = se.expr;
3724 gfc_init_se (&se, NULL);
3725 gfc_conv_expr_val (&se, fa->end);
3726 /* Record it in this_forall. */
3727 this_forall->end = se.expr;
3728 gfc_make_safe_expr (&se);
3729 gfc_add_block_to_block (&block, &se.pre);
3730 end[n] = se.expr;
3732 gfc_init_se (&se, NULL);
3733 gfc_conv_expr_val (&se, fa->stride);
3734 /* Record it in this_forall. */
3735 this_forall->step = se.expr;
3736 gfc_make_safe_expr (&se);
3737 gfc_add_block_to_block (&block, &se.pre);
3738 step[n] = se.expr;
3740 /* Set the NEXT field of this_forall to NULL. */
3741 this_forall->next = NULL;
3742 /* Link this_forall to the info construct. */
3743 if (info->this_loop)
3745 iter_info *iter_tmp = info->this_loop;
3746 while (iter_tmp->next != NULL)
3747 iter_tmp = iter_tmp->next;
3748 iter_tmp->next = this_forall;
3750 else
3751 info->this_loop = this_forall;
3753 n++;
3755 nvar = n;
3757 /* Calculate the size needed for the current forall level. */
3758 size = gfc_index_one_node;
3759 for (n = 0; n < nvar; n++)
3761 /* size = (end + step - start) / step. */
3762 tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (start[n]),
3763 step[n], start[n]);
3764 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (end[n]),
3765 end[n], tmp);
3766 tmp = fold_build2_loc (input_location, FLOOR_DIV_EXPR, TREE_TYPE (tmp),
3767 tmp, step[n]);
3768 tmp = convert (gfc_array_index_type, tmp);
3770 size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
3771 size, tmp);
3774 /* Record the nvar and size of current forall level. */
3775 info->nvar = nvar;
3776 info->size = size;
3778 if (code->expr1)
3780 /* If the mask is .true., consider the FORALL unconditional. */
3781 if (code->expr1->expr_type == EXPR_CONSTANT
3782 && code->expr1->value.logical)
3783 need_mask = false;
3784 else
3785 need_mask = true;
3787 else
3788 need_mask = false;
3790 /* First we need to allocate the mask. */
3791 if (need_mask)
3793 /* As the mask array can be very big, prefer compact boolean types. */
3794 tree mask_type = gfc_get_logical_type (gfc_logical_kinds[0].kind);
3795 mask = allocate_temp_for_forall_nest (nested_forall_info, mask_type,
3796 size, NULL, &block, &pmask);
3797 maskindex = gfc_create_var_np (gfc_array_index_type, "mi");
3799 /* Record them in the info structure. */
3800 info->maskindex = maskindex;
3801 info->mask = mask;
3803 else
3805 /* No mask was specified. */
3806 maskindex = NULL_TREE;
3807 mask = pmask = NULL_TREE;
3810 /* Link the current forall level to nested_forall_info. */
3811 info->prev_nest = nested_forall_info;
3812 nested_forall_info = info;
3814 /* Copy the mask into a temporary variable if required.
3815 For now we assume a mask temporary is needed. */
3816 if (need_mask)
3818 /* As the mask array can be very big, prefer compact boolean types. */
3819 tree mask_type = gfc_get_logical_type (gfc_logical_kinds[0].kind);
3821 gfc_add_modify (&block, maskindex, gfc_index_zero_node);
3823 /* Start of mask assignment loop body. */
3824 gfc_start_block (&body);
3826 /* Evaluate the mask expression. */
3827 gfc_init_se (&se, NULL);
3828 gfc_conv_expr_val (&se, code->expr1);
3829 gfc_add_block_to_block (&body, &se.pre);
3831 /* Store the mask. */
3832 se.expr = convert (mask_type, se.expr);
3834 tmp = gfc_build_array_ref (mask, maskindex, NULL);
3835 gfc_add_modify (&body, tmp, se.expr);
3837 /* Advance to the next mask element. */
3838 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
3839 maskindex, gfc_index_one_node);
3840 gfc_add_modify (&body, maskindex, tmp);
3842 /* Generate the loops. */
3843 tmp = gfc_finish_block (&body);
3844 tmp = gfc_trans_nested_forall_loop (info, tmp, 0);
3845 gfc_add_expr_to_block (&block, tmp);
3848 if (code->op == EXEC_DO_CONCURRENT)
3850 gfc_init_block (&body);
3851 cycle_label = gfc_build_label_decl (NULL_TREE);
3852 code->cycle_label = cycle_label;
3853 tmp = gfc_trans_code (code->block->next);
3854 gfc_add_expr_to_block (&body, tmp);
3856 if (TREE_USED (cycle_label))
3858 tmp = build1_v (LABEL_EXPR, cycle_label);
3859 gfc_add_expr_to_block (&body, tmp);
3862 tmp = gfc_finish_block (&body);
3863 nested_forall_info->do_concurrent = true;
3864 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
3865 gfc_add_expr_to_block (&block, tmp);
3866 goto done;
3869 c = code->block->next;
3871 /* TODO: loop merging in FORALL statements. */
3872 /* Now that we've got a copy of the mask, generate the assignment loops. */
3873 while (c)
3875 switch (c->op)
3877 case EXEC_ASSIGN:
3878 /* A scalar or array assignment. DO the simple check for
3879 lhs to rhs dependencies. These make a temporary for the
3880 rhs and form a second forall block to copy to variable. */
3881 need_temp = check_forall_dependencies(c, &pre, &post);
3883 /* Temporaries due to array assignment data dependencies introduce
3884 no end of problems. */
3885 if (need_temp)
3886 gfc_trans_assign_need_temp (c->expr1, c->expr2, NULL, false,
3887 nested_forall_info, &block);
3888 else
3890 /* Use the normal assignment copying routines. */
3891 assign = gfc_trans_assignment (c->expr1, c->expr2, false, true);
3893 /* Generate body and loops. */
3894 tmp = gfc_trans_nested_forall_loop (nested_forall_info,
3895 assign, 1);
3896 gfc_add_expr_to_block (&block, tmp);
3899 /* Cleanup any temporary symtrees that have been made to deal
3900 with dependencies. */
3901 if (new_symtree)
3902 cleanup_forall_symtrees (c);
3904 break;
3906 case EXEC_WHERE:
3907 /* Translate WHERE or WHERE construct nested in FORALL. */
3908 gfc_trans_where_2 (c, NULL, false, nested_forall_info, &block);
3909 break;
3911 /* Pointer assignment inside FORALL. */
3912 case EXEC_POINTER_ASSIGN:
3913 need_temp = gfc_check_dependency (c->expr1, c->expr2, 0);
3914 if (need_temp)
3915 gfc_trans_pointer_assign_need_temp (c->expr1, c->expr2,
3916 nested_forall_info, &block);
3917 else
3919 /* Use the normal assignment copying routines. */
3920 assign = gfc_trans_pointer_assignment (c->expr1, c->expr2);
3922 /* Generate body and loops. */
3923 tmp = gfc_trans_nested_forall_loop (nested_forall_info,
3924 assign, 1);
3925 gfc_add_expr_to_block (&block, tmp);
3927 break;
3929 case EXEC_FORALL:
3930 tmp = gfc_trans_forall_1 (c, nested_forall_info);
3931 gfc_add_expr_to_block (&block, tmp);
3932 break;
3934 /* Explicit subroutine calls are prevented by the frontend but interface
3935 assignments can legitimately produce them. */
3936 case EXEC_ASSIGN_CALL:
3937 assign = gfc_trans_call (c, true, NULL_TREE, NULL_TREE, false);
3938 tmp = gfc_trans_nested_forall_loop (nested_forall_info, assign, 1);
3939 gfc_add_expr_to_block (&block, tmp);
3940 break;
3942 default:
3943 gcc_unreachable ();
3946 c = c->next;
3949 done:
3950 /* Restore the original index variables. */
3951 for (fa = code->ext.forall_iterator, n = 0; fa; fa = fa->next, n++)
3952 gfc_restore_sym (fa->var->symtree->n.sym, &saved_vars[n]);
3954 /* Free the space for var, start, end, step, varexpr. */
3955 free (var);
3956 free (start);
3957 free (end);
3958 free (step);
3959 free (varexpr);
3960 free (saved_vars);
3962 for (this_forall = info->this_loop; this_forall;)
3964 iter_info *next = this_forall->next;
3965 free (this_forall);
3966 this_forall = next;
3969 /* Free the space for this forall_info. */
3970 free (info);
3972 if (pmask)
3974 /* Free the temporary for the mask. */
3975 tmp = gfc_call_free (pmask);
3976 gfc_add_expr_to_block (&block, tmp);
3978 if (maskindex)
3979 pushdecl (maskindex);
3981 gfc_add_block_to_block (&pre, &block);
3982 gfc_add_block_to_block (&pre, &post);
3984 return gfc_finish_block (&pre);
3988 /* Translate the FORALL statement or construct. */
3990 tree gfc_trans_forall (gfc_code * code)
3992 return gfc_trans_forall_1 (code, NULL);
3996 /* Translate the DO CONCURRENT construct. */
3998 tree gfc_trans_do_concurrent (gfc_code * code)
4000 return gfc_trans_forall_1 (code, NULL);
4004 /* Evaluate the WHERE mask expression, copy its value to a temporary.
4005 If the WHERE construct is nested in FORALL, compute the overall temporary
4006 needed by the WHERE mask expression multiplied by the iterator number of
4007 the nested forall.
4008 ME is the WHERE mask expression.
4009 MASK is the current execution mask upon input, whose sense may or may
4010 not be inverted as specified by the INVERT argument.
4011 CMASK is the updated execution mask on output, or NULL if not required.
4012 PMASK is the pending execution mask on output, or NULL if not required.
4013 BLOCK is the block in which to place the condition evaluation loops. */
4015 static void
4016 gfc_evaluate_where_mask (gfc_expr * me, forall_info * nested_forall_info,
4017 tree mask, bool invert, tree cmask, tree pmask,
4018 tree mask_type, stmtblock_t * block)
4020 tree tmp, tmp1;
4021 gfc_ss *lss, *rss;
4022 gfc_loopinfo loop;
4023 stmtblock_t body, body1;
4024 tree count, cond, mtmp;
4025 gfc_se lse, rse;
4027 gfc_init_loopinfo (&loop);
4029 lss = gfc_walk_expr (me);
4030 rss = gfc_walk_expr (me);
4032 /* Variable to index the temporary. */
4033 count = gfc_create_var (gfc_array_index_type, "count");
4034 /* Initialize count. */
4035 gfc_add_modify (block, count, gfc_index_zero_node);
4037 gfc_start_block (&body);
4039 gfc_init_se (&rse, NULL);
4040 gfc_init_se (&lse, NULL);
4042 if (lss == gfc_ss_terminator)
4044 gfc_init_block (&body1);
4046 else
4048 /* Initialize the loop. */
4049 gfc_init_loopinfo (&loop);
4051 /* We may need LSS to determine the shape of the expression. */
4052 gfc_add_ss_to_loop (&loop, lss);
4053 gfc_add_ss_to_loop (&loop, rss);
4055 gfc_conv_ss_startstride (&loop);
4056 gfc_conv_loop_setup (&loop, &me->where);
4058 gfc_mark_ss_chain_used (rss, 1);
4059 /* Start the loop body. */
4060 gfc_start_scalarized_body (&loop, &body1);
4062 /* Translate the expression. */
4063 gfc_copy_loopinfo_to_se (&rse, &loop);
4064 rse.ss = rss;
4065 gfc_conv_expr (&rse, me);
4068 /* Variable to evaluate mask condition. */
4069 cond = gfc_create_var (mask_type, "cond");
4070 if (mask && (cmask || pmask))
4071 mtmp = gfc_create_var (mask_type, "mask");
4072 else mtmp = NULL_TREE;
4074 gfc_add_block_to_block (&body1, &lse.pre);
4075 gfc_add_block_to_block (&body1, &rse.pre);
4077 gfc_add_modify (&body1, cond, fold_convert (mask_type, rse.expr));
4079 if (mask && (cmask || pmask))
4081 tmp = gfc_build_array_ref (mask, count, NULL);
4082 if (invert)
4083 tmp = fold_build1_loc (input_location, TRUTH_NOT_EXPR, mask_type, tmp);
4084 gfc_add_modify (&body1, mtmp, tmp);
4087 if (cmask)
4089 tmp1 = gfc_build_array_ref (cmask, count, NULL);
4090 tmp = cond;
4091 if (mask)
4092 tmp = fold_build2_loc (input_location, TRUTH_AND_EXPR, mask_type,
4093 mtmp, tmp);
4094 gfc_add_modify (&body1, tmp1, tmp);
4097 if (pmask)
4099 tmp1 = gfc_build_array_ref (pmask, count, NULL);
4100 tmp = fold_build1_loc (input_location, TRUTH_NOT_EXPR, mask_type, cond);
4101 if (mask)
4102 tmp = fold_build2_loc (input_location, TRUTH_AND_EXPR, mask_type, mtmp,
4103 tmp);
4104 gfc_add_modify (&body1, tmp1, tmp);
4107 gfc_add_block_to_block (&body1, &lse.post);
4108 gfc_add_block_to_block (&body1, &rse.post);
4110 if (lss == gfc_ss_terminator)
4112 gfc_add_block_to_block (&body, &body1);
4114 else
4116 /* Increment count. */
4117 tmp1 = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
4118 count, gfc_index_one_node);
4119 gfc_add_modify (&body1, count, tmp1);
4121 /* Generate the copying loops. */
4122 gfc_trans_scalarizing_loops (&loop, &body1);
4124 gfc_add_block_to_block (&body, &loop.pre);
4125 gfc_add_block_to_block (&body, &loop.post);
4127 gfc_cleanup_loop (&loop);
4128 /* TODO: Reuse lss and rss when copying temp->lhs. Need to be careful
4129 as tree nodes in SS may not be valid in different scope. */
4132 tmp1 = gfc_finish_block (&body);
4133 /* If the WHERE construct is inside FORALL, fill the full temporary. */
4134 if (nested_forall_info != NULL)
4135 tmp1 = gfc_trans_nested_forall_loop (nested_forall_info, tmp1, 1);
4137 gfc_add_expr_to_block (block, tmp1);
4141 /* Translate an assignment statement in a WHERE statement or construct
4142 statement. The MASK expression is used to control which elements
4143 of EXPR1 shall be assigned. The sense of MASK is specified by
4144 INVERT. */
4146 static tree
4147 gfc_trans_where_assign (gfc_expr *expr1, gfc_expr *expr2,
4148 tree mask, bool invert,
4149 tree count1, tree count2,
4150 gfc_code *cnext)
4152 gfc_se lse;
4153 gfc_se rse;
4154 gfc_ss *lss;
4155 gfc_ss *lss_section;
4156 gfc_ss *rss;
4158 gfc_loopinfo loop;
4159 tree tmp;
4160 stmtblock_t block;
4161 stmtblock_t body;
4162 tree index, maskexpr;
4164 /* A defined assignment. */
4165 if (cnext && cnext->resolved_sym)
4166 return gfc_trans_call (cnext, true, mask, count1, invert);
4168 #if 0
4169 /* TODO: handle this special case.
4170 Special case a single function returning an array. */
4171 if (expr2->expr_type == EXPR_FUNCTION && expr2->rank > 0)
4173 tmp = gfc_trans_arrayfunc_assign (expr1, expr2);
4174 if (tmp)
4175 return tmp;
4177 #endif
4179 /* Assignment of the form lhs = rhs. */
4180 gfc_start_block (&block);
4182 gfc_init_se (&lse, NULL);
4183 gfc_init_se (&rse, NULL);
4185 /* Walk the lhs. */
4186 lss = gfc_walk_expr (expr1);
4187 rss = NULL;
4189 /* In each where-assign-stmt, the mask-expr and the variable being
4190 defined shall be arrays of the same shape. */
4191 gcc_assert (lss != gfc_ss_terminator);
4193 /* The assignment needs scalarization. */
4194 lss_section = lss;
4196 /* Find a non-scalar SS from the lhs. */
4197 while (lss_section != gfc_ss_terminator
4198 && lss_section->info->type != GFC_SS_SECTION)
4199 lss_section = lss_section->next;
4201 gcc_assert (lss_section != gfc_ss_terminator);
4203 /* Initialize the scalarizer. */
4204 gfc_init_loopinfo (&loop);
4206 /* Walk the rhs. */
4207 rss = gfc_walk_expr (expr2);
4208 if (rss == gfc_ss_terminator)
4210 /* The rhs is scalar. Add a ss for the expression. */
4211 rss = gfc_get_scalar_ss (gfc_ss_terminator, expr2);
4212 rss->info->where = 1;
4215 /* Associate the SS with the loop. */
4216 gfc_add_ss_to_loop (&loop, lss);
4217 gfc_add_ss_to_loop (&loop, rss);
4219 /* Calculate the bounds of the scalarization. */
4220 gfc_conv_ss_startstride (&loop);
4222 /* Resolve any data dependencies in the statement. */
4223 gfc_conv_resolve_dependencies (&loop, lss_section, rss);
4225 /* Setup the scalarizing loops. */
4226 gfc_conv_loop_setup (&loop, &expr2->where);
4228 /* Setup the gfc_se structures. */
4229 gfc_copy_loopinfo_to_se (&lse, &loop);
4230 gfc_copy_loopinfo_to_se (&rse, &loop);
4232 rse.ss = rss;
4233 gfc_mark_ss_chain_used (rss, 1);
4234 if (loop.temp_ss == NULL)
4236 lse.ss = lss;
4237 gfc_mark_ss_chain_used (lss, 1);
4239 else
4241 lse.ss = loop.temp_ss;
4242 gfc_mark_ss_chain_used (lss, 3);
4243 gfc_mark_ss_chain_used (loop.temp_ss, 3);
4246 /* Start the scalarized loop body. */
4247 gfc_start_scalarized_body (&loop, &body);
4249 /* Translate the expression. */
4250 gfc_conv_expr (&rse, expr2);
4251 if (lss != gfc_ss_terminator && loop.temp_ss != NULL)
4252 gfc_conv_tmp_array_ref (&lse);
4253 else
4254 gfc_conv_expr (&lse, expr1);
4256 /* Form the mask expression according to the mask. */
4257 index = count1;
4258 maskexpr = gfc_build_array_ref (mask, index, NULL);
4259 if (invert)
4260 maskexpr = fold_build1_loc (input_location, TRUTH_NOT_EXPR,
4261 TREE_TYPE (maskexpr), maskexpr);
4263 /* Use the scalar assignment as is. */
4264 tmp = gfc_trans_scalar_assign (&lse, &rse, expr1->ts,
4265 loop.temp_ss != NULL, false, true);
4267 tmp = build3_v (COND_EXPR, maskexpr, tmp, build_empty_stmt (input_location));
4269 gfc_add_expr_to_block (&body, tmp);
4271 if (lss == gfc_ss_terminator)
4273 /* Increment count1. */
4274 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
4275 count1, gfc_index_one_node);
4276 gfc_add_modify (&body, count1, tmp);
4278 /* Use the scalar assignment as is. */
4279 gfc_add_block_to_block (&block, &body);
4281 else
4283 gcc_assert (lse.ss == gfc_ss_terminator
4284 && rse.ss == gfc_ss_terminator);
4286 if (loop.temp_ss != NULL)
4288 /* Increment count1 before finish the main body of a scalarized
4289 expression. */
4290 tmp = fold_build2_loc (input_location, PLUS_EXPR,
4291 gfc_array_index_type, count1, gfc_index_one_node);
4292 gfc_add_modify (&body, count1, tmp);
4293 gfc_trans_scalarized_loop_boundary (&loop, &body);
4295 /* We need to copy the temporary to the actual lhs. */
4296 gfc_init_se (&lse, NULL);
4297 gfc_init_se (&rse, NULL);
4298 gfc_copy_loopinfo_to_se (&lse, &loop);
4299 gfc_copy_loopinfo_to_se (&rse, &loop);
4301 rse.ss = loop.temp_ss;
4302 lse.ss = lss;
4304 gfc_conv_tmp_array_ref (&rse);
4305 gfc_conv_expr (&lse, expr1);
4307 gcc_assert (lse.ss == gfc_ss_terminator
4308 && rse.ss == gfc_ss_terminator);
4310 /* Form the mask expression according to the mask tree list. */
4311 index = count2;
4312 maskexpr = gfc_build_array_ref (mask, index, NULL);
4313 if (invert)
4314 maskexpr = fold_build1_loc (input_location, TRUTH_NOT_EXPR,
4315 TREE_TYPE (maskexpr), maskexpr);
4317 /* Use the scalar assignment as is. */
4318 tmp = gfc_trans_scalar_assign (&lse, &rse, expr1->ts, false, false,
4319 true);
4320 tmp = build3_v (COND_EXPR, maskexpr, tmp,
4321 build_empty_stmt (input_location));
4322 gfc_add_expr_to_block (&body, tmp);
4324 /* Increment count2. */
4325 tmp = fold_build2_loc (input_location, PLUS_EXPR,
4326 gfc_array_index_type, count2,
4327 gfc_index_one_node);
4328 gfc_add_modify (&body, count2, tmp);
4330 else
4332 /* Increment count1. */
4333 tmp = fold_build2_loc (input_location, PLUS_EXPR,
4334 gfc_array_index_type, count1,
4335 gfc_index_one_node);
4336 gfc_add_modify (&body, count1, tmp);
4339 /* Generate the copying loops. */
4340 gfc_trans_scalarizing_loops (&loop, &body);
4342 /* Wrap the whole thing up. */
4343 gfc_add_block_to_block (&block, &loop.pre);
4344 gfc_add_block_to_block (&block, &loop.post);
4345 gfc_cleanup_loop (&loop);
4348 return gfc_finish_block (&block);
4352 /* Translate the WHERE construct or statement.
4353 This function can be called iteratively to translate the nested WHERE
4354 construct or statement.
4355 MASK is the control mask. */
4357 static void
4358 gfc_trans_where_2 (gfc_code * code, tree mask, bool invert,
4359 forall_info * nested_forall_info, stmtblock_t * block)
4361 stmtblock_t inner_size_body;
4362 tree inner_size, size;
4363 gfc_ss *lss, *rss;
4364 tree mask_type;
4365 gfc_expr *expr1;
4366 gfc_expr *expr2;
4367 gfc_code *cblock;
4368 gfc_code *cnext;
4369 tree tmp;
4370 tree cond;
4371 tree count1, count2;
4372 bool need_cmask;
4373 bool need_pmask;
4374 int need_temp;
4375 tree pcmask = NULL_TREE;
4376 tree ppmask = NULL_TREE;
4377 tree cmask = NULL_TREE;
4378 tree pmask = NULL_TREE;
4379 gfc_actual_arglist *arg;
4381 /* the WHERE statement or the WHERE construct statement. */
4382 cblock = code->block;
4384 /* As the mask array can be very big, prefer compact boolean types. */
4385 mask_type = gfc_get_logical_type (gfc_logical_kinds[0].kind);
4387 /* Determine which temporary masks are needed. */
4388 if (!cblock->block)
4390 /* One clause: No ELSEWHEREs. */
4391 need_cmask = (cblock->next != 0);
4392 need_pmask = false;
4394 else if (cblock->block->block)
4396 /* Three or more clauses: Conditional ELSEWHEREs. */
4397 need_cmask = true;
4398 need_pmask = true;
4400 else if (cblock->next)
4402 /* Two clauses, the first non-empty. */
4403 need_cmask = true;
4404 need_pmask = (mask != NULL_TREE
4405 && cblock->block->next != 0);
4407 else if (!cblock->block->next)
4409 /* Two clauses, both empty. */
4410 need_cmask = false;
4411 need_pmask = false;
4413 /* Two clauses, the first empty, the second non-empty. */
4414 else if (mask)
4416 need_cmask = (cblock->block->expr1 != 0);
4417 need_pmask = true;
4419 else
4421 need_cmask = true;
4422 need_pmask = false;
4425 if (need_cmask || need_pmask)
4427 /* Calculate the size of temporary needed by the mask-expr. */
4428 gfc_init_block (&inner_size_body);
4429 inner_size = compute_inner_temp_size (cblock->expr1, cblock->expr1,
4430 &inner_size_body, &lss, &rss);
4432 gfc_free_ss_chain (lss);
4433 gfc_free_ss_chain (rss);
4435 /* Calculate the total size of temporary needed. */
4436 size = compute_overall_iter_number (nested_forall_info, inner_size,
4437 &inner_size_body, block);
4439 /* Check whether the size is negative. */
4440 cond = fold_build2_loc (input_location, LE_EXPR, boolean_type_node, size,
4441 gfc_index_zero_node);
4442 size = fold_build3_loc (input_location, COND_EXPR, gfc_array_index_type,
4443 cond, gfc_index_zero_node, size);
4444 size = gfc_evaluate_now (size, block);
4446 /* Allocate temporary for WHERE mask if needed. */
4447 if (need_cmask)
4448 cmask = allocate_temp_for_forall_nest_1 (mask_type, size, block,
4449 &pcmask);
4451 /* Allocate temporary for !mask if needed. */
4452 if (need_pmask)
4453 pmask = allocate_temp_for_forall_nest_1 (mask_type, size, block,
4454 &ppmask);
4457 while (cblock)
4459 /* Each time around this loop, the where clause is conditional
4460 on the value of mask and invert, which are updated at the
4461 bottom of the loop. */
4463 /* Has mask-expr. */
4464 if (cblock->expr1)
4466 /* Ensure that the WHERE mask will be evaluated exactly once.
4467 If there are no statements in this WHERE/ELSEWHERE clause,
4468 then we don't need to update the control mask (cmask).
4469 If this is the last clause of the WHERE construct, then
4470 we don't need to update the pending control mask (pmask). */
4471 if (mask)
4472 gfc_evaluate_where_mask (cblock->expr1, nested_forall_info,
4473 mask, invert,
4474 cblock->next ? cmask : NULL_TREE,
4475 cblock->block ? pmask : NULL_TREE,
4476 mask_type, block);
4477 else
4478 gfc_evaluate_where_mask (cblock->expr1, nested_forall_info,
4479 NULL_TREE, false,
4480 (cblock->next || cblock->block)
4481 ? cmask : NULL_TREE,
4482 NULL_TREE, mask_type, block);
4484 invert = false;
4486 /* It's a final elsewhere-stmt. No mask-expr is present. */
4487 else
4488 cmask = mask;
4490 /* The body of this where clause are controlled by cmask with
4491 sense specified by invert. */
4493 /* Get the assignment statement of a WHERE statement, or the first
4494 statement in where-body-construct of a WHERE construct. */
4495 cnext = cblock->next;
4496 while (cnext)
4498 switch (cnext->op)
4500 /* WHERE assignment statement. */
4501 case EXEC_ASSIGN_CALL:
4503 arg = cnext->ext.actual;
4504 expr1 = expr2 = NULL;
4505 for (; arg; arg = arg->next)
4507 if (!arg->expr)
4508 continue;
4509 if (expr1 == NULL)
4510 expr1 = arg->expr;
4511 else
4512 expr2 = arg->expr;
4514 goto evaluate;
4516 case EXEC_ASSIGN:
4517 expr1 = cnext->expr1;
4518 expr2 = cnext->expr2;
4519 evaluate:
4520 if (nested_forall_info != NULL)
4522 need_temp = gfc_check_dependency (expr1, expr2, 0);
4523 if (need_temp && cnext->op != EXEC_ASSIGN_CALL)
4524 gfc_trans_assign_need_temp (expr1, expr2,
4525 cmask, invert,
4526 nested_forall_info, block);
4527 else
4529 /* Variables to control maskexpr. */
4530 count1 = gfc_create_var (gfc_array_index_type, "count1");
4531 count2 = gfc_create_var (gfc_array_index_type, "count2");
4532 gfc_add_modify (block, count1, gfc_index_zero_node);
4533 gfc_add_modify (block, count2, gfc_index_zero_node);
4535 tmp = gfc_trans_where_assign (expr1, expr2,
4536 cmask, invert,
4537 count1, count2,
4538 cnext);
4540 tmp = gfc_trans_nested_forall_loop (nested_forall_info,
4541 tmp, 1);
4542 gfc_add_expr_to_block (block, tmp);
4545 else
4547 /* Variables to control maskexpr. */
4548 count1 = gfc_create_var (gfc_array_index_type, "count1");
4549 count2 = gfc_create_var (gfc_array_index_type, "count2");
4550 gfc_add_modify (block, count1, gfc_index_zero_node);
4551 gfc_add_modify (block, count2, gfc_index_zero_node);
4553 tmp = gfc_trans_where_assign (expr1, expr2,
4554 cmask, invert,
4555 count1, count2,
4556 cnext);
4557 gfc_add_expr_to_block (block, tmp);
4560 break;
4562 /* WHERE or WHERE construct is part of a where-body-construct. */
4563 case EXEC_WHERE:
4564 gfc_trans_where_2 (cnext, cmask, invert,
4565 nested_forall_info, block);
4566 break;
4568 default:
4569 gcc_unreachable ();
4572 /* The next statement within the same where-body-construct. */
4573 cnext = cnext->next;
4575 /* The next masked-elsewhere-stmt, elsewhere-stmt, or end-where-stmt. */
4576 cblock = cblock->block;
4577 if (mask == NULL_TREE)
4579 /* If we're the initial WHERE, we can simply invert the sense
4580 of the current mask to obtain the "mask" for the remaining
4581 ELSEWHEREs. */
4582 invert = true;
4583 mask = cmask;
4585 else
4587 /* Otherwise, for nested WHERE's we need to use the pending mask. */
4588 invert = false;
4589 mask = pmask;
4593 /* If we allocated a pending mask array, deallocate it now. */
4594 if (ppmask)
4596 tmp = gfc_call_free (ppmask);
4597 gfc_add_expr_to_block (block, tmp);
4600 /* If we allocated a current mask array, deallocate it now. */
4601 if (pcmask)
4603 tmp = gfc_call_free (pcmask);
4604 gfc_add_expr_to_block (block, tmp);
4608 /* Translate a simple WHERE construct or statement without dependencies.
4609 CBLOCK is the "then" clause of the WHERE statement, where CBLOCK->EXPR
4610 is the mask condition, and EBLOCK if non-NULL is the "else" clause.
4611 Currently both CBLOCK and EBLOCK are restricted to single assignments. */
4613 static tree
4614 gfc_trans_where_3 (gfc_code * cblock, gfc_code * eblock)
4616 stmtblock_t block, body;
4617 gfc_expr *cond, *tdst, *tsrc, *edst, *esrc;
4618 tree tmp, cexpr, tstmt, estmt;
4619 gfc_ss *css, *tdss, *tsss;
4620 gfc_se cse, tdse, tsse, edse, esse;
4621 gfc_loopinfo loop;
4622 gfc_ss *edss = 0;
4623 gfc_ss *esss = 0;
4625 /* Allow the scalarizer to workshare simple where loops. */
4626 if (ompws_flags & OMPWS_WORKSHARE_FLAG)
4627 ompws_flags |= OMPWS_SCALARIZER_WS;
4629 cond = cblock->expr1;
4630 tdst = cblock->next->expr1;
4631 tsrc = cblock->next->expr2;
4632 edst = eblock ? eblock->next->expr1 : NULL;
4633 esrc = eblock ? eblock->next->expr2 : NULL;
4635 gfc_start_block (&block);
4636 gfc_init_loopinfo (&loop);
4638 /* Handle the condition. */
4639 gfc_init_se (&cse, NULL);
4640 css = gfc_walk_expr (cond);
4641 gfc_add_ss_to_loop (&loop, css);
4643 /* Handle the then-clause. */
4644 gfc_init_se (&tdse, NULL);
4645 gfc_init_se (&tsse, NULL);
4646 tdss = gfc_walk_expr (tdst);
4647 tsss = gfc_walk_expr (tsrc);
4648 if (tsss == gfc_ss_terminator)
4650 tsss = gfc_get_scalar_ss (gfc_ss_terminator, tsrc);
4651 tsss->info->where = 1;
4653 gfc_add_ss_to_loop (&loop, tdss);
4654 gfc_add_ss_to_loop (&loop, tsss);
4656 if (eblock)
4658 /* Handle the else clause. */
4659 gfc_init_se (&edse, NULL);
4660 gfc_init_se (&esse, NULL);
4661 edss = gfc_walk_expr (edst);
4662 esss = gfc_walk_expr (esrc);
4663 if (esss == gfc_ss_terminator)
4665 esss = gfc_get_scalar_ss (gfc_ss_terminator, esrc);
4666 esss->info->where = 1;
4668 gfc_add_ss_to_loop (&loop, edss);
4669 gfc_add_ss_to_loop (&loop, esss);
4672 gfc_conv_ss_startstride (&loop);
4673 gfc_conv_loop_setup (&loop, &tdst->where);
4675 gfc_mark_ss_chain_used (css, 1);
4676 gfc_mark_ss_chain_used (tdss, 1);
4677 gfc_mark_ss_chain_used (tsss, 1);
4678 if (eblock)
4680 gfc_mark_ss_chain_used (edss, 1);
4681 gfc_mark_ss_chain_used (esss, 1);
4684 gfc_start_scalarized_body (&loop, &body);
4686 gfc_copy_loopinfo_to_se (&cse, &loop);
4687 gfc_copy_loopinfo_to_se (&tdse, &loop);
4688 gfc_copy_loopinfo_to_se (&tsse, &loop);
4689 cse.ss = css;
4690 tdse.ss = tdss;
4691 tsse.ss = tsss;
4692 if (eblock)
4694 gfc_copy_loopinfo_to_se (&edse, &loop);
4695 gfc_copy_loopinfo_to_se (&esse, &loop);
4696 edse.ss = edss;
4697 esse.ss = esss;
4700 gfc_conv_expr (&cse, cond);
4701 gfc_add_block_to_block (&body, &cse.pre);
4702 cexpr = cse.expr;
4704 gfc_conv_expr (&tsse, tsrc);
4705 if (tdss != gfc_ss_terminator && loop.temp_ss != NULL)
4706 gfc_conv_tmp_array_ref (&tdse);
4707 else
4708 gfc_conv_expr (&tdse, tdst);
4710 if (eblock)
4712 gfc_conv_expr (&esse, esrc);
4713 if (edss != gfc_ss_terminator && loop.temp_ss != NULL)
4714 gfc_conv_tmp_array_ref (&edse);
4715 else
4716 gfc_conv_expr (&edse, edst);
4719 tstmt = gfc_trans_scalar_assign (&tdse, &tsse, tdst->ts, false, false, true);
4720 estmt = eblock ? gfc_trans_scalar_assign (&edse, &esse, edst->ts, false,
4721 false, true)
4722 : build_empty_stmt (input_location);
4723 tmp = build3_v (COND_EXPR, cexpr, tstmt, estmt);
4724 gfc_add_expr_to_block (&body, tmp);
4725 gfc_add_block_to_block (&body, &cse.post);
4727 gfc_trans_scalarizing_loops (&loop, &body);
4728 gfc_add_block_to_block (&block, &loop.pre);
4729 gfc_add_block_to_block (&block, &loop.post);
4730 gfc_cleanup_loop (&loop);
4732 return gfc_finish_block (&block);
4735 /* As the WHERE or WHERE construct statement can be nested, we call
4736 gfc_trans_where_2 to do the translation, and pass the initial
4737 NULL values for both the control mask and the pending control mask. */
4739 tree
4740 gfc_trans_where (gfc_code * code)
4742 stmtblock_t block;
4743 gfc_code *cblock;
4744 gfc_code *eblock;
4746 cblock = code->block;
4747 if (cblock->next
4748 && cblock->next->op == EXEC_ASSIGN
4749 && !cblock->next->next)
4751 eblock = cblock->block;
4752 if (!eblock)
4754 /* A simple "WHERE (cond) x = y" statement or block is
4755 dependence free if cond is not dependent upon writing x,
4756 and the source y is unaffected by the destination x. */
4757 if (!gfc_check_dependency (cblock->next->expr1,
4758 cblock->expr1, 0)
4759 && !gfc_check_dependency (cblock->next->expr1,
4760 cblock->next->expr2, 0))
4761 return gfc_trans_where_3 (cblock, NULL);
4763 else if (!eblock->expr1
4764 && !eblock->block
4765 && eblock->next
4766 && eblock->next->op == EXEC_ASSIGN
4767 && !eblock->next->next)
4769 /* A simple "WHERE (cond) x1 = y1 ELSEWHERE x2 = y2 ENDWHERE"
4770 block is dependence free if cond is not dependent on writes
4771 to x1 and x2, y1 is not dependent on writes to x2, and y2
4772 is not dependent on writes to x1, and both y's are not
4773 dependent upon their own x's. In addition to this, the
4774 final two dependency checks below exclude all but the same
4775 array reference if the where and elswhere destinations
4776 are the same. In short, this is VERY conservative and this
4777 is needed because the two loops, required by the standard
4778 are coalesced in gfc_trans_where_3. */
4779 if (!gfc_check_dependency (cblock->next->expr1,
4780 cblock->expr1, 0)
4781 && !gfc_check_dependency (eblock->next->expr1,
4782 cblock->expr1, 0)
4783 && !gfc_check_dependency (cblock->next->expr1,
4784 eblock->next->expr2, 1)
4785 && !gfc_check_dependency (eblock->next->expr1,
4786 cblock->next->expr2, 1)
4787 && !gfc_check_dependency (cblock->next->expr1,
4788 cblock->next->expr2, 1)
4789 && !gfc_check_dependency (eblock->next->expr1,
4790 eblock->next->expr2, 1)
4791 && !gfc_check_dependency (cblock->next->expr1,
4792 eblock->next->expr1, 0)
4793 && !gfc_check_dependency (eblock->next->expr1,
4794 cblock->next->expr1, 0))
4795 return gfc_trans_where_3 (cblock, eblock);
4799 gfc_start_block (&block);
4801 gfc_trans_where_2 (code, NULL, false, NULL, &block);
4803 return gfc_finish_block (&block);
4807 /* CYCLE a DO loop. The label decl has already been created by
4808 gfc_trans_do(), it's in TREE_PURPOSE (backend_decl) of the gfc_code
4809 node at the head of the loop. We must mark the label as used. */
4811 tree
4812 gfc_trans_cycle (gfc_code * code)
4814 tree cycle_label;
4816 cycle_label = code->ext.which_construct->cycle_label;
4817 gcc_assert (cycle_label);
4819 TREE_USED (cycle_label) = 1;
4820 return build1_v (GOTO_EXPR, cycle_label);
4824 /* EXIT a DO loop. Similar to CYCLE, but now the label is in
4825 TREE_VALUE (backend_decl) of the gfc_code node at the head of the
4826 loop. */
4828 tree
4829 gfc_trans_exit (gfc_code * code)
4831 tree exit_label;
4833 exit_label = code->ext.which_construct->exit_label;
4834 gcc_assert (exit_label);
4836 TREE_USED (exit_label) = 1;
4837 return build1_v (GOTO_EXPR, exit_label);
4841 /* Translate the ALLOCATE statement. */
4843 tree
4844 gfc_trans_allocate (gfc_code * code)
4846 gfc_alloc *al;
4847 gfc_expr *e;
4848 gfc_expr *expr;
4849 gfc_se se;
4850 tree tmp;
4851 tree parm;
4852 tree stat;
4853 tree errmsg;
4854 tree errlen;
4855 tree label_errmsg;
4856 tree label_finish;
4857 tree memsz;
4858 tree expr3;
4859 tree slen3;
4860 stmtblock_t block;
4861 stmtblock_t post;
4862 gfc_expr *sz;
4863 gfc_se se_sz;
4864 tree class_expr;
4865 tree nelems;
4866 tree memsize = NULL_TREE;
4867 tree classexpr = NULL_TREE;
4869 if (!code->ext.alloc.list)
4870 return NULL_TREE;
4872 stat = tmp = memsz = NULL_TREE;
4873 label_errmsg = label_finish = errmsg = errlen = NULL_TREE;
4875 gfc_init_block (&block);
4876 gfc_init_block (&post);
4878 /* STAT= (and maybe ERRMSG=) is present. */
4879 if (code->expr1)
4881 /* STAT=. */
4882 tree gfc_int4_type_node = gfc_get_int_type (4);
4883 stat = gfc_create_var (gfc_int4_type_node, "stat");
4885 /* ERRMSG= only makes sense with STAT=. */
4886 if (code->expr2)
4888 gfc_init_se (&se, NULL);
4889 se.want_pointer = 1;
4890 gfc_conv_expr_lhs (&se, code->expr2);
4891 errmsg = se.expr;
4892 errlen = se.string_length;
4894 else
4896 errmsg = null_pointer_node;
4897 errlen = build_int_cst (gfc_charlen_type_node, 0);
4900 /* GOTO destinations. */
4901 label_errmsg = gfc_build_label_decl (NULL_TREE);
4902 label_finish = gfc_build_label_decl (NULL_TREE);
4903 TREE_USED (label_finish) = 0;
4906 expr3 = NULL_TREE;
4907 slen3 = NULL_TREE;
4909 for (al = code->ext.alloc.list; al != NULL; al = al->next)
4911 expr = gfc_copy_expr (al->expr);
4913 if (expr->ts.type == BT_CLASS)
4914 gfc_add_data_component (expr);
4916 gfc_init_se (&se, NULL);
4918 se.want_pointer = 1;
4919 se.descriptor_only = 1;
4920 gfc_conv_expr (&se, expr);
4922 /* Evaluate expr3 just once if not a variable. */
4923 if (al == code->ext.alloc.list
4924 && al->expr->ts.type == BT_CLASS
4925 && code->expr3
4926 && code->expr3->ts.type == BT_CLASS
4927 && code->expr3->expr_type != EXPR_VARIABLE)
4929 gfc_init_se (&se_sz, NULL);
4930 gfc_conv_expr_reference (&se_sz, code->expr3);
4931 gfc_conv_class_to_class (&se_sz, code->expr3,
4932 code->expr3->ts, false, true, false, false);
4933 gfc_add_block_to_block (&se.pre, &se_sz.pre);
4934 gfc_add_block_to_block (&se.post, &se_sz.post);
4935 classexpr = build_fold_indirect_ref_loc (input_location,
4936 se_sz.expr);
4937 classexpr = gfc_evaluate_now (classexpr, &se.pre);
4938 memsize = gfc_vtable_size_get (classexpr);
4939 memsize = fold_convert (sizetype, memsize);
4942 memsz = memsize;
4943 class_expr = classexpr;
4945 nelems = NULL_TREE;
4946 if (!gfc_array_allocate (&se, expr, stat, errmsg, errlen, label_finish,
4947 memsz, &nelems, code->expr3, &code->ext.alloc.ts))
4949 bool unlimited_char;
4951 unlimited_char = UNLIMITED_POLY (al->expr)
4952 && ((code->expr3 && code->expr3->ts.type == BT_CHARACTER)
4953 || (code->ext.alloc.ts.type == BT_CHARACTER
4954 && code->ext.alloc.ts.u.cl
4955 && code->ext.alloc.ts.u.cl->length));
4957 /* A scalar or derived type. */
4959 /* Determine allocate size. */
4960 if (al->expr->ts.type == BT_CLASS
4961 && !unlimited_char
4962 && code->expr3
4963 && memsz == NULL_TREE)
4965 if (code->expr3->ts.type == BT_CLASS)
4967 sz = gfc_copy_expr (code->expr3);
4968 gfc_add_vptr_component (sz);
4969 gfc_add_size_component (sz);
4970 gfc_init_se (&se_sz, NULL);
4971 gfc_conv_expr (&se_sz, sz);
4972 gfc_free_expr (sz);
4973 memsz = se_sz.expr;
4975 else
4976 memsz = TYPE_SIZE_UNIT (gfc_typenode_for_spec (&code->expr3->ts));
4978 else if (((al->expr->ts.type == BT_CHARACTER && al->expr->ts.deferred)
4979 || unlimited_char) && code->expr3)
4981 if (!code->expr3->ts.u.cl->backend_decl)
4983 /* Convert and use the length expression. */
4984 gfc_init_se (&se_sz, NULL);
4985 if (code->expr3->expr_type == EXPR_VARIABLE
4986 || code->expr3->expr_type == EXPR_CONSTANT)
4988 gfc_conv_expr (&se_sz, code->expr3);
4989 gfc_add_block_to_block (&se.pre, &se_sz.pre);
4990 se_sz.string_length
4991 = gfc_evaluate_now (se_sz.string_length, &se.pre);
4992 gfc_add_block_to_block (&se.pre, &se_sz.post);
4993 memsz = se_sz.string_length;
4995 else if (code->expr3->mold
4996 && code->expr3->ts.u.cl
4997 && code->expr3->ts.u.cl->length)
4999 gfc_conv_expr (&se_sz, code->expr3->ts.u.cl->length);
5000 gfc_add_block_to_block (&se.pre, &se_sz.pre);
5001 se_sz.expr = gfc_evaluate_now (se_sz.expr, &se.pre);
5002 gfc_add_block_to_block (&se.pre, &se_sz.post);
5003 memsz = se_sz.expr;
5005 else
5007 /* This is would be inefficient and possibly could
5008 generate wrong code if the result were not stored
5009 in expr3/slen3. */
5010 if (slen3 == NULL_TREE)
5012 gfc_conv_expr (&se_sz, code->expr3);
5013 gfc_add_block_to_block (&se.pre, &se_sz.pre);
5014 expr3 = gfc_evaluate_now (se_sz.expr, &se.pre);
5015 gfc_add_block_to_block (&post, &se_sz.post);
5016 slen3 = gfc_evaluate_now (se_sz.string_length,
5017 &se.pre);
5019 memsz = slen3;
5022 else
5023 /* Otherwise use the stored string length. */
5024 memsz = code->expr3->ts.u.cl->backend_decl;
5025 tmp = al->expr->ts.u.cl->backend_decl;
5027 /* Store the string length. */
5028 if (tmp && TREE_CODE (tmp) == VAR_DECL)
5029 gfc_add_modify (&se.pre, tmp, fold_convert (TREE_TYPE (tmp),
5030 memsz));
5031 else if (al->expr->ts.type == BT_CHARACTER
5032 && al->expr->ts.deferred && se.string_length)
5033 gfc_add_modify (&se.pre, se.string_length,
5034 fold_convert (TREE_TYPE (se.string_length),
5035 memsz));
5037 /* Convert to size in bytes, using the character KIND. */
5038 if (unlimited_char)
5039 tmp = TREE_TYPE (gfc_typenode_for_spec (&code->expr3->ts));
5040 else
5041 tmp = TREE_TYPE (gfc_typenode_for_spec (&al->expr->ts));
5042 tmp = TYPE_SIZE_UNIT (tmp);
5043 memsz = fold_build2_loc (input_location, MULT_EXPR,
5044 TREE_TYPE (tmp), tmp,
5045 fold_convert (TREE_TYPE (tmp), memsz));
5047 else if ((al->expr->ts.type == BT_CHARACTER && al->expr->ts.deferred)
5048 || unlimited_char)
5050 gcc_assert (code->ext.alloc.ts.u.cl && code->ext.alloc.ts.u.cl->length);
5051 gfc_init_se (&se_sz, NULL);
5052 gfc_conv_expr (&se_sz, code->ext.alloc.ts.u.cl->length);
5053 gfc_add_block_to_block (&se.pre, &se_sz.pre);
5054 se_sz.expr = gfc_evaluate_now (se_sz.expr, &se.pre);
5055 gfc_add_block_to_block (&se.pre, &se_sz.post);
5056 /* Store the string length. */
5057 tmp = al->expr->ts.u.cl->backend_decl;
5058 gfc_add_modify (&se.pre, tmp, fold_convert (TREE_TYPE (tmp),
5059 se_sz.expr));
5060 tmp = TREE_TYPE (gfc_typenode_for_spec (&code->ext.alloc.ts));
5061 tmp = TYPE_SIZE_UNIT (tmp);
5062 memsz = fold_build2_loc (input_location, MULT_EXPR,
5063 TREE_TYPE (tmp), tmp,
5064 fold_convert (TREE_TYPE (se_sz.expr),
5065 se_sz.expr));
5067 else if (code->ext.alloc.ts.type != BT_UNKNOWN)
5068 memsz = TYPE_SIZE_UNIT (gfc_typenode_for_spec (&code->ext.alloc.ts));
5069 else if (memsz == NULL_TREE)
5070 memsz = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (se.expr)));
5072 if (expr->ts.type == BT_CHARACTER && memsz == NULL_TREE)
5074 memsz = se.string_length;
5076 /* Convert to size in bytes, using the character KIND. */
5077 tmp = TREE_TYPE (gfc_typenode_for_spec (&code->ext.alloc.ts));
5078 tmp = TYPE_SIZE_UNIT (tmp);
5079 memsz = fold_build2_loc (input_location, MULT_EXPR,
5080 TREE_TYPE (tmp), tmp,
5081 fold_convert (TREE_TYPE (tmp), memsz));
5084 /* Allocate - for non-pointers with re-alloc checking. */
5085 if (gfc_expr_attr (expr).allocatable)
5086 gfc_allocate_allocatable (&se.pre, se.expr, memsz, NULL_TREE,
5087 stat, errmsg, errlen, label_finish, expr);
5088 else
5089 gfc_allocate_using_malloc (&se.pre, se.expr, memsz, stat);
5091 if (al->expr->ts.type == BT_DERIVED
5092 && expr->ts.u.derived->attr.alloc_comp)
5094 tmp = build_fold_indirect_ref_loc (input_location, se.expr);
5095 tmp = gfc_nullify_alloc_comp (expr->ts.u.derived, tmp, 0);
5096 gfc_add_expr_to_block (&se.pre, tmp);
5100 gfc_add_block_to_block (&block, &se.pre);
5102 /* Error checking -- Note: ERRMSG only makes sense with STAT. */
5103 if (code->expr1)
5105 tmp = build1_v (GOTO_EXPR, label_errmsg);
5106 parm = fold_build2_loc (input_location, NE_EXPR,
5107 boolean_type_node, stat,
5108 build_int_cst (TREE_TYPE (stat), 0));
5109 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
5110 gfc_unlikely (parm, PRED_FORTRAN_FAIL_ALLOC),
5111 tmp, build_empty_stmt (input_location));
5112 gfc_add_expr_to_block (&block, tmp);
5115 /* We need the vptr of CLASS objects to be initialized. */
5116 e = gfc_copy_expr (al->expr);
5117 if (e->ts.type == BT_CLASS)
5119 gfc_expr *lhs, *rhs;
5120 gfc_se lse;
5121 gfc_ref *ref, *class_ref, *tail;
5123 /* Find the last class reference. */
5124 class_ref = NULL;
5125 for (ref = e->ref; ref; ref = ref->next)
5127 if (ref->type == REF_COMPONENT
5128 && ref->u.c.component->ts.type == BT_CLASS)
5129 class_ref = ref;
5131 if (ref->next == NULL)
5132 break;
5135 /* Remove and store all subsequent references after the
5136 CLASS reference. */
5137 if (class_ref)
5139 tail = class_ref->next;
5140 class_ref->next = NULL;
5142 else
5144 tail = e->ref;
5145 e->ref = NULL;
5148 lhs = gfc_expr_to_initialize (e);
5149 gfc_add_vptr_component (lhs);
5151 /* Remove the _vptr component and restore the original tail
5152 references. */
5153 if (class_ref)
5155 gfc_free_ref_list (class_ref->next);
5156 class_ref->next = tail;
5158 else
5160 gfc_free_ref_list (e->ref);
5161 e->ref = tail;
5164 if (class_expr != NULL_TREE)
5166 /* Polymorphic SOURCE: VPTR must be determined at run time. */
5167 gfc_init_se (&lse, NULL);
5168 lse.want_pointer = 1;
5169 gfc_conv_expr (&lse, lhs);
5170 tmp = gfc_class_vptr_get (class_expr);
5171 gfc_add_modify (&block, lse.expr,
5172 fold_convert (TREE_TYPE (lse.expr), tmp));
5174 else if (code->expr3 && code->expr3->ts.type == BT_CLASS)
5176 /* Polymorphic SOURCE: VPTR must be determined at run time. */
5177 rhs = gfc_copy_expr (code->expr3);
5178 gfc_add_vptr_component (rhs);
5179 tmp = gfc_trans_pointer_assignment (lhs, rhs);
5180 gfc_add_expr_to_block (&block, tmp);
5181 gfc_free_expr (rhs);
5182 rhs = gfc_expr_to_initialize (e);
5184 else
5186 /* VPTR is fixed at compile time. */
5187 gfc_symbol *vtab;
5188 gfc_typespec *ts;
5189 if (code->expr3)
5190 ts = &code->expr3->ts;
5191 else if (e->ts.type == BT_DERIVED)
5192 ts = &e->ts;
5193 else if (code->ext.alloc.ts.type == BT_DERIVED || UNLIMITED_POLY (al->expr))
5194 ts = &code->ext.alloc.ts;
5195 else if (e->ts.type == BT_CLASS)
5196 ts = &CLASS_DATA (e)->ts;
5197 else
5198 ts = &e->ts;
5200 if (ts->type == BT_DERIVED || UNLIMITED_POLY (e))
5202 vtab = gfc_find_vtab (ts);
5203 gcc_assert (vtab);
5204 gfc_init_se (&lse, NULL);
5205 lse.want_pointer = 1;
5206 gfc_conv_expr (&lse, lhs);
5207 tmp = gfc_build_addr_expr (NULL_TREE,
5208 gfc_get_symbol_decl (vtab));
5209 gfc_add_modify (&block, lse.expr,
5210 fold_convert (TREE_TYPE (lse.expr), tmp));
5213 gfc_free_expr (lhs);
5216 gfc_free_expr (e);
5218 if (code->expr3 && !code->expr3->mold)
5220 /* Initialization via SOURCE block
5221 (or static default initializer). */
5222 gfc_expr *rhs = gfc_copy_expr (code->expr3);
5223 if (class_expr != NULL_TREE)
5225 tree to;
5226 to = TREE_OPERAND (se.expr, 0);
5228 tmp = gfc_copy_class_to_class (class_expr, to, nelems);
5230 else if (al->expr->ts.type == BT_CLASS)
5232 gfc_actual_arglist *actual;
5233 gfc_expr *ppc;
5234 gfc_code *ppc_code;
5235 gfc_ref *ref, *dataref;
5237 /* Do a polymorphic deep copy. */
5238 actual = gfc_get_actual_arglist ();
5239 actual->expr = gfc_copy_expr (rhs);
5240 if (rhs->ts.type == BT_CLASS)
5241 gfc_add_data_component (actual->expr);
5242 actual->next = gfc_get_actual_arglist ();
5243 actual->next->expr = gfc_copy_expr (al->expr);
5244 actual->next->expr->ts.type = BT_CLASS;
5245 gfc_add_data_component (actual->next->expr);
5247 dataref = NULL;
5248 /* Make sure we go up through the reference chain to
5249 the _data reference, where the arrayspec is found. */
5250 for (ref = actual->next->expr->ref; ref; ref = ref->next)
5251 if (ref->type == REF_COMPONENT
5252 && strcmp (ref->u.c.component->name, "_data") == 0)
5253 dataref = ref;
5255 if (dataref && dataref->u.c.component->as)
5257 int dim;
5258 gfc_expr *temp;
5259 gfc_ref *ref = dataref->next;
5260 ref->u.ar.type = AR_SECTION;
5261 /* We have to set up the array reference to give ranges
5262 in all dimensions and ensure that the end and stride
5263 are set so that the copy can be scalarized. */
5264 dim = 0;
5265 for (; dim < dataref->u.c.component->as->rank; dim++)
5267 ref->u.ar.dimen_type[dim] = DIMEN_RANGE;
5268 if (ref->u.ar.end[dim] == NULL)
5270 ref->u.ar.end[dim] = ref->u.ar.start[dim];
5271 temp = gfc_get_int_expr (gfc_default_integer_kind,
5272 &al->expr->where, 1);
5273 ref->u.ar.start[dim] = temp;
5275 temp = gfc_subtract (gfc_copy_expr (ref->u.ar.end[dim]),
5276 gfc_copy_expr (ref->u.ar.start[dim]));
5277 temp = gfc_add (gfc_get_int_expr (gfc_default_integer_kind,
5278 &al->expr->where, 1),
5279 temp);
5282 if (rhs->ts.type == BT_CLASS)
5284 ppc = gfc_copy_expr (rhs);
5285 gfc_add_vptr_component (ppc);
5287 else
5288 ppc = gfc_lval_expr_from_sym (gfc_find_vtab (&rhs->ts));
5289 gfc_add_component_ref (ppc, "_copy");
5291 ppc_code = gfc_get_code (EXEC_CALL);
5292 ppc_code->resolved_sym = ppc->symtree->n.sym;
5293 /* Although '_copy' is set to be elemental in class.c, it is
5294 not staying that way. Find out why, sometime.... */
5295 ppc_code->resolved_sym->attr.elemental = 1;
5296 ppc_code->ext.actual = actual;
5297 ppc_code->expr1 = ppc;
5298 /* Since '_copy' is elemental, the scalarizer will take care
5299 of arrays in gfc_trans_call. */
5300 tmp = gfc_trans_call (ppc_code, true, NULL, NULL, false);
5301 gfc_free_statements (ppc_code);
5303 else if (expr3 != NULL_TREE)
5305 tmp = build_fold_indirect_ref_loc (input_location, se.expr);
5306 gfc_trans_string_copy (&block, slen3, tmp, code->expr3->ts.kind,
5307 slen3, expr3, code->expr3->ts.kind);
5308 tmp = NULL_TREE;
5310 else
5312 /* Switch off automatic reallocation since we have just done
5313 the ALLOCATE. */
5314 int realloc_lhs = gfc_option.flag_realloc_lhs;
5315 gfc_option.flag_realloc_lhs = 0;
5316 tmp = gfc_trans_assignment (gfc_expr_to_initialize (expr),
5317 rhs, false, false);
5318 gfc_option.flag_realloc_lhs = realloc_lhs;
5320 gfc_free_expr (rhs);
5321 gfc_add_expr_to_block (&block, tmp);
5323 else if (code->expr3 && code->expr3->mold
5324 && code->expr3->ts.type == BT_CLASS)
5326 /* Since the _vptr has already been assigned to the allocate
5327 object, we can use gfc_copy_class_to_class in its
5328 initialization mode. */
5329 tmp = TREE_OPERAND (se.expr, 0);
5330 tmp = gfc_copy_class_to_class (NULL_TREE, tmp, nelems);
5331 gfc_add_expr_to_block (&block, tmp);
5334 gfc_free_expr (expr);
5337 /* STAT. */
5338 if (code->expr1)
5340 tmp = build1_v (LABEL_EXPR, label_errmsg);
5341 gfc_add_expr_to_block (&block, tmp);
5344 /* ERRMSG - only useful if STAT is present. */
5345 if (code->expr1 && code->expr2)
5347 const char *msg = "Attempt to allocate an allocated object";
5348 tree slen, dlen, errmsg_str;
5349 stmtblock_t errmsg_block;
5351 gfc_init_block (&errmsg_block);
5353 errmsg_str = gfc_create_var (pchar_type_node, "ERRMSG");
5354 gfc_add_modify (&errmsg_block, errmsg_str,
5355 gfc_build_addr_expr (pchar_type_node,
5356 gfc_build_localized_cstring_const (msg)));
5358 slen = build_int_cst (gfc_charlen_type_node, ((int) strlen (msg)));
5359 dlen = gfc_get_expr_charlen (code->expr2);
5360 slen = fold_build2_loc (input_location, MIN_EXPR, TREE_TYPE (slen), dlen,
5361 slen);
5363 gfc_trans_string_copy (&errmsg_block, dlen, errmsg, code->expr2->ts.kind,
5364 slen, errmsg_str, gfc_default_character_kind);
5365 dlen = gfc_finish_block (&errmsg_block);
5367 tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, stat,
5368 build_int_cst (TREE_TYPE (stat), 0));
5370 tmp = build3_v (COND_EXPR, tmp, dlen, build_empty_stmt (input_location));
5372 gfc_add_expr_to_block (&block, tmp);
5375 /* STAT block. */
5376 if (code->expr1)
5378 if (TREE_USED (label_finish))
5380 tmp = build1_v (LABEL_EXPR, label_finish);
5381 gfc_add_expr_to_block (&block, tmp);
5384 gfc_init_se (&se, NULL);
5385 gfc_conv_expr_lhs (&se, code->expr1);
5386 tmp = convert (TREE_TYPE (se.expr), stat);
5387 gfc_add_modify (&block, se.expr, tmp);
5390 gfc_add_block_to_block (&block, &se.post);
5391 gfc_add_block_to_block (&block, &post);
5393 return gfc_finish_block (&block);
5397 /* Translate a DEALLOCATE statement. */
5399 tree
5400 gfc_trans_deallocate (gfc_code *code)
5402 gfc_se se;
5403 gfc_alloc *al;
5404 tree apstat, pstat, stat, errmsg, errlen, tmp;
5405 tree label_finish, label_errmsg;
5406 stmtblock_t block;
5408 pstat = apstat = stat = errmsg = errlen = tmp = NULL_TREE;
5409 label_finish = label_errmsg = NULL_TREE;
5411 gfc_start_block (&block);
5413 /* Count the number of failed deallocations. If deallocate() was
5414 called with STAT= , then set STAT to the count. If deallocate
5415 was called with ERRMSG, then set ERRMG to a string. */
5416 if (code->expr1)
5418 tree gfc_int4_type_node = gfc_get_int_type (4);
5420 stat = gfc_create_var (gfc_int4_type_node, "stat");
5421 pstat = gfc_build_addr_expr (NULL_TREE, stat);
5423 /* GOTO destinations. */
5424 label_errmsg = gfc_build_label_decl (NULL_TREE);
5425 label_finish = gfc_build_label_decl (NULL_TREE);
5426 TREE_USED (label_finish) = 0;
5429 /* Set ERRMSG - only needed if STAT is available. */
5430 if (code->expr1 && code->expr2)
5432 gfc_init_se (&se, NULL);
5433 se.want_pointer = 1;
5434 gfc_conv_expr_lhs (&se, code->expr2);
5435 errmsg = se.expr;
5436 errlen = se.string_length;
5439 for (al = code->ext.alloc.list; al != NULL; al = al->next)
5441 gfc_expr *expr = gfc_copy_expr (al->expr);
5442 gcc_assert (expr->expr_type == EXPR_VARIABLE);
5444 if (expr->ts.type == BT_CLASS)
5445 gfc_add_data_component (expr);
5447 gfc_init_se (&se, NULL);
5448 gfc_start_block (&se.pre);
5450 se.want_pointer = 1;
5451 se.descriptor_only = 1;
5452 gfc_conv_expr (&se, expr);
5454 if (expr->rank || gfc_is_coarray (expr))
5456 if (expr->ts.type == BT_DERIVED && expr->ts.u.derived->attr.alloc_comp
5457 && !gfc_is_finalizable (expr->ts.u.derived, NULL))
5459 gfc_ref *ref;
5460 gfc_ref *last = NULL;
5461 for (ref = expr->ref; ref; ref = ref->next)
5462 if (ref->type == REF_COMPONENT)
5463 last = ref;
5465 /* Do not deallocate the components of a derived type
5466 ultimate pointer component. */
5467 if (!(last && last->u.c.component->attr.pointer)
5468 && !(!last && expr->symtree->n.sym->attr.pointer))
5470 tmp = gfc_deallocate_alloc_comp (expr->ts.u.derived, se.expr,
5471 expr->rank);
5472 gfc_add_expr_to_block (&se.pre, tmp);
5475 tmp = gfc_array_deallocate (se.expr, pstat, errmsg, errlen,
5476 label_finish, expr);
5477 gfc_add_expr_to_block (&se.pre, tmp);
5478 if (al->expr->ts.type == BT_CLASS)
5479 gfc_reset_vptr (&se.pre, al->expr);
5481 else
5483 tmp = gfc_deallocate_scalar_with_status (se.expr, pstat, false,
5484 al->expr, al->expr->ts);
5485 gfc_add_expr_to_block (&se.pre, tmp);
5487 /* Set to zero after deallocation. */
5488 tmp = fold_build2_loc (input_location, MODIFY_EXPR, void_type_node,
5489 se.expr,
5490 build_int_cst (TREE_TYPE (se.expr), 0));
5491 gfc_add_expr_to_block (&se.pre, tmp);
5493 if (al->expr->ts.type == BT_CLASS)
5494 gfc_reset_vptr (&se.pre, al->expr);
5497 if (code->expr1)
5499 tree cond;
5501 cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, stat,
5502 build_int_cst (TREE_TYPE (stat), 0));
5503 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
5504 gfc_unlikely (cond, PRED_FORTRAN_FAIL_ALLOC),
5505 build1_v (GOTO_EXPR, label_errmsg),
5506 build_empty_stmt (input_location));
5507 gfc_add_expr_to_block (&se.pre, tmp);
5510 tmp = gfc_finish_block (&se.pre);
5511 gfc_add_expr_to_block (&block, tmp);
5512 gfc_free_expr (expr);
5515 if (code->expr1)
5517 tmp = build1_v (LABEL_EXPR, label_errmsg);
5518 gfc_add_expr_to_block (&block, tmp);
5521 /* Set ERRMSG - only needed if STAT is available. */
5522 if (code->expr1 && code->expr2)
5524 const char *msg = "Attempt to deallocate an unallocated object";
5525 stmtblock_t errmsg_block;
5526 tree errmsg_str, slen, dlen, cond;
5528 gfc_init_block (&errmsg_block);
5530 errmsg_str = gfc_create_var (pchar_type_node, "ERRMSG");
5531 gfc_add_modify (&errmsg_block, errmsg_str,
5532 gfc_build_addr_expr (pchar_type_node,
5533 gfc_build_localized_cstring_const (msg)));
5534 slen = build_int_cst (gfc_charlen_type_node, ((int) strlen (msg)));
5535 dlen = gfc_get_expr_charlen (code->expr2);
5537 gfc_trans_string_copy (&errmsg_block, dlen, errmsg, code->expr2->ts.kind,
5538 slen, errmsg_str, gfc_default_character_kind);
5539 tmp = gfc_finish_block (&errmsg_block);
5541 cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, stat,
5542 build_int_cst (TREE_TYPE (stat), 0));
5543 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
5544 gfc_unlikely (cond, PRED_FORTRAN_FAIL_ALLOC), tmp,
5545 build_empty_stmt (input_location));
5547 gfc_add_expr_to_block (&block, tmp);
5550 if (code->expr1 && TREE_USED (label_finish))
5552 tmp = build1_v (LABEL_EXPR, label_finish);
5553 gfc_add_expr_to_block (&block, tmp);
5556 /* Set STAT. */
5557 if (code->expr1)
5559 gfc_init_se (&se, NULL);
5560 gfc_conv_expr_lhs (&se, code->expr1);
5561 tmp = convert (TREE_TYPE (se.expr), stat);
5562 gfc_add_modify (&block, se.expr, tmp);
5565 return gfc_finish_block (&block);
5568 #include "gt-fortran-trans-stmt.h"