Rebase.
[official-gcc.git] / gcc / fortran / trans-stmt.c
blob547e9c1bb91b38cfc0c054d5babc325a85aa2344
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 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_num_images,
788 2, integer_zero_node,
789 build_int_cst (integer_type_node, -1));
790 cond = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
791 images, tmp);
792 cond2 = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
793 images,
794 build_int_cst (TREE_TYPE (images), 1));
795 cond = fold_build2_loc (input_location, TRUTH_OR_EXPR,
796 boolean_type_node, cond, cond2);
798 gfc_trans_runtime_check (true, false, cond, &se.pre,
799 &code->expr1->where, "Invalid image number "
800 "%d in SYNC IMAGES",
801 fold_convert (integer_type_node, images));
804 /* Per F2008, 8.5.1, a SYNC MEMORY is implied by calling the
805 image control statements SYNC IMAGES and SYNC ALL. */
806 if (gfc_option.coarray == GFC_FCOARRAY_LIB)
808 tmp = builtin_decl_explicit (BUILT_IN_SYNC_SYNCHRONIZE);
809 tmp = build_call_expr_loc (input_location, tmp, 0);
810 gfc_add_expr_to_block (&se.pre, tmp);
813 if (gfc_option.coarray != GFC_FCOARRAY_LIB || type == EXEC_SYNC_MEMORY)
815 /* Set STAT to zero. */
816 if (code->expr2)
817 gfc_add_modify (&se.pre, stat, build_int_cst (TREE_TYPE (stat), 0));
819 else if (type == EXEC_SYNC_ALL)
821 /* SYNC ALL => stat == null_pointer_node
822 SYNC ALL(stat=s) => stat has an integer type
824 If "stat" has the wrong integer type, use a temp variable of
825 the right type and later cast the result back into "stat". */
826 if (stat == null_pointer_node || TREE_TYPE (stat) == integer_type_node)
828 if (TREE_TYPE (stat) == integer_type_node)
829 stat = gfc_build_addr_expr (NULL, stat);
831 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sync_all,
832 3, stat, errmsg, errmsglen);
833 gfc_add_expr_to_block (&se.pre, tmp);
835 else
837 tree tmp_stat = gfc_create_var (integer_type_node, "stat");
839 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sync_all,
840 3, gfc_build_addr_expr (NULL, tmp_stat),
841 errmsg, errmsglen);
842 gfc_add_expr_to_block (&se.pre, tmp);
844 gfc_add_modify (&se.pre, stat,
845 fold_convert (TREE_TYPE (stat), tmp_stat));
848 else
850 tree len;
852 gcc_assert (type == EXEC_SYNC_IMAGES);
854 if (!code->expr1)
856 len = build_int_cst (integer_type_node, -1);
857 images = null_pointer_node;
859 else if (code->expr1->rank == 0)
861 len = build_int_cst (integer_type_node, 1);
862 images = gfc_build_addr_expr (NULL_TREE, images);
864 else
866 /* FIXME. */
867 if (code->expr1->ts.kind != gfc_c_int_kind)
868 gfc_fatal_error ("Sorry, only support for integer kind %d "
869 "implemented for image-set at %L",
870 gfc_c_int_kind, &code->expr1->where);
872 gfc_conv_array_parameter (&se, code->expr1, true, NULL, NULL, &len);
873 images = se.expr;
875 tmp = gfc_typenode_for_spec (&code->expr1->ts);
876 if (GFC_ARRAY_TYPE_P (tmp) || GFC_DESCRIPTOR_TYPE_P (tmp))
877 tmp = gfc_get_element_type (tmp);
879 len = fold_build2_loc (input_location, TRUNC_DIV_EXPR,
880 TREE_TYPE (len), len,
881 fold_convert (TREE_TYPE (len),
882 TYPE_SIZE_UNIT (tmp)));
883 len = fold_convert (integer_type_node, len);
886 /* SYNC IMAGES(imgs) => stat == null_pointer_node
887 SYNC IMAGES(imgs,stat=s) => stat has an integer type
889 If "stat" has the wrong integer type, use a temp variable of
890 the right type and later cast the result back into "stat". */
891 if (stat == null_pointer_node || TREE_TYPE (stat) == integer_type_node)
893 if (TREE_TYPE (stat) == integer_type_node)
894 stat = gfc_build_addr_expr (NULL, stat);
896 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sync_images,
897 5, fold_convert (integer_type_node, len),
898 images, stat, errmsg, errmsglen);
899 gfc_add_expr_to_block (&se.pre, tmp);
901 else
903 tree tmp_stat = gfc_create_var (integer_type_node, "stat");
905 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sync_images,
906 5, fold_convert (integer_type_node, len),
907 images, gfc_build_addr_expr (NULL, tmp_stat),
908 errmsg, errmsglen);
909 gfc_add_expr_to_block (&se.pre, tmp);
911 gfc_add_modify (&se.pre, stat,
912 fold_convert (TREE_TYPE (stat), tmp_stat));
916 return gfc_finish_block (&se.pre);
920 /* Generate GENERIC for the IF construct. This function also deals with
921 the simple IF statement, because the front end translates the IF
922 statement into an IF construct.
924 We translate:
926 IF (cond) THEN
927 then_clause
928 ELSEIF (cond2)
929 elseif_clause
930 ELSE
931 else_clause
932 ENDIF
934 into:
936 pre_cond_s;
937 if (cond_s)
939 then_clause;
941 else
943 pre_cond_s
944 if (cond_s)
946 elseif_clause
948 else
950 else_clause;
954 where COND_S is the simplified version of the predicate. PRE_COND_S
955 are the pre side-effects produced by the translation of the
956 conditional.
957 We need to build the chain recursively otherwise we run into
958 problems with folding incomplete statements. */
960 static tree
961 gfc_trans_if_1 (gfc_code * code)
963 gfc_se if_se;
964 tree stmt, elsestmt;
965 locus saved_loc;
966 location_t loc;
968 /* Check for an unconditional ELSE clause. */
969 if (!code->expr1)
970 return gfc_trans_code (code->next);
972 /* Initialize a statement builder for each block. Puts in NULL_TREEs. */
973 gfc_init_se (&if_se, NULL);
974 gfc_start_block (&if_se.pre);
976 /* Calculate the IF condition expression. */
977 if (code->expr1->where.lb)
979 gfc_save_backend_locus (&saved_loc);
980 gfc_set_backend_locus (&code->expr1->where);
983 gfc_conv_expr_val (&if_se, code->expr1);
985 if (code->expr1->where.lb)
986 gfc_restore_backend_locus (&saved_loc);
988 /* Translate the THEN clause. */
989 stmt = gfc_trans_code (code->next);
991 /* Translate the ELSE clause. */
992 if (code->block)
993 elsestmt = gfc_trans_if_1 (code->block);
994 else
995 elsestmt = build_empty_stmt (input_location);
997 /* Build the condition expression and add it to the condition block. */
998 loc = code->expr1->where.lb ? code->expr1->where.lb->location : input_location;
999 stmt = fold_build3_loc (loc, COND_EXPR, void_type_node, if_se.expr, stmt,
1000 elsestmt);
1002 gfc_add_expr_to_block (&if_se.pre, stmt);
1004 /* Finish off this statement. */
1005 return gfc_finish_block (&if_se.pre);
1008 tree
1009 gfc_trans_if (gfc_code * code)
1011 stmtblock_t body;
1012 tree exit_label;
1014 /* Create exit label so it is available for trans'ing the body code. */
1015 exit_label = gfc_build_label_decl (NULL_TREE);
1016 code->exit_label = exit_label;
1018 /* Translate the actual code in code->block. */
1019 gfc_init_block (&body);
1020 gfc_add_expr_to_block (&body, gfc_trans_if_1 (code->block));
1022 /* Add exit label. */
1023 gfc_add_expr_to_block (&body, build1_v (LABEL_EXPR, exit_label));
1025 return gfc_finish_block (&body);
1029 /* Translate an arithmetic IF expression.
1031 IF (cond) label1, label2, label3 translates to
1033 if (cond <= 0)
1035 if (cond < 0)
1036 goto label1;
1037 else // cond == 0
1038 goto label2;
1040 else // cond > 0
1041 goto label3;
1043 An optimized version can be generated in case of equal labels.
1044 E.g., if label1 is equal to label2, we can translate it to
1046 if (cond <= 0)
1047 goto label1;
1048 else
1049 goto label3;
1052 tree
1053 gfc_trans_arithmetic_if (gfc_code * code)
1055 gfc_se se;
1056 tree tmp;
1057 tree branch1;
1058 tree branch2;
1059 tree zero;
1061 /* Start a new block. */
1062 gfc_init_se (&se, NULL);
1063 gfc_start_block (&se.pre);
1065 /* Pre-evaluate COND. */
1066 gfc_conv_expr_val (&se, code->expr1);
1067 se.expr = gfc_evaluate_now (se.expr, &se.pre);
1069 /* Build something to compare with. */
1070 zero = gfc_build_const (TREE_TYPE (se.expr), integer_zero_node);
1072 if (code->label1->value != code->label2->value)
1074 /* If (cond < 0) take branch1 else take branch2.
1075 First build jumps to the COND .LT. 0 and the COND .EQ. 0 cases. */
1076 branch1 = build1_v (GOTO_EXPR, gfc_get_label_decl (code->label1));
1077 branch2 = build1_v (GOTO_EXPR, gfc_get_label_decl (code->label2));
1079 if (code->label1->value != code->label3->value)
1080 tmp = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
1081 se.expr, zero);
1082 else
1083 tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
1084 se.expr, zero);
1086 branch1 = fold_build3_loc (input_location, COND_EXPR, void_type_node,
1087 tmp, branch1, branch2);
1089 else
1090 branch1 = build1_v (GOTO_EXPR, gfc_get_label_decl (code->label1));
1092 if (code->label1->value != code->label3->value
1093 && code->label2->value != code->label3->value)
1095 /* if (cond <= 0) take branch1 else take branch2. */
1096 branch2 = build1_v (GOTO_EXPR, gfc_get_label_decl (code->label3));
1097 tmp = fold_build2_loc (input_location, LE_EXPR, boolean_type_node,
1098 se.expr, zero);
1099 branch1 = fold_build3_loc (input_location, COND_EXPR, void_type_node,
1100 tmp, branch1, branch2);
1103 /* Append the COND_EXPR to the evaluation of COND, and return. */
1104 gfc_add_expr_to_block (&se.pre, branch1);
1105 return gfc_finish_block (&se.pre);
1109 /* Translate a CRITICAL block. */
1110 tree
1111 gfc_trans_critical (gfc_code *code)
1113 stmtblock_t block;
1114 tree tmp;
1116 gfc_start_block (&block);
1118 if (gfc_option.coarray == GFC_FCOARRAY_LIB)
1120 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_critical, 0);
1121 gfc_add_expr_to_block (&block, tmp);
1124 tmp = gfc_trans_code (code->block->next);
1125 gfc_add_expr_to_block (&block, tmp);
1127 if (gfc_option.coarray == GFC_FCOARRAY_LIB)
1129 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_end_critical,
1131 gfc_add_expr_to_block (&block, tmp);
1135 return gfc_finish_block (&block);
1139 /* Do proper initialization for ASSOCIATE names. */
1141 static void
1142 trans_associate_var (gfc_symbol *sym, gfc_wrapped_block *block)
1144 gfc_expr *e;
1145 tree tmp;
1146 bool class_target;
1147 bool unlimited;
1148 tree desc;
1149 tree offset;
1150 tree dim;
1151 int n;
1153 gcc_assert (sym->assoc);
1154 e = sym->assoc->target;
1156 class_target = (e->expr_type == EXPR_VARIABLE)
1157 && (gfc_is_class_scalar_expr (e)
1158 || gfc_is_class_array_ref (e, NULL));
1160 unlimited = UNLIMITED_POLY (e);
1162 /* Do a `pointer assignment' with updated descriptor (or assign descriptor
1163 to array temporary) for arrays with either unknown shape or if associating
1164 to a variable. */
1165 if (sym->attr.dimension && !class_target
1166 && (sym->as->type == AS_DEFERRED || sym->assoc->variable))
1168 gfc_se se;
1169 tree desc;
1170 bool cst_array_ctor;
1172 desc = sym->backend_decl;
1173 cst_array_ctor = e->expr_type == EXPR_ARRAY
1174 && gfc_constant_array_constructor_p (e->value.constructor);
1176 /* If association is to an expression, evaluate it and create temporary.
1177 Otherwise, get descriptor of target for pointer assignment. */
1178 gfc_init_se (&se, NULL);
1179 if (sym->assoc->variable || cst_array_ctor)
1181 se.direct_byref = 1;
1182 se.use_offset = 1;
1183 se.expr = desc;
1186 gfc_conv_expr_descriptor (&se, e);
1188 /* If we didn't already do the pointer assignment, set associate-name
1189 descriptor to the one generated for the temporary. */
1190 if (!sym->assoc->variable && !cst_array_ctor)
1192 int dim;
1194 gfc_add_modify (&se.pre, desc, se.expr);
1196 /* The generated descriptor has lower bound zero (as array
1197 temporary), shift bounds so we get lower bounds of 1. */
1198 for (dim = 0; dim < e->rank; ++dim)
1199 gfc_conv_shift_descriptor_lbound (&se.pre, desc,
1200 dim, gfc_index_one_node);
1203 /* If this is a subreference array pointer associate name use the
1204 associate variable element size for the value of 'span'. */
1205 if (sym->attr.subref_array_pointer)
1207 gcc_assert (e->expr_type == EXPR_VARIABLE);
1208 tmp = e->symtree->n.sym->backend_decl;
1209 tmp = gfc_get_element_type (TREE_TYPE (tmp));
1210 tmp = fold_convert (gfc_array_index_type, size_in_bytes (tmp));
1211 gfc_add_modify (&se.pre, GFC_DECL_SPAN(desc), tmp);
1214 /* Done, register stuff as init / cleanup code. */
1215 gfc_add_init_cleanup (block, gfc_finish_block (&se.pre),
1216 gfc_finish_block (&se.post));
1219 /* Temporaries, arising from TYPE IS, just need the descriptor of class
1220 arrays to be assigned directly. */
1221 else if (class_target && sym->attr.dimension
1222 && (sym->ts.type == BT_DERIVED || unlimited))
1224 gfc_se se;
1226 gfc_init_se (&se, NULL);
1227 se.descriptor_only = 1;
1228 gfc_conv_expr (&se, e);
1230 gcc_assert (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (se.expr)));
1231 gcc_assert (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (sym->backend_decl)));
1233 gfc_add_modify (&se.pre, sym->backend_decl, se.expr);
1235 if (unlimited)
1237 /* Recover the dtype, which has been overwritten by the
1238 assignment from an unlimited polymorphic object. */
1239 tmp = gfc_conv_descriptor_dtype (sym->backend_decl);
1240 gfc_add_modify (&se.pre, tmp,
1241 gfc_get_dtype (TREE_TYPE (sym->backend_decl)));
1244 gfc_add_init_cleanup (block, gfc_finish_block( &se.pre),
1245 gfc_finish_block (&se.post));
1248 /* Do a scalar pointer assignment; this is for scalar variable targets. */
1249 else if (gfc_is_associate_pointer (sym))
1251 gfc_se se;
1253 gcc_assert (!sym->attr.dimension);
1255 gfc_init_se (&se, NULL);
1257 /* Class associate-names come this way because they are
1258 unconditionally associate pointers and the symbol is scalar. */
1259 if (sym->ts.type == BT_CLASS && CLASS_DATA (sym)->attr.dimension)
1261 /* For a class array we need a descriptor for the selector. */
1262 gfc_conv_expr_descriptor (&se, e);
1264 /* Obtain a temporary class container for the result. */
1265 gfc_conv_class_to_class (&se, e, sym->ts, false, true, false, false);
1266 se.expr = build_fold_indirect_ref_loc (input_location, se.expr);
1268 /* Set the offset. */
1269 desc = gfc_class_data_get (se.expr);
1270 offset = gfc_index_zero_node;
1271 for (n = 0; n < e->rank; n++)
1273 dim = gfc_rank_cst[n];
1274 tmp = fold_build2_loc (input_location, MULT_EXPR,
1275 gfc_array_index_type,
1276 gfc_conv_descriptor_stride_get (desc, dim),
1277 gfc_conv_descriptor_lbound_get (desc, dim));
1278 offset = fold_build2_loc (input_location, MINUS_EXPR,
1279 gfc_array_index_type,
1280 offset, tmp);
1282 gfc_conv_descriptor_offset_set (&se.pre, desc, offset);
1284 else if (sym->ts.type == BT_CLASS && e->ts.type == BT_CLASS
1285 && CLASS_DATA (e)->attr.dimension)
1287 /* This is bound to be a class array element. */
1288 gfc_conv_expr_reference (&se, e);
1289 /* Get the _vptr component of the class object. */
1290 tmp = gfc_get_vptr_from_expr (se.expr);
1291 /* Obtain a temporary class container for the result. */
1292 gfc_conv_derived_to_class (&se, e, sym->ts, tmp, false, false);
1293 se.expr = build_fold_indirect_ref_loc (input_location, se.expr);
1295 else
1296 gfc_conv_expr (&se, e);
1298 tmp = TREE_TYPE (sym->backend_decl);
1299 tmp = gfc_build_addr_expr (tmp, se.expr);
1300 gfc_add_modify (&se.pre, sym->backend_decl, tmp);
1302 gfc_add_init_cleanup (block, gfc_finish_block( &se.pre),
1303 gfc_finish_block (&se.post));
1306 /* Do a simple assignment. This is for scalar expressions, where we
1307 can simply use expression assignment. */
1308 else
1310 gfc_expr *lhs;
1312 lhs = gfc_lval_expr_from_sym (sym);
1313 tmp = gfc_trans_assignment (lhs, e, false, true);
1314 gfc_add_init_cleanup (block, tmp, NULL_TREE);
1317 /* Set the stringlength from the vtable size. */
1318 if (sym->ts.type == BT_CHARACTER && sym->attr.select_type_temporary)
1320 tree charlen;
1321 gfc_se se;
1322 gfc_init_se (&se, NULL);
1323 gcc_assert (UNLIMITED_POLY (e->symtree->n.sym));
1324 tmp = gfc_get_symbol_decl (e->symtree->n.sym);
1325 tmp = gfc_vtable_size_get (tmp);
1326 gfc_get_symbol_decl (sym);
1327 charlen = sym->ts.u.cl->backend_decl;
1328 gfc_add_modify (&se.pre, charlen,
1329 fold_convert (TREE_TYPE (charlen), tmp));
1330 gfc_add_init_cleanup (block, gfc_finish_block( &se.pre),
1331 gfc_finish_block (&se.post));
1336 /* Translate a BLOCK construct. This is basically what we would do for a
1337 procedure body. */
1339 tree
1340 gfc_trans_block_construct (gfc_code* code)
1342 gfc_namespace* ns;
1343 gfc_symbol* sym;
1344 gfc_wrapped_block block;
1345 tree exit_label;
1346 stmtblock_t body;
1347 gfc_association_list *ass;
1349 ns = code->ext.block.ns;
1350 gcc_assert (ns);
1351 sym = ns->proc_name;
1352 gcc_assert (sym);
1354 /* Process local variables. */
1355 gcc_assert (!sym->tlink);
1356 sym->tlink = sym;
1357 gfc_process_block_locals (ns);
1359 /* Generate code including exit-label. */
1360 gfc_init_block (&body);
1361 exit_label = gfc_build_label_decl (NULL_TREE);
1362 code->exit_label = exit_label;
1363 gfc_add_expr_to_block (&body, gfc_trans_code (ns->code));
1364 gfc_add_expr_to_block (&body, build1_v (LABEL_EXPR, exit_label));
1366 /* Finish everything. */
1367 gfc_start_wrapped_block (&block, gfc_finish_block (&body));
1368 gfc_trans_deferred_vars (sym, &block);
1369 for (ass = code->ext.block.assoc; ass; ass = ass->next)
1370 trans_associate_var (ass->st->n.sym, &block);
1372 return gfc_finish_wrapped_block (&block);
1376 /* Translate the simple DO construct. This is where the loop variable has
1377 integer type and step +-1. We can't use this in the general case
1378 because integer overflow and floating point errors could give incorrect
1379 results.
1380 We translate a do loop from:
1382 DO dovar = from, to, step
1383 body
1384 END DO
1388 [Evaluate loop bounds and step]
1389 dovar = from;
1390 if ((step > 0) ? (dovar <= to) : (dovar => to))
1392 for (;;)
1394 body;
1395 cycle_label:
1396 cond = (dovar == to);
1397 dovar += step;
1398 if (cond) goto end_label;
1401 end_label:
1403 This helps the optimizers by avoiding the extra induction variable
1404 used in the general case. */
1406 static tree
1407 gfc_trans_simple_do (gfc_code * code, stmtblock_t *pblock, tree dovar,
1408 tree from, tree to, tree step, tree exit_cond)
1410 stmtblock_t body;
1411 tree type;
1412 tree cond;
1413 tree tmp;
1414 tree saved_dovar = NULL;
1415 tree cycle_label;
1416 tree exit_label;
1417 location_t loc;
1419 type = TREE_TYPE (dovar);
1421 loc = code->ext.iterator->start->where.lb->location;
1423 /* Initialize the DO variable: dovar = from. */
1424 gfc_add_modify_loc (loc, pblock, dovar,
1425 fold_convert (TREE_TYPE(dovar), from));
1427 /* Save value for do-tinkering checking. */
1428 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
1430 saved_dovar = gfc_create_var (type, ".saved_dovar");
1431 gfc_add_modify_loc (loc, pblock, saved_dovar, dovar);
1434 /* Cycle and exit statements are implemented with gotos. */
1435 cycle_label = gfc_build_label_decl (NULL_TREE);
1436 exit_label = gfc_build_label_decl (NULL_TREE);
1438 /* Put the labels where they can be found later. See gfc_trans_do(). */
1439 code->cycle_label = cycle_label;
1440 code->exit_label = exit_label;
1442 /* Loop body. */
1443 gfc_start_block (&body);
1445 /* Main loop body. */
1446 tmp = gfc_trans_code_cond (code->block->next, exit_cond);
1447 gfc_add_expr_to_block (&body, tmp);
1449 /* Label for cycle statements (if needed). */
1450 if (TREE_USED (cycle_label))
1452 tmp = build1_v (LABEL_EXPR, cycle_label);
1453 gfc_add_expr_to_block (&body, tmp);
1456 /* Check whether someone has modified the loop variable. */
1457 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
1459 tmp = fold_build2_loc (loc, NE_EXPR, boolean_type_node,
1460 dovar, saved_dovar);
1461 gfc_trans_runtime_check (true, false, tmp, &body, &code->loc,
1462 "Loop variable has been modified");
1465 /* Exit the loop if there is an I/O result condition or error. */
1466 if (exit_cond)
1468 tmp = build1_v (GOTO_EXPR, exit_label);
1469 tmp = fold_build3_loc (loc, COND_EXPR, void_type_node,
1470 exit_cond, tmp,
1471 build_empty_stmt (loc));
1472 gfc_add_expr_to_block (&body, tmp);
1475 /* Evaluate the loop condition. */
1476 cond = fold_build2_loc (loc, EQ_EXPR, boolean_type_node, dovar,
1477 to);
1478 cond = gfc_evaluate_now_loc (loc, cond, &body);
1480 /* Increment the loop variable. */
1481 tmp = fold_build2_loc (loc, PLUS_EXPR, type, dovar, step);
1482 gfc_add_modify_loc (loc, &body, dovar, tmp);
1484 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
1485 gfc_add_modify_loc (loc, &body, saved_dovar, dovar);
1487 /* The loop exit. */
1488 tmp = fold_build1_loc (loc, GOTO_EXPR, void_type_node, exit_label);
1489 TREE_USED (exit_label) = 1;
1490 tmp = fold_build3_loc (loc, COND_EXPR, void_type_node,
1491 cond, tmp, build_empty_stmt (loc));
1492 gfc_add_expr_to_block (&body, tmp);
1494 /* Finish the loop body. */
1495 tmp = gfc_finish_block (&body);
1496 tmp = fold_build1_loc (loc, LOOP_EXPR, void_type_node, tmp);
1498 /* Only execute the loop if the number of iterations is positive. */
1499 if (tree_int_cst_sgn (step) > 0)
1500 cond = fold_build2_loc (loc, LE_EXPR, boolean_type_node, dovar,
1501 to);
1502 else
1503 cond = fold_build2_loc (loc, GE_EXPR, boolean_type_node, dovar,
1504 to);
1505 tmp = fold_build3_loc (loc, COND_EXPR, void_type_node, cond, tmp,
1506 build_empty_stmt (loc));
1507 gfc_add_expr_to_block (pblock, tmp);
1509 /* Add the exit label. */
1510 tmp = build1_v (LABEL_EXPR, exit_label);
1511 gfc_add_expr_to_block (pblock, tmp);
1513 return gfc_finish_block (pblock);
1516 /* Translate the DO construct. This obviously is one of the most
1517 important ones to get right with any compiler, but especially
1518 so for Fortran.
1520 We special case some loop forms as described in gfc_trans_simple_do.
1521 For other cases we implement them with a separate loop count,
1522 as described in the standard.
1524 We translate a do loop from:
1526 DO dovar = from, to, step
1527 body
1528 END DO
1532 [evaluate loop bounds and step]
1533 empty = (step > 0 ? to < from : to > from);
1534 countm1 = (to - from) / step;
1535 dovar = from;
1536 if (empty) goto exit_label;
1537 for (;;)
1539 body;
1540 cycle_label:
1541 dovar += step
1542 countm1t = countm1;
1543 countm1--;
1544 if (countm1t == 0) goto exit_label;
1546 exit_label:
1548 countm1 is an unsigned integer. It is equal to the loop count minus one,
1549 because the loop count itself can overflow. */
1551 tree
1552 gfc_trans_do (gfc_code * code, tree exit_cond)
1554 gfc_se se;
1555 tree dovar;
1556 tree saved_dovar = NULL;
1557 tree from;
1558 tree to;
1559 tree step;
1560 tree countm1;
1561 tree type;
1562 tree utype;
1563 tree cond;
1564 tree cycle_label;
1565 tree exit_label;
1566 tree tmp;
1567 stmtblock_t block;
1568 stmtblock_t body;
1569 location_t loc;
1571 gfc_start_block (&block);
1573 loc = code->ext.iterator->start->where.lb->location;
1575 /* Evaluate all the expressions in the iterator. */
1576 gfc_init_se (&se, NULL);
1577 gfc_conv_expr_lhs (&se, code->ext.iterator->var);
1578 gfc_add_block_to_block (&block, &se.pre);
1579 dovar = se.expr;
1580 type = TREE_TYPE (dovar);
1582 gfc_init_se (&se, NULL);
1583 gfc_conv_expr_val (&se, code->ext.iterator->start);
1584 gfc_add_block_to_block (&block, &se.pre);
1585 from = gfc_evaluate_now (se.expr, &block);
1587 gfc_init_se (&se, NULL);
1588 gfc_conv_expr_val (&se, code->ext.iterator->end);
1589 gfc_add_block_to_block (&block, &se.pre);
1590 to = gfc_evaluate_now (se.expr, &block);
1592 gfc_init_se (&se, NULL);
1593 gfc_conv_expr_val (&se, code->ext.iterator->step);
1594 gfc_add_block_to_block (&block, &se.pre);
1595 step = gfc_evaluate_now (se.expr, &block);
1597 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
1599 tmp = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, step,
1600 build_zero_cst (type));
1601 gfc_trans_runtime_check (true, false, tmp, &block, &code->loc,
1602 "DO step value is zero");
1605 /* Special case simple loops. */
1606 if (TREE_CODE (type) == INTEGER_TYPE
1607 && (integer_onep (step)
1608 || tree_int_cst_equal (step, integer_minus_one_node)))
1609 return gfc_trans_simple_do (code, &block, dovar, from, to, step, exit_cond);
1612 if (TREE_CODE (type) == INTEGER_TYPE)
1613 utype = unsigned_type_for (type);
1614 else
1615 utype = unsigned_type_for (gfc_array_index_type);
1616 countm1 = gfc_create_var (utype, "countm1");
1618 /* Cycle and exit statements are implemented with gotos. */
1619 cycle_label = gfc_build_label_decl (NULL_TREE);
1620 exit_label = gfc_build_label_decl (NULL_TREE);
1621 TREE_USED (exit_label) = 1;
1623 /* Put these labels where they can be found later. */
1624 code->cycle_label = cycle_label;
1625 code->exit_label = exit_label;
1627 /* Initialize the DO variable: dovar = from. */
1628 gfc_add_modify (&block, dovar, from);
1630 /* Save value for do-tinkering checking. */
1631 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
1633 saved_dovar = gfc_create_var (type, ".saved_dovar");
1634 gfc_add_modify_loc (loc, &block, saved_dovar, dovar);
1637 /* Initialize loop count and jump to exit label if the loop is empty.
1638 This code is executed before we enter the loop body. We generate:
1639 if (step > 0)
1641 if (to < from)
1642 goto exit_label;
1643 countm1 = (to - from) / step;
1645 else
1647 if (to > from)
1648 goto exit_label;
1649 countm1 = (from - to) / -step;
1653 if (TREE_CODE (type) == INTEGER_TYPE)
1655 tree pos, neg, tou, fromu, stepu, tmp2;
1657 /* The distance from FROM to TO cannot always be represented in a signed
1658 type, thus use unsigned arithmetic, also to avoid any undefined
1659 overflow issues. */
1660 tou = fold_convert (utype, to);
1661 fromu = fold_convert (utype, from);
1662 stepu = fold_convert (utype, step);
1664 /* For a positive step, when to < from, exit, otherwise compute
1665 countm1 = ((unsigned)to - (unsigned)from) / (unsigned)step */
1666 tmp = fold_build2_loc (loc, LT_EXPR, boolean_type_node, to, from);
1667 tmp2 = fold_build2_loc (loc, TRUNC_DIV_EXPR, utype,
1668 fold_build2_loc (loc, MINUS_EXPR, utype,
1669 tou, fromu),
1670 stepu);
1671 pos = fold_build3_loc (loc, COND_EXPR, void_type_node, tmp,
1672 fold_build1_loc (loc, GOTO_EXPR, void_type_node,
1673 exit_label),
1674 fold_build2 (MODIFY_EXPR, void_type_node,
1675 countm1, tmp2));
1677 /* For a negative step, when to > from, exit, otherwise compute
1678 countm1 = ((unsigned)from - (unsigned)to) / -(unsigned)step */
1679 tmp = fold_build2_loc (loc, GT_EXPR, boolean_type_node, to, from);
1680 tmp2 = fold_build2_loc (loc, TRUNC_DIV_EXPR, utype,
1681 fold_build2_loc (loc, MINUS_EXPR, utype,
1682 fromu, tou),
1683 fold_build1_loc (loc, NEGATE_EXPR, utype, stepu));
1684 neg = fold_build3_loc (loc, COND_EXPR, void_type_node, tmp,
1685 fold_build1_loc (loc, GOTO_EXPR, void_type_node,
1686 exit_label),
1687 fold_build2 (MODIFY_EXPR, void_type_node,
1688 countm1, tmp2));
1690 tmp = fold_build2_loc (loc, LT_EXPR, boolean_type_node, step,
1691 build_int_cst (TREE_TYPE (step), 0));
1692 tmp = fold_build3_loc (loc, COND_EXPR, void_type_node, tmp, neg, pos);
1694 gfc_add_expr_to_block (&block, tmp);
1696 else
1698 tree pos_step;
1700 /* TODO: We could use the same width as the real type.
1701 This would probably cause more problems that it solves
1702 when we implement "long double" types. */
1704 tmp = fold_build2_loc (loc, MINUS_EXPR, type, to, from);
1705 tmp = fold_build2_loc (loc, RDIV_EXPR, type, tmp, step);
1706 tmp = fold_build1_loc (loc, FIX_TRUNC_EXPR, utype, tmp);
1707 gfc_add_modify (&block, countm1, tmp);
1709 /* We need a special check for empty loops:
1710 empty = (step > 0 ? to < from : to > from); */
1711 pos_step = fold_build2_loc (loc, GT_EXPR, boolean_type_node, step,
1712 build_zero_cst (type));
1713 tmp = fold_build3_loc (loc, COND_EXPR, boolean_type_node, pos_step,
1714 fold_build2_loc (loc, LT_EXPR,
1715 boolean_type_node, to, from),
1716 fold_build2_loc (loc, GT_EXPR,
1717 boolean_type_node, to, from));
1718 /* If the loop is empty, go directly to the exit label. */
1719 tmp = fold_build3_loc (loc, COND_EXPR, void_type_node, tmp,
1720 build1_v (GOTO_EXPR, exit_label),
1721 build_empty_stmt (input_location));
1722 gfc_add_expr_to_block (&block, tmp);
1725 /* Loop body. */
1726 gfc_start_block (&body);
1728 /* Main loop body. */
1729 tmp = gfc_trans_code_cond (code->block->next, exit_cond);
1730 gfc_add_expr_to_block (&body, tmp);
1732 /* Label for cycle statements (if needed). */
1733 if (TREE_USED (cycle_label))
1735 tmp = build1_v (LABEL_EXPR, cycle_label);
1736 gfc_add_expr_to_block (&body, tmp);
1739 /* Check whether someone has modified the loop variable. */
1740 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
1742 tmp = fold_build2_loc (loc, NE_EXPR, boolean_type_node, dovar,
1743 saved_dovar);
1744 gfc_trans_runtime_check (true, false, tmp, &body, &code->loc,
1745 "Loop variable has been modified");
1748 /* Exit the loop if there is an I/O result condition or error. */
1749 if (exit_cond)
1751 tmp = build1_v (GOTO_EXPR, exit_label);
1752 tmp = fold_build3_loc (loc, COND_EXPR, void_type_node,
1753 exit_cond, tmp,
1754 build_empty_stmt (input_location));
1755 gfc_add_expr_to_block (&body, tmp);
1758 /* Increment the loop variable. */
1759 tmp = fold_build2_loc (loc, PLUS_EXPR, type, dovar, step);
1760 gfc_add_modify_loc (loc, &body, dovar, tmp);
1762 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
1763 gfc_add_modify_loc (loc, &body, saved_dovar, dovar);
1765 /* Initialize countm1t. */
1766 tree countm1t = gfc_create_var (utype, "countm1t");
1767 gfc_add_modify_loc (loc, &body, countm1t, countm1);
1769 /* Decrement the loop count. */
1770 tmp = fold_build2_loc (loc, MINUS_EXPR, utype, countm1,
1771 build_int_cst (utype, 1));
1772 gfc_add_modify_loc (loc, &body, countm1, tmp);
1774 /* End with the loop condition. Loop until countm1t == 0. */
1775 cond = fold_build2_loc (loc, EQ_EXPR, boolean_type_node, countm1t,
1776 build_int_cst (utype, 0));
1777 tmp = fold_build1_loc (loc, GOTO_EXPR, void_type_node, exit_label);
1778 tmp = fold_build3_loc (loc, COND_EXPR, void_type_node,
1779 cond, tmp, build_empty_stmt (loc));
1780 gfc_add_expr_to_block (&body, tmp);
1782 /* End of loop body. */
1783 tmp = gfc_finish_block (&body);
1785 /* The for loop itself. */
1786 tmp = fold_build1_loc (loc, LOOP_EXPR, void_type_node, tmp);
1787 gfc_add_expr_to_block (&block, tmp);
1789 /* Add the exit label. */
1790 tmp = build1_v (LABEL_EXPR, exit_label);
1791 gfc_add_expr_to_block (&block, tmp);
1793 return gfc_finish_block (&block);
1797 /* Translate the DO WHILE construct.
1799 We translate
1801 DO WHILE (cond)
1802 body
1803 END DO
1807 for ( ; ; )
1809 pre_cond;
1810 if (! cond) goto exit_label;
1811 body;
1812 cycle_label:
1814 exit_label:
1816 Because the evaluation of the exit condition `cond' may have side
1817 effects, we can't do much for empty loop bodies. The backend optimizers
1818 should be smart enough to eliminate any dead loops. */
1820 tree
1821 gfc_trans_do_while (gfc_code * code)
1823 gfc_se cond;
1824 tree tmp;
1825 tree cycle_label;
1826 tree exit_label;
1827 stmtblock_t block;
1829 /* Everything we build here is part of the loop body. */
1830 gfc_start_block (&block);
1832 /* Cycle and exit statements are implemented with gotos. */
1833 cycle_label = gfc_build_label_decl (NULL_TREE);
1834 exit_label = gfc_build_label_decl (NULL_TREE);
1836 /* Put the labels where they can be found later. See gfc_trans_do(). */
1837 code->cycle_label = cycle_label;
1838 code->exit_label = exit_label;
1840 /* Create a GIMPLE version of the exit condition. */
1841 gfc_init_se (&cond, NULL);
1842 gfc_conv_expr_val (&cond, code->expr1);
1843 gfc_add_block_to_block (&block, &cond.pre);
1844 cond.expr = fold_build1_loc (code->expr1->where.lb->location,
1845 TRUTH_NOT_EXPR, TREE_TYPE (cond.expr), cond.expr);
1847 /* Build "IF (! cond) GOTO exit_label". */
1848 tmp = build1_v (GOTO_EXPR, exit_label);
1849 TREE_USED (exit_label) = 1;
1850 tmp = fold_build3_loc (code->expr1->where.lb->location, COND_EXPR,
1851 void_type_node, cond.expr, tmp,
1852 build_empty_stmt (code->expr1->where.lb->location));
1853 gfc_add_expr_to_block (&block, tmp);
1855 /* The main body of the loop. */
1856 tmp = gfc_trans_code (code->block->next);
1857 gfc_add_expr_to_block (&block, tmp);
1859 /* Label for cycle statements (if needed). */
1860 if (TREE_USED (cycle_label))
1862 tmp = build1_v (LABEL_EXPR, cycle_label);
1863 gfc_add_expr_to_block (&block, tmp);
1866 /* End of loop body. */
1867 tmp = gfc_finish_block (&block);
1869 gfc_init_block (&block);
1870 /* Build the loop. */
1871 tmp = fold_build1_loc (code->expr1->where.lb->location, LOOP_EXPR,
1872 void_type_node, tmp);
1873 gfc_add_expr_to_block (&block, tmp);
1875 /* Add the exit label. */
1876 tmp = build1_v (LABEL_EXPR, exit_label);
1877 gfc_add_expr_to_block (&block, tmp);
1879 return gfc_finish_block (&block);
1883 /* Translate the SELECT CASE construct for INTEGER case expressions,
1884 without killing all potential optimizations. The problem is that
1885 Fortran allows unbounded cases, but the back-end does not, so we
1886 need to intercept those before we enter the equivalent SWITCH_EXPR
1887 we can build.
1889 For example, we translate this,
1891 SELECT CASE (expr)
1892 CASE (:100,101,105:115)
1893 block_1
1894 CASE (190:199,200:)
1895 block_2
1896 CASE (300)
1897 block_3
1898 CASE DEFAULT
1899 block_4
1900 END SELECT
1902 to the GENERIC equivalent,
1904 switch (expr)
1906 case (minimum value for typeof(expr) ... 100:
1907 case 101:
1908 case 105 ... 114:
1909 block1:
1910 goto end_label;
1912 case 200 ... (maximum value for typeof(expr):
1913 case 190 ... 199:
1914 block2;
1915 goto end_label;
1917 case 300:
1918 block_3;
1919 goto end_label;
1921 default:
1922 block_4;
1923 goto end_label;
1926 end_label: */
1928 static tree
1929 gfc_trans_integer_select (gfc_code * code)
1931 gfc_code *c;
1932 gfc_case *cp;
1933 tree end_label;
1934 tree tmp;
1935 gfc_se se;
1936 stmtblock_t block;
1937 stmtblock_t body;
1939 gfc_start_block (&block);
1941 /* Calculate the switch expression. */
1942 gfc_init_se (&se, NULL);
1943 gfc_conv_expr_val (&se, code->expr1);
1944 gfc_add_block_to_block (&block, &se.pre);
1946 end_label = gfc_build_label_decl (NULL_TREE);
1948 gfc_init_block (&body);
1950 for (c = code->block; c; c = c->block)
1952 for (cp = c->ext.block.case_list; cp; cp = cp->next)
1954 tree low, high;
1955 tree label;
1957 /* Assume it's the default case. */
1958 low = high = NULL_TREE;
1960 if (cp->low)
1962 low = gfc_conv_mpz_to_tree (cp->low->value.integer,
1963 cp->low->ts.kind);
1965 /* If there's only a lower bound, set the high bound to the
1966 maximum value of the case expression. */
1967 if (!cp->high)
1968 high = TYPE_MAX_VALUE (TREE_TYPE (se.expr));
1971 if (cp->high)
1973 /* Three cases are possible here:
1975 1) There is no lower bound, e.g. CASE (:N).
1976 2) There is a lower bound .NE. high bound, that is
1977 a case range, e.g. CASE (N:M) where M>N (we make
1978 sure that M>N during type resolution).
1979 3) There is a lower bound, and it has the same value
1980 as the high bound, e.g. CASE (N:N). This is our
1981 internal representation of CASE(N).
1983 In the first and second case, we need to set a value for
1984 high. In the third case, we don't because the GCC middle
1985 end represents a single case value by just letting high be
1986 a NULL_TREE. We can't do that because we need to be able
1987 to represent unbounded cases. */
1989 if (!cp->low
1990 || (cp->low
1991 && mpz_cmp (cp->low->value.integer,
1992 cp->high->value.integer) != 0))
1993 high = gfc_conv_mpz_to_tree (cp->high->value.integer,
1994 cp->high->ts.kind);
1996 /* Unbounded case. */
1997 if (!cp->low)
1998 low = TYPE_MIN_VALUE (TREE_TYPE (se.expr));
2001 /* Build a label. */
2002 label = gfc_build_label_decl (NULL_TREE);
2004 /* Add this case label.
2005 Add parameter 'label', make it match GCC backend. */
2006 tmp = build_case_label (low, high, label);
2007 gfc_add_expr_to_block (&body, tmp);
2010 /* Add the statements for this case. */
2011 tmp = gfc_trans_code (c->next);
2012 gfc_add_expr_to_block (&body, tmp);
2014 /* Break to the end of the construct. */
2015 tmp = build1_v (GOTO_EXPR, end_label);
2016 gfc_add_expr_to_block (&body, tmp);
2019 tmp = gfc_finish_block (&body);
2020 tmp = fold_build3_loc (input_location, SWITCH_EXPR, NULL_TREE,
2021 se.expr, tmp, NULL_TREE);
2022 gfc_add_expr_to_block (&block, tmp);
2024 tmp = build1_v (LABEL_EXPR, end_label);
2025 gfc_add_expr_to_block (&block, tmp);
2027 return gfc_finish_block (&block);
2031 /* Translate the SELECT CASE construct for LOGICAL case expressions.
2033 There are only two cases possible here, even though the standard
2034 does allow three cases in a LOGICAL SELECT CASE construct: .TRUE.,
2035 .FALSE., and DEFAULT.
2037 We never generate more than two blocks here. Instead, we always
2038 try to eliminate the DEFAULT case. This way, we can translate this
2039 kind of SELECT construct to a simple
2041 if {} else {};
2043 expression in GENERIC. */
2045 static tree
2046 gfc_trans_logical_select (gfc_code * code)
2048 gfc_code *c;
2049 gfc_code *t, *f, *d;
2050 gfc_case *cp;
2051 gfc_se se;
2052 stmtblock_t block;
2054 /* Assume we don't have any cases at all. */
2055 t = f = d = NULL;
2057 /* Now see which ones we actually do have. We can have at most two
2058 cases in a single case list: one for .TRUE. and one for .FALSE.
2059 The default case is always separate. If the cases for .TRUE. and
2060 .FALSE. are in the same case list, the block for that case list
2061 always executed, and we don't generate code a COND_EXPR. */
2062 for (c = code->block; c; c = c->block)
2064 for (cp = c->ext.block.case_list; cp; cp = cp->next)
2066 if (cp->low)
2068 if (cp->low->value.logical == 0) /* .FALSE. */
2069 f = c;
2070 else /* if (cp->value.logical != 0), thus .TRUE. */
2071 t = c;
2073 else
2074 d = c;
2078 /* Start a new block. */
2079 gfc_start_block (&block);
2081 /* Calculate the switch expression. We always need to do this
2082 because it may have side effects. */
2083 gfc_init_se (&se, NULL);
2084 gfc_conv_expr_val (&se, code->expr1);
2085 gfc_add_block_to_block (&block, &se.pre);
2087 if (t == f && t != NULL)
2089 /* Cases for .TRUE. and .FALSE. are in the same block. Just
2090 translate the code for these cases, append it to the current
2091 block. */
2092 gfc_add_expr_to_block (&block, gfc_trans_code (t->next));
2094 else
2096 tree true_tree, false_tree, stmt;
2098 true_tree = build_empty_stmt (input_location);
2099 false_tree = build_empty_stmt (input_location);
2101 /* If we have a case for .TRUE. and for .FALSE., discard the default case.
2102 Otherwise, if .TRUE. or .FALSE. is missing and there is a default case,
2103 make the missing case the default case. */
2104 if (t != NULL && f != NULL)
2105 d = NULL;
2106 else if (d != NULL)
2108 if (t == NULL)
2109 t = d;
2110 else
2111 f = d;
2114 /* Translate the code for each of these blocks, and append it to
2115 the current block. */
2116 if (t != NULL)
2117 true_tree = gfc_trans_code (t->next);
2119 if (f != NULL)
2120 false_tree = gfc_trans_code (f->next);
2122 stmt = fold_build3_loc (input_location, COND_EXPR, void_type_node,
2123 se.expr, true_tree, false_tree);
2124 gfc_add_expr_to_block (&block, stmt);
2127 return gfc_finish_block (&block);
2131 /* The jump table types are stored in static variables to avoid
2132 constructing them from scratch every single time. */
2133 static GTY(()) tree select_struct[2];
2135 /* Translate the SELECT CASE construct for CHARACTER case expressions.
2136 Instead of generating compares and jumps, it is far simpler to
2137 generate a data structure describing the cases in order and call a
2138 library subroutine that locates the right case.
2139 This is particularly true because this is the only case where we
2140 might have to dispose of a temporary.
2141 The library subroutine returns a pointer to jump to or NULL if no
2142 branches are to be taken. */
2144 static tree
2145 gfc_trans_character_select (gfc_code *code)
2147 tree init, end_label, tmp, type, case_num, label, fndecl;
2148 stmtblock_t block, body;
2149 gfc_case *cp, *d;
2150 gfc_code *c;
2151 gfc_se se, expr1se;
2152 int n, k;
2153 vec<constructor_elt, va_gc> *inits = NULL;
2155 tree pchartype = gfc_get_pchar_type (code->expr1->ts.kind);
2157 /* The jump table types are stored in static variables to avoid
2158 constructing them from scratch every single time. */
2159 static tree ss_string1[2], ss_string1_len[2];
2160 static tree ss_string2[2], ss_string2_len[2];
2161 static tree ss_target[2];
2163 cp = code->block->ext.block.case_list;
2164 while (cp->left != NULL)
2165 cp = cp->left;
2167 /* Generate the body */
2168 gfc_start_block (&block);
2169 gfc_init_se (&expr1se, NULL);
2170 gfc_conv_expr_reference (&expr1se, code->expr1);
2172 gfc_add_block_to_block (&block, &expr1se.pre);
2174 end_label = gfc_build_label_decl (NULL_TREE);
2176 gfc_init_block (&body);
2178 /* Attempt to optimize length 1 selects. */
2179 if (integer_onep (expr1se.string_length))
2181 for (d = cp; d; d = d->right)
2183 int i;
2184 if (d->low)
2186 gcc_assert (d->low->expr_type == EXPR_CONSTANT
2187 && d->low->ts.type == BT_CHARACTER);
2188 if (d->low->value.character.length > 1)
2190 for (i = 1; i < d->low->value.character.length; i++)
2191 if (d->low->value.character.string[i] != ' ')
2192 break;
2193 if (i != d->low->value.character.length)
2195 if (optimize && d->high && i == 1)
2197 gcc_assert (d->high->expr_type == EXPR_CONSTANT
2198 && d->high->ts.type == BT_CHARACTER);
2199 if (d->high->value.character.length > 1
2200 && (d->low->value.character.string[0]
2201 == d->high->value.character.string[0])
2202 && d->high->value.character.string[1] != ' '
2203 && ((d->low->value.character.string[1] < ' ')
2204 == (d->high->value.character.string[1]
2205 < ' ')))
2206 continue;
2208 break;
2212 if (d->high)
2214 gcc_assert (d->high->expr_type == EXPR_CONSTANT
2215 && d->high->ts.type == BT_CHARACTER);
2216 if (d->high->value.character.length > 1)
2218 for (i = 1; i < d->high->value.character.length; i++)
2219 if (d->high->value.character.string[i] != ' ')
2220 break;
2221 if (i != d->high->value.character.length)
2222 break;
2226 if (d == NULL)
2228 tree ctype = gfc_get_char_type (code->expr1->ts.kind);
2230 for (c = code->block; c; c = c->block)
2232 for (cp = c->ext.block.case_list; cp; cp = cp->next)
2234 tree low, high;
2235 tree label;
2236 gfc_char_t r;
2238 /* Assume it's the default case. */
2239 low = high = NULL_TREE;
2241 if (cp->low)
2243 /* CASE ('ab') or CASE ('ab':'az') will never match
2244 any length 1 character. */
2245 if (cp->low->value.character.length > 1
2246 && cp->low->value.character.string[1] != ' ')
2247 continue;
2249 if (cp->low->value.character.length > 0)
2250 r = cp->low->value.character.string[0];
2251 else
2252 r = ' ';
2253 low = build_int_cst (ctype, r);
2255 /* If there's only a lower bound, set the high bound
2256 to the maximum value of the case expression. */
2257 if (!cp->high)
2258 high = TYPE_MAX_VALUE (ctype);
2261 if (cp->high)
2263 if (!cp->low
2264 || (cp->low->value.character.string[0]
2265 != cp->high->value.character.string[0]))
2267 if (cp->high->value.character.length > 0)
2268 r = cp->high->value.character.string[0];
2269 else
2270 r = ' ';
2271 high = build_int_cst (ctype, r);
2274 /* Unbounded case. */
2275 if (!cp->low)
2276 low = TYPE_MIN_VALUE (ctype);
2279 /* Build a label. */
2280 label = gfc_build_label_decl (NULL_TREE);
2282 /* Add this case label.
2283 Add parameter 'label', make it match GCC backend. */
2284 tmp = build_case_label (low, high, label);
2285 gfc_add_expr_to_block (&body, tmp);
2288 /* Add the statements for this case. */
2289 tmp = gfc_trans_code (c->next);
2290 gfc_add_expr_to_block (&body, tmp);
2292 /* Break to the end of the construct. */
2293 tmp = build1_v (GOTO_EXPR, end_label);
2294 gfc_add_expr_to_block (&body, tmp);
2297 tmp = gfc_string_to_single_character (expr1se.string_length,
2298 expr1se.expr,
2299 code->expr1->ts.kind);
2300 case_num = gfc_create_var (ctype, "case_num");
2301 gfc_add_modify (&block, case_num, tmp);
2303 gfc_add_block_to_block (&block, &expr1se.post);
2305 tmp = gfc_finish_block (&body);
2306 tmp = fold_build3_loc (input_location, SWITCH_EXPR, NULL_TREE,
2307 case_num, tmp, NULL_TREE);
2308 gfc_add_expr_to_block (&block, tmp);
2310 tmp = build1_v (LABEL_EXPR, end_label);
2311 gfc_add_expr_to_block (&block, tmp);
2313 return gfc_finish_block (&block);
2317 if (code->expr1->ts.kind == 1)
2318 k = 0;
2319 else if (code->expr1->ts.kind == 4)
2320 k = 1;
2321 else
2322 gcc_unreachable ();
2324 if (select_struct[k] == NULL)
2326 tree *chain = NULL;
2327 select_struct[k] = make_node (RECORD_TYPE);
2329 if (code->expr1->ts.kind == 1)
2330 TYPE_NAME (select_struct[k]) = get_identifier ("_jump_struct_char1");
2331 else if (code->expr1->ts.kind == 4)
2332 TYPE_NAME (select_struct[k]) = get_identifier ("_jump_struct_char4");
2333 else
2334 gcc_unreachable ();
2336 #undef ADD_FIELD
2337 #define ADD_FIELD(NAME, TYPE) \
2338 ss_##NAME[k] = gfc_add_field_to_struct (select_struct[k], \
2339 get_identifier (stringize(NAME)), \
2340 TYPE, \
2341 &chain)
2343 ADD_FIELD (string1, pchartype);
2344 ADD_FIELD (string1_len, gfc_charlen_type_node);
2346 ADD_FIELD (string2, pchartype);
2347 ADD_FIELD (string2_len, gfc_charlen_type_node);
2349 ADD_FIELD (target, integer_type_node);
2350 #undef ADD_FIELD
2352 gfc_finish_type (select_struct[k]);
2355 n = 0;
2356 for (d = cp; d; d = d->right)
2357 d->n = n++;
2359 for (c = code->block; c; c = c->block)
2361 for (d = c->ext.block.case_list; d; d = d->next)
2363 label = gfc_build_label_decl (NULL_TREE);
2364 tmp = build_case_label ((d->low == NULL && d->high == NULL)
2365 ? NULL
2366 : build_int_cst (integer_type_node, d->n),
2367 NULL, label);
2368 gfc_add_expr_to_block (&body, tmp);
2371 tmp = gfc_trans_code (c->next);
2372 gfc_add_expr_to_block (&body, tmp);
2374 tmp = build1_v (GOTO_EXPR, end_label);
2375 gfc_add_expr_to_block (&body, tmp);
2378 /* Generate the structure describing the branches */
2379 for (d = cp; d; d = d->right)
2381 vec<constructor_elt, va_gc> *node = NULL;
2383 gfc_init_se (&se, NULL);
2385 if (d->low == NULL)
2387 CONSTRUCTOR_APPEND_ELT (node, ss_string1[k], null_pointer_node);
2388 CONSTRUCTOR_APPEND_ELT (node, ss_string1_len[k], integer_zero_node);
2390 else
2392 gfc_conv_expr_reference (&se, d->low);
2394 CONSTRUCTOR_APPEND_ELT (node, ss_string1[k], se.expr);
2395 CONSTRUCTOR_APPEND_ELT (node, ss_string1_len[k], se.string_length);
2398 if (d->high == NULL)
2400 CONSTRUCTOR_APPEND_ELT (node, ss_string2[k], null_pointer_node);
2401 CONSTRUCTOR_APPEND_ELT (node, ss_string2_len[k], integer_zero_node);
2403 else
2405 gfc_init_se (&se, NULL);
2406 gfc_conv_expr_reference (&se, d->high);
2408 CONSTRUCTOR_APPEND_ELT (node, ss_string2[k], se.expr);
2409 CONSTRUCTOR_APPEND_ELT (node, ss_string2_len[k], se.string_length);
2412 CONSTRUCTOR_APPEND_ELT (node, ss_target[k],
2413 build_int_cst (integer_type_node, d->n));
2415 tmp = build_constructor (select_struct[k], node);
2416 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, tmp);
2419 type = build_array_type (select_struct[k],
2420 build_index_type (size_int (n-1)));
2422 init = build_constructor (type, inits);
2423 TREE_CONSTANT (init) = 1;
2424 TREE_STATIC (init) = 1;
2425 /* Create a static variable to hold the jump table. */
2426 tmp = gfc_create_var (type, "jumptable");
2427 TREE_CONSTANT (tmp) = 1;
2428 TREE_STATIC (tmp) = 1;
2429 TREE_READONLY (tmp) = 1;
2430 DECL_INITIAL (tmp) = init;
2431 init = tmp;
2433 /* Build the library call */
2434 init = gfc_build_addr_expr (pvoid_type_node, init);
2436 if (code->expr1->ts.kind == 1)
2437 fndecl = gfor_fndecl_select_string;
2438 else if (code->expr1->ts.kind == 4)
2439 fndecl = gfor_fndecl_select_string_char4;
2440 else
2441 gcc_unreachable ();
2443 tmp = build_call_expr_loc (input_location,
2444 fndecl, 4, init,
2445 build_int_cst (gfc_charlen_type_node, n),
2446 expr1se.expr, expr1se.string_length);
2447 case_num = gfc_create_var (integer_type_node, "case_num");
2448 gfc_add_modify (&block, case_num, tmp);
2450 gfc_add_block_to_block (&block, &expr1se.post);
2452 tmp = gfc_finish_block (&body);
2453 tmp = fold_build3_loc (input_location, SWITCH_EXPR, NULL_TREE,
2454 case_num, tmp, NULL_TREE);
2455 gfc_add_expr_to_block (&block, tmp);
2457 tmp = build1_v (LABEL_EXPR, end_label);
2458 gfc_add_expr_to_block (&block, tmp);
2460 return gfc_finish_block (&block);
2464 /* Translate the three variants of the SELECT CASE construct.
2466 SELECT CASEs with INTEGER case expressions can be translated to an
2467 equivalent GENERIC switch statement, and for LOGICAL case
2468 expressions we build one or two if-else compares.
2470 SELECT CASEs with CHARACTER case expressions are a whole different
2471 story, because they don't exist in GENERIC. So we sort them and
2472 do a binary search at runtime.
2474 Fortran has no BREAK statement, and it does not allow jumps from
2475 one case block to another. That makes things a lot easier for
2476 the optimizers. */
2478 tree
2479 gfc_trans_select (gfc_code * code)
2481 stmtblock_t block;
2482 tree body;
2483 tree exit_label;
2485 gcc_assert (code && code->expr1);
2486 gfc_init_block (&block);
2488 /* Build the exit label and hang it in. */
2489 exit_label = gfc_build_label_decl (NULL_TREE);
2490 code->exit_label = exit_label;
2492 /* Empty SELECT constructs are legal. */
2493 if (code->block == NULL)
2494 body = build_empty_stmt (input_location);
2496 /* Select the correct translation function. */
2497 else
2498 switch (code->expr1->ts.type)
2500 case BT_LOGICAL:
2501 body = gfc_trans_logical_select (code);
2502 break;
2504 case BT_INTEGER:
2505 body = gfc_trans_integer_select (code);
2506 break;
2508 case BT_CHARACTER:
2509 body = gfc_trans_character_select (code);
2510 break;
2512 default:
2513 gfc_internal_error ("gfc_trans_select(): Bad type for case expr.");
2514 /* Not reached */
2517 /* Build everything together. */
2518 gfc_add_expr_to_block (&block, body);
2519 gfc_add_expr_to_block (&block, build1_v (LABEL_EXPR, exit_label));
2521 return gfc_finish_block (&block);
2525 /* Traversal function to substitute a replacement symtree if the symbol
2526 in the expression is the same as that passed. f == 2 signals that
2527 that variable itself is not to be checked - only the references.
2528 This group of functions is used when the variable expression in a
2529 FORALL assignment has internal references. For example:
2530 FORALL (i = 1:4) p(p(i)) = i
2531 The only recourse here is to store a copy of 'p' for the index
2532 expression. */
2534 static gfc_symtree *new_symtree;
2535 static gfc_symtree *old_symtree;
2537 static bool
2538 forall_replace (gfc_expr *expr, gfc_symbol *sym, int *f)
2540 if (expr->expr_type != EXPR_VARIABLE)
2541 return false;
2543 if (*f == 2)
2544 *f = 1;
2545 else if (expr->symtree->n.sym == sym)
2546 expr->symtree = new_symtree;
2548 return false;
2551 static void
2552 forall_replace_symtree (gfc_expr *e, gfc_symbol *sym, int f)
2554 gfc_traverse_expr (e, sym, forall_replace, f);
2557 static bool
2558 forall_restore (gfc_expr *expr,
2559 gfc_symbol *sym ATTRIBUTE_UNUSED,
2560 int *f ATTRIBUTE_UNUSED)
2562 if (expr->expr_type != EXPR_VARIABLE)
2563 return false;
2565 if (expr->symtree == new_symtree)
2566 expr->symtree = old_symtree;
2568 return false;
2571 static void
2572 forall_restore_symtree (gfc_expr *e)
2574 gfc_traverse_expr (e, NULL, forall_restore, 0);
2577 static void
2578 forall_make_variable_temp (gfc_code *c, stmtblock_t *pre, stmtblock_t *post)
2580 gfc_se tse;
2581 gfc_se rse;
2582 gfc_expr *e;
2583 gfc_symbol *new_sym;
2584 gfc_symbol *old_sym;
2585 gfc_symtree *root;
2586 tree tmp;
2588 /* Build a copy of the lvalue. */
2589 old_symtree = c->expr1->symtree;
2590 old_sym = old_symtree->n.sym;
2591 e = gfc_lval_expr_from_sym (old_sym);
2592 if (old_sym->attr.dimension)
2594 gfc_init_se (&tse, NULL);
2595 gfc_conv_subref_array_arg (&tse, e, 0, INTENT_IN, false);
2596 gfc_add_block_to_block (pre, &tse.pre);
2597 gfc_add_block_to_block (post, &tse.post);
2598 tse.expr = build_fold_indirect_ref_loc (input_location, tse.expr);
2600 if (e->ts.type != BT_CHARACTER)
2602 /* Use the variable offset for the temporary. */
2603 tmp = gfc_conv_array_offset (old_sym->backend_decl);
2604 gfc_conv_descriptor_offset_set (pre, tse.expr, tmp);
2607 else
2609 gfc_init_se (&tse, NULL);
2610 gfc_init_se (&rse, NULL);
2611 gfc_conv_expr (&rse, e);
2612 if (e->ts.type == BT_CHARACTER)
2614 tse.string_length = rse.string_length;
2615 tmp = gfc_get_character_type_len (gfc_default_character_kind,
2616 tse.string_length);
2617 tse.expr = gfc_conv_string_tmp (&tse, build_pointer_type (tmp),
2618 rse.string_length);
2619 gfc_add_block_to_block (pre, &tse.pre);
2620 gfc_add_block_to_block (post, &tse.post);
2622 else
2624 tmp = gfc_typenode_for_spec (&e->ts);
2625 tse.expr = gfc_create_var (tmp, "temp");
2628 tmp = gfc_trans_scalar_assign (&tse, &rse, e->ts, true,
2629 e->expr_type == EXPR_VARIABLE, true);
2630 gfc_add_expr_to_block (pre, tmp);
2632 gfc_free_expr (e);
2634 /* Create a new symbol to represent the lvalue. */
2635 new_sym = gfc_new_symbol (old_sym->name, NULL);
2636 new_sym->ts = old_sym->ts;
2637 new_sym->attr.referenced = 1;
2638 new_sym->attr.temporary = 1;
2639 new_sym->attr.dimension = old_sym->attr.dimension;
2640 new_sym->attr.flavor = old_sym->attr.flavor;
2642 /* Use the temporary as the backend_decl. */
2643 new_sym->backend_decl = tse.expr;
2645 /* Create a fake symtree for it. */
2646 root = NULL;
2647 new_symtree = gfc_new_symtree (&root, old_sym->name);
2648 new_symtree->n.sym = new_sym;
2649 gcc_assert (new_symtree == root);
2651 /* Go through the expression reference replacing the old_symtree
2652 with the new. */
2653 forall_replace_symtree (c->expr1, old_sym, 2);
2655 /* Now we have made this temporary, we might as well use it for
2656 the right hand side. */
2657 forall_replace_symtree (c->expr2, old_sym, 1);
2661 /* Handles dependencies in forall assignments. */
2662 static int
2663 check_forall_dependencies (gfc_code *c, stmtblock_t *pre, stmtblock_t *post)
2665 gfc_ref *lref;
2666 gfc_ref *rref;
2667 int need_temp;
2668 gfc_symbol *lsym;
2670 lsym = c->expr1->symtree->n.sym;
2671 need_temp = gfc_check_dependency (c->expr1, c->expr2, 0);
2673 /* Now check for dependencies within the 'variable'
2674 expression itself. These are treated by making a complete
2675 copy of variable and changing all the references to it
2676 point to the copy instead. Note that the shallow copy of
2677 the variable will not suffice for derived types with
2678 pointer components. We therefore leave these to their
2679 own devices. */
2680 if (lsym->ts.type == BT_DERIVED
2681 && lsym->ts.u.derived->attr.pointer_comp)
2682 return need_temp;
2684 new_symtree = NULL;
2685 if (find_forall_index (c->expr1, lsym, 2))
2687 forall_make_variable_temp (c, pre, post);
2688 need_temp = 0;
2691 /* Substrings with dependencies are treated in the same
2692 way. */
2693 if (c->expr1->ts.type == BT_CHARACTER
2694 && c->expr1->ref
2695 && c->expr2->expr_type == EXPR_VARIABLE
2696 && lsym == c->expr2->symtree->n.sym)
2698 for (lref = c->expr1->ref; lref; lref = lref->next)
2699 if (lref->type == REF_SUBSTRING)
2700 break;
2701 for (rref = c->expr2->ref; rref; rref = rref->next)
2702 if (rref->type == REF_SUBSTRING)
2703 break;
2705 if (rref && lref
2706 && gfc_dep_compare_expr (rref->u.ss.start, lref->u.ss.start) < 0)
2708 forall_make_variable_temp (c, pre, post);
2709 need_temp = 0;
2712 return need_temp;
2716 static void
2717 cleanup_forall_symtrees (gfc_code *c)
2719 forall_restore_symtree (c->expr1);
2720 forall_restore_symtree (c->expr2);
2721 free (new_symtree->n.sym);
2722 free (new_symtree);
2726 /* Generate the loops for a FORALL block, specified by FORALL_TMP. BODY
2727 is the contents of the FORALL block/stmt to be iterated. MASK_FLAG
2728 indicates whether we should generate code to test the FORALLs mask
2729 array. OUTER is the loop header to be used for initializing mask
2730 indices.
2732 The generated loop format is:
2733 count = (end - start + step) / step
2734 loopvar = start
2735 while (1)
2737 if (count <=0 )
2738 goto end_of_loop
2739 <body>
2740 loopvar += step
2741 count --
2743 end_of_loop: */
2745 static tree
2746 gfc_trans_forall_loop (forall_info *forall_tmp, tree body,
2747 int mask_flag, stmtblock_t *outer)
2749 int n, nvar;
2750 tree tmp;
2751 tree cond;
2752 stmtblock_t block;
2753 tree exit_label;
2754 tree count;
2755 tree var, start, end, step;
2756 iter_info *iter;
2758 /* Initialize the mask index outside the FORALL nest. */
2759 if (mask_flag && forall_tmp->mask)
2760 gfc_add_modify (outer, forall_tmp->maskindex, gfc_index_zero_node);
2762 iter = forall_tmp->this_loop;
2763 nvar = forall_tmp->nvar;
2764 for (n = 0; n < nvar; n++)
2766 var = iter->var;
2767 start = iter->start;
2768 end = iter->end;
2769 step = iter->step;
2771 exit_label = gfc_build_label_decl (NULL_TREE);
2772 TREE_USED (exit_label) = 1;
2774 /* The loop counter. */
2775 count = gfc_create_var (TREE_TYPE (var), "count");
2777 /* The body of the loop. */
2778 gfc_init_block (&block);
2780 /* The exit condition. */
2781 cond = fold_build2_loc (input_location, LE_EXPR, boolean_type_node,
2782 count, build_int_cst (TREE_TYPE (count), 0));
2783 if (forall_tmp->do_concurrent)
2784 cond = build2 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
2785 build_int_cst (integer_type_node,
2786 annot_expr_ivdep_kind));
2788 tmp = build1_v (GOTO_EXPR, exit_label);
2789 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
2790 cond, tmp, build_empty_stmt (input_location));
2791 gfc_add_expr_to_block (&block, tmp);
2793 /* The main loop body. */
2794 gfc_add_expr_to_block (&block, body);
2796 /* Increment the loop variable. */
2797 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (var), var,
2798 step);
2799 gfc_add_modify (&block, var, tmp);
2801 /* Advance to the next mask element. Only do this for the
2802 innermost loop. */
2803 if (n == 0 && mask_flag && forall_tmp->mask)
2805 tree maskindex = forall_tmp->maskindex;
2806 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
2807 maskindex, gfc_index_one_node);
2808 gfc_add_modify (&block, maskindex, tmp);
2811 /* Decrement the loop counter. */
2812 tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (var), count,
2813 build_int_cst (TREE_TYPE (var), 1));
2814 gfc_add_modify (&block, count, tmp);
2816 body = gfc_finish_block (&block);
2818 /* Loop var initialization. */
2819 gfc_init_block (&block);
2820 gfc_add_modify (&block, var, start);
2823 /* Initialize the loop counter. */
2824 tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (var), step,
2825 start);
2826 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (var), end,
2827 tmp);
2828 tmp = fold_build2_loc (input_location, TRUNC_DIV_EXPR, TREE_TYPE (var),
2829 tmp, step);
2830 gfc_add_modify (&block, count, tmp);
2832 /* The loop expression. */
2833 tmp = build1_v (LOOP_EXPR, body);
2834 gfc_add_expr_to_block (&block, tmp);
2836 /* The exit label. */
2837 tmp = build1_v (LABEL_EXPR, exit_label);
2838 gfc_add_expr_to_block (&block, tmp);
2840 body = gfc_finish_block (&block);
2841 iter = iter->next;
2843 return body;
2847 /* Generate the body and loops according to MASK_FLAG. If MASK_FLAG
2848 is nonzero, the body is controlled by all masks in the forall nest.
2849 Otherwise, the innermost loop is not controlled by it's mask. This
2850 is used for initializing that mask. */
2852 static tree
2853 gfc_trans_nested_forall_loop (forall_info * nested_forall_info, tree body,
2854 int mask_flag)
2856 tree tmp;
2857 stmtblock_t header;
2858 forall_info *forall_tmp;
2859 tree mask, maskindex;
2861 gfc_start_block (&header);
2863 forall_tmp = nested_forall_info;
2864 while (forall_tmp != NULL)
2866 /* Generate body with masks' control. */
2867 if (mask_flag)
2869 mask = forall_tmp->mask;
2870 maskindex = forall_tmp->maskindex;
2872 /* If a mask was specified make the assignment conditional. */
2873 if (mask)
2875 tmp = gfc_build_array_ref (mask, maskindex, NULL);
2876 body = build3_v (COND_EXPR, tmp, body,
2877 build_empty_stmt (input_location));
2880 body = gfc_trans_forall_loop (forall_tmp, body, mask_flag, &header);
2881 forall_tmp = forall_tmp->prev_nest;
2882 mask_flag = 1;
2885 gfc_add_expr_to_block (&header, body);
2886 return gfc_finish_block (&header);
2890 /* Allocate data for holding a temporary array. Returns either a local
2891 temporary array or a pointer variable. */
2893 static tree
2894 gfc_do_allocate (tree bytesize, tree size, tree * pdata, stmtblock_t * pblock,
2895 tree elem_type)
2897 tree tmpvar;
2898 tree type;
2899 tree tmp;
2901 if (INTEGER_CST_P (size))
2902 tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
2903 size, gfc_index_one_node);
2904 else
2905 tmp = NULL_TREE;
2907 type = build_range_type (gfc_array_index_type, gfc_index_zero_node, tmp);
2908 type = build_array_type (elem_type, type);
2909 if (gfc_can_put_var_on_stack (bytesize))
2911 gcc_assert (INTEGER_CST_P (size));
2912 tmpvar = gfc_create_var (type, "temp");
2913 *pdata = NULL_TREE;
2915 else
2917 tmpvar = gfc_create_var (build_pointer_type (type), "temp");
2918 *pdata = convert (pvoid_type_node, tmpvar);
2920 tmp = gfc_call_malloc (pblock, TREE_TYPE (tmpvar), bytesize);
2921 gfc_add_modify (pblock, tmpvar, tmp);
2923 return tmpvar;
2927 /* Generate codes to copy the temporary to the actual lhs. */
2929 static tree
2930 generate_loop_for_temp_to_lhs (gfc_expr *expr, tree tmp1, tree count3,
2931 tree count1, tree wheremask, bool invert)
2933 gfc_ss *lss;
2934 gfc_se lse, rse;
2935 stmtblock_t block, body;
2936 gfc_loopinfo loop1;
2937 tree tmp;
2938 tree wheremaskexpr;
2940 /* Walk the lhs. */
2941 lss = gfc_walk_expr (expr);
2943 if (lss == gfc_ss_terminator)
2945 gfc_start_block (&block);
2947 gfc_init_se (&lse, NULL);
2949 /* Translate the expression. */
2950 gfc_conv_expr (&lse, expr);
2952 /* Form the expression for the temporary. */
2953 tmp = gfc_build_array_ref (tmp1, count1, NULL);
2955 /* Use the scalar assignment as is. */
2956 gfc_add_block_to_block (&block, &lse.pre);
2957 gfc_add_modify (&block, lse.expr, tmp);
2958 gfc_add_block_to_block (&block, &lse.post);
2960 /* Increment the count1. */
2961 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (count1),
2962 count1, gfc_index_one_node);
2963 gfc_add_modify (&block, count1, tmp);
2965 tmp = gfc_finish_block (&block);
2967 else
2969 gfc_start_block (&block);
2971 gfc_init_loopinfo (&loop1);
2972 gfc_init_se (&rse, NULL);
2973 gfc_init_se (&lse, NULL);
2975 /* Associate the lss with the loop. */
2976 gfc_add_ss_to_loop (&loop1, lss);
2978 /* Calculate the bounds of the scalarization. */
2979 gfc_conv_ss_startstride (&loop1);
2980 /* Setup the scalarizing loops. */
2981 gfc_conv_loop_setup (&loop1, &expr->where);
2983 gfc_mark_ss_chain_used (lss, 1);
2985 /* Start the scalarized loop body. */
2986 gfc_start_scalarized_body (&loop1, &body);
2988 /* Setup the gfc_se structures. */
2989 gfc_copy_loopinfo_to_se (&lse, &loop1);
2990 lse.ss = lss;
2992 /* Form the expression of the temporary. */
2993 if (lss != gfc_ss_terminator)
2994 rse.expr = gfc_build_array_ref (tmp1, count1, NULL);
2995 /* Translate expr. */
2996 gfc_conv_expr (&lse, expr);
2998 /* Use the scalar assignment. */
2999 rse.string_length = lse.string_length;
3000 tmp = gfc_trans_scalar_assign (&lse, &rse, expr->ts, false, true, true);
3002 /* Form the mask expression according to the mask tree list. */
3003 if (wheremask)
3005 wheremaskexpr = gfc_build_array_ref (wheremask, count3, NULL);
3006 if (invert)
3007 wheremaskexpr = fold_build1_loc (input_location, TRUTH_NOT_EXPR,
3008 TREE_TYPE (wheremaskexpr),
3009 wheremaskexpr);
3010 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
3011 wheremaskexpr, tmp,
3012 build_empty_stmt (input_location));
3015 gfc_add_expr_to_block (&body, tmp);
3017 /* Increment count1. */
3018 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
3019 count1, gfc_index_one_node);
3020 gfc_add_modify (&body, count1, tmp);
3022 /* Increment count3. */
3023 if (count3)
3025 tmp = fold_build2_loc (input_location, PLUS_EXPR,
3026 gfc_array_index_type, count3,
3027 gfc_index_one_node);
3028 gfc_add_modify (&body, count3, tmp);
3031 /* Generate the copying loops. */
3032 gfc_trans_scalarizing_loops (&loop1, &body);
3033 gfc_add_block_to_block (&block, &loop1.pre);
3034 gfc_add_block_to_block (&block, &loop1.post);
3035 gfc_cleanup_loop (&loop1);
3037 tmp = gfc_finish_block (&block);
3039 return tmp;
3043 /* Generate codes to copy rhs to the temporary. TMP1 is the address of
3044 temporary, LSS and RSS are formed in function compute_inner_temp_size(),
3045 and should not be freed. WHEREMASK is the conditional execution mask
3046 whose sense may be inverted by INVERT. */
3048 static tree
3049 generate_loop_for_rhs_to_temp (gfc_expr *expr2, tree tmp1, tree count3,
3050 tree count1, gfc_ss *lss, gfc_ss *rss,
3051 tree wheremask, bool invert)
3053 stmtblock_t block, body1;
3054 gfc_loopinfo loop;
3055 gfc_se lse;
3056 gfc_se rse;
3057 tree tmp;
3058 tree wheremaskexpr;
3060 gfc_start_block (&block);
3062 gfc_init_se (&rse, NULL);
3063 gfc_init_se (&lse, NULL);
3065 if (lss == gfc_ss_terminator)
3067 gfc_init_block (&body1);
3068 gfc_conv_expr (&rse, expr2);
3069 lse.expr = gfc_build_array_ref (tmp1, count1, NULL);
3071 else
3073 /* Initialize the loop. */
3074 gfc_init_loopinfo (&loop);
3076 /* We may need LSS to determine the shape of the expression. */
3077 gfc_add_ss_to_loop (&loop, lss);
3078 gfc_add_ss_to_loop (&loop, rss);
3080 gfc_conv_ss_startstride (&loop);
3081 gfc_conv_loop_setup (&loop, &expr2->where);
3083 gfc_mark_ss_chain_used (rss, 1);
3084 /* Start the loop body. */
3085 gfc_start_scalarized_body (&loop, &body1);
3087 /* Translate the expression. */
3088 gfc_copy_loopinfo_to_se (&rse, &loop);
3089 rse.ss = rss;
3090 gfc_conv_expr (&rse, expr2);
3092 /* Form the expression of the temporary. */
3093 lse.expr = gfc_build_array_ref (tmp1, count1, NULL);
3096 /* Use the scalar assignment. */
3097 lse.string_length = rse.string_length;
3098 tmp = gfc_trans_scalar_assign (&lse, &rse, expr2->ts, true,
3099 expr2->expr_type == EXPR_VARIABLE, true);
3101 /* Form the mask expression according to the mask tree list. */
3102 if (wheremask)
3104 wheremaskexpr = gfc_build_array_ref (wheremask, count3, NULL);
3105 if (invert)
3106 wheremaskexpr = fold_build1_loc (input_location, TRUTH_NOT_EXPR,
3107 TREE_TYPE (wheremaskexpr),
3108 wheremaskexpr);
3109 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
3110 wheremaskexpr, tmp,
3111 build_empty_stmt (input_location));
3114 gfc_add_expr_to_block (&body1, tmp);
3116 if (lss == gfc_ss_terminator)
3118 gfc_add_block_to_block (&block, &body1);
3120 /* Increment count1. */
3121 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (count1),
3122 count1, gfc_index_one_node);
3123 gfc_add_modify (&block, count1, tmp);
3125 else
3127 /* Increment count1. */
3128 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
3129 count1, gfc_index_one_node);
3130 gfc_add_modify (&body1, count1, tmp);
3132 /* Increment count3. */
3133 if (count3)
3135 tmp = fold_build2_loc (input_location, PLUS_EXPR,
3136 gfc_array_index_type,
3137 count3, gfc_index_one_node);
3138 gfc_add_modify (&body1, count3, tmp);
3141 /* Generate the copying loops. */
3142 gfc_trans_scalarizing_loops (&loop, &body1);
3144 gfc_add_block_to_block (&block, &loop.pre);
3145 gfc_add_block_to_block (&block, &loop.post);
3147 gfc_cleanup_loop (&loop);
3148 /* TODO: Reuse lss and rss when copying temp->lhs. Need to be careful
3149 as tree nodes in SS may not be valid in different scope. */
3152 tmp = gfc_finish_block (&block);
3153 return tmp;
3157 /* Calculate the size of temporary needed in the assignment inside forall.
3158 LSS and RSS are filled in this function. */
3160 static tree
3161 compute_inner_temp_size (gfc_expr *expr1, gfc_expr *expr2,
3162 stmtblock_t * pblock,
3163 gfc_ss **lss, gfc_ss **rss)
3165 gfc_loopinfo loop;
3166 tree size;
3167 int i;
3168 int save_flag;
3169 tree tmp;
3171 *lss = gfc_walk_expr (expr1);
3172 *rss = NULL;
3174 size = gfc_index_one_node;
3175 if (*lss != gfc_ss_terminator)
3177 gfc_init_loopinfo (&loop);
3179 /* Walk the RHS of the expression. */
3180 *rss = gfc_walk_expr (expr2);
3181 if (*rss == gfc_ss_terminator)
3182 /* The rhs is scalar. Add a ss for the expression. */
3183 *rss = gfc_get_scalar_ss (gfc_ss_terminator, expr2);
3185 /* Associate the SS with the loop. */
3186 gfc_add_ss_to_loop (&loop, *lss);
3187 /* We don't actually need to add the rhs at this point, but it might
3188 make guessing the loop bounds a bit easier. */
3189 gfc_add_ss_to_loop (&loop, *rss);
3191 /* We only want the shape of the expression, not rest of the junk
3192 generated by the scalarizer. */
3193 loop.array_parameter = 1;
3195 /* Calculate the bounds of the scalarization. */
3196 save_flag = gfc_option.rtcheck;
3197 gfc_option.rtcheck &= ~GFC_RTCHECK_BOUNDS;
3198 gfc_conv_ss_startstride (&loop);
3199 gfc_option.rtcheck = save_flag;
3200 gfc_conv_loop_setup (&loop, &expr2->where);
3202 /* Figure out how many elements we need. */
3203 for (i = 0; i < loop.dimen; i++)
3205 tmp = fold_build2_loc (input_location, MINUS_EXPR,
3206 gfc_array_index_type,
3207 gfc_index_one_node, loop.from[i]);
3208 tmp = fold_build2_loc (input_location, PLUS_EXPR,
3209 gfc_array_index_type, tmp, loop.to[i]);
3210 size = fold_build2_loc (input_location, MULT_EXPR,
3211 gfc_array_index_type, size, tmp);
3213 gfc_add_block_to_block (pblock, &loop.pre);
3214 size = gfc_evaluate_now (size, pblock);
3215 gfc_add_block_to_block (pblock, &loop.post);
3217 /* TODO: write a function that cleans up a loopinfo without freeing
3218 the SS chains. Currently a NOP. */
3221 return size;
3225 /* Calculate the overall iterator number of the nested forall construct.
3226 This routine actually calculates the number of times the body of the
3227 nested forall specified by NESTED_FORALL_INFO is executed and multiplies
3228 that by the expression INNER_SIZE. The BLOCK argument specifies the
3229 block in which to calculate the result, and the optional INNER_SIZE_BODY
3230 argument contains any statements that need to executed (inside the loop)
3231 to initialize or calculate INNER_SIZE. */
3233 static tree
3234 compute_overall_iter_number (forall_info *nested_forall_info, tree inner_size,
3235 stmtblock_t *inner_size_body, stmtblock_t *block)
3237 forall_info *forall_tmp = nested_forall_info;
3238 tree tmp, number;
3239 stmtblock_t body;
3241 /* We can eliminate the innermost unconditional loops with constant
3242 array bounds. */
3243 if (INTEGER_CST_P (inner_size))
3245 while (forall_tmp
3246 && !forall_tmp->mask
3247 && INTEGER_CST_P (forall_tmp->size))
3249 inner_size = fold_build2_loc (input_location, MULT_EXPR,
3250 gfc_array_index_type,
3251 inner_size, forall_tmp->size);
3252 forall_tmp = forall_tmp->prev_nest;
3255 /* If there are no loops left, we have our constant result. */
3256 if (!forall_tmp)
3257 return inner_size;
3260 /* Otherwise, create a temporary variable to compute the result. */
3261 number = gfc_create_var (gfc_array_index_type, "num");
3262 gfc_add_modify (block, number, gfc_index_zero_node);
3264 gfc_start_block (&body);
3265 if (inner_size_body)
3266 gfc_add_block_to_block (&body, inner_size_body);
3267 if (forall_tmp)
3268 tmp = fold_build2_loc (input_location, PLUS_EXPR,
3269 gfc_array_index_type, number, inner_size);
3270 else
3271 tmp = inner_size;
3272 gfc_add_modify (&body, number, tmp);
3273 tmp = gfc_finish_block (&body);
3275 /* Generate loops. */
3276 if (forall_tmp != NULL)
3277 tmp = gfc_trans_nested_forall_loop (forall_tmp, tmp, 1);
3279 gfc_add_expr_to_block (block, tmp);
3281 return number;
3285 /* Allocate temporary for forall construct. SIZE is the size of temporary
3286 needed. PTEMP1 is returned for space free. */
3288 static tree
3289 allocate_temp_for_forall_nest_1 (tree type, tree size, stmtblock_t * block,
3290 tree * ptemp1)
3292 tree bytesize;
3293 tree unit;
3294 tree tmp;
3296 unit = fold_convert (gfc_array_index_type, TYPE_SIZE_UNIT (type));
3297 if (!integer_onep (unit))
3298 bytesize = fold_build2_loc (input_location, MULT_EXPR,
3299 gfc_array_index_type, size, unit);
3300 else
3301 bytesize = size;
3303 *ptemp1 = NULL;
3304 tmp = gfc_do_allocate (bytesize, size, ptemp1, block, type);
3306 if (*ptemp1)
3307 tmp = build_fold_indirect_ref_loc (input_location, tmp);
3308 return tmp;
3312 /* Allocate temporary for forall construct according to the information in
3313 nested_forall_info. INNER_SIZE is the size of temporary needed in the
3314 assignment inside forall. PTEMP1 is returned for space free. */
3316 static tree
3317 allocate_temp_for_forall_nest (forall_info * nested_forall_info, tree type,
3318 tree inner_size, stmtblock_t * inner_size_body,
3319 stmtblock_t * block, tree * ptemp1)
3321 tree size;
3323 /* Calculate the total size of temporary needed in forall construct. */
3324 size = compute_overall_iter_number (nested_forall_info, inner_size,
3325 inner_size_body, block);
3327 return allocate_temp_for_forall_nest_1 (type, size, block, ptemp1);
3331 /* Handle assignments inside forall which need temporary.
3333 forall (i=start:end:stride; maskexpr)
3334 e<i> = f<i>
3335 end forall
3336 (where e,f<i> are arbitrary expressions possibly involving i
3337 and there is a dependency between e<i> and f<i>)
3338 Translates to:
3339 masktmp(:) = maskexpr(:)
3341 maskindex = 0;
3342 count1 = 0;
3343 num = 0;
3344 for (i = start; i <= end; i += stride)
3345 num += SIZE (f<i>)
3346 count1 = 0;
3347 ALLOCATE (tmp(num))
3348 for (i = start; i <= end; i += stride)
3350 if (masktmp[maskindex++])
3351 tmp[count1++] = f<i>
3353 maskindex = 0;
3354 count1 = 0;
3355 for (i = start; i <= end; i += stride)
3357 if (masktmp[maskindex++])
3358 e<i> = tmp[count1++]
3360 DEALLOCATE (tmp)
3362 static void
3363 gfc_trans_assign_need_temp (gfc_expr * expr1, gfc_expr * expr2,
3364 tree wheremask, bool invert,
3365 forall_info * nested_forall_info,
3366 stmtblock_t * block)
3368 tree type;
3369 tree inner_size;
3370 gfc_ss *lss, *rss;
3371 tree count, count1;
3372 tree tmp, tmp1;
3373 tree ptemp1;
3374 stmtblock_t inner_size_body;
3376 /* Create vars. count1 is the current iterator number of the nested
3377 forall. */
3378 count1 = gfc_create_var (gfc_array_index_type, "count1");
3380 /* Count is the wheremask index. */
3381 if (wheremask)
3383 count = gfc_create_var (gfc_array_index_type, "count");
3384 gfc_add_modify (block, count, gfc_index_zero_node);
3386 else
3387 count = NULL;
3389 /* Initialize count1. */
3390 gfc_add_modify (block, count1, gfc_index_zero_node);
3392 /* Calculate the size of temporary needed in the assignment. Return loop, lss
3393 and rss which are used in function generate_loop_for_rhs_to_temp(). */
3394 gfc_init_block (&inner_size_body);
3395 inner_size = compute_inner_temp_size (expr1, expr2, &inner_size_body,
3396 &lss, &rss);
3398 /* The type of LHS. Used in function allocate_temp_for_forall_nest */
3399 if (expr1->ts.type == BT_CHARACTER && expr1->ts.u.cl->length)
3401 if (!expr1->ts.u.cl->backend_decl)
3403 gfc_se tse;
3404 gfc_init_se (&tse, NULL);
3405 gfc_conv_expr (&tse, expr1->ts.u.cl->length);
3406 expr1->ts.u.cl->backend_decl = tse.expr;
3408 type = gfc_get_character_type_len (gfc_default_character_kind,
3409 expr1->ts.u.cl->backend_decl);
3411 else
3412 type = gfc_typenode_for_spec (&expr1->ts);
3414 /* Allocate temporary for nested forall construct according to the
3415 information in nested_forall_info and inner_size. */
3416 tmp1 = allocate_temp_for_forall_nest (nested_forall_info, type, inner_size,
3417 &inner_size_body, block, &ptemp1);
3419 /* Generate codes to copy rhs to the temporary . */
3420 tmp = generate_loop_for_rhs_to_temp (expr2, tmp1, count, count1, lss, rss,
3421 wheremask, invert);
3423 /* Generate body and loops according to the information in
3424 nested_forall_info. */
3425 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
3426 gfc_add_expr_to_block (block, tmp);
3428 /* Reset count1. */
3429 gfc_add_modify (block, count1, gfc_index_zero_node);
3431 /* Reset count. */
3432 if (wheremask)
3433 gfc_add_modify (block, count, gfc_index_zero_node);
3435 /* Generate codes to copy the temporary to lhs. */
3436 tmp = generate_loop_for_temp_to_lhs (expr1, tmp1, count, count1,
3437 wheremask, invert);
3439 /* Generate body and loops according to the information in
3440 nested_forall_info. */
3441 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
3442 gfc_add_expr_to_block (block, tmp);
3444 if (ptemp1)
3446 /* Free the temporary. */
3447 tmp = gfc_call_free (ptemp1);
3448 gfc_add_expr_to_block (block, tmp);
3453 /* Translate pointer assignment inside FORALL which need temporary. */
3455 static void
3456 gfc_trans_pointer_assign_need_temp (gfc_expr * expr1, gfc_expr * expr2,
3457 forall_info * nested_forall_info,
3458 stmtblock_t * block)
3460 tree type;
3461 tree inner_size;
3462 gfc_ss *lss, *rss;
3463 gfc_se lse;
3464 gfc_se rse;
3465 gfc_array_info *info;
3466 gfc_loopinfo loop;
3467 tree desc;
3468 tree parm;
3469 tree parmtype;
3470 stmtblock_t body;
3471 tree count;
3472 tree tmp, tmp1, ptemp1;
3474 count = gfc_create_var (gfc_array_index_type, "count");
3475 gfc_add_modify (block, count, gfc_index_zero_node);
3477 inner_size = gfc_index_one_node;
3478 lss = gfc_walk_expr (expr1);
3479 rss = gfc_walk_expr (expr2);
3480 if (lss == gfc_ss_terminator)
3482 type = gfc_typenode_for_spec (&expr1->ts);
3483 type = build_pointer_type (type);
3485 /* Allocate temporary for nested forall construct according to the
3486 information in nested_forall_info and inner_size. */
3487 tmp1 = allocate_temp_for_forall_nest (nested_forall_info, type,
3488 inner_size, NULL, block, &ptemp1);
3489 gfc_start_block (&body);
3490 gfc_init_se (&lse, NULL);
3491 lse.expr = gfc_build_array_ref (tmp1, count, NULL);
3492 gfc_init_se (&rse, NULL);
3493 rse.want_pointer = 1;
3494 gfc_conv_expr (&rse, expr2);
3495 gfc_add_block_to_block (&body, &rse.pre);
3496 gfc_add_modify (&body, lse.expr,
3497 fold_convert (TREE_TYPE (lse.expr), rse.expr));
3498 gfc_add_block_to_block (&body, &rse.post);
3500 /* Increment count. */
3501 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
3502 count, gfc_index_one_node);
3503 gfc_add_modify (&body, count, tmp);
3505 tmp = gfc_finish_block (&body);
3507 /* Generate body and loops according to the information in
3508 nested_forall_info. */
3509 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
3510 gfc_add_expr_to_block (block, tmp);
3512 /* Reset count. */
3513 gfc_add_modify (block, count, gfc_index_zero_node);
3515 gfc_start_block (&body);
3516 gfc_init_se (&lse, NULL);
3517 gfc_init_se (&rse, NULL);
3518 rse.expr = gfc_build_array_ref (tmp1, count, NULL);
3519 lse.want_pointer = 1;
3520 gfc_conv_expr (&lse, expr1);
3521 gfc_add_block_to_block (&body, &lse.pre);
3522 gfc_add_modify (&body, lse.expr, rse.expr);
3523 gfc_add_block_to_block (&body, &lse.post);
3524 /* Increment count. */
3525 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
3526 count, gfc_index_one_node);
3527 gfc_add_modify (&body, count, tmp);
3528 tmp = gfc_finish_block (&body);
3530 /* Generate body and loops according to the information in
3531 nested_forall_info. */
3532 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
3533 gfc_add_expr_to_block (block, tmp);
3535 else
3537 gfc_init_loopinfo (&loop);
3539 /* Associate the SS with the loop. */
3540 gfc_add_ss_to_loop (&loop, rss);
3542 /* Setup the scalarizing loops and bounds. */
3543 gfc_conv_ss_startstride (&loop);
3545 gfc_conv_loop_setup (&loop, &expr2->where);
3547 info = &rss->info->data.array;
3548 desc = info->descriptor;
3550 /* Make a new descriptor. */
3551 parmtype = gfc_get_element_type (TREE_TYPE (desc));
3552 parmtype = gfc_get_array_type_bounds (parmtype, loop.dimen, 0,
3553 loop.from, loop.to, 1,
3554 GFC_ARRAY_UNKNOWN, true);
3556 /* Allocate temporary for nested forall construct. */
3557 tmp1 = allocate_temp_for_forall_nest (nested_forall_info, parmtype,
3558 inner_size, NULL, block, &ptemp1);
3559 gfc_start_block (&body);
3560 gfc_init_se (&lse, NULL);
3561 lse.expr = gfc_build_array_ref (tmp1, count, NULL);
3562 lse.direct_byref = 1;
3563 gfc_conv_expr_descriptor (&lse, expr2);
3565 gfc_add_block_to_block (&body, &lse.pre);
3566 gfc_add_block_to_block (&body, &lse.post);
3568 /* Increment count. */
3569 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
3570 count, gfc_index_one_node);
3571 gfc_add_modify (&body, count, tmp);
3573 tmp = gfc_finish_block (&body);
3575 /* Generate body and loops according to the information in
3576 nested_forall_info. */
3577 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
3578 gfc_add_expr_to_block (block, tmp);
3580 /* Reset count. */
3581 gfc_add_modify (block, count, gfc_index_zero_node);
3583 parm = gfc_build_array_ref (tmp1, count, NULL);
3584 gfc_init_se (&lse, NULL);
3585 gfc_conv_expr_descriptor (&lse, expr1);
3586 gfc_add_modify (&lse.pre, lse.expr, parm);
3587 gfc_start_block (&body);
3588 gfc_add_block_to_block (&body, &lse.pre);
3589 gfc_add_block_to_block (&body, &lse.post);
3591 /* Increment count. */
3592 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
3593 count, gfc_index_one_node);
3594 gfc_add_modify (&body, count, tmp);
3596 tmp = gfc_finish_block (&body);
3598 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
3599 gfc_add_expr_to_block (block, tmp);
3601 /* Free the temporary. */
3602 if (ptemp1)
3604 tmp = gfc_call_free (ptemp1);
3605 gfc_add_expr_to_block (block, tmp);
3610 /* FORALL and WHERE statements are really nasty, especially when you nest
3611 them. All the rhs of a forall assignment must be evaluated before the
3612 actual assignments are performed. Presumably this also applies to all the
3613 assignments in an inner where statement. */
3615 /* Generate code for a FORALL statement. Any temporaries are allocated as a
3616 linear array, relying on the fact that we process in the same order in all
3617 loops.
3619 forall (i=start:end:stride; maskexpr)
3620 e<i> = f<i>
3621 g<i> = h<i>
3622 end forall
3623 (where e,f,g,h<i> are arbitrary expressions possibly involving i)
3624 Translates to:
3625 count = ((end + 1 - start) / stride)
3626 masktmp(:) = maskexpr(:)
3628 maskindex = 0;
3629 for (i = start; i <= end; i += stride)
3631 if (masktmp[maskindex++])
3632 e<i> = f<i>
3634 maskindex = 0;
3635 for (i = start; i <= end; i += stride)
3637 if (masktmp[maskindex++])
3638 g<i> = h<i>
3641 Note that this code only works when there are no dependencies.
3642 Forall loop with array assignments and data dependencies are a real pain,
3643 because the size of the temporary cannot always be determined before the
3644 loop is executed. This problem is compounded by the presence of nested
3645 FORALL constructs.
3648 static tree
3649 gfc_trans_forall_1 (gfc_code * code, forall_info * nested_forall_info)
3651 stmtblock_t pre;
3652 stmtblock_t post;
3653 stmtblock_t block;
3654 stmtblock_t body;
3655 tree *var;
3656 tree *start;
3657 tree *end;
3658 tree *step;
3659 gfc_expr **varexpr;
3660 tree tmp;
3661 tree assign;
3662 tree size;
3663 tree maskindex;
3664 tree mask;
3665 tree pmask;
3666 tree cycle_label = NULL_TREE;
3667 int n;
3668 int nvar;
3669 int need_temp;
3670 gfc_forall_iterator *fa;
3671 gfc_se se;
3672 gfc_code *c;
3673 gfc_saved_var *saved_vars;
3674 iter_info *this_forall;
3675 forall_info *info;
3676 bool need_mask;
3678 /* Do nothing if the mask is false. */
3679 if (code->expr1
3680 && code->expr1->expr_type == EXPR_CONSTANT
3681 && !code->expr1->value.logical)
3682 return build_empty_stmt (input_location);
3684 n = 0;
3685 /* Count the FORALL index number. */
3686 for (fa = code->ext.forall_iterator; fa; fa = fa->next)
3687 n++;
3688 nvar = n;
3690 /* Allocate the space for var, start, end, step, varexpr. */
3691 var = XCNEWVEC (tree, nvar);
3692 start = XCNEWVEC (tree, nvar);
3693 end = XCNEWVEC (tree, nvar);
3694 step = XCNEWVEC (tree, nvar);
3695 varexpr = XCNEWVEC (gfc_expr *, nvar);
3696 saved_vars = XCNEWVEC (gfc_saved_var, nvar);
3698 /* Allocate the space for info. */
3699 info = XCNEW (forall_info);
3701 gfc_start_block (&pre);
3702 gfc_init_block (&post);
3703 gfc_init_block (&block);
3705 n = 0;
3706 for (fa = code->ext.forall_iterator; fa; fa = fa->next)
3708 gfc_symbol *sym = fa->var->symtree->n.sym;
3710 /* Allocate space for this_forall. */
3711 this_forall = XCNEW (iter_info);
3713 /* Create a temporary variable for the FORALL index. */
3714 tmp = gfc_typenode_for_spec (&sym->ts);
3715 var[n] = gfc_create_var (tmp, sym->name);
3716 gfc_shadow_sym (sym, var[n], &saved_vars[n]);
3718 /* Record it in this_forall. */
3719 this_forall->var = var[n];
3721 /* Replace the index symbol's backend_decl with the temporary decl. */
3722 sym->backend_decl = var[n];
3724 /* Work out the start, end and stride for the loop. */
3725 gfc_init_se (&se, NULL);
3726 gfc_conv_expr_val (&se, fa->start);
3727 /* Record it in this_forall. */
3728 this_forall->start = se.expr;
3729 gfc_add_block_to_block (&block, &se.pre);
3730 start[n] = se.expr;
3732 gfc_init_se (&se, NULL);
3733 gfc_conv_expr_val (&se, fa->end);
3734 /* Record it in this_forall. */
3735 this_forall->end = se.expr;
3736 gfc_make_safe_expr (&se);
3737 gfc_add_block_to_block (&block, &se.pre);
3738 end[n] = se.expr;
3740 gfc_init_se (&se, NULL);
3741 gfc_conv_expr_val (&se, fa->stride);
3742 /* Record it in this_forall. */
3743 this_forall->step = se.expr;
3744 gfc_make_safe_expr (&se);
3745 gfc_add_block_to_block (&block, &se.pre);
3746 step[n] = se.expr;
3748 /* Set the NEXT field of this_forall to NULL. */
3749 this_forall->next = NULL;
3750 /* Link this_forall to the info construct. */
3751 if (info->this_loop)
3753 iter_info *iter_tmp = info->this_loop;
3754 while (iter_tmp->next != NULL)
3755 iter_tmp = iter_tmp->next;
3756 iter_tmp->next = this_forall;
3758 else
3759 info->this_loop = this_forall;
3761 n++;
3763 nvar = n;
3765 /* Calculate the size needed for the current forall level. */
3766 size = gfc_index_one_node;
3767 for (n = 0; n < nvar; n++)
3769 /* size = (end + step - start) / step. */
3770 tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (start[n]),
3771 step[n], start[n]);
3772 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (end[n]),
3773 end[n], tmp);
3774 tmp = fold_build2_loc (input_location, FLOOR_DIV_EXPR, TREE_TYPE (tmp),
3775 tmp, step[n]);
3776 tmp = convert (gfc_array_index_type, tmp);
3778 size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
3779 size, tmp);
3782 /* Record the nvar and size of current forall level. */
3783 info->nvar = nvar;
3784 info->size = size;
3786 if (code->expr1)
3788 /* If the mask is .true., consider the FORALL unconditional. */
3789 if (code->expr1->expr_type == EXPR_CONSTANT
3790 && code->expr1->value.logical)
3791 need_mask = false;
3792 else
3793 need_mask = true;
3795 else
3796 need_mask = false;
3798 /* First we need to allocate the mask. */
3799 if (need_mask)
3801 /* As the mask array can be very big, prefer compact boolean types. */
3802 tree mask_type = gfc_get_logical_type (gfc_logical_kinds[0].kind);
3803 mask = allocate_temp_for_forall_nest (nested_forall_info, mask_type,
3804 size, NULL, &block, &pmask);
3805 maskindex = gfc_create_var_np (gfc_array_index_type, "mi");
3807 /* Record them in the info structure. */
3808 info->maskindex = maskindex;
3809 info->mask = mask;
3811 else
3813 /* No mask was specified. */
3814 maskindex = NULL_TREE;
3815 mask = pmask = NULL_TREE;
3818 /* Link the current forall level to nested_forall_info. */
3819 info->prev_nest = nested_forall_info;
3820 nested_forall_info = info;
3822 /* Copy the mask into a temporary variable if required.
3823 For now we assume a mask temporary is needed. */
3824 if (need_mask)
3826 /* As the mask array can be very big, prefer compact boolean types. */
3827 tree mask_type = gfc_get_logical_type (gfc_logical_kinds[0].kind);
3829 gfc_add_modify (&block, maskindex, gfc_index_zero_node);
3831 /* Start of mask assignment loop body. */
3832 gfc_start_block (&body);
3834 /* Evaluate the mask expression. */
3835 gfc_init_se (&se, NULL);
3836 gfc_conv_expr_val (&se, code->expr1);
3837 gfc_add_block_to_block (&body, &se.pre);
3839 /* Store the mask. */
3840 se.expr = convert (mask_type, se.expr);
3842 tmp = gfc_build_array_ref (mask, maskindex, NULL);
3843 gfc_add_modify (&body, tmp, se.expr);
3845 /* Advance to the next mask element. */
3846 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
3847 maskindex, gfc_index_one_node);
3848 gfc_add_modify (&body, maskindex, tmp);
3850 /* Generate the loops. */
3851 tmp = gfc_finish_block (&body);
3852 tmp = gfc_trans_nested_forall_loop (info, tmp, 0);
3853 gfc_add_expr_to_block (&block, tmp);
3856 if (code->op == EXEC_DO_CONCURRENT)
3858 gfc_init_block (&body);
3859 cycle_label = gfc_build_label_decl (NULL_TREE);
3860 code->cycle_label = cycle_label;
3861 tmp = gfc_trans_code (code->block->next);
3862 gfc_add_expr_to_block (&body, tmp);
3864 if (TREE_USED (cycle_label))
3866 tmp = build1_v (LABEL_EXPR, cycle_label);
3867 gfc_add_expr_to_block (&body, tmp);
3870 tmp = gfc_finish_block (&body);
3871 nested_forall_info->do_concurrent = true;
3872 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
3873 gfc_add_expr_to_block (&block, tmp);
3874 goto done;
3877 c = code->block->next;
3879 /* TODO: loop merging in FORALL statements. */
3880 /* Now that we've got a copy of the mask, generate the assignment loops. */
3881 while (c)
3883 switch (c->op)
3885 case EXEC_ASSIGN:
3886 /* A scalar or array assignment. DO the simple check for
3887 lhs to rhs dependencies. These make a temporary for the
3888 rhs and form a second forall block to copy to variable. */
3889 need_temp = check_forall_dependencies(c, &pre, &post);
3891 /* Temporaries due to array assignment data dependencies introduce
3892 no end of problems. */
3893 if (need_temp)
3894 gfc_trans_assign_need_temp (c->expr1, c->expr2, NULL, false,
3895 nested_forall_info, &block);
3896 else
3898 /* Use the normal assignment copying routines. */
3899 assign = gfc_trans_assignment (c->expr1, c->expr2, false, true);
3901 /* Generate body and loops. */
3902 tmp = gfc_trans_nested_forall_loop (nested_forall_info,
3903 assign, 1);
3904 gfc_add_expr_to_block (&block, tmp);
3907 /* Cleanup any temporary symtrees that have been made to deal
3908 with dependencies. */
3909 if (new_symtree)
3910 cleanup_forall_symtrees (c);
3912 break;
3914 case EXEC_WHERE:
3915 /* Translate WHERE or WHERE construct nested in FORALL. */
3916 gfc_trans_where_2 (c, NULL, false, nested_forall_info, &block);
3917 break;
3919 /* Pointer assignment inside FORALL. */
3920 case EXEC_POINTER_ASSIGN:
3921 need_temp = gfc_check_dependency (c->expr1, c->expr2, 0);
3922 if (need_temp)
3923 gfc_trans_pointer_assign_need_temp (c->expr1, c->expr2,
3924 nested_forall_info, &block);
3925 else
3927 /* Use the normal assignment copying routines. */
3928 assign = gfc_trans_pointer_assignment (c->expr1, c->expr2);
3930 /* Generate body and loops. */
3931 tmp = gfc_trans_nested_forall_loop (nested_forall_info,
3932 assign, 1);
3933 gfc_add_expr_to_block (&block, tmp);
3935 break;
3937 case EXEC_FORALL:
3938 tmp = gfc_trans_forall_1 (c, nested_forall_info);
3939 gfc_add_expr_to_block (&block, tmp);
3940 break;
3942 /* Explicit subroutine calls are prevented by the frontend but interface
3943 assignments can legitimately produce them. */
3944 case EXEC_ASSIGN_CALL:
3945 assign = gfc_trans_call (c, true, NULL_TREE, NULL_TREE, false);
3946 tmp = gfc_trans_nested_forall_loop (nested_forall_info, assign, 1);
3947 gfc_add_expr_to_block (&block, tmp);
3948 break;
3950 default:
3951 gcc_unreachable ();
3954 c = c->next;
3957 done:
3958 /* Restore the original index variables. */
3959 for (fa = code->ext.forall_iterator, n = 0; fa; fa = fa->next, n++)
3960 gfc_restore_sym (fa->var->symtree->n.sym, &saved_vars[n]);
3962 /* Free the space for var, start, end, step, varexpr. */
3963 free (var);
3964 free (start);
3965 free (end);
3966 free (step);
3967 free (varexpr);
3968 free (saved_vars);
3970 for (this_forall = info->this_loop; this_forall;)
3972 iter_info *next = this_forall->next;
3973 free (this_forall);
3974 this_forall = next;
3977 /* Free the space for this forall_info. */
3978 free (info);
3980 if (pmask)
3982 /* Free the temporary for the mask. */
3983 tmp = gfc_call_free (pmask);
3984 gfc_add_expr_to_block (&block, tmp);
3986 if (maskindex)
3987 pushdecl (maskindex);
3989 gfc_add_block_to_block (&pre, &block);
3990 gfc_add_block_to_block (&pre, &post);
3992 return gfc_finish_block (&pre);
3996 /* Translate the FORALL statement or construct. */
3998 tree gfc_trans_forall (gfc_code * code)
4000 return gfc_trans_forall_1 (code, NULL);
4004 /* Translate the DO CONCURRENT construct. */
4006 tree gfc_trans_do_concurrent (gfc_code * code)
4008 return gfc_trans_forall_1 (code, NULL);
4012 /* Evaluate the WHERE mask expression, copy its value to a temporary.
4013 If the WHERE construct is nested in FORALL, compute the overall temporary
4014 needed by the WHERE mask expression multiplied by the iterator number of
4015 the nested forall.
4016 ME is the WHERE mask expression.
4017 MASK is the current execution mask upon input, whose sense may or may
4018 not be inverted as specified by the INVERT argument.
4019 CMASK is the updated execution mask on output, or NULL if not required.
4020 PMASK is the pending execution mask on output, or NULL if not required.
4021 BLOCK is the block in which to place the condition evaluation loops. */
4023 static void
4024 gfc_evaluate_where_mask (gfc_expr * me, forall_info * nested_forall_info,
4025 tree mask, bool invert, tree cmask, tree pmask,
4026 tree mask_type, stmtblock_t * block)
4028 tree tmp, tmp1;
4029 gfc_ss *lss, *rss;
4030 gfc_loopinfo loop;
4031 stmtblock_t body, body1;
4032 tree count, cond, mtmp;
4033 gfc_se lse, rse;
4035 gfc_init_loopinfo (&loop);
4037 lss = gfc_walk_expr (me);
4038 rss = gfc_walk_expr (me);
4040 /* Variable to index the temporary. */
4041 count = gfc_create_var (gfc_array_index_type, "count");
4042 /* Initialize count. */
4043 gfc_add_modify (block, count, gfc_index_zero_node);
4045 gfc_start_block (&body);
4047 gfc_init_se (&rse, NULL);
4048 gfc_init_se (&lse, NULL);
4050 if (lss == gfc_ss_terminator)
4052 gfc_init_block (&body1);
4054 else
4056 /* Initialize the loop. */
4057 gfc_init_loopinfo (&loop);
4059 /* We may need LSS to determine the shape of the expression. */
4060 gfc_add_ss_to_loop (&loop, lss);
4061 gfc_add_ss_to_loop (&loop, rss);
4063 gfc_conv_ss_startstride (&loop);
4064 gfc_conv_loop_setup (&loop, &me->where);
4066 gfc_mark_ss_chain_used (rss, 1);
4067 /* Start the loop body. */
4068 gfc_start_scalarized_body (&loop, &body1);
4070 /* Translate the expression. */
4071 gfc_copy_loopinfo_to_se (&rse, &loop);
4072 rse.ss = rss;
4073 gfc_conv_expr (&rse, me);
4076 /* Variable to evaluate mask condition. */
4077 cond = gfc_create_var (mask_type, "cond");
4078 if (mask && (cmask || pmask))
4079 mtmp = gfc_create_var (mask_type, "mask");
4080 else mtmp = NULL_TREE;
4082 gfc_add_block_to_block (&body1, &lse.pre);
4083 gfc_add_block_to_block (&body1, &rse.pre);
4085 gfc_add_modify (&body1, cond, fold_convert (mask_type, rse.expr));
4087 if (mask && (cmask || pmask))
4089 tmp = gfc_build_array_ref (mask, count, NULL);
4090 if (invert)
4091 tmp = fold_build1_loc (input_location, TRUTH_NOT_EXPR, mask_type, tmp);
4092 gfc_add_modify (&body1, mtmp, tmp);
4095 if (cmask)
4097 tmp1 = gfc_build_array_ref (cmask, count, NULL);
4098 tmp = cond;
4099 if (mask)
4100 tmp = fold_build2_loc (input_location, TRUTH_AND_EXPR, mask_type,
4101 mtmp, tmp);
4102 gfc_add_modify (&body1, tmp1, tmp);
4105 if (pmask)
4107 tmp1 = gfc_build_array_ref (pmask, count, NULL);
4108 tmp = fold_build1_loc (input_location, TRUTH_NOT_EXPR, mask_type, cond);
4109 if (mask)
4110 tmp = fold_build2_loc (input_location, TRUTH_AND_EXPR, mask_type, mtmp,
4111 tmp);
4112 gfc_add_modify (&body1, tmp1, tmp);
4115 gfc_add_block_to_block (&body1, &lse.post);
4116 gfc_add_block_to_block (&body1, &rse.post);
4118 if (lss == gfc_ss_terminator)
4120 gfc_add_block_to_block (&body, &body1);
4122 else
4124 /* Increment count. */
4125 tmp1 = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
4126 count, gfc_index_one_node);
4127 gfc_add_modify (&body1, count, tmp1);
4129 /* Generate the copying loops. */
4130 gfc_trans_scalarizing_loops (&loop, &body1);
4132 gfc_add_block_to_block (&body, &loop.pre);
4133 gfc_add_block_to_block (&body, &loop.post);
4135 gfc_cleanup_loop (&loop);
4136 /* TODO: Reuse lss and rss when copying temp->lhs. Need to be careful
4137 as tree nodes in SS may not be valid in different scope. */
4140 tmp1 = gfc_finish_block (&body);
4141 /* If the WHERE construct is inside FORALL, fill the full temporary. */
4142 if (nested_forall_info != NULL)
4143 tmp1 = gfc_trans_nested_forall_loop (nested_forall_info, tmp1, 1);
4145 gfc_add_expr_to_block (block, tmp1);
4149 /* Translate an assignment statement in a WHERE statement or construct
4150 statement. The MASK expression is used to control which elements
4151 of EXPR1 shall be assigned. The sense of MASK is specified by
4152 INVERT. */
4154 static tree
4155 gfc_trans_where_assign (gfc_expr *expr1, gfc_expr *expr2,
4156 tree mask, bool invert,
4157 tree count1, tree count2,
4158 gfc_code *cnext)
4160 gfc_se lse;
4161 gfc_se rse;
4162 gfc_ss *lss;
4163 gfc_ss *lss_section;
4164 gfc_ss *rss;
4166 gfc_loopinfo loop;
4167 tree tmp;
4168 stmtblock_t block;
4169 stmtblock_t body;
4170 tree index, maskexpr;
4172 /* A defined assignment. */
4173 if (cnext && cnext->resolved_sym)
4174 return gfc_trans_call (cnext, true, mask, count1, invert);
4176 #if 0
4177 /* TODO: handle this special case.
4178 Special case a single function returning an array. */
4179 if (expr2->expr_type == EXPR_FUNCTION && expr2->rank > 0)
4181 tmp = gfc_trans_arrayfunc_assign (expr1, expr2);
4182 if (tmp)
4183 return tmp;
4185 #endif
4187 /* Assignment of the form lhs = rhs. */
4188 gfc_start_block (&block);
4190 gfc_init_se (&lse, NULL);
4191 gfc_init_se (&rse, NULL);
4193 /* Walk the lhs. */
4194 lss = gfc_walk_expr (expr1);
4195 rss = NULL;
4197 /* In each where-assign-stmt, the mask-expr and the variable being
4198 defined shall be arrays of the same shape. */
4199 gcc_assert (lss != gfc_ss_terminator);
4201 /* The assignment needs scalarization. */
4202 lss_section = lss;
4204 /* Find a non-scalar SS from the lhs. */
4205 while (lss_section != gfc_ss_terminator
4206 && lss_section->info->type != GFC_SS_SECTION)
4207 lss_section = lss_section->next;
4209 gcc_assert (lss_section != gfc_ss_terminator);
4211 /* Initialize the scalarizer. */
4212 gfc_init_loopinfo (&loop);
4214 /* Walk the rhs. */
4215 rss = gfc_walk_expr (expr2);
4216 if (rss == gfc_ss_terminator)
4218 /* The rhs is scalar. Add a ss for the expression. */
4219 rss = gfc_get_scalar_ss (gfc_ss_terminator, expr2);
4220 rss->info->where = 1;
4223 /* Associate the SS with the loop. */
4224 gfc_add_ss_to_loop (&loop, lss);
4225 gfc_add_ss_to_loop (&loop, rss);
4227 /* Calculate the bounds of the scalarization. */
4228 gfc_conv_ss_startstride (&loop);
4230 /* Resolve any data dependencies in the statement. */
4231 gfc_conv_resolve_dependencies (&loop, lss_section, rss);
4233 /* Setup the scalarizing loops. */
4234 gfc_conv_loop_setup (&loop, &expr2->where);
4236 /* Setup the gfc_se structures. */
4237 gfc_copy_loopinfo_to_se (&lse, &loop);
4238 gfc_copy_loopinfo_to_se (&rse, &loop);
4240 rse.ss = rss;
4241 gfc_mark_ss_chain_used (rss, 1);
4242 if (loop.temp_ss == NULL)
4244 lse.ss = lss;
4245 gfc_mark_ss_chain_used (lss, 1);
4247 else
4249 lse.ss = loop.temp_ss;
4250 gfc_mark_ss_chain_used (lss, 3);
4251 gfc_mark_ss_chain_used (loop.temp_ss, 3);
4254 /* Start the scalarized loop body. */
4255 gfc_start_scalarized_body (&loop, &body);
4257 /* Translate the expression. */
4258 gfc_conv_expr (&rse, expr2);
4259 if (lss != gfc_ss_terminator && loop.temp_ss != NULL)
4260 gfc_conv_tmp_array_ref (&lse);
4261 else
4262 gfc_conv_expr (&lse, expr1);
4264 /* Form the mask expression according to the mask. */
4265 index = count1;
4266 maskexpr = gfc_build_array_ref (mask, index, NULL);
4267 if (invert)
4268 maskexpr = fold_build1_loc (input_location, TRUTH_NOT_EXPR,
4269 TREE_TYPE (maskexpr), maskexpr);
4271 /* Use the scalar assignment as is. */
4272 tmp = gfc_trans_scalar_assign (&lse, &rse, expr1->ts,
4273 loop.temp_ss != NULL, false, true);
4275 tmp = build3_v (COND_EXPR, maskexpr, tmp, build_empty_stmt (input_location));
4277 gfc_add_expr_to_block (&body, tmp);
4279 if (lss == gfc_ss_terminator)
4281 /* Increment count1. */
4282 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
4283 count1, gfc_index_one_node);
4284 gfc_add_modify (&body, count1, tmp);
4286 /* Use the scalar assignment as is. */
4287 gfc_add_block_to_block (&block, &body);
4289 else
4291 gcc_assert (lse.ss == gfc_ss_terminator
4292 && rse.ss == gfc_ss_terminator);
4294 if (loop.temp_ss != NULL)
4296 /* Increment count1 before finish the main body of a scalarized
4297 expression. */
4298 tmp = fold_build2_loc (input_location, PLUS_EXPR,
4299 gfc_array_index_type, count1, gfc_index_one_node);
4300 gfc_add_modify (&body, count1, tmp);
4301 gfc_trans_scalarized_loop_boundary (&loop, &body);
4303 /* We need to copy the temporary to the actual lhs. */
4304 gfc_init_se (&lse, NULL);
4305 gfc_init_se (&rse, NULL);
4306 gfc_copy_loopinfo_to_se (&lse, &loop);
4307 gfc_copy_loopinfo_to_se (&rse, &loop);
4309 rse.ss = loop.temp_ss;
4310 lse.ss = lss;
4312 gfc_conv_tmp_array_ref (&rse);
4313 gfc_conv_expr (&lse, expr1);
4315 gcc_assert (lse.ss == gfc_ss_terminator
4316 && rse.ss == gfc_ss_terminator);
4318 /* Form the mask expression according to the mask tree list. */
4319 index = count2;
4320 maskexpr = gfc_build_array_ref (mask, index, NULL);
4321 if (invert)
4322 maskexpr = fold_build1_loc (input_location, TRUTH_NOT_EXPR,
4323 TREE_TYPE (maskexpr), maskexpr);
4325 /* Use the scalar assignment as is. */
4326 tmp = gfc_trans_scalar_assign (&lse, &rse, expr1->ts, false, false,
4327 true);
4328 tmp = build3_v (COND_EXPR, maskexpr, tmp,
4329 build_empty_stmt (input_location));
4330 gfc_add_expr_to_block (&body, tmp);
4332 /* Increment count2. */
4333 tmp = fold_build2_loc (input_location, PLUS_EXPR,
4334 gfc_array_index_type, count2,
4335 gfc_index_one_node);
4336 gfc_add_modify (&body, count2, tmp);
4338 else
4340 /* Increment count1. */
4341 tmp = fold_build2_loc (input_location, PLUS_EXPR,
4342 gfc_array_index_type, count1,
4343 gfc_index_one_node);
4344 gfc_add_modify (&body, count1, tmp);
4347 /* Generate the copying loops. */
4348 gfc_trans_scalarizing_loops (&loop, &body);
4350 /* Wrap the whole thing up. */
4351 gfc_add_block_to_block (&block, &loop.pre);
4352 gfc_add_block_to_block (&block, &loop.post);
4353 gfc_cleanup_loop (&loop);
4356 return gfc_finish_block (&block);
4360 /* Translate the WHERE construct or statement.
4361 This function can be called iteratively to translate the nested WHERE
4362 construct or statement.
4363 MASK is the control mask. */
4365 static void
4366 gfc_trans_where_2 (gfc_code * code, tree mask, bool invert,
4367 forall_info * nested_forall_info, stmtblock_t * block)
4369 stmtblock_t inner_size_body;
4370 tree inner_size, size;
4371 gfc_ss *lss, *rss;
4372 tree mask_type;
4373 gfc_expr *expr1;
4374 gfc_expr *expr2;
4375 gfc_code *cblock;
4376 gfc_code *cnext;
4377 tree tmp;
4378 tree cond;
4379 tree count1, count2;
4380 bool need_cmask;
4381 bool need_pmask;
4382 int need_temp;
4383 tree pcmask = NULL_TREE;
4384 tree ppmask = NULL_TREE;
4385 tree cmask = NULL_TREE;
4386 tree pmask = NULL_TREE;
4387 gfc_actual_arglist *arg;
4389 /* the WHERE statement or the WHERE construct statement. */
4390 cblock = code->block;
4392 /* As the mask array can be very big, prefer compact boolean types. */
4393 mask_type = gfc_get_logical_type (gfc_logical_kinds[0].kind);
4395 /* Determine which temporary masks are needed. */
4396 if (!cblock->block)
4398 /* One clause: No ELSEWHEREs. */
4399 need_cmask = (cblock->next != 0);
4400 need_pmask = false;
4402 else if (cblock->block->block)
4404 /* Three or more clauses: Conditional ELSEWHEREs. */
4405 need_cmask = true;
4406 need_pmask = true;
4408 else if (cblock->next)
4410 /* Two clauses, the first non-empty. */
4411 need_cmask = true;
4412 need_pmask = (mask != NULL_TREE
4413 && cblock->block->next != 0);
4415 else if (!cblock->block->next)
4417 /* Two clauses, both empty. */
4418 need_cmask = false;
4419 need_pmask = false;
4421 /* Two clauses, the first empty, the second non-empty. */
4422 else if (mask)
4424 need_cmask = (cblock->block->expr1 != 0);
4425 need_pmask = true;
4427 else
4429 need_cmask = true;
4430 need_pmask = false;
4433 if (need_cmask || need_pmask)
4435 /* Calculate the size of temporary needed by the mask-expr. */
4436 gfc_init_block (&inner_size_body);
4437 inner_size = compute_inner_temp_size (cblock->expr1, cblock->expr1,
4438 &inner_size_body, &lss, &rss);
4440 gfc_free_ss_chain (lss);
4441 gfc_free_ss_chain (rss);
4443 /* Calculate the total size of temporary needed. */
4444 size = compute_overall_iter_number (nested_forall_info, inner_size,
4445 &inner_size_body, block);
4447 /* Check whether the size is negative. */
4448 cond = fold_build2_loc (input_location, LE_EXPR, boolean_type_node, size,
4449 gfc_index_zero_node);
4450 size = fold_build3_loc (input_location, COND_EXPR, gfc_array_index_type,
4451 cond, gfc_index_zero_node, size);
4452 size = gfc_evaluate_now (size, block);
4454 /* Allocate temporary for WHERE mask if needed. */
4455 if (need_cmask)
4456 cmask = allocate_temp_for_forall_nest_1 (mask_type, size, block,
4457 &pcmask);
4459 /* Allocate temporary for !mask if needed. */
4460 if (need_pmask)
4461 pmask = allocate_temp_for_forall_nest_1 (mask_type, size, block,
4462 &ppmask);
4465 while (cblock)
4467 /* Each time around this loop, the where clause is conditional
4468 on the value of mask and invert, which are updated at the
4469 bottom of the loop. */
4471 /* Has mask-expr. */
4472 if (cblock->expr1)
4474 /* Ensure that the WHERE mask will be evaluated exactly once.
4475 If there are no statements in this WHERE/ELSEWHERE clause,
4476 then we don't need to update the control mask (cmask).
4477 If this is the last clause of the WHERE construct, then
4478 we don't need to update the pending control mask (pmask). */
4479 if (mask)
4480 gfc_evaluate_where_mask (cblock->expr1, nested_forall_info,
4481 mask, invert,
4482 cblock->next ? cmask : NULL_TREE,
4483 cblock->block ? pmask : NULL_TREE,
4484 mask_type, block);
4485 else
4486 gfc_evaluate_where_mask (cblock->expr1, nested_forall_info,
4487 NULL_TREE, false,
4488 (cblock->next || cblock->block)
4489 ? cmask : NULL_TREE,
4490 NULL_TREE, mask_type, block);
4492 invert = false;
4494 /* It's a final elsewhere-stmt. No mask-expr is present. */
4495 else
4496 cmask = mask;
4498 /* The body of this where clause are controlled by cmask with
4499 sense specified by invert. */
4501 /* Get the assignment statement of a WHERE statement, or the first
4502 statement in where-body-construct of a WHERE construct. */
4503 cnext = cblock->next;
4504 while (cnext)
4506 switch (cnext->op)
4508 /* WHERE assignment statement. */
4509 case EXEC_ASSIGN_CALL:
4511 arg = cnext->ext.actual;
4512 expr1 = expr2 = NULL;
4513 for (; arg; arg = arg->next)
4515 if (!arg->expr)
4516 continue;
4517 if (expr1 == NULL)
4518 expr1 = arg->expr;
4519 else
4520 expr2 = arg->expr;
4522 goto evaluate;
4524 case EXEC_ASSIGN:
4525 expr1 = cnext->expr1;
4526 expr2 = cnext->expr2;
4527 evaluate:
4528 if (nested_forall_info != NULL)
4530 need_temp = gfc_check_dependency (expr1, expr2, 0);
4531 if (need_temp && cnext->op != EXEC_ASSIGN_CALL)
4532 gfc_trans_assign_need_temp (expr1, expr2,
4533 cmask, invert,
4534 nested_forall_info, block);
4535 else
4537 /* Variables to control maskexpr. */
4538 count1 = gfc_create_var (gfc_array_index_type, "count1");
4539 count2 = gfc_create_var (gfc_array_index_type, "count2");
4540 gfc_add_modify (block, count1, gfc_index_zero_node);
4541 gfc_add_modify (block, count2, gfc_index_zero_node);
4543 tmp = gfc_trans_where_assign (expr1, expr2,
4544 cmask, invert,
4545 count1, count2,
4546 cnext);
4548 tmp = gfc_trans_nested_forall_loop (nested_forall_info,
4549 tmp, 1);
4550 gfc_add_expr_to_block (block, tmp);
4553 else
4555 /* Variables to control maskexpr. */
4556 count1 = gfc_create_var (gfc_array_index_type, "count1");
4557 count2 = gfc_create_var (gfc_array_index_type, "count2");
4558 gfc_add_modify (block, count1, gfc_index_zero_node);
4559 gfc_add_modify (block, count2, gfc_index_zero_node);
4561 tmp = gfc_trans_where_assign (expr1, expr2,
4562 cmask, invert,
4563 count1, count2,
4564 cnext);
4565 gfc_add_expr_to_block (block, tmp);
4568 break;
4570 /* WHERE or WHERE construct is part of a where-body-construct. */
4571 case EXEC_WHERE:
4572 gfc_trans_where_2 (cnext, cmask, invert,
4573 nested_forall_info, block);
4574 break;
4576 default:
4577 gcc_unreachable ();
4580 /* The next statement within the same where-body-construct. */
4581 cnext = cnext->next;
4583 /* The next masked-elsewhere-stmt, elsewhere-stmt, or end-where-stmt. */
4584 cblock = cblock->block;
4585 if (mask == NULL_TREE)
4587 /* If we're the initial WHERE, we can simply invert the sense
4588 of the current mask to obtain the "mask" for the remaining
4589 ELSEWHEREs. */
4590 invert = true;
4591 mask = cmask;
4593 else
4595 /* Otherwise, for nested WHERE's we need to use the pending mask. */
4596 invert = false;
4597 mask = pmask;
4601 /* If we allocated a pending mask array, deallocate it now. */
4602 if (ppmask)
4604 tmp = gfc_call_free (ppmask);
4605 gfc_add_expr_to_block (block, tmp);
4608 /* If we allocated a current mask array, deallocate it now. */
4609 if (pcmask)
4611 tmp = gfc_call_free (pcmask);
4612 gfc_add_expr_to_block (block, tmp);
4616 /* Translate a simple WHERE construct or statement without dependencies.
4617 CBLOCK is the "then" clause of the WHERE statement, where CBLOCK->EXPR
4618 is the mask condition, and EBLOCK if non-NULL is the "else" clause.
4619 Currently both CBLOCK and EBLOCK are restricted to single assignments. */
4621 static tree
4622 gfc_trans_where_3 (gfc_code * cblock, gfc_code * eblock)
4624 stmtblock_t block, body;
4625 gfc_expr *cond, *tdst, *tsrc, *edst, *esrc;
4626 tree tmp, cexpr, tstmt, estmt;
4627 gfc_ss *css, *tdss, *tsss;
4628 gfc_se cse, tdse, tsse, edse, esse;
4629 gfc_loopinfo loop;
4630 gfc_ss *edss = 0;
4631 gfc_ss *esss = 0;
4633 /* Allow the scalarizer to workshare simple where loops. */
4634 if (ompws_flags & OMPWS_WORKSHARE_FLAG)
4635 ompws_flags |= OMPWS_SCALARIZER_WS;
4637 cond = cblock->expr1;
4638 tdst = cblock->next->expr1;
4639 tsrc = cblock->next->expr2;
4640 edst = eblock ? eblock->next->expr1 : NULL;
4641 esrc = eblock ? eblock->next->expr2 : NULL;
4643 gfc_start_block (&block);
4644 gfc_init_loopinfo (&loop);
4646 /* Handle the condition. */
4647 gfc_init_se (&cse, NULL);
4648 css = gfc_walk_expr (cond);
4649 gfc_add_ss_to_loop (&loop, css);
4651 /* Handle the then-clause. */
4652 gfc_init_se (&tdse, NULL);
4653 gfc_init_se (&tsse, NULL);
4654 tdss = gfc_walk_expr (tdst);
4655 tsss = gfc_walk_expr (tsrc);
4656 if (tsss == gfc_ss_terminator)
4658 tsss = gfc_get_scalar_ss (gfc_ss_terminator, tsrc);
4659 tsss->info->where = 1;
4661 gfc_add_ss_to_loop (&loop, tdss);
4662 gfc_add_ss_to_loop (&loop, tsss);
4664 if (eblock)
4666 /* Handle the else clause. */
4667 gfc_init_se (&edse, NULL);
4668 gfc_init_se (&esse, NULL);
4669 edss = gfc_walk_expr (edst);
4670 esss = gfc_walk_expr (esrc);
4671 if (esss == gfc_ss_terminator)
4673 esss = gfc_get_scalar_ss (gfc_ss_terminator, esrc);
4674 esss->info->where = 1;
4676 gfc_add_ss_to_loop (&loop, edss);
4677 gfc_add_ss_to_loop (&loop, esss);
4680 gfc_conv_ss_startstride (&loop);
4681 gfc_conv_loop_setup (&loop, &tdst->where);
4683 gfc_mark_ss_chain_used (css, 1);
4684 gfc_mark_ss_chain_used (tdss, 1);
4685 gfc_mark_ss_chain_used (tsss, 1);
4686 if (eblock)
4688 gfc_mark_ss_chain_used (edss, 1);
4689 gfc_mark_ss_chain_used (esss, 1);
4692 gfc_start_scalarized_body (&loop, &body);
4694 gfc_copy_loopinfo_to_se (&cse, &loop);
4695 gfc_copy_loopinfo_to_se (&tdse, &loop);
4696 gfc_copy_loopinfo_to_se (&tsse, &loop);
4697 cse.ss = css;
4698 tdse.ss = tdss;
4699 tsse.ss = tsss;
4700 if (eblock)
4702 gfc_copy_loopinfo_to_se (&edse, &loop);
4703 gfc_copy_loopinfo_to_se (&esse, &loop);
4704 edse.ss = edss;
4705 esse.ss = esss;
4708 gfc_conv_expr (&cse, cond);
4709 gfc_add_block_to_block (&body, &cse.pre);
4710 cexpr = cse.expr;
4712 gfc_conv_expr (&tsse, tsrc);
4713 if (tdss != gfc_ss_terminator && loop.temp_ss != NULL)
4714 gfc_conv_tmp_array_ref (&tdse);
4715 else
4716 gfc_conv_expr (&tdse, tdst);
4718 if (eblock)
4720 gfc_conv_expr (&esse, esrc);
4721 if (edss != gfc_ss_terminator && loop.temp_ss != NULL)
4722 gfc_conv_tmp_array_ref (&edse);
4723 else
4724 gfc_conv_expr (&edse, edst);
4727 tstmt = gfc_trans_scalar_assign (&tdse, &tsse, tdst->ts, false, false, true);
4728 estmt = eblock ? gfc_trans_scalar_assign (&edse, &esse, edst->ts, false,
4729 false, true)
4730 : build_empty_stmt (input_location);
4731 tmp = build3_v (COND_EXPR, cexpr, tstmt, estmt);
4732 gfc_add_expr_to_block (&body, tmp);
4733 gfc_add_block_to_block (&body, &cse.post);
4735 gfc_trans_scalarizing_loops (&loop, &body);
4736 gfc_add_block_to_block (&block, &loop.pre);
4737 gfc_add_block_to_block (&block, &loop.post);
4738 gfc_cleanup_loop (&loop);
4740 return gfc_finish_block (&block);
4743 /* As the WHERE or WHERE construct statement can be nested, we call
4744 gfc_trans_where_2 to do the translation, and pass the initial
4745 NULL values for both the control mask and the pending control mask. */
4747 tree
4748 gfc_trans_where (gfc_code * code)
4750 stmtblock_t block;
4751 gfc_code *cblock;
4752 gfc_code *eblock;
4754 cblock = code->block;
4755 if (cblock->next
4756 && cblock->next->op == EXEC_ASSIGN
4757 && !cblock->next->next)
4759 eblock = cblock->block;
4760 if (!eblock)
4762 /* A simple "WHERE (cond) x = y" statement or block is
4763 dependence free if cond is not dependent upon writing x,
4764 and the source y is unaffected by the destination x. */
4765 if (!gfc_check_dependency (cblock->next->expr1,
4766 cblock->expr1, 0)
4767 && !gfc_check_dependency (cblock->next->expr1,
4768 cblock->next->expr2, 0))
4769 return gfc_trans_where_3 (cblock, NULL);
4771 else if (!eblock->expr1
4772 && !eblock->block
4773 && eblock->next
4774 && eblock->next->op == EXEC_ASSIGN
4775 && !eblock->next->next)
4777 /* A simple "WHERE (cond) x1 = y1 ELSEWHERE x2 = y2 ENDWHERE"
4778 block is dependence free if cond is not dependent on writes
4779 to x1 and x2, y1 is not dependent on writes to x2, and y2
4780 is not dependent on writes to x1, and both y's are not
4781 dependent upon their own x's. In addition to this, the
4782 final two dependency checks below exclude all but the same
4783 array reference if the where and elswhere destinations
4784 are the same. In short, this is VERY conservative and this
4785 is needed because the two loops, required by the standard
4786 are coalesced in gfc_trans_where_3. */
4787 if (!gfc_check_dependency (cblock->next->expr1,
4788 cblock->expr1, 0)
4789 && !gfc_check_dependency (eblock->next->expr1,
4790 cblock->expr1, 0)
4791 && !gfc_check_dependency (cblock->next->expr1,
4792 eblock->next->expr2, 1)
4793 && !gfc_check_dependency (eblock->next->expr1,
4794 cblock->next->expr2, 1)
4795 && !gfc_check_dependency (cblock->next->expr1,
4796 cblock->next->expr2, 1)
4797 && !gfc_check_dependency (eblock->next->expr1,
4798 eblock->next->expr2, 1)
4799 && !gfc_check_dependency (cblock->next->expr1,
4800 eblock->next->expr1, 0)
4801 && !gfc_check_dependency (eblock->next->expr1,
4802 cblock->next->expr1, 0))
4803 return gfc_trans_where_3 (cblock, eblock);
4807 gfc_start_block (&block);
4809 gfc_trans_where_2 (code, NULL, false, NULL, &block);
4811 return gfc_finish_block (&block);
4815 /* CYCLE a DO loop. The label decl has already been created by
4816 gfc_trans_do(), it's in TREE_PURPOSE (backend_decl) of the gfc_code
4817 node at the head of the loop. We must mark the label as used. */
4819 tree
4820 gfc_trans_cycle (gfc_code * code)
4822 tree cycle_label;
4824 cycle_label = code->ext.which_construct->cycle_label;
4825 gcc_assert (cycle_label);
4827 TREE_USED (cycle_label) = 1;
4828 return build1_v (GOTO_EXPR, cycle_label);
4832 /* EXIT a DO loop. Similar to CYCLE, but now the label is in
4833 TREE_VALUE (backend_decl) of the gfc_code node at the head of the
4834 loop. */
4836 tree
4837 gfc_trans_exit (gfc_code * code)
4839 tree exit_label;
4841 exit_label = code->ext.which_construct->exit_label;
4842 gcc_assert (exit_label);
4844 TREE_USED (exit_label) = 1;
4845 return build1_v (GOTO_EXPR, exit_label);
4849 /* Translate the ALLOCATE statement. */
4851 tree
4852 gfc_trans_allocate (gfc_code * code)
4854 gfc_alloc *al;
4855 gfc_expr *e;
4856 gfc_expr *expr;
4857 gfc_se se;
4858 tree tmp;
4859 tree parm;
4860 tree stat;
4861 tree errmsg;
4862 tree errlen;
4863 tree label_errmsg;
4864 tree label_finish;
4865 tree memsz;
4866 tree expr3;
4867 tree slen3;
4868 stmtblock_t block;
4869 stmtblock_t post;
4870 gfc_expr *sz;
4871 gfc_se se_sz;
4872 tree class_expr;
4873 tree nelems;
4874 tree memsize = NULL_TREE;
4875 tree classexpr = NULL_TREE;
4877 if (!code->ext.alloc.list)
4878 return NULL_TREE;
4880 stat = tmp = memsz = NULL_TREE;
4881 label_errmsg = label_finish = errmsg = errlen = NULL_TREE;
4883 gfc_init_block (&block);
4884 gfc_init_block (&post);
4886 /* STAT= (and maybe ERRMSG=) is present. */
4887 if (code->expr1)
4889 /* STAT=. */
4890 tree gfc_int4_type_node = gfc_get_int_type (4);
4891 stat = gfc_create_var (gfc_int4_type_node, "stat");
4893 /* ERRMSG= only makes sense with STAT=. */
4894 if (code->expr2)
4896 gfc_init_se (&se, NULL);
4897 se.want_pointer = 1;
4898 gfc_conv_expr_lhs (&se, code->expr2);
4899 errmsg = se.expr;
4900 errlen = se.string_length;
4902 else
4904 errmsg = null_pointer_node;
4905 errlen = build_int_cst (gfc_charlen_type_node, 0);
4908 /* GOTO destinations. */
4909 label_errmsg = gfc_build_label_decl (NULL_TREE);
4910 label_finish = gfc_build_label_decl (NULL_TREE);
4911 TREE_USED (label_finish) = 0;
4914 expr3 = NULL_TREE;
4915 slen3 = NULL_TREE;
4917 for (al = code->ext.alloc.list; al != NULL; al = al->next)
4919 expr = gfc_copy_expr (al->expr);
4921 if (expr->ts.type == BT_CLASS)
4922 gfc_add_data_component (expr);
4924 gfc_init_se (&se, NULL);
4926 se.want_pointer = 1;
4927 se.descriptor_only = 1;
4928 gfc_conv_expr (&se, expr);
4930 /* Evaluate expr3 just once if not a variable. */
4931 if (al == code->ext.alloc.list
4932 && al->expr->ts.type == BT_CLASS
4933 && code->expr3
4934 && code->expr3->ts.type == BT_CLASS
4935 && code->expr3->expr_type != EXPR_VARIABLE)
4937 gfc_init_se (&se_sz, NULL);
4938 gfc_conv_expr_reference (&se_sz, code->expr3);
4939 gfc_conv_class_to_class (&se_sz, code->expr3,
4940 code->expr3->ts, false, true, false, false);
4941 gfc_add_block_to_block (&se.pre, &se_sz.pre);
4942 gfc_add_block_to_block (&se.post, &se_sz.post);
4943 classexpr = build_fold_indirect_ref_loc (input_location,
4944 se_sz.expr);
4945 classexpr = gfc_evaluate_now (classexpr, &se.pre);
4946 memsize = gfc_vtable_size_get (classexpr);
4947 memsize = fold_convert (sizetype, memsize);
4950 memsz = memsize;
4951 class_expr = classexpr;
4953 nelems = NULL_TREE;
4954 if (!gfc_array_allocate (&se, expr, stat, errmsg, errlen, label_finish,
4955 memsz, &nelems, code->expr3, &code->ext.alloc.ts))
4957 bool unlimited_char;
4959 unlimited_char = UNLIMITED_POLY (al->expr)
4960 && ((code->expr3 && code->expr3->ts.type == BT_CHARACTER)
4961 || (code->ext.alloc.ts.type == BT_CHARACTER
4962 && code->ext.alloc.ts.u.cl
4963 && code->ext.alloc.ts.u.cl->length));
4965 /* A scalar or derived type. */
4967 /* Determine allocate size. */
4968 if (al->expr->ts.type == BT_CLASS
4969 && !unlimited_char
4970 && code->expr3
4971 && memsz == NULL_TREE)
4973 if (code->expr3->ts.type == BT_CLASS)
4975 sz = gfc_copy_expr (code->expr3);
4976 gfc_add_vptr_component (sz);
4977 gfc_add_size_component (sz);
4978 gfc_init_se (&se_sz, NULL);
4979 gfc_conv_expr (&se_sz, sz);
4980 gfc_free_expr (sz);
4981 memsz = se_sz.expr;
4983 else
4984 memsz = TYPE_SIZE_UNIT (gfc_typenode_for_spec (&code->expr3->ts));
4986 else if (((al->expr->ts.type == BT_CHARACTER && al->expr->ts.deferred)
4987 || unlimited_char) && code->expr3)
4989 if (!code->expr3->ts.u.cl->backend_decl)
4991 /* Convert and use the length expression. */
4992 gfc_init_se (&se_sz, NULL);
4993 if (code->expr3->expr_type == EXPR_VARIABLE
4994 || code->expr3->expr_type == EXPR_CONSTANT)
4996 gfc_conv_expr (&se_sz, code->expr3);
4997 gfc_add_block_to_block (&se.pre, &se_sz.pre);
4998 se_sz.string_length
4999 = gfc_evaluate_now (se_sz.string_length, &se.pre);
5000 gfc_add_block_to_block (&se.pre, &se_sz.post);
5001 memsz = se_sz.string_length;
5003 else if (code->expr3->mold
5004 && code->expr3->ts.u.cl
5005 && code->expr3->ts.u.cl->length)
5007 gfc_conv_expr (&se_sz, code->expr3->ts.u.cl->length);
5008 gfc_add_block_to_block (&se.pre, &se_sz.pre);
5009 se_sz.expr = gfc_evaluate_now (se_sz.expr, &se.pre);
5010 gfc_add_block_to_block (&se.pre, &se_sz.post);
5011 memsz = se_sz.expr;
5013 else
5015 /* This is would be inefficient and possibly could
5016 generate wrong code if the result were not stored
5017 in expr3/slen3. */
5018 if (slen3 == NULL_TREE)
5020 gfc_conv_expr (&se_sz, code->expr3);
5021 gfc_add_block_to_block (&se.pre, &se_sz.pre);
5022 expr3 = gfc_evaluate_now (se_sz.expr, &se.pre);
5023 gfc_add_block_to_block (&post, &se_sz.post);
5024 slen3 = gfc_evaluate_now (se_sz.string_length,
5025 &se.pre);
5027 memsz = slen3;
5030 else
5031 /* Otherwise use the stored string length. */
5032 memsz = code->expr3->ts.u.cl->backend_decl;
5033 tmp = al->expr->ts.u.cl->backend_decl;
5035 /* Store the string length. */
5036 if (tmp && TREE_CODE (tmp) == VAR_DECL)
5037 gfc_add_modify (&se.pre, tmp, fold_convert (TREE_TYPE (tmp),
5038 memsz));
5039 else if (al->expr->ts.type == BT_CHARACTER
5040 && al->expr->ts.deferred && se.string_length)
5041 gfc_add_modify (&se.pre, se.string_length,
5042 fold_convert (TREE_TYPE (se.string_length),
5043 memsz));
5045 /* Convert to size in bytes, using the character KIND. */
5046 if (unlimited_char)
5047 tmp = TREE_TYPE (gfc_typenode_for_spec (&code->expr3->ts));
5048 else
5049 tmp = TREE_TYPE (gfc_typenode_for_spec (&al->expr->ts));
5050 tmp = TYPE_SIZE_UNIT (tmp);
5051 memsz = fold_build2_loc (input_location, MULT_EXPR,
5052 TREE_TYPE (tmp), tmp,
5053 fold_convert (TREE_TYPE (tmp), memsz));
5055 else if ((al->expr->ts.type == BT_CHARACTER && al->expr->ts.deferred)
5056 || unlimited_char)
5058 gcc_assert (code->ext.alloc.ts.u.cl && code->ext.alloc.ts.u.cl->length);
5059 gfc_init_se (&se_sz, NULL);
5060 gfc_conv_expr (&se_sz, code->ext.alloc.ts.u.cl->length);
5061 gfc_add_block_to_block (&se.pre, &se_sz.pre);
5062 se_sz.expr = gfc_evaluate_now (se_sz.expr, &se.pre);
5063 gfc_add_block_to_block (&se.pre, &se_sz.post);
5064 /* Store the string length. */
5065 tmp = al->expr->ts.u.cl->backend_decl;
5066 gfc_add_modify (&se.pre, tmp, fold_convert (TREE_TYPE (tmp),
5067 se_sz.expr));
5068 tmp = TREE_TYPE (gfc_typenode_for_spec (&code->ext.alloc.ts));
5069 tmp = TYPE_SIZE_UNIT (tmp);
5070 memsz = fold_build2_loc (input_location, MULT_EXPR,
5071 TREE_TYPE (tmp), tmp,
5072 fold_convert (TREE_TYPE (se_sz.expr),
5073 se_sz.expr));
5075 else if (code->ext.alloc.ts.type != BT_UNKNOWN)
5076 memsz = TYPE_SIZE_UNIT (gfc_typenode_for_spec (&code->ext.alloc.ts));
5077 else if (memsz == NULL_TREE)
5078 memsz = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (se.expr)));
5080 if (expr->ts.type == BT_CHARACTER && memsz == NULL_TREE)
5082 memsz = se.string_length;
5084 /* Convert to size in bytes, using the character KIND. */
5085 tmp = TREE_TYPE (gfc_typenode_for_spec (&code->ext.alloc.ts));
5086 tmp = TYPE_SIZE_UNIT (tmp);
5087 memsz = fold_build2_loc (input_location, MULT_EXPR,
5088 TREE_TYPE (tmp), tmp,
5089 fold_convert (TREE_TYPE (tmp), memsz));
5092 /* Allocate - for non-pointers with re-alloc checking. */
5093 if (gfc_expr_attr (expr).allocatable)
5094 gfc_allocate_allocatable (&se.pre, se.expr, memsz, NULL_TREE,
5095 stat, errmsg, errlen, label_finish, expr);
5096 else
5097 gfc_allocate_using_malloc (&se.pre, se.expr, memsz, stat);
5099 if (al->expr->ts.type == BT_DERIVED
5100 && expr->ts.u.derived->attr.alloc_comp)
5102 tmp = build_fold_indirect_ref_loc (input_location, se.expr);
5103 tmp = gfc_nullify_alloc_comp (expr->ts.u.derived, tmp, 0);
5104 gfc_add_expr_to_block (&se.pre, tmp);
5108 gfc_add_block_to_block (&block, &se.pre);
5110 /* Error checking -- Note: ERRMSG only makes sense with STAT. */
5111 if (code->expr1)
5113 tmp = build1_v (GOTO_EXPR, label_errmsg);
5114 parm = fold_build2_loc (input_location, NE_EXPR,
5115 boolean_type_node, stat,
5116 build_int_cst (TREE_TYPE (stat), 0));
5117 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
5118 gfc_unlikely (parm, PRED_FORTRAN_FAIL_ALLOC),
5119 tmp, build_empty_stmt (input_location));
5120 gfc_add_expr_to_block (&block, tmp);
5123 /* We need the vptr of CLASS objects to be initialized. */
5124 e = gfc_copy_expr (al->expr);
5125 if (e->ts.type == BT_CLASS)
5127 gfc_expr *lhs, *rhs;
5128 gfc_se lse;
5129 gfc_ref *ref, *class_ref, *tail;
5131 /* Find the last class reference. */
5132 class_ref = NULL;
5133 for (ref = e->ref; ref; ref = ref->next)
5135 if (ref->type == REF_COMPONENT
5136 && ref->u.c.component->ts.type == BT_CLASS)
5137 class_ref = ref;
5139 if (ref->next == NULL)
5140 break;
5143 /* Remove and store all subsequent references after the
5144 CLASS reference. */
5145 if (class_ref)
5147 tail = class_ref->next;
5148 class_ref->next = NULL;
5150 else
5152 tail = e->ref;
5153 e->ref = NULL;
5156 lhs = gfc_expr_to_initialize (e);
5157 gfc_add_vptr_component (lhs);
5159 /* Remove the _vptr component and restore the original tail
5160 references. */
5161 if (class_ref)
5163 gfc_free_ref_list (class_ref->next);
5164 class_ref->next = tail;
5166 else
5168 gfc_free_ref_list (e->ref);
5169 e->ref = tail;
5172 if (class_expr != NULL_TREE)
5174 /* Polymorphic SOURCE: VPTR must be determined at run time. */
5175 gfc_init_se (&lse, NULL);
5176 lse.want_pointer = 1;
5177 gfc_conv_expr (&lse, lhs);
5178 tmp = gfc_class_vptr_get (class_expr);
5179 gfc_add_modify (&block, lse.expr,
5180 fold_convert (TREE_TYPE (lse.expr), tmp));
5182 else if (code->expr3 && code->expr3->ts.type == BT_CLASS)
5184 /* Polymorphic SOURCE: VPTR must be determined at run time. */
5185 rhs = gfc_copy_expr (code->expr3);
5186 gfc_add_vptr_component (rhs);
5187 tmp = gfc_trans_pointer_assignment (lhs, rhs);
5188 gfc_add_expr_to_block (&block, tmp);
5189 gfc_free_expr (rhs);
5190 rhs = gfc_expr_to_initialize (e);
5192 else
5194 /* VPTR is fixed at compile time. */
5195 gfc_symbol *vtab;
5196 gfc_typespec *ts;
5197 if (code->expr3)
5198 ts = &code->expr3->ts;
5199 else if (e->ts.type == BT_DERIVED)
5200 ts = &e->ts;
5201 else if (code->ext.alloc.ts.type == BT_DERIVED || UNLIMITED_POLY (al->expr))
5202 ts = &code->ext.alloc.ts;
5203 else if (e->ts.type == BT_CLASS)
5204 ts = &CLASS_DATA (e)->ts;
5205 else
5206 ts = &e->ts;
5208 if (ts->type == BT_DERIVED || UNLIMITED_POLY (e))
5210 vtab = gfc_find_vtab (ts);
5211 gcc_assert (vtab);
5212 gfc_init_se (&lse, NULL);
5213 lse.want_pointer = 1;
5214 gfc_conv_expr (&lse, lhs);
5215 tmp = gfc_build_addr_expr (NULL_TREE,
5216 gfc_get_symbol_decl (vtab));
5217 gfc_add_modify (&block, lse.expr,
5218 fold_convert (TREE_TYPE (lse.expr), tmp));
5221 gfc_free_expr (lhs);
5224 gfc_free_expr (e);
5226 if (code->expr3 && !code->expr3->mold)
5228 /* Initialization via SOURCE block
5229 (or static default initializer). */
5230 gfc_expr *rhs = gfc_copy_expr (code->expr3);
5231 if (class_expr != NULL_TREE)
5233 tree to;
5234 to = TREE_OPERAND (se.expr, 0);
5236 tmp = gfc_copy_class_to_class (class_expr, to, nelems);
5238 else if (al->expr->ts.type == BT_CLASS)
5240 gfc_actual_arglist *actual;
5241 gfc_expr *ppc;
5242 gfc_code *ppc_code;
5243 gfc_ref *ref, *dataref;
5245 /* Do a polymorphic deep copy. */
5246 actual = gfc_get_actual_arglist ();
5247 actual->expr = gfc_copy_expr (rhs);
5248 if (rhs->ts.type == BT_CLASS)
5249 gfc_add_data_component (actual->expr);
5250 actual->next = gfc_get_actual_arglist ();
5251 actual->next->expr = gfc_copy_expr (al->expr);
5252 actual->next->expr->ts.type = BT_CLASS;
5253 gfc_add_data_component (actual->next->expr);
5255 dataref = NULL;
5256 /* Make sure we go up through the reference chain to
5257 the _data reference, where the arrayspec is found. */
5258 for (ref = actual->next->expr->ref; ref; ref = ref->next)
5259 if (ref->type == REF_COMPONENT
5260 && strcmp (ref->u.c.component->name, "_data") == 0)
5261 dataref = ref;
5263 if (dataref && dataref->u.c.component->as)
5265 int dim;
5266 gfc_expr *temp;
5267 gfc_ref *ref = dataref->next;
5268 ref->u.ar.type = AR_SECTION;
5269 /* We have to set up the array reference to give ranges
5270 in all dimensions and ensure that the end and stride
5271 are set so that the copy can be scalarized. */
5272 dim = 0;
5273 for (; dim < dataref->u.c.component->as->rank; dim++)
5275 ref->u.ar.dimen_type[dim] = DIMEN_RANGE;
5276 if (ref->u.ar.end[dim] == NULL)
5278 ref->u.ar.end[dim] = ref->u.ar.start[dim];
5279 temp = gfc_get_int_expr (gfc_default_integer_kind,
5280 &al->expr->where, 1);
5281 ref->u.ar.start[dim] = temp;
5283 temp = gfc_subtract (gfc_copy_expr (ref->u.ar.end[dim]),
5284 gfc_copy_expr (ref->u.ar.start[dim]));
5285 temp = gfc_add (gfc_get_int_expr (gfc_default_integer_kind,
5286 &al->expr->where, 1),
5287 temp);
5290 if (rhs->ts.type == BT_CLASS)
5292 ppc = gfc_copy_expr (rhs);
5293 gfc_add_vptr_component (ppc);
5295 else
5296 ppc = gfc_lval_expr_from_sym (gfc_find_vtab (&rhs->ts));
5297 gfc_add_component_ref (ppc, "_copy");
5299 ppc_code = gfc_get_code (EXEC_CALL);
5300 ppc_code->resolved_sym = ppc->symtree->n.sym;
5301 /* Although '_copy' is set to be elemental in class.c, it is
5302 not staying that way. Find out why, sometime.... */
5303 ppc_code->resolved_sym->attr.elemental = 1;
5304 ppc_code->ext.actual = actual;
5305 ppc_code->expr1 = ppc;
5306 /* Since '_copy' is elemental, the scalarizer will take care
5307 of arrays in gfc_trans_call. */
5308 tmp = gfc_trans_call (ppc_code, true, NULL, NULL, false);
5309 gfc_free_statements (ppc_code);
5311 else if (expr3 != NULL_TREE)
5313 tmp = build_fold_indirect_ref_loc (input_location, se.expr);
5314 gfc_trans_string_copy (&block, slen3, tmp, code->expr3->ts.kind,
5315 slen3, expr3, code->expr3->ts.kind);
5316 tmp = NULL_TREE;
5318 else
5320 /* Switch off automatic reallocation since we have just done
5321 the ALLOCATE. */
5322 int realloc_lhs = gfc_option.flag_realloc_lhs;
5323 gfc_option.flag_realloc_lhs = 0;
5324 tmp = gfc_trans_assignment (gfc_expr_to_initialize (expr),
5325 rhs, false, false);
5326 gfc_option.flag_realloc_lhs = realloc_lhs;
5328 gfc_free_expr (rhs);
5329 gfc_add_expr_to_block (&block, tmp);
5331 else if (code->expr3 && code->expr3->mold
5332 && code->expr3->ts.type == BT_CLASS)
5334 /* Since the _vptr has already been assigned to the allocate
5335 object, we can use gfc_copy_class_to_class in its
5336 initialization mode. */
5337 tmp = TREE_OPERAND (se.expr, 0);
5338 tmp = gfc_copy_class_to_class (NULL_TREE, tmp, nelems);
5339 gfc_add_expr_to_block (&block, tmp);
5342 gfc_free_expr (expr);
5345 /* STAT. */
5346 if (code->expr1)
5348 tmp = build1_v (LABEL_EXPR, label_errmsg);
5349 gfc_add_expr_to_block (&block, tmp);
5352 /* ERRMSG - only useful if STAT is present. */
5353 if (code->expr1 && code->expr2)
5355 const char *msg = "Attempt to allocate an allocated object";
5356 tree slen, dlen, errmsg_str;
5357 stmtblock_t errmsg_block;
5359 gfc_init_block (&errmsg_block);
5361 errmsg_str = gfc_create_var (pchar_type_node, "ERRMSG");
5362 gfc_add_modify (&errmsg_block, errmsg_str,
5363 gfc_build_addr_expr (pchar_type_node,
5364 gfc_build_localized_cstring_const (msg)));
5366 slen = build_int_cst (gfc_charlen_type_node, ((int) strlen (msg)));
5367 dlen = gfc_get_expr_charlen (code->expr2);
5368 slen = fold_build2_loc (input_location, MIN_EXPR, TREE_TYPE (slen), dlen,
5369 slen);
5371 gfc_trans_string_copy (&errmsg_block, dlen, errmsg, code->expr2->ts.kind,
5372 slen, errmsg_str, gfc_default_character_kind);
5373 dlen = gfc_finish_block (&errmsg_block);
5375 tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, stat,
5376 build_int_cst (TREE_TYPE (stat), 0));
5378 tmp = build3_v (COND_EXPR, tmp, dlen, build_empty_stmt (input_location));
5380 gfc_add_expr_to_block (&block, tmp);
5383 /* STAT block. */
5384 if (code->expr1)
5386 if (TREE_USED (label_finish))
5388 tmp = build1_v (LABEL_EXPR, label_finish);
5389 gfc_add_expr_to_block (&block, tmp);
5392 gfc_init_se (&se, NULL);
5393 gfc_conv_expr_lhs (&se, code->expr1);
5394 tmp = convert (TREE_TYPE (se.expr), stat);
5395 gfc_add_modify (&block, se.expr, tmp);
5398 gfc_add_block_to_block (&block, &se.post);
5399 gfc_add_block_to_block (&block, &post);
5401 return gfc_finish_block (&block);
5405 /* Translate a DEALLOCATE statement. */
5407 tree
5408 gfc_trans_deallocate (gfc_code *code)
5410 gfc_se se;
5411 gfc_alloc *al;
5412 tree apstat, pstat, stat, errmsg, errlen, tmp;
5413 tree label_finish, label_errmsg;
5414 stmtblock_t block;
5416 pstat = apstat = stat = errmsg = errlen = tmp = NULL_TREE;
5417 label_finish = label_errmsg = NULL_TREE;
5419 gfc_start_block (&block);
5421 /* Count the number of failed deallocations. If deallocate() was
5422 called with STAT= , then set STAT to the count. If deallocate
5423 was called with ERRMSG, then set ERRMG to a string. */
5424 if (code->expr1)
5426 tree gfc_int4_type_node = gfc_get_int_type (4);
5428 stat = gfc_create_var (gfc_int4_type_node, "stat");
5429 pstat = gfc_build_addr_expr (NULL_TREE, stat);
5431 /* GOTO destinations. */
5432 label_errmsg = gfc_build_label_decl (NULL_TREE);
5433 label_finish = gfc_build_label_decl (NULL_TREE);
5434 TREE_USED (label_finish) = 0;
5437 /* Set ERRMSG - only needed if STAT is available. */
5438 if (code->expr1 && code->expr2)
5440 gfc_init_se (&se, NULL);
5441 se.want_pointer = 1;
5442 gfc_conv_expr_lhs (&se, code->expr2);
5443 errmsg = se.expr;
5444 errlen = se.string_length;
5447 for (al = code->ext.alloc.list; al != NULL; al = al->next)
5449 gfc_expr *expr = gfc_copy_expr (al->expr);
5450 gcc_assert (expr->expr_type == EXPR_VARIABLE);
5452 if (expr->ts.type == BT_CLASS)
5453 gfc_add_data_component (expr);
5455 gfc_init_se (&se, NULL);
5456 gfc_start_block (&se.pre);
5458 se.want_pointer = 1;
5459 se.descriptor_only = 1;
5460 gfc_conv_expr (&se, expr);
5462 if (expr->rank || gfc_is_coarray (expr))
5464 if (expr->ts.type == BT_DERIVED && expr->ts.u.derived->attr.alloc_comp
5465 && !gfc_is_finalizable (expr->ts.u.derived, NULL))
5467 gfc_ref *ref;
5468 gfc_ref *last = NULL;
5469 for (ref = expr->ref; ref; ref = ref->next)
5470 if (ref->type == REF_COMPONENT)
5471 last = ref;
5473 /* Do not deallocate the components of a derived type
5474 ultimate pointer component. */
5475 if (!(last && last->u.c.component->attr.pointer)
5476 && !(!last && expr->symtree->n.sym->attr.pointer))
5478 tmp = gfc_deallocate_alloc_comp (expr->ts.u.derived, se.expr,
5479 expr->rank);
5480 gfc_add_expr_to_block (&se.pre, tmp);
5483 tmp = gfc_array_deallocate (se.expr, pstat, errmsg, errlen,
5484 label_finish, expr);
5485 gfc_add_expr_to_block (&se.pre, tmp);
5486 if (al->expr->ts.type == BT_CLASS)
5487 gfc_reset_vptr (&se.pre, al->expr);
5489 else
5491 tmp = gfc_deallocate_scalar_with_status (se.expr, pstat, false,
5492 al->expr, al->expr->ts);
5493 gfc_add_expr_to_block (&se.pre, tmp);
5495 /* Set to zero after deallocation. */
5496 tmp = fold_build2_loc (input_location, MODIFY_EXPR, void_type_node,
5497 se.expr,
5498 build_int_cst (TREE_TYPE (se.expr), 0));
5499 gfc_add_expr_to_block (&se.pre, tmp);
5501 if (al->expr->ts.type == BT_CLASS)
5502 gfc_reset_vptr (&se.pre, al->expr);
5505 if (code->expr1)
5507 tree cond;
5509 cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, stat,
5510 build_int_cst (TREE_TYPE (stat), 0));
5511 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
5512 gfc_unlikely (cond, PRED_FORTRAN_FAIL_ALLOC),
5513 build1_v (GOTO_EXPR, label_errmsg),
5514 build_empty_stmt (input_location));
5515 gfc_add_expr_to_block (&se.pre, tmp);
5518 tmp = gfc_finish_block (&se.pre);
5519 gfc_add_expr_to_block (&block, tmp);
5520 gfc_free_expr (expr);
5523 if (code->expr1)
5525 tmp = build1_v (LABEL_EXPR, label_errmsg);
5526 gfc_add_expr_to_block (&block, tmp);
5529 /* Set ERRMSG - only needed if STAT is available. */
5530 if (code->expr1 && code->expr2)
5532 const char *msg = "Attempt to deallocate an unallocated object";
5533 stmtblock_t errmsg_block;
5534 tree errmsg_str, slen, dlen, cond;
5536 gfc_init_block (&errmsg_block);
5538 errmsg_str = gfc_create_var (pchar_type_node, "ERRMSG");
5539 gfc_add_modify (&errmsg_block, errmsg_str,
5540 gfc_build_addr_expr (pchar_type_node,
5541 gfc_build_localized_cstring_const (msg)));
5542 slen = build_int_cst (gfc_charlen_type_node, ((int) strlen (msg)));
5543 dlen = gfc_get_expr_charlen (code->expr2);
5545 gfc_trans_string_copy (&errmsg_block, dlen, errmsg, code->expr2->ts.kind,
5546 slen, errmsg_str, gfc_default_character_kind);
5547 tmp = gfc_finish_block (&errmsg_block);
5549 cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, stat,
5550 build_int_cst (TREE_TYPE (stat), 0));
5551 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
5552 gfc_unlikely (cond, PRED_FORTRAN_FAIL_ALLOC), tmp,
5553 build_empty_stmt (input_location));
5555 gfc_add_expr_to_block (&block, tmp);
5558 if (code->expr1 && TREE_USED (label_finish))
5560 tmp = build1_v (LABEL_EXPR, label_finish);
5561 gfc_add_expr_to_block (&block, tmp);
5564 /* Set STAT. */
5565 if (code->expr1)
5567 gfc_init_se (&se, NULL);
5568 gfc_conv_expr_lhs (&se, code->expr1);
5569 tmp = convert (TREE_TYPE (se.expr), stat);
5570 gfc_add_modify (&block, se.expr, tmp);
5573 return gfc_finish_block (&block);
5576 #include "gt-fortran-trans-stmt.h"