svn merge -r 218679:218997 svn+ssh://gcc.gnu.org/svn/gcc/trunk
[official-gcc.git] / gcc / fortran / trans-stmt.c
blob277ff59a26440a1f563b5f08e8fcc75fadb63d05
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 (flag_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 ? (flag_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 ? (flag_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 ? (flag_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 && flag_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 && flag_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 && flag_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 (flag_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 (flag_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 (flag_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 (flag_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, token = NULL_TREE;
1116 gfc_start_block (&block);
1118 if (flag_coarray == GFC_FCOARRAY_LIB)
1120 token = gfc_get_symbol_decl (code->resolved_sym);
1121 token = GFC_TYPE_ARRAY_CAF_TOKEN (TREE_TYPE (token));
1122 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_lock, 7,
1123 token, integer_zero_node, integer_one_node,
1124 null_pointer_node, null_pointer_node,
1125 null_pointer_node, integer_zero_node);
1126 gfc_add_expr_to_block (&block, tmp);
1129 tmp = gfc_trans_code (code->block->next);
1130 gfc_add_expr_to_block (&block, tmp);
1132 if (flag_coarray == GFC_FCOARRAY_LIB)
1134 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_unlock, 6,
1135 token, integer_zero_node, integer_one_node,
1136 null_pointer_node, null_pointer_node,
1137 integer_zero_node);
1138 gfc_add_expr_to_block (&block, tmp);
1142 return gfc_finish_block (&block);
1146 /* Do proper initialization for ASSOCIATE names. */
1148 static void
1149 trans_associate_var (gfc_symbol *sym, gfc_wrapped_block *block)
1151 gfc_expr *e;
1152 tree tmp;
1153 bool class_target;
1154 bool unlimited;
1155 tree desc;
1156 tree offset;
1157 tree dim;
1158 int n;
1160 gcc_assert (sym->assoc);
1161 e = sym->assoc->target;
1163 class_target = (e->expr_type == EXPR_VARIABLE)
1164 && (gfc_is_class_scalar_expr (e)
1165 || gfc_is_class_array_ref (e, NULL));
1167 unlimited = UNLIMITED_POLY (e);
1169 /* Do a `pointer assignment' with updated descriptor (or assign descriptor
1170 to array temporary) for arrays with either unknown shape or if associating
1171 to a variable. */
1172 if (sym->attr.dimension && !class_target
1173 && (sym->as->type == AS_DEFERRED || sym->assoc->variable))
1175 gfc_se se;
1176 tree desc;
1177 bool cst_array_ctor;
1179 desc = sym->backend_decl;
1180 cst_array_ctor = e->expr_type == EXPR_ARRAY
1181 && gfc_constant_array_constructor_p (e->value.constructor);
1183 /* If association is to an expression, evaluate it and create temporary.
1184 Otherwise, get descriptor of target for pointer assignment. */
1185 gfc_init_se (&se, NULL);
1186 if (sym->assoc->variable || cst_array_ctor)
1188 se.direct_byref = 1;
1189 se.use_offset = 1;
1190 se.expr = desc;
1193 gfc_conv_expr_descriptor (&se, e);
1195 /* If we didn't already do the pointer assignment, set associate-name
1196 descriptor to the one generated for the temporary. */
1197 if (!sym->assoc->variable && !cst_array_ctor)
1199 int dim;
1201 gfc_add_modify (&se.pre, desc, se.expr);
1203 /* The generated descriptor has lower bound zero (as array
1204 temporary), shift bounds so we get lower bounds of 1. */
1205 for (dim = 0; dim < e->rank; ++dim)
1206 gfc_conv_shift_descriptor_lbound (&se.pre, desc,
1207 dim, gfc_index_one_node);
1210 /* If this is a subreference array pointer associate name use the
1211 associate variable element size for the value of 'span'. */
1212 if (sym->attr.subref_array_pointer)
1214 gcc_assert (e->expr_type == EXPR_VARIABLE);
1215 tmp = e->symtree->n.sym->backend_decl;
1216 tmp = gfc_get_element_type (TREE_TYPE (tmp));
1217 tmp = fold_convert (gfc_array_index_type, size_in_bytes (tmp));
1218 gfc_add_modify (&se.pre, GFC_DECL_SPAN(desc), tmp);
1221 /* Done, register stuff as init / cleanup code. */
1222 gfc_add_init_cleanup (block, gfc_finish_block (&se.pre),
1223 gfc_finish_block (&se.post));
1226 /* Temporaries, arising from TYPE IS, just need the descriptor of class
1227 arrays to be assigned directly. */
1228 else if (class_target && sym->attr.dimension
1229 && (sym->ts.type == BT_DERIVED || unlimited))
1231 gfc_se se;
1233 gfc_init_se (&se, NULL);
1234 se.descriptor_only = 1;
1235 gfc_conv_expr (&se, e);
1237 gcc_assert (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (se.expr)));
1238 gcc_assert (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (sym->backend_decl)));
1240 gfc_add_modify (&se.pre, sym->backend_decl, se.expr);
1242 if (unlimited)
1244 /* Recover the dtype, which has been overwritten by the
1245 assignment from an unlimited polymorphic object. */
1246 tmp = gfc_conv_descriptor_dtype (sym->backend_decl);
1247 gfc_add_modify (&se.pre, tmp,
1248 gfc_get_dtype (TREE_TYPE (sym->backend_decl)));
1251 gfc_add_init_cleanup (block, gfc_finish_block( &se.pre),
1252 gfc_finish_block (&se.post));
1255 /* Do a scalar pointer assignment; this is for scalar variable targets. */
1256 else if (gfc_is_associate_pointer (sym))
1258 gfc_se se;
1260 gcc_assert (!sym->attr.dimension);
1262 gfc_init_se (&se, NULL);
1264 /* Class associate-names come this way because they are
1265 unconditionally associate pointers and the symbol is scalar. */
1266 if (sym->ts.type == BT_CLASS && CLASS_DATA (sym)->attr.dimension)
1268 /* For a class array we need a descriptor for the selector. */
1269 gfc_conv_expr_descriptor (&se, e);
1271 /* Obtain a temporary class container for the result. */
1272 gfc_conv_class_to_class (&se, e, sym->ts, false, true, false, false);
1273 se.expr = build_fold_indirect_ref_loc (input_location, se.expr);
1275 /* Set the offset. */
1276 desc = gfc_class_data_get (se.expr);
1277 offset = gfc_index_zero_node;
1278 for (n = 0; n < e->rank; n++)
1280 dim = gfc_rank_cst[n];
1281 tmp = fold_build2_loc (input_location, MULT_EXPR,
1282 gfc_array_index_type,
1283 gfc_conv_descriptor_stride_get (desc, dim),
1284 gfc_conv_descriptor_lbound_get (desc, dim));
1285 offset = fold_build2_loc (input_location, MINUS_EXPR,
1286 gfc_array_index_type,
1287 offset, tmp);
1289 gfc_conv_descriptor_offset_set (&se.pre, desc, offset);
1291 else if (sym->ts.type == BT_CLASS && e->ts.type == BT_CLASS
1292 && CLASS_DATA (e)->attr.dimension)
1294 /* This is bound to be a class array element. */
1295 gfc_conv_expr_reference (&se, e);
1296 /* Get the _vptr component of the class object. */
1297 tmp = gfc_get_vptr_from_expr (se.expr);
1298 /* Obtain a temporary class container for the result. */
1299 gfc_conv_derived_to_class (&se, e, sym->ts, tmp, false, false);
1300 se.expr = build_fold_indirect_ref_loc (input_location, se.expr);
1302 else
1303 gfc_conv_expr (&se, e);
1305 tmp = TREE_TYPE (sym->backend_decl);
1306 tmp = gfc_build_addr_expr (tmp, se.expr);
1307 gfc_add_modify (&se.pre, sym->backend_decl, tmp);
1309 gfc_add_init_cleanup (block, gfc_finish_block( &se.pre),
1310 gfc_finish_block (&se.post));
1313 /* Do a simple assignment. This is for scalar expressions, where we
1314 can simply use expression assignment. */
1315 else
1317 gfc_expr *lhs;
1319 lhs = gfc_lval_expr_from_sym (sym);
1320 tmp = gfc_trans_assignment (lhs, e, false, true);
1321 gfc_add_init_cleanup (block, tmp, NULL_TREE);
1324 /* Set the stringlength from the vtable size. */
1325 if (sym->ts.type == BT_CHARACTER && sym->attr.select_type_temporary)
1327 tree charlen;
1328 gfc_se se;
1329 gfc_init_se (&se, NULL);
1330 gcc_assert (UNLIMITED_POLY (e->symtree->n.sym));
1331 tmp = gfc_get_symbol_decl (e->symtree->n.sym);
1332 tmp = gfc_vtable_size_get (tmp);
1333 gfc_get_symbol_decl (sym);
1334 charlen = sym->ts.u.cl->backend_decl;
1335 gfc_add_modify (&se.pre, charlen,
1336 fold_convert (TREE_TYPE (charlen), tmp));
1337 gfc_add_init_cleanup (block, gfc_finish_block( &se.pre),
1338 gfc_finish_block (&se.post));
1343 /* Translate a BLOCK construct. This is basically what we would do for a
1344 procedure body. */
1346 tree
1347 gfc_trans_block_construct (gfc_code* code)
1349 gfc_namespace* ns;
1350 gfc_symbol* sym;
1351 gfc_wrapped_block block;
1352 tree exit_label;
1353 stmtblock_t body;
1354 gfc_association_list *ass;
1356 ns = code->ext.block.ns;
1357 gcc_assert (ns);
1358 sym = ns->proc_name;
1359 gcc_assert (sym);
1361 /* Process local variables. */
1362 gcc_assert (!sym->tlink);
1363 sym->tlink = sym;
1364 gfc_process_block_locals (ns);
1366 /* Generate code including exit-label. */
1367 gfc_init_block (&body);
1368 exit_label = gfc_build_label_decl (NULL_TREE);
1369 code->exit_label = exit_label;
1371 /* Generate !$ACC DECLARE directive. */
1372 if (ns->oacc_declare_clauses)
1374 tree tmp = gfc_trans_oacc_declare (&body, ns);
1375 gfc_add_expr_to_block (&body, tmp);
1378 gfc_add_expr_to_block (&body, gfc_trans_code (ns->code));
1379 gfc_add_expr_to_block (&body, build1_v (LABEL_EXPR, exit_label));
1381 /* Finish everything. */
1382 gfc_start_wrapped_block (&block, gfc_finish_block (&body));
1383 gfc_trans_deferred_vars (sym, &block);
1384 for (ass = code->ext.block.assoc; ass; ass = ass->next)
1385 trans_associate_var (ass->st->n.sym, &block);
1387 return gfc_finish_wrapped_block (&block);
1391 /* Translate the simple DO construct. This is where the loop variable has
1392 integer type and step +-1. We can't use this in the general case
1393 because integer overflow and floating point errors could give incorrect
1394 results.
1395 We translate a do loop from:
1397 DO dovar = from, to, step
1398 body
1399 END DO
1403 [Evaluate loop bounds and step]
1404 dovar = from;
1405 if ((step > 0) ? (dovar <= to) : (dovar => to))
1407 for (;;)
1409 body;
1410 cycle_label:
1411 cond = (dovar == to);
1412 dovar += step;
1413 if (cond) goto end_label;
1416 end_label:
1418 This helps the optimizers by avoiding the extra induction variable
1419 used in the general case. */
1421 static tree
1422 gfc_trans_simple_do (gfc_code * code, stmtblock_t *pblock, tree dovar,
1423 tree from, tree to, tree step, tree exit_cond)
1425 stmtblock_t body;
1426 tree type;
1427 tree cond;
1428 tree tmp;
1429 tree saved_dovar = NULL;
1430 tree cycle_label;
1431 tree exit_label;
1432 location_t loc;
1434 type = TREE_TYPE (dovar);
1436 loc = code->ext.iterator->start->where.lb->location;
1438 /* Initialize the DO variable: dovar = from. */
1439 gfc_add_modify_loc (loc, pblock, dovar,
1440 fold_convert (TREE_TYPE(dovar), from));
1442 /* Save value for do-tinkering checking. */
1443 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
1445 saved_dovar = gfc_create_var (type, ".saved_dovar");
1446 gfc_add_modify_loc (loc, pblock, saved_dovar, dovar);
1449 /* Cycle and exit statements are implemented with gotos. */
1450 cycle_label = gfc_build_label_decl (NULL_TREE);
1451 exit_label = gfc_build_label_decl (NULL_TREE);
1453 /* Put the labels where they can be found later. See gfc_trans_do(). */
1454 code->cycle_label = cycle_label;
1455 code->exit_label = exit_label;
1457 /* Loop body. */
1458 gfc_start_block (&body);
1460 /* Main loop body. */
1461 tmp = gfc_trans_code_cond (code->block->next, exit_cond);
1462 gfc_add_expr_to_block (&body, tmp);
1464 /* Label for cycle statements (if needed). */
1465 if (TREE_USED (cycle_label))
1467 tmp = build1_v (LABEL_EXPR, cycle_label);
1468 gfc_add_expr_to_block (&body, tmp);
1471 /* Check whether someone has modified the loop variable. */
1472 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
1474 tmp = fold_build2_loc (loc, NE_EXPR, boolean_type_node,
1475 dovar, saved_dovar);
1476 gfc_trans_runtime_check (true, false, tmp, &body, &code->loc,
1477 "Loop variable has been modified");
1480 /* Exit the loop if there is an I/O result condition or error. */
1481 if (exit_cond)
1483 tmp = build1_v (GOTO_EXPR, exit_label);
1484 tmp = fold_build3_loc (loc, COND_EXPR, void_type_node,
1485 exit_cond, tmp,
1486 build_empty_stmt (loc));
1487 gfc_add_expr_to_block (&body, tmp);
1490 /* Evaluate the loop condition. */
1491 cond = fold_build2_loc (loc, EQ_EXPR, boolean_type_node, dovar,
1492 to);
1493 cond = gfc_evaluate_now_loc (loc, cond, &body);
1495 /* Increment the loop variable. */
1496 tmp = fold_build2_loc (loc, PLUS_EXPR, type, dovar, step);
1497 gfc_add_modify_loc (loc, &body, dovar, tmp);
1499 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
1500 gfc_add_modify_loc (loc, &body, saved_dovar, dovar);
1502 /* The loop exit. */
1503 tmp = fold_build1_loc (loc, GOTO_EXPR, void_type_node, exit_label);
1504 TREE_USED (exit_label) = 1;
1505 tmp = fold_build3_loc (loc, COND_EXPR, void_type_node,
1506 cond, tmp, build_empty_stmt (loc));
1507 gfc_add_expr_to_block (&body, tmp);
1509 /* Finish the loop body. */
1510 tmp = gfc_finish_block (&body);
1511 tmp = fold_build1_loc (loc, LOOP_EXPR, void_type_node, tmp);
1513 /* Only execute the loop if the number of iterations is positive. */
1514 if (tree_int_cst_sgn (step) > 0)
1515 cond = fold_build2_loc (loc, LE_EXPR, boolean_type_node, dovar,
1516 to);
1517 else
1518 cond = fold_build2_loc (loc, GE_EXPR, boolean_type_node, dovar,
1519 to);
1520 tmp = fold_build3_loc (loc, COND_EXPR, void_type_node, cond, tmp,
1521 build_empty_stmt (loc));
1522 gfc_add_expr_to_block (pblock, tmp);
1524 /* Add the exit label. */
1525 tmp = build1_v (LABEL_EXPR, exit_label);
1526 gfc_add_expr_to_block (pblock, tmp);
1528 return gfc_finish_block (pblock);
1531 /* Translate the DO construct. This obviously is one of the most
1532 important ones to get right with any compiler, but especially
1533 so for Fortran.
1535 We special case some loop forms as described in gfc_trans_simple_do.
1536 For other cases we implement them with a separate loop count,
1537 as described in the standard.
1539 We translate a do loop from:
1541 DO dovar = from, to, step
1542 body
1543 END DO
1547 [evaluate loop bounds and step]
1548 empty = (step > 0 ? to < from : to > from);
1549 countm1 = (to - from) / step;
1550 dovar = from;
1551 if (empty) goto exit_label;
1552 for (;;)
1554 body;
1555 cycle_label:
1556 dovar += step
1557 countm1t = countm1;
1558 countm1--;
1559 if (countm1t == 0) goto exit_label;
1561 exit_label:
1563 countm1 is an unsigned integer. It is equal to the loop count minus one,
1564 because the loop count itself can overflow. */
1566 tree
1567 gfc_trans_do (gfc_code * code, tree exit_cond)
1569 gfc_se se;
1570 tree dovar;
1571 tree saved_dovar = NULL;
1572 tree from;
1573 tree to;
1574 tree step;
1575 tree countm1;
1576 tree type;
1577 tree utype;
1578 tree cond;
1579 tree cycle_label;
1580 tree exit_label;
1581 tree tmp;
1582 stmtblock_t block;
1583 stmtblock_t body;
1584 location_t loc;
1586 gfc_start_block (&block);
1588 loc = code->ext.iterator->start->where.lb->location;
1590 /* Evaluate all the expressions in the iterator. */
1591 gfc_init_se (&se, NULL);
1592 gfc_conv_expr_lhs (&se, code->ext.iterator->var);
1593 gfc_add_block_to_block (&block, &se.pre);
1594 dovar = se.expr;
1595 type = TREE_TYPE (dovar);
1597 gfc_init_se (&se, NULL);
1598 gfc_conv_expr_val (&se, code->ext.iterator->start);
1599 gfc_add_block_to_block (&block, &se.pre);
1600 from = gfc_evaluate_now (se.expr, &block);
1602 gfc_init_se (&se, NULL);
1603 gfc_conv_expr_val (&se, code->ext.iterator->end);
1604 gfc_add_block_to_block (&block, &se.pre);
1605 to = gfc_evaluate_now (se.expr, &block);
1607 gfc_init_se (&se, NULL);
1608 gfc_conv_expr_val (&se, code->ext.iterator->step);
1609 gfc_add_block_to_block (&block, &se.pre);
1610 step = gfc_evaluate_now (se.expr, &block);
1612 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
1614 tmp = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, step,
1615 build_zero_cst (type));
1616 gfc_trans_runtime_check (true, false, tmp, &block, &code->loc,
1617 "DO step value is zero");
1620 /* Special case simple loops. */
1621 if (TREE_CODE (type) == INTEGER_TYPE
1622 && (integer_onep (step)
1623 || tree_int_cst_equal (step, integer_minus_one_node)))
1624 return gfc_trans_simple_do (code, &block, dovar, from, to, step, exit_cond);
1627 if (TREE_CODE (type) == INTEGER_TYPE)
1628 utype = unsigned_type_for (type);
1629 else
1630 utype = unsigned_type_for (gfc_array_index_type);
1631 countm1 = gfc_create_var (utype, "countm1");
1633 /* Cycle and exit statements are implemented with gotos. */
1634 cycle_label = gfc_build_label_decl (NULL_TREE);
1635 exit_label = gfc_build_label_decl (NULL_TREE);
1636 TREE_USED (exit_label) = 1;
1638 /* Put these labels where they can be found later. */
1639 code->cycle_label = cycle_label;
1640 code->exit_label = exit_label;
1642 /* Initialize the DO variable: dovar = from. */
1643 gfc_add_modify (&block, dovar, from);
1645 /* Save value for do-tinkering checking. */
1646 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
1648 saved_dovar = gfc_create_var (type, ".saved_dovar");
1649 gfc_add_modify_loc (loc, &block, saved_dovar, dovar);
1652 /* Initialize loop count and jump to exit label if the loop is empty.
1653 This code is executed before we enter the loop body. We generate:
1654 if (step > 0)
1656 countm1 = (to - from) / step;
1657 if (to < from)
1658 goto exit_label;
1660 else
1662 countm1 = (from - to) / -step;
1663 if (to > from)
1664 goto exit_label;
1668 if (TREE_CODE (type) == INTEGER_TYPE)
1670 tree pos, neg, tou, fromu, stepu, tmp2;
1672 /* The distance from FROM to TO cannot always be represented in a signed
1673 type, thus use unsigned arithmetic, also to avoid any undefined
1674 overflow issues. */
1675 tou = fold_convert (utype, to);
1676 fromu = fold_convert (utype, from);
1677 stepu = fold_convert (utype, step);
1679 /* For a positive step, when to < from, exit, otherwise compute
1680 countm1 = ((unsigned)to - (unsigned)from) / (unsigned)step */
1681 tmp = fold_build2_loc (loc, LT_EXPR, boolean_type_node, to, from);
1682 tmp2 = fold_build2_loc (loc, TRUNC_DIV_EXPR, utype,
1683 fold_build2_loc (loc, MINUS_EXPR, utype,
1684 tou, fromu),
1685 stepu);
1686 pos = build2 (COMPOUND_EXPR, void_type_node,
1687 fold_build2 (MODIFY_EXPR, void_type_node,
1688 countm1, tmp2),
1689 build3_loc (loc, COND_EXPR, void_type_node, tmp,
1690 build1_loc (loc, GOTO_EXPR, void_type_node,
1691 exit_label), NULL_TREE));
1693 /* For a negative step, when to > from, exit, otherwise compute
1694 countm1 = ((unsigned)from - (unsigned)to) / -(unsigned)step */
1695 tmp = fold_build2_loc (loc, GT_EXPR, boolean_type_node, to, from);
1696 tmp2 = fold_build2_loc (loc, TRUNC_DIV_EXPR, utype,
1697 fold_build2_loc (loc, MINUS_EXPR, utype,
1698 fromu, tou),
1699 fold_build1_loc (loc, NEGATE_EXPR, utype, stepu));
1700 neg = build2 (COMPOUND_EXPR, void_type_node,
1701 fold_build2 (MODIFY_EXPR, void_type_node,
1702 countm1, tmp2),
1703 build3_loc (loc, COND_EXPR, void_type_node, tmp,
1704 build1_loc (loc, GOTO_EXPR, void_type_node,
1705 exit_label), NULL_TREE));
1707 tmp = fold_build2_loc (loc, LT_EXPR, boolean_type_node, step,
1708 build_int_cst (TREE_TYPE (step), 0));
1709 tmp = fold_build3_loc (loc, COND_EXPR, void_type_node, tmp, neg, pos);
1711 gfc_add_expr_to_block (&block, tmp);
1713 else
1715 tree pos_step;
1717 /* TODO: We could use the same width as the real type.
1718 This would probably cause more problems that it solves
1719 when we implement "long double" types. */
1721 tmp = fold_build2_loc (loc, MINUS_EXPR, type, to, from);
1722 tmp = fold_build2_loc (loc, RDIV_EXPR, type, tmp, step);
1723 tmp = fold_build1_loc (loc, FIX_TRUNC_EXPR, utype, tmp);
1724 gfc_add_modify (&block, countm1, tmp);
1726 /* We need a special check for empty loops:
1727 empty = (step > 0 ? to < from : to > from); */
1728 pos_step = fold_build2_loc (loc, GT_EXPR, boolean_type_node, step,
1729 build_zero_cst (type));
1730 tmp = fold_build3_loc (loc, COND_EXPR, boolean_type_node, pos_step,
1731 fold_build2_loc (loc, LT_EXPR,
1732 boolean_type_node, to, from),
1733 fold_build2_loc (loc, GT_EXPR,
1734 boolean_type_node, to, from));
1735 /* If the loop is empty, go directly to the exit label. */
1736 tmp = fold_build3_loc (loc, COND_EXPR, void_type_node, tmp,
1737 build1_v (GOTO_EXPR, exit_label),
1738 build_empty_stmt (input_location));
1739 gfc_add_expr_to_block (&block, tmp);
1742 /* Loop body. */
1743 gfc_start_block (&body);
1745 /* Main loop body. */
1746 tmp = gfc_trans_code_cond (code->block->next, exit_cond);
1747 gfc_add_expr_to_block (&body, tmp);
1749 /* Label for cycle statements (if needed). */
1750 if (TREE_USED (cycle_label))
1752 tmp = build1_v (LABEL_EXPR, cycle_label);
1753 gfc_add_expr_to_block (&body, tmp);
1756 /* Check whether someone has modified the loop variable. */
1757 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
1759 tmp = fold_build2_loc (loc, NE_EXPR, boolean_type_node, dovar,
1760 saved_dovar);
1761 gfc_trans_runtime_check (true, false, tmp, &body, &code->loc,
1762 "Loop variable has been modified");
1765 /* Exit the loop if there is an I/O result condition or error. */
1766 if (exit_cond)
1768 tmp = build1_v (GOTO_EXPR, exit_label);
1769 tmp = fold_build3_loc (loc, COND_EXPR, void_type_node,
1770 exit_cond, tmp,
1771 build_empty_stmt (input_location));
1772 gfc_add_expr_to_block (&body, tmp);
1775 /* Increment the loop variable. */
1776 tmp = fold_build2_loc (loc, PLUS_EXPR, type, dovar, step);
1777 gfc_add_modify_loc (loc, &body, dovar, tmp);
1779 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
1780 gfc_add_modify_loc (loc, &body, saved_dovar, dovar);
1782 /* Initialize countm1t. */
1783 tree countm1t = gfc_create_var (utype, "countm1t");
1784 gfc_add_modify_loc (loc, &body, countm1t, countm1);
1786 /* Decrement the loop count. */
1787 tmp = fold_build2_loc (loc, MINUS_EXPR, utype, countm1,
1788 build_int_cst (utype, 1));
1789 gfc_add_modify_loc (loc, &body, countm1, tmp);
1791 /* End with the loop condition. Loop until countm1t == 0. */
1792 cond = fold_build2_loc (loc, EQ_EXPR, boolean_type_node, countm1t,
1793 build_int_cst (utype, 0));
1794 tmp = fold_build1_loc (loc, GOTO_EXPR, void_type_node, exit_label);
1795 tmp = fold_build3_loc (loc, COND_EXPR, void_type_node,
1796 cond, tmp, build_empty_stmt (loc));
1797 gfc_add_expr_to_block (&body, tmp);
1799 /* End of loop body. */
1800 tmp = gfc_finish_block (&body);
1802 /* The for loop itself. */
1803 tmp = fold_build1_loc (loc, LOOP_EXPR, void_type_node, tmp);
1804 gfc_add_expr_to_block (&block, tmp);
1806 /* Add the exit label. */
1807 tmp = build1_v (LABEL_EXPR, exit_label);
1808 gfc_add_expr_to_block (&block, tmp);
1810 return gfc_finish_block (&block);
1814 /* Translate the DO WHILE construct.
1816 We translate
1818 DO WHILE (cond)
1819 body
1820 END DO
1824 for ( ; ; )
1826 pre_cond;
1827 if (! cond) goto exit_label;
1828 body;
1829 cycle_label:
1831 exit_label:
1833 Because the evaluation of the exit condition `cond' may have side
1834 effects, we can't do much for empty loop bodies. The backend optimizers
1835 should be smart enough to eliminate any dead loops. */
1837 tree
1838 gfc_trans_do_while (gfc_code * code)
1840 gfc_se cond;
1841 tree tmp;
1842 tree cycle_label;
1843 tree exit_label;
1844 stmtblock_t block;
1846 /* Everything we build here is part of the loop body. */
1847 gfc_start_block (&block);
1849 /* Cycle and exit statements are implemented with gotos. */
1850 cycle_label = gfc_build_label_decl (NULL_TREE);
1851 exit_label = gfc_build_label_decl (NULL_TREE);
1853 /* Put the labels where they can be found later. See gfc_trans_do(). */
1854 code->cycle_label = cycle_label;
1855 code->exit_label = exit_label;
1857 /* Create a GIMPLE version of the exit condition. */
1858 gfc_init_se (&cond, NULL);
1859 gfc_conv_expr_val (&cond, code->expr1);
1860 gfc_add_block_to_block (&block, &cond.pre);
1861 cond.expr = fold_build1_loc (code->expr1->where.lb->location,
1862 TRUTH_NOT_EXPR, TREE_TYPE (cond.expr), cond.expr);
1864 /* Build "IF (! cond) GOTO exit_label". */
1865 tmp = build1_v (GOTO_EXPR, exit_label);
1866 TREE_USED (exit_label) = 1;
1867 tmp = fold_build3_loc (code->expr1->where.lb->location, COND_EXPR,
1868 void_type_node, cond.expr, tmp,
1869 build_empty_stmt (code->expr1->where.lb->location));
1870 gfc_add_expr_to_block (&block, tmp);
1872 /* The main body of the loop. */
1873 tmp = gfc_trans_code (code->block->next);
1874 gfc_add_expr_to_block (&block, tmp);
1876 /* Label for cycle statements (if needed). */
1877 if (TREE_USED (cycle_label))
1879 tmp = build1_v (LABEL_EXPR, cycle_label);
1880 gfc_add_expr_to_block (&block, tmp);
1883 /* End of loop body. */
1884 tmp = gfc_finish_block (&block);
1886 gfc_init_block (&block);
1887 /* Build the loop. */
1888 tmp = fold_build1_loc (code->expr1->where.lb->location, LOOP_EXPR,
1889 void_type_node, tmp);
1890 gfc_add_expr_to_block (&block, tmp);
1892 /* Add the exit label. */
1893 tmp = build1_v (LABEL_EXPR, exit_label);
1894 gfc_add_expr_to_block (&block, tmp);
1896 return gfc_finish_block (&block);
1900 /* Translate the SELECT CASE construct for INTEGER case expressions,
1901 without killing all potential optimizations. The problem is that
1902 Fortran allows unbounded cases, but the back-end does not, so we
1903 need to intercept those before we enter the equivalent SWITCH_EXPR
1904 we can build.
1906 For example, we translate this,
1908 SELECT CASE (expr)
1909 CASE (:100,101,105:115)
1910 block_1
1911 CASE (190:199,200:)
1912 block_2
1913 CASE (300)
1914 block_3
1915 CASE DEFAULT
1916 block_4
1917 END SELECT
1919 to the GENERIC equivalent,
1921 switch (expr)
1923 case (minimum value for typeof(expr) ... 100:
1924 case 101:
1925 case 105 ... 114:
1926 block1:
1927 goto end_label;
1929 case 200 ... (maximum value for typeof(expr):
1930 case 190 ... 199:
1931 block2;
1932 goto end_label;
1934 case 300:
1935 block_3;
1936 goto end_label;
1938 default:
1939 block_4;
1940 goto end_label;
1943 end_label: */
1945 static tree
1946 gfc_trans_integer_select (gfc_code * code)
1948 gfc_code *c;
1949 gfc_case *cp;
1950 tree end_label;
1951 tree tmp;
1952 gfc_se se;
1953 stmtblock_t block;
1954 stmtblock_t body;
1956 gfc_start_block (&block);
1958 /* Calculate the switch expression. */
1959 gfc_init_se (&se, NULL);
1960 gfc_conv_expr_val (&se, code->expr1);
1961 gfc_add_block_to_block (&block, &se.pre);
1963 end_label = gfc_build_label_decl (NULL_TREE);
1965 gfc_init_block (&body);
1967 for (c = code->block; c; c = c->block)
1969 for (cp = c->ext.block.case_list; cp; cp = cp->next)
1971 tree low, high;
1972 tree label;
1974 /* Assume it's the default case. */
1975 low = high = NULL_TREE;
1977 if (cp->low)
1979 low = gfc_conv_mpz_to_tree (cp->low->value.integer,
1980 cp->low->ts.kind);
1982 /* If there's only a lower bound, set the high bound to the
1983 maximum value of the case expression. */
1984 if (!cp->high)
1985 high = TYPE_MAX_VALUE (TREE_TYPE (se.expr));
1988 if (cp->high)
1990 /* Three cases are possible here:
1992 1) There is no lower bound, e.g. CASE (:N).
1993 2) There is a lower bound .NE. high bound, that is
1994 a case range, e.g. CASE (N:M) where M>N (we make
1995 sure that M>N during type resolution).
1996 3) There is a lower bound, and it has the same value
1997 as the high bound, e.g. CASE (N:N). This is our
1998 internal representation of CASE(N).
2000 In the first and second case, we need to set a value for
2001 high. In the third case, we don't because the GCC middle
2002 end represents a single case value by just letting high be
2003 a NULL_TREE. We can't do that because we need to be able
2004 to represent unbounded cases. */
2006 if (!cp->low
2007 || (cp->low
2008 && mpz_cmp (cp->low->value.integer,
2009 cp->high->value.integer) != 0))
2010 high = gfc_conv_mpz_to_tree (cp->high->value.integer,
2011 cp->high->ts.kind);
2013 /* Unbounded case. */
2014 if (!cp->low)
2015 low = TYPE_MIN_VALUE (TREE_TYPE (se.expr));
2018 /* Build a label. */
2019 label = gfc_build_label_decl (NULL_TREE);
2021 /* Add this case label.
2022 Add parameter 'label', make it match GCC backend. */
2023 tmp = build_case_label (low, high, label);
2024 gfc_add_expr_to_block (&body, tmp);
2027 /* Add the statements for this case. */
2028 tmp = gfc_trans_code (c->next);
2029 gfc_add_expr_to_block (&body, tmp);
2031 /* Break to the end of the construct. */
2032 tmp = build1_v (GOTO_EXPR, end_label);
2033 gfc_add_expr_to_block (&body, tmp);
2036 tmp = gfc_finish_block (&body);
2037 tmp = fold_build3_loc (input_location, SWITCH_EXPR, NULL_TREE,
2038 se.expr, tmp, NULL_TREE);
2039 gfc_add_expr_to_block (&block, tmp);
2041 tmp = build1_v (LABEL_EXPR, end_label);
2042 gfc_add_expr_to_block (&block, tmp);
2044 return gfc_finish_block (&block);
2048 /* Translate the SELECT CASE construct for LOGICAL case expressions.
2050 There are only two cases possible here, even though the standard
2051 does allow three cases in a LOGICAL SELECT CASE construct: .TRUE.,
2052 .FALSE., and DEFAULT.
2054 We never generate more than two blocks here. Instead, we always
2055 try to eliminate the DEFAULT case. This way, we can translate this
2056 kind of SELECT construct to a simple
2058 if {} else {};
2060 expression in GENERIC. */
2062 static tree
2063 gfc_trans_logical_select (gfc_code * code)
2065 gfc_code *c;
2066 gfc_code *t, *f, *d;
2067 gfc_case *cp;
2068 gfc_se se;
2069 stmtblock_t block;
2071 /* Assume we don't have any cases at all. */
2072 t = f = d = NULL;
2074 /* Now see which ones we actually do have. We can have at most two
2075 cases in a single case list: one for .TRUE. and one for .FALSE.
2076 The default case is always separate. If the cases for .TRUE. and
2077 .FALSE. are in the same case list, the block for that case list
2078 always executed, and we don't generate code a COND_EXPR. */
2079 for (c = code->block; c; c = c->block)
2081 for (cp = c->ext.block.case_list; cp; cp = cp->next)
2083 if (cp->low)
2085 if (cp->low->value.logical == 0) /* .FALSE. */
2086 f = c;
2087 else /* if (cp->value.logical != 0), thus .TRUE. */
2088 t = c;
2090 else
2091 d = c;
2095 /* Start a new block. */
2096 gfc_start_block (&block);
2098 /* Calculate the switch expression. We always need to do this
2099 because it may have side effects. */
2100 gfc_init_se (&se, NULL);
2101 gfc_conv_expr_val (&se, code->expr1);
2102 gfc_add_block_to_block (&block, &se.pre);
2104 if (t == f && t != NULL)
2106 /* Cases for .TRUE. and .FALSE. are in the same block. Just
2107 translate the code for these cases, append it to the current
2108 block. */
2109 gfc_add_expr_to_block (&block, gfc_trans_code (t->next));
2111 else
2113 tree true_tree, false_tree, stmt;
2115 true_tree = build_empty_stmt (input_location);
2116 false_tree = build_empty_stmt (input_location);
2118 /* If we have a case for .TRUE. and for .FALSE., discard the default case.
2119 Otherwise, if .TRUE. or .FALSE. is missing and there is a default case,
2120 make the missing case the default case. */
2121 if (t != NULL && f != NULL)
2122 d = NULL;
2123 else if (d != NULL)
2125 if (t == NULL)
2126 t = d;
2127 else
2128 f = d;
2131 /* Translate the code for each of these blocks, and append it to
2132 the current block. */
2133 if (t != NULL)
2134 true_tree = gfc_trans_code (t->next);
2136 if (f != NULL)
2137 false_tree = gfc_trans_code (f->next);
2139 stmt = fold_build3_loc (input_location, COND_EXPR, void_type_node,
2140 se.expr, true_tree, false_tree);
2141 gfc_add_expr_to_block (&block, stmt);
2144 return gfc_finish_block (&block);
2148 /* The jump table types are stored in static variables to avoid
2149 constructing them from scratch every single time. */
2150 static GTY(()) tree select_struct[2];
2152 /* Translate the SELECT CASE construct for CHARACTER case expressions.
2153 Instead of generating compares and jumps, it is far simpler to
2154 generate a data structure describing the cases in order and call a
2155 library subroutine that locates the right case.
2156 This is particularly true because this is the only case where we
2157 might have to dispose of a temporary.
2158 The library subroutine returns a pointer to jump to or NULL if no
2159 branches are to be taken. */
2161 static tree
2162 gfc_trans_character_select (gfc_code *code)
2164 tree init, end_label, tmp, type, case_num, label, fndecl;
2165 stmtblock_t block, body;
2166 gfc_case *cp, *d;
2167 gfc_code *c;
2168 gfc_se se, expr1se;
2169 int n, k;
2170 vec<constructor_elt, va_gc> *inits = NULL;
2172 tree pchartype = gfc_get_pchar_type (code->expr1->ts.kind);
2174 /* The jump table types are stored in static variables to avoid
2175 constructing them from scratch every single time. */
2176 static tree ss_string1[2], ss_string1_len[2];
2177 static tree ss_string2[2], ss_string2_len[2];
2178 static tree ss_target[2];
2180 cp = code->block->ext.block.case_list;
2181 while (cp->left != NULL)
2182 cp = cp->left;
2184 /* Generate the body */
2185 gfc_start_block (&block);
2186 gfc_init_se (&expr1se, NULL);
2187 gfc_conv_expr_reference (&expr1se, code->expr1);
2189 gfc_add_block_to_block (&block, &expr1se.pre);
2191 end_label = gfc_build_label_decl (NULL_TREE);
2193 gfc_init_block (&body);
2195 /* Attempt to optimize length 1 selects. */
2196 if (integer_onep (expr1se.string_length))
2198 for (d = cp; d; d = d->right)
2200 int i;
2201 if (d->low)
2203 gcc_assert (d->low->expr_type == EXPR_CONSTANT
2204 && d->low->ts.type == BT_CHARACTER);
2205 if (d->low->value.character.length > 1)
2207 for (i = 1; i < d->low->value.character.length; i++)
2208 if (d->low->value.character.string[i] != ' ')
2209 break;
2210 if (i != d->low->value.character.length)
2212 if (optimize && d->high && i == 1)
2214 gcc_assert (d->high->expr_type == EXPR_CONSTANT
2215 && d->high->ts.type == BT_CHARACTER);
2216 if (d->high->value.character.length > 1
2217 && (d->low->value.character.string[0]
2218 == d->high->value.character.string[0])
2219 && d->high->value.character.string[1] != ' '
2220 && ((d->low->value.character.string[1] < ' ')
2221 == (d->high->value.character.string[1]
2222 < ' ')))
2223 continue;
2225 break;
2229 if (d->high)
2231 gcc_assert (d->high->expr_type == EXPR_CONSTANT
2232 && d->high->ts.type == BT_CHARACTER);
2233 if (d->high->value.character.length > 1)
2235 for (i = 1; i < d->high->value.character.length; i++)
2236 if (d->high->value.character.string[i] != ' ')
2237 break;
2238 if (i != d->high->value.character.length)
2239 break;
2243 if (d == NULL)
2245 tree ctype = gfc_get_char_type (code->expr1->ts.kind);
2247 for (c = code->block; c; c = c->block)
2249 for (cp = c->ext.block.case_list; cp; cp = cp->next)
2251 tree low, high;
2252 tree label;
2253 gfc_char_t r;
2255 /* Assume it's the default case. */
2256 low = high = NULL_TREE;
2258 if (cp->low)
2260 /* CASE ('ab') or CASE ('ab':'az') will never match
2261 any length 1 character. */
2262 if (cp->low->value.character.length > 1
2263 && cp->low->value.character.string[1] != ' ')
2264 continue;
2266 if (cp->low->value.character.length > 0)
2267 r = cp->low->value.character.string[0];
2268 else
2269 r = ' ';
2270 low = build_int_cst (ctype, r);
2272 /* If there's only a lower bound, set the high bound
2273 to the maximum value of the case expression. */
2274 if (!cp->high)
2275 high = TYPE_MAX_VALUE (ctype);
2278 if (cp->high)
2280 if (!cp->low
2281 || (cp->low->value.character.string[0]
2282 != cp->high->value.character.string[0]))
2284 if (cp->high->value.character.length > 0)
2285 r = cp->high->value.character.string[0];
2286 else
2287 r = ' ';
2288 high = build_int_cst (ctype, r);
2291 /* Unbounded case. */
2292 if (!cp->low)
2293 low = TYPE_MIN_VALUE (ctype);
2296 /* Build a label. */
2297 label = gfc_build_label_decl (NULL_TREE);
2299 /* Add this case label.
2300 Add parameter 'label', make it match GCC backend. */
2301 tmp = build_case_label (low, high, label);
2302 gfc_add_expr_to_block (&body, tmp);
2305 /* Add the statements for this case. */
2306 tmp = gfc_trans_code (c->next);
2307 gfc_add_expr_to_block (&body, tmp);
2309 /* Break to the end of the construct. */
2310 tmp = build1_v (GOTO_EXPR, end_label);
2311 gfc_add_expr_to_block (&body, tmp);
2314 tmp = gfc_string_to_single_character (expr1se.string_length,
2315 expr1se.expr,
2316 code->expr1->ts.kind);
2317 case_num = gfc_create_var (ctype, "case_num");
2318 gfc_add_modify (&block, case_num, tmp);
2320 gfc_add_block_to_block (&block, &expr1se.post);
2322 tmp = gfc_finish_block (&body);
2323 tmp = fold_build3_loc (input_location, SWITCH_EXPR, NULL_TREE,
2324 case_num, tmp, NULL_TREE);
2325 gfc_add_expr_to_block (&block, tmp);
2327 tmp = build1_v (LABEL_EXPR, end_label);
2328 gfc_add_expr_to_block (&block, tmp);
2330 return gfc_finish_block (&block);
2334 if (code->expr1->ts.kind == 1)
2335 k = 0;
2336 else if (code->expr1->ts.kind == 4)
2337 k = 1;
2338 else
2339 gcc_unreachable ();
2341 if (select_struct[k] == NULL)
2343 tree *chain = NULL;
2344 select_struct[k] = make_node (RECORD_TYPE);
2346 if (code->expr1->ts.kind == 1)
2347 TYPE_NAME (select_struct[k]) = get_identifier ("_jump_struct_char1");
2348 else if (code->expr1->ts.kind == 4)
2349 TYPE_NAME (select_struct[k]) = get_identifier ("_jump_struct_char4");
2350 else
2351 gcc_unreachable ();
2353 #undef ADD_FIELD
2354 #define ADD_FIELD(NAME, TYPE) \
2355 ss_##NAME[k] = gfc_add_field_to_struct (select_struct[k], \
2356 get_identifier (stringize(NAME)), \
2357 TYPE, \
2358 &chain)
2360 ADD_FIELD (string1, pchartype);
2361 ADD_FIELD (string1_len, gfc_charlen_type_node);
2363 ADD_FIELD (string2, pchartype);
2364 ADD_FIELD (string2_len, gfc_charlen_type_node);
2366 ADD_FIELD (target, integer_type_node);
2367 #undef ADD_FIELD
2369 gfc_finish_type (select_struct[k]);
2372 n = 0;
2373 for (d = cp; d; d = d->right)
2374 d->n = n++;
2376 for (c = code->block; c; c = c->block)
2378 for (d = c->ext.block.case_list; d; d = d->next)
2380 label = gfc_build_label_decl (NULL_TREE);
2381 tmp = build_case_label ((d->low == NULL && d->high == NULL)
2382 ? NULL
2383 : build_int_cst (integer_type_node, d->n),
2384 NULL, label);
2385 gfc_add_expr_to_block (&body, tmp);
2388 tmp = gfc_trans_code (c->next);
2389 gfc_add_expr_to_block (&body, tmp);
2391 tmp = build1_v (GOTO_EXPR, end_label);
2392 gfc_add_expr_to_block (&body, tmp);
2395 /* Generate the structure describing the branches */
2396 for (d = cp; d; d = d->right)
2398 vec<constructor_elt, va_gc> *node = NULL;
2400 gfc_init_se (&se, NULL);
2402 if (d->low == NULL)
2404 CONSTRUCTOR_APPEND_ELT (node, ss_string1[k], null_pointer_node);
2405 CONSTRUCTOR_APPEND_ELT (node, ss_string1_len[k], integer_zero_node);
2407 else
2409 gfc_conv_expr_reference (&se, d->low);
2411 CONSTRUCTOR_APPEND_ELT (node, ss_string1[k], se.expr);
2412 CONSTRUCTOR_APPEND_ELT (node, ss_string1_len[k], se.string_length);
2415 if (d->high == NULL)
2417 CONSTRUCTOR_APPEND_ELT (node, ss_string2[k], null_pointer_node);
2418 CONSTRUCTOR_APPEND_ELT (node, ss_string2_len[k], integer_zero_node);
2420 else
2422 gfc_init_se (&se, NULL);
2423 gfc_conv_expr_reference (&se, d->high);
2425 CONSTRUCTOR_APPEND_ELT (node, ss_string2[k], se.expr);
2426 CONSTRUCTOR_APPEND_ELT (node, ss_string2_len[k], se.string_length);
2429 CONSTRUCTOR_APPEND_ELT (node, ss_target[k],
2430 build_int_cst (integer_type_node, d->n));
2432 tmp = build_constructor (select_struct[k], node);
2433 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, tmp);
2436 type = build_array_type (select_struct[k],
2437 build_index_type (size_int (n-1)));
2439 init = build_constructor (type, inits);
2440 TREE_CONSTANT (init) = 1;
2441 TREE_STATIC (init) = 1;
2442 /* Create a static variable to hold the jump table. */
2443 tmp = gfc_create_var (type, "jumptable");
2444 TREE_CONSTANT (tmp) = 1;
2445 TREE_STATIC (tmp) = 1;
2446 TREE_READONLY (tmp) = 1;
2447 DECL_INITIAL (tmp) = init;
2448 init = tmp;
2450 /* Build the library call */
2451 init = gfc_build_addr_expr (pvoid_type_node, init);
2453 if (code->expr1->ts.kind == 1)
2454 fndecl = gfor_fndecl_select_string;
2455 else if (code->expr1->ts.kind == 4)
2456 fndecl = gfor_fndecl_select_string_char4;
2457 else
2458 gcc_unreachable ();
2460 tmp = build_call_expr_loc (input_location,
2461 fndecl, 4, init,
2462 build_int_cst (gfc_charlen_type_node, n),
2463 expr1se.expr, expr1se.string_length);
2464 case_num = gfc_create_var (integer_type_node, "case_num");
2465 gfc_add_modify (&block, case_num, tmp);
2467 gfc_add_block_to_block (&block, &expr1se.post);
2469 tmp = gfc_finish_block (&body);
2470 tmp = fold_build3_loc (input_location, SWITCH_EXPR, NULL_TREE,
2471 case_num, tmp, NULL_TREE);
2472 gfc_add_expr_to_block (&block, tmp);
2474 tmp = build1_v (LABEL_EXPR, end_label);
2475 gfc_add_expr_to_block (&block, tmp);
2477 return gfc_finish_block (&block);
2481 /* Translate the three variants of the SELECT CASE construct.
2483 SELECT CASEs with INTEGER case expressions can be translated to an
2484 equivalent GENERIC switch statement, and for LOGICAL case
2485 expressions we build one or two if-else compares.
2487 SELECT CASEs with CHARACTER case expressions are a whole different
2488 story, because they don't exist in GENERIC. So we sort them and
2489 do a binary search at runtime.
2491 Fortran has no BREAK statement, and it does not allow jumps from
2492 one case block to another. That makes things a lot easier for
2493 the optimizers. */
2495 tree
2496 gfc_trans_select (gfc_code * code)
2498 stmtblock_t block;
2499 tree body;
2500 tree exit_label;
2502 gcc_assert (code && code->expr1);
2503 gfc_init_block (&block);
2505 /* Build the exit label and hang it in. */
2506 exit_label = gfc_build_label_decl (NULL_TREE);
2507 code->exit_label = exit_label;
2509 /* Empty SELECT constructs are legal. */
2510 if (code->block == NULL)
2511 body = build_empty_stmt (input_location);
2513 /* Select the correct translation function. */
2514 else
2515 switch (code->expr1->ts.type)
2517 case BT_LOGICAL:
2518 body = gfc_trans_logical_select (code);
2519 break;
2521 case BT_INTEGER:
2522 body = gfc_trans_integer_select (code);
2523 break;
2525 case BT_CHARACTER:
2526 body = gfc_trans_character_select (code);
2527 break;
2529 default:
2530 gfc_internal_error ("gfc_trans_select(): Bad type for case expr.");
2531 /* Not reached */
2534 /* Build everything together. */
2535 gfc_add_expr_to_block (&block, body);
2536 gfc_add_expr_to_block (&block, build1_v (LABEL_EXPR, exit_label));
2538 return gfc_finish_block (&block);
2542 /* Traversal function to substitute a replacement symtree if the symbol
2543 in the expression is the same as that passed. f == 2 signals that
2544 that variable itself is not to be checked - only the references.
2545 This group of functions is used when the variable expression in a
2546 FORALL assignment has internal references. For example:
2547 FORALL (i = 1:4) p(p(i)) = i
2548 The only recourse here is to store a copy of 'p' for the index
2549 expression. */
2551 static gfc_symtree *new_symtree;
2552 static gfc_symtree *old_symtree;
2554 static bool
2555 forall_replace (gfc_expr *expr, gfc_symbol *sym, int *f)
2557 if (expr->expr_type != EXPR_VARIABLE)
2558 return false;
2560 if (*f == 2)
2561 *f = 1;
2562 else if (expr->symtree->n.sym == sym)
2563 expr->symtree = new_symtree;
2565 return false;
2568 static void
2569 forall_replace_symtree (gfc_expr *e, gfc_symbol *sym, int f)
2571 gfc_traverse_expr (e, sym, forall_replace, f);
2574 static bool
2575 forall_restore (gfc_expr *expr,
2576 gfc_symbol *sym ATTRIBUTE_UNUSED,
2577 int *f ATTRIBUTE_UNUSED)
2579 if (expr->expr_type != EXPR_VARIABLE)
2580 return false;
2582 if (expr->symtree == new_symtree)
2583 expr->symtree = old_symtree;
2585 return false;
2588 static void
2589 forall_restore_symtree (gfc_expr *e)
2591 gfc_traverse_expr (e, NULL, forall_restore, 0);
2594 static void
2595 forall_make_variable_temp (gfc_code *c, stmtblock_t *pre, stmtblock_t *post)
2597 gfc_se tse;
2598 gfc_se rse;
2599 gfc_expr *e;
2600 gfc_symbol *new_sym;
2601 gfc_symbol *old_sym;
2602 gfc_symtree *root;
2603 tree tmp;
2605 /* Build a copy of the lvalue. */
2606 old_symtree = c->expr1->symtree;
2607 old_sym = old_symtree->n.sym;
2608 e = gfc_lval_expr_from_sym (old_sym);
2609 if (old_sym->attr.dimension)
2611 gfc_init_se (&tse, NULL);
2612 gfc_conv_subref_array_arg (&tse, e, 0, INTENT_IN, false);
2613 gfc_add_block_to_block (pre, &tse.pre);
2614 gfc_add_block_to_block (post, &tse.post);
2615 tse.expr = build_fold_indirect_ref_loc (input_location, tse.expr);
2617 if (e->ts.type != BT_CHARACTER)
2619 /* Use the variable offset for the temporary. */
2620 tmp = gfc_conv_array_offset (old_sym->backend_decl);
2621 gfc_conv_descriptor_offset_set (pre, tse.expr, tmp);
2624 else
2626 gfc_init_se (&tse, NULL);
2627 gfc_init_se (&rse, NULL);
2628 gfc_conv_expr (&rse, e);
2629 if (e->ts.type == BT_CHARACTER)
2631 tse.string_length = rse.string_length;
2632 tmp = gfc_get_character_type_len (gfc_default_character_kind,
2633 tse.string_length);
2634 tse.expr = gfc_conv_string_tmp (&tse, build_pointer_type (tmp),
2635 rse.string_length);
2636 gfc_add_block_to_block (pre, &tse.pre);
2637 gfc_add_block_to_block (post, &tse.post);
2639 else
2641 tmp = gfc_typenode_for_spec (&e->ts);
2642 tse.expr = gfc_create_var (tmp, "temp");
2645 tmp = gfc_trans_scalar_assign (&tse, &rse, e->ts, true,
2646 e->expr_type == EXPR_VARIABLE, true);
2647 gfc_add_expr_to_block (pre, tmp);
2649 gfc_free_expr (e);
2651 /* Create a new symbol to represent the lvalue. */
2652 new_sym = gfc_new_symbol (old_sym->name, NULL);
2653 new_sym->ts = old_sym->ts;
2654 new_sym->attr.referenced = 1;
2655 new_sym->attr.temporary = 1;
2656 new_sym->attr.dimension = old_sym->attr.dimension;
2657 new_sym->attr.flavor = old_sym->attr.flavor;
2659 /* Use the temporary as the backend_decl. */
2660 new_sym->backend_decl = tse.expr;
2662 /* Create a fake symtree for it. */
2663 root = NULL;
2664 new_symtree = gfc_new_symtree (&root, old_sym->name);
2665 new_symtree->n.sym = new_sym;
2666 gcc_assert (new_symtree == root);
2668 /* Go through the expression reference replacing the old_symtree
2669 with the new. */
2670 forall_replace_symtree (c->expr1, old_sym, 2);
2672 /* Now we have made this temporary, we might as well use it for
2673 the right hand side. */
2674 forall_replace_symtree (c->expr2, old_sym, 1);
2678 /* Handles dependencies in forall assignments. */
2679 static int
2680 check_forall_dependencies (gfc_code *c, stmtblock_t *pre, stmtblock_t *post)
2682 gfc_ref *lref;
2683 gfc_ref *rref;
2684 int need_temp;
2685 gfc_symbol *lsym;
2687 lsym = c->expr1->symtree->n.sym;
2688 need_temp = gfc_check_dependency (c->expr1, c->expr2, 0);
2690 /* Now check for dependencies within the 'variable'
2691 expression itself. These are treated by making a complete
2692 copy of variable and changing all the references to it
2693 point to the copy instead. Note that the shallow copy of
2694 the variable will not suffice for derived types with
2695 pointer components. We therefore leave these to their
2696 own devices. */
2697 if (lsym->ts.type == BT_DERIVED
2698 && lsym->ts.u.derived->attr.pointer_comp)
2699 return need_temp;
2701 new_symtree = NULL;
2702 if (find_forall_index (c->expr1, lsym, 2))
2704 forall_make_variable_temp (c, pre, post);
2705 need_temp = 0;
2708 /* Substrings with dependencies are treated in the same
2709 way. */
2710 if (c->expr1->ts.type == BT_CHARACTER
2711 && c->expr1->ref
2712 && c->expr2->expr_type == EXPR_VARIABLE
2713 && lsym == c->expr2->symtree->n.sym)
2715 for (lref = c->expr1->ref; lref; lref = lref->next)
2716 if (lref->type == REF_SUBSTRING)
2717 break;
2718 for (rref = c->expr2->ref; rref; rref = rref->next)
2719 if (rref->type == REF_SUBSTRING)
2720 break;
2722 if (rref && lref
2723 && gfc_dep_compare_expr (rref->u.ss.start, lref->u.ss.start) < 0)
2725 forall_make_variable_temp (c, pre, post);
2726 need_temp = 0;
2729 return need_temp;
2733 static void
2734 cleanup_forall_symtrees (gfc_code *c)
2736 forall_restore_symtree (c->expr1);
2737 forall_restore_symtree (c->expr2);
2738 free (new_symtree->n.sym);
2739 free (new_symtree);
2743 /* Generate the loops for a FORALL block, specified by FORALL_TMP. BODY
2744 is the contents of the FORALL block/stmt to be iterated. MASK_FLAG
2745 indicates whether we should generate code to test the FORALLs mask
2746 array. OUTER is the loop header to be used for initializing mask
2747 indices.
2749 The generated loop format is:
2750 count = (end - start + step) / step
2751 loopvar = start
2752 while (1)
2754 if (count <=0 )
2755 goto end_of_loop
2756 <body>
2757 loopvar += step
2758 count --
2760 end_of_loop: */
2762 static tree
2763 gfc_trans_forall_loop (forall_info *forall_tmp, tree body,
2764 int mask_flag, stmtblock_t *outer)
2766 int n, nvar;
2767 tree tmp;
2768 tree cond;
2769 stmtblock_t block;
2770 tree exit_label;
2771 tree count;
2772 tree var, start, end, step;
2773 iter_info *iter;
2775 /* Initialize the mask index outside the FORALL nest. */
2776 if (mask_flag && forall_tmp->mask)
2777 gfc_add_modify (outer, forall_tmp->maskindex, gfc_index_zero_node);
2779 iter = forall_tmp->this_loop;
2780 nvar = forall_tmp->nvar;
2781 for (n = 0; n < nvar; n++)
2783 var = iter->var;
2784 start = iter->start;
2785 end = iter->end;
2786 step = iter->step;
2788 exit_label = gfc_build_label_decl (NULL_TREE);
2789 TREE_USED (exit_label) = 1;
2791 /* The loop counter. */
2792 count = gfc_create_var (TREE_TYPE (var), "count");
2794 /* The body of the loop. */
2795 gfc_init_block (&block);
2797 /* The exit condition. */
2798 cond = fold_build2_loc (input_location, LE_EXPR, boolean_type_node,
2799 count, build_int_cst (TREE_TYPE (count), 0));
2800 if (forall_tmp->do_concurrent)
2801 cond = build2 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
2802 build_int_cst (integer_type_node,
2803 annot_expr_ivdep_kind));
2805 tmp = build1_v (GOTO_EXPR, exit_label);
2806 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
2807 cond, tmp, build_empty_stmt (input_location));
2808 gfc_add_expr_to_block (&block, tmp);
2810 /* The main loop body. */
2811 gfc_add_expr_to_block (&block, body);
2813 /* Increment the loop variable. */
2814 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (var), var,
2815 step);
2816 gfc_add_modify (&block, var, tmp);
2818 /* Advance to the next mask element. Only do this for the
2819 innermost loop. */
2820 if (n == 0 && mask_flag && forall_tmp->mask)
2822 tree maskindex = forall_tmp->maskindex;
2823 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
2824 maskindex, gfc_index_one_node);
2825 gfc_add_modify (&block, maskindex, tmp);
2828 /* Decrement the loop counter. */
2829 tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (var), count,
2830 build_int_cst (TREE_TYPE (var), 1));
2831 gfc_add_modify (&block, count, tmp);
2833 body = gfc_finish_block (&block);
2835 /* Loop var initialization. */
2836 gfc_init_block (&block);
2837 gfc_add_modify (&block, var, start);
2840 /* Initialize the loop counter. */
2841 tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (var), step,
2842 start);
2843 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (var), end,
2844 tmp);
2845 tmp = fold_build2_loc (input_location, TRUNC_DIV_EXPR, TREE_TYPE (var),
2846 tmp, step);
2847 gfc_add_modify (&block, count, tmp);
2849 /* The loop expression. */
2850 tmp = build1_v (LOOP_EXPR, body);
2851 gfc_add_expr_to_block (&block, tmp);
2853 /* The exit label. */
2854 tmp = build1_v (LABEL_EXPR, exit_label);
2855 gfc_add_expr_to_block (&block, tmp);
2857 body = gfc_finish_block (&block);
2858 iter = iter->next;
2860 return body;
2864 /* Generate the body and loops according to MASK_FLAG. If MASK_FLAG
2865 is nonzero, the body is controlled by all masks in the forall nest.
2866 Otherwise, the innermost loop is not controlled by it's mask. This
2867 is used for initializing that mask. */
2869 static tree
2870 gfc_trans_nested_forall_loop (forall_info * nested_forall_info, tree body,
2871 int mask_flag)
2873 tree tmp;
2874 stmtblock_t header;
2875 forall_info *forall_tmp;
2876 tree mask, maskindex;
2878 gfc_start_block (&header);
2880 forall_tmp = nested_forall_info;
2881 while (forall_tmp != NULL)
2883 /* Generate body with masks' control. */
2884 if (mask_flag)
2886 mask = forall_tmp->mask;
2887 maskindex = forall_tmp->maskindex;
2889 /* If a mask was specified make the assignment conditional. */
2890 if (mask)
2892 tmp = gfc_build_array_ref (mask, maskindex, NULL);
2893 body = build3_v (COND_EXPR, tmp, body,
2894 build_empty_stmt (input_location));
2897 body = gfc_trans_forall_loop (forall_tmp, body, mask_flag, &header);
2898 forall_tmp = forall_tmp->prev_nest;
2899 mask_flag = 1;
2902 gfc_add_expr_to_block (&header, body);
2903 return gfc_finish_block (&header);
2907 /* Allocate data for holding a temporary array. Returns either a local
2908 temporary array or a pointer variable. */
2910 static tree
2911 gfc_do_allocate (tree bytesize, tree size, tree * pdata, stmtblock_t * pblock,
2912 tree elem_type)
2914 tree tmpvar;
2915 tree type;
2916 tree tmp;
2918 if (INTEGER_CST_P (size))
2919 tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
2920 size, gfc_index_one_node);
2921 else
2922 tmp = NULL_TREE;
2924 type = build_range_type (gfc_array_index_type, gfc_index_zero_node, tmp);
2925 type = build_array_type (elem_type, type);
2926 if (gfc_can_put_var_on_stack (bytesize))
2928 gcc_assert (INTEGER_CST_P (size));
2929 tmpvar = gfc_create_var (type, "temp");
2930 *pdata = NULL_TREE;
2932 else
2934 tmpvar = gfc_create_var (build_pointer_type (type), "temp");
2935 *pdata = convert (pvoid_type_node, tmpvar);
2937 tmp = gfc_call_malloc (pblock, TREE_TYPE (tmpvar), bytesize);
2938 gfc_add_modify (pblock, tmpvar, tmp);
2940 return tmpvar;
2944 /* Generate codes to copy the temporary to the actual lhs. */
2946 static tree
2947 generate_loop_for_temp_to_lhs (gfc_expr *expr, tree tmp1, tree count3,
2948 tree count1, tree wheremask, bool invert)
2950 gfc_ss *lss;
2951 gfc_se lse, rse;
2952 stmtblock_t block, body;
2953 gfc_loopinfo loop1;
2954 tree tmp;
2955 tree wheremaskexpr;
2957 /* Walk the lhs. */
2958 lss = gfc_walk_expr (expr);
2960 if (lss == gfc_ss_terminator)
2962 gfc_start_block (&block);
2964 gfc_init_se (&lse, NULL);
2966 /* Translate the expression. */
2967 gfc_conv_expr (&lse, expr);
2969 /* Form the expression for the temporary. */
2970 tmp = gfc_build_array_ref (tmp1, count1, NULL);
2972 /* Use the scalar assignment as is. */
2973 gfc_add_block_to_block (&block, &lse.pre);
2974 gfc_add_modify (&block, lse.expr, tmp);
2975 gfc_add_block_to_block (&block, &lse.post);
2977 /* Increment the count1. */
2978 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (count1),
2979 count1, gfc_index_one_node);
2980 gfc_add_modify (&block, count1, tmp);
2982 tmp = gfc_finish_block (&block);
2984 else
2986 gfc_start_block (&block);
2988 gfc_init_loopinfo (&loop1);
2989 gfc_init_se (&rse, NULL);
2990 gfc_init_se (&lse, NULL);
2992 /* Associate the lss with the loop. */
2993 gfc_add_ss_to_loop (&loop1, lss);
2995 /* Calculate the bounds of the scalarization. */
2996 gfc_conv_ss_startstride (&loop1);
2997 /* Setup the scalarizing loops. */
2998 gfc_conv_loop_setup (&loop1, &expr->where);
3000 gfc_mark_ss_chain_used (lss, 1);
3002 /* Start the scalarized loop body. */
3003 gfc_start_scalarized_body (&loop1, &body);
3005 /* Setup the gfc_se structures. */
3006 gfc_copy_loopinfo_to_se (&lse, &loop1);
3007 lse.ss = lss;
3009 /* Form the expression of the temporary. */
3010 if (lss != gfc_ss_terminator)
3011 rse.expr = gfc_build_array_ref (tmp1, count1, NULL);
3012 /* Translate expr. */
3013 gfc_conv_expr (&lse, expr);
3015 /* Use the scalar assignment. */
3016 rse.string_length = lse.string_length;
3017 tmp = gfc_trans_scalar_assign (&lse, &rse, expr->ts, false, true, true);
3019 /* Form the mask expression according to the mask tree list. */
3020 if (wheremask)
3022 wheremaskexpr = gfc_build_array_ref (wheremask, count3, NULL);
3023 if (invert)
3024 wheremaskexpr = fold_build1_loc (input_location, TRUTH_NOT_EXPR,
3025 TREE_TYPE (wheremaskexpr),
3026 wheremaskexpr);
3027 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
3028 wheremaskexpr, tmp,
3029 build_empty_stmt (input_location));
3032 gfc_add_expr_to_block (&body, tmp);
3034 /* Increment count1. */
3035 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
3036 count1, gfc_index_one_node);
3037 gfc_add_modify (&body, count1, tmp);
3039 /* Increment count3. */
3040 if (count3)
3042 tmp = fold_build2_loc (input_location, PLUS_EXPR,
3043 gfc_array_index_type, count3,
3044 gfc_index_one_node);
3045 gfc_add_modify (&body, count3, tmp);
3048 /* Generate the copying loops. */
3049 gfc_trans_scalarizing_loops (&loop1, &body);
3050 gfc_add_block_to_block (&block, &loop1.pre);
3051 gfc_add_block_to_block (&block, &loop1.post);
3052 gfc_cleanup_loop (&loop1);
3054 tmp = gfc_finish_block (&block);
3056 return tmp;
3060 /* Generate codes to copy rhs to the temporary. TMP1 is the address of
3061 temporary, LSS and RSS are formed in function compute_inner_temp_size(),
3062 and should not be freed. WHEREMASK is the conditional execution mask
3063 whose sense may be inverted by INVERT. */
3065 static tree
3066 generate_loop_for_rhs_to_temp (gfc_expr *expr2, tree tmp1, tree count3,
3067 tree count1, gfc_ss *lss, gfc_ss *rss,
3068 tree wheremask, bool invert)
3070 stmtblock_t block, body1;
3071 gfc_loopinfo loop;
3072 gfc_se lse;
3073 gfc_se rse;
3074 tree tmp;
3075 tree wheremaskexpr;
3077 gfc_start_block (&block);
3079 gfc_init_se (&rse, NULL);
3080 gfc_init_se (&lse, NULL);
3082 if (lss == gfc_ss_terminator)
3084 gfc_init_block (&body1);
3085 gfc_conv_expr (&rse, expr2);
3086 lse.expr = gfc_build_array_ref (tmp1, count1, NULL);
3088 else
3090 /* Initialize the loop. */
3091 gfc_init_loopinfo (&loop);
3093 /* We may need LSS to determine the shape of the expression. */
3094 gfc_add_ss_to_loop (&loop, lss);
3095 gfc_add_ss_to_loop (&loop, rss);
3097 gfc_conv_ss_startstride (&loop);
3098 gfc_conv_loop_setup (&loop, &expr2->where);
3100 gfc_mark_ss_chain_used (rss, 1);
3101 /* Start the loop body. */
3102 gfc_start_scalarized_body (&loop, &body1);
3104 /* Translate the expression. */
3105 gfc_copy_loopinfo_to_se (&rse, &loop);
3106 rse.ss = rss;
3107 gfc_conv_expr (&rse, expr2);
3109 /* Form the expression of the temporary. */
3110 lse.expr = gfc_build_array_ref (tmp1, count1, NULL);
3113 /* Use the scalar assignment. */
3114 lse.string_length = rse.string_length;
3115 tmp = gfc_trans_scalar_assign (&lse, &rse, expr2->ts, true,
3116 expr2->expr_type == EXPR_VARIABLE, true);
3118 /* Form the mask expression according to the mask tree list. */
3119 if (wheremask)
3121 wheremaskexpr = gfc_build_array_ref (wheremask, count3, NULL);
3122 if (invert)
3123 wheremaskexpr = fold_build1_loc (input_location, TRUTH_NOT_EXPR,
3124 TREE_TYPE (wheremaskexpr),
3125 wheremaskexpr);
3126 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
3127 wheremaskexpr, tmp,
3128 build_empty_stmt (input_location));
3131 gfc_add_expr_to_block (&body1, tmp);
3133 if (lss == gfc_ss_terminator)
3135 gfc_add_block_to_block (&block, &body1);
3137 /* Increment count1. */
3138 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (count1),
3139 count1, gfc_index_one_node);
3140 gfc_add_modify (&block, count1, tmp);
3142 else
3144 /* Increment count1. */
3145 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
3146 count1, gfc_index_one_node);
3147 gfc_add_modify (&body1, count1, tmp);
3149 /* Increment count3. */
3150 if (count3)
3152 tmp = fold_build2_loc (input_location, PLUS_EXPR,
3153 gfc_array_index_type,
3154 count3, gfc_index_one_node);
3155 gfc_add_modify (&body1, count3, tmp);
3158 /* Generate the copying loops. */
3159 gfc_trans_scalarizing_loops (&loop, &body1);
3161 gfc_add_block_to_block (&block, &loop.pre);
3162 gfc_add_block_to_block (&block, &loop.post);
3164 gfc_cleanup_loop (&loop);
3165 /* TODO: Reuse lss and rss when copying temp->lhs. Need to be careful
3166 as tree nodes in SS may not be valid in different scope. */
3169 tmp = gfc_finish_block (&block);
3170 return tmp;
3174 /* Calculate the size of temporary needed in the assignment inside forall.
3175 LSS and RSS are filled in this function. */
3177 static tree
3178 compute_inner_temp_size (gfc_expr *expr1, gfc_expr *expr2,
3179 stmtblock_t * pblock,
3180 gfc_ss **lss, gfc_ss **rss)
3182 gfc_loopinfo loop;
3183 tree size;
3184 int i;
3185 int save_flag;
3186 tree tmp;
3188 *lss = gfc_walk_expr (expr1);
3189 *rss = NULL;
3191 size = gfc_index_one_node;
3192 if (*lss != gfc_ss_terminator)
3194 gfc_init_loopinfo (&loop);
3196 /* Walk the RHS of the expression. */
3197 *rss = gfc_walk_expr (expr2);
3198 if (*rss == gfc_ss_terminator)
3199 /* The rhs is scalar. Add a ss for the expression. */
3200 *rss = gfc_get_scalar_ss (gfc_ss_terminator, expr2);
3202 /* Associate the SS with the loop. */
3203 gfc_add_ss_to_loop (&loop, *lss);
3204 /* We don't actually need to add the rhs at this point, but it might
3205 make guessing the loop bounds a bit easier. */
3206 gfc_add_ss_to_loop (&loop, *rss);
3208 /* We only want the shape of the expression, not rest of the junk
3209 generated by the scalarizer. */
3210 loop.array_parameter = 1;
3212 /* Calculate the bounds of the scalarization. */
3213 save_flag = gfc_option.rtcheck;
3214 gfc_option.rtcheck &= ~GFC_RTCHECK_BOUNDS;
3215 gfc_conv_ss_startstride (&loop);
3216 gfc_option.rtcheck = save_flag;
3217 gfc_conv_loop_setup (&loop, &expr2->where);
3219 /* Figure out how many elements we need. */
3220 for (i = 0; i < loop.dimen; i++)
3222 tmp = fold_build2_loc (input_location, MINUS_EXPR,
3223 gfc_array_index_type,
3224 gfc_index_one_node, loop.from[i]);
3225 tmp = fold_build2_loc (input_location, PLUS_EXPR,
3226 gfc_array_index_type, tmp, loop.to[i]);
3227 size = fold_build2_loc (input_location, MULT_EXPR,
3228 gfc_array_index_type, size, tmp);
3230 gfc_add_block_to_block (pblock, &loop.pre);
3231 size = gfc_evaluate_now (size, pblock);
3232 gfc_add_block_to_block (pblock, &loop.post);
3234 /* TODO: write a function that cleans up a loopinfo without freeing
3235 the SS chains. Currently a NOP. */
3238 return size;
3242 /* Calculate the overall iterator number of the nested forall construct.
3243 This routine actually calculates the number of times the body of the
3244 nested forall specified by NESTED_FORALL_INFO is executed and multiplies
3245 that by the expression INNER_SIZE. The BLOCK argument specifies the
3246 block in which to calculate the result, and the optional INNER_SIZE_BODY
3247 argument contains any statements that need to executed (inside the loop)
3248 to initialize or calculate INNER_SIZE. */
3250 static tree
3251 compute_overall_iter_number (forall_info *nested_forall_info, tree inner_size,
3252 stmtblock_t *inner_size_body, stmtblock_t *block)
3254 forall_info *forall_tmp = nested_forall_info;
3255 tree tmp, number;
3256 stmtblock_t body;
3258 /* We can eliminate the innermost unconditional loops with constant
3259 array bounds. */
3260 if (INTEGER_CST_P (inner_size))
3262 while (forall_tmp
3263 && !forall_tmp->mask
3264 && INTEGER_CST_P (forall_tmp->size))
3266 inner_size = fold_build2_loc (input_location, MULT_EXPR,
3267 gfc_array_index_type,
3268 inner_size, forall_tmp->size);
3269 forall_tmp = forall_tmp->prev_nest;
3272 /* If there are no loops left, we have our constant result. */
3273 if (!forall_tmp)
3274 return inner_size;
3277 /* Otherwise, create a temporary variable to compute the result. */
3278 number = gfc_create_var (gfc_array_index_type, "num");
3279 gfc_add_modify (block, number, gfc_index_zero_node);
3281 gfc_start_block (&body);
3282 if (inner_size_body)
3283 gfc_add_block_to_block (&body, inner_size_body);
3284 if (forall_tmp)
3285 tmp = fold_build2_loc (input_location, PLUS_EXPR,
3286 gfc_array_index_type, number, inner_size);
3287 else
3288 tmp = inner_size;
3289 gfc_add_modify (&body, number, tmp);
3290 tmp = gfc_finish_block (&body);
3292 /* Generate loops. */
3293 if (forall_tmp != NULL)
3294 tmp = gfc_trans_nested_forall_loop (forall_tmp, tmp, 1);
3296 gfc_add_expr_to_block (block, tmp);
3298 return number;
3302 /* Allocate temporary for forall construct. SIZE is the size of temporary
3303 needed. PTEMP1 is returned for space free. */
3305 static tree
3306 allocate_temp_for_forall_nest_1 (tree type, tree size, stmtblock_t * block,
3307 tree * ptemp1)
3309 tree bytesize;
3310 tree unit;
3311 tree tmp;
3313 unit = fold_convert (gfc_array_index_type, TYPE_SIZE_UNIT (type));
3314 if (!integer_onep (unit))
3315 bytesize = fold_build2_loc (input_location, MULT_EXPR,
3316 gfc_array_index_type, size, unit);
3317 else
3318 bytesize = size;
3320 *ptemp1 = NULL;
3321 tmp = gfc_do_allocate (bytesize, size, ptemp1, block, type);
3323 if (*ptemp1)
3324 tmp = build_fold_indirect_ref_loc (input_location, tmp);
3325 return tmp;
3329 /* Allocate temporary for forall construct according to the information in
3330 nested_forall_info. INNER_SIZE is the size of temporary needed in the
3331 assignment inside forall. PTEMP1 is returned for space free. */
3333 static tree
3334 allocate_temp_for_forall_nest (forall_info * nested_forall_info, tree type,
3335 tree inner_size, stmtblock_t * inner_size_body,
3336 stmtblock_t * block, tree * ptemp1)
3338 tree size;
3340 /* Calculate the total size of temporary needed in forall construct. */
3341 size = compute_overall_iter_number (nested_forall_info, inner_size,
3342 inner_size_body, block);
3344 return allocate_temp_for_forall_nest_1 (type, size, block, ptemp1);
3348 /* Handle assignments inside forall which need temporary.
3350 forall (i=start:end:stride; maskexpr)
3351 e<i> = f<i>
3352 end forall
3353 (where e,f<i> are arbitrary expressions possibly involving i
3354 and there is a dependency between e<i> and f<i>)
3355 Translates to:
3356 masktmp(:) = maskexpr(:)
3358 maskindex = 0;
3359 count1 = 0;
3360 num = 0;
3361 for (i = start; i <= end; i += stride)
3362 num += SIZE (f<i>)
3363 count1 = 0;
3364 ALLOCATE (tmp(num))
3365 for (i = start; i <= end; i += stride)
3367 if (masktmp[maskindex++])
3368 tmp[count1++] = f<i>
3370 maskindex = 0;
3371 count1 = 0;
3372 for (i = start; i <= end; i += stride)
3374 if (masktmp[maskindex++])
3375 e<i> = tmp[count1++]
3377 DEALLOCATE (tmp)
3379 static void
3380 gfc_trans_assign_need_temp (gfc_expr * expr1, gfc_expr * expr2,
3381 tree wheremask, bool invert,
3382 forall_info * nested_forall_info,
3383 stmtblock_t * block)
3385 tree type;
3386 tree inner_size;
3387 gfc_ss *lss, *rss;
3388 tree count, count1;
3389 tree tmp, tmp1;
3390 tree ptemp1;
3391 stmtblock_t inner_size_body;
3393 /* Create vars. count1 is the current iterator number of the nested
3394 forall. */
3395 count1 = gfc_create_var (gfc_array_index_type, "count1");
3397 /* Count is the wheremask index. */
3398 if (wheremask)
3400 count = gfc_create_var (gfc_array_index_type, "count");
3401 gfc_add_modify (block, count, gfc_index_zero_node);
3403 else
3404 count = NULL;
3406 /* Initialize count1. */
3407 gfc_add_modify (block, count1, gfc_index_zero_node);
3409 /* Calculate the size of temporary needed in the assignment. Return loop, lss
3410 and rss which are used in function generate_loop_for_rhs_to_temp(). */
3411 gfc_init_block (&inner_size_body);
3412 inner_size = compute_inner_temp_size (expr1, expr2, &inner_size_body,
3413 &lss, &rss);
3415 /* The type of LHS. Used in function allocate_temp_for_forall_nest */
3416 if (expr1->ts.type == BT_CHARACTER && expr1->ts.u.cl->length)
3418 if (!expr1->ts.u.cl->backend_decl)
3420 gfc_se tse;
3421 gfc_init_se (&tse, NULL);
3422 gfc_conv_expr (&tse, expr1->ts.u.cl->length);
3423 expr1->ts.u.cl->backend_decl = tse.expr;
3425 type = gfc_get_character_type_len (gfc_default_character_kind,
3426 expr1->ts.u.cl->backend_decl);
3428 else
3429 type = gfc_typenode_for_spec (&expr1->ts);
3431 /* Allocate temporary for nested forall construct according to the
3432 information in nested_forall_info and inner_size. */
3433 tmp1 = allocate_temp_for_forall_nest (nested_forall_info, type, inner_size,
3434 &inner_size_body, block, &ptemp1);
3436 /* Generate codes to copy rhs to the temporary . */
3437 tmp = generate_loop_for_rhs_to_temp (expr2, tmp1, count, count1, lss, rss,
3438 wheremask, invert);
3440 /* Generate body and loops according to the information in
3441 nested_forall_info. */
3442 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
3443 gfc_add_expr_to_block (block, tmp);
3445 /* Reset count1. */
3446 gfc_add_modify (block, count1, gfc_index_zero_node);
3448 /* Reset count. */
3449 if (wheremask)
3450 gfc_add_modify (block, count, gfc_index_zero_node);
3452 /* Generate codes to copy the temporary to lhs. */
3453 tmp = generate_loop_for_temp_to_lhs (expr1, tmp1, count, count1,
3454 wheremask, invert);
3456 /* Generate body and loops according to the information in
3457 nested_forall_info. */
3458 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
3459 gfc_add_expr_to_block (block, tmp);
3461 if (ptemp1)
3463 /* Free the temporary. */
3464 tmp = gfc_call_free (ptemp1);
3465 gfc_add_expr_to_block (block, tmp);
3470 /* Translate pointer assignment inside FORALL which need temporary. */
3472 static void
3473 gfc_trans_pointer_assign_need_temp (gfc_expr * expr1, gfc_expr * expr2,
3474 forall_info * nested_forall_info,
3475 stmtblock_t * block)
3477 tree type;
3478 tree inner_size;
3479 gfc_ss *lss, *rss;
3480 gfc_se lse;
3481 gfc_se rse;
3482 gfc_array_info *info;
3483 gfc_loopinfo loop;
3484 tree desc;
3485 tree parm;
3486 tree parmtype;
3487 stmtblock_t body;
3488 tree count;
3489 tree tmp, tmp1, ptemp1;
3491 count = gfc_create_var (gfc_array_index_type, "count");
3492 gfc_add_modify (block, count, gfc_index_zero_node);
3494 inner_size = gfc_index_one_node;
3495 lss = gfc_walk_expr (expr1);
3496 rss = gfc_walk_expr (expr2);
3497 if (lss == gfc_ss_terminator)
3499 type = gfc_typenode_for_spec (&expr1->ts);
3500 type = build_pointer_type (type);
3502 /* Allocate temporary for nested forall construct according to the
3503 information in nested_forall_info and inner_size. */
3504 tmp1 = allocate_temp_for_forall_nest (nested_forall_info, type,
3505 inner_size, NULL, block, &ptemp1);
3506 gfc_start_block (&body);
3507 gfc_init_se (&lse, NULL);
3508 lse.expr = gfc_build_array_ref (tmp1, count, NULL);
3509 gfc_init_se (&rse, NULL);
3510 rse.want_pointer = 1;
3511 gfc_conv_expr (&rse, expr2);
3512 gfc_add_block_to_block (&body, &rse.pre);
3513 gfc_add_modify (&body, lse.expr,
3514 fold_convert (TREE_TYPE (lse.expr), rse.expr));
3515 gfc_add_block_to_block (&body, &rse.post);
3517 /* Increment count. */
3518 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
3519 count, gfc_index_one_node);
3520 gfc_add_modify (&body, count, tmp);
3522 tmp = gfc_finish_block (&body);
3524 /* Generate body and loops according to the information in
3525 nested_forall_info. */
3526 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
3527 gfc_add_expr_to_block (block, tmp);
3529 /* Reset count. */
3530 gfc_add_modify (block, count, gfc_index_zero_node);
3532 gfc_start_block (&body);
3533 gfc_init_se (&lse, NULL);
3534 gfc_init_se (&rse, NULL);
3535 rse.expr = gfc_build_array_ref (tmp1, count, NULL);
3536 lse.want_pointer = 1;
3537 gfc_conv_expr (&lse, expr1);
3538 gfc_add_block_to_block (&body, &lse.pre);
3539 gfc_add_modify (&body, lse.expr, rse.expr);
3540 gfc_add_block_to_block (&body, &lse.post);
3541 /* Increment count. */
3542 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
3543 count, gfc_index_one_node);
3544 gfc_add_modify (&body, count, tmp);
3545 tmp = gfc_finish_block (&body);
3547 /* Generate body and loops according to the information in
3548 nested_forall_info. */
3549 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
3550 gfc_add_expr_to_block (block, tmp);
3552 else
3554 gfc_init_loopinfo (&loop);
3556 /* Associate the SS with the loop. */
3557 gfc_add_ss_to_loop (&loop, rss);
3559 /* Setup the scalarizing loops and bounds. */
3560 gfc_conv_ss_startstride (&loop);
3562 gfc_conv_loop_setup (&loop, &expr2->where);
3564 info = &rss->info->data.array;
3565 desc = info->descriptor;
3567 /* Make a new descriptor. */
3568 parmtype = gfc_get_element_type (TREE_TYPE (desc));
3569 parmtype = gfc_get_array_type_bounds (parmtype, loop.dimen, 0,
3570 loop.from, loop.to, 1,
3571 GFC_ARRAY_UNKNOWN, true);
3573 /* Allocate temporary for nested forall construct. */
3574 tmp1 = allocate_temp_for_forall_nest (nested_forall_info, parmtype,
3575 inner_size, NULL, block, &ptemp1);
3576 gfc_start_block (&body);
3577 gfc_init_se (&lse, NULL);
3578 lse.expr = gfc_build_array_ref (tmp1, count, NULL);
3579 lse.direct_byref = 1;
3580 gfc_conv_expr_descriptor (&lse, expr2);
3582 gfc_add_block_to_block (&body, &lse.pre);
3583 gfc_add_block_to_block (&body, &lse.post);
3585 /* Increment count. */
3586 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
3587 count, gfc_index_one_node);
3588 gfc_add_modify (&body, count, tmp);
3590 tmp = gfc_finish_block (&body);
3592 /* Generate body and loops according to the information in
3593 nested_forall_info. */
3594 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
3595 gfc_add_expr_to_block (block, tmp);
3597 /* Reset count. */
3598 gfc_add_modify (block, count, gfc_index_zero_node);
3600 parm = gfc_build_array_ref (tmp1, count, NULL);
3601 gfc_init_se (&lse, NULL);
3602 gfc_conv_expr_descriptor (&lse, expr1);
3603 gfc_add_modify (&lse.pre, lse.expr, parm);
3604 gfc_start_block (&body);
3605 gfc_add_block_to_block (&body, &lse.pre);
3606 gfc_add_block_to_block (&body, &lse.post);
3608 /* Increment count. */
3609 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
3610 count, gfc_index_one_node);
3611 gfc_add_modify (&body, count, tmp);
3613 tmp = gfc_finish_block (&body);
3615 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
3616 gfc_add_expr_to_block (block, tmp);
3618 /* Free the temporary. */
3619 if (ptemp1)
3621 tmp = gfc_call_free (ptemp1);
3622 gfc_add_expr_to_block (block, tmp);
3627 /* FORALL and WHERE statements are really nasty, especially when you nest
3628 them. All the rhs of a forall assignment must be evaluated before the
3629 actual assignments are performed. Presumably this also applies to all the
3630 assignments in an inner where statement. */
3632 /* Generate code for a FORALL statement. Any temporaries are allocated as a
3633 linear array, relying on the fact that we process in the same order in all
3634 loops.
3636 forall (i=start:end:stride; maskexpr)
3637 e<i> = f<i>
3638 g<i> = h<i>
3639 end forall
3640 (where e,f,g,h<i> are arbitrary expressions possibly involving i)
3641 Translates to:
3642 count = ((end + 1 - start) / stride)
3643 masktmp(:) = maskexpr(:)
3645 maskindex = 0;
3646 for (i = start; i <= end; i += stride)
3648 if (masktmp[maskindex++])
3649 e<i> = f<i>
3651 maskindex = 0;
3652 for (i = start; i <= end; i += stride)
3654 if (masktmp[maskindex++])
3655 g<i> = h<i>
3658 Note that this code only works when there are no dependencies.
3659 Forall loop with array assignments and data dependencies are a real pain,
3660 because the size of the temporary cannot always be determined before the
3661 loop is executed. This problem is compounded by the presence of nested
3662 FORALL constructs.
3665 static tree
3666 gfc_trans_forall_1 (gfc_code * code, forall_info * nested_forall_info)
3668 stmtblock_t pre;
3669 stmtblock_t post;
3670 stmtblock_t block;
3671 stmtblock_t body;
3672 tree *var;
3673 tree *start;
3674 tree *end;
3675 tree *step;
3676 gfc_expr **varexpr;
3677 tree tmp;
3678 tree assign;
3679 tree size;
3680 tree maskindex;
3681 tree mask;
3682 tree pmask;
3683 tree cycle_label = NULL_TREE;
3684 int n;
3685 int nvar;
3686 int need_temp;
3687 gfc_forall_iterator *fa;
3688 gfc_se se;
3689 gfc_code *c;
3690 gfc_saved_var *saved_vars;
3691 iter_info *this_forall;
3692 forall_info *info;
3693 bool need_mask;
3695 /* Do nothing if the mask is false. */
3696 if (code->expr1
3697 && code->expr1->expr_type == EXPR_CONSTANT
3698 && !code->expr1->value.logical)
3699 return build_empty_stmt (input_location);
3701 n = 0;
3702 /* Count the FORALL index number. */
3703 for (fa = code->ext.forall_iterator; fa; fa = fa->next)
3704 n++;
3705 nvar = n;
3707 /* Allocate the space for var, start, end, step, varexpr. */
3708 var = XCNEWVEC (tree, nvar);
3709 start = XCNEWVEC (tree, nvar);
3710 end = XCNEWVEC (tree, nvar);
3711 step = XCNEWVEC (tree, nvar);
3712 varexpr = XCNEWVEC (gfc_expr *, nvar);
3713 saved_vars = XCNEWVEC (gfc_saved_var, nvar);
3715 /* Allocate the space for info. */
3716 info = XCNEW (forall_info);
3718 gfc_start_block (&pre);
3719 gfc_init_block (&post);
3720 gfc_init_block (&block);
3722 n = 0;
3723 for (fa = code->ext.forall_iterator; fa; fa = fa->next)
3725 gfc_symbol *sym = fa->var->symtree->n.sym;
3727 /* Allocate space for this_forall. */
3728 this_forall = XCNEW (iter_info);
3730 /* Create a temporary variable for the FORALL index. */
3731 tmp = gfc_typenode_for_spec (&sym->ts);
3732 var[n] = gfc_create_var (tmp, sym->name);
3733 gfc_shadow_sym (sym, var[n], &saved_vars[n]);
3735 /* Record it in this_forall. */
3736 this_forall->var = var[n];
3738 /* Replace the index symbol's backend_decl with the temporary decl. */
3739 sym->backend_decl = var[n];
3741 /* Work out the start, end and stride for the loop. */
3742 gfc_init_se (&se, NULL);
3743 gfc_conv_expr_val (&se, fa->start);
3744 /* Record it in this_forall. */
3745 this_forall->start = se.expr;
3746 gfc_add_block_to_block (&block, &se.pre);
3747 start[n] = se.expr;
3749 gfc_init_se (&se, NULL);
3750 gfc_conv_expr_val (&se, fa->end);
3751 /* Record it in this_forall. */
3752 this_forall->end = se.expr;
3753 gfc_make_safe_expr (&se);
3754 gfc_add_block_to_block (&block, &se.pre);
3755 end[n] = se.expr;
3757 gfc_init_se (&se, NULL);
3758 gfc_conv_expr_val (&se, fa->stride);
3759 /* Record it in this_forall. */
3760 this_forall->step = se.expr;
3761 gfc_make_safe_expr (&se);
3762 gfc_add_block_to_block (&block, &se.pre);
3763 step[n] = se.expr;
3765 /* Set the NEXT field of this_forall to NULL. */
3766 this_forall->next = NULL;
3767 /* Link this_forall to the info construct. */
3768 if (info->this_loop)
3770 iter_info *iter_tmp = info->this_loop;
3771 while (iter_tmp->next != NULL)
3772 iter_tmp = iter_tmp->next;
3773 iter_tmp->next = this_forall;
3775 else
3776 info->this_loop = this_forall;
3778 n++;
3780 nvar = n;
3782 /* Calculate the size needed for the current forall level. */
3783 size = gfc_index_one_node;
3784 for (n = 0; n < nvar; n++)
3786 /* size = (end + step - start) / step. */
3787 tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (start[n]),
3788 step[n], start[n]);
3789 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (end[n]),
3790 end[n], tmp);
3791 tmp = fold_build2_loc (input_location, FLOOR_DIV_EXPR, TREE_TYPE (tmp),
3792 tmp, step[n]);
3793 tmp = convert (gfc_array_index_type, tmp);
3795 size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
3796 size, tmp);
3799 /* Record the nvar and size of current forall level. */
3800 info->nvar = nvar;
3801 info->size = size;
3803 if (code->expr1)
3805 /* If the mask is .true., consider the FORALL unconditional. */
3806 if (code->expr1->expr_type == EXPR_CONSTANT
3807 && code->expr1->value.logical)
3808 need_mask = false;
3809 else
3810 need_mask = true;
3812 else
3813 need_mask = false;
3815 /* First we need to allocate the mask. */
3816 if (need_mask)
3818 /* As the mask array can be very big, prefer compact boolean types. */
3819 tree mask_type = gfc_get_logical_type (gfc_logical_kinds[0].kind);
3820 mask = allocate_temp_for_forall_nest (nested_forall_info, mask_type,
3821 size, NULL, &block, &pmask);
3822 maskindex = gfc_create_var_np (gfc_array_index_type, "mi");
3824 /* Record them in the info structure. */
3825 info->maskindex = maskindex;
3826 info->mask = mask;
3828 else
3830 /* No mask was specified. */
3831 maskindex = NULL_TREE;
3832 mask = pmask = NULL_TREE;
3835 /* Link the current forall level to nested_forall_info. */
3836 info->prev_nest = nested_forall_info;
3837 nested_forall_info = info;
3839 /* Copy the mask into a temporary variable if required.
3840 For now we assume a mask temporary is needed. */
3841 if (need_mask)
3843 /* As the mask array can be very big, prefer compact boolean types. */
3844 tree mask_type = gfc_get_logical_type (gfc_logical_kinds[0].kind);
3846 gfc_add_modify (&block, maskindex, gfc_index_zero_node);
3848 /* Start of mask assignment loop body. */
3849 gfc_start_block (&body);
3851 /* Evaluate the mask expression. */
3852 gfc_init_se (&se, NULL);
3853 gfc_conv_expr_val (&se, code->expr1);
3854 gfc_add_block_to_block (&body, &se.pre);
3856 /* Store the mask. */
3857 se.expr = convert (mask_type, se.expr);
3859 tmp = gfc_build_array_ref (mask, maskindex, NULL);
3860 gfc_add_modify (&body, tmp, se.expr);
3862 /* Advance to the next mask element. */
3863 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
3864 maskindex, gfc_index_one_node);
3865 gfc_add_modify (&body, maskindex, tmp);
3867 /* Generate the loops. */
3868 tmp = gfc_finish_block (&body);
3869 tmp = gfc_trans_nested_forall_loop (info, tmp, 0);
3870 gfc_add_expr_to_block (&block, tmp);
3873 if (code->op == EXEC_DO_CONCURRENT)
3875 gfc_init_block (&body);
3876 cycle_label = gfc_build_label_decl (NULL_TREE);
3877 code->cycle_label = cycle_label;
3878 tmp = gfc_trans_code (code->block->next);
3879 gfc_add_expr_to_block (&body, tmp);
3881 if (TREE_USED (cycle_label))
3883 tmp = build1_v (LABEL_EXPR, cycle_label);
3884 gfc_add_expr_to_block (&body, tmp);
3887 tmp = gfc_finish_block (&body);
3888 nested_forall_info->do_concurrent = true;
3889 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
3890 gfc_add_expr_to_block (&block, tmp);
3891 goto done;
3894 c = code->block->next;
3896 /* TODO: loop merging in FORALL statements. */
3897 /* Now that we've got a copy of the mask, generate the assignment loops. */
3898 while (c)
3900 switch (c->op)
3902 case EXEC_ASSIGN:
3903 /* A scalar or array assignment. DO the simple check for
3904 lhs to rhs dependencies. These make a temporary for the
3905 rhs and form a second forall block to copy to variable. */
3906 need_temp = check_forall_dependencies(c, &pre, &post);
3908 /* Temporaries due to array assignment data dependencies introduce
3909 no end of problems. */
3910 if (need_temp)
3911 gfc_trans_assign_need_temp (c->expr1, c->expr2, NULL, false,
3912 nested_forall_info, &block);
3913 else
3915 /* Use the normal assignment copying routines. */
3916 assign = gfc_trans_assignment (c->expr1, c->expr2, false, true);
3918 /* Generate body and loops. */
3919 tmp = gfc_trans_nested_forall_loop (nested_forall_info,
3920 assign, 1);
3921 gfc_add_expr_to_block (&block, tmp);
3924 /* Cleanup any temporary symtrees that have been made to deal
3925 with dependencies. */
3926 if (new_symtree)
3927 cleanup_forall_symtrees (c);
3929 break;
3931 case EXEC_WHERE:
3932 /* Translate WHERE or WHERE construct nested in FORALL. */
3933 gfc_trans_where_2 (c, NULL, false, nested_forall_info, &block);
3934 break;
3936 /* Pointer assignment inside FORALL. */
3937 case EXEC_POINTER_ASSIGN:
3938 need_temp = gfc_check_dependency (c->expr1, c->expr2, 0);
3939 if (need_temp)
3940 gfc_trans_pointer_assign_need_temp (c->expr1, c->expr2,
3941 nested_forall_info, &block);
3942 else
3944 /* Use the normal assignment copying routines. */
3945 assign = gfc_trans_pointer_assignment (c->expr1, c->expr2);
3947 /* Generate body and loops. */
3948 tmp = gfc_trans_nested_forall_loop (nested_forall_info,
3949 assign, 1);
3950 gfc_add_expr_to_block (&block, tmp);
3952 break;
3954 case EXEC_FORALL:
3955 tmp = gfc_trans_forall_1 (c, nested_forall_info);
3956 gfc_add_expr_to_block (&block, tmp);
3957 break;
3959 /* Explicit subroutine calls are prevented by the frontend but interface
3960 assignments can legitimately produce them. */
3961 case EXEC_ASSIGN_CALL:
3962 assign = gfc_trans_call (c, true, NULL_TREE, NULL_TREE, false);
3963 tmp = gfc_trans_nested_forall_loop (nested_forall_info, assign, 1);
3964 gfc_add_expr_to_block (&block, tmp);
3965 break;
3967 default:
3968 gcc_unreachable ();
3971 c = c->next;
3974 done:
3975 /* Restore the original index variables. */
3976 for (fa = code->ext.forall_iterator, n = 0; fa; fa = fa->next, n++)
3977 gfc_restore_sym (fa->var->symtree->n.sym, &saved_vars[n]);
3979 /* Free the space for var, start, end, step, varexpr. */
3980 free (var);
3981 free (start);
3982 free (end);
3983 free (step);
3984 free (varexpr);
3985 free (saved_vars);
3987 for (this_forall = info->this_loop; this_forall;)
3989 iter_info *next = this_forall->next;
3990 free (this_forall);
3991 this_forall = next;
3994 /* Free the space for this forall_info. */
3995 free (info);
3997 if (pmask)
3999 /* Free the temporary for the mask. */
4000 tmp = gfc_call_free (pmask);
4001 gfc_add_expr_to_block (&block, tmp);
4003 if (maskindex)
4004 pushdecl (maskindex);
4006 gfc_add_block_to_block (&pre, &block);
4007 gfc_add_block_to_block (&pre, &post);
4009 return gfc_finish_block (&pre);
4013 /* Translate the FORALL statement or construct. */
4015 tree gfc_trans_forall (gfc_code * code)
4017 return gfc_trans_forall_1 (code, NULL);
4021 /* Translate the DO CONCURRENT construct. */
4023 tree gfc_trans_do_concurrent (gfc_code * code)
4025 return gfc_trans_forall_1 (code, NULL);
4029 /* Evaluate the WHERE mask expression, copy its value to a temporary.
4030 If the WHERE construct is nested in FORALL, compute the overall temporary
4031 needed by the WHERE mask expression multiplied by the iterator number of
4032 the nested forall.
4033 ME is the WHERE mask expression.
4034 MASK is the current execution mask upon input, whose sense may or may
4035 not be inverted as specified by the INVERT argument.
4036 CMASK is the updated execution mask on output, or NULL if not required.
4037 PMASK is the pending execution mask on output, or NULL if not required.
4038 BLOCK is the block in which to place the condition evaluation loops. */
4040 static void
4041 gfc_evaluate_where_mask (gfc_expr * me, forall_info * nested_forall_info,
4042 tree mask, bool invert, tree cmask, tree pmask,
4043 tree mask_type, stmtblock_t * block)
4045 tree tmp, tmp1;
4046 gfc_ss *lss, *rss;
4047 gfc_loopinfo loop;
4048 stmtblock_t body, body1;
4049 tree count, cond, mtmp;
4050 gfc_se lse, rse;
4052 gfc_init_loopinfo (&loop);
4054 lss = gfc_walk_expr (me);
4055 rss = gfc_walk_expr (me);
4057 /* Variable to index the temporary. */
4058 count = gfc_create_var (gfc_array_index_type, "count");
4059 /* Initialize count. */
4060 gfc_add_modify (block, count, gfc_index_zero_node);
4062 gfc_start_block (&body);
4064 gfc_init_se (&rse, NULL);
4065 gfc_init_se (&lse, NULL);
4067 if (lss == gfc_ss_terminator)
4069 gfc_init_block (&body1);
4071 else
4073 /* Initialize the loop. */
4074 gfc_init_loopinfo (&loop);
4076 /* We may need LSS to determine the shape of the expression. */
4077 gfc_add_ss_to_loop (&loop, lss);
4078 gfc_add_ss_to_loop (&loop, rss);
4080 gfc_conv_ss_startstride (&loop);
4081 gfc_conv_loop_setup (&loop, &me->where);
4083 gfc_mark_ss_chain_used (rss, 1);
4084 /* Start the loop body. */
4085 gfc_start_scalarized_body (&loop, &body1);
4087 /* Translate the expression. */
4088 gfc_copy_loopinfo_to_se (&rse, &loop);
4089 rse.ss = rss;
4090 gfc_conv_expr (&rse, me);
4093 /* Variable to evaluate mask condition. */
4094 cond = gfc_create_var (mask_type, "cond");
4095 if (mask && (cmask || pmask))
4096 mtmp = gfc_create_var (mask_type, "mask");
4097 else mtmp = NULL_TREE;
4099 gfc_add_block_to_block (&body1, &lse.pre);
4100 gfc_add_block_to_block (&body1, &rse.pre);
4102 gfc_add_modify (&body1, cond, fold_convert (mask_type, rse.expr));
4104 if (mask && (cmask || pmask))
4106 tmp = gfc_build_array_ref (mask, count, NULL);
4107 if (invert)
4108 tmp = fold_build1_loc (input_location, TRUTH_NOT_EXPR, mask_type, tmp);
4109 gfc_add_modify (&body1, mtmp, tmp);
4112 if (cmask)
4114 tmp1 = gfc_build_array_ref (cmask, count, NULL);
4115 tmp = cond;
4116 if (mask)
4117 tmp = fold_build2_loc (input_location, TRUTH_AND_EXPR, mask_type,
4118 mtmp, tmp);
4119 gfc_add_modify (&body1, tmp1, tmp);
4122 if (pmask)
4124 tmp1 = gfc_build_array_ref (pmask, count, NULL);
4125 tmp = fold_build1_loc (input_location, TRUTH_NOT_EXPR, mask_type, cond);
4126 if (mask)
4127 tmp = fold_build2_loc (input_location, TRUTH_AND_EXPR, mask_type, mtmp,
4128 tmp);
4129 gfc_add_modify (&body1, tmp1, tmp);
4132 gfc_add_block_to_block (&body1, &lse.post);
4133 gfc_add_block_to_block (&body1, &rse.post);
4135 if (lss == gfc_ss_terminator)
4137 gfc_add_block_to_block (&body, &body1);
4139 else
4141 /* Increment count. */
4142 tmp1 = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
4143 count, gfc_index_one_node);
4144 gfc_add_modify (&body1, count, tmp1);
4146 /* Generate the copying loops. */
4147 gfc_trans_scalarizing_loops (&loop, &body1);
4149 gfc_add_block_to_block (&body, &loop.pre);
4150 gfc_add_block_to_block (&body, &loop.post);
4152 gfc_cleanup_loop (&loop);
4153 /* TODO: Reuse lss and rss when copying temp->lhs. Need to be careful
4154 as tree nodes in SS may not be valid in different scope. */
4157 tmp1 = gfc_finish_block (&body);
4158 /* If the WHERE construct is inside FORALL, fill the full temporary. */
4159 if (nested_forall_info != NULL)
4160 tmp1 = gfc_trans_nested_forall_loop (nested_forall_info, tmp1, 1);
4162 gfc_add_expr_to_block (block, tmp1);
4166 /* Translate an assignment statement in a WHERE statement or construct
4167 statement. The MASK expression is used to control which elements
4168 of EXPR1 shall be assigned. The sense of MASK is specified by
4169 INVERT. */
4171 static tree
4172 gfc_trans_where_assign (gfc_expr *expr1, gfc_expr *expr2,
4173 tree mask, bool invert,
4174 tree count1, tree count2,
4175 gfc_code *cnext)
4177 gfc_se lse;
4178 gfc_se rse;
4179 gfc_ss *lss;
4180 gfc_ss *lss_section;
4181 gfc_ss *rss;
4183 gfc_loopinfo loop;
4184 tree tmp;
4185 stmtblock_t block;
4186 stmtblock_t body;
4187 tree index, maskexpr;
4189 /* A defined assignment. */
4190 if (cnext && cnext->resolved_sym)
4191 return gfc_trans_call (cnext, true, mask, count1, invert);
4193 #if 0
4194 /* TODO: handle this special case.
4195 Special case a single function returning an array. */
4196 if (expr2->expr_type == EXPR_FUNCTION && expr2->rank > 0)
4198 tmp = gfc_trans_arrayfunc_assign (expr1, expr2);
4199 if (tmp)
4200 return tmp;
4202 #endif
4204 /* Assignment of the form lhs = rhs. */
4205 gfc_start_block (&block);
4207 gfc_init_se (&lse, NULL);
4208 gfc_init_se (&rse, NULL);
4210 /* Walk the lhs. */
4211 lss = gfc_walk_expr (expr1);
4212 rss = NULL;
4214 /* In each where-assign-stmt, the mask-expr and the variable being
4215 defined shall be arrays of the same shape. */
4216 gcc_assert (lss != gfc_ss_terminator);
4218 /* The assignment needs scalarization. */
4219 lss_section = lss;
4221 /* Find a non-scalar SS from the lhs. */
4222 while (lss_section != gfc_ss_terminator
4223 && lss_section->info->type != GFC_SS_SECTION)
4224 lss_section = lss_section->next;
4226 gcc_assert (lss_section != gfc_ss_terminator);
4228 /* Initialize the scalarizer. */
4229 gfc_init_loopinfo (&loop);
4231 /* Walk the rhs. */
4232 rss = gfc_walk_expr (expr2);
4233 if (rss == gfc_ss_terminator)
4235 /* The rhs is scalar. Add a ss for the expression. */
4236 rss = gfc_get_scalar_ss (gfc_ss_terminator, expr2);
4237 rss->info->where = 1;
4240 /* Associate the SS with the loop. */
4241 gfc_add_ss_to_loop (&loop, lss);
4242 gfc_add_ss_to_loop (&loop, rss);
4244 /* Calculate the bounds of the scalarization. */
4245 gfc_conv_ss_startstride (&loop);
4247 /* Resolve any data dependencies in the statement. */
4248 gfc_conv_resolve_dependencies (&loop, lss_section, rss);
4250 /* Setup the scalarizing loops. */
4251 gfc_conv_loop_setup (&loop, &expr2->where);
4253 /* Setup the gfc_se structures. */
4254 gfc_copy_loopinfo_to_se (&lse, &loop);
4255 gfc_copy_loopinfo_to_se (&rse, &loop);
4257 rse.ss = rss;
4258 gfc_mark_ss_chain_used (rss, 1);
4259 if (loop.temp_ss == NULL)
4261 lse.ss = lss;
4262 gfc_mark_ss_chain_used (lss, 1);
4264 else
4266 lse.ss = loop.temp_ss;
4267 gfc_mark_ss_chain_used (lss, 3);
4268 gfc_mark_ss_chain_used (loop.temp_ss, 3);
4271 /* Start the scalarized loop body. */
4272 gfc_start_scalarized_body (&loop, &body);
4274 /* Translate the expression. */
4275 gfc_conv_expr (&rse, expr2);
4276 if (lss != gfc_ss_terminator && loop.temp_ss != NULL)
4277 gfc_conv_tmp_array_ref (&lse);
4278 else
4279 gfc_conv_expr (&lse, expr1);
4281 /* Form the mask expression according to the mask. */
4282 index = count1;
4283 maskexpr = gfc_build_array_ref (mask, index, NULL);
4284 if (invert)
4285 maskexpr = fold_build1_loc (input_location, TRUTH_NOT_EXPR,
4286 TREE_TYPE (maskexpr), maskexpr);
4288 /* Use the scalar assignment as is. */
4289 tmp = gfc_trans_scalar_assign (&lse, &rse, expr1->ts,
4290 loop.temp_ss != NULL, false, true);
4292 tmp = build3_v (COND_EXPR, maskexpr, tmp, build_empty_stmt (input_location));
4294 gfc_add_expr_to_block (&body, tmp);
4296 if (lss == gfc_ss_terminator)
4298 /* Increment count1. */
4299 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
4300 count1, gfc_index_one_node);
4301 gfc_add_modify (&body, count1, tmp);
4303 /* Use the scalar assignment as is. */
4304 gfc_add_block_to_block (&block, &body);
4306 else
4308 gcc_assert (lse.ss == gfc_ss_terminator
4309 && rse.ss == gfc_ss_terminator);
4311 if (loop.temp_ss != NULL)
4313 /* Increment count1 before finish the main body of a scalarized
4314 expression. */
4315 tmp = fold_build2_loc (input_location, PLUS_EXPR,
4316 gfc_array_index_type, count1, gfc_index_one_node);
4317 gfc_add_modify (&body, count1, tmp);
4318 gfc_trans_scalarized_loop_boundary (&loop, &body);
4320 /* We need to copy the temporary to the actual lhs. */
4321 gfc_init_se (&lse, NULL);
4322 gfc_init_se (&rse, NULL);
4323 gfc_copy_loopinfo_to_se (&lse, &loop);
4324 gfc_copy_loopinfo_to_se (&rse, &loop);
4326 rse.ss = loop.temp_ss;
4327 lse.ss = lss;
4329 gfc_conv_tmp_array_ref (&rse);
4330 gfc_conv_expr (&lse, expr1);
4332 gcc_assert (lse.ss == gfc_ss_terminator
4333 && rse.ss == gfc_ss_terminator);
4335 /* Form the mask expression according to the mask tree list. */
4336 index = count2;
4337 maskexpr = gfc_build_array_ref (mask, index, NULL);
4338 if (invert)
4339 maskexpr = fold_build1_loc (input_location, TRUTH_NOT_EXPR,
4340 TREE_TYPE (maskexpr), maskexpr);
4342 /* Use the scalar assignment as is. */
4343 tmp = gfc_trans_scalar_assign (&lse, &rse, expr1->ts, false, false,
4344 true);
4345 tmp = build3_v (COND_EXPR, maskexpr, tmp,
4346 build_empty_stmt (input_location));
4347 gfc_add_expr_to_block (&body, tmp);
4349 /* Increment count2. */
4350 tmp = fold_build2_loc (input_location, PLUS_EXPR,
4351 gfc_array_index_type, count2,
4352 gfc_index_one_node);
4353 gfc_add_modify (&body, count2, tmp);
4355 else
4357 /* Increment count1. */
4358 tmp = fold_build2_loc (input_location, PLUS_EXPR,
4359 gfc_array_index_type, count1,
4360 gfc_index_one_node);
4361 gfc_add_modify (&body, count1, tmp);
4364 /* Generate the copying loops. */
4365 gfc_trans_scalarizing_loops (&loop, &body);
4367 /* Wrap the whole thing up. */
4368 gfc_add_block_to_block (&block, &loop.pre);
4369 gfc_add_block_to_block (&block, &loop.post);
4370 gfc_cleanup_loop (&loop);
4373 return gfc_finish_block (&block);
4377 /* Translate the WHERE construct or statement.
4378 This function can be called iteratively to translate the nested WHERE
4379 construct or statement.
4380 MASK is the control mask. */
4382 static void
4383 gfc_trans_where_2 (gfc_code * code, tree mask, bool invert,
4384 forall_info * nested_forall_info, stmtblock_t * block)
4386 stmtblock_t inner_size_body;
4387 tree inner_size, size;
4388 gfc_ss *lss, *rss;
4389 tree mask_type;
4390 gfc_expr *expr1;
4391 gfc_expr *expr2;
4392 gfc_code *cblock;
4393 gfc_code *cnext;
4394 tree tmp;
4395 tree cond;
4396 tree count1, count2;
4397 bool need_cmask;
4398 bool need_pmask;
4399 int need_temp;
4400 tree pcmask = NULL_TREE;
4401 tree ppmask = NULL_TREE;
4402 tree cmask = NULL_TREE;
4403 tree pmask = NULL_TREE;
4404 gfc_actual_arglist *arg;
4406 /* the WHERE statement or the WHERE construct statement. */
4407 cblock = code->block;
4409 /* As the mask array can be very big, prefer compact boolean types. */
4410 mask_type = gfc_get_logical_type (gfc_logical_kinds[0].kind);
4412 /* Determine which temporary masks are needed. */
4413 if (!cblock->block)
4415 /* One clause: No ELSEWHEREs. */
4416 need_cmask = (cblock->next != 0);
4417 need_pmask = false;
4419 else if (cblock->block->block)
4421 /* Three or more clauses: Conditional ELSEWHEREs. */
4422 need_cmask = true;
4423 need_pmask = true;
4425 else if (cblock->next)
4427 /* Two clauses, the first non-empty. */
4428 need_cmask = true;
4429 need_pmask = (mask != NULL_TREE
4430 && cblock->block->next != 0);
4432 else if (!cblock->block->next)
4434 /* Two clauses, both empty. */
4435 need_cmask = false;
4436 need_pmask = false;
4438 /* Two clauses, the first empty, the second non-empty. */
4439 else if (mask)
4441 need_cmask = (cblock->block->expr1 != 0);
4442 need_pmask = true;
4444 else
4446 need_cmask = true;
4447 need_pmask = false;
4450 if (need_cmask || need_pmask)
4452 /* Calculate the size of temporary needed by the mask-expr. */
4453 gfc_init_block (&inner_size_body);
4454 inner_size = compute_inner_temp_size (cblock->expr1, cblock->expr1,
4455 &inner_size_body, &lss, &rss);
4457 gfc_free_ss_chain (lss);
4458 gfc_free_ss_chain (rss);
4460 /* Calculate the total size of temporary needed. */
4461 size = compute_overall_iter_number (nested_forall_info, inner_size,
4462 &inner_size_body, block);
4464 /* Check whether the size is negative. */
4465 cond = fold_build2_loc (input_location, LE_EXPR, boolean_type_node, size,
4466 gfc_index_zero_node);
4467 size = fold_build3_loc (input_location, COND_EXPR, gfc_array_index_type,
4468 cond, gfc_index_zero_node, size);
4469 size = gfc_evaluate_now (size, block);
4471 /* Allocate temporary for WHERE mask if needed. */
4472 if (need_cmask)
4473 cmask = allocate_temp_for_forall_nest_1 (mask_type, size, block,
4474 &pcmask);
4476 /* Allocate temporary for !mask if needed. */
4477 if (need_pmask)
4478 pmask = allocate_temp_for_forall_nest_1 (mask_type, size, block,
4479 &ppmask);
4482 while (cblock)
4484 /* Each time around this loop, the where clause is conditional
4485 on the value of mask and invert, which are updated at the
4486 bottom of the loop. */
4488 /* Has mask-expr. */
4489 if (cblock->expr1)
4491 /* Ensure that the WHERE mask will be evaluated exactly once.
4492 If there are no statements in this WHERE/ELSEWHERE clause,
4493 then we don't need to update the control mask (cmask).
4494 If this is the last clause of the WHERE construct, then
4495 we don't need to update the pending control mask (pmask). */
4496 if (mask)
4497 gfc_evaluate_where_mask (cblock->expr1, nested_forall_info,
4498 mask, invert,
4499 cblock->next ? cmask : NULL_TREE,
4500 cblock->block ? pmask : NULL_TREE,
4501 mask_type, block);
4502 else
4503 gfc_evaluate_where_mask (cblock->expr1, nested_forall_info,
4504 NULL_TREE, false,
4505 (cblock->next || cblock->block)
4506 ? cmask : NULL_TREE,
4507 NULL_TREE, mask_type, block);
4509 invert = false;
4511 /* It's a final elsewhere-stmt. No mask-expr is present. */
4512 else
4513 cmask = mask;
4515 /* The body of this where clause are controlled by cmask with
4516 sense specified by invert. */
4518 /* Get the assignment statement of a WHERE statement, or the first
4519 statement in where-body-construct of a WHERE construct. */
4520 cnext = cblock->next;
4521 while (cnext)
4523 switch (cnext->op)
4525 /* WHERE assignment statement. */
4526 case EXEC_ASSIGN_CALL:
4528 arg = cnext->ext.actual;
4529 expr1 = expr2 = NULL;
4530 for (; arg; arg = arg->next)
4532 if (!arg->expr)
4533 continue;
4534 if (expr1 == NULL)
4535 expr1 = arg->expr;
4536 else
4537 expr2 = arg->expr;
4539 goto evaluate;
4541 case EXEC_ASSIGN:
4542 expr1 = cnext->expr1;
4543 expr2 = cnext->expr2;
4544 evaluate:
4545 if (nested_forall_info != NULL)
4547 need_temp = gfc_check_dependency (expr1, expr2, 0);
4548 if (need_temp && cnext->op != EXEC_ASSIGN_CALL)
4549 gfc_trans_assign_need_temp (expr1, expr2,
4550 cmask, invert,
4551 nested_forall_info, block);
4552 else
4554 /* Variables to control maskexpr. */
4555 count1 = gfc_create_var (gfc_array_index_type, "count1");
4556 count2 = gfc_create_var (gfc_array_index_type, "count2");
4557 gfc_add_modify (block, count1, gfc_index_zero_node);
4558 gfc_add_modify (block, count2, gfc_index_zero_node);
4560 tmp = gfc_trans_where_assign (expr1, expr2,
4561 cmask, invert,
4562 count1, count2,
4563 cnext);
4565 tmp = gfc_trans_nested_forall_loop (nested_forall_info,
4566 tmp, 1);
4567 gfc_add_expr_to_block (block, tmp);
4570 else
4572 /* Variables to control maskexpr. */
4573 count1 = gfc_create_var (gfc_array_index_type, "count1");
4574 count2 = gfc_create_var (gfc_array_index_type, "count2");
4575 gfc_add_modify (block, count1, gfc_index_zero_node);
4576 gfc_add_modify (block, count2, gfc_index_zero_node);
4578 tmp = gfc_trans_where_assign (expr1, expr2,
4579 cmask, invert,
4580 count1, count2,
4581 cnext);
4582 gfc_add_expr_to_block (block, tmp);
4585 break;
4587 /* WHERE or WHERE construct is part of a where-body-construct. */
4588 case EXEC_WHERE:
4589 gfc_trans_where_2 (cnext, cmask, invert,
4590 nested_forall_info, block);
4591 break;
4593 default:
4594 gcc_unreachable ();
4597 /* The next statement within the same where-body-construct. */
4598 cnext = cnext->next;
4600 /* The next masked-elsewhere-stmt, elsewhere-stmt, or end-where-stmt. */
4601 cblock = cblock->block;
4602 if (mask == NULL_TREE)
4604 /* If we're the initial WHERE, we can simply invert the sense
4605 of the current mask to obtain the "mask" for the remaining
4606 ELSEWHEREs. */
4607 invert = true;
4608 mask = cmask;
4610 else
4612 /* Otherwise, for nested WHERE's we need to use the pending mask. */
4613 invert = false;
4614 mask = pmask;
4618 /* If we allocated a pending mask array, deallocate it now. */
4619 if (ppmask)
4621 tmp = gfc_call_free (ppmask);
4622 gfc_add_expr_to_block (block, tmp);
4625 /* If we allocated a current mask array, deallocate it now. */
4626 if (pcmask)
4628 tmp = gfc_call_free (pcmask);
4629 gfc_add_expr_to_block (block, tmp);
4633 /* Translate a simple WHERE construct or statement without dependencies.
4634 CBLOCK is the "then" clause of the WHERE statement, where CBLOCK->EXPR
4635 is the mask condition, and EBLOCK if non-NULL is the "else" clause.
4636 Currently both CBLOCK and EBLOCK are restricted to single assignments. */
4638 static tree
4639 gfc_trans_where_3 (gfc_code * cblock, gfc_code * eblock)
4641 stmtblock_t block, body;
4642 gfc_expr *cond, *tdst, *tsrc, *edst, *esrc;
4643 tree tmp, cexpr, tstmt, estmt;
4644 gfc_ss *css, *tdss, *tsss;
4645 gfc_se cse, tdse, tsse, edse, esse;
4646 gfc_loopinfo loop;
4647 gfc_ss *edss = 0;
4648 gfc_ss *esss = 0;
4650 /* Allow the scalarizer to workshare simple where loops. */
4651 if (ompws_flags & OMPWS_WORKSHARE_FLAG)
4652 ompws_flags |= OMPWS_SCALARIZER_WS;
4654 cond = cblock->expr1;
4655 tdst = cblock->next->expr1;
4656 tsrc = cblock->next->expr2;
4657 edst = eblock ? eblock->next->expr1 : NULL;
4658 esrc = eblock ? eblock->next->expr2 : NULL;
4660 gfc_start_block (&block);
4661 gfc_init_loopinfo (&loop);
4663 /* Handle the condition. */
4664 gfc_init_se (&cse, NULL);
4665 css = gfc_walk_expr (cond);
4666 gfc_add_ss_to_loop (&loop, css);
4668 /* Handle the then-clause. */
4669 gfc_init_se (&tdse, NULL);
4670 gfc_init_se (&tsse, NULL);
4671 tdss = gfc_walk_expr (tdst);
4672 tsss = gfc_walk_expr (tsrc);
4673 if (tsss == gfc_ss_terminator)
4675 tsss = gfc_get_scalar_ss (gfc_ss_terminator, tsrc);
4676 tsss->info->where = 1;
4678 gfc_add_ss_to_loop (&loop, tdss);
4679 gfc_add_ss_to_loop (&loop, tsss);
4681 if (eblock)
4683 /* Handle the else clause. */
4684 gfc_init_se (&edse, NULL);
4685 gfc_init_se (&esse, NULL);
4686 edss = gfc_walk_expr (edst);
4687 esss = gfc_walk_expr (esrc);
4688 if (esss == gfc_ss_terminator)
4690 esss = gfc_get_scalar_ss (gfc_ss_terminator, esrc);
4691 esss->info->where = 1;
4693 gfc_add_ss_to_loop (&loop, edss);
4694 gfc_add_ss_to_loop (&loop, esss);
4697 gfc_conv_ss_startstride (&loop);
4698 gfc_conv_loop_setup (&loop, &tdst->where);
4700 gfc_mark_ss_chain_used (css, 1);
4701 gfc_mark_ss_chain_used (tdss, 1);
4702 gfc_mark_ss_chain_used (tsss, 1);
4703 if (eblock)
4705 gfc_mark_ss_chain_used (edss, 1);
4706 gfc_mark_ss_chain_used (esss, 1);
4709 gfc_start_scalarized_body (&loop, &body);
4711 gfc_copy_loopinfo_to_se (&cse, &loop);
4712 gfc_copy_loopinfo_to_se (&tdse, &loop);
4713 gfc_copy_loopinfo_to_se (&tsse, &loop);
4714 cse.ss = css;
4715 tdse.ss = tdss;
4716 tsse.ss = tsss;
4717 if (eblock)
4719 gfc_copy_loopinfo_to_se (&edse, &loop);
4720 gfc_copy_loopinfo_to_se (&esse, &loop);
4721 edse.ss = edss;
4722 esse.ss = esss;
4725 gfc_conv_expr (&cse, cond);
4726 gfc_add_block_to_block (&body, &cse.pre);
4727 cexpr = cse.expr;
4729 gfc_conv_expr (&tsse, tsrc);
4730 if (tdss != gfc_ss_terminator && loop.temp_ss != NULL)
4731 gfc_conv_tmp_array_ref (&tdse);
4732 else
4733 gfc_conv_expr (&tdse, tdst);
4735 if (eblock)
4737 gfc_conv_expr (&esse, esrc);
4738 if (edss != gfc_ss_terminator && loop.temp_ss != NULL)
4739 gfc_conv_tmp_array_ref (&edse);
4740 else
4741 gfc_conv_expr (&edse, edst);
4744 tstmt = gfc_trans_scalar_assign (&tdse, &tsse, tdst->ts, false, false, true);
4745 estmt = eblock ? gfc_trans_scalar_assign (&edse, &esse, edst->ts, false,
4746 false, true)
4747 : build_empty_stmt (input_location);
4748 tmp = build3_v (COND_EXPR, cexpr, tstmt, estmt);
4749 gfc_add_expr_to_block (&body, tmp);
4750 gfc_add_block_to_block (&body, &cse.post);
4752 gfc_trans_scalarizing_loops (&loop, &body);
4753 gfc_add_block_to_block (&block, &loop.pre);
4754 gfc_add_block_to_block (&block, &loop.post);
4755 gfc_cleanup_loop (&loop);
4757 return gfc_finish_block (&block);
4760 /* As the WHERE or WHERE construct statement can be nested, we call
4761 gfc_trans_where_2 to do the translation, and pass the initial
4762 NULL values for both the control mask and the pending control mask. */
4764 tree
4765 gfc_trans_where (gfc_code * code)
4767 stmtblock_t block;
4768 gfc_code *cblock;
4769 gfc_code *eblock;
4771 cblock = code->block;
4772 if (cblock->next
4773 && cblock->next->op == EXEC_ASSIGN
4774 && !cblock->next->next)
4776 eblock = cblock->block;
4777 if (!eblock)
4779 /* A simple "WHERE (cond) x = y" statement or block is
4780 dependence free if cond is not dependent upon writing x,
4781 and the source y is unaffected by the destination x. */
4782 if (!gfc_check_dependency (cblock->next->expr1,
4783 cblock->expr1, 0)
4784 && !gfc_check_dependency (cblock->next->expr1,
4785 cblock->next->expr2, 0))
4786 return gfc_trans_where_3 (cblock, NULL);
4788 else if (!eblock->expr1
4789 && !eblock->block
4790 && eblock->next
4791 && eblock->next->op == EXEC_ASSIGN
4792 && !eblock->next->next)
4794 /* A simple "WHERE (cond) x1 = y1 ELSEWHERE x2 = y2 ENDWHERE"
4795 block is dependence free if cond is not dependent on writes
4796 to x1 and x2, y1 is not dependent on writes to x2, and y2
4797 is not dependent on writes to x1, and both y's are not
4798 dependent upon their own x's. In addition to this, the
4799 final two dependency checks below exclude all but the same
4800 array reference if the where and elswhere destinations
4801 are the same. In short, this is VERY conservative and this
4802 is needed because the two loops, required by the standard
4803 are coalesced in gfc_trans_where_3. */
4804 if (!gfc_check_dependency (cblock->next->expr1,
4805 cblock->expr1, 0)
4806 && !gfc_check_dependency (eblock->next->expr1,
4807 cblock->expr1, 0)
4808 && !gfc_check_dependency (cblock->next->expr1,
4809 eblock->next->expr2, 1)
4810 && !gfc_check_dependency (eblock->next->expr1,
4811 cblock->next->expr2, 1)
4812 && !gfc_check_dependency (cblock->next->expr1,
4813 cblock->next->expr2, 1)
4814 && !gfc_check_dependency (eblock->next->expr1,
4815 eblock->next->expr2, 1)
4816 && !gfc_check_dependency (cblock->next->expr1,
4817 eblock->next->expr1, 0)
4818 && !gfc_check_dependency (eblock->next->expr1,
4819 cblock->next->expr1, 0))
4820 return gfc_trans_where_3 (cblock, eblock);
4824 gfc_start_block (&block);
4826 gfc_trans_where_2 (code, NULL, false, NULL, &block);
4828 return gfc_finish_block (&block);
4832 /* CYCLE a DO loop. The label decl has already been created by
4833 gfc_trans_do(), it's in TREE_PURPOSE (backend_decl) of the gfc_code
4834 node at the head of the loop. We must mark the label as used. */
4836 tree
4837 gfc_trans_cycle (gfc_code * code)
4839 tree cycle_label;
4841 cycle_label = code->ext.which_construct->cycle_label;
4842 gcc_assert (cycle_label);
4844 TREE_USED (cycle_label) = 1;
4845 return build1_v (GOTO_EXPR, cycle_label);
4849 /* EXIT a DO loop. Similar to CYCLE, but now the label is in
4850 TREE_VALUE (backend_decl) of the gfc_code node at the head of the
4851 loop. */
4853 tree
4854 gfc_trans_exit (gfc_code * code)
4856 tree exit_label;
4858 exit_label = code->ext.which_construct->exit_label;
4859 gcc_assert (exit_label);
4861 TREE_USED (exit_label) = 1;
4862 return build1_v (GOTO_EXPR, exit_label);
4866 /* Translate the ALLOCATE statement. */
4868 tree
4869 gfc_trans_allocate (gfc_code * code)
4871 gfc_alloc *al;
4872 gfc_expr *e;
4873 gfc_expr *expr;
4874 gfc_se se;
4875 tree tmp;
4876 tree parm;
4877 tree stat;
4878 tree errmsg;
4879 tree errlen;
4880 tree label_errmsg;
4881 tree label_finish;
4882 tree memsz;
4883 tree expr3;
4884 tree slen3;
4885 stmtblock_t block;
4886 stmtblock_t post;
4887 gfc_expr *sz;
4888 gfc_se se_sz;
4889 tree class_expr;
4890 tree nelems;
4891 tree memsize = NULL_TREE;
4892 tree classexpr = NULL_TREE;
4894 if (!code->ext.alloc.list)
4895 return NULL_TREE;
4897 stat = tmp = memsz = NULL_TREE;
4898 label_errmsg = label_finish = errmsg = errlen = NULL_TREE;
4900 gfc_init_block (&block);
4901 gfc_init_block (&post);
4903 /* STAT= (and maybe ERRMSG=) is present. */
4904 if (code->expr1)
4906 /* STAT=. */
4907 tree gfc_int4_type_node = gfc_get_int_type (4);
4908 stat = gfc_create_var (gfc_int4_type_node, "stat");
4910 /* ERRMSG= only makes sense with STAT=. */
4911 if (code->expr2)
4913 gfc_init_se (&se, NULL);
4914 se.want_pointer = 1;
4915 gfc_conv_expr_lhs (&se, code->expr2);
4916 errmsg = se.expr;
4917 errlen = se.string_length;
4919 else
4921 errmsg = null_pointer_node;
4922 errlen = build_int_cst (gfc_charlen_type_node, 0);
4925 /* GOTO destinations. */
4926 label_errmsg = gfc_build_label_decl (NULL_TREE);
4927 label_finish = gfc_build_label_decl (NULL_TREE);
4928 TREE_USED (label_finish) = 0;
4931 expr3 = NULL_TREE;
4932 slen3 = NULL_TREE;
4934 for (al = code->ext.alloc.list; al != NULL; al = al->next)
4936 expr = gfc_copy_expr (al->expr);
4938 if (expr->ts.type == BT_CLASS)
4939 gfc_add_data_component (expr);
4941 gfc_init_se (&se, NULL);
4943 se.want_pointer = 1;
4944 se.descriptor_only = 1;
4945 gfc_conv_expr (&se, expr);
4947 /* Evaluate expr3 just once if not a variable. */
4948 if (al == code->ext.alloc.list
4949 && al->expr->ts.type == BT_CLASS
4950 && code->expr3
4951 && code->expr3->ts.type == BT_CLASS
4952 && code->expr3->expr_type != EXPR_VARIABLE)
4954 gfc_init_se (&se_sz, NULL);
4955 gfc_conv_expr_reference (&se_sz, code->expr3);
4956 gfc_conv_class_to_class (&se_sz, code->expr3,
4957 code->expr3->ts, false, true, false, false);
4958 gfc_add_block_to_block (&se.pre, &se_sz.pre);
4959 gfc_add_block_to_block (&se.post, &se_sz.post);
4960 classexpr = build_fold_indirect_ref_loc (input_location,
4961 se_sz.expr);
4962 classexpr = gfc_evaluate_now (classexpr, &se.pre);
4963 memsize = gfc_vtable_size_get (classexpr);
4964 memsize = fold_convert (sizetype, memsize);
4967 memsz = memsize;
4968 class_expr = classexpr;
4970 nelems = NULL_TREE;
4971 if (!gfc_array_allocate (&se, expr, stat, errmsg, errlen, label_finish,
4972 memsz, &nelems, code->expr3, &code->ext.alloc.ts))
4974 bool unlimited_char;
4976 unlimited_char = UNLIMITED_POLY (al->expr)
4977 && ((code->expr3 && code->expr3->ts.type == BT_CHARACTER)
4978 || (code->ext.alloc.ts.type == BT_CHARACTER
4979 && code->ext.alloc.ts.u.cl
4980 && code->ext.alloc.ts.u.cl->length));
4982 /* A scalar or derived type. */
4984 /* Determine allocate size. */
4985 if (al->expr->ts.type == BT_CLASS
4986 && !unlimited_char
4987 && code->expr3
4988 && memsz == NULL_TREE)
4990 if (code->expr3->ts.type == BT_CLASS)
4992 sz = gfc_copy_expr (code->expr3);
4993 gfc_add_vptr_component (sz);
4994 gfc_add_size_component (sz);
4995 gfc_init_se (&se_sz, NULL);
4996 gfc_conv_expr (&se_sz, sz);
4997 gfc_free_expr (sz);
4998 memsz = se_sz.expr;
5000 else
5001 memsz = TYPE_SIZE_UNIT (gfc_typenode_for_spec (&code->expr3->ts));
5003 else if (((al->expr->ts.type == BT_CHARACTER && al->expr->ts.deferred)
5004 || unlimited_char) && code->expr3)
5006 if (!code->expr3->ts.u.cl->backend_decl)
5008 /* Convert and use the length expression. */
5009 gfc_init_se (&se_sz, NULL);
5010 if (code->expr3->expr_type == EXPR_VARIABLE
5011 || code->expr3->expr_type == EXPR_CONSTANT)
5013 gfc_conv_expr (&se_sz, code->expr3);
5014 gfc_add_block_to_block (&se.pre, &se_sz.pre);
5015 se_sz.string_length
5016 = gfc_evaluate_now (se_sz.string_length, &se.pre);
5017 gfc_add_block_to_block (&se.pre, &se_sz.post);
5018 memsz = se_sz.string_length;
5020 else if (code->expr3->mold
5021 && code->expr3->ts.u.cl
5022 && code->expr3->ts.u.cl->length)
5024 gfc_conv_expr (&se_sz, code->expr3->ts.u.cl->length);
5025 gfc_add_block_to_block (&se.pre, &se_sz.pre);
5026 se_sz.expr = gfc_evaluate_now (se_sz.expr, &se.pre);
5027 gfc_add_block_to_block (&se.pre, &se_sz.post);
5028 memsz = se_sz.expr;
5030 else
5032 /* This is would be inefficient and possibly could
5033 generate wrong code if the result were not stored
5034 in expr3/slen3. */
5035 if (slen3 == NULL_TREE)
5037 gfc_conv_expr (&se_sz, code->expr3);
5038 gfc_add_block_to_block (&se.pre, &se_sz.pre);
5039 expr3 = gfc_evaluate_now (se_sz.expr, &se.pre);
5040 gfc_add_block_to_block (&post, &se_sz.post);
5041 slen3 = gfc_evaluate_now (se_sz.string_length,
5042 &se.pre);
5044 memsz = slen3;
5047 else
5048 /* Otherwise use the stored string length. */
5049 memsz = code->expr3->ts.u.cl->backend_decl;
5050 tmp = al->expr->ts.u.cl->backend_decl;
5052 /* Store the string length. */
5053 if (tmp && TREE_CODE (tmp) == VAR_DECL)
5054 gfc_add_modify (&se.pre, tmp, fold_convert (TREE_TYPE (tmp),
5055 memsz));
5056 else if (al->expr->ts.type == BT_CHARACTER
5057 && al->expr->ts.deferred && se.string_length)
5058 gfc_add_modify (&se.pre, se.string_length,
5059 fold_convert (TREE_TYPE (se.string_length),
5060 memsz));
5062 /* Convert to size in bytes, using the character KIND. */
5063 if (unlimited_char)
5064 tmp = TREE_TYPE (gfc_typenode_for_spec (&code->expr3->ts));
5065 else
5066 tmp = TREE_TYPE (gfc_typenode_for_spec (&al->expr->ts));
5067 tmp = TYPE_SIZE_UNIT (tmp);
5068 memsz = fold_build2_loc (input_location, MULT_EXPR,
5069 TREE_TYPE (tmp), tmp,
5070 fold_convert (TREE_TYPE (tmp), memsz));
5072 else if ((al->expr->ts.type == BT_CHARACTER && al->expr->ts.deferred)
5073 || unlimited_char)
5075 gcc_assert (code->ext.alloc.ts.u.cl && code->ext.alloc.ts.u.cl->length);
5076 gfc_init_se (&se_sz, NULL);
5077 gfc_conv_expr (&se_sz, code->ext.alloc.ts.u.cl->length);
5078 gfc_add_block_to_block (&se.pre, &se_sz.pre);
5079 se_sz.expr = gfc_evaluate_now (se_sz.expr, &se.pre);
5080 gfc_add_block_to_block (&se.pre, &se_sz.post);
5081 /* Store the string length. */
5082 tmp = al->expr->ts.u.cl->backend_decl;
5083 gfc_add_modify (&se.pre, tmp, fold_convert (TREE_TYPE (tmp),
5084 se_sz.expr));
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 (se_sz.expr),
5090 se_sz.expr));
5092 else if (code->ext.alloc.ts.type != BT_UNKNOWN)
5093 memsz = TYPE_SIZE_UNIT (gfc_typenode_for_spec (&code->ext.alloc.ts));
5094 else if (memsz == NULL_TREE)
5095 memsz = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (se.expr)));
5097 if (expr->ts.type == BT_CHARACTER && memsz == NULL_TREE)
5099 memsz = se.string_length;
5101 /* Convert to size in bytes, using the character KIND. */
5102 tmp = TREE_TYPE (gfc_typenode_for_spec (&code->ext.alloc.ts));
5103 tmp = TYPE_SIZE_UNIT (tmp);
5104 memsz = fold_build2_loc (input_location, MULT_EXPR,
5105 TREE_TYPE (tmp), tmp,
5106 fold_convert (TREE_TYPE (tmp), memsz));
5109 /* Allocate - for non-pointers with re-alloc checking. */
5110 if (gfc_expr_attr (expr).allocatable)
5111 gfc_allocate_allocatable (&se.pre, se.expr, memsz, NULL_TREE,
5112 stat, errmsg, errlen, label_finish, expr);
5113 else
5114 gfc_allocate_using_malloc (&se.pre, se.expr, memsz, stat);
5116 if (al->expr->ts.type == BT_DERIVED
5117 && expr->ts.u.derived->attr.alloc_comp)
5119 tmp = build_fold_indirect_ref_loc (input_location, se.expr);
5120 tmp = gfc_nullify_alloc_comp (expr->ts.u.derived, tmp, 0);
5121 gfc_add_expr_to_block (&se.pre, tmp);
5125 gfc_add_block_to_block (&block, &se.pre);
5127 /* Error checking -- Note: ERRMSG only makes sense with STAT. */
5128 if (code->expr1)
5130 tmp = build1_v (GOTO_EXPR, label_errmsg);
5131 parm = fold_build2_loc (input_location, NE_EXPR,
5132 boolean_type_node, stat,
5133 build_int_cst (TREE_TYPE (stat), 0));
5134 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
5135 gfc_unlikely (parm, PRED_FORTRAN_FAIL_ALLOC),
5136 tmp, build_empty_stmt (input_location));
5137 gfc_add_expr_to_block (&block, tmp);
5140 /* We need the vptr of CLASS objects to be initialized. */
5141 e = gfc_copy_expr (al->expr);
5142 if (e->ts.type == BT_CLASS)
5144 gfc_expr *lhs, *rhs;
5145 gfc_se lse;
5146 gfc_ref *ref, *class_ref, *tail;
5148 /* Find the last class reference. */
5149 class_ref = NULL;
5150 for (ref = e->ref; ref; ref = ref->next)
5152 if (ref->type == REF_COMPONENT
5153 && ref->u.c.component->ts.type == BT_CLASS)
5154 class_ref = ref;
5156 if (ref->next == NULL)
5157 break;
5160 /* Remove and store all subsequent references after the
5161 CLASS reference. */
5162 if (class_ref)
5164 tail = class_ref->next;
5165 class_ref->next = NULL;
5167 else
5169 tail = e->ref;
5170 e->ref = NULL;
5173 lhs = gfc_expr_to_initialize (e);
5174 gfc_add_vptr_component (lhs);
5176 /* Remove the _vptr component and restore the original tail
5177 references. */
5178 if (class_ref)
5180 gfc_free_ref_list (class_ref->next);
5181 class_ref->next = tail;
5183 else
5185 gfc_free_ref_list (e->ref);
5186 e->ref = tail;
5189 if (class_expr != NULL_TREE)
5191 /* Polymorphic SOURCE: VPTR must be determined at run time. */
5192 gfc_init_se (&lse, NULL);
5193 lse.want_pointer = 1;
5194 gfc_conv_expr (&lse, lhs);
5195 tmp = gfc_class_vptr_get (class_expr);
5196 gfc_add_modify (&block, lse.expr,
5197 fold_convert (TREE_TYPE (lse.expr), tmp));
5199 else if (code->expr3 && code->expr3->ts.type == BT_CLASS)
5201 /* Polymorphic SOURCE: VPTR must be determined at run time. */
5202 rhs = gfc_copy_expr (code->expr3);
5203 gfc_add_vptr_component (rhs);
5204 tmp = gfc_trans_pointer_assignment (lhs, rhs);
5205 gfc_add_expr_to_block (&block, tmp);
5206 gfc_free_expr (rhs);
5207 rhs = gfc_expr_to_initialize (e);
5209 else
5211 /* VPTR is fixed at compile time. */
5212 gfc_symbol *vtab;
5213 gfc_typespec *ts;
5214 if (code->expr3)
5215 ts = &code->expr3->ts;
5216 else if (e->ts.type == BT_DERIVED)
5217 ts = &e->ts;
5218 else if (code->ext.alloc.ts.type == BT_DERIVED || UNLIMITED_POLY (al->expr))
5219 ts = &code->ext.alloc.ts;
5220 else if (e->ts.type == BT_CLASS)
5221 ts = &CLASS_DATA (e)->ts;
5222 else
5223 ts = &e->ts;
5225 if (ts->type == BT_DERIVED || UNLIMITED_POLY (e))
5227 vtab = gfc_find_vtab (ts);
5228 gcc_assert (vtab);
5229 gfc_init_se (&lse, NULL);
5230 lse.want_pointer = 1;
5231 gfc_conv_expr (&lse, lhs);
5232 tmp = gfc_build_addr_expr (NULL_TREE,
5233 gfc_get_symbol_decl (vtab));
5234 gfc_add_modify (&block, lse.expr,
5235 fold_convert (TREE_TYPE (lse.expr), tmp));
5238 gfc_free_expr (lhs);
5241 gfc_free_expr (e);
5243 if (code->expr3 && !code->expr3->mold)
5245 /* Initialization via SOURCE block
5246 (or static default initializer). */
5247 gfc_expr *rhs = gfc_copy_expr (code->expr3);
5248 if (class_expr != NULL_TREE)
5250 tree to;
5251 to = TREE_OPERAND (se.expr, 0);
5253 tmp = gfc_copy_class_to_class (class_expr, to, nelems);
5255 else if (al->expr->ts.type == BT_CLASS)
5257 gfc_actual_arglist *actual;
5258 gfc_expr *ppc;
5259 gfc_code *ppc_code;
5260 gfc_ref *ref, *dataref;
5262 /* Do a polymorphic deep copy. */
5263 actual = gfc_get_actual_arglist ();
5264 actual->expr = gfc_copy_expr (rhs);
5265 if (rhs->ts.type == BT_CLASS)
5266 gfc_add_data_component (actual->expr);
5267 actual->next = gfc_get_actual_arglist ();
5268 actual->next->expr = gfc_copy_expr (al->expr);
5269 actual->next->expr->ts.type = BT_CLASS;
5270 gfc_add_data_component (actual->next->expr);
5272 dataref = NULL;
5273 /* Make sure we go up through the reference chain to
5274 the _data reference, where the arrayspec is found. */
5275 for (ref = actual->next->expr->ref; ref; ref = ref->next)
5276 if (ref->type == REF_COMPONENT
5277 && strcmp (ref->u.c.component->name, "_data") == 0)
5278 dataref = ref;
5280 if (dataref && dataref->u.c.component->as)
5282 int dim;
5283 gfc_expr *temp;
5284 gfc_ref *ref = dataref->next;
5285 ref->u.ar.type = AR_SECTION;
5286 /* We have to set up the array reference to give ranges
5287 in all dimensions and ensure that the end and stride
5288 are set so that the copy can be scalarized. */
5289 dim = 0;
5290 for (; dim < dataref->u.c.component->as->rank; dim++)
5292 ref->u.ar.dimen_type[dim] = DIMEN_RANGE;
5293 if (ref->u.ar.end[dim] == NULL)
5295 ref->u.ar.end[dim] = ref->u.ar.start[dim];
5296 temp = gfc_get_int_expr (gfc_default_integer_kind,
5297 &al->expr->where, 1);
5298 ref->u.ar.start[dim] = temp;
5300 temp = gfc_subtract (gfc_copy_expr (ref->u.ar.end[dim]),
5301 gfc_copy_expr (ref->u.ar.start[dim]));
5302 temp = gfc_add (gfc_get_int_expr (gfc_default_integer_kind,
5303 &al->expr->where, 1),
5304 temp);
5307 if (rhs->ts.type == BT_CLASS)
5309 ppc = gfc_copy_expr (rhs);
5310 gfc_add_vptr_component (ppc);
5312 else
5313 ppc = gfc_lval_expr_from_sym (gfc_find_vtab (&rhs->ts));
5314 gfc_add_component_ref (ppc, "_copy");
5316 ppc_code = gfc_get_code (EXEC_CALL);
5317 ppc_code->resolved_sym = ppc->symtree->n.sym;
5318 /* Although '_copy' is set to be elemental in class.c, it is
5319 not staying that way. Find out why, sometime.... */
5320 ppc_code->resolved_sym->attr.elemental = 1;
5321 ppc_code->ext.actual = actual;
5322 ppc_code->expr1 = ppc;
5323 /* Since '_copy' is elemental, the scalarizer will take care
5324 of arrays in gfc_trans_call. */
5325 tmp = gfc_trans_call (ppc_code, true, NULL, NULL, false);
5326 gfc_free_statements (ppc_code);
5328 else if (expr3 != NULL_TREE)
5330 tmp = build_fold_indirect_ref_loc (input_location, se.expr);
5331 gfc_trans_string_copy (&block, slen3, tmp, code->expr3->ts.kind,
5332 slen3, expr3, code->expr3->ts.kind);
5333 tmp = NULL_TREE;
5335 else
5337 /* Switch off automatic reallocation since we have just done
5338 the ALLOCATE. */
5339 int realloc_lhs = flag_realloc_lhs;
5340 flag_realloc_lhs = 0;
5341 tmp = gfc_trans_assignment (gfc_expr_to_initialize (expr),
5342 rhs, false, false);
5343 flag_realloc_lhs = realloc_lhs;
5345 gfc_free_expr (rhs);
5346 gfc_add_expr_to_block (&block, tmp);
5348 else if (code->expr3 && code->expr3->mold
5349 && code->expr3->ts.type == BT_CLASS)
5351 /* Since the _vptr has already been assigned to the allocate
5352 object, we can use gfc_copy_class_to_class in its
5353 initialization mode. */
5354 tmp = TREE_OPERAND (se.expr, 0);
5355 tmp = gfc_copy_class_to_class (NULL_TREE, tmp, nelems);
5356 gfc_add_expr_to_block (&block, tmp);
5359 gfc_free_expr (expr);
5362 /* STAT. */
5363 if (code->expr1)
5365 tmp = build1_v (LABEL_EXPR, label_errmsg);
5366 gfc_add_expr_to_block (&block, tmp);
5369 /* ERRMSG - only useful if STAT is present. */
5370 if (code->expr1 && code->expr2)
5372 const char *msg = "Attempt to allocate an allocated object";
5373 tree slen, dlen, errmsg_str;
5374 stmtblock_t errmsg_block;
5376 gfc_init_block (&errmsg_block);
5378 errmsg_str = gfc_create_var (pchar_type_node, "ERRMSG");
5379 gfc_add_modify (&errmsg_block, errmsg_str,
5380 gfc_build_addr_expr (pchar_type_node,
5381 gfc_build_localized_cstring_const (msg)));
5383 slen = build_int_cst (gfc_charlen_type_node, ((int) strlen (msg)));
5384 dlen = gfc_get_expr_charlen (code->expr2);
5385 slen = fold_build2_loc (input_location, MIN_EXPR, TREE_TYPE (slen), dlen,
5386 slen);
5388 gfc_trans_string_copy (&errmsg_block, dlen, errmsg, code->expr2->ts.kind,
5389 slen, errmsg_str, gfc_default_character_kind);
5390 dlen = gfc_finish_block (&errmsg_block);
5392 tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, stat,
5393 build_int_cst (TREE_TYPE (stat), 0));
5395 tmp = build3_v (COND_EXPR, tmp, dlen, build_empty_stmt (input_location));
5397 gfc_add_expr_to_block (&block, tmp);
5400 /* STAT block. */
5401 if (code->expr1)
5403 if (TREE_USED (label_finish))
5405 tmp = build1_v (LABEL_EXPR, label_finish);
5406 gfc_add_expr_to_block (&block, tmp);
5409 gfc_init_se (&se, NULL);
5410 gfc_conv_expr_lhs (&se, code->expr1);
5411 tmp = convert (TREE_TYPE (se.expr), stat);
5412 gfc_add_modify (&block, se.expr, tmp);
5415 gfc_add_block_to_block (&block, &se.post);
5416 gfc_add_block_to_block (&block, &post);
5418 return gfc_finish_block (&block);
5422 /* Translate a DEALLOCATE statement. */
5424 tree
5425 gfc_trans_deallocate (gfc_code *code)
5427 gfc_se se;
5428 gfc_alloc *al;
5429 tree apstat, pstat, stat, errmsg, errlen, tmp;
5430 tree label_finish, label_errmsg;
5431 stmtblock_t block;
5433 pstat = apstat = stat = errmsg = errlen = tmp = NULL_TREE;
5434 label_finish = label_errmsg = NULL_TREE;
5436 gfc_start_block (&block);
5438 /* Count the number of failed deallocations. If deallocate() was
5439 called with STAT= , then set STAT to the count. If deallocate
5440 was called with ERRMSG, then set ERRMG to a string. */
5441 if (code->expr1)
5443 tree gfc_int4_type_node = gfc_get_int_type (4);
5445 stat = gfc_create_var (gfc_int4_type_node, "stat");
5446 pstat = gfc_build_addr_expr (NULL_TREE, stat);
5448 /* GOTO destinations. */
5449 label_errmsg = gfc_build_label_decl (NULL_TREE);
5450 label_finish = gfc_build_label_decl (NULL_TREE);
5451 TREE_USED (label_finish) = 0;
5454 /* Set ERRMSG - only needed if STAT is available. */
5455 if (code->expr1 && code->expr2)
5457 gfc_init_se (&se, NULL);
5458 se.want_pointer = 1;
5459 gfc_conv_expr_lhs (&se, code->expr2);
5460 errmsg = se.expr;
5461 errlen = se.string_length;
5464 for (al = code->ext.alloc.list; al != NULL; al = al->next)
5466 gfc_expr *expr = gfc_copy_expr (al->expr);
5467 gcc_assert (expr->expr_type == EXPR_VARIABLE);
5469 if (expr->ts.type == BT_CLASS)
5470 gfc_add_data_component (expr);
5472 gfc_init_se (&se, NULL);
5473 gfc_start_block (&se.pre);
5475 se.want_pointer = 1;
5476 se.descriptor_only = 1;
5477 gfc_conv_expr (&se, expr);
5479 if (expr->rank || gfc_is_coarray (expr))
5481 if (expr->ts.type == BT_DERIVED && expr->ts.u.derived->attr.alloc_comp
5482 && !gfc_is_finalizable (expr->ts.u.derived, NULL))
5484 gfc_ref *ref;
5485 gfc_ref *last = NULL;
5486 for (ref = expr->ref; ref; ref = ref->next)
5487 if (ref->type == REF_COMPONENT)
5488 last = ref;
5490 /* Do not deallocate the components of a derived type
5491 ultimate pointer component. */
5492 if (!(last && last->u.c.component->attr.pointer)
5493 && !(!last && expr->symtree->n.sym->attr.pointer))
5495 tmp = gfc_deallocate_alloc_comp (expr->ts.u.derived, se.expr,
5496 expr->rank);
5497 gfc_add_expr_to_block (&se.pre, tmp);
5500 tmp = gfc_array_deallocate (se.expr, pstat, errmsg, errlen,
5501 label_finish, expr);
5502 gfc_add_expr_to_block (&se.pre, tmp);
5503 if (al->expr->ts.type == BT_CLASS)
5504 gfc_reset_vptr (&se.pre, al->expr);
5506 else
5508 tmp = gfc_deallocate_scalar_with_status (se.expr, pstat, false,
5509 al->expr, al->expr->ts);
5510 gfc_add_expr_to_block (&se.pre, tmp);
5512 /* Set to zero after deallocation. */
5513 tmp = fold_build2_loc (input_location, MODIFY_EXPR, void_type_node,
5514 se.expr,
5515 build_int_cst (TREE_TYPE (se.expr), 0));
5516 gfc_add_expr_to_block (&se.pre, tmp);
5518 if (al->expr->ts.type == BT_CLASS)
5519 gfc_reset_vptr (&se.pre, al->expr);
5522 if (code->expr1)
5524 tree cond;
5526 cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, stat,
5527 build_int_cst (TREE_TYPE (stat), 0));
5528 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
5529 gfc_unlikely (cond, PRED_FORTRAN_FAIL_ALLOC),
5530 build1_v (GOTO_EXPR, label_errmsg),
5531 build_empty_stmt (input_location));
5532 gfc_add_expr_to_block (&se.pre, tmp);
5535 tmp = gfc_finish_block (&se.pre);
5536 gfc_add_expr_to_block (&block, tmp);
5537 gfc_free_expr (expr);
5540 if (code->expr1)
5542 tmp = build1_v (LABEL_EXPR, label_errmsg);
5543 gfc_add_expr_to_block (&block, tmp);
5546 /* Set ERRMSG - only needed if STAT is available. */
5547 if (code->expr1 && code->expr2)
5549 const char *msg = "Attempt to deallocate an unallocated object";
5550 stmtblock_t errmsg_block;
5551 tree errmsg_str, slen, dlen, cond;
5553 gfc_init_block (&errmsg_block);
5555 errmsg_str = gfc_create_var (pchar_type_node, "ERRMSG");
5556 gfc_add_modify (&errmsg_block, errmsg_str,
5557 gfc_build_addr_expr (pchar_type_node,
5558 gfc_build_localized_cstring_const (msg)));
5559 slen = build_int_cst (gfc_charlen_type_node, ((int) strlen (msg)));
5560 dlen = gfc_get_expr_charlen (code->expr2);
5562 gfc_trans_string_copy (&errmsg_block, dlen, errmsg, code->expr2->ts.kind,
5563 slen, errmsg_str, gfc_default_character_kind);
5564 tmp = gfc_finish_block (&errmsg_block);
5566 cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, stat,
5567 build_int_cst (TREE_TYPE (stat), 0));
5568 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
5569 gfc_unlikely (cond, PRED_FORTRAN_FAIL_ALLOC), tmp,
5570 build_empty_stmt (input_location));
5572 gfc_add_expr_to_block (&block, tmp);
5575 if (code->expr1 && TREE_USED (label_finish))
5577 tmp = build1_v (LABEL_EXPR, label_finish);
5578 gfc_add_expr_to_block (&block, tmp);
5581 /* Set STAT. */
5582 if (code->expr1)
5584 gfc_init_se (&se, NULL);
5585 gfc_conv_expr_lhs (&se, code->expr1);
5586 tmp = convert (TREE_TYPE (se.expr), stat);
5587 gfc_add_modify (&block, se.expr, tmp);
5590 return gfc_finish_block (&block);
5593 #include "gt-fortran-trans-stmt.h"