2015-03-13 Robert Dewar <dewar@adacore.com>
[official-gcc.git] / gcc / fortran / trans-stmt.c
blob6450a0ecec2df541821d2a7f69092ac10956765e
1 /* Statement translation -- generate GCC trees from gfc_code.
2 Copyright (C) 2002-2015 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 "hash-set.h"
27 #include "machmode.h"
28 #include "vec.h"
29 #include "double-int.h"
30 #include "input.h"
31 #include "alias.h"
32 #include "symtab.h"
33 #include "options.h"
34 #include "wide-int.h"
35 #include "inchash.h"
36 #include "tree.h"
37 #include "fold-const.h"
38 #include "stringpool.h"
39 #include "gfortran.h"
40 #include "flags.h"
41 #include "trans.h"
42 #include "trans-stmt.h"
43 #include "trans-types.h"
44 #include "trans-array.h"
45 #include "trans-const.h"
46 #include "arith.h"
47 #include "dependency.h"
48 #include "ggc.h"
50 typedef struct iter_info
52 tree var;
53 tree start;
54 tree end;
55 tree step;
56 struct iter_info *next;
58 iter_info;
60 typedef struct forall_info
62 iter_info *this_loop;
63 tree mask;
64 tree maskindex;
65 int nvar;
66 tree size;
67 struct forall_info *prev_nest;
68 bool do_concurrent;
70 forall_info;
72 static void gfc_trans_where_2 (gfc_code *, tree, bool,
73 forall_info *, stmtblock_t *);
75 /* Translate a F95 label number to a LABEL_EXPR. */
77 tree
78 gfc_trans_label_here (gfc_code * code)
80 return build1_v (LABEL_EXPR, gfc_get_label_decl (code->here));
84 /* Given a variable expression which has been ASSIGNed to, find the decl
85 containing the auxiliary variables. For variables in common blocks this
86 is a field_decl. */
88 void
89 gfc_conv_label_variable (gfc_se * se, gfc_expr * expr)
91 gcc_assert (expr->symtree->n.sym->attr.assign == 1);
92 gfc_conv_expr (se, expr);
93 /* Deals with variable in common block. Get the field declaration. */
94 if (TREE_CODE (se->expr) == COMPONENT_REF)
95 se->expr = TREE_OPERAND (se->expr, 1);
96 /* Deals with dummy argument. Get the parameter declaration. */
97 else if (TREE_CODE (se->expr) == INDIRECT_REF)
98 se->expr = TREE_OPERAND (se->expr, 0);
101 /* Translate a label assignment statement. */
103 tree
104 gfc_trans_label_assign (gfc_code * code)
106 tree label_tree;
107 gfc_se se;
108 tree len;
109 tree addr;
110 tree len_tree;
111 int label_len;
113 /* Start a new block. */
114 gfc_init_se (&se, NULL);
115 gfc_start_block (&se.pre);
116 gfc_conv_label_variable (&se, code->expr1);
118 len = GFC_DECL_STRING_LEN (se.expr);
119 addr = GFC_DECL_ASSIGN_ADDR (se.expr);
121 label_tree = gfc_get_label_decl (code->label1);
123 if (code->label1->defined == ST_LABEL_TARGET
124 || code->label1->defined == ST_LABEL_DO_TARGET)
126 label_tree = gfc_build_addr_expr (pvoid_type_node, label_tree);
127 len_tree = integer_minus_one_node;
129 else
131 gfc_expr *format = code->label1->format;
133 label_len = format->value.character.length;
134 len_tree = build_int_cst (gfc_charlen_type_node, label_len);
135 label_tree = gfc_build_wide_string_const (format->ts.kind, label_len + 1,
136 format->value.character.string);
137 label_tree = gfc_build_addr_expr (pvoid_type_node, label_tree);
140 gfc_add_modify (&se.pre, len, len_tree);
141 gfc_add_modify (&se.pre, addr, label_tree);
143 return gfc_finish_block (&se.pre);
146 /* Translate a GOTO statement. */
148 tree
149 gfc_trans_goto (gfc_code * code)
151 locus loc = code->loc;
152 tree assigned_goto;
153 tree target;
154 tree tmp;
155 gfc_se se;
157 if (code->label1 != NULL)
158 return build1_v (GOTO_EXPR, gfc_get_label_decl (code->label1));
160 /* ASSIGNED GOTO. */
161 gfc_init_se (&se, NULL);
162 gfc_start_block (&se.pre);
163 gfc_conv_label_variable (&se, code->expr1);
164 tmp = GFC_DECL_STRING_LEN (se.expr);
165 tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, tmp,
166 build_int_cst (TREE_TYPE (tmp), -1));
167 gfc_trans_runtime_check (true, false, tmp, &se.pre, &loc,
168 "Assigned label is not a target label");
170 assigned_goto = GFC_DECL_ASSIGN_ADDR (se.expr);
172 /* We're going to ignore a label list. It does not really change the
173 statement's semantics (because it is just a further restriction on
174 what's legal code); before, we were comparing label addresses here, but
175 that's a very fragile business and may break with optimization. So
176 just ignore it. */
178 target = fold_build1_loc (input_location, GOTO_EXPR, void_type_node,
179 assigned_goto);
180 gfc_add_expr_to_block (&se.pre, target);
181 return gfc_finish_block (&se.pre);
185 /* Translate an ENTRY statement. Just adds a label for this entry point. */
186 tree
187 gfc_trans_entry (gfc_code * code)
189 return build1_v (LABEL_EXPR, code->ext.entry->label);
193 /* Replace a gfc_ss structure by another both in the gfc_se struct
194 and the gfc_loopinfo struct. This is used in gfc_conv_elemental_dependencies
195 to replace a variable ss by the corresponding temporary. */
197 static void
198 replace_ss (gfc_se *se, gfc_ss *old_ss, gfc_ss *new_ss)
200 gfc_ss **sess, **loopss;
202 /* The old_ss is a ss for a single variable. */
203 gcc_assert (old_ss->info->type == GFC_SS_SECTION);
205 for (sess = &(se->ss); *sess != gfc_ss_terminator; sess = &((*sess)->next))
206 if (*sess == old_ss)
207 break;
208 gcc_assert (*sess != gfc_ss_terminator);
210 *sess = new_ss;
211 new_ss->next = old_ss->next;
214 for (loopss = &(se->loop->ss); *loopss != gfc_ss_terminator;
215 loopss = &((*loopss)->loop_chain))
216 if (*loopss == old_ss)
217 break;
218 gcc_assert (*loopss != gfc_ss_terminator);
220 *loopss = new_ss;
221 new_ss->loop_chain = old_ss->loop_chain;
222 new_ss->loop = old_ss->loop;
224 gfc_free_ss (old_ss);
228 /* Check for dependencies between INTENT(IN) and INTENT(OUT) arguments of
229 elemental subroutines. Make temporaries for output arguments if any such
230 dependencies are found. Output arguments are chosen because internal_unpack
231 can be used, as is, to copy the result back to the variable. */
232 static void
233 gfc_conv_elemental_dependencies (gfc_se * se, gfc_se * loopse,
234 gfc_symbol * sym, gfc_actual_arglist * arg,
235 gfc_dep_check check_variable)
237 gfc_actual_arglist *arg0;
238 gfc_expr *e;
239 gfc_formal_arglist *formal;
240 gfc_se parmse;
241 gfc_ss *ss;
242 gfc_symbol *fsym;
243 tree data;
244 tree size;
245 tree tmp;
247 if (loopse->ss == NULL)
248 return;
250 ss = loopse->ss;
251 arg0 = arg;
252 formal = gfc_sym_get_dummy_args (sym);
254 /* Loop over all the arguments testing for dependencies. */
255 for (; arg != NULL; arg = arg->next, formal = formal ? formal->next : NULL)
257 e = arg->expr;
258 if (e == NULL)
259 continue;
261 /* Obtain the info structure for the current argument. */
262 for (ss = loopse->ss; ss && ss != gfc_ss_terminator; ss = ss->next)
263 if (ss->info->expr == e)
264 break;
266 /* If there is a dependency, create a temporary and use it
267 instead of the variable. */
268 fsym = formal ? formal->sym : NULL;
269 if (e->expr_type == EXPR_VARIABLE
270 && e->rank && fsym
271 && fsym->attr.intent != INTENT_IN
272 && gfc_check_fncall_dependency (e, fsym->attr.intent,
273 sym, arg0, check_variable))
275 tree initial, temptype;
276 stmtblock_t temp_post;
277 gfc_ss *tmp_ss;
279 tmp_ss = gfc_get_array_ss (gfc_ss_terminator, NULL, ss->dimen,
280 GFC_SS_SECTION);
281 gfc_mark_ss_chain_used (tmp_ss, 1);
282 tmp_ss->info->expr = ss->info->expr;
283 replace_ss (loopse, ss, tmp_ss);
285 /* Obtain the argument descriptor for unpacking. */
286 gfc_init_se (&parmse, NULL);
287 parmse.want_pointer = 1;
288 gfc_conv_expr_descriptor (&parmse, e);
289 gfc_add_block_to_block (&se->pre, &parmse.pre);
291 /* If we've got INTENT(INOUT) or a derived type with INTENT(OUT),
292 initialize the array temporary with a copy of the values. */
293 if (fsym->attr.intent == INTENT_INOUT
294 || (fsym->ts.type ==BT_DERIVED
295 && fsym->attr.intent == INTENT_OUT))
296 initial = parmse.expr;
297 /* For class expressions, we always initialize with the copy of
298 the values. */
299 else if (e->ts.type == BT_CLASS)
300 initial = parmse.expr;
301 else
302 initial = NULL_TREE;
304 if (e->ts.type != BT_CLASS)
306 /* Find the type of the temporary to create; we don't use the type
307 of e itself as this breaks for subcomponent-references in e
308 (where the type of e is that of the final reference, but
309 parmse.expr's type corresponds to the full derived-type). */
310 /* TODO: Fix this somehow so we don't need a temporary of the whole
311 array but instead only the components referenced. */
312 temptype = TREE_TYPE (parmse.expr); /* Pointer to descriptor. */
313 gcc_assert (TREE_CODE (temptype) == POINTER_TYPE);
314 temptype = TREE_TYPE (temptype);
315 temptype = gfc_get_element_type (temptype);
318 else
319 /* For class arrays signal that the size of the dynamic type has to
320 be obtained from the vtable, using the 'initial' expression. */
321 temptype = NULL_TREE;
323 /* Generate the temporary. Cleaning up the temporary should be the
324 very last thing done, so we add the code to a new block and add it
325 to se->post as last instructions. */
326 size = gfc_create_var (gfc_array_index_type, NULL);
327 data = gfc_create_var (pvoid_type_node, NULL);
328 gfc_init_block (&temp_post);
329 tmp = gfc_trans_create_temp_array (&se->pre, &temp_post, tmp_ss,
330 temptype, initial, false, true,
331 false, &arg->expr->where);
332 gfc_add_modify (&se->pre, size, tmp);
333 tmp = fold_convert (pvoid_type_node, tmp_ss->info->data.array.data);
334 gfc_add_modify (&se->pre, data, tmp);
336 /* Update other ss' delta. */
337 gfc_set_delta (loopse->loop);
339 /* Copy the result back using unpack..... */
340 if (e->ts.type != BT_CLASS)
341 tmp = build_call_expr_loc (input_location,
342 gfor_fndecl_in_unpack, 2, parmse.expr, data);
343 else
345 /* ... except for class results where the copy is
346 unconditional. */
347 tmp = build_fold_indirect_ref_loc (input_location, parmse.expr);
348 tmp = gfc_conv_descriptor_data_get (tmp);
349 tmp = build_call_expr_loc (input_location,
350 builtin_decl_explicit (BUILT_IN_MEMCPY),
351 3, tmp, data,
352 fold_convert (size_type_node, size));
354 gfc_add_expr_to_block (&se->post, tmp);
356 /* parmse.pre is already added above. */
357 gfc_add_block_to_block (&se->post, &parmse.post);
358 gfc_add_block_to_block (&se->post, &temp_post);
364 /* Get the interface symbol for the procedure corresponding to the given call.
365 We can't get the procedure symbol directly as we have to handle the case
366 of (deferred) type-bound procedures. */
368 static gfc_symbol *
369 get_proc_ifc_for_call (gfc_code *c)
371 gfc_symbol *sym;
373 gcc_assert (c->op == EXEC_ASSIGN_CALL || c->op == EXEC_CALL);
375 sym = gfc_get_proc_ifc_for_expr (c->expr1);
377 /* Fall back/last resort try. */
378 if (sym == NULL)
379 sym = c->resolved_sym;
381 return sym;
385 /* Translate the CALL statement. Builds a call to an F95 subroutine. */
387 tree
388 gfc_trans_call (gfc_code * code, bool dependency_check,
389 tree mask, tree count1, bool invert)
391 gfc_se se;
392 gfc_ss * ss;
393 int has_alternate_specifier;
394 gfc_dep_check check_variable;
395 tree index = NULL_TREE;
396 tree maskexpr = NULL_TREE;
397 tree tmp;
399 /* A CALL starts a new block because the actual arguments may have to
400 be evaluated first. */
401 gfc_init_se (&se, NULL);
402 gfc_start_block (&se.pre);
404 gcc_assert (code->resolved_sym);
406 ss = gfc_ss_terminator;
407 if (code->resolved_sym->attr.elemental)
408 ss = gfc_walk_elemental_function_args (ss, code->ext.actual,
409 get_proc_ifc_for_call (code),
410 GFC_SS_REFERENCE);
412 /* Is not an elemental subroutine call with array valued arguments. */
413 if (ss == gfc_ss_terminator)
416 /* Translate the call. */
417 has_alternate_specifier
418 = gfc_conv_procedure_call (&se, code->resolved_sym, code->ext.actual,
419 code->expr1, NULL);
421 /* A subroutine without side-effect, by definition, does nothing! */
422 TREE_SIDE_EFFECTS (se.expr) = 1;
424 /* Chain the pieces together and return the block. */
425 if (has_alternate_specifier)
427 gfc_code *select_code;
428 gfc_symbol *sym;
429 select_code = code->next;
430 gcc_assert(select_code->op == EXEC_SELECT);
431 sym = select_code->expr1->symtree->n.sym;
432 se.expr = convert (gfc_typenode_for_spec (&sym->ts), se.expr);
433 if (sym->backend_decl == NULL)
434 sym->backend_decl = gfc_get_symbol_decl (sym);
435 gfc_add_modify (&se.pre, sym->backend_decl, se.expr);
437 else
438 gfc_add_expr_to_block (&se.pre, se.expr);
440 gfc_add_block_to_block (&se.pre, &se.post);
443 else
445 /* An elemental subroutine call with array valued arguments has
446 to be scalarized. */
447 gfc_loopinfo loop;
448 stmtblock_t body;
449 stmtblock_t block;
450 gfc_se loopse;
451 gfc_se depse;
453 /* gfc_walk_elemental_function_args renders the ss chain in the
454 reverse order to the actual argument order. */
455 ss = gfc_reverse_ss (ss);
457 /* Initialize the loop. */
458 gfc_init_se (&loopse, NULL);
459 gfc_init_loopinfo (&loop);
460 gfc_add_ss_to_loop (&loop, ss);
462 gfc_conv_ss_startstride (&loop);
463 /* TODO: gfc_conv_loop_setup generates a temporary for vector
464 subscripts. This could be prevented in the elemental case
465 as temporaries are handled separatedly
466 (below in gfc_conv_elemental_dependencies). */
467 gfc_conv_loop_setup (&loop, &code->expr1->where);
468 gfc_mark_ss_chain_used (ss, 1);
470 /* Convert the arguments, checking for dependencies. */
471 gfc_copy_loopinfo_to_se (&loopse, &loop);
472 loopse.ss = ss;
474 /* For operator assignment, do dependency checking. */
475 if (dependency_check)
476 check_variable = ELEM_CHECK_VARIABLE;
477 else
478 check_variable = ELEM_DONT_CHECK_VARIABLE;
480 gfc_init_se (&depse, NULL);
481 gfc_conv_elemental_dependencies (&depse, &loopse, code->resolved_sym,
482 code->ext.actual, check_variable);
484 gfc_add_block_to_block (&loop.pre, &depse.pre);
485 gfc_add_block_to_block (&loop.post, &depse.post);
487 /* Generate the loop body. */
488 gfc_start_scalarized_body (&loop, &body);
489 gfc_init_block (&block);
491 if (mask && count1)
493 /* Form the mask expression according to the mask. */
494 index = count1;
495 maskexpr = gfc_build_array_ref (mask, index, NULL);
496 if (invert)
497 maskexpr = fold_build1_loc (input_location, TRUTH_NOT_EXPR,
498 TREE_TYPE (maskexpr), maskexpr);
501 /* Add the subroutine call to the block. */
502 gfc_conv_procedure_call (&loopse, code->resolved_sym,
503 code->ext.actual, code->expr1,
504 NULL);
506 if (mask && count1)
508 tmp = build3_v (COND_EXPR, maskexpr, loopse.expr,
509 build_empty_stmt (input_location));
510 gfc_add_expr_to_block (&loopse.pre, tmp);
511 tmp = fold_build2_loc (input_location, PLUS_EXPR,
512 gfc_array_index_type,
513 count1, gfc_index_one_node);
514 gfc_add_modify (&loopse.pre, count1, tmp);
516 else
517 gfc_add_expr_to_block (&loopse.pre, loopse.expr);
519 gfc_add_block_to_block (&block, &loopse.pre);
520 gfc_add_block_to_block (&block, &loopse.post);
522 /* Finish up the loop block and the loop. */
523 gfc_add_expr_to_block (&body, gfc_finish_block (&block));
524 gfc_trans_scalarizing_loops (&loop, &body);
525 gfc_add_block_to_block (&se.pre, &loop.pre);
526 gfc_add_block_to_block (&se.pre, &loop.post);
527 gfc_add_block_to_block (&se.pre, &se.post);
528 gfc_cleanup_loop (&loop);
531 return gfc_finish_block (&se.pre);
535 /* Translate the RETURN statement. */
537 tree
538 gfc_trans_return (gfc_code * code)
540 if (code->expr1)
542 gfc_se se;
543 tree tmp;
544 tree result;
546 /* If code->expr is not NULL, this return statement must appear
547 in a subroutine and current_fake_result_decl has already
548 been generated. */
550 result = gfc_get_fake_result_decl (NULL, 0);
551 if (!result)
553 gfc_warning (0,
554 "An alternate return at %L without a * dummy argument",
555 &code->expr1->where);
556 return gfc_generate_return ();
559 /* Start a new block for this statement. */
560 gfc_init_se (&se, NULL);
561 gfc_start_block (&se.pre);
563 gfc_conv_expr (&se, code->expr1);
565 /* Note that the actually returned expression is a simple value and
566 does not depend on any pointers or such; thus we can clean-up with
567 se.post before returning. */
568 tmp = fold_build2_loc (input_location, MODIFY_EXPR, TREE_TYPE (result),
569 result, fold_convert (TREE_TYPE (result),
570 se.expr));
571 gfc_add_expr_to_block (&se.pre, tmp);
572 gfc_add_block_to_block (&se.pre, &se.post);
574 tmp = gfc_generate_return ();
575 gfc_add_expr_to_block (&se.pre, tmp);
576 return gfc_finish_block (&se.pre);
579 return gfc_generate_return ();
583 /* Translate the PAUSE statement. We have to translate this statement
584 to a runtime library call. */
586 tree
587 gfc_trans_pause (gfc_code * code)
589 tree gfc_int4_type_node = gfc_get_int_type (4);
590 gfc_se se;
591 tree tmp;
593 /* Start a new block for this statement. */
594 gfc_init_se (&se, NULL);
595 gfc_start_block (&se.pre);
598 if (code->expr1 == NULL)
600 tmp = build_int_cst (gfc_int4_type_node, 0);
601 tmp = build_call_expr_loc (input_location,
602 gfor_fndecl_pause_string, 2,
603 build_int_cst (pchar_type_node, 0), tmp);
605 else if (code->expr1->ts.type == BT_INTEGER)
607 gfc_conv_expr (&se, code->expr1);
608 tmp = build_call_expr_loc (input_location,
609 gfor_fndecl_pause_numeric, 1,
610 fold_convert (gfc_int4_type_node, se.expr));
612 else
614 gfc_conv_expr_reference (&se, code->expr1);
615 tmp = build_call_expr_loc (input_location,
616 gfor_fndecl_pause_string, 2,
617 se.expr, se.string_length);
620 gfc_add_expr_to_block (&se.pre, tmp);
622 gfc_add_block_to_block (&se.pre, &se.post);
624 return gfc_finish_block (&se.pre);
628 /* Translate the STOP statement. We have to translate this statement
629 to a runtime library call. */
631 tree
632 gfc_trans_stop (gfc_code *code, bool error_stop)
634 tree gfc_int4_type_node = gfc_get_int_type (4);
635 gfc_se se;
636 tree tmp;
638 /* Start a new block for this statement. */
639 gfc_init_se (&se, NULL);
640 gfc_start_block (&se.pre);
642 if (code->expr1 == NULL)
644 tmp = build_int_cst (gfc_int4_type_node, 0);
645 tmp = build_call_expr_loc (input_location,
646 error_stop
647 ? (flag_coarray == GFC_FCOARRAY_LIB
648 ? gfor_fndecl_caf_error_stop_str
649 : gfor_fndecl_error_stop_string)
650 : gfor_fndecl_stop_string,
651 2, build_int_cst (pchar_type_node, 0), tmp);
653 else if (code->expr1->ts.type == BT_INTEGER)
655 gfc_conv_expr (&se, code->expr1);
656 tmp = build_call_expr_loc (input_location,
657 error_stop
658 ? (flag_coarray == GFC_FCOARRAY_LIB
659 ? gfor_fndecl_caf_error_stop
660 : gfor_fndecl_error_stop_numeric)
661 : gfor_fndecl_stop_numeric_f08, 1,
662 fold_convert (gfc_int4_type_node, se.expr));
664 else
666 gfc_conv_expr_reference (&se, code->expr1);
667 tmp = build_call_expr_loc (input_location,
668 error_stop
669 ? (flag_coarray == GFC_FCOARRAY_LIB
670 ? gfor_fndecl_caf_error_stop_str
671 : gfor_fndecl_error_stop_string)
672 : gfor_fndecl_stop_string,
673 2, se.expr, se.string_length);
676 gfc_add_expr_to_block (&se.pre, tmp);
678 gfc_add_block_to_block (&se.pre, &se.post);
680 return gfc_finish_block (&se.pre);
684 tree
685 gfc_trans_lock_unlock (gfc_code *code, gfc_exec_op type ATTRIBUTE_UNUSED)
687 gfc_se se, argse;
688 tree stat = NULL_TREE, lock_acquired = NULL_TREE;
690 /* Short cut: For single images without STAT= or LOCK_ACQUIRED
691 return early. (ERRMSG= is always untouched for -fcoarray=single.) */
692 if (!code->expr2 && !code->expr4 && flag_coarray != GFC_FCOARRAY_LIB)
693 return NULL_TREE;
695 gfc_init_se (&se, NULL);
696 gfc_start_block (&se.pre);
698 if (code->expr2)
700 gcc_assert (code->expr2->expr_type == EXPR_VARIABLE);
701 gfc_init_se (&argse, NULL);
702 gfc_conv_expr_val (&argse, code->expr2);
703 stat = argse.expr;
706 if (code->expr4)
708 gcc_assert (code->expr4->expr_type == EXPR_VARIABLE);
709 gfc_init_se (&argse, NULL);
710 gfc_conv_expr_val (&argse, code->expr4);
711 lock_acquired = argse.expr;
714 if (stat != NULL_TREE)
715 gfc_add_modify (&se.pre, stat, build_int_cst (TREE_TYPE (stat), 0));
717 if (lock_acquired != NULL_TREE)
718 gfc_add_modify (&se.pre, lock_acquired,
719 fold_convert (TREE_TYPE (lock_acquired),
720 boolean_true_node));
722 return gfc_finish_block (&se.pre);
726 tree
727 gfc_trans_sync (gfc_code *code, gfc_exec_op type)
729 gfc_se se, argse;
730 tree tmp;
731 tree images = NULL_TREE, stat = NULL_TREE,
732 errmsg = NULL_TREE, errmsglen = NULL_TREE;
734 /* Short cut: For single images without bound checking or without STAT=,
735 return early. (ERRMSG= is always untouched for -fcoarray=single.) */
736 if (!code->expr2 && !(gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
737 && flag_coarray != GFC_FCOARRAY_LIB)
738 return NULL_TREE;
740 gfc_init_se (&se, NULL);
741 gfc_start_block (&se.pre);
743 if (code->expr1 && code->expr1->rank == 0)
745 gfc_init_se (&argse, NULL);
746 gfc_conv_expr_val (&argse, code->expr1);
747 images = argse.expr;
750 if (code->expr2)
752 gcc_assert (code->expr2->expr_type == EXPR_VARIABLE);
753 gfc_init_se (&argse, NULL);
754 gfc_conv_expr_val (&argse, code->expr2);
755 stat = argse.expr;
757 else
758 stat = null_pointer_node;
760 if (code->expr3 && flag_coarray == GFC_FCOARRAY_LIB)
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)
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 if (flag_coarray != GFC_FCOARRAY_LIB)
806 /* Set STAT to zero. */
807 if (code->expr2)
808 gfc_add_modify (&se.pre, stat, build_int_cst (TREE_TYPE (stat), 0));
810 else if (type == EXEC_SYNC_ALL || type == EXEC_SYNC_MEMORY)
812 /* SYNC ALL => stat == null_pointer_node
813 SYNC ALL(stat=s) => stat has an integer type
815 If "stat" has the wrong integer type, use a temp variable of
816 the right type and later cast the result back into "stat". */
817 if (stat == null_pointer_node || TREE_TYPE (stat) == integer_type_node)
819 if (TREE_TYPE (stat) == integer_type_node)
820 stat = gfc_build_addr_expr (NULL, stat);
822 if(type == EXEC_SYNC_MEMORY)
823 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sync_memory,
824 3, stat, errmsg, errmsglen);
825 else
826 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sync_all,
827 3, stat, errmsg, errmsglen);
829 gfc_add_expr_to_block (&se.pre, tmp);
831 else
833 tree tmp_stat = gfc_create_var (integer_type_node, "stat");
835 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sync_all,
836 3, gfc_build_addr_expr (NULL, tmp_stat),
837 errmsg, errmsglen);
838 gfc_add_expr_to_block (&se.pre, tmp);
840 gfc_add_modify (&se.pre, stat,
841 fold_convert (TREE_TYPE (stat), tmp_stat));
844 else
846 tree len;
848 gcc_assert (type == EXEC_SYNC_IMAGES);
850 if (!code->expr1)
852 len = build_int_cst (integer_type_node, -1);
853 images = null_pointer_node;
855 else if (code->expr1->rank == 0)
857 len = build_int_cst (integer_type_node, 1);
858 images = gfc_build_addr_expr (NULL_TREE, images);
860 else
862 /* FIXME. */
863 if (code->expr1->ts.kind != gfc_c_int_kind)
864 gfc_fatal_error ("Sorry, only support for integer kind %d "
865 "implemented for image-set at %L",
866 gfc_c_int_kind, &code->expr1->where);
868 gfc_conv_array_parameter (&se, code->expr1, true, NULL, NULL, &len);
869 images = se.expr;
871 tmp = gfc_typenode_for_spec (&code->expr1->ts);
872 if (GFC_ARRAY_TYPE_P (tmp) || GFC_DESCRIPTOR_TYPE_P (tmp))
873 tmp = gfc_get_element_type (tmp);
875 len = fold_build2_loc (input_location, TRUNC_DIV_EXPR,
876 TREE_TYPE (len), len,
877 fold_convert (TREE_TYPE (len),
878 TYPE_SIZE_UNIT (tmp)));
879 len = fold_convert (integer_type_node, len);
882 /* SYNC IMAGES(imgs) => stat == null_pointer_node
883 SYNC IMAGES(imgs,stat=s) => stat has an integer type
885 If "stat" has the wrong integer type, use a temp variable of
886 the right type and later cast the result back into "stat". */
887 if (stat == null_pointer_node || TREE_TYPE (stat) == integer_type_node)
889 if (TREE_TYPE (stat) == integer_type_node)
890 stat = gfc_build_addr_expr (NULL, stat);
892 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sync_images,
893 5, fold_convert (integer_type_node, len),
894 images, stat, errmsg, errmsglen);
895 gfc_add_expr_to_block (&se.pre, tmp);
897 else
899 tree tmp_stat = gfc_create_var (integer_type_node, "stat");
901 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sync_images,
902 5, fold_convert (integer_type_node, len),
903 images, gfc_build_addr_expr (NULL, tmp_stat),
904 errmsg, errmsglen);
905 gfc_add_expr_to_block (&se.pre, tmp);
907 gfc_add_modify (&se.pre, stat,
908 fold_convert (TREE_TYPE (stat), tmp_stat));
912 return gfc_finish_block (&se.pre);
916 /* Generate GENERIC for the IF construct. This function also deals with
917 the simple IF statement, because the front end translates the IF
918 statement into an IF construct.
920 We translate:
922 IF (cond) THEN
923 then_clause
924 ELSEIF (cond2)
925 elseif_clause
926 ELSE
927 else_clause
928 ENDIF
930 into:
932 pre_cond_s;
933 if (cond_s)
935 then_clause;
937 else
939 pre_cond_s
940 if (cond_s)
942 elseif_clause
944 else
946 else_clause;
950 where COND_S is the simplified version of the predicate. PRE_COND_S
951 are the pre side-effects produced by the translation of the
952 conditional.
953 We need to build the chain recursively otherwise we run into
954 problems with folding incomplete statements. */
956 static tree
957 gfc_trans_if_1 (gfc_code * code)
959 gfc_se if_se;
960 tree stmt, elsestmt;
961 locus saved_loc;
962 location_t loc;
964 /* Check for an unconditional ELSE clause. */
965 if (!code->expr1)
966 return gfc_trans_code (code->next);
968 /* Initialize a statement builder for each block. Puts in NULL_TREEs. */
969 gfc_init_se (&if_se, NULL);
970 gfc_start_block (&if_se.pre);
972 /* Calculate the IF condition expression. */
973 if (code->expr1->where.lb)
975 gfc_save_backend_locus (&saved_loc);
976 gfc_set_backend_locus (&code->expr1->where);
979 gfc_conv_expr_val (&if_se, code->expr1);
981 if (code->expr1->where.lb)
982 gfc_restore_backend_locus (&saved_loc);
984 /* Translate the THEN clause. */
985 stmt = gfc_trans_code (code->next);
987 /* Translate the ELSE clause. */
988 if (code->block)
989 elsestmt = gfc_trans_if_1 (code->block);
990 else
991 elsestmt = build_empty_stmt (input_location);
993 /* Build the condition expression and add it to the condition block. */
994 loc = code->expr1->where.lb ? code->expr1->where.lb->location : input_location;
995 stmt = fold_build3_loc (loc, COND_EXPR, void_type_node, if_se.expr, stmt,
996 elsestmt);
998 gfc_add_expr_to_block (&if_se.pre, stmt);
1000 /* Finish off this statement. */
1001 return gfc_finish_block (&if_se.pre);
1004 tree
1005 gfc_trans_if (gfc_code * code)
1007 stmtblock_t body;
1008 tree exit_label;
1010 /* Create exit label so it is available for trans'ing the body code. */
1011 exit_label = gfc_build_label_decl (NULL_TREE);
1012 code->exit_label = exit_label;
1014 /* Translate the actual code in code->block. */
1015 gfc_init_block (&body);
1016 gfc_add_expr_to_block (&body, gfc_trans_if_1 (code->block));
1018 /* Add exit label. */
1019 gfc_add_expr_to_block (&body, build1_v (LABEL_EXPR, exit_label));
1021 return gfc_finish_block (&body);
1025 /* Translate an arithmetic IF expression.
1027 IF (cond) label1, label2, label3 translates to
1029 if (cond <= 0)
1031 if (cond < 0)
1032 goto label1;
1033 else // cond == 0
1034 goto label2;
1036 else // cond > 0
1037 goto label3;
1039 An optimized version can be generated in case of equal labels.
1040 E.g., if label1 is equal to label2, we can translate it to
1042 if (cond <= 0)
1043 goto label1;
1044 else
1045 goto label3;
1048 tree
1049 gfc_trans_arithmetic_if (gfc_code * code)
1051 gfc_se se;
1052 tree tmp;
1053 tree branch1;
1054 tree branch2;
1055 tree zero;
1057 /* Start a new block. */
1058 gfc_init_se (&se, NULL);
1059 gfc_start_block (&se.pre);
1061 /* Pre-evaluate COND. */
1062 gfc_conv_expr_val (&se, code->expr1);
1063 se.expr = gfc_evaluate_now (se.expr, &se.pre);
1065 /* Build something to compare with. */
1066 zero = gfc_build_const (TREE_TYPE (se.expr), integer_zero_node);
1068 if (code->label1->value != code->label2->value)
1070 /* If (cond < 0) take branch1 else take branch2.
1071 First build jumps to the COND .LT. 0 and the COND .EQ. 0 cases. */
1072 branch1 = build1_v (GOTO_EXPR, gfc_get_label_decl (code->label1));
1073 branch2 = build1_v (GOTO_EXPR, gfc_get_label_decl (code->label2));
1075 if (code->label1->value != code->label3->value)
1076 tmp = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
1077 se.expr, zero);
1078 else
1079 tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
1080 se.expr, zero);
1082 branch1 = fold_build3_loc (input_location, COND_EXPR, void_type_node,
1083 tmp, branch1, branch2);
1085 else
1086 branch1 = build1_v (GOTO_EXPR, gfc_get_label_decl (code->label1));
1088 if (code->label1->value != code->label3->value
1089 && code->label2->value != code->label3->value)
1091 /* if (cond <= 0) take branch1 else take branch2. */
1092 branch2 = build1_v (GOTO_EXPR, gfc_get_label_decl (code->label3));
1093 tmp = fold_build2_loc (input_location, LE_EXPR, boolean_type_node,
1094 se.expr, zero);
1095 branch1 = fold_build3_loc (input_location, COND_EXPR, void_type_node,
1096 tmp, branch1, branch2);
1099 /* Append the COND_EXPR to the evaluation of COND, and return. */
1100 gfc_add_expr_to_block (&se.pre, branch1);
1101 return gfc_finish_block (&se.pre);
1105 /* Translate a CRITICAL block. */
1106 tree
1107 gfc_trans_critical (gfc_code *code)
1109 stmtblock_t block;
1110 tree tmp, token = NULL_TREE;
1112 gfc_start_block (&block);
1114 if (flag_coarray == GFC_FCOARRAY_LIB)
1116 token = gfc_get_symbol_decl (code->resolved_sym);
1117 token = GFC_TYPE_ARRAY_CAF_TOKEN (TREE_TYPE (token));
1118 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_lock, 7,
1119 token, integer_zero_node, integer_one_node,
1120 null_pointer_node, null_pointer_node,
1121 null_pointer_node, integer_zero_node);
1122 gfc_add_expr_to_block (&block, tmp);
1125 tmp = gfc_trans_code (code->block->next);
1126 gfc_add_expr_to_block (&block, tmp);
1128 if (flag_coarray == GFC_FCOARRAY_LIB)
1130 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_unlock, 6,
1131 token, integer_zero_node, integer_one_node,
1132 null_pointer_node, null_pointer_node,
1133 integer_zero_node);
1134 gfc_add_expr_to_block (&block, tmp);
1138 return gfc_finish_block (&block);
1142 /* Return true, when the class has a _len component. */
1144 static bool
1145 class_has_len_component (gfc_symbol *sym)
1147 gfc_component *comp = sym->ts.u.derived->components;
1148 while (comp)
1150 if (strcmp (comp->name, "_len") == 0)
1151 return true;
1152 comp = comp->next;
1154 return false;
1158 /* Do proper initialization for ASSOCIATE names. */
1160 static void
1161 trans_associate_var (gfc_symbol *sym, gfc_wrapped_block *block)
1163 gfc_expr *e;
1164 tree tmp;
1165 bool class_target;
1166 bool unlimited;
1167 tree desc;
1168 tree offset;
1169 tree dim;
1170 int n;
1171 tree charlen;
1172 bool need_len_assign;
1174 gcc_assert (sym->assoc);
1175 e = sym->assoc->target;
1177 class_target = (e->expr_type == EXPR_VARIABLE)
1178 && (gfc_is_class_scalar_expr (e)
1179 || gfc_is_class_array_ref (e, NULL));
1181 unlimited = UNLIMITED_POLY (e);
1183 /* Assignments to the string length need to be generated, when
1184 ( sym is a char array or
1185 sym has a _len component)
1186 and the associated expression is unlimited polymorphic, which is
1187 not (yet) correctly in 'unlimited', because for an already associated
1188 BT_DERIVED the u-poly flag is not set, i.e.,
1189 __tmp_CHARACTER_0_1 => w => arg
1190 ^ generated temp ^ from code, the w does not have the u-poly
1191 flag set, where UNLIMITED_POLY(e) expects it. */
1192 need_len_assign = ((unlimited || (e->ts.type == BT_DERIVED
1193 && e->ts.u.derived->attr.unlimited_polymorphic))
1194 && (sym->ts.type == BT_CHARACTER
1195 || ((sym->ts.type == BT_CLASS || sym->ts.type == BT_DERIVED)
1196 && class_has_len_component (sym))));
1197 /* Do a `pointer assignment' with updated descriptor (or assign descriptor
1198 to array temporary) for arrays with either unknown shape or if associating
1199 to a variable. */
1200 if (sym->attr.dimension && !class_target
1201 && (sym->as->type == AS_DEFERRED || sym->assoc->variable))
1203 gfc_se se;
1204 tree desc;
1205 bool cst_array_ctor;
1207 desc = sym->backend_decl;
1208 cst_array_ctor = e->expr_type == EXPR_ARRAY
1209 && gfc_constant_array_constructor_p (e->value.constructor);
1211 /* If association is to an expression, evaluate it and create temporary.
1212 Otherwise, get descriptor of target for pointer assignment. */
1213 gfc_init_se (&se, NULL);
1214 if (sym->assoc->variable || cst_array_ctor)
1216 se.direct_byref = 1;
1217 se.use_offset = 1;
1218 se.expr = desc;
1221 gfc_conv_expr_descriptor (&se, e);
1223 /* If we didn't already do the pointer assignment, set associate-name
1224 descriptor to the one generated for the temporary. */
1225 if (!sym->assoc->variable && !cst_array_ctor)
1227 int dim;
1229 gfc_add_modify (&se.pre, desc, se.expr);
1231 /* The generated descriptor has lower bound zero (as array
1232 temporary), shift bounds so we get lower bounds of 1. */
1233 for (dim = 0; dim < e->rank; ++dim)
1234 gfc_conv_shift_descriptor_lbound (&se.pre, desc,
1235 dim, gfc_index_one_node);
1238 /* If this is a subreference array pointer associate name use the
1239 associate variable element size for the value of 'span'. */
1240 if (sym->attr.subref_array_pointer)
1242 gcc_assert (e->expr_type == EXPR_VARIABLE);
1243 tmp = e->symtree->n.sym->backend_decl;
1244 tmp = gfc_get_element_type (TREE_TYPE (tmp));
1245 tmp = fold_convert (gfc_array_index_type, size_in_bytes (tmp));
1246 gfc_add_modify (&se.pre, GFC_DECL_SPAN(desc), tmp);
1249 /* Done, register stuff as init / cleanup code. */
1250 gfc_add_init_cleanup (block, gfc_finish_block (&se.pre),
1251 gfc_finish_block (&se.post));
1254 /* Temporaries, arising from TYPE IS, just need the descriptor of class
1255 arrays to be assigned directly. */
1256 else if (class_target && sym->attr.dimension
1257 && (sym->ts.type == BT_DERIVED || unlimited))
1259 gfc_se se;
1261 gfc_init_se (&se, NULL);
1262 se.descriptor_only = 1;
1263 gfc_conv_expr (&se, e);
1265 gcc_assert (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (se.expr)));
1266 gcc_assert (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (sym->backend_decl)));
1268 gfc_add_modify (&se.pre, sym->backend_decl, se.expr);
1270 if (unlimited)
1272 /* Recover the dtype, which has been overwritten by the
1273 assignment from an unlimited polymorphic object. */
1274 tmp = gfc_conv_descriptor_dtype (sym->backend_decl);
1275 gfc_add_modify (&se.pre, tmp,
1276 gfc_get_dtype (TREE_TYPE (sym->backend_decl)));
1279 gfc_add_init_cleanup (block, gfc_finish_block( &se.pre),
1280 gfc_finish_block (&se.post));
1283 /* Do a scalar pointer assignment; this is for scalar variable targets. */
1284 else if (gfc_is_associate_pointer (sym))
1286 gfc_se se;
1288 gcc_assert (!sym->attr.dimension);
1290 gfc_init_se (&se, NULL);
1292 /* Class associate-names come this way because they are
1293 unconditionally associate pointers and the symbol is scalar. */
1294 if (sym->ts.type == BT_CLASS && CLASS_DATA (sym)->attr.dimension)
1296 tree target_expr;
1297 /* For a class array we need a descriptor for the selector. */
1298 gfc_conv_expr_descriptor (&se, e);
1299 /* Needed to get/set the _len component below. */
1300 target_expr = se.expr;
1302 /* Obtain a temporary class container for the result. */
1303 gfc_conv_class_to_class (&se, e, sym->ts, false, true, false, false);
1304 se.expr = build_fold_indirect_ref_loc (input_location, se.expr);
1306 /* Set the offset. */
1307 desc = gfc_class_data_get (se.expr);
1308 offset = gfc_index_zero_node;
1309 for (n = 0; n < e->rank; n++)
1311 dim = gfc_rank_cst[n];
1312 tmp = fold_build2_loc (input_location, MULT_EXPR,
1313 gfc_array_index_type,
1314 gfc_conv_descriptor_stride_get (desc, dim),
1315 gfc_conv_descriptor_lbound_get (desc, dim));
1316 offset = fold_build2_loc (input_location, MINUS_EXPR,
1317 gfc_array_index_type,
1318 offset, tmp);
1320 if (need_len_assign)
1322 /* Get the _len comp from the target expr by stripping _data
1323 from it and adding component-ref to _len. */
1324 tmp = gfc_class_len_get (TREE_OPERAND (target_expr, 0));
1325 /* Get the component-ref for the temp structure's _len comp. */
1326 charlen = gfc_class_len_get (se.expr);
1327 /* Add the assign to the beginning of the the block... */
1328 gfc_add_modify (&se.pre, charlen,
1329 fold_convert (TREE_TYPE (charlen), tmp));
1330 /* and the oposite way at the end of the block, to hand changes
1331 on the string length back. */
1332 gfc_add_modify (&se.post, tmp,
1333 fold_convert (TREE_TYPE (tmp), charlen));
1334 /* Length assignment done, prevent adding it again below. */
1335 need_len_assign = false;
1337 gfc_conv_descriptor_offset_set (&se.pre, desc, offset);
1339 else if (sym->ts.type == BT_CLASS && e->ts.type == BT_CLASS
1340 && CLASS_DATA (e)->attr.dimension)
1342 /* This is bound to be a class array element. */
1343 gfc_conv_expr_reference (&se, e);
1344 /* Get the _vptr component of the class object. */
1345 tmp = gfc_get_vptr_from_expr (se.expr);
1346 /* Obtain a temporary class container for the result. */
1347 gfc_conv_derived_to_class (&se, e, sym->ts, tmp, false, false);
1348 se.expr = build_fold_indirect_ref_loc (input_location, se.expr);
1350 else
1352 /* For BT_CLASS and BT_DERIVED, this boils down to a pointer assign,
1353 which has the string length included. For CHARACTERS it is still
1354 needed and will be done at the end of this routine. */
1355 gfc_conv_expr (&se, e);
1356 need_len_assign = need_len_assign && sym->ts.type == BT_CHARACTER;
1359 tmp = TREE_TYPE (sym->backend_decl);
1360 tmp = gfc_build_addr_expr (tmp, se.expr);
1361 gfc_add_modify (&se.pre, sym->backend_decl, tmp);
1363 gfc_add_init_cleanup (block, gfc_finish_block( &se.pre),
1364 gfc_finish_block (&se.post));
1367 /* Do a simple assignment. This is for scalar expressions, where we
1368 can simply use expression assignment. */
1369 else
1371 gfc_expr *lhs;
1373 lhs = gfc_lval_expr_from_sym (sym);
1374 tmp = gfc_trans_assignment (lhs, e, false, true);
1375 gfc_add_init_cleanup (block, tmp, NULL_TREE);
1378 /* Set the stringlength, when needed. */
1379 if (need_len_assign)
1381 gfc_se se;
1382 gfc_init_se (&se, NULL);
1383 if (e->symtree->n.sym->ts.type == BT_CHARACTER)
1385 /* What about deferred strings? */
1386 gcc_assert (!e->symtree->n.sym->ts.deferred);
1387 tmp = e->symtree->n.sym->ts.u.cl->backend_decl;
1389 else
1390 tmp = gfc_class_len_get (gfc_get_symbol_decl (e->symtree->n.sym));
1391 gfc_get_symbol_decl (sym);
1392 charlen = sym->ts.type == BT_CHARACTER ? sym->ts.u.cl->backend_decl
1393 : gfc_class_len_get (sym->backend_decl);
1394 /* Prevent adding a noop len= len. */
1395 if (tmp != charlen)
1397 gfc_add_modify (&se.pre, charlen,
1398 fold_convert (TREE_TYPE (charlen), tmp));
1399 gfc_add_init_cleanup (block, gfc_finish_block (&se.pre),
1400 gfc_finish_block (&se.post));
1406 /* Translate a BLOCK construct. This is basically what we would do for a
1407 procedure body. */
1409 tree
1410 gfc_trans_block_construct (gfc_code* code)
1412 gfc_namespace* ns;
1413 gfc_symbol* sym;
1414 gfc_wrapped_block block;
1415 tree exit_label;
1416 stmtblock_t body;
1417 gfc_association_list *ass;
1419 ns = code->ext.block.ns;
1420 gcc_assert (ns);
1421 sym = ns->proc_name;
1422 gcc_assert (sym);
1424 /* Process local variables. */
1425 gcc_assert (!sym->tlink);
1426 sym->tlink = sym;
1427 gfc_process_block_locals (ns);
1429 /* Generate code including exit-label. */
1430 gfc_init_block (&body);
1431 exit_label = gfc_build_label_decl (NULL_TREE);
1432 code->exit_label = exit_label;
1434 /* Generate !$ACC DECLARE directive. */
1435 if (ns->oacc_declare_clauses)
1437 tree tmp = gfc_trans_oacc_declare (&body, ns);
1438 gfc_add_expr_to_block (&body, tmp);
1441 gfc_add_expr_to_block (&body, gfc_trans_code (ns->code));
1442 gfc_add_expr_to_block (&body, build1_v (LABEL_EXPR, exit_label));
1444 /* Finish everything. */
1445 gfc_start_wrapped_block (&block, gfc_finish_block (&body));
1446 gfc_trans_deferred_vars (sym, &block);
1447 for (ass = code->ext.block.assoc; ass; ass = ass->next)
1448 trans_associate_var (ass->st->n.sym, &block);
1450 return gfc_finish_wrapped_block (&block);
1454 /* Translate the simple DO construct. This is where the loop variable has
1455 integer type and step +-1. We can't use this in the general case
1456 because integer overflow and floating point errors could give incorrect
1457 results.
1458 We translate a do loop from:
1460 DO dovar = from, to, step
1461 body
1462 END DO
1466 [Evaluate loop bounds and step]
1467 dovar = from;
1468 if ((step > 0) ? (dovar <= to) : (dovar => to))
1470 for (;;)
1472 body;
1473 cycle_label:
1474 cond = (dovar == to);
1475 dovar += step;
1476 if (cond) goto end_label;
1479 end_label:
1481 This helps the optimizers by avoiding the extra induction variable
1482 used in the general case. */
1484 static tree
1485 gfc_trans_simple_do (gfc_code * code, stmtblock_t *pblock, tree dovar,
1486 tree from, tree to, tree step, tree exit_cond)
1488 stmtblock_t body;
1489 tree type;
1490 tree cond;
1491 tree tmp;
1492 tree saved_dovar = NULL;
1493 tree cycle_label;
1494 tree exit_label;
1495 location_t loc;
1497 type = TREE_TYPE (dovar);
1499 loc = code->ext.iterator->start->where.lb->location;
1501 /* Initialize the DO variable: dovar = from. */
1502 gfc_add_modify_loc (loc, pblock, dovar,
1503 fold_convert (TREE_TYPE(dovar), from));
1505 /* Save value for do-tinkering checking. */
1506 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
1508 saved_dovar = gfc_create_var (type, ".saved_dovar");
1509 gfc_add_modify_loc (loc, pblock, saved_dovar, dovar);
1512 /* Cycle and exit statements are implemented with gotos. */
1513 cycle_label = gfc_build_label_decl (NULL_TREE);
1514 exit_label = gfc_build_label_decl (NULL_TREE);
1516 /* Put the labels where they can be found later. See gfc_trans_do(). */
1517 code->cycle_label = cycle_label;
1518 code->exit_label = exit_label;
1520 /* Loop body. */
1521 gfc_start_block (&body);
1523 /* Main loop body. */
1524 tmp = gfc_trans_code_cond (code->block->next, exit_cond);
1525 gfc_add_expr_to_block (&body, tmp);
1527 /* Label for cycle statements (if needed). */
1528 if (TREE_USED (cycle_label))
1530 tmp = build1_v (LABEL_EXPR, cycle_label);
1531 gfc_add_expr_to_block (&body, tmp);
1534 /* Check whether someone has modified the loop variable. */
1535 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
1537 tmp = fold_build2_loc (loc, NE_EXPR, boolean_type_node,
1538 dovar, saved_dovar);
1539 gfc_trans_runtime_check (true, false, tmp, &body, &code->loc,
1540 "Loop variable has been modified");
1543 /* Exit the loop if there is an I/O result condition or error. */
1544 if (exit_cond)
1546 tmp = build1_v (GOTO_EXPR, exit_label);
1547 tmp = fold_build3_loc (loc, COND_EXPR, void_type_node,
1548 exit_cond, tmp,
1549 build_empty_stmt (loc));
1550 gfc_add_expr_to_block (&body, tmp);
1553 /* Evaluate the loop condition. */
1554 cond = fold_build2_loc (loc, EQ_EXPR, boolean_type_node, dovar,
1555 to);
1556 cond = gfc_evaluate_now_loc (loc, cond, &body);
1558 /* Increment the loop variable. */
1559 tmp = fold_build2_loc (loc, PLUS_EXPR, type, dovar, step);
1560 gfc_add_modify_loc (loc, &body, dovar, tmp);
1562 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
1563 gfc_add_modify_loc (loc, &body, saved_dovar, dovar);
1565 /* The loop exit. */
1566 tmp = fold_build1_loc (loc, GOTO_EXPR, void_type_node, exit_label);
1567 TREE_USED (exit_label) = 1;
1568 tmp = fold_build3_loc (loc, COND_EXPR, void_type_node,
1569 cond, tmp, build_empty_stmt (loc));
1570 gfc_add_expr_to_block (&body, tmp);
1572 /* Finish the loop body. */
1573 tmp = gfc_finish_block (&body);
1574 tmp = fold_build1_loc (loc, LOOP_EXPR, void_type_node, tmp);
1576 /* Only execute the loop if the number of iterations is positive. */
1577 if (tree_int_cst_sgn (step) > 0)
1578 cond = fold_build2_loc (loc, LE_EXPR, boolean_type_node, dovar,
1579 to);
1580 else
1581 cond = fold_build2_loc (loc, GE_EXPR, boolean_type_node, dovar,
1582 to);
1583 tmp = fold_build3_loc (loc, COND_EXPR, void_type_node, cond, tmp,
1584 build_empty_stmt (loc));
1585 gfc_add_expr_to_block (pblock, tmp);
1587 /* Add the exit label. */
1588 tmp = build1_v (LABEL_EXPR, exit_label);
1589 gfc_add_expr_to_block (pblock, tmp);
1591 return gfc_finish_block (pblock);
1594 /* Translate the DO construct. This obviously is one of the most
1595 important ones to get right with any compiler, but especially
1596 so for Fortran.
1598 We special case some loop forms as described in gfc_trans_simple_do.
1599 For other cases we implement them with a separate loop count,
1600 as described in the standard.
1602 We translate a do loop from:
1604 DO dovar = from, to, step
1605 body
1606 END DO
1610 [evaluate loop bounds and step]
1611 empty = (step > 0 ? to < from : to > from);
1612 countm1 = (to - from) / step;
1613 dovar = from;
1614 if (empty) goto exit_label;
1615 for (;;)
1617 body;
1618 cycle_label:
1619 dovar += step
1620 countm1t = countm1;
1621 countm1--;
1622 if (countm1t == 0) goto exit_label;
1624 exit_label:
1626 countm1 is an unsigned integer. It is equal to the loop count minus one,
1627 because the loop count itself can overflow. */
1629 tree
1630 gfc_trans_do (gfc_code * code, tree exit_cond)
1632 gfc_se se;
1633 tree dovar;
1634 tree saved_dovar = NULL;
1635 tree from;
1636 tree to;
1637 tree step;
1638 tree countm1;
1639 tree type;
1640 tree utype;
1641 tree cond;
1642 tree cycle_label;
1643 tree exit_label;
1644 tree tmp;
1645 stmtblock_t block;
1646 stmtblock_t body;
1647 location_t loc;
1649 gfc_start_block (&block);
1651 loc = code->ext.iterator->start->where.lb->location;
1653 /* Evaluate all the expressions in the iterator. */
1654 gfc_init_se (&se, NULL);
1655 gfc_conv_expr_lhs (&se, code->ext.iterator->var);
1656 gfc_add_block_to_block (&block, &se.pre);
1657 dovar = se.expr;
1658 type = TREE_TYPE (dovar);
1660 gfc_init_se (&se, NULL);
1661 gfc_conv_expr_val (&se, code->ext.iterator->start);
1662 gfc_add_block_to_block (&block, &se.pre);
1663 from = gfc_evaluate_now (se.expr, &block);
1665 gfc_init_se (&se, NULL);
1666 gfc_conv_expr_val (&se, code->ext.iterator->end);
1667 gfc_add_block_to_block (&block, &se.pre);
1668 to = gfc_evaluate_now (se.expr, &block);
1670 gfc_init_se (&se, NULL);
1671 gfc_conv_expr_val (&se, code->ext.iterator->step);
1672 gfc_add_block_to_block (&block, &se.pre);
1673 step = gfc_evaluate_now (se.expr, &block);
1675 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
1677 tmp = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, step,
1678 build_zero_cst (type));
1679 gfc_trans_runtime_check (true, false, tmp, &block, &code->loc,
1680 "DO step value is zero");
1683 /* Special case simple loops. */
1684 if (TREE_CODE (type) == INTEGER_TYPE
1685 && (integer_onep (step)
1686 || tree_int_cst_equal (step, integer_minus_one_node)))
1687 return gfc_trans_simple_do (code, &block, dovar, from, to, step, exit_cond);
1690 if (TREE_CODE (type) == INTEGER_TYPE)
1691 utype = unsigned_type_for (type);
1692 else
1693 utype = unsigned_type_for (gfc_array_index_type);
1694 countm1 = gfc_create_var (utype, "countm1");
1696 /* Cycle and exit statements are implemented with gotos. */
1697 cycle_label = gfc_build_label_decl (NULL_TREE);
1698 exit_label = gfc_build_label_decl (NULL_TREE);
1699 TREE_USED (exit_label) = 1;
1701 /* Put these labels where they can be found later. */
1702 code->cycle_label = cycle_label;
1703 code->exit_label = exit_label;
1705 /* Initialize the DO variable: dovar = from. */
1706 gfc_add_modify (&block, dovar, from);
1708 /* Save value for do-tinkering checking. */
1709 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
1711 saved_dovar = gfc_create_var (type, ".saved_dovar");
1712 gfc_add_modify_loc (loc, &block, saved_dovar, dovar);
1715 /* Initialize loop count and jump to exit label if the loop is empty.
1716 This code is executed before we enter the loop body. We generate:
1717 if (step > 0)
1719 countm1 = (to - from) / step;
1720 if (to < from)
1721 goto exit_label;
1723 else
1725 countm1 = (from - to) / -step;
1726 if (to > from)
1727 goto exit_label;
1731 if (TREE_CODE (type) == INTEGER_TYPE)
1733 tree pos, neg, tou, fromu, stepu, tmp2;
1735 /* The distance from FROM to TO cannot always be represented in a signed
1736 type, thus use unsigned arithmetic, also to avoid any undefined
1737 overflow issues. */
1738 tou = fold_convert (utype, to);
1739 fromu = fold_convert (utype, from);
1740 stepu = fold_convert (utype, step);
1742 /* For a positive step, when to < from, exit, otherwise compute
1743 countm1 = ((unsigned)to - (unsigned)from) / (unsigned)step */
1744 tmp = fold_build2_loc (loc, LT_EXPR, boolean_type_node, to, from);
1745 tmp2 = fold_build2_loc (loc, TRUNC_DIV_EXPR, utype,
1746 fold_build2_loc (loc, MINUS_EXPR, utype,
1747 tou, fromu),
1748 stepu);
1749 pos = build2 (COMPOUND_EXPR, void_type_node,
1750 fold_build2 (MODIFY_EXPR, void_type_node,
1751 countm1, tmp2),
1752 build3_loc (loc, COND_EXPR, void_type_node, tmp,
1753 build1_loc (loc, GOTO_EXPR, void_type_node,
1754 exit_label), NULL_TREE));
1756 /* For a negative step, when to > from, exit, otherwise compute
1757 countm1 = ((unsigned)from - (unsigned)to) / -(unsigned)step */
1758 tmp = fold_build2_loc (loc, GT_EXPR, boolean_type_node, to, from);
1759 tmp2 = fold_build2_loc (loc, TRUNC_DIV_EXPR, utype,
1760 fold_build2_loc (loc, MINUS_EXPR, utype,
1761 fromu, tou),
1762 fold_build1_loc (loc, NEGATE_EXPR, utype, stepu));
1763 neg = build2 (COMPOUND_EXPR, void_type_node,
1764 fold_build2 (MODIFY_EXPR, void_type_node,
1765 countm1, tmp2),
1766 build3_loc (loc, COND_EXPR, void_type_node, tmp,
1767 build1_loc (loc, GOTO_EXPR, void_type_node,
1768 exit_label), NULL_TREE));
1770 tmp = fold_build2_loc (loc, LT_EXPR, boolean_type_node, step,
1771 build_int_cst (TREE_TYPE (step), 0));
1772 tmp = fold_build3_loc (loc, COND_EXPR, void_type_node, tmp, neg, pos);
1774 gfc_add_expr_to_block (&block, tmp);
1776 else
1778 tree pos_step;
1780 /* TODO: We could use the same width as the real type.
1781 This would probably cause more problems that it solves
1782 when we implement "long double" types. */
1784 tmp = fold_build2_loc (loc, MINUS_EXPR, type, to, from);
1785 tmp = fold_build2_loc (loc, RDIV_EXPR, type, tmp, step);
1786 tmp = fold_build1_loc (loc, FIX_TRUNC_EXPR, utype, tmp);
1787 gfc_add_modify (&block, countm1, tmp);
1789 /* We need a special check for empty loops:
1790 empty = (step > 0 ? to < from : to > from); */
1791 pos_step = fold_build2_loc (loc, GT_EXPR, boolean_type_node, step,
1792 build_zero_cst (type));
1793 tmp = fold_build3_loc (loc, COND_EXPR, boolean_type_node, pos_step,
1794 fold_build2_loc (loc, LT_EXPR,
1795 boolean_type_node, to, from),
1796 fold_build2_loc (loc, GT_EXPR,
1797 boolean_type_node, to, from));
1798 /* If the loop is empty, go directly to the exit label. */
1799 tmp = fold_build3_loc (loc, COND_EXPR, void_type_node, tmp,
1800 build1_v (GOTO_EXPR, exit_label),
1801 build_empty_stmt (input_location));
1802 gfc_add_expr_to_block (&block, tmp);
1805 /* Loop body. */
1806 gfc_start_block (&body);
1808 /* Main loop body. */
1809 tmp = gfc_trans_code_cond (code->block->next, exit_cond);
1810 gfc_add_expr_to_block (&body, tmp);
1812 /* Label for cycle statements (if needed). */
1813 if (TREE_USED (cycle_label))
1815 tmp = build1_v (LABEL_EXPR, cycle_label);
1816 gfc_add_expr_to_block (&body, tmp);
1819 /* Check whether someone has modified the loop variable. */
1820 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
1822 tmp = fold_build2_loc (loc, NE_EXPR, boolean_type_node, dovar,
1823 saved_dovar);
1824 gfc_trans_runtime_check (true, false, tmp, &body, &code->loc,
1825 "Loop variable has been modified");
1828 /* Exit the loop if there is an I/O result condition or error. */
1829 if (exit_cond)
1831 tmp = build1_v (GOTO_EXPR, exit_label);
1832 tmp = fold_build3_loc (loc, COND_EXPR, void_type_node,
1833 exit_cond, tmp,
1834 build_empty_stmt (input_location));
1835 gfc_add_expr_to_block (&body, tmp);
1838 /* Increment the loop variable. */
1839 tmp = fold_build2_loc (loc, PLUS_EXPR, type, dovar, step);
1840 gfc_add_modify_loc (loc, &body, dovar, tmp);
1842 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
1843 gfc_add_modify_loc (loc, &body, saved_dovar, dovar);
1845 /* Initialize countm1t. */
1846 tree countm1t = gfc_create_var (utype, "countm1t");
1847 gfc_add_modify_loc (loc, &body, countm1t, countm1);
1849 /* Decrement the loop count. */
1850 tmp = fold_build2_loc (loc, MINUS_EXPR, utype, countm1,
1851 build_int_cst (utype, 1));
1852 gfc_add_modify_loc (loc, &body, countm1, tmp);
1854 /* End with the loop condition. Loop until countm1t == 0. */
1855 cond = fold_build2_loc (loc, EQ_EXPR, boolean_type_node, countm1t,
1856 build_int_cst (utype, 0));
1857 tmp = fold_build1_loc (loc, GOTO_EXPR, void_type_node, exit_label);
1858 tmp = fold_build3_loc (loc, COND_EXPR, void_type_node,
1859 cond, tmp, build_empty_stmt (loc));
1860 gfc_add_expr_to_block (&body, tmp);
1862 /* End of loop body. */
1863 tmp = gfc_finish_block (&body);
1865 /* The for loop itself. */
1866 tmp = fold_build1_loc (loc, LOOP_EXPR, void_type_node, tmp);
1867 gfc_add_expr_to_block (&block, tmp);
1869 /* Add the exit label. */
1870 tmp = build1_v (LABEL_EXPR, exit_label);
1871 gfc_add_expr_to_block (&block, tmp);
1873 return gfc_finish_block (&block);
1877 /* Translate the DO WHILE construct.
1879 We translate
1881 DO WHILE (cond)
1882 body
1883 END DO
1887 for ( ; ; )
1889 pre_cond;
1890 if (! cond) goto exit_label;
1891 body;
1892 cycle_label:
1894 exit_label:
1896 Because the evaluation of the exit condition `cond' may have side
1897 effects, we can't do much for empty loop bodies. The backend optimizers
1898 should be smart enough to eliminate any dead loops. */
1900 tree
1901 gfc_trans_do_while (gfc_code * code)
1903 gfc_se cond;
1904 tree tmp;
1905 tree cycle_label;
1906 tree exit_label;
1907 stmtblock_t block;
1909 /* Everything we build here is part of the loop body. */
1910 gfc_start_block (&block);
1912 /* Cycle and exit statements are implemented with gotos. */
1913 cycle_label = gfc_build_label_decl (NULL_TREE);
1914 exit_label = gfc_build_label_decl (NULL_TREE);
1916 /* Put the labels where they can be found later. See gfc_trans_do(). */
1917 code->cycle_label = cycle_label;
1918 code->exit_label = exit_label;
1920 /* Create a GIMPLE version of the exit condition. */
1921 gfc_init_se (&cond, NULL);
1922 gfc_conv_expr_val (&cond, code->expr1);
1923 gfc_add_block_to_block (&block, &cond.pre);
1924 cond.expr = fold_build1_loc (code->expr1->where.lb->location,
1925 TRUTH_NOT_EXPR, TREE_TYPE (cond.expr), cond.expr);
1927 /* Build "IF (! cond) GOTO exit_label". */
1928 tmp = build1_v (GOTO_EXPR, exit_label);
1929 TREE_USED (exit_label) = 1;
1930 tmp = fold_build3_loc (code->expr1->where.lb->location, COND_EXPR,
1931 void_type_node, cond.expr, tmp,
1932 build_empty_stmt (code->expr1->where.lb->location));
1933 gfc_add_expr_to_block (&block, tmp);
1935 /* The main body of the loop. */
1936 tmp = gfc_trans_code (code->block->next);
1937 gfc_add_expr_to_block (&block, tmp);
1939 /* Label for cycle statements (if needed). */
1940 if (TREE_USED (cycle_label))
1942 tmp = build1_v (LABEL_EXPR, cycle_label);
1943 gfc_add_expr_to_block (&block, tmp);
1946 /* End of loop body. */
1947 tmp = gfc_finish_block (&block);
1949 gfc_init_block (&block);
1950 /* Build the loop. */
1951 tmp = fold_build1_loc (code->expr1->where.lb->location, LOOP_EXPR,
1952 void_type_node, tmp);
1953 gfc_add_expr_to_block (&block, tmp);
1955 /* Add the exit label. */
1956 tmp = build1_v (LABEL_EXPR, exit_label);
1957 gfc_add_expr_to_block (&block, tmp);
1959 return gfc_finish_block (&block);
1963 /* Translate the SELECT CASE construct for INTEGER case expressions,
1964 without killing all potential optimizations. The problem is that
1965 Fortran allows unbounded cases, but the back-end does not, so we
1966 need to intercept those before we enter the equivalent SWITCH_EXPR
1967 we can build.
1969 For example, we translate this,
1971 SELECT CASE (expr)
1972 CASE (:100,101,105:115)
1973 block_1
1974 CASE (190:199,200:)
1975 block_2
1976 CASE (300)
1977 block_3
1978 CASE DEFAULT
1979 block_4
1980 END SELECT
1982 to the GENERIC equivalent,
1984 switch (expr)
1986 case (minimum value for typeof(expr) ... 100:
1987 case 101:
1988 case 105 ... 114:
1989 block1:
1990 goto end_label;
1992 case 200 ... (maximum value for typeof(expr):
1993 case 190 ... 199:
1994 block2;
1995 goto end_label;
1997 case 300:
1998 block_3;
1999 goto end_label;
2001 default:
2002 block_4;
2003 goto end_label;
2006 end_label: */
2008 static tree
2009 gfc_trans_integer_select (gfc_code * code)
2011 gfc_code *c;
2012 gfc_case *cp;
2013 tree end_label;
2014 tree tmp;
2015 gfc_se se;
2016 stmtblock_t block;
2017 stmtblock_t body;
2019 gfc_start_block (&block);
2021 /* Calculate the switch expression. */
2022 gfc_init_se (&se, NULL);
2023 gfc_conv_expr_val (&se, code->expr1);
2024 gfc_add_block_to_block (&block, &se.pre);
2026 end_label = gfc_build_label_decl (NULL_TREE);
2028 gfc_init_block (&body);
2030 for (c = code->block; c; c = c->block)
2032 for (cp = c->ext.block.case_list; cp; cp = cp->next)
2034 tree low, high;
2035 tree label;
2037 /* Assume it's the default case. */
2038 low = high = NULL_TREE;
2040 if (cp->low)
2042 low = gfc_conv_mpz_to_tree (cp->low->value.integer,
2043 cp->low->ts.kind);
2045 /* If there's only a lower bound, set the high bound to the
2046 maximum value of the case expression. */
2047 if (!cp->high)
2048 high = TYPE_MAX_VALUE (TREE_TYPE (se.expr));
2051 if (cp->high)
2053 /* Three cases are possible here:
2055 1) There is no lower bound, e.g. CASE (:N).
2056 2) There is a lower bound .NE. high bound, that is
2057 a case range, e.g. CASE (N:M) where M>N (we make
2058 sure that M>N during type resolution).
2059 3) There is a lower bound, and it has the same value
2060 as the high bound, e.g. CASE (N:N). This is our
2061 internal representation of CASE(N).
2063 In the first and second case, we need to set a value for
2064 high. In the third case, we don't because the GCC middle
2065 end represents a single case value by just letting high be
2066 a NULL_TREE. We can't do that because we need to be able
2067 to represent unbounded cases. */
2069 if (!cp->low
2070 || (cp->low
2071 && mpz_cmp (cp->low->value.integer,
2072 cp->high->value.integer) != 0))
2073 high = gfc_conv_mpz_to_tree (cp->high->value.integer,
2074 cp->high->ts.kind);
2076 /* Unbounded case. */
2077 if (!cp->low)
2078 low = TYPE_MIN_VALUE (TREE_TYPE (se.expr));
2081 /* Build a label. */
2082 label = gfc_build_label_decl (NULL_TREE);
2084 /* Add this case label.
2085 Add parameter 'label', make it match GCC backend. */
2086 tmp = build_case_label (low, high, label);
2087 gfc_add_expr_to_block (&body, tmp);
2090 /* Add the statements for this case. */
2091 tmp = gfc_trans_code (c->next);
2092 gfc_add_expr_to_block (&body, tmp);
2094 /* Break to the end of the construct. */
2095 tmp = build1_v (GOTO_EXPR, end_label);
2096 gfc_add_expr_to_block (&body, tmp);
2099 tmp = gfc_finish_block (&body);
2100 tmp = fold_build3_loc (input_location, SWITCH_EXPR, NULL_TREE,
2101 se.expr, tmp, NULL_TREE);
2102 gfc_add_expr_to_block (&block, tmp);
2104 tmp = build1_v (LABEL_EXPR, end_label);
2105 gfc_add_expr_to_block (&block, tmp);
2107 return gfc_finish_block (&block);
2111 /* Translate the SELECT CASE construct for LOGICAL case expressions.
2113 There are only two cases possible here, even though the standard
2114 does allow three cases in a LOGICAL SELECT CASE construct: .TRUE.,
2115 .FALSE., and DEFAULT.
2117 We never generate more than two blocks here. Instead, we always
2118 try to eliminate the DEFAULT case. This way, we can translate this
2119 kind of SELECT construct to a simple
2121 if {} else {};
2123 expression in GENERIC. */
2125 static tree
2126 gfc_trans_logical_select (gfc_code * code)
2128 gfc_code *c;
2129 gfc_code *t, *f, *d;
2130 gfc_case *cp;
2131 gfc_se se;
2132 stmtblock_t block;
2134 /* Assume we don't have any cases at all. */
2135 t = f = d = NULL;
2137 /* Now see which ones we actually do have. We can have at most two
2138 cases in a single case list: one for .TRUE. and one for .FALSE.
2139 The default case is always separate. If the cases for .TRUE. and
2140 .FALSE. are in the same case list, the block for that case list
2141 always executed, and we don't generate code a COND_EXPR. */
2142 for (c = code->block; c; c = c->block)
2144 for (cp = c->ext.block.case_list; cp; cp = cp->next)
2146 if (cp->low)
2148 if (cp->low->value.logical == 0) /* .FALSE. */
2149 f = c;
2150 else /* if (cp->value.logical != 0), thus .TRUE. */
2151 t = c;
2153 else
2154 d = c;
2158 /* Start a new block. */
2159 gfc_start_block (&block);
2161 /* Calculate the switch expression. We always need to do this
2162 because it may have side effects. */
2163 gfc_init_se (&se, NULL);
2164 gfc_conv_expr_val (&se, code->expr1);
2165 gfc_add_block_to_block (&block, &se.pre);
2167 if (t == f && t != NULL)
2169 /* Cases for .TRUE. and .FALSE. are in the same block. Just
2170 translate the code for these cases, append it to the current
2171 block. */
2172 gfc_add_expr_to_block (&block, gfc_trans_code (t->next));
2174 else
2176 tree true_tree, false_tree, stmt;
2178 true_tree = build_empty_stmt (input_location);
2179 false_tree = build_empty_stmt (input_location);
2181 /* If we have a case for .TRUE. and for .FALSE., discard the default case.
2182 Otherwise, if .TRUE. or .FALSE. is missing and there is a default case,
2183 make the missing case the default case. */
2184 if (t != NULL && f != NULL)
2185 d = NULL;
2186 else if (d != NULL)
2188 if (t == NULL)
2189 t = d;
2190 else
2191 f = d;
2194 /* Translate the code for each of these blocks, and append it to
2195 the current block. */
2196 if (t != NULL)
2197 true_tree = gfc_trans_code (t->next);
2199 if (f != NULL)
2200 false_tree = gfc_trans_code (f->next);
2202 stmt = fold_build3_loc (input_location, COND_EXPR, void_type_node,
2203 se.expr, true_tree, false_tree);
2204 gfc_add_expr_to_block (&block, stmt);
2207 return gfc_finish_block (&block);
2211 /* The jump table types are stored in static variables to avoid
2212 constructing them from scratch every single time. */
2213 static GTY(()) tree select_struct[2];
2215 /* Translate the SELECT CASE construct for CHARACTER case expressions.
2216 Instead of generating compares and jumps, it is far simpler to
2217 generate a data structure describing the cases in order and call a
2218 library subroutine that locates the right case.
2219 This is particularly true because this is the only case where we
2220 might have to dispose of a temporary.
2221 The library subroutine returns a pointer to jump to or NULL if no
2222 branches are to be taken. */
2224 static tree
2225 gfc_trans_character_select (gfc_code *code)
2227 tree init, end_label, tmp, type, case_num, label, fndecl;
2228 stmtblock_t block, body;
2229 gfc_case *cp, *d;
2230 gfc_code *c;
2231 gfc_se se, expr1se;
2232 int n, k;
2233 vec<constructor_elt, va_gc> *inits = NULL;
2235 tree pchartype = gfc_get_pchar_type (code->expr1->ts.kind);
2237 /* The jump table types are stored in static variables to avoid
2238 constructing them from scratch every single time. */
2239 static tree ss_string1[2], ss_string1_len[2];
2240 static tree ss_string2[2], ss_string2_len[2];
2241 static tree ss_target[2];
2243 cp = code->block->ext.block.case_list;
2244 while (cp->left != NULL)
2245 cp = cp->left;
2247 /* Generate the body */
2248 gfc_start_block (&block);
2249 gfc_init_se (&expr1se, NULL);
2250 gfc_conv_expr_reference (&expr1se, code->expr1);
2252 gfc_add_block_to_block (&block, &expr1se.pre);
2254 end_label = gfc_build_label_decl (NULL_TREE);
2256 gfc_init_block (&body);
2258 /* Attempt to optimize length 1 selects. */
2259 if (integer_onep (expr1se.string_length))
2261 for (d = cp; d; d = d->right)
2263 int i;
2264 if (d->low)
2266 gcc_assert (d->low->expr_type == EXPR_CONSTANT
2267 && d->low->ts.type == BT_CHARACTER);
2268 if (d->low->value.character.length > 1)
2270 for (i = 1; i < d->low->value.character.length; i++)
2271 if (d->low->value.character.string[i] != ' ')
2272 break;
2273 if (i != d->low->value.character.length)
2275 if (optimize && d->high && i == 1)
2277 gcc_assert (d->high->expr_type == EXPR_CONSTANT
2278 && d->high->ts.type == BT_CHARACTER);
2279 if (d->high->value.character.length > 1
2280 && (d->low->value.character.string[0]
2281 == d->high->value.character.string[0])
2282 && d->high->value.character.string[1] != ' '
2283 && ((d->low->value.character.string[1] < ' ')
2284 == (d->high->value.character.string[1]
2285 < ' ')))
2286 continue;
2288 break;
2292 if (d->high)
2294 gcc_assert (d->high->expr_type == EXPR_CONSTANT
2295 && d->high->ts.type == BT_CHARACTER);
2296 if (d->high->value.character.length > 1)
2298 for (i = 1; i < d->high->value.character.length; i++)
2299 if (d->high->value.character.string[i] != ' ')
2300 break;
2301 if (i != d->high->value.character.length)
2302 break;
2306 if (d == NULL)
2308 tree ctype = gfc_get_char_type (code->expr1->ts.kind);
2310 for (c = code->block; c; c = c->block)
2312 for (cp = c->ext.block.case_list; cp; cp = cp->next)
2314 tree low, high;
2315 tree label;
2316 gfc_char_t r;
2318 /* Assume it's the default case. */
2319 low = high = NULL_TREE;
2321 if (cp->low)
2323 /* CASE ('ab') or CASE ('ab':'az') will never match
2324 any length 1 character. */
2325 if (cp->low->value.character.length > 1
2326 && cp->low->value.character.string[1] != ' ')
2327 continue;
2329 if (cp->low->value.character.length > 0)
2330 r = cp->low->value.character.string[0];
2331 else
2332 r = ' ';
2333 low = build_int_cst (ctype, r);
2335 /* If there's only a lower bound, set the high bound
2336 to the maximum value of the case expression. */
2337 if (!cp->high)
2338 high = TYPE_MAX_VALUE (ctype);
2341 if (cp->high)
2343 if (!cp->low
2344 || (cp->low->value.character.string[0]
2345 != cp->high->value.character.string[0]))
2347 if (cp->high->value.character.length > 0)
2348 r = cp->high->value.character.string[0];
2349 else
2350 r = ' ';
2351 high = build_int_cst (ctype, r);
2354 /* Unbounded case. */
2355 if (!cp->low)
2356 low = TYPE_MIN_VALUE (ctype);
2359 /* Build a label. */
2360 label = gfc_build_label_decl (NULL_TREE);
2362 /* Add this case label.
2363 Add parameter 'label', make it match GCC backend. */
2364 tmp = build_case_label (low, high, label);
2365 gfc_add_expr_to_block (&body, tmp);
2368 /* Add the statements for this case. */
2369 tmp = gfc_trans_code (c->next);
2370 gfc_add_expr_to_block (&body, tmp);
2372 /* Break to the end of the construct. */
2373 tmp = build1_v (GOTO_EXPR, end_label);
2374 gfc_add_expr_to_block (&body, tmp);
2377 tmp = gfc_string_to_single_character (expr1se.string_length,
2378 expr1se.expr,
2379 code->expr1->ts.kind);
2380 case_num = gfc_create_var (ctype, "case_num");
2381 gfc_add_modify (&block, case_num, tmp);
2383 gfc_add_block_to_block (&block, &expr1se.post);
2385 tmp = gfc_finish_block (&body);
2386 tmp = fold_build3_loc (input_location, SWITCH_EXPR, NULL_TREE,
2387 case_num, tmp, NULL_TREE);
2388 gfc_add_expr_to_block (&block, tmp);
2390 tmp = build1_v (LABEL_EXPR, end_label);
2391 gfc_add_expr_to_block (&block, tmp);
2393 return gfc_finish_block (&block);
2397 if (code->expr1->ts.kind == 1)
2398 k = 0;
2399 else if (code->expr1->ts.kind == 4)
2400 k = 1;
2401 else
2402 gcc_unreachable ();
2404 if (select_struct[k] == NULL)
2406 tree *chain = NULL;
2407 select_struct[k] = make_node (RECORD_TYPE);
2409 if (code->expr1->ts.kind == 1)
2410 TYPE_NAME (select_struct[k]) = get_identifier ("_jump_struct_char1");
2411 else if (code->expr1->ts.kind == 4)
2412 TYPE_NAME (select_struct[k]) = get_identifier ("_jump_struct_char4");
2413 else
2414 gcc_unreachable ();
2416 #undef ADD_FIELD
2417 #define ADD_FIELD(NAME, TYPE) \
2418 ss_##NAME[k] = gfc_add_field_to_struct (select_struct[k], \
2419 get_identifier (stringize(NAME)), \
2420 TYPE, \
2421 &chain)
2423 ADD_FIELD (string1, pchartype);
2424 ADD_FIELD (string1_len, gfc_charlen_type_node);
2426 ADD_FIELD (string2, pchartype);
2427 ADD_FIELD (string2_len, gfc_charlen_type_node);
2429 ADD_FIELD (target, integer_type_node);
2430 #undef ADD_FIELD
2432 gfc_finish_type (select_struct[k]);
2435 n = 0;
2436 for (d = cp; d; d = d->right)
2437 d->n = n++;
2439 for (c = code->block; c; c = c->block)
2441 for (d = c->ext.block.case_list; d; d = d->next)
2443 label = gfc_build_label_decl (NULL_TREE);
2444 tmp = build_case_label ((d->low == NULL && d->high == NULL)
2445 ? NULL
2446 : build_int_cst (integer_type_node, d->n),
2447 NULL, label);
2448 gfc_add_expr_to_block (&body, tmp);
2451 tmp = gfc_trans_code (c->next);
2452 gfc_add_expr_to_block (&body, tmp);
2454 tmp = build1_v (GOTO_EXPR, end_label);
2455 gfc_add_expr_to_block (&body, tmp);
2458 /* Generate the structure describing the branches */
2459 for (d = cp; d; d = d->right)
2461 vec<constructor_elt, va_gc> *node = NULL;
2463 gfc_init_se (&se, NULL);
2465 if (d->low == NULL)
2467 CONSTRUCTOR_APPEND_ELT (node, ss_string1[k], null_pointer_node);
2468 CONSTRUCTOR_APPEND_ELT (node, ss_string1_len[k], integer_zero_node);
2470 else
2472 gfc_conv_expr_reference (&se, d->low);
2474 CONSTRUCTOR_APPEND_ELT (node, ss_string1[k], se.expr);
2475 CONSTRUCTOR_APPEND_ELT (node, ss_string1_len[k], se.string_length);
2478 if (d->high == NULL)
2480 CONSTRUCTOR_APPEND_ELT (node, ss_string2[k], null_pointer_node);
2481 CONSTRUCTOR_APPEND_ELT (node, ss_string2_len[k], integer_zero_node);
2483 else
2485 gfc_init_se (&se, NULL);
2486 gfc_conv_expr_reference (&se, d->high);
2488 CONSTRUCTOR_APPEND_ELT (node, ss_string2[k], se.expr);
2489 CONSTRUCTOR_APPEND_ELT (node, ss_string2_len[k], se.string_length);
2492 CONSTRUCTOR_APPEND_ELT (node, ss_target[k],
2493 build_int_cst (integer_type_node, d->n));
2495 tmp = build_constructor (select_struct[k], node);
2496 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, tmp);
2499 type = build_array_type (select_struct[k],
2500 build_index_type (size_int (n-1)));
2502 init = build_constructor (type, inits);
2503 TREE_CONSTANT (init) = 1;
2504 TREE_STATIC (init) = 1;
2505 /* Create a static variable to hold the jump table. */
2506 tmp = gfc_create_var (type, "jumptable");
2507 TREE_CONSTANT (tmp) = 1;
2508 TREE_STATIC (tmp) = 1;
2509 TREE_READONLY (tmp) = 1;
2510 DECL_INITIAL (tmp) = init;
2511 init = tmp;
2513 /* Build the library call */
2514 init = gfc_build_addr_expr (pvoid_type_node, init);
2516 if (code->expr1->ts.kind == 1)
2517 fndecl = gfor_fndecl_select_string;
2518 else if (code->expr1->ts.kind == 4)
2519 fndecl = gfor_fndecl_select_string_char4;
2520 else
2521 gcc_unreachable ();
2523 tmp = build_call_expr_loc (input_location,
2524 fndecl, 4, init,
2525 build_int_cst (gfc_charlen_type_node, n),
2526 expr1se.expr, expr1se.string_length);
2527 case_num = gfc_create_var (integer_type_node, "case_num");
2528 gfc_add_modify (&block, case_num, tmp);
2530 gfc_add_block_to_block (&block, &expr1se.post);
2532 tmp = gfc_finish_block (&body);
2533 tmp = fold_build3_loc (input_location, SWITCH_EXPR, NULL_TREE,
2534 case_num, tmp, NULL_TREE);
2535 gfc_add_expr_to_block (&block, tmp);
2537 tmp = build1_v (LABEL_EXPR, end_label);
2538 gfc_add_expr_to_block (&block, tmp);
2540 return gfc_finish_block (&block);
2544 /* Translate the three variants of the SELECT CASE construct.
2546 SELECT CASEs with INTEGER case expressions can be translated to an
2547 equivalent GENERIC switch statement, and for LOGICAL case
2548 expressions we build one or two if-else compares.
2550 SELECT CASEs with CHARACTER case expressions are a whole different
2551 story, because they don't exist in GENERIC. So we sort them and
2552 do a binary search at runtime.
2554 Fortran has no BREAK statement, and it does not allow jumps from
2555 one case block to another. That makes things a lot easier for
2556 the optimizers. */
2558 tree
2559 gfc_trans_select (gfc_code * code)
2561 stmtblock_t block;
2562 tree body;
2563 tree exit_label;
2565 gcc_assert (code && code->expr1);
2566 gfc_init_block (&block);
2568 /* Build the exit label and hang it in. */
2569 exit_label = gfc_build_label_decl (NULL_TREE);
2570 code->exit_label = exit_label;
2572 /* Empty SELECT constructs are legal. */
2573 if (code->block == NULL)
2574 body = build_empty_stmt (input_location);
2576 /* Select the correct translation function. */
2577 else
2578 switch (code->expr1->ts.type)
2580 case BT_LOGICAL:
2581 body = gfc_trans_logical_select (code);
2582 break;
2584 case BT_INTEGER:
2585 body = gfc_trans_integer_select (code);
2586 break;
2588 case BT_CHARACTER:
2589 body = gfc_trans_character_select (code);
2590 break;
2592 default:
2593 gfc_internal_error ("gfc_trans_select(): Bad type for case expr.");
2594 /* Not reached */
2597 /* Build everything together. */
2598 gfc_add_expr_to_block (&block, body);
2599 gfc_add_expr_to_block (&block, build1_v (LABEL_EXPR, exit_label));
2601 return gfc_finish_block (&block);
2605 /* Traversal function to substitute a replacement symtree if the symbol
2606 in the expression is the same as that passed. f == 2 signals that
2607 that variable itself is not to be checked - only the references.
2608 This group of functions is used when the variable expression in a
2609 FORALL assignment has internal references. For example:
2610 FORALL (i = 1:4) p(p(i)) = i
2611 The only recourse here is to store a copy of 'p' for the index
2612 expression. */
2614 static gfc_symtree *new_symtree;
2615 static gfc_symtree *old_symtree;
2617 static bool
2618 forall_replace (gfc_expr *expr, gfc_symbol *sym, int *f)
2620 if (expr->expr_type != EXPR_VARIABLE)
2621 return false;
2623 if (*f == 2)
2624 *f = 1;
2625 else if (expr->symtree->n.sym == sym)
2626 expr->symtree = new_symtree;
2628 return false;
2631 static void
2632 forall_replace_symtree (gfc_expr *e, gfc_symbol *sym, int f)
2634 gfc_traverse_expr (e, sym, forall_replace, f);
2637 static bool
2638 forall_restore (gfc_expr *expr,
2639 gfc_symbol *sym ATTRIBUTE_UNUSED,
2640 int *f ATTRIBUTE_UNUSED)
2642 if (expr->expr_type != EXPR_VARIABLE)
2643 return false;
2645 if (expr->symtree == new_symtree)
2646 expr->symtree = old_symtree;
2648 return false;
2651 static void
2652 forall_restore_symtree (gfc_expr *e)
2654 gfc_traverse_expr (e, NULL, forall_restore, 0);
2657 static void
2658 forall_make_variable_temp (gfc_code *c, stmtblock_t *pre, stmtblock_t *post)
2660 gfc_se tse;
2661 gfc_se rse;
2662 gfc_expr *e;
2663 gfc_symbol *new_sym;
2664 gfc_symbol *old_sym;
2665 gfc_symtree *root;
2666 tree tmp;
2668 /* Build a copy of the lvalue. */
2669 old_symtree = c->expr1->symtree;
2670 old_sym = old_symtree->n.sym;
2671 e = gfc_lval_expr_from_sym (old_sym);
2672 if (old_sym->attr.dimension)
2674 gfc_init_se (&tse, NULL);
2675 gfc_conv_subref_array_arg (&tse, e, 0, INTENT_IN, false);
2676 gfc_add_block_to_block (pre, &tse.pre);
2677 gfc_add_block_to_block (post, &tse.post);
2678 tse.expr = build_fold_indirect_ref_loc (input_location, tse.expr);
2680 if (e->ts.type != BT_CHARACTER)
2682 /* Use the variable offset for the temporary. */
2683 tmp = gfc_conv_array_offset (old_sym->backend_decl);
2684 gfc_conv_descriptor_offset_set (pre, tse.expr, tmp);
2687 else
2689 gfc_init_se (&tse, NULL);
2690 gfc_init_se (&rse, NULL);
2691 gfc_conv_expr (&rse, e);
2692 if (e->ts.type == BT_CHARACTER)
2694 tse.string_length = rse.string_length;
2695 tmp = gfc_get_character_type_len (gfc_default_character_kind,
2696 tse.string_length);
2697 tse.expr = gfc_conv_string_tmp (&tse, build_pointer_type (tmp),
2698 rse.string_length);
2699 gfc_add_block_to_block (pre, &tse.pre);
2700 gfc_add_block_to_block (post, &tse.post);
2702 else
2704 tmp = gfc_typenode_for_spec (&e->ts);
2705 tse.expr = gfc_create_var (tmp, "temp");
2708 tmp = gfc_trans_scalar_assign (&tse, &rse, e->ts, true,
2709 e->expr_type == EXPR_VARIABLE, true);
2710 gfc_add_expr_to_block (pre, tmp);
2712 gfc_free_expr (e);
2714 /* Create a new symbol to represent the lvalue. */
2715 new_sym = gfc_new_symbol (old_sym->name, NULL);
2716 new_sym->ts = old_sym->ts;
2717 new_sym->attr.referenced = 1;
2718 new_sym->attr.temporary = 1;
2719 new_sym->attr.dimension = old_sym->attr.dimension;
2720 new_sym->attr.flavor = old_sym->attr.flavor;
2722 /* Use the temporary as the backend_decl. */
2723 new_sym->backend_decl = tse.expr;
2725 /* Create a fake symtree for it. */
2726 root = NULL;
2727 new_symtree = gfc_new_symtree (&root, old_sym->name);
2728 new_symtree->n.sym = new_sym;
2729 gcc_assert (new_symtree == root);
2731 /* Go through the expression reference replacing the old_symtree
2732 with the new. */
2733 forall_replace_symtree (c->expr1, old_sym, 2);
2735 /* Now we have made this temporary, we might as well use it for
2736 the right hand side. */
2737 forall_replace_symtree (c->expr2, old_sym, 1);
2741 /* Handles dependencies in forall assignments. */
2742 static int
2743 check_forall_dependencies (gfc_code *c, stmtblock_t *pre, stmtblock_t *post)
2745 gfc_ref *lref;
2746 gfc_ref *rref;
2747 int need_temp;
2748 gfc_symbol *lsym;
2750 lsym = c->expr1->symtree->n.sym;
2751 need_temp = gfc_check_dependency (c->expr1, c->expr2, 0);
2753 /* Now check for dependencies within the 'variable'
2754 expression itself. These are treated by making a complete
2755 copy of variable and changing all the references to it
2756 point to the copy instead. Note that the shallow copy of
2757 the variable will not suffice for derived types with
2758 pointer components. We therefore leave these to their
2759 own devices. */
2760 if (lsym->ts.type == BT_DERIVED
2761 && lsym->ts.u.derived->attr.pointer_comp)
2762 return need_temp;
2764 new_symtree = NULL;
2765 if (find_forall_index (c->expr1, lsym, 2))
2767 forall_make_variable_temp (c, pre, post);
2768 need_temp = 0;
2771 /* Substrings with dependencies are treated in the same
2772 way. */
2773 if (c->expr1->ts.type == BT_CHARACTER
2774 && c->expr1->ref
2775 && c->expr2->expr_type == EXPR_VARIABLE
2776 && lsym == c->expr2->symtree->n.sym)
2778 for (lref = c->expr1->ref; lref; lref = lref->next)
2779 if (lref->type == REF_SUBSTRING)
2780 break;
2781 for (rref = c->expr2->ref; rref; rref = rref->next)
2782 if (rref->type == REF_SUBSTRING)
2783 break;
2785 if (rref && lref
2786 && gfc_dep_compare_expr (rref->u.ss.start, lref->u.ss.start) < 0)
2788 forall_make_variable_temp (c, pre, post);
2789 need_temp = 0;
2792 return need_temp;
2796 static void
2797 cleanup_forall_symtrees (gfc_code *c)
2799 forall_restore_symtree (c->expr1);
2800 forall_restore_symtree (c->expr2);
2801 free (new_symtree->n.sym);
2802 free (new_symtree);
2806 /* Generate the loops for a FORALL block, specified by FORALL_TMP. BODY
2807 is the contents of the FORALL block/stmt to be iterated. MASK_FLAG
2808 indicates whether we should generate code to test the FORALLs mask
2809 array. OUTER is the loop header to be used for initializing mask
2810 indices.
2812 The generated loop format is:
2813 count = (end - start + step) / step
2814 loopvar = start
2815 while (1)
2817 if (count <=0 )
2818 goto end_of_loop
2819 <body>
2820 loopvar += step
2821 count --
2823 end_of_loop: */
2825 static tree
2826 gfc_trans_forall_loop (forall_info *forall_tmp, tree body,
2827 int mask_flag, stmtblock_t *outer)
2829 int n, nvar;
2830 tree tmp;
2831 tree cond;
2832 stmtblock_t block;
2833 tree exit_label;
2834 tree count;
2835 tree var, start, end, step;
2836 iter_info *iter;
2838 /* Initialize the mask index outside the FORALL nest. */
2839 if (mask_flag && forall_tmp->mask)
2840 gfc_add_modify (outer, forall_tmp->maskindex, gfc_index_zero_node);
2842 iter = forall_tmp->this_loop;
2843 nvar = forall_tmp->nvar;
2844 for (n = 0; n < nvar; n++)
2846 var = iter->var;
2847 start = iter->start;
2848 end = iter->end;
2849 step = iter->step;
2851 exit_label = gfc_build_label_decl (NULL_TREE);
2852 TREE_USED (exit_label) = 1;
2854 /* The loop counter. */
2855 count = gfc_create_var (TREE_TYPE (var), "count");
2857 /* The body of the loop. */
2858 gfc_init_block (&block);
2860 /* The exit condition. */
2861 cond = fold_build2_loc (input_location, LE_EXPR, boolean_type_node,
2862 count, build_int_cst (TREE_TYPE (count), 0));
2863 if (forall_tmp->do_concurrent)
2864 cond = build2 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
2865 build_int_cst (integer_type_node,
2866 annot_expr_ivdep_kind));
2868 tmp = build1_v (GOTO_EXPR, exit_label);
2869 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
2870 cond, tmp, build_empty_stmt (input_location));
2871 gfc_add_expr_to_block (&block, tmp);
2873 /* The main loop body. */
2874 gfc_add_expr_to_block (&block, body);
2876 /* Increment the loop variable. */
2877 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (var), var,
2878 step);
2879 gfc_add_modify (&block, var, tmp);
2881 /* Advance to the next mask element. Only do this for the
2882 innermost loop. */
2883 if (n == 0 && mask_flag && forall_tmp->mask)
2885 tree maskindex = forall_tmp->maskindex;
2886 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
2887 maskindex, gfc_index_one_node);
2888 gfc_add_modify (&block, maskindex, tmp);
2891 /* Decrement the loop counter. */
2892 tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (var), count,
2893 build_int_cst (TREE_TYPE (var), 1));
2894 gfc_add_modify (&block, count, tmp);
2896 body = gfc_finish_block (&block);
2898 /* Loop var initialization. */
2899 gfc_init_block (&block);
2900 gfc_add_modify (&block, var, start);
2903 /* Initialize the loop counter. */
2904 tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (var), step,
2905 start);
2906 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (var), end,
2907 tmp);
2908 tmp = fold_build2_loc (input_location, TRUNC_DIV_EXPR, TREE_TYPE (var),
2909 tmp, step);
2910 gfc_add_modify (&block, count, tmp);
2912 /* The loop expression. */
2913 tmp = build1_v (LOOP_EXPR, body);
2914 gfc_add_expr_to_block (&block, tmp);
2916 /* The exit label. */
2917 tmp = build1_v (LABEL_EXPR, exit_label);
2918 gfc_add_expr_to_block (&block, tmp);
2920 body = gfc_finish_block (&block);
2921 iter = iter->next;
2923 return body;
2927 /* Generate the body and loops according to MASK_FLAG. If MASK_FLAG
2928 is nonzero, the body is controlled by all masks in the forall nest.
2929 Otherwise, the innermost loop is not controlled by it's mask. This
2930 is used for initializing that mask. */
2932 static tree
2933 gfc_trans_nested_forall_loop (forall_info * nested_forall_info, tree body,
2934 int mask_flag)
2936 tree tmp;
2937 stmtblock_t header;
2938 forall_info *forall_tmp;
2939 tree mask, maskindex;
2941 gfc_start_block (&header);
2943 forall_tmp = nested_forall_info;
2944 while (forall_tmp != NULL)
2946 /* Generate body with masks' control. */
2947 if (mask_flag)
2949 mask = forall_tmp->mask;
2950 maskindex = forall_tmp->maskindex;
2952 /* If a mask was specified make the assignment conditional. */
2953 if (mask)
2955 tmp = gfc_build_array_ref (mask, maskindex, NULL);
2956 body = build3_v (COND_EXPR, tmp, body,
2957 build_empty_stmt (input_location));
2960 body = gfc_trans_forall_loop (forall_tmp, body, mask_flag, &header);
2961 forall_tmp = forall_tmp->prev_nest;
2962 mask_flag = 1;
2965 gfc_add_expr_to_block (&header, body);
2966 return gfc_finish_block (&header);
2970 /* Allocate data for holding a temporary array. Returns either a local
2971 temporary array or a pointer variable. */
2973 static tree
2974 gfc_do_allocate (tree bytesize, tree size, tree * pdata, stmtblock_t * pblock,
2975 tree elem_type)
2977 tree tmpvar;
2978 tree type;
2979 tree tmp;
2981 if (INTEGER_CST_P (size))
2982 tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
2983 size, gfc_index_one_node);
2984 else
2985 tmp = NULL_TREE;
2987 type = build_range_type (gfc_array_index_type, gfc_index_zero_node, tmp);
2988 type = build_array_type (elem_type, type);
2989 if (gfc_can_put_var_on_stack (bytesize))
2991 gcc_assert (INTEGER_CST_P (size));
2992 tmpvar = gfc_create_var (type, "temp");
2993 *pdata = NULL_TREE;
2995 else
2997 tmpvar = gfc_create_var (build_pointer_type (type), "temp");
2998 *pdata = convert (pvoid_type_node, tmpvar);
3000 tmp = gfc_call_malloc (pblock, TREE_TYPE (tmpvar), bytesize);
3001 gfc_add_modify (pblock, tmpvar, tmp);
3003 return tmpvar;
3007 /* Generate codes to copy the temporary to the actual lhs. */
3009 static tree
3010 generate_loop_for_temp_to_lhs (gfc_expr *expr, tree tmp1, tree count3,
3011 tree count1, tree wheremask, bool invert)
3013 gfc_ss *lss;
3014 gfc_se lse, rse;
3015 stmtblock_t block, body;
3016 gfc_loopinfo loop1;
3017 tree tmp;
3018 tree wheremaskexpr;
3020 /* Walk the lhs. */
3021 lss = gfc_walk_expr (expr);
3023 if (lss == gfc_ss_terminator)
3025 gfc_start_block (&block);
3027 gfc_init_se (&lse, NULL);
3029 /* Translate the expression. */
3030 gfc_conv_expr (&lse, expr);
3032 /* Form the expression for the temporary. */
3033 tmp = gfc_build_array_ref (tmp1, count1, NULL);
3035 /* Use the scalar assignment as is. */
3036 gfc_add_block_to_block (&block, &lse.pre);
3037 gfc_add_modify (&block, lse.expr, tmp);
3038 gfc_add_block_to_block (&block, &lse.post);
3040 /* Increment the count1. */
3041 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (count1),
3042 count1, gfc_index_one_node);
3043 gfc_add_modify (&block, count1, tmp);
3045 tmp = gfc_finish_block (&block);
3047 else
3049 gfc_start_block (&block);
3051 gfc_init_loopinfo (&loop1);
3052 gfc_init_se (&rse, NULL);
3053 gfc_init_se (&lse, NULL);
3055 /* Associate the lss with the loop. */
3056 gfc_add_ss_to_loop (&loop1, lss);
3058 /* Calculate the bounds of the scalarization. */
3059 gfc_conv_ss_startstride (&loop1);
3060 /* Setup the scalarizing loops. */
3061 gfc_conv_loop_setup (&loop1, &expr->where);
3063 gfc_mark_ss_chain_used (lss, 1);
3065 /* Start the scalarized loop body. */
3066 gfc_start_scalarized_body (&loop1, &body);
3068 /* Setup the gfc_se structures. */
3069 gfc_copy_loopinfo_to_se (&lse, &loop1);
3070 lse.ss = lss;
3072 /* Form the expression of the temporary. */
3073 if (lss != gfc_ss_terminator)
3074 rse.expr = gfc_build_array_ref (tmp1, count1, NULL);
3075 /* Translate expr. */
3076 gfc_conv_expr (&lse, expr);
3078 /* Use the scalar assignment. */
3079 rse.string_length = lse.string_length;
3080 tmp = gfc_trans_scalar_assign (&lse, &rse, expr->ts, false, true, true);
3082 /* Form the mask expression according to the mask tree list. */
3083 if (wheremask)
3085 wheremaskexpr = gfc_build_array_ref (wheremask, count3, NULL);
3086 if (invert)
3087 wheremaskexpr = fold_build1_loc (input_location, TRUTH_NOT_EXPR,
3088 TREE_TYPE (wheremaskexpr),
3089 wheremaskexpr);
3090 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
3091 wheremaskexpr, tmp,
3092 build_empty_stmt (input_location));
3095 gfc_add_expr_to_block (&body, tmp);
3097 /* Increment count1. */
3098 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
3099 count1, gfc_index_one_node);
3100 gfc_add_modify (&body, count1, tmp);
3102 /* Increment count3. */
3103 if (count3)
3105 tmp = fold_build2_loc (input_location, PLUS_EXPR,
3106 gfc_array_index_type, count3,
3107 gfc_index_one_node);
3108 gfc_add_modify (&body, count3, tmp);
3111 /* Generate the copying loops. */
3112 gfc_trans_scalarizing_loops (&loop1, &body);
3113 gfc_add_block_to_block (&block, &loop1.pre);
3114 gfc_add_block_to_block (&block, &loop1.post);
3115 gfc_cleanup_loop (&loop1);
3117 tmp = gfc_finish_block (&block);
3119 return tmp;
3123 /* Generate codes to copy rhs to the temporary. TMP1 is the address of
3124 temporary, LSS and RSS are formed in function compute_inner_temp_size(),
3125 and should not be freed. WHEREMASK is the conditional execution mask
3126 whose sense may be inverted by INVERT. */
3128 static tree
3129 generate_loop_for_rhs_to_temp (gfc_expr *expr2, tree tmp1, tree count3,
3130 tree count1, gfc_ss *lss, gfc_ss *rss,
3131 tree wheremask, bool invert)
3133 stmtblock_t block, body1;
3134 gfc_loopinfo loop;
3135 gfc_se lse;
3136 gfc_se rse;
3137 tree tmp;
3138 tree wheremaskexpr;
3140 gfc_start_block (&block);
3142 gfc_init_se (&rse, NULL);
3143 gfc_init_se (&lse, NULL);
3145 if (lss == gfc_ss_terminator)
3147 gfc_init_block (&body1);
3148 gfc_conv_expr (&rse, expr2);
3149 lse.expr = gfc_build_array_ref (tmp1, count1, NULL);
3151 else
3153 /* Initialize the loop. */
3154 gfc_init_loopinfo (&loop);
3156 /* We may need LSS to determine the shape of the expression. */
3157 gfc_add_ss_to_loop (&loop, lss);
3158 gfc_add_ss_to_loop (&loop, rss);
3160 gfc_conv_ss_startstride (&loop);
3161 gfc_conv_loop_setup (&loop, &expr2->where);
3163 gfc_mark_ss_chain_used (rss, 1);
3164 /* Start the loop body. */
3165 gfc_start_scalarized_body (&loop, &body1);
3167 /* Translate the expression. */
3168 gfc_copy_loopinfo_to_se (&rse, &loop);
3169 rse.ss = rss;
3170 gfc_conv_expr (&rse, expr2);
3172 /* Form the expression of the temporary. */
3173 lse.expr = gfc_build_array_ref (tmp1, count1, NULL);
3176 /* Use the scalar assignment. */
3177 lse.string_length = rse.string_length;
3178 tmp = gfc_trans_scalar_assign (&lse, &rse, expr2->ts, true,
3179 expr2->expr_type == EXPR_VARIABLE, true);
3181 /* Form the mask expression according to the mask tree list. */
3182 if (wheremask)
3184 wheremaskexpr = gfc_build_array_ref (wheremask, count3, NULL);
3185 if (invert)
3186 wheremaskexpr = fold_build1_loc (input_location, TRUTH_NOT_EXPR,
3187 TREE_TYPE (wheremaskexpr),
3188 wheremaskexpr);
3189 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
3190 wheremaskexpr, tmp,
3191 build_empty_stmt (input_location));
3194 gfc_add_expr_to_block (&body1, tmp);
3196 if (lss == gfc_ss_terminator)
3198 gfc_add_block_to_block (&block, &body1);
3200 /* Increment count1. */
3201 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (count1),
3202 count1, gfc_index_one_node);
3203 gfc_add_modify (&block, count1, tmp);
3205 else
3207 /* Increment count1. */
3208 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
3209 count1, gfc_index_one_node);
3210 gfc_add_modify (&body1, count1, tmp);
3212 /* Increment count3. */
3213 if (count3)
3215 tmp = fold_build2_loc (input_location, PLUS_EXPR,
3216 gfc_array_index_type,
3217 count3, gfc_index_one_node);
3218 gfc_add_modify (&body1, count3, tmp);
3221 /* Generate the copying loops. */
3222 gfc_trans_scalarizing_loops (&loop, &body1);
3224 gfc_add_block_to_block (&block, &loop.pre);
3225 gfc_add_block_to_block (&block, &loop.post);
3227 gfc_cleanup_loop (&loop);
3228 /* TODO: Reuse lss and rss when copying temp->lhs. Need to be careful
3229 as tree nodes in SS may not be valid in different scope. */
3232 tmp = gfc_finish_block (&block);
3233 return tmp;
3237 /* Calculate the size of temporary needed in the assignment inside forall.
3238 LSS and RSS are filled in this function. */
3240 static tree
3241 compute_inner_temp_size (gfc_expr *expr1, gfc_expr *expr2,
3242 stmtblock_t * pblock,
3243 gfc_ss **lss, gfc_ss **rss)
3245 gfc_loopinfo loop;
3246 tree size;
3247 int i;
3248 int save_flag;
3249 tree tmp;
3251 *lss = gfc_walk_expr (expr1);
3252 *rss = NULL;
3254 size = gfc_index_one_node;
3255 if (*lss != gfc_ss_terminator)
3257 gfc_init_loopinfo (&loop);
3259 /* Walk the RHS of the expression. */
3260 *rss = gfc_walk_expr (expr2);
3261 if (*rss == gfc_ss_terminator)
3262 /* The rhs is scalar. Add a ss for the expression. */
3263 *rss = gfc_get_scalar_ss (gfc_ss_terminator, expr2);
3265 /* Associate the SS with the loop. */
3266 gfc_add_ss_to_loop (&loop, *lss);
3267 /* We don't actually need to add the rhs at this point, but it might
3268 make guessing the loop bounds a bit easier. */
3269 gfc_add_ss_to_loop (&loop, *rss);
3271 /* We only want the shape of the expression, not rest of the junk
3272 generated by the scalarizer. */
3273 loop.array_parameter = 1;
3275 /* Calculate the bounds of the scalarization. */
3276 save_flag = gfc_option.rtcheck;
3277 gfc_option.rtcheck &= ~GFC_RTCHECK_BOUNDS;
3278 gfc_conv_ss_startstride (&loop);
3279 gfc_option.rtcheck = save_flag;
3280 gfc_conv_loop_setup (&loop, &expr2->where);
3282 /* Figure out how many elements we need. */
3283 for (i = 0; i < loop.dimen; i++)
3285 tmp = fold_build2_loc (input_location, MINUS_EXPR,
3286 gfc_array_index_type,
3287 gfc_index_one_node, loop.from[i]);
3288 tmp = fold_build2_loc (input_location, PLUS_EXPR,
3289 gfc_array_index_type, tmp, loop.to[i]);
3290 size = fold_build2_loc (input_location, MULT_EXPR,
3291 gfc_array_index_type, size, tmp);
3293 gfc_add_block_to_block (pblock, &loop.pre);
3294 size = gfc_evaluate_now (size, pblock);
3295 gfc_add_block_to_block (pblock, &loop.post);
3297 /* TODO: write a function that cleans up a loopinfo without freeing
3298 the SS chains. Currently a NOP. */
3301 return size;
3305 /* Calculate the overall iterator number of the nested forall construct.
3306 This routine actually calculates the number of times the body of the
3307 nested forall specified by NESTED_FORALL_INFO is executed and multiplies
3308 that by the expression INNER_SIZE. The BLOCK argument specifies the
3309 block in which to calculate the result, and the optional INNER_SIZE_BODY
3310 argument contains any statements that need to executed (inside the loop)
3311 to initialize or calculate INNER_SIZE. */
3313 static tree
3314 compute_overall_iter_number (forall_info *nested_forall_info, tree inner_size,
3315 stmtblock_t *inner_size_body, stmtblock_t *block)
3317 forall_info *forall_tmp = nested_forall_info;
3318 tree tmp, number;
3319 stmtblock_t body;
3321 /* We can eliminate the innermost unconditional loops with constant
3322 array bounds. */
3323 if (INTEGER_CST_P (inner_size))
3325 while (forall_tmp
3326 && !forall_tmp->mask
3327 && INTEGER_CST_P (forall_tmp->size))
3329 inner_size = fold_build2_loc (input_location, MULT_EXPR,
3330 gfc_array_index_type,
3331 inner_size, forall_tmp->size);
3332 forall_tmp = forall_tmp->prev_nest;
3335 /* If there are no loops left, we have our constant result. */
3336 if (!forall_tmp)
3337 return inner_size;
3340 /* Otherwise, create a temporary variable to compute the result. */
3341 number = gfc_create_var (gfc_array_index_type, "num");
3342 gfc_add_modify (block, number, gfc_index_zero_node);
3344 gfc_start_block (&body);
3345 if (inner_size_body)
3346 gfc_add_block_to_block (&body, inner_size_body);
3347 if (forall_tmp)
3348 tmp = fold_build2_loc (input_location, PLUS_EXPR,
3349 gfc_array_index_type, number, inner_size);
3350 else
3351 tmp = inner_size;
3352 gfc_add_modify (&body, number, tmp);
3353 tmp = gfc_finish_block (&body);
3355 /* Generate loops. */
3356 if (forall_tmp != NULL)
3357 tmp = gfc_trans_nested_forall_loop (forall_tmp, tmp, 1);
3359 gfc_add_expr_to_block (block, tmp);
3361 return number;
3365 /* Allocate temporary for forall construct. SIZE is the size of temporary
3366 needed. PTEMP1 is returned for space free. */
3368 static tree
3369 allocate_temp_for_forall_nest_1 (tree type, tree size, stmtblock_t * block,
3370 tree * ptemp1)
3372 tree bytesize;
3373 tree unit;
3374 tree tmp;
3376 unit = fold_convert (gfc_array_index_type, TYPE_SIZE_UNIT (type));
3377 if (!integer_onep (unit))
3378 bytesize = fold_build2_loc (input_location, MULT_EXPR,
3379 gfc_array_index_type, size, unit);
3380 else
3381 bytesize = size;
3383 *ptemp1 = NULL;
3384 tmp = gfc_do_allocate (bytesize, size, ptemp1, block, type);
3386 if (*ptemp1)
3387 tmp = build_fold_indirect_ref_loc (input_location, tmp);
3388 return tmp;
3392 /* Allocate temporary for forall construct according to the information in
3393 nested_forall_info. INNER_SIZE is the size of temporary needed in the
3394 assignment inside forall. PTEMP1 is returned for space free. */
3396 static tree
3397 allocate_temp_for_forall_nest (forall_info * nested_forall_info, tree type,
3398 tree inner_size, stmtblock_t * inner_size_body,
3399 stmtblock_t * block, tree * ptemp1)
3401 tree size;
3403 /* Calculate the total size of temporary needed in forall construct. */
3404 size = compute_overall_iter_number (nested_forall_info, inner_size,
3405 inner_size_body, block);
3407 return allocate_temp_for_forall_nest_1 (type, size, block, ptemp1);
3411 /* Handle assignments inside forall which need temporary.
3413 forall (i=start:end:stride; maskexpr)
3414 e<i> = f<i>
3415 end forall
3416 (where e,f<i> are arbitrary expressions possibly involving i
3417 and there is a dependency between e<i> and f<i>)
3418 Translates to:
3419 masktmp(:) = maskexpr(:)
3421 maskindex = 0;
3422 count1 = 0;
3423 num = 0;
3424 for (i = start; i <= end; i += stride)
3425 num += SIZE (f<i>)
3426 count1 = 0;
3427 ALLOCATE (tmp(num))
3428 for (i = start; i <= end; i += stride)
3430 if (masktmp[maskindex++])
3431 tmp[count1++] = f<i>
3433 maskindex = 0;
3434 count1 = 0;
3435 for (i = start; i <= end; i += stride)
3437 if (masktmp[maskindex++])
3438 e<i> = tmp[count1++]
3440 DEALLOCATE (tmp)
3442 static void
3443 gfc_trans_assign_need_temp (gfc_expr * expr1, gfc_expr * expr2,
3444 tree wheremask, bool invert,
3445 forall_info * nested_forall_info,
3446 stmtblock_t * block)
3448 tree type;
3449 tree inner_size;
3450 gfc_ss *lss, *rss;
3451 tree count, count1;
3452 tree tmp, tmp1;
3453 tree ptemp1;
3454 stmtblock_t inner_size_body;
3456 /* Create vars. count1 is the current iterator number of the nested
3457 forall. */
3458 count1 = gfc_create_var (gfc_array_index_type, "count1");
3460 /* Count is the wheremask index. */
3461 if (wheremask)
3463 count = gfc_create_var (gfc_array_index_type, "count");
3464 gfc_add_modify (block, count, gfc_index_zero_node);
3466 else
3467 count = NULL;
3469 /* Initialize count1. */
3470 gfc_add_modify (block, count1, gfc_index_zero_node);
3472 /* Calculate the size of temporary needed in the assignment. Return loop, lss
3473 and rss which are used in function generate_loop_for_rhs_to_temp(). */
3474 gfc_init_block (&inner_size_body);
3475 inner_size = compute_inner_temp_size (expr1, expr2, &inner_size_body,
3476 &lss, &rss);
3478 /* The type of LHS. Used in function allocate_temp_for_forall_nest */
3479 if (expr1->ts.type == BT_CHARACTER && expr1->ts.u.cl->length)
3481 if (!expr1->ts.u.cl->backend_decl)
3483 gfc_se tse;
3484 gfc_init_se (&tse, NULL);
3485 gfc_conv_expr (&tse, expr1->ts.u.cl->length);
3486 expr1->ts.u.cl->backend_decl = tse.expr;
3488 type = gfc_get_character_type_len (gfc_default_character_kind,
3489 expr1->ts.u.cl->backend_decl);
3491 else
3492 type = gfc_typenode_for_spec (&expr1->ts);
3494 /* Allocate temporary for nested forall construct according to the
3495 information in nested_forall_info and inner_size. */
3496 tmp1 = allocate_temp_for_forall_nest (nested_forall_info, type, inner_size,
3497 &inner_size_body, block, &ptemp1);
3499 /* Generate codes to copy rhs to the temporary . */
3500 tmp = generate_loop_for_rhs_to_temp (expr2, tmp1, count, count1, lss, rss,
3501 wheremask, invert);
3503 /* Generate body and loops according to the information in
3504 nested_forall_info. */
3505 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
3506 gfc_add_expr_to_block (block, tmp);
3508 /* Reset count1. */
3509 gfc_add_modify (block, count1, gfc_index_zero_node);
3511 /* Reset count. */
3512 if (wheremask)
3513 gfc_add_modify (block, count, gfc_index_zero_node);
3515 /* Generate codes to copy the temporary to lhs. */
3516 tmp = generate_loop_for_temp_to_lhs (expr1, tmp1, count, count1,
3517 wheremask, invert);
3519 /* Generate body and loops according to the information in
3520 nested_forall_info. */
3521 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
3522 gfc_add_expr_to_block (block, tmp);
3524 if (ptemp1)
3526 /* Free the temporary. */
3527 tmp = gfc_call_free (ptemp1);
3528 gfc_add_expr_to_block (block, tmp);
3533 /* Translate pointer assignment inside FORALL which need temporary. */
3535 static void
3536 gfc_trans_pointer_assign_need_temp (gfc_expr * expr1, gfc_expr * expr2,
3537 forall_info * nested_forall_info,
3538 stmtblock_t * block)
3540 tree type;
3541 tree inner_size;
3542 gfc_ss *lss, *rss;
3543 gfc_se lse;
3544 gfc_se rse;
3545 gfc_array_info *info;
3546 gfc_loopinfo loop;
3547 tree desc;
3548 tree parm;
3549 tree parmtype;
3550 stmtblock_t body;
3551 tree count;
3552 tree tmp, tmp1, ptemp1;
3554 count = gfc_create_var (gfc_array_index_type, "count");
3555 gfc_add_modify (block, count, gfc_index_zero_node);
3557 inner_size = gfc_index_one_node;
3558 lss = gfc_walk_expr (expr1);
3559 rss = gfc_walk_expr (expr2);
3560 if (lss == gfc_ss_terminator)
3562 type = gfc_typenode_for_spec (&expr1->ts);
3563 type = build_pointer_type (type);
3565 /* Allocate temporary for nested forall construct according to the
3566 information in nested_forall_info and inner_size. */
3567 tmp1 = allocate_temp_for_forall_nest (nested_forall_info, type,
3568 inner_size, NULL, block, &ptemp1);
3569 gfc_start_block (&body);
3570 gfc_init_se (&lse, NULL);
3571 lse.expr = gfc_build_array_ref (tmp1, count, NULL);
3572 gfc_init_se (&rse, NULL);
3573 rse.want_pointer = 1;
3574 gfc_conv_expr (&rse, expr2);
3575 gfc_add_block_to_block (&body, &rse.pre);
3576 gfc_add_modify (&body, lse.expr,
3577 fold_convert (TREE_TYPE (lse.expr), rse.expr));
3578 gfc_add_block_to_block (&body, &rse.post);
3580 /* Increment count. */
3581 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
3582 count, gfc_index_one_node);
3583 gfc_add_modify (&body, count, tmp);
3585 tmp = gfc_finish_block (&body);
3587 /* Generate body and loops according to the information in
3588 nested_forall_info. */
3589 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
3590 gfc_add_expr_to_block (block, tmp);
3592 /* Reset count. */
3593 gfc_add_modify (block, count, gfc_index_zero_node);
3595 gfc_start_block (&body);
3596 gfc_init_se (&lse, NULL);
3597 gfc_init_se (&rse, NULL);
3598 rse.expr = gfc_build_array_ref (tmp1, count, NULL);
3599 lse.want_pointer = 1;
3600 gfc_conv_expr (&lse, expr1);
3601 gfc_add_block_to_block (&body, &lse.pre);
3602 gfc_add_modify (&body, lse.expr, rse.expr);
3603 gfc_add_block_to_block (&body, &lse.post);
3604 /* Increment count. */
3605 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
3606 count, gfc_index_one_node);
3607 gfc_add_modify (&body, count, tmp);
3608 tmp = gfc_finish_block (&body);
3610 /* Generate body and loops according to the information in
3611 nested_forall_info. */
3612 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
3613 gfc_add_expr_to_block (block, tmp);
3615 else
3617 gfc_init_loopinfo (&loop);
3619 /* Associate the SS with the loop. */
3620 gfc_add_ss_to_loop (&loop, rss);
3622 /* Setup the scalarizing loops and bounds. */
3623 gfc_conv_ss_startstride (&loop);
3625 gfc_conv_loop_setup (&loop, &expr2->where);
3627 info = &rss->info->data.array;
3628 desc = info->descriptor;
3630 /* Make a new descriptor. */
3631 parmtype = gfc_get_element_type (TREE_TYPE (desc));
3632 parmtype = gfc_get_array_type_bounds (parmtype, loop.dimen, 0,
3633 loop.from, loop.to, 1,
3634 GFC_ARRAY_UNKNOWN, true);
3636 /* Allocate temporary for nested forall construct. */
3637 tmp1 = allocate_temp_for_forall_nest (nested_forall_info, parmtype,
3638 inner_size, NULL, block, &ptemp1);
3639 gfc_start_block (&body);
3640 gfc_init_se (&lse, NULL);
3641 lse.expr = gfc_build_array_ref (tmp1, count, NULL);
3642 lse.direct_byref = 1;
3643 gfc_conv_expr_descriptor (&lse, expr2);
3645 gfc_add_block_to_block (&body, &lse.pre);
3646 gfc_add_block_to_block (&body, &lse.post);
3648 /* Increment count. */
3649 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
3650 count, gfc_index_one_node);
3651 gfc_add_modify (&body, count, tmp);
3653 tmp = gfc_finish_block (&body);
3655 /* Generate body and loops according to the information in
3656 nested_forall_info. */
3657 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
3658 gfc_add_expr_to_block (block, tmp);
3660 /* Reset count. */
3661 gfc_add_modify (block, count, gfc_index_zero_node);
3663 parm = gfc_build_array_ref (tmp1, count, NULL);
3664 gfc_init_se (&lse, NULL);
3665 gfc_conv_expr_descriptor (&lse, expr1);
3666 gfc_add_modify (&lse.pre, lse.expr, parm);
3667 gfc_start_block (&body);
3668 gfc_add_block_to_block (&body, &lse.pre);
3669 gfc_add_block_to_block (&body, &lse.post);
3671 /* Increment count. */
3672 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
3673 count, gfc_index_one_node);
3674 gfc_add_modify (&body, count, tmp);
3676 tmp = gfc_finish_block (&body);
3678 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
3679 gfc_add_expr_to_block (block, tmp);
3681 /* Free the temporary. */
3682 if (ptemp1)
3684 tmp = gfc_call_free (ptemp1);
3685 gfc_add_expr_to_block (block, tmp);
3690 /* FORALL and WHERE statements are really nasty, especially when you nest
3691 them. All the rhs of a forall assignment must be evaluated before the
3692 actual assignments are performed. Presumably this also applies to all the
3693 assignments in an inner where statement. */
3695 /* Generate code for a FORALL statement. Any temporaries are allocated as a
3696 linear array, relying on the fact that we process in the same order in all
3697 loops.
3699 forall (i=start:end:stride; maskexpr)
3700 e<i> = f<i>
3701 g<i> = h<i>
3702 end forall
3703 (where e,f,g,h<i> are arbitrary expressions possibly involving i)
3704 Translates to:
3705 count = ((end + 1 - start) / stride)
3706 masktmp(:) = maskexpr(:)
3708 maskindex = 0;
3709 for (i = start; i <= end; i += stride)
3711 if (masktmp[maskindex++])
3712 e<i> = f<i>
3714 maskindex = 0;
3715 for (i = start; i <= end; i += stride)
3717 if (masktmp[maskindex++])
3718 g<i> = h<i>
3721 Note that this code only works when there are no dependencies.
3722 Forall loop with array assignments and data dependencies are a real pain,
3723 because the size of the temporary cannot always be determined before the
3724 loop is executed. This problem is compounded by the presence of nested
3725 FORALL constructs.
3728 static tree
3729 gfc_trans_forall_1 (gfc_code * code, forall_info * nested_forall_info)
3731 stmtblock_t pre;
3732 stmtblock_t post;
3733 stmtblock_t block;
3734 stmtblock_t body;
3735 tree *var;
3736 tree *start;
3737 tree *end;
3738 tree *step;
3739 gfc_expr **varexpr;
3740 tree tmp;
3741 tree assign;
3742 tree size;
3743 tree maskindex;
3744 tree mask;
3745 tree pmask;
3746 tree cycle_label = NULL_TREE;
3747 int n;
3748 int nvar;
3749 int need_temp;
3750 gfc_forall_iterator *fa;
3751 gfc_se se;
3752 gfc_code *c;
3753 gfc_saved_var *saved_vars;
3754 iter_info *this_forall;
3755 forall_info *info;
3756 bool need_mask;
3758 /* Do nothing if the mask is false. */
3759 if (code->expr1
3760 && code->expr1->expr_type == EXPR_CONSTANT
3761 && !code->expr1->value.logical)
3762 return build_empty_stmt (input_location);
3764 n = 0;
3765 /* Count the FORALL index number. */
3766 for (fa = code->ext.forall_iterator; fa; fa = fa->next)
3767 n++;
3768 nvar = n;
3770 /* Allocate the space for var, start, end, step, varexpr. */
3771 var = XCNEWVEC (tree, nvar);
3772 start = XCNEWVEC (tree, nvar);
3773 end = XCNEWVEC (tree, nvar);
3774 step = XCNEWVEC (tree, nvar);
3775 varexpr = XCNEWVEC (gfc_expr *, nvar);
3776 saved_vars = XCNEWVEC (gfc_saved_var, nvar);
3778 /* Allocate the space for info. */
3779 info = XCNEW (forall_info);
3781 gfc_start_block (&pre);
3782 gfc_init_block (&post);
3783 gfc_init_block (&block);
3785 n = 0;
3786 for (fa = code->ext.forall_iterator; fa; fa = fa->next)
3788 gfc_symbol *sym = fa->var->symtree->n.sym;
3790 /* Allocate space for this_forall. */
3791 this_forall = XCNEW (iter_info);
3793 /* Create a temporary variable for the FORALL index. */
3794 tmp = gfc_typenode_for_spec (&sym->ts);
3795 var[n] = gfc_create_var (tmp, sym->name);
3796 gfc_shadow_sym (sym, var[n], &saved_vars[n]);
3798 /* Record it in this_forall. */
3799 this_forall->var = var[n];
3801 /* Replace the index symbol's backend_decl with the temporary decl. */
3802 sym->backend_decl = var[n];
3804 /* Work out the start, end and stride for the loop. */
3805 gfc_init_se (&se, NULL);
3806 gfc_conv_expr_val (&se, fa->start);
3807 /* Record it in this_forall. */
3808 this_forall->start = se.expr;
3809 gfc_add_block_to_block (&block, &se.pre);
3810 start[n] = se.expr;
3812 gfc_init_se (&se, NULL);
3813 gfc_conv_expr_val (&se, fa->end);
3814 /* Record it in this_forall. */
3815 this_forall->end = se.expr;
3816 gfc_make_safe_expr (&se);
3817 gfc_add_block_to_block (&block, &se.pre);
3818 end[n] = se.expr;
3820 gfc_init_se (&se, NULL);
3821 gfc_conv_expr_val (&se, fa->stride);
3822 /* Record it in this_forall. */
3823 this_forall->step = se.expr;
3824 gfc_make_safe_expr (&se);
3825 gfc_add_block_to_block (&block, &se.pre);
3826 step[n] = se.expr;
3828 /* Set the NEXT field of this_forall to NULL. */
3829 this_forall->next = NULL;
3830 /* Link this_forall to the info construct. */
3831 if (info->this_loop)
3833 iter_info *iter_tmp = info->this_loop;
3834 while (iter_tmp->next != NULL)
3835 iter_tmp = iter_tmp->next;
3836 iter_tmp->next = this_forall;
3838 else
3839 info->this_loop = this_forall;
3841 n++;
3843 nvar = n;
3845 /* Calculate the size needed for the current forall level. */
3846 size = gfc_index_one_node;
3847 for (n = 0; n < nvar; n++)
3849 /* size = (end + step - start) / step. */
3850 tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (start[n]),
3851 step[n], start[n]);
3852 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (end[n]),
3853 end[n], tmp);
3854 tmp = fold_build2_loc (input_location, FLOOR_DIV_EXPR, TREE_TYPE (tmp),
3855 tmp, step[n]);
3856 tmp = convert (gfc_array_index_type, tmp);
3858 size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
3859 size, tmp);
3862 /* Record the nvar and size of current forall level. */
3863 info->nvar = nvar;
3864 info->size = size;
3866 if (code->expr1)
3868 /* If the mask is .true., consider the FORALL unconditional. */
3869 if (code->expr1->expr_type == EXPR_CONSTANT
3870 && code->expr1->value.logical)
3871 need_mask = false;
3872 else
3873 need_mask = true;
3875 else
3876 need_mask = false;
3878 /* First we need to allocate the mask. */
3879 if (need_mask)
3881 /* As the mask array can be very big, prefer compact boolean types. */
3882 tree mask_type = gfc_get_logical_type (gfc_logical_kinds[0].kind);
3883 mask = allocate_temp_for_forall_nest (nested_forall_info, mask_type,
3884 size, NULL, &block, &pmask);
3885 maskindex = gfc_create_var_np (gfc_array_index_type, "mi");
3887 /* Record them in the info structure. */
3888 info->maskindex = maskindex;
3889 info->mask = mask;
3891 else
3893 /* No mask was specified. */
3894 maskindex = NULL_TREE;
3895 mask = pmask = NULL_TREE;
3898 /* Link the current forall level to nested_forall_info. */
3899 info->prev_nest = nested_forall_info;
3900 nested_forall_info = info;
3902 /* Copy the mask into a temporary variable if required.
3903 For now we assume a mask temporary is needed. */
3904 if (need_mask)
3906 /* As the mask array can be very big, prefer compact boolean types. */
3907 tree mask_type = gfc_get_logical_type (gfc_logical_kinds[0].kind);
3909 gfc_add_modify (&block, maskindex, gfc_index_zero_node);
3911 /* Start of mask assignment loop body. */
3912 gfc_start_block (&body);
3914 /* Evaluate the mask expression. */
3915 gfc_init_se (&se, NULL);
3916 gfc_conv_expr_val (&se, code->expr1);
3917 gfc_add_block_to_block (&body, &se.pre);
3919 /* Store the mask. */
3920 se.expr = convert (mask_type, se.expr);
3922 tmp = gfc_build_array_ref (mask, maskindex, NULL);
3923 gfc_add_modify (&body, tmp, se.expr);
3925 /* Advance to the next mask element. */
3926 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
3927 maskindex, gfc_index_one_node);
3928 gfc_add_modify (&body, maskindex, tmp);
3930 /* Generate the loops. */
3931 tmp = gfc_finish_block (&body);
3932 tmp = gfc_trans_nested_forall_loop (info, tmp, 0);
3933 gfc_add_expr_to_block (&block, tmp);
3936 if (code->op == EXEC_DO_CONCURRENT)
3938 gfc_init_block (&body);
3939 cycle_label = gfc_build_label_decl (NULL_TREE);
3940 code->cycle_label = cycle_label;
3941 tmp = gfc_trans_code (code->block->next);
3942 gfc_add_expr_to_block (&body, tmp);
3944 if (TREE_USED (cycle_label))
3946 tmp = build1_v (LABEL_EXPR, cycle_label);
3947 gfc_add_expr_to_block (&body, tmp);
3950 tmp = gfc_finish_block (&body);
3951 nested_forall_info->do_concurrent = true;
3952 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
3953 gfc_add_expr_to_block (&block, tmp);
3954 goto done;
3957 c = code->block->next;
3959 /* TODO: loop merging in FORALL statements. */
3960 /* Now that we've got a copy of the mask, generate the assignment loops. */
3961 while (c)
3963 switch (c->op)
3965 case EXEC_ASSIGN:
3966 /* A scalar or array assignment. DO the simple check for
3967 lhs to rhs dependencies. These make a temporary for the
3968 rhs and form a second forall block to copy to variable. */
3969 need_temp = check_forall_dependencies(c, &pre, &post);
3971 /* Temporaries due to array assignment data dependencies introduce
3972 no end of problems. */
3973 if (need_temp)
3974 gfc_trans_assign_need_temp (c->expr1, c->expr2, NULL, false,
3975 nested_forall_info, &block);
3976 else
3978 /* Use the normal assignment copying routines. */
3979 assign = gfc_trans_assignment (c->expr1, c->expr2, false, true);
3981 /* Generate body and loops. */
3982 tmp = gfc_trans_nested_forall_loop (nested_forall_info,
3983 assign, 1);
3984 gfc_add_expr_to_block (&block, tmp);
3987 /* Cleanup any temporary symtrees that have been made to deal
3988 with dependencies. */
3989 if (new_symtree)
3990 cleanup_forall_symtrees (c);
3992 break;
3994 case EXEC_WHERE:
3995 /* Translate WHERE or WHERE construct nested in FORALL. */
3996 gfc_trans_where_2 (c, NULL, false, nested_forall_info, &block);
3997 break;
3999 /* Pointer assignment inside FORALL. */
4000 case EXEC_POINTER_ASSIGN:
4001 need_temp = gfc_check_dependency (c->expr1, c->expr2, 0);
4002 if (need_temp)
4003 gfc_trans_pointer_assign_need_temp (c->expr1, c->expr2,
4004 nested_forall_info, &block);
4005 else
4007 /* Use the normal assignment copying routines. */
4008 assign = gfc_trans_pointer_assignment (c->expr1, c->expr2);
4010 /* Generate body and loops. */
4011 tmp = gfc_trans_nested_forall_loop (nested_forall_info,
4012 assign, 1);
4013 gfc_add_expr_to_block (&block, tmp);
4015 break;
4017 case EXEC_FORALL:
4018 tmp = gfc_trans_forall_1 (c, nested_forall_info);
4019 gfc_add_expr_to_block (&block, tmp);
4020 break;
4022 /* Explicit subroutine calls are prevented by the frontend but interface
4023 assignments can legitimately produce them. */
4024 case EXEC_ASSIGN_CALL:
4025 assign = gfc_trans_call (c, true, NULL_TREE, NULL_TREE, false);
4026 tmp = gfc_trans_nested_forall_loop (nested_forall_info, assign, 1);
4027 gfc_add_expr_to_block (&block, tmp);
4028 break;
4030 default:
4031 gcc_unreachable ();
4034 c = c->next;
4037 done:
4038 /* Restore the original index variables. */
4039 for (fa = code->ext.forall_iterator, n = 0; fa; fa = fa->next, n++)
4040 gfc_restore_sym (fa->var->symtree->n.sym, &saved_vars[n]);
4042 /* Free the space for var, start, end, step, varexpr. */
4043 free (var);
4044 free (start);
4045 free (end);
4046 free (step);
4047 free (varexpr);
4048 free (saved_vars);
4050 for (this_forall = info->this_loop; this_forall;)
4052 iter_info *next = this_forall->next;
4053 free (this_forall);
4054 this_forall = next;
4057 /* Free the space for this forall_info. */
4058 free (info);
4060 if (pmask)
4062 /* Free the temporary for the mask. */
4063 tmp = gfc_call_free (pmask);
4064 gfc_add_expr_to_block (&block, tmp);
4066 if (maskindex)
4067 pushdecl (maskindex);
4069 gfc_add_block_to_block (&pre, &block);
4070 gfc_add_block_to_block (&pre, &post);
4072 return gfc_finish_block (&pre);
4076 /* Translate the FORALL statement or construct. */
4078 tree gfc_trans_forall (gfc_code * code)
4080 return gfc_trans_forall_1 (code, NULL);
4084 /* Translate the DO CONCURRENT construct. */
4086 tree gfc_trans_do_concurrent (gfc_code * code)
4088 return gfc_trans_forall_1 (code, NULL);
4092 /* Evaluate the WHERE mask expression, copy its value to a temporary.
4093 If the WHERE construct is nested in FORALL, compute the overall temporary
4094 needed by the WHERE mask expression multiplied by the iterator number of
4095 the nested forall.
4096 ME is the WHERE mask expression.
4097 MASK is the current execution mask upon input, whose sense may or may
4098 not be inverted as specified by the INVERT argument.
4099 CMASK is the updated execution mask on output, or NULL if not required.
4100 PMASK is the pending execution mask on output, or NULL if not required.
4101 BLOCK is the block in which to place the condition evaluation loops. */
4103 static void
4104 gfc_evaluate_where_mask (gfc_expr * me, forall_info * nested_forall_info,
4105 tree mask, bool invert, tree cmask, tree pmask,
4106 tree mask_type, stmtblock_t * block)
4108 tree tmp, tmp1;
4109 gfc_ss *lss, *rss;
4110 gfc_loopinfo loop;
4111 stmtblock_t body, body1;
4112 tree count, cond, mtmp;
4113 gfc_se lse, rse;
4115 gfc_init_loopinfo (&loop);
4117 lss = gfc_walk_expr (me);
4118 rss = gfc_walk_expr (me);
4120 /* Variable to index the temporary. */
4121 count = gfc_create_var (gfc_array_index_type, "count");
4122 /* Initialize count. */
4123 gfc_add_modify (block, count, gfc_index_zero_node);
4125 gfc_start_block (&body);
4127 gfc_init_se (&rse, NULL);
4128 gfc_init_se (&lse, NULL);
4130 if (lss == gfc_ss_terminator)
4132 gfc_init_block (&body1);
4134 else
4136 /* Initialize the loop. */
4137 gfc_init_loopinfo (&loop);
4139 /* We may need LSS to determine the shape of the expression. */
4140 gfc_add_ss_to_loop (&loop, lss);
4141 gfc_add_ss_to_loop (&loop, rss);
4143 gfc_conv_ss_startstride (&loop);
4144 gfc_conv_loop_setup (&loop, &me->where);
4146 gfc_mark_ss_chain_used (rss, 1);
4147 /* Start the loop body. */
4148 gfc_start_scalarized_body (&loop, &body1);
4150 /* Translate the expression. */
4151 gfc_copy_loopinfo_to_se (&rse, &loop);
4152 rse.ss = rss;
4153 gfc_conv_expr (&rse, me);
4156 /* Variable to evaluate mask condition. */
4157 cond = gfc_create_var (mask_type, "cond");
4158 if (mask && (cmask || pmask))
4159 mtmp = gfc_create_var (mask_type, "mask");
4160 else mtmp = NULL_TREE;
4162 gfc_add_block_to_block (&body1, &lse.pre);
4163 gfc_add_block_to_block (&body1, &rse.pre);
4165 gfc_add_modify (&body1, cond, fold_convert (mask_type, rse.expr));
4167 if (mask && (cmask || pmask))
4169 tmp = gfc_build_array_ref (mask, count, NULL);
4170 if (invert)
4171 tmp = fold_build1_loc (input_location, TRUTH_NOT_EXPR, mask_type, tmp);
4172 gfc_add_modify (&body1, mtmp, tmp);
4175 if (cmask)
4177 tmp1 = gfc_build_array_ref (cmask, count, NULL);
4178 tmp = cond;
4179 if (mask)
4180 tmp = fold_build2_loc (input_location, TRUTH_AND_EXPR, mask_type,
4181 mtmp, tmp);
4182 gfc_add_modify (&body1, tmp1, tmp);
4185 if (pmask)
4187 tmp1 = gfc_build_array_ref (pmask, count, NULL);
4188 tmp = fold_build1_loc (input_location, TRUTH_NOT_EXPR, mask_type, cond);
4189 if (mask)
4190 tmp = fold_build2_loc (input_location, TRUTH_AND_EXPR, mask_type, mtmp,
4191 tmp);
4192 gfc_add_modify (&body1, tmp1, tmp);
4195 gfc_add_block_to_block (&body1, &lse.post);
4196 gfc_add_block_to_block (&body1, &rse.post);
4198 if (lss == gfc_ss_terminator)
4200 gfc_add_block_to_block (&body, &body1);
4202 else
4204 /* Increment count. */
4205 tmp1 = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
4206 count, gfc_index_one_node);
4207 gfc_add_modify (&body1, count, tmp1);
4209 /* Generate the copying loops. */
4210 gfc_trans_scalarizing_loops (&loop, &body1);
4212 gfc_add_block_to_block (&body, &loop.pre);
4213 gfc_add_block_to_block (&body, &loop.post);
4215 gfc_cleanup_loop (&loop);
4216 /* TODO: Reuse lss and rss when copying temp->lhs. Need to be careful
4217 as tree nodes in SS may not be valid in different scope. */
4220 tmp1 = gfc_finish_block (&body);
4221 /* If the WHERE construct is inside FORALL, fill the full temporary. */
4222 if (nested_forall_info != NULL)
4223 tmp1 = gfc_trans_nested_forall_loop (nested_forall_info, tmp1, 1);
4225 gfc_add_expr_to_block (block, tmp1);
4229 /* Translate an assignment statement in a WHERE statement or construct
4230 statement. The MASK expression is used to control which elements
4231 of EXPR1 shall be assigned. The sense of MASK is specified by
4232 INVERT. */
4234 static tree
4235 gfc_trans_where_assign (gfc_expr *expr1, gfc_expr *expr2,
4236 tree mask, bool invert,
4237 tree count1, tree count2,
4238 gfc_code *cnext)
4240 gfc_se lse;
4241 gfc_se rse;
4242 gfc_ss *lss;
4243 gfc_ss *lss_section;
4244 gfc_ss *rss;
4246 gfc_loopinfo loop;
4247 tree tmp;
4248 stmtblock_t block;
4249 stmtblock_t body;
4250 tree index, maskexpr;
4252 /* A defined assignment. */
4253 if (cnext && cnext->resolved_sym)
4254 return gfc_trans_call (cnext, true, mask, count1, invert);
4256 #if 0
4257 /* TODO: handle this special case.
4258 Special case a single function returning an array. */
4259 if (expr2->expr_type == EXPR_FUNCTION && expr2->rank > 0)
4261 tmp = gfc_trans_arrayfunc_assign (expr1, expr2);
4262 if (tmp)
4263 return tmp;
4265 #endif
4267 /* Assignment of the form lhs = rhs. */
4268 gfc_start_block (&block);
4270 gfc_init_se (&lse, NULL);
4271 gfc_init_se (&rse, NULL);
4273 /* Walk the lhs. */
4274 lss = gfc_walk_expr (expr1);
4275 rss = NULL;
4277 /* In each where-assign-stmt, the mask-expr and the variable being
4278 defined shall be arrays of the same shape. */
4279 gcc_assert (lss != gfc_ss_terminator);
4281 /* The assignment needs scalarization. */
4282 lss_section = lss;
4284 /* Find a non-scalar SS from the lhs. */
4285 while (lss_section != gfc_ss_terminator
4286 && lss_section->info->type != GFC_SS_SECTION)
4287 lss_section = lss_section->next;
4289 gcc_assert (lss_section != gfc_ss_terminator);
4291 /* Initialize the scalarizer. */
4292 gfc_init_loopinfo (&loop);
4294 /* Walk the rhs. */
4295 rss = gfc_walk_expr (expr2);
4296 if (rss == gfc_ss_terminator)
4298 /* The rhs is scalar. Add a ss for the expression. */
4299 rss = gfc_get_scalar_ss (gfc_ss_terminator, expr2);
4300 rss->info->where = 1;
4303 /* Associate the SS with the loop. */
4304 gfc_add_ss_to_loop (&loop, lss);
4305 gfc_add_ss_to_loop (&loop, rss);
4307 /* Calculate the bounds of the scalarization. */
4308 gfc_conv_ss_startstride (&loop);
4310 /* Resolve any data dependencies in the statement. */
4311 gfc_conv_resolve_dependencies (&loop, lss_section, rss);
4313 /* Setup the scalarizing loops. */
4314 gfc_conv_loop_setup (&loop, &expr2->where);
4316 /* Setup the gfc_se structures. */
4317 gfc_copy_loopinfo_to_se (&lse, &loop);
4318 gfc_copy_loopinfo_to_se (&rse, &loop);
4320 rse.ss = rss;
4321 gfc_mark_ss_chain_used (rss, 1);
4322 if (loop.temp_ss == NULL)
4324 lse.ss = lss;
4325 gfc_mark_ss_chain_used (lss, 1);
4327 else
4329 lse.ss = loop.temp_ss;
4330 gfc_mark_ss_chain_used (lss, 3);
4331 gfc_mark_ss_chain_used (loop.temp_ss, 3);
4334 /* Start the scalarized loop body. */
4335 gfc_start_scalarized_body (&loop, &body);
4337 /* Translate the expression. */
4338 gfc_conv_expr (&rse, expr2);
4339 if (lss != gfc_ss_terminator && loop.temp_ss != NULL)
4340 gfc_conv_tmp_array_ref (&lse);
4341 else
4342 gfc_conv_expr (&lse, expr1);
4344 /* Form the mask expression according to the mask. */
4345 index = count1;
4346 maskexpr = gfc_build_array_ref (mask, index, NULL);
4347 if (invert)
4348 maskexpr = fold_build1_loc (input_location, TRUTH_NOT_EXPR,
4349 TREE_TYPE (maskexpr), maskexpr);
4351 /* Use the scalar assignment as is. */
4352 tmp = gfc_trans_scalar_assign (&lse, &rse, expr1->ts,
4353 loop.temp_ss != NULL, false, true);
4355 tmp = build3_v (COND_EXPR, maskexpr, tmp, build_empty_stmt (input_location));
4357 gfc_add_expr_to_block (&body, tmp);
4359 if (lss == gfc_ss_terminator)
4361 /* Increment count1. */
4362 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
4363 count1, gfc_index_one_node);
4364 gfc_add_modify (&body, count1, tmp);
4366 /* Use the scalar assignment as is. */
4367 gfc_add_block_to_block (&block, &body);
4369 else
4371 gcc_assert (lse.ss == gfc_ss_terminator
4372 && rse.ss == gfc_ss_terminator);
4374 if (loop.temp_ss != NULL)
4376 /* Increment count1 before finish the main body of a scalarized
4377 expression. */
4378 tmp = fold_build2_loc (input_location, PLUS_EXPR,
4379 gfc_array_index_type, count1, gfc_index_one_node);
4380 gfc_add_modify (&body, count1, tmp);
4381 gfc_trans_scalarized_loop_boundary (&loop, &body);
4383 /* We need to copy the temporary to the actual lhs. */
4384 gfc_init_se (&lse, NULL);
4385 gfc_init_se (&rse, NULL);
4386 gfc_copy_loopinfo_to_se (&lse, &loop);
4387 gfc_copy_loopinfo_to_se (&rse, &loop);
4389 rse.ss = loop.temp_ss;
4390 lse.ss = lss;
4392 gfc_conv_tmp_array_ref (&rse);
4393 gfc_conv_expr (&lse, expr1);
4395 gcc_assert (lse.ss == gfc_ss_terminator
4396 && rse.ss == gfc_ss_terminator);
4398 /* Form the mask expression according to the mask tree list. */
4399 index = count2;
4400 maskexpr = gfc_build_array_ref (mask, index, NULL);
4401 if (invert)
4402 maskexpr = fold_build1_loc (input_location, TRUTH_NOT_EXPR,
4403 TREE_TYPE (maskexpr), maskexpr);
4405 /* Use the scalar assignment as is. */
4406 tmp = gfc_trans_scalar_assign (&lse, &rse, expr1->ts, false, false,
4407 true);
4408 tmp = build3_v (COND_EXPR, maskexpr, tmp,
4409 build_empty_stmt (input_location));
4410 gfc_add_expr_to_block (&body, tmp);
4412 /* Increment count2. */
4413 tmp = fold_build2_loc (input_location, PLUS_EXPR,
4414 gfc_array_index_type, count2,
4415 gfc_index_one_node);
4416 gfc_add_modify (&body, count2, tmp);
4418 else
4420 /* Increment count1. */
4421 tmp = fold_build2_loc (input_location, PLUS_EXPR,
4422 gfc_array_index_type, count1,
4423 gfc_index_one_node);
4424 gfc_add_modify (&body, count1, tmp);
4427 /* Generate the copying loops. */
4428 gfc_trans_scalarizing_loops (&loop, &body);
4430 /* Wrap the whole thing up. */
4431 gfc_add_block_to_block (&block, &loop.pre);
4432 gfc_add_block_to_block (&block, &loop.post);
4433 gfc_cleanup_loop (&loop);
4436 return gfc_finish_block (&block);
4440 /* Translate the WHERE construct or statement.
4441 This function can be called iteratively to translate the nested WHERE
4442 construct or statement.
4443 MASK is the control mask. */
4445 static void
4446 gfc_trans_where_2 (gfc_code * code, tree mask, bool invert,
4447 forall_info * nested_forall_info, stmtblock_t * block)
4449 stmtblock_t inner_size_body;
4450 tree inner_size, size;
4451 gfc_ss *lss, *rss;
4452 tree mask_type;
4453 gfc_expr *expr1;
4454 gfc_expr *expr2;
4455 gfc_code *cblock;
4456 gfc_code *cnext;
4457 tree tmp;
4458 tree cond;
4459 tree count1, count2;
4460 bool need_cmask;
4461 bool need_pmask;
4462 int need_temp;
4463 tree pcmask = NULL_TREE;
4464 tree ppmask = NULL_TREE;
4465 tree cmask = NULL_TREE;
4466 tree pmask = NULL_TREE;
4467 gfc_actual_arglist *arg;
4469 /* the WHERE statement or the WHERE construct statement. */
4470 cblock = code->block;
4472 /* As the mask array can be very big, prefer compact boolean types. */
4473 mask_type = gfc_get_logical_type (gfc_logical_kinds[0].kind);
4475 /* Determine which temporary masks are needed. */
4476 if (!cblock->block)
4478 /* One clause: No ELSEWHEREs. */
4479 need_cmask = (cblock->next != 0);
4480 need_pmask = false;
4482 else if (cblock->block->block)
4484 /* Three or more clauses: Conditional ELSEWHEREs. */
4485 need_cmask = true;
4486 need_pmask = true;
4488 else if (cblock->next)
4490 /* Two clauses, the first non-empty. */
4491 need_cmask = true;
4492 need_pmask = (mask != NULL_TREE
4493 && cblock->block->next != 0);
4495 else if (!cblock->block->next)
4497 /* Two clauses, both empty. */
4498 need_cmask = false;
4499 need_pmask = false;
4501 /* Two clauses, the first empty, the second non-empty. */
4502 else if (mask)
4504 need_cmask = (cblock->block->expr1 != 0);
4505 need_pmask = true;
4507 else
4509 need_cmask = true;
4510 need_pmask = false;
4513 if (need_cmask || need_pmask)
4515 /* Calculate the size of temporary needed by the mask-expr. */
4516 gfc_init_block (&inner_size_body);
4517 inner_size = compute_inner_temp_size (cblock->expr1, cblock->expr1,
4518 &inner_size_body, &lss, &rss);
4520 gfc_free_ss_chain (lss);
4521 gfc_free_ss_chain (rss);
4523 /* Calculate the total size of temporary needed. */
4524 size = compute_overall_iter_number (nested_forall_info, inner_size,
4525 &inner_size_body, block);
4527 /* Check whether the size is negative. */
4528 cond = fold_build2_loc (input_location, LE_EXPR, boolean_type_node, size,
4529 gfc_index_zero_node);
4530 size = fold_build3_loc (input_location, COND_EXPR, gfc_array_index_type,
4531 cond, gfc_index_zero_node, size);
4532 size = gfc_evaluate_now (size, block);
4534 /* Allocate temporary for WHERE mask if needed. */
4535 if (need_cmask)
4536 cmask = allocate_temp_for_forall_nest_1 (mask_type, size, block,
4537 &pcmask);
4539 /* Allocate temporary for !mask if needed. */
4540 if (need_pmask)
4541 pmask = allocate_temp_for_forall_nest_1 (mask_type, size, block,
4542 &ppmask);
4545 while (cblock)
4547 /* Each time around this loop, the where clause is conditional
4548 on the value of mask and invert, which are updated at the
4549 bottom of the loop. */
4551 /* Has mask-expr. */
4552 if (cblock->expr1)
4554 /* Ensure that the WHERE mask will be evaluated exactly once.
4555 If there are no statements in this WHERE/ELSEWHERE clause,
4556 then we don't need to update the control mask (cmask).
4557 If this is the last clause of the WHERE construct, then
4558 we don't need to update the pending control mask (pmask). */
4559 if (mask)
4560 gfc_evaluate_where_mask (cblock->expr1, nested_forall_info,
4561 mask, invert,
4562 cblock->next ? cmask : NULL_TREE,
4563 cblock->block ? pmask : NULL_TREE,
4564 mask_type, block);
4565 else
4566 gfc_evaluate_where_mask (cblock->expr1, nested_forall_info,
4567 NULL_TREE, false,
4568 (cblock->next || cblock->block)
4569 ? cmask : NULL_TREE,
4570 NULL_TREE, mask_type, block);
4572 invert = false;
4574 /* It's a final elsewhere-stmt. No mask-expr is present. */
4575 else
4576 cmask = mask;
4578 /* The body of this where clause are controlled by cmask with
4579 sense specified by invert. */
4581 /* Get the assignment statement of a WHERE statement, or the first
4582 statement in where-body-construct of a WHERE construct. */
4583 cnext = cblock->next;
4584 while (cnext)
4586 switch (cnext->op)
4588 /* WHERE assignment statement. */
4589 case EXEC_ASSIGN_CALL:
4591 arg = cnext->ext.actual;
4592 expr1 = expr2 = NULL;
4593 for (; arg; arg = arg->next)
4595 if (!arg->expr)
4596 continue;
4597 if (expr1 == NULL)
4598 expr1 = arg->expr;
4599 else
4600 expr2 = arg->expr;
4602 goto evaluate;
4604 case EXEC_ASSIGN:
4605 expr1 = cnext->expr1;
4606 expr2 = cnext->expr2;
4607 evaluate:
4608 if (nested_forall_info != NULL)
4610 need_temp = gfc_check_dependency (expr1, expr2, 0);
4611 if (need_temp && cnext->op != EXEC_ASSIGN_CALL)
4612 gfc_trans_assign_need_temp (expr1, expr2,
4613 cmask, invert,
4614 nested_forall_info, block);
4615 else
4617 /* Variables to control maskexpr. */
4618 count1 = gfc_create_var (gfc_array_index_type, "count1");
4619 count2 = gfc_create_var (gfc_array_index_type, "count2");
4620 gfc_add_modify (block, count1, gfc_index_zero_node);
4621 gfc_add_modify (block, count2, gfc_index_zero_node);
4623 tmp = gfc_trans_where_assign (expr1, expr2,
4624 cmask, invert,
4625 count1, count2,
4626 cnext);
4628 tmp = gfc_trans_nested_forall_loop (nested_forall_info,
4629 tmp, 1);
4630 gfc_add_expr_to_block (block, tmp);
4633 else
4635 /* Variables to control maskexpr. */
4636 count1 = gfc_create_var (gfc_array_index_type, "count1");
4637 count2 = gfc_create_var (gfc_array_index_type, "count2");
4638 gfc_add_modify (block, count1, gfc_index_zero_node);
4639 gfc_add_modify (block, count2, gfc_index_zero_node);
4641 tmp = gfc_trans_where_assign (expr1, expr2,
4642 cmask, invert,
4643 count1, count2,
4644 cnext);
4645 gfc_add_expr_to_block (block, tmp);
4648 break;
4650 /* WHERE or WHERE construct is part of a where-body-construct. */
4651 case EXEC_WHERE:
4652 gfc_trans_where_2 (cnext, cmask, invert,
4653 nested_forall_info, block);
4654 break;
4656 default:
4657 gcc_unreachable ();
4660 /* The next statement within the same where-body-construct. */
4661 cnext = cnext->next;
4663 /* The next masked-elsewhere-stmt, elsewhere-stmt, or end-where-stmt. */
4664 cblock = cblock->block;
4665 if (mask == NULL_TREE)
4667 /* If we're the initial WHERE, we can simply invert the sense
4668 of the current mask to obtain the "mask" for the remaining
4669 ELSEWHEREs. */
4670 invert = true;
4671 mask = cmask;
4673 else
4675 /* Otherwise, for nested WHERE's we need to use the pending mask. */
4676 invert = false;
4677 mask = pmask;
4681 /* If we allocated a pending mask array, deallocate it now. */
4682 if (ppmask)
4684 tmp = gfc_call_free (ppmask);
4685 gfc_add_expr_to_block (block, tmp);
4688 /* If we allocated a current mask array, deallocate it now. */
4689 if (pcmask)
4691 tmp = gfc_call_free (pcmask);
4692 gfc_add_expr_to_block (block, tmp);
4696 /* Translate a simple WHERE construct or statement without dependencies.
4697 CBLOCK is the "then" clause of the WHERE statement, where CBLOCK->EXPR
4698 is the mask condition, and EBLOCK if non-NULL is the "else" clause.
4699 Currently both CBLOCK and EBLOCK are restricted to single assignments. */
4701 static tree
4702 gfc_trans_where_3 (gfc_code * cblock, gfc_code * eblock)
4704 stmtblock_t block, body;
4705 gfc_expr *cond, *tdst, *tsrc, *edst, *esrc;
4706 tree tmp, cexpr, tstmt, estmt;
4707 gfc_ss *css, *tdss, *tsss;
4708 gfc_se cse, tdse, tsse, edse, esse;
4709 gfc_loopinfo loop;
4710 gfc_ss *edss = 0;
4711 gfc_ss *esss = 0;
4713 /* Allow the scalarizer to workshare simple where loops. */
4714 if (ompws_flags & OMPWS_WORKSHARE_FLAG)
4715 ompws_flags |= OMPWS_SCALARIZER_WS;
4717 cond = cblock->expr1;
4718 tdst = cblock->next->expr1;
4719 tsrc = cblock->next->expr2;
4720 edst = eblock ? eblock->next->expr1 : NULL;
4721 esrc = eblock ? eblock->next->expr2 : NULL;
4723 gfc_start_block (&block);
4724 gfc_init_loopinfo (&loop);
4726 /* Handle the condition. */
4727 gfc_init_se (&cse, NULL);
4728 css = gfc_walk_expr (cond);
4729 gfc_add_ss_to_loop (&loop, css);
4731 /* Handle the then-clause. */
4732 gfc_init_se (&tdse, NULL);
4733 gfc_init_se (&tsse, NULL);
4734 tdss = gfc_walk_expr (tdst);
4735 tsss = gfc_walk_expr (tsrc);
4736 if (tsss == gfc_ss_terminator)
4738 tsss = gfc_get_scalar_ss (gfc_ss_terminator, tsrc);
4739 tsss->info->where = 1;
4741 gfc_add_ss_to_loop (&loop, tdss);
4742 gfc_add_ss_to_loop (&loop, tsss);
4744 if (eblock)
4746 /* Handle the else clause. */
4747 gfc_init_se (&edse, NULL);
4748 gfc_init_se (&esse, NULL);
4749 edss = gfc_walk_expr (edst);
4750 esss = gfc_walk_expr (esrc);
4751 if (esss == gfc_ss_terminator)
4753 esss = gfc_get_scalar_ss (gfc_ss_terminator, esrc);
4754 esss->info->where = 1;
4756 gfc_add_ss_to_loop (&loop, edss);
4757 gfc_add_ss_to_loop (&loop, esss);
4760 gfc_conv_ss_startstride (&loop);
4761 gfc_conv_loop_setup (&loop, &tdst->where);
4763 gfc_mark_ss_chain_used (css, 1);
4764 gfc_mark_ss_chain_used (tdss, 1);
4765 gfc_mark_ss_chain_used (tsss, 1);
4766 if (eblock)
4768 gfc_mark_ss_chain_used (edss, 1);
4769 gfc_mark_ss_chain_used (esss, 1);
4772 gfc_start_scalarized_body (&loop, &body);
4774 gfc_copy_loopinfo_to_se (&cse, &loop);
4775 gfc_copy_loopinfo_to_se (&tdse, &loop);
4776 gfc_copy_loopinfo_to_se (&tsse, &loop);
4777 cse.ss = css;
4778 tdse.ss = tdss;
4779 tsse.ss = tsss;
4780 if (eblock)
4782 gfc_copy_loopinfo_to_se (&edse, &loop);
4783 gfc_copy_loopinfo_to_se (&esse, &loop);
4784 edse.ss = edss;
4785 esse.ss = esss;
4788 gfc_conv_expr (&cse, cond);
4789 gfc_add_block_to_block (&body, &cse.pre);
4790 cexpr = cse.expr;
4792 gfc_conv_expr (&tsse, tsrc);
4793 if (tdss != gfc_ss_terminator && loop.temp_ss != NULL)
4794 gfc_conv_tmp_array_ref (&tdse);
4795 else
4796 gfc_conv_expr (&tdse, tdst);
4798 if (eblock)
4800 gfc_conv_expr (&esse, esrc);
4801 if (edss != gfc_ss_terminator && loop.temp_ss != NULL)
4802 gfc_conv_tmp_array_ref (&edse);
4803 else
4804 gfc_conv_expr (&edse, edst);
4807 tstmt = gfc_trans_scalar_assign (&tdse, &tsse, tdst->ts, false, false, true);
4808 estmt = eblock ? gfc_trans_scalar_assign (&edse, &esse, edst->ts, false,
4809 false, true)
4810 : build_empty_stmt (input_location);
4811 tmp = build3_v (COND_EXPR, cexpr, tstmt, estmt);
4812 gfc_add_expr_to_block (&body, tmp);
4813 gfc_add_block_to_block (&body, &cse.post);
4815 gfc_trans_scalarizing_loops (&loop, &body);
4816 gfc_add_block_to_block (&block, &loop.pre);
4817 gfc_add_block_to_block (&block, &loop.post);
4818 gfc_cleanup_loop (&loop);
4820 return gfc_finish_block (&block);
4823 /* As the WHERE or WHERE construct statement can be nested, we call
4824 gfc_trans_where_2 to do the translation, and pass the initial
4825 NULL values for both the control mask and the pending control mask. */
4827 tree
4828 gfc_trans_where (gfc_code * code)
4830 stmtblock_t block;
4831 gfc_code *cblock;
4832 gfc_code *eblock;
4834 cblock = code->block;
4835 if (cblock->next
4836 && cblock->next->op == EXEC_ASSIGN
4837 && !cblock->next->next)
4839 eblock = cblock->block;
4840 if (!eblock)
4842 /* A simple "WHERE (cond) x = y" statement or block is
4843 dependence free if cond is not dependent upon writing x,
4844 and the source y is unaffected by the destination x. */
4845 if (!gfc_check_dependency (cblock->next->expr1,
4846 cblock->expr1, 0)
4847 && !gfc_check_dependency (cblock->next->expr1,
4848 cblock->next->expr2, 0))
4849 return gfc_trans_where_3 (cblock, NULL);
4851 else if (!eblock->expr1
4852 && !eblock->block
4853 && eblock->next
4854 && eblock->next->op == EXEC_ASSIGN
4855 && !eblock->next->next)
4857 /* A simple "WHERE (cond) x1 = y1 ELSEWHERE x2 = y2 ENDWHERE"
4858 block is dependence free if cond is not dependent on writes
4859 to x1 and x2, y1 is not dependent on writes to x2, and y2
4860 is not dependent on writes to x1, and both y's are not
4861 dependent upon their own x's. In addition to this, the
4862 final two dependency checks below exclude all but the same
4863 array reference if the where and elswhere destinations
4864 are the same. In short, this is VERY conservative and this
4865 is needed because the two loops, required by the standard
4866 are coalesced in gfc_trans_where_3. */
4867 if (!gfc_check_dependency (cblock->next->expr1,
4868 cblock->expr1, 0)
4869 && !gfc_check_dependency (eblock->next->expr1,
4870 cblock->expr1, 0)
4871 && !gfc_check_dependency (cblock->next->expr1,
4872 eblock->next->expr2, 1)
4873 && !gfc_check_dependency (eblock->next->expr1,
4874 cblock->next->expr2, 1)
4875 && !gfc_check_dependency (cblock->next->expr1,
4876 cblock->next->expr2, 1)
4877 && !gfc_check_dependency (eblock->next->expr1,
4878 eblock->next->expr2, 1)
4879 && !gfc_check_dependency (cblock->next->expr1,
4880 eblock->next->expr1, 0)
4881 && !gfc_check_dependency (eblock->next->expr1,
4882 cblock->next->expr1, 0))
4883 return gfc_trans_where_3 (cblock, eblock);
4887 gfc_start_block (&block);
4889 gfc_trans_where_2 (code, NULL, false, NULL, &block);
4891 return gfc_finish_block (&block);
4895 /* CYCLE a DO loop. The label decl has already been created by
4896 gfc_trans_do(), it's in TREE_PURPOSE (backend_decl) of the gfc_code
4897 node at the head of the loop. We must mark the label as used. */
4899 tree
4900 gfc_trans_cycle (gfc_code * code)
4902 tree cycle_label;
4904 cycle_label = code->ext.which_construct->cycle_label;
4905 gcc_assert (cycle_label);
4907 TREE_USED (cycle_label) = 1;
4908 return build1_v (GOTO_EXPR, cycle_label);
4912 /* EXIT a DO loop. Similar to CYCLE, but now the label is in
4913 TREE_VALUE (backend_decl) of the gfc_code node at the head of the
4914 loop. */
4916 tree
4917 gfc_trans_exit (gfc_code * code)
4919 tree exit_label;
4921 exit_label = code->ext.which_construct->exit_label;
4922 gcc_assert (exit_label);
4924 TREE_USED (exit_label) = 1;
4925 return build1_v (GOTO_EXPR, exit_label);
4929 /* Translate the ALLOCATE statement. */
4931 tree
4932 gfc_trans_allocate (gfc_code * code)
4934 gfc_alloc *al;
4935 gfc_expr *e;
4936 gfc_expr *expr;
4937 gfc_se se;
4938 tree tmp;
4939 tree parm;
4940 tree stat;
4941 tree errmsg;
4942 tree errlen;
4943 tree label_errmsg;
4944 tree label_finish;
4945 tree memsz;
4946 tree expr3;
4947 tree slen3;
4948 stmtblock_t block;
4949 stmtblock_t post;
4950 gfc_expr *sz;
4951 gfc_se se_sz;
4952 tree class_expr;
4953 tree nelems;
4954 tree memsize = NULL_TREE;
4955 tree classexpr = NULL_TREE;
4957 if (!code->ext.alloc.list)
4958 return NULL_TREE;
4960 stat = tmp = memsz = NULL_TREE;
4961 label_errmsg = label_finish = errmsg = errlen = NULL_TREE;
4963 gfc_init_block (&block);
4964 gfc_init_block (&post);
4966 /* STAT= (and maybe ERRMSG=) is present. */
4967 if (code->expr1)
4969 /* STAT=. */
4970 tree gfc_int4_type_node = gfc_get_int_type (4);
4971 stat = gfc_create_var (gfc_int4_type_node, "stat");
4973 /* ERRMSG= only makes sense with STAT=. */
4974 if (code->expr2)
4976 gfc_init_se (&se, NULL);
4977 se.want_pointer = 1;
4978 gfc_conv_expr_lhs (&se, code->expr2);
4979 errmsg = se.expr;
4980 errlen = se.string_length;
4982 else
4984 errmsg = null_pointer_node;
4985 errlen = build_int_cst (gfc_charlen_type_node, 0);
4988 /* GOTO destinations. */
4989 label_errmsg = gfc_build_label_decl (NULL_TREE);
4990 label_finish = gfc_build_label_decl (NULL_TREE);
4991 TREE_USED (label_finish) = 0;
4994 expr3 = NULL_TREE;
4995 slen3 = NULL_TREE;
4997 for (al = code->ext.alloc.list; al != NULL; al = al->next)
4999 expr = gfc_copy_expr (al->expr);
5001 if (expr->ts.type == BT_CLASS)
5002 gfc_add_data_component (expr);
5004 gfc_init_se (&se, NULL);
5006 se.want_pointer = 1;
5007 se.descriptor_only = 1;
5008 gfc_conv_expr (&se, expr);
5010 /* Evaluate expr3 just once if not a variable. */
5011 if (al == code->ext.alloc.list
5012 && al->expr->ts.type == BT_CLASS
5013 && code->expr3
5014 && code->expr3->ts.type == BT_CLASS
5015 && code->expr3->expr_type != EXPR_VARIABLE)
5017 gfc_init_se (&se_sz, NULL);
5018 gfc_conv_expr_reference (&se_sz, code->expr3);
5019 gfc_conv_class_to_class (&se_sz, code->expr3,
5020 code->expr3->ts, false, true, false, false);
5021 gfc_add_block_to_block (&se.pre, &se_sz.pre);
5022 gfc_add_block_to_block (&se.post, &se_sz.post);
5023 classexpr = build_fold_indirect_ref_loc (input_location,
5024 se_sz.expr);
5025 classexpr = gfc_evaluate_now (classexpr, &se.pre);
5026 memsize = gfc_vtable_size_get (classexpr);
5027 memsize = fold_convert (sizetype, memsize);
5030 memsz = memsize;
5031 class_expr = classexpr;
5033 nelems = NULL_TREE;
5034 if (!gfc_array_allocate (&se, expr, stat, errmsg, errlen, label_finish,
5035 memsz, &nelems, code->expr3, &code->ext.alloc.ts))
5037 bool unlimited_char;
5039 unlimited_char = UNLIMITED_POLY (al->expr)
5040 && ((code->expr3 && code->expr3->ts.type == BT_CHARACTER)
5041 || (code->ext.alloc.ts.type == BT_CHARACTER
5042 && code->ext.alloc.ts.u.cl
5043 && code->ext.alloc.ts.u.cl->length));
5045 /* A scalar or derived type. */
5047 /* Determine allocate size. */
5048 if (al->expr->ts.type == BT_CLASS
5049 && !unlimited_char
5050 && code->expr3
5051 && memsz == NULL_TREE)
5053 if (code->expr3->ts.type == BT_CLASS)
5055 sz = gfc_copy_expr (code->expr3);
5056 gfc_add_vptr_component (sz);
5057 gfc_add_size_component (sz);
5058 gfc_init_se (&se_sz, NULL);
5059 gfc_conv_expr (&se_sz, sz);
5060 gfc_free_expr (sz);
5061 memsz = se_sz.expr;
5063 else
5064 memsz = TYPE_SIZE_UNIT (gfc_typenode_for_spec (&code->expr3->ts));
5066 else if (((al->expr->ts.type == BT_CHARACTER && al->expr->ts.deferred)
5067 || unlimited_char) && code->expr3)
5069 if (!code->expr3->ts.u.cl->backend_decl)
5071 /* Convert and use the length expression. */
5072 gfc_init_se (&se_sz, NULL);
5073 if (code->expr3->expr_type == EXPR_VARIABLE
5074 || code->expr3->expr_type == EXPR_CONSTANT)
5076 gfc_conv_expr (&se_sz, code->expr3);
5077 gfc_add_block_to_block (&se.pre, &se_sz.pre);
5078 se_sz.string_length
5079 = gfc_evaluate_now (se_sz.string_length, &se.pre);
5080 gfc_add_block_to_block (&se.pre, &se_sz.post);
5081 memsz = se_sz.string_length;
5083 else if (code->expr3->mold
5084 && code->expr3->ts.u.cl
5085 && code->expr3->ts.u.cl->length)
5087 gfc_conv_expr (&se_sz, code->expr3->ts.u.cl->length);
5088 gfc_add_block_to_block (&se.pre, &se_sz.pre);
5089 se_sz.expr = gfc_evaluate_now (se_sz.expr, &se.pre);
5090 gfc_add_block_to_block (&se.pre, &se_sz.post);
5091 memsz = se_sz.expr;
5093 else
5095 /* This is would be inefficient and possibly could
5096 generate wrong code if the result were not stored
5097 in expr3/slen3. */
5098 if (slen3 == NULL_TREE)
5100 gfc_conv_expr (&se_sz, code->expr3);
5101 gfc_add_block_to_block (&se.pre, &se_sz.pre);
5102 expr3 = gfc_evaluate_now (se_sz.expr, &se.pre);
5103 gfc_add_block_to_block (&post, &se_sz.post);
5104 slen3 = gfc_evaluate_now (se_sz.string_length,
5105 &se.pre);
5107 memsz = slen3;
5110 else
5111 /* Otherwise use the stored string length. */
5112 memsz = code->expr3->ts.u.cl->backend_decl;
5113 tmp = al->expr->ts.u.cl->backend_decl;
5115 /* Store the string length. */
5116 if (tmp && TREE_CODE (tmp) == VAR_DECL)
5117 gfc_add_modify (&se.pre, tmp, fold_convert (TREE_TYPE (tmp),
5118 memsz));
5119 else if (al->expr->ts.type == BT_CHARACTER
5120 && al->expr->ts.deferred && se.string_length)
5121 gfc_add_modify (&se.pre, se.string_length,
5122 fold_convert (TREE_TYPE (se.string_length),
5123 memsz));
5124 else if ((al->expr->ts.type == BT_DERIVED
5125 || al->expr->ts.type == BT_CLASS)
5126 && expr->ts.u.derived->attr.unlimited_polymorphic)
5128 tmp = gfc_class_len_get (al->expr->symtree->n.sym->backend_decl);
5129 gfc_add_modify (&se.pre, tmp,
5130 fold_convert (TREE_TYPE (tmp),
5131 memsz));
5134 /* Convert to size in bytes, using the character KIND. */
5135 if (unlimited_char)
5136 tmp = TREE_TYPE (gfc_typenode_for_spec (&code->expr3->ts));
5137 else
5138 tmp = TREE_TYPE (gfc_typenode_for_spec (&al->expr->ts));
5139 tmp = TYPE_SIZE_UNIT (tmp);
5140 memsz = fold_build2_loc (input_location, MULT_EXPR,
5141 TREE_TYPE (tmp), tmp,
5142 fold_convert (TREE_TYPE (tmp), memsz));
5144 else if ((al->expr->ts.type == BT_CHARACTER && al->expr->ts.deferred)
5145 || unlimited_char)
5147 gcc_assert (code->ext.alloc.ts.u.cl && code->ext.alloc.ts.u.cl->length);
5148 gfc_init_se (&se_sz, NULL);
5149 gfc_conv_expr (&se_sz, code->ext.alloc.ts.u.cl->length);
5150 gfc_add_block_to_block (&se.pre, &se_sz.pre);
5151 se_sz.expr = gfc_evaluate_now (se_sz.expr, &se.pre);
5152 gfc_add_block_to_block (&se.pre, &se_sz.post);
5153 /* Store the string length. */
5154 if ((expr->symtree->n.sym->ts.type == BT_CLASS
5155 || expr->symtree->n.sym->ts.type == BT_DERIVED)
5156 && expr->ts.u.derived->attr.unlimited_polymorphic)
5157 /* For unlimited polymorphic entities get the backend_decl of
5158 the _len component for that. */
5159 tmp = gfc_class_len_get (gfc_get_symbol_decl (
5160 expr->symtree->n.sym));
5161 else
5162 /* Else use what is stored in the charlen->backend_decl. */
5163 tmp = al->expr->ts.u.cl->backend_decl;
5164 gfc_add_modify (&se.pre, tmp, fold_convert (TREE_TYPE (tmp),
5165 se_sz.expr));
5166 tmp = TREE_TYPE (gfc_typenode_for_spec (&code->ext.alloc.ts));
5167 tmp = TYPE_SIZE_UNIT (tmp);
5168 memsz = fold_build2_loc (input_location, MULT_EXPR,
5169 TREE_TYPE (tmp), tmp,
5170 fold_convert (TREE_TYPE (se_sz.expr),
5171 se_sz.expr));
5173 else if (code->ext.alloc.ts.type != BT_UNKNOWN)
5174 memsz = TYPE_SIZE_UNIT (gfc_typenode_for_spec (&code->ext.alloc.ts));
5175 else if (memsz == NULL_TREE)
5176 memsz = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (se.expr)));
5178 if (expr->ts.type == BT_CHARACTER && memsz == NULL_TREE)
5180 memsz = se.string_length;
5182 /* Convert to size in bytes, using the character KIND. */
5183 tmp = TREE_TYPE (gfc_typenode_for_spec (&code->ext.alloc.ts));
5184 tmp = TYPE_SIZE_UNIT (tmp);
5185 memsz = fold_build2_loc (input_location, MULT_EXPR,
5186 TREE_TYPE (tmp), tmp,
5187 fold_convert (TREE_TYPE (tmp), memsz));
5190 /* Allocate - for non-pointers with re-alloc checking. */
5191 if (gfc_expr_attr (expr).allocatable)
5192 gfc_allocate_allocatable (&se.pre, se.expr, memsz, NULL_TREE,
5193 stat, errmsg, errlen, label_finish, expr);
5194 else
5195 gfc_allocate_using_malloc (&se.pre, se.expr, memsz, stat);
5197 if (al->expr->ts.type == BT_DERIVED
5198 && expr->ts.u.derived->attr.alloc_comp)
5200 tmp = build_fold_indirect_ref_loc (input_location, se.expr);
5201 tmp = gfc_nullify_alloc_comp (expr->ts.u.derived, tmp, 0);
5202 gfc_add_expr_to_block (&se.pre, tmp);
5206 gfc_add_block_to_block (&block, &se.pre);
5208 /* Error checking -- Note: ERRMSG only makes sense with STAT. */
5209 if (code->expr1)
5211 tmp = build1_v (GOTO_EXPR, label_errmsg);
5212 parm = fold_build2_loc (input_location, NE_EXPR,
5213 boolean_type_node, stat,
5214 build_int_cst (TREE_TYPE (stat), 0));
5215 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
5216 gfc_unlikely (parm, PRED_FORTRAN_FAIL_ALLOC),
5217 tmp, build_empty_stmt (input_location));
5218 gfc_add_expr_to_block (&block, tmp);
5221 /* We need the vptr of CLASS objects to be initialized. */
5222 e = gfc_copy_expr (al->expr);
5223 if (e->ts.type == BT_CLASS)
5225 gfc_expr *lhs, *rhs;
5226 gfc_se lse;
5227 gfc_ref *ref, *class_ref, *tail;
5229 /* Find the last class reference. */
5230 class_ref = NULL;
5231 for (ref = e->ref; ref; ref = ref->next)
5233 if (ref->type == REF_COMPONENT
5234 && ref->u.c.component->ts.type == BT_CLASS)
5235 class_ref = ref;
5237 if (ref->next == NULL)
5238 break;
5241 /* Remove and store all subsequent references after the
5242 CLASS reference. */
5243 if (class_ref)
5245 tail = class_ref->next;
5246 class_ref->next = NULL;
5248 else
5250 tail = e->ref;
5251 e->ref = NULL;
5254 lhs = gfc_expr_to_initialize (e);
5255 gfc_add_vptr_component (lhs);
5257 /* Remove the _vptr component and restore the original tail
5258 references. */
5259 if (class_ref)
5261 gfc_free_ref_list (class_ref->next);
5262 class_ref->next = tail;
5264 else
5266 gfc_free_ref_list (e->ref);
5267 e->ref = tail;
5270 if (class_expr != NULL_TREE)
5272 /* Polymorphic SOURCE: VPTR must be determined at run time. */
5273 gfc_init_se (&lse, NULL);
5274 lse.want_pointer = 1;
5275 gfc_conv_expr (&lse, lhs);
5276 tmp = gfc_class_vptr_get (class_expr);
5277 gfc_add_modify (&block, lse.expr,
5278 fold_convert (TREE_TYPE (lse.expr), tmp));
5280 else if (code->expr3 && code->expr3->ts.type == BT_CLASS)
5282 /* Polymorphic SOURCE: VPTR must be determined at run time. */
5283 rhs = gfc_copy_expr (code->expr3);
5284 gfc_add_vptr_component (rhs);
5285 tmp = gfc_trans_pointer_assignment (lhs, rhs);
5286 gfc_add_expr_to_block (&block, tmp);
5287 gfc_free_expr (rhs);
5288 rhs = gfc_expr_to_initialize (e);
5290 else
5292 /* VPTR is fixed at compile time. */
5293 gfc_symbol *vtab;
5294 gfc_typespec *ts;
5295 if (code->expr3)
5296 ts = &code->expr3->ts;
5297 else if (e->ts.type == BT_DERIVED)
5298 ts = &e->ts;
5299 else if (code->ext.alloc.ts.type == BT_DERIVED || UNLIMITED_POLY (al->expr))
5300 ts = &code->ext.alloc.ts;
5301 else if (e->ts.type == BT_CLASS)
5302 ts = &CLASS_DATA (e)->ts;
5303 else
5304 ts = &e->ts;
5306 if (ts->type == BT_DERIVED || UNLIMITED_POLY (e))
5308 vtab = gfc_find_vtab (ts);
5309 gcc_assert (vtab);
5310 gfc_init_se (&lse, NULL);
5311 lse.want_pointer = 1;
5312 gfc_conv_expr (&lse, lhs);
5313 tmp = gfc_build_addr_expr (NULL_TREE,
5314 gfc_get_symbol_decl (vtab));
5315 gfc_add_modify (&block, lse.expr,
5316 fold_convert (TREE_TYPE (lse.expr), tmp));
5319 gfc_free_expr (lhs);
5322 gfc_free_expr (e);
5324 if (code->expr3 && !code->expr3->mold)
5326 /* Initialization via SOURCE block
5327 (or static default initializer). */
5328 gfc_expr *rhs = gfc_copy_expr (code->expr3);
5329 if (class_expr != NULL_TREE)
5331 tree to;
5332 to = TREE_OPERAND (se.expr, 0);
5334 tmp = gfc_copy_class_to_class (class_expr, to, nelems);
5336 else if (al->expr->ts.type == BT_CLASS)
5338 gfc_actual_arglist *actual;
5339 gfc_expr *ppc;
5340 gfc_code *ppc_code;
5341 gfc_ref *ref, *dataref;
5343 /* Do a polymorphic deep copy. */
5344 actual = gfc_get_actual_arglist ();
5345 actual->expr = gfc_copy_expr (rhs);
5346 if (rhs->ts.type == BT_CLASS)
5347 gfc_add_data_component (actual->expr);
5348 actual->next = gfc_get_actual_arglist ();
5349 actual->next->expr = gfc_copy_expr (al->expr);
5350 actual->next->expr->ts.type = BT_CLASS;
5351 gfc_add_data_component (actual->next->expr);
5353 dataref = NULL;
5354 /* Make sure we go up through the reference chain to
5355 the _data reference, where the arrayspec is found. */
5356 for (ref = actual->next->expr->ref; ref; ref = ref->next)
5357 if (ref->type == REF_COMPONENT
5358 && strcmp (ref->u.c.component->name, "_data") == 0)
5359 dataref = ref;
5361 if (dataref && dataref->u.c.component->as)
5363 int dim;
5364 gfc_expr *temp;
5365 gfc_ref *ref = dataref->next;
5366 ref->u.ar.type = AR_SECTION;
5367 /* We have to set up the array reference to give ranges
5368 in all dimensions and ensure that the end and stride
5369 are set so that the copy can be scalarized. */
5370 dim = 0;
5371 for (; dim < dataref->u.c.component->as->rank; dim++)
5373 ref->u.ar.dimen_type[dim] = DIMEN_RANGE;
5374 if (ref->u.ar.end[dim] == NULL)
5376 ref->u.ar.end[dim] = ref->u.ar.start[dim];
5377 temp = gfc_get_int_expr (gfc_default_integer_kind,
5378 &al->expr->where, 1);
5379 ref->u.ar.start[dim] = temp;
5381 temp = gfc_subtract (gfc_copy_expr (ref->u.ar.end[dim]),
5382 gfc_copy_expr (ref->u.ar.start[dim]));
5383 temp = gfc_add (gfc_get_int_expr (gfc_default_integer_kind,
5384 &al->expr->where, 1),
5385 temp);
5388 if (rhs->ts.type == BT_CLASS)
5390 ppc = gfc_copy_expr (rhs);
5391 gfc_add_vptr_component (ppc);
5393 else
5394 ppc = gfc_lval_expr_from_sym (gfc_find_vtab (&rhs->ts));
5395 gfc_add_component_ref (ppc, "_copy");
5397 ppc_code = gfc_get_code (EXEC_CALL);
5398 ppc_code->resolved_sym = ppc->symtree->n.sym;
5399 /* Although '_copy' is set to be elemental in class.c, it is
5400 not staying that way. Find out why, sometime.... */
5401 ppc_code->resolved_sym->attr.elemental = 1;
5402 ppc_code->ext.actual = actual;
5403 ppc_code->expr1 = ppc;
5404 /* Since '_copy' is elemental, the scalarizer will take care
5405 of arrays in gfc_trans_call. */
5406 tmp = gfc_trans_call (ppc_code, true, NULL, NULL, false);
5407 gfc_free_statements (ppc_code);
5409 else if (expr3 != NULL_TREE)
5411 tmp = build_fold_indirect_ref_loc (input_location, se.expr);
5412 gfc_trans_string_copy (&block, slen3, tmp, code->expr3->ts.kind,
5413 slen3, expr3, code->expr3->ts.kind);
5414 tmp = NULL_TREE;
5416 else
5418 /* Switch off automatic reallocation since we have just done
5419 the ALLOCATE. */
5420 int realloc_lhs = flag_realloc_lhs;
5421 flag_realloc_lhs = 0;
5422 tmp = gfc_trans_assignment (gfc_expr_to_initialize (expr),
5423 rhs, false, false);
5424 flag_realloc_lhs = realloc_lhs;
5426 gfc_free_expr (rhs);
5427 gfc_add_expr_to_block (&block, tmp);
5429 else if (code->expr3 && code->expr3->mold
5430 && code->expr3->ts.type == BT_CLASS)
5432 /* Since the _vptr has already been assigned to the allocate
5433 object, we can use gfc_copy_class_to_class in its
5434 initialization mode. */
5435 tmp = TREE_OPERAND (se.expr, 0);
5436 tmp = gfc_copy_class_to_class (NULL_TREE, tmp, nelems);
5437 gfc_add_expr_to_block (&block, tmp);
5440 gfc_free_expr (expr);
5443 /* STAT. */
5444 if (code->expr1)
5446 tmp = build1_v (LABEL_EXPR, label_errmsg);
5447 gfc_add_expr_to_block (&block, tmp);
5450 /* ERRMSG - only useful if STAT is present. */
5451 if (code->expr1 && code->expr2)
5453 const char *msg = "Attempt to allocate an allocated object";
5454 tree slen, dlen, errmsg_str;
5455 stmtblock_t errmsg_block;
5457 gfc_init_block (&errmsg_block);
5459 errmsg_str = gfc_create_var (pchar_type_node, "ERRMSG");
5460 gfc_add_modify (&errmsg_block, errmsg_str,
5461 gfc_build_addr_expr (pchar_type_node,
5462 gfc_build_localized_cstring_const (msg)));
5464 slen = build_int_cst (gfc_charlen_type_node, ((int) strlen (msg)));
5465 dlen = gfc_get_expr_charlen (code->expr2);
5466 slen = fold_build2_loc (input_location, MIN_EXPR, TREE_TYPE (slen), dlen,
5467 slen);
5469 gfc_trans_string_copy (&errmsg_block, dlen, errmsg, code->expr2->ts.kind,
5470 slen, errmsg_str, gfc_default_character_kind);
5471 dlen = gfc_finish_block (&errmsg_block);
5473 tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, stat,
5474 build_int_cst (TREE_TYPE (stat), 0));
5476 tmp = build3_v (COND_EXPR, tmp, dlen, build_empty_stmt (input_location));
5478 gfc_add_expr_to_block (&block, tmp);
5481 /* STAT block. */
5482 if (code->expr1)
5484 if (TREE_USED (label_finish))
5486 tmp = build1_v (LABEL_EXPR, label_finish);
5487 gfc_add_expr_to_block (&block, tmp);
5490 gfc_init_se (&se, NULL);
5491 gfc_conv_expr_lhs (&se, code->expr1);
5492 tmp = convert (TREE_TYPE (se.expr), stat);
5493 gfc_add_modify (&block, se.expr, tmp);
5496 gfc_add_block_to_block (&block, &se.post);
5497 gfc_add_block_to_block (&block, &post);
5499 return gfc_finish_block (&block);
5503 /* Translate a DEALLOCATE statement. */
5505 tree
5506 gfc_trans_deallocate (gfc_code *code)
5508 gfc_se se;
5509 gfc_alloc *al;
5510 tree apstat, pstat, stat, errmsg, errlen, tmp;
5511 tree label_finish, label_errmsg;
5512 stmtblock_t block;
5514 pstat = apstat = stat = errmsg = errlen = tmp = NULL_TREE;
5515 label_finish = label_errmsg = NULL_TREE;
5517 gfc_start_block (&block);
5519 /* Count the number of failed deallocations. If deallocate() was
5520 called with STAT= , then set STAT to the count. If deallocate
5521 was called with ERRMSG, then set ERRMG to a string. */
5522 if (code->expr1)
5524 tree gfc_int4_type_node = gfc_get_int_type (4);
5526 stat = gfc_create_var (gfc_int4_type_node, "stat");
5527 pstat = gfc_build_addr_expr (NULL_TREE, stat);
5529 /* GOTO destinations. */
5530 label_errmsg = gfc_build_label_decl (NULL_TREE);
5531 label_finish = gfc_build_label_decl (NULL_TREE);
5532 TREE_USED (label_finish) = 0;
5535 /* Set ERRMSG - only needed if STAT is available. */
5536 if (code->expr1 && code->expr2)
5538 gfc_init_se (&se, NULL);
5539 se.want_pointer = 1;
5540 gfc_conv_expr_lhs (&se, code->expr2);
5541 errmsg = se.expr;
5542 errlen = se.string_length;
5545 for (al = code->ext.alloc.list; al != NULL; al = al->next)
5547 gfc_expr *expr = gfc_copy_expr (al->expr);
5548 gcc_assert (expr->expr_type == EXPR_VARIABLE);
5550 if (expr->ts.type == BT_CLASS)
5551 gfc_add_data_component (expr);
5553 gfc_init_se (&se, NULL);
5554 gfc_start_block (&se.pre);
5556 se.want_pointer = 1;
5557 se.descriptor_only = 1;
5558 gfc_conv_expr (&se, expr);
5560 if (expr->rank || gfc_is_coarray (expr))
5562 gfc_ref *ref;
5564 if (expr->ts.type == BT_DERIVED && expr->ts.u.derived->attr.alloc_comp
5565 && !gfc_is_finalizable (expr->ts.u.derived, NULL))
5567 gfc_ref *last = NULL;
5569 for (ref = expr->ref; ref; ref = ref->next)
5570 if (ref->type == REF_COMPONENT)
5571 last = ref;
5573 /* Do not deallocate the components of a derived type
5574 ultimate pointer component. */
5575 if (!(last && last->u.c.component->attr.pointer)
5576 && !(!last && expr->symtree->n.sym->attr.pointer))
5578 tmp = gfc_deallocate_alloc_comp (expr->ts.u.derived, se.expr,
5579 expr->rank);
5580 gfc_add_expr_to_block (&se.pre, tmp);
5584 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (se.expr)))
5586 tmp = gfc_array_deallocate (se.expr, pstat, errmsg, errlen,
5587 label_finish, expr);
5588 gfc_add_expr_to_block (&se.pre, tmp);
5590 else if (TREE_CODE (se.expr) == COMPONENT_REF
5591 && TREE_CODE (TREE_TYPE (se.expr)) == ARRAY_TYPE
5592 && TREE_CODE (TREE_TYPE (TREE_TYPE (se.expr)))
5593 == RECORD_TYPE)
5595 /* class.c(finalize_component) generates these, when a
5596 finalizable entity has a non-allocatable derived type array
5597 component, which has allocatable components. Obtain the
5598 derived type of the array and deallocate the allocatable
5599 components. */
5600 for (ref = expr->ref; ref; ref = ref->next)
5602 if (ref->u.c.component->attr.dimension
5603 && ref->u.c.component->ts.type == BT_DERIVED)
5604 break;
5607 if (ref && ref->u.c.component->ts.u.derived->attr.alloc_comp
5608 && !gfc_is_finalizable (ref->u.c.component->ts.u.derived,
5609 NULL))
5611 tmp = gfc_deallocate_alloc_comp
5612 (ref->u.c.component->ts.u.derived,
5613 se.expr, expr->rank);
5614 gfc_add_expr_to_block (&se.pre, tmp);
5618 if (al->expr->ts.type == BT_CLASS)
5619 gfc_reset_vptr (&se.pre, al->expr);
5621 else
5623 tmp = gfc_deallocate_scalar_with_status (se.expr, pstat, false,
5624 al->expr, al->expr->ts);
5625 gfc_add_expr_to_block (&se.pre, tmp);
5627 /* Set to zero after deallocation. */
5628 tmp = fold_build2_loc (input_location, MODIFY_EXPR, void_type_node,
5629 se.expr,
5630 build_int_cst (TREE_TYPE (se.expr), 0));
5631 gfc_add_expr_to_block (&se.pre, tmp);
5633 if (al->expr->ts.type == BT_CLASS)
5634 gfc_reset_vptr (&se.pre, al->expr);
5637 if (code->expr1)
5639 tree cond;
5641 cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, stat,
5642 build_int_cst (TREE_TYPE (stat), 0));
5643 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
5644 gfc_unlikely (cond, PRED_FORTRAN_FAIL_ALLOC),
5645 build1_v (GOTO_EXPR, label_errmsg),
5646 build_empty_stmt (input_location));
5647 gfc_add_expr_to_block (&se.pre, tmp);
5650 tmp = gfc_finish_block (&se.pre);
5651 gfc_add_expr_to_block (&block, tmp);
5652 gfc_free_expr (expr);
5655 if (code->expr1)
5657 tmp = build1_v (LABEL_EXPR, label_errmsg);
5658 gfc_add_expr_to_block (&block, tmp);
5661 /* Set ERRMSG - only needed if STAT is available. */
5662 if (code->expr1 && code->expr2)
5664 const char *msg = "Attempt to deallocate an unallocated object";
5665 stmtblock_t errmsg_block;
5666 tree errmsg_str, slen, dlen, cond;
5668 gfc_init_block (&errmsg_block);
5670 errmsg_str = gfc_create_var (pchar_type_node, "ERRMSG");
5671 gfc_add_modify (&errmsg_block, errmsg_str,
5672 gfc_build_addr_expr (pchar_type_node,
5673 gfc_build_localized_cstring_const (msg)));
5674 slen = build_int_cst (gfc_charlen_type_node, ((int) strlen (msg)));
5675 dlen = gfc_get_expr_charlen (code->expr2);
5677 gfc_trans_string_copy (&errmsg_block, dlen, errmsg, code->expr2->ts.kind,
5678 slen, errmsg_str, gfc_default_character_kind);
5679 tmp = gfc_finish_block (&errmsg_block);
5681 cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, stat,
5682 build_int_cst (TREE_TYPE (stat), 0));
5683 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
5684 gfc_unlikely (cond, PRED_FORTRAN_FAIL_ALLOC), tmp,
5685 build_empty_stmt (input_location));
5687 gfc_add_expr_to_block (&block, tmp);
5690 if (code->expr1 && TREE_USED (label_finish))
5692 tmp = build1_v (LABEL_EXPR, label_finish);
5693 gfc_add_expr_to_block (&block, tmp);
5696 /* Set STAT. */
5697 if (code->expr1)
5699 gfc_init_se (&se, NULL);
5700 gfc_conv_expr_lhs (&se, code->expr1);
5701 tmp = convert (TREE_TYPE (se.expr), stat);
5702 gfc_add_modify (&block, se.expr, tmp);
5705 return gfc_finish_block (&block);
5708 #include "gt-fortran-trans-stmt.h"