2016-09-19 Richard Biener <rguenther@suse.de>
[official-gcc.git] / gcc / fortran / trans-stmt.c
blob5884e7a4e24358ec1124f5728b085e18cf488f08
1 /* Statement translation -- generate GCC trees from gfc_code.
2 Copyright (C) 2002-2016 Free Software Foundation, Inc.
3 Contributed by Paul Brook <paul@nowt.org>
4 and Steven Bosscher <s.bosscher@student.tudelft.nl>
6 This file is part of GCC.
8 GCC is free software; you can redistribute it and/or modify it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 3, or (at your option) any later
11 version.
13 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 for more details.
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING3. If not see
20 <http://www.gnu.org/licenses/>. */
23 #include "config.h"
24 #include "system.h"
25 #include "coretypes.h"
26 #include "options.h"
27 #include "tree.h"
28 #include "gfortran.h"
29 #include "trans.h"
30 #include "stringpool.h"
31 #include "fold-const.h"
32 #include "trans-stmt.h"
33 #include "trans-types.h"
34 #include "trans-array.h"
35 #include "trans-const.h"
36 #include "dependency.h"
38 typedef struct iter_info
40 tree var;
41 tree start;
42 tree end;
43 tree step;
44 struct iter_info *next;
46 iter_info;
48 typedef struct forall_info
50 iter_info *this_loop;
51 tree mask;
52 tree maskindex;
53 int nvar;
54 tree size;
55 struct forall_info *prev_nest;
56 bool do_concurrent;
58 forall_info;
60 static void gfc_trans_where_2 (gfc_code *, tree, bool,
61 forall_info *, stmtblock_t *);
63 /* Translate a F95 label number to a LABEL_EXPR. */
65 tree
66 gfc_trans_label_here (gfc_code * code)
68 return build1_v (LABEL_EXPR, gfc_get_label_decl (code->here));
72 /* Given a variable expression which has been ASSIGNed to, find the decl
73 containing the auxiliary variables. For variables in common blocks this
74 is a field_decl. */
76 void
77 gfc_conv_label_variable (gfc_se * se, gfc_expr * expr)
79 gcc_assert (expr->symtree->n.sym->attr.assign == 1);
80 gfc_conv_expr (se, expr);
81 /* Deals with variable in common block. Get the field declaration. */
82 if (TREE_CODE (se->expr) == COMPONENT_REF)
83 se->expr = TREE_OPERAND (se->expr, 1);
84 /* Deals with dummy argument. Get the parameter declaration. */
85 else if (TREE_CODE (se->expr) == INDIRECT_REF)
86 se->expr = TREE_OPERAND (se->expr, 0);
89 /* Translate a label assignment statement. */
91 tree
92 gfc_trans_label_assign (gfc_code * code)
94 tree label_tree;
95 gfc_se se;
96 tree len;
97 tree addr;
98 tree len_tree;
99 int label_len;
101 /* Start a new block. */
102 gfc_init_se (&se, NULL);
103 gfc_start_block (&se.pre);
104 gfc_conv_label_variable (&se, code->expr1);
106 len = GFC_DECL_STRING_LEN (se.expr);
107 addr = GFC_DECL_ASSIGN_ADDR (se.expr);
109 label_tree = gfc_get_label_decl (code->label1);
111 if (code->label1->defined == ST_LABEL_TARGET
112 || code->label1->defined == ST_LABEL_DO_TARGET)
114 label_tree = gfc_build_addr_expr (pvoid_type_node, label_tree);
115 len_tree = integer_minus_one_node;
117 else
119 gfc_expr *format = code->label1->format;
121 label_len = format->value.character.length;
122 len_tree = build_int_cst (gfc_charlen_type_node, label_len);
123 label_tree = gfc_build_wide_string_const (format->ts.kind, label_len + 1,
124 format->value.character.string);
125 label_tree = gfc_build_addr_expr (pvoid_type_node, label_tree);
128 gfc_add_modify (&se.pre, len, len_tree);
129 gfc_add_modify (&se.pre, addr, label_tree);
131 return gfc_finish_block (&se.pre);
134 /* Translate a GOTO statement. */
136 tree
137 gfc_trans_goto (gfc_code * code)
139 locus loc = code->loc;
140 tree assigned_goto;
141 tree target;
142 tree tmp;
143 gfc_se se;
145 if (code->label1 != NULL)
146 return build1_v (GOTO_EXPR, gfc_get_label_decl (code->label1));
148 /* ASSIGNED GOTO. */
149 gfc_init_se (&se, NULL);
150 gfc_start_block (&se.pre);
151 gfc_conv_label_variable (&se, code->expr1);
152 tmp = GFC_DECL_STRING_LEN (se.expr);
153 tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, tmp,
154 build_int_cst (TREE_TYPE (tmp), -1));
155 gfc_trans_runtime_check (true, false, tmp, &se.pre, &loc,
156 "Assigned label is not a target label");
158 assigned_goto = GFC_DECL_ASSIGN_ADDR (se.expr);
160 /* We're going to ignore a label list. It does not really change the
161 statement's semantics (because it is just a further restriction on
162 what's legal code); before, we were comparing label addresses here, but
163 that's a very fragile business and may break with optimization. So
164 just ignore it. */
166 target = fold_build1_loc (input_location, GOTO_EXPR, void_type_node,
167 assigned_goto);
168 gfc_add_expr_to_block (&se.pre, target);
169 return gfc_finish_block (&se.pre);
173 /* Translate an ENTRY statement. Just adds a label for this entry point. */
174 tree
175 gfc_trans_entry (gfc_code * code)
177 return build1_v (LABEL_EXPR, code->ext.entry->label);
181 /* Replace a gfc_ss structure by another both in the gfc_se struct
182 and the gfc_loopinfo struct. This is used in gfc_conv_elemental_dependencies
183 to replace a variable ss by the corresponding temporary. */
185 static void
186 replace_ss (gfc_se *se, gfc_ss *old_ss, gfc_ss *new_ss)
188 gfc_ss **sess, **loopss;
190 /* The old_ss is a ss for a single variable. */
191 gcc_assert (old_ss->info->type == GFC_SS_SECTION);
193 for (sess = &(se->ss); *sess != gfc_ss_terminator; sess = &((*sess)->next))
194 if (*sess == old_ss)
195 break;
196 gcc_assert (*sess != gfc_ss_terminator);
198 *sess = new_ss;
199 new_ss->next = old_ss->next;
202 for (loopss = &(se->loop->ss); *loopss != gfc_ss_terminator;
203 loopss = &((*loopss)->loop_chain))
204 if (*loopss == old_ss)
205 break;
206 gcc_assert (*loopss != gfc_ss_terminator);
208 *loopss = new_ss;
209 new_ss->loop_chain = old_ss->loop_chain;
210 new_ss->loop = old_ss->loop;
212 gfc_free_ss (old_ss);
216 /* Check for dependencies between INTENT(IN) and INTENT(OUT) arguments of
217 elemental subroutines. Make temporaries for output arguments if any such
218 dependencies are found. Output arguments are chosen because internal_unpack
219 can be used, as is, to copy the result back to the variable. */
220 static void
221 gfc_conv_elemental_dependencies (gfc_se * se, gfc_se * loopse,
222 gfc_symbol * sym, gfc_actual_arglist * arg,
223 gfc_dep_check check_variable)
225 gfc_actual_arglist *arg0;
226 gfc_expr *e;
227 gfc_formal_arglist *formal;
228 gfc_se parmse;
229 gfc_ss *ss;
230 gfc_symbol *fsym;
231 tree data;
232 tree size;
233 tree tmp;
235 if (loopse->ss == NULL)
236 return;
238 ss = loopse->ss;
239 arg0 = arg;
240 formal = gfc_sym_get_dummy_args (sym);
242 /* Loop over all the arguments testing for dependencies. */
243 for (; arg != NULL; arg = arg->next, formal = formal ? formal->next : NULL)
245 e = arg->expr;
246 if (e == NULL)
247 continue;
249 /* Obtain the info structure for the current argument. */
250 for (ss = loopse->ss; ss && ss != gfc_ss_terminator; ss = ss->next)
251 if (ss->info->expr == e)
252 break;
254 /* If there is a dependency, create a temporary and use it
255 instead of the variable. */
256 fsym = formal ? formal->sym : NULL;
257 if (e->expr_type == EXPR_VARIABLE
258 && e->rank && fsym
259 && fsym->attr.intent != INTENT_IN
260 && gfc_check_fncall_dependency (e, fsym->attr.intent,
261 sym, arg0, check_variable))
263 tree initial, temptype;
264 stmtblock_t temp_post;
265 gfc_ss *tmp_ss;
267 tmp_ss = gfc_get_array_ss (gfc_ss_terminator, NULL, ss->dimen,
268 GFC_SS_SECTION);
269 gfc_mark_ss_chain_used (tmp_ss, 1);
270 tmp_ss->info->expr = ss->info->expr;
271 replace_ss (loopse, ss, tmp_ss);
273 /* Obtain the argument descriptor for unpacking. */
274 gfc_init_se (&parmse, NULL);
275 parmse.want_pointer = 1;
276 gfc_conv_expr_descriptor (&parmse, e);
277 gfc_add_block_to_block (&se->pre, &parmse.pre);
279 /* If we've got INTENT(INOUT) or a derived type with INTENT(OUT),
280 initialize the array temporary with a copy of the values. */
281 if (fsym->attr.intent == INTENT_INOUT
282 || (fsym->ts.type ==BT_DERIVED
283 && fsym->attr.intent == INTENT_OUT))
284 initial = parmse.expr;
285 /* For class expressions, we always initialize with the copy of
286 the values. */
287 else if (e->ts.type == BT_CLASS)
288 initial = parmse.expr;
289 else
290 initial = NULL_TREE;
292 if (e->ts.type != BT_CLASS)
294 /* Find the type of the temporary to create; we don't use the type
295 of e itself as this breaks for subcomponent-references in e
296 (where the type of e is that of the final reference, but
297 parmse.expr's type corresponds to the full derived-type). */
298 /* TODO: Fix this somehow so we don't need a temporary of the whole
299 array but instead only the components referenced. */
300 temptype = TREE_TYPE (parmse.expr); /* Pointer to descriptor. */
301 gcc_assert (TREE_CODE (temptype) == POINTER_TYPE);
302 temptype = TREE_TYPE (temptype);
303 temptype = gfc_get_element_type (temptype);
306 else
307 /* For class arrays signal that the size of the dynamic type has to
308 be obtained from the vtable, using the 'initial' expression. */
309 temptype = NULL_TREE;
311 /* Generate the temporary. Cleaning up the temporary should be the
312 very last thing done, so we add the code to a new block and add it
313 to se->post as last instructions. */
314 size = gfc_create_var (gfc_array_index_type, NULL);
315 data = gfc_create_var (pvoid_type_node, NULL);
316 gfc_init_block (&temp_post);
317 tmp = gfc_trans_create_temp_array (&se->pre, &temp_post, tmp_ss,
318 temptype, initial, false, true,
319 false, &arg->expr->where);
320 gfc_add_modify (&se->pre, size, tmp);
321 tmp = fold_convert (pvoid_type_node, tmp_ss->info->data.array.data);
322 gfc_add_modify (&se->pre, data, tmp);
324 /* Update other ss' delta. */
325 gfc_set_delta (loopse->loop);
327 /* Copy the result back using unpack..... */
328 if (e->ts.type != BT_CLASS)
329 tmp = build_call_expr_loc (input_location,
330 gfor_fndecl_in_unpack, 2, parmse.expr, data);
331 else
333 /* ... except for class results where the copy is
334 unconditional. */
335 tmp = build_fold_indirect_ref_loc (input_location, parmse.expr);
336 tmp = gfc_conv_descriptor_data_get (tmp);
337 tmp = build_call_expr_loc (input_location,
338 builtin_decl_explicit (BUILT_IN_MEMCPY),
339 3, tmp, data,
340 fold_convert (size_type_node, size));
342 gfc_add_expr_to_block (&se->post, tmp);
344 /* parmse.pre is already added above. */
345 gfc_add_block_to_block (&se->post, &parmse.post);
346 gfc_add_block_to_block (&se->post, &temp_post);
352 /* Get the interface symbol for the procedure corresponding to the given call.
353 We can't get the procedure symbol directly as we have to handle the case
354 of (deferred) type-bound procedures. */
356 static gfc_symbol *
357 get_proc_ifc_for_call (gfc_code *c)
359 gfc_symbol *sym;
361 gcc_assert (c->op == EXEC_ASSIGN_CALL || c->op == EXEC_CALL);
363 sym = gfc_get_proc_ifc_for_expr (c->expr1);
365 /* Fall back/last resort try. */
366 if (sym == NULL)
367 sym = c->resolved_sym;
369 return sym;
373 /* Translate the CALL statement. Builds a call to an F95 subroutine. */
375 tree
376 gfc_trans_call (gfc_code * code, bool dependency_check,
377 tree mask, tree count1, bool invert)
379 gfc_se se;
380 gfc_ss * ss;
381 int has_alternate_specifier;
382 gfc_dep_check check_variable;
383 tree index = NULL_TREE;
384 tree maskexpr = NULL_TREE;
385 tree tmp;
387 /* A CALL starts a new block because the actual arguments may have to
388 be evaluated first. */
389 gfc_init_se (&se, NULL);
390 gfc_start_block (&se.pre);
392 gcc_assert (code->resolved_sym);
394 ss = gfc_ss_terminator;
395 if (code->resolved_sym->attr.elemental)
396 ss = gfc_walk_elemental_function_args (ss, code->ext.actual,
397 get_proc_ifc_for_call (code),
398 GFC_SS_REFERENCE);
400 /* Is not an elemental subroutine call with array valued arguments. */
401 if (ss == gfc_ss_terminator)
404 /* Translate the call. */
405 has_alternate_specifier
406 = gfc_conv_procedure_call (&se, code->resolved_sym, code->ext.actual,
407 code->expr1, NULL);
409 /* A subroutine without side-effect, by definition, does nothing! */
410 TREE_SIDE_EFFECTS (se.expr) = 1;
412 /* Chain the pieces together and return the block. */
413 if (has_alternate_specifier)
415 gfc_code *select_code;
416 gfc_symbol *sym;
417 select_code = code->next;
418 gcc_assert(select_code->op == EXEC_SELECT);
419 sym = select_code->expr1->symtree->n.sym;
420 se.expr = convert (gfc_typenode_for_spec (&sym->ts), se.expr);
421 if (sym->backend_decl == NULL)
422 sym->backend_decl = gfc_get_symbol_decl (sym);
423 gfc_add_modify (&se.pre, sym->backend_decl, se.expr);
425 else
426 gfc_add_expr_to_block (&se.pre, se.expr);
428 gfc_add_block_to_block (&se.pre, &se.post);
431 else
433 /* An elemental subroutine call with array valued arguments has
434 to be scalarized. */
435 gfc_loopinfo loop;
436 stmtblock_t body;
437 stmtblock_t block;
438 gfc_se loopse;
439 gfc_se depse;
441 /* gfc_walk_elemental_function_args renders the ss chain in the
442 reverse order to the actual argument order. */
443 ss = gfc_reverse_ss (ss);
445 /* Initialize the loop. */
446 gfc_init_se (&loopse, NULL);
447 gfc_init_loopinfo (&loop);
448 gfc_add_ss_to_loop (&loop, ss);
450 gfc_conv_ss_startstride (&loop);
451 /* TODO: gfc_conv_loop_setup generates a temporary for vector
452 subscripts. This could be prevented in the elemental case
453 as temporaries are handled separatedly
454 (below in gfc_conv_elemental_dependencies). */
455 gfc_conv_loop_setup (&loop, &code->expr1->where);
456 gfc_mark_ss_chain_used (ss, 1);
458 /* Convert the arguments, checking for dependencies. */
459 gfc_copy_loopinfo_to_se (&loopse, &loop);
460 loopse.ss = ss;
462 /* For operator assignment, do dependency checking. */
463 if (dependency_check)
464 check_variable = ELEM_CHECK_VARIABLE;
465 else
466 check_variable = ELEM_DONT_CHECK_VARIABLE;
468 gfc_init_se (&depse, NULL);
469 gfc_conv_elemental_dependencies (&depse, &loopse, code->resolved_sym,
470 code->ext.actual, check_variable);
472 gfc_add_block_to_block (&loop.pre, &depse.pre);
473 gfc_add_block_to_block (&loop.post, &depse.post);
475 /* Generate the loop body. */
476 gfc_start_scalarized_body (&loop, &body);
477 gfc_init_block (&block);
479 if (mask && count1)
481 /* Form the mask expression according to the mask. */
482 index = count1;
483 maskexpr = gfc_build_array_ref (mask, index, NULL);
484 if (invert)
485 maskexpr = fold_build1_loc (input_location, TRUTH_NOT_EXPR,
486 TREE_TYPE (maskexpr), maskexpr);
489 /* Add the subroutine call to the block. */
490 gfc_conv_procedure_call (&loopse, code->resolved_sym,
491 code->ext.actual, code->expr1,
492 NULL);
494 if (mask && count1)
496 tmp = build3_v (COND_EXPR, maskexpr, loopse.expr,
497 build_empty_stmt (input_location));
498 gfc_add_expr_to_block (&loopse.pre, tmp);
499 tmp = fold_build2_loc (input_location, PLUS_EXPR,
500 gfc_array_index_type,
501 count1, gfc_index_one_node);
502 gfc_add_modify (&loopse.pre, count1, tmp);
504 else
505 gfc_add_expr_to_block (&loopse.pre, loopse.expr);
507 gfc_add_block_to_block (&block, &loopse.pre);
508 gfc_add_block_to_block (&block, &loopse.post);
510 /* Finish up the loop block and the loop. */
511 gfc_add_expr_to_block (&body, gfc_finish_block (&block));
512 gfc_trans_scalarizing_loops (&loop, &body);
513 gfc_add_block_to_block (&se.pre, &loop.pre);
514 gfc_add_block_to_block (&se.pre, &loop.post);
515 gfc_add_block_to_block (&se.pre, &se.post);
516 gfc_cleanup_loop (&loop);
519 return gfc_finish_block (&se.pre);
523 /* Translate the RETURN statement. */
525 tree
526 gfc_trans_return (gfc_code * code)
528 if (code->expr1)
530 gfc_se se;
531 tree tmp;
532 tree result;
534 /* If code->expr is not NULL, this return statement must appear
535 in a subroutine and current_fake_result_decl has already
536 been generated. */
538 result = gfc_get_fake_result_decl (NULL, 0);
539 if (!result)
541 gfc_warning (0,
542 "An alternate return at %L without a * dummy argument",
543 &code->expr1->where);
544 return gfc_generate_return ();
547 /* Start a new block for this statement. */
548 gfc_init_se (&se, NULL);
549 gfc_start_block (&se.pre);
551 gfc_conv_expr (&se, code->expr1);
553 /* Note that the actually returned expression is a simple value and
554 does not depend on any pointers or such; thus we can clean-up with
555 se.post before returning. */
556 tmp = fold_build2_loc (input_location, MODIFY_EXPR, TREE_TYPE (result),
557 result, fold_convert (TREE_TYPE (result),
558 se.expr));
559 gfc_add_expr_to_block (&se.pre, tmp);
560 gfc_add_block_to_block (&se.pre, &se.post);
562 tmp = gfc_generate_return ();
563 gfc_add_expr_to_block (&se.pre, tmp);
564 return gfc_finish_block (&se.pre);
567 return gfc_generate_return ();
571 /* Translate the PAUSE statement. We have to translate this statement
572 to a runtime library call. */
574 tree
575 gfc_trans_pause (gfc_code * code)
577 tree gfc_int4_type_node = gfc_get_int_type (4);
578 gfc_se se;
579 tree tmp;
581 /* Start a new block for this statement. */
582 gfc_init_se (&se, NULL);
583 gfc_start_block (&se.pre);
586 if (code->expr1 == NULL)
588 tmp = build_int_cst (gfc_int4_type_node, 0);
589 tmp = build_call_expr_loc (input_location,
590 gfor_fndecl_pause_string, 2,
591 build_int_cst (pchar_type_node, 0), tmp);
593 else if (code->expr1->ts.type == BT_INTEGER)
595 gfc_conv_expr (&se, code->expr1);
596 tmp = build_call_expr_loc (input_location,
597 gfor_fndecl_pause_numeric, 1,
598 fold_convert (gfc_int4_type_node, se.expr));
600 else
602 gfc_conv_expr_reference (&se, code->expr1);
603 tmp = build_call_expr_loc (input_location,
604 gfor_fndecl_pause_string, 2,
605 se.expr, se.string_length);
608 gfc_add_expr_to_block (&se.pre, tmp);
610 gfc_add_block_to_block (&se.pre, &se.post);
612 return gfc_finish_block (&se.pre);
616 /* Translate the STOP statement. We have to translate this statement
617 to a runtime library call. */
619 tree
620 gfc_trans_stop (gfc_code *code, bool error_stop)
622 tree gfc_int4_type_node = gfc_get_int_type (4);
623 gfc_se se;
624 tree tmp;
626 /* Start a new block for this statement. */
627 gfc_init_se (&se, NULL);
628 gfc_start_block (&se.pre);
630 if (code->expr1 == NULL)
632 tmp = build_int_cst (gfc_int4_type_node, 0);
633 tmp = build_call_expr_loc (input_location,
634 error_stop
635 ? (flag_coarray == GFC_FCOARRAY_LIB
636 ? gfor_fndecl_caf_error_stop_str
637 : gfor_fndecl_error_stop_string)
638 : (flag_coarray == GFC_FCOARRAY_LIB
639 ? gfor_fndecl_caf_stop_str
640 : gfor_fndecl_stop_string),
641 2, build_int_cst (pchar_type_node, 0), tmp);
643 else if (code->expr1->ts.type == BT_INTEGER)
645 gfc_conv_expr (&se, code->expr1);
646 tmp = build_call_expr_loc (input_location,
647 error_stop
648 ? (flag_coarray == GFC_FCOARRAY_LIB
649 ? gfor_fndecl_caf_error_stop
650 : gfor_fndecl_error_stop_numeric)
651 : (flag_coarray == GFC_FCOARRAY_LIB
652 ? gfor_fndecl_caf_stop_numeric
653 : gfor_fndecl_stop_numeric_f08), 1,
654 fold_convert (gfc_int4_type_node, se.expr));
656 else
658 gfc_conv_expr_reference (&se, code->expr1);
659 tmp = build_call_expr_loc (input_location,
660 error_stop
661 ? (flag_coarray == GFC_FCOARRAY_LIB
662 ? gfor_fndecl_caf_error_stop_str
663 : gfor_fndecl_error_stop_string)
664 : (flag_coarray == GFC_FCOARRAY_LIB
665 ? gfor_fndecl_caf_stop_str
666 : gfor_fndecl_stop_string),
667 2, se.expr, se.string_length);
670 gfc_add_expr_to_block (&se.pre, tmp);
672 gfc_add_block_to_block (&se.pre, &se.post);
674 return gfc_finish_block (&se.pre);
678 tree
679 gfc_trans_lock_unlock (gfc_code *code, gfc_exec_op op)
681 gfc_se se, argse;
682 tree stat = NULL_TREE, stat2 = NULL_TREE;
683 tree lock_acquired = NULL_TREE, lock_acquired2 = NULL_TREE;
685 /* Short cut: For single images without STAT= or LOCK_ACQUIRED
686 return early. (ERRMSG= is always untouched for -fcoarray=single.) */
687 if (!code->expr2 && !code->expr4 && flag_coarray != GFC_FCOARRAY_LIB)
688 return NULL_TREE;
690 if (code->expr2)
692 gcc_assert (code->expr2->expr_type == EXPR_VARIABLE);
693 gfc_init_se (&argse, NULL);
694 gfc_conv_expr_val (&argse, code->expr2);
695 stat = argse.expr;
697 else if (flag_coarray == GFC_FCOARRAY_LIB)
698 stat = null_pointer_node;
700 if (code->expr4)
702 gcc_assert (code->expr4->expr_type == EXPR_VARIABLE);
703 gfc_init_se (&argse, NULL);
704 gfc_conv_expr_val (&argse, code->expr4);
705 lock_acquired = argse.expr;
707 else if (flag_coarray == GFC_FCOARRAY_LIB)
708 lock_acquired = null_pointer_node;
710 gfc_start_block (&se.pre);
711 if (flag_coarray == GFC_FCOARRAY_LIB)
713 tree tmp, token, image_index, errmsg, errmsg_len;
714 tree index = size_zero_node;
715 tree caf_decl = gfc_get_tree_for_caf_expr (code->expr1);
717 if (code->expr1->symtree->n.sym->ts.type != BT_DERIVED
718 || code->expr1->symtree->n.sym->ts.u.derived->from_intmod
719 != INTMOD_ISO_FORTRAN_ENV
720 || code->expr1->symtree->n.sym->ts.u.derived->intmod_sym_id
721 != ISOFORTRAN_LOCK_TYPE)
723 gfc_error ("Sorry, the lock component of derived type at %L is not "
724 "yet supported", &code->expr1->where);
725 return NULL_TREE;
728 gfc_get_caf_token_offset (&token, NULL, caf_decl, NULL_TREE, code->expr1);
730 if (gfc_is_coindexed (code->expr1))
731 image_index = gfc_caf_get_image_index (&se.pre, code->expr1, caf_decl);
732 else
733 image_index = integer_zero_node;
735 /* For arrays, obtain the array index. */
736 if (gfc_expr_attr (code->expr1).dimension)
738 tree desc, tmp, extent, lbound, ubound;
739 gfc_array_ref *ar, ar2;
740 int i;
742 /* TODO: Extend this, once DT components are supported. */
743 ar = &code->expr1->ref->u.ar;
744 ar2 = *ar;
745 memset (ar, '\0', sizeof (*ar));
746 ar->as = ar2.as;
747 ar->type = AR_FULL;
749 gfc_init_se (&argse, NULL);
750 argse.descriptor_only = 1;
751 gfc_conv_expr_descriptor (&argse, code->expr1);
752 gfc_add_block_to_block (&se.pre, &argse.pre);
753 desc = argse.expr;
754 *ar = ar2;
756 extent = integer_one_node;
757 for (i = 0; i < ar->dimen; i++)
759 gfc_init_se (&argse, NULL);
760 gfc_conv_expr_type (&argse, ar->start[i], integer_type_node);
761 gfc_add_block_to_block (&argse.pre, &argse.pre);
762 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[i]);
763 tmp = fold_build2_loc (input_location, MINUS_EXPR,
764 integer_type_node, argse.expr,
765 fold_convert(integer_type_node, lbound));
766 tmp = fold_build2_loc (input_location, MULT_EXPR,
767 integer_type_node, extent, tmp);
768 index = fold_build2_loc (input_location, PLUS_EXPR,
769 integer_type_node, index, tmp);
770 if (i < ar->dimen - 1)
772 ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[i]);
773 tmp = gfc_conv_array_extent_dim (lbound, ubound, NULL);
774 tmp = fold_convert (integer_type_node, tmp);
775 extent = fold_build2_loc (input_location, MULT_EXPR,
776 integer_type_node, extent, tmp);
781 /* errmsg. */
782 if (code->expr3)
784 gfc_init_se (&argse, NULL);
785 argse.want_pointer = 1;
786 gfc_conv_expr (&argse, code->expr3);
787 gfc_add_block_to_block (&se.pre, &argse.pre);
788 errmsg = argse.expr;
789 errmsg_len = fold_convert (integer_type_node, argse.string_length);
791 else
793 errmsg = null_pointer_node;
794 errmsg_len = integer_zero_node;
797 if (stat != null_pointer_node && TREE_TYPE (stat) != integer_type_node)
799 stat2 = stat;
800 stat = gfc_create_var (integer_type_node, "stat");
803 if (lock_acquired != null_pointer_node
804 && TREE_TYPE (lock_acquired) != integer_type_node)
806 lock_acquired2 = lock_acquired;
807 lock_acquired = gfc_create_var (integer_type_node, "acquired");
810 if (op == EXEC_LOCK)
811 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_lock, 7,
812 token, index, image_index,
813 lock_acquired != null_pointer_node
814 ? gfc_build_addr_expr (NULL, lock_acquired)
815 : lock_acquired,
816 stat != null_pointer_node
817 ? gfc_build_addr_expr (NULL, stat) : stat,
818 errmsg, errmsg_len);
819 else
820 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_unlock, 6,
821 token, index, image_index,
822 stat != null_pointer_node
823 ? gfc_build_addr_expr (NULL, stat) : stat,
824 errmsg, errmsg_len);
825 gfc_add_expr_to_block (&se.pre, tmp);
827 /* It guarantees memory consistency within the same segment */
828 tmp = gfc_build_string_const (strlen ("memory")+1, "memory"),
829 tmp = build5_loc (input_location, ASM_EXPR, void_type_node,
830 gfc_build_string_const (1, ""), NULL_TREE, NULL_TREE,
831 tree_cons (NULL_TREE, tmp, NULL_TREE), NULL_TREE);
832 ASM_VOLATILE_P (tmp) = 1;
834 gfc_add_expr_to_block (&se.pre, tmp);
836 if (stat2 != NULL_TREE)
837 gfc_add_modify (&se.pre, stat2,
838 fold_convert (TREE_TYPE (stat2), stat));
840 if (lock_acquired2 != NULL_TREE)
841 gfc_add_modify (&se.pre, lock_acquired2,
842 fold_convert (TREE_TYPE (lock_acquired2),
843 lock_acquired));
845 return gfc_finish_block (&se.pre);
848 if (stat != NULL_TREE)
849 gfc_add_modify (&se.pre, stat, build_int_cst (TREE_TYPE (stat), 0));
851 if (lock_acquired != NULL_TREE)
852 gfc_add_modify (&se.pre, lock_acquired,
853 fold_convert (TREE_TYPE (lock_acquired),
854 boolean_true_node));
856 return gfc_finish_block (&se.pre);
859 tree
860 gfc_trans_event_post_wait (gfc_code *code, gfc_exec_op op)
862 gfc_se se, argse;
863 tree stat = NULL_TREE, stat2 = NULL_TREE;
864 tree until_count = NULL_TREE;
866 if (code->expr2)
868 gcc_assert (code->expr2->expr_type == EXPR_VARIABLE);
869 gfc_init_se (&argse, NULL);
870 gfc_conv_expr_val (&argse, code->expr2);
871 stat = argse.expr;
873 else if (flag_coarray == GFC_FCOARRAY_LIB)
874 stat = null_pointer_node;
876 if (code->expr4)
878 gfc_init_se (&argse, NULL);
879 gfc_conv_expr_val (&argse, code->expr4);
880 until_count = fold_convert (integer_type_node, argse.expr);
882 else
883 until_count = integer_one_node;
885 if (flag_coarray != GFC_FCOARRAY_LIB)
887 gfc_start_block (&se.pre);
888 gfc_init_se (&argse, NULL);
889 gfc_conv_expr_val (&argse, code->expr1);
891 if (op == EXEC_EVENT_POST)
892 gfc_add_modify (&se.pre, argse.expr,
893 fold_build2_loc (input_location, PLUS_EXPR,
894 TREE_TYPE (argse.expr), argse.expr,
895 build_int_cst (TREE_TYPE (argse.expr), 1)));
896 else
897 gfc_add_modify (&se.pre, argse.expr,
898 fold_build2_loc (input_location, MINUS_EXPR,
899 TREE_TYPE (argse.expr), argse.expr,
900 fold_convert (TREE_TYPE (argse.expr),
901 until_count)));
902 if (stat != NULL_TREE)
903 gfc_add_modify (&se.pre, stat, build_int_cst (TREE_TYPE (stat), 0));
905 return gfc_finish_block (&se.pre);
908 gfc_start_block (&se.pre);
909 tree tmp, token, image_index, errmsg, errmsg_len;
910 tree index = size_zero_node;
911 tree caf_decl = gfc_get_tree_for_caf_expr (code->expr1);
913 if (code->expr1->symtree->n.sym->ts.type != BT_DERIVED
914 || code->expr1->symtree->n.sym->ts.u.derived->from_intmod
915 != INTMOD_ISO_FORTRAN_ENV
916 || code->expr1->symtree->n.sym->ts.u.derived->intmod_sym_id
917 != ISOFORTRAN_EVENT_TYPE)
919 gfc_error ("Sorry, the event component of derived type at %L is not "
920 "yet supported", &code->expr1->where);
921 return NULL_TREE;
924 gfc_get_caf_token_offset (&token, NULL, caf_decl, NULL_TREE, code->expr1);
926 if (gfc_is_coindexed (code->expr1))
927 image_index = gfc_caf_get_image_index (&se.pre, code->expr1, caf_decl);
928 else
929 image_index = integer_zero_node;
931 /* For arrays, obtain the array index. */
932 if (gfc_expr_attr (code->expr1).dimension)
934 tree desc, tmp, extent, lbound, ubound;
935 gfc_array_ref *ar, ar2;
936 int i;
938 /* TODO: Extend this, once DT components are supported. */
939 ar = &code->expr1->ref->u.ar;
940 ar2 = *ar;
941 memset (ar, '\0', sizeof (*ar));
942 ar->as = ar2.as;
943 ar->type = AR_FULL;
945 gfc_init_se (&argse, NULL);
946 argse.descriptor_only = 1;
947 gfc_conv_expr_descriptor (&argse, code->expr1);
948 gfc_add_block_to_block (&se.pre, &argse.pre);
949 desc = argse.expr;
950 *ar = ar2;
952 extent = integer_one_node;
953 for (i = 0; i < ar->dimen; i++)
955 gfc_init_se (&argse, NULL);
956 gfc_conv_expr_type (&argse, ar->start[i], integer_type_node);
957 gfc_add_block_to_block (&argse.pre, &argse.pre);
958 lbound = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[i]);
959 tmp = fold_build2_loc (input_location, MINUS_EXPR,
960 integer_type_node, argse.expr,
961 fold_convert(integer_type_node, lbound));
962 tmp = fold_build2_loc (input_location, MULT_EXPR,
963 integer_type_node, extent, tmp);
964 index = fold_build2_loc (input_location, PLUS_EXPR,
965 integer_type_node, index, tmp);
966 if (i < ar->dimen - 1)
968 ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[i]);
969 tmp = gfc_conv_array_extent_dim (lbound, ubound, NULL);
970 tmp = fold_convert (integer_type_node, tmp);
971 extent = fold_build2_loc (input_location, MULT_EXPR,
972 integer_type_node, extent, tmp);
977 /* errmsg. */
978 if (code->expr3)
980 gfc_init_se (&argse, NULL);
981 argse.want_pointer = 1;
982 gfc_conv_expr (&argse, code->expr3);
983 gfc_add_block_to_block (&se.pre, &argse.pre);
984 errmsg = argse.expr;
985 errmsg_len = fold_convert (integer_type_node, argse.string_length);
987 else
989 errmsg = null_pointer_node;
990 errmsg_len = integer_zero_node;
993 if (stat != null_pointer_node && TREE_TYPE (stat) != integer_type_node)
995 stat2 = stat;
996 stat = gfc_create_var (integer_type_node, "stat");
999 if (op == EXEC_EVENT_POST)
1000 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_event_post, 6,
1001 token, index, image_index,
1002 stat != null_pointer_node
1003 ? gfc_build_addr_expr (NULL, stat) : stat,
1004 errmsg, errmsg_len);
1005 else
1006 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_event_wait, 6,
1007 token, index, until_count,
1008 stat != null_pointer_node
1009 ? gfc_build_addr_expr (NULL, stat) : stat,
1010 errmsg, errmsg_len);
1011 gfc_add_expr_to_block (&se.pre, tmp);
1013 /* It guarantees memory consistency within the same segment */
1014 tmp = gfc_build_string_const (strlen ("memory")+1, "memory"),
1015 tmp = build5_loc (input_location, ASM_EXPR, void_type_node,
1016 gfc_build_string_const (1, ""), NULL_TREE, NULL_TREE,
1017 tree_cons (NULL_TREE, tmp, NULL_TREE), NULL_TREE);
1018 ASM_VOLATILE_P (tmp) = 1;
1019 gfc_add_expr_to_block (&se.pre, tmp);
1021 if (stat2 != NULL_TREE)
1022 gfc_add_modify (&se.pre, stat2, fold_convert (TREE_TYPE (stat2), stat));
1024 return gfc_finish_block (&se.pre);
1027 tree
1028 gfc_trans_sync (gfc_code *code, gfc_exec_op type)
1030 gfc_se se, argse;
1031 tree tmp;
1032 tree images = NULL_TREE, stat = NULL_TREE,
1033 errmsg = NULL_TREE, errmsglen = NULL_TREE;
1035 /* Short cut: For single images without bound checking or without STAT=,
1036 return early. (ERRMSG= is always untouched for -fcoarray=single.) */
1037 if (!code->expr2 && !(gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
1038 && flag_coarray != GFC_FCOARRAY_LIB)
1039 return NULL_TREE;
1041 gfc_init_se (&se, NULL);
1042 gfc_start_block (&se.pre);
1044 if (code->expr1 && code->expr1->rank == 0)
1046 gfc_init_se (&argse, NULL);
1047 gfc_conv_expr_val (&argse, code->expr1);
1048 images = argse.expr;
1051 if (code->expr2)
1053 gcc_assert (code->expr2->expr_type == EXPR_VARIABLE);
1054 gfc_init_se (&argse, NULL);
1055 gfc_conv_expr_val (&argse, code->expr2);
1056 stat = argse.expr;
1058 else
1059 stat = null_pointer_node;
1061 if (code->expr3 && flag_coarray == GFC_FCOARRAY_LIB)
1063 gcc_assert (code->expr3->expr_type == EXPR_VARIABLE);
1064 gfc_init_se (&argse, NULL);
1065 argse.want_pointer = 1;
1066 gfc_conv_expr (&argse, code->expr3);
1067 gfc_conv_string_parameter (&argse);
1068 errmsg = gfc_build_addr_expr (NULL, argse.expr);
1069 errmsglen = argse.string_length;
1071 else if (flag_coarray == GFC_FCOARRAY_LIB)
1073 errmsg = null_pointer_node;
1074 errmsglen = build_int_cst (integer_type_node, 0);
1077 /* Check SYNC IMAGES(imageset) for valid image index.
1078 FIXME: Add a check for image-set arrays. */
1079 if (code->expr1 && (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
1080 && code->expr1->rank == 0)
1082 tree cond;
1083 if (flag_coarray != GFC_FCOARRAY_LIB)
1084 cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
1085 images, build_int_cst (TREE_TYPE (images), 1));
1086 else
1088 tree cond2;
1089 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_num_images,
1090 2, integer_zero_node,
1091 build_int_cst (integer_type_node, -1));
1092 cond = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
1093 images, tmp);
1094 cond2 = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
1095 images,
1096 build_int_cst (TREE_TYPE (images), 1));
1097 cond = fold_build2_loc (input_location, TRUTH_OR_EXPR,
1098 boolean_type_node, cond, cond2);
1100 gfc_trans_runtime_check (true, false, cond, &se.pre,
1101 &code->expr1->where, "Invalid image number "
1102 "%d in SYNC IMAGES",
1103 fold_convert (integer_type_node, images));
1106 /* Per F2008, 8.5.1, a SYNC MEMORY is implied by calling the
1107 image control statements SYNC IMAGES and SYNC ALL. */
1108 if (flag_coarray == GFC_FCOARRAY_LIB)
1110 tmp = gfc_build_string_const (strlen ("memory")+1, "memory"),
1111 tmp = build5_loc (input_location, ASM_EXPR, void_type_node,
1112 gfc_build_string_const (1, ""), NULL_TREE, NULL_TREE,
1113 tree_cons (NULL_TREE, tmp, NULL_TREE), NULL_TREE);
1114 ASM_VOLATILE_P (tmp) = 1;
1115 gfc_add_expr_to_block (&se.pre, tmp);
1118 if (flag_coarray != GFC_FCOARRAY_LIB)
1120 /* Set STAT to zero. */
1121 if (code->expr2)
1122 gfc_add_modify (&se.pre, stat, build_int_cst (TREE_TYPE (stat), 0));
1124 else if (type == EXEC_SYNC_ALL || type == EXEC_SYNC_MEMORY)
1126 /* SYNC ALL => stat == null_pointer_node
1127 SYNC ALL(stat=s) => stat has an integer type
1129 If "stat" has the wrong integer type, use a temp variable of
1130 the right type and later cast the result back into "stat". */
1131 if (stat == null_pointer_node || TREE_TYPE (stat) == integer_type_node)
1133 if (TREE_TYPE (stat) == integer_type_node)
1134 stat = gfc_build_addr_expr (NULL, stat);
1136 if(type == EXEC_SYNC_MEMORY)
1137 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sync_memory,
1138 3, stat, errmsg, errmsglen);
1139 else
1140 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sync_all,
1141 3, stat, errmsg, errmsglen);
1143 gfc_add_expr_to_block (&se.pre, tmp);
1145 else
1147 tree tmp_stat = gfc_create_var (integer_type_node, "stat");
1149 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sync_all,
1150 3, gfc_build_addr_expr (NULL, tmp_stat),
1151 errmsg, errmsglen);
1152 gfc_add_expr_to_block (&se.pre, tmp);
1154 gfc_add_modify (&se.pre, stat,
1155 fold_convert (TREE_TYPE (stat), tmp_stat));
1158 else
1160 tree len;
1162 gcc_assert (type == EXEC_SYNC_IMAGES);
1164 if (!code->expr1)
1166 len = build_int_cst (integer_type_node, -1);
1167 images = null_pointer_node;
1169 else if (code->expr1->rank == 0)
1171 len = build_int_cst (integer_type_node, 1);
1172 images = gfc_build_addr_expr (NULL_TREE, images);
1174 else
1176 /* FIXME. */
1177 if (code->expr1->ts.kind != gfc_c_int_kind)
1178 gfc_fatal_error ("Sorry, only support for integer kind %d "
1179 "implemented for image-set at %L",
1180 gfc_c_int_kind, &code->expr1->where);
1182 gfc_conv_array_parameter (&se, code->expr1, true, NULL, NULL, &len);
1183 images = se.expr;
1185 tmp = gfc_typenode_for_spec (&code->expr1->ts);
1186 if (GFC_ARRAY_TYPE_P (tmp) || GFC_DESCRIPTOR_TYPE_P (tmp))
1187 tmp = gfc_get_element_type (tmp);
1189 len = fold_build2_loc (input_location, TRUNC_DIV_EXPR,
1190 TREE_TYPE (len), len,
1191 fold_convert (TREE_TYPE (len),
1192 TYPE_SIZE_UNIT (tmp)));
1193 len = fold_convert (integer_type_node, len);
1196 /* SYNC IMAGES(imgs) => stat == null_pointer_node
1197 SYNC IMAGES(imgs,stat=s) => stat has an integer type
1199 If "stat" has the wrong integer type, use a temp variable of
1200 the right type and later cast the result back into "stat". */
1201 if (stat == null_pointer_node || TREE_TYPE (stat) == integer_type_node)
1203 if (TREE_TYPE (stat) == integer_type_node)
1204 stat = gfc_build_addr_expr (NULL, stat);
1206 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sync_images,
1207 5, fold_convert (integer_type_node, len),
1208 images, stat, errmsg, errmsglen);
1209 gfc_add_expr_to_block (&se.pre, tmp);
1211 else
1213 tree tmp_stat = gfc_create_var (integer_type_node, "stat");
1215 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sync_images,
1216 5, fold_convert (integer_type_node, len),
1217 images, gfc_build_addr_expr (NULL, tmp_stat),
1218 errmsg, errmsglen);
1219 gfc_add_expr_to_block (&se.pre, tmp);
1221 gfc_add_modify (&se.pre, stat,
1222 fold_convert (TREE_TYPE (stat), tmp_stat));
1226 return gfc_finish_block (&se.pre);
1230 /* Generate GENERIC for the IF construct. This function also deals with
1231 the simple IF statement, because the front end translates the IF
1232 statement into an IF construct.
1234 We translate:
1236 IF (cond) THEN
1237 then_clause
1238 ELSEIF (cond2)
1239 elseif_clause
1240 ELSE
1241 else_clause
1242 ENDIF
1244 into:
1246 pre_cond_s;
1247 if (cond_s)
1249 then_clause;
1251 else
1253 pre_cond_s
1254 if (cond_s)
1256 elseif_clause
1258 else
1260 else_clause;
1264 where COND_S is the simplified version of the predicate. PRE_COND_S
1265 are the pre side-effects produced by the translation of the
1266 conditional.
1267 We need to build the chain recursively otherwise we run into
1268 problems with folding incomplete statements. */
1270 static tree
1271 gfc_trans_if_1 (gfc_code * code)
1273 gfc_se if_se;
1274 tree stmt, elsestmt;
1275 locus saved_loc;
1276 location_t loc;
1278 /* Check for an unconditional ELSE clause. */
1279 if (!code->expr1)
1280 return gfc_trans_code (code->next);
1282 /* Initialize a statement builder for each block. Puts in NULL_TREEs. */
1283 gfc_init_se (&if_se, NULL);
1284 gfc_start_block (&if_se.pre);
1286 /* Calculate the IF condition expression. */
1287 if (code->expr1->where.lb)
1289 gfc_save_backend_locus (&saved_loc);
1290 gfc_set_backend_locus (&code->expr1->where);
1293 gfc_conv_expr_val (&if_se, code->expr1);
1295 if (code->expr1->where.lb)
1296 gfc_restore_backend_locus (&saved_loc);
1298 /* Translate the THEN clause. */
1299 stmt = gfc_trans_code (code->next);
1301 /* Translate the ELSE clause. */
1302 if (code->block)
1303 elsestmt = gfc_trans_if_1 (code->block);
1304 else
1305 elsestmt = build_empty_stmt (input_location);
1307 /* Build the condition expression and add it to the condition block. */
1308 loc = code->expr1->where.lb ? code->expr1->where.lb->location : input_location;
1309 stmt = fold_build3_loc (loc, COND_EXPR, void_type_node, if_se.expr, stmt,
1310 elsestmt);
1312 gfc_add_expr_to_block (&if_se.pre, stmt);
1314 /* Finish off this statement. */
1315 return gfc_finish_block (&if_se.pre);
1318 tree
1319 gfc_trans_if (gfc_code * code)
1321 stmtblock_t body;
1322 tree exit_label;
1324 /* Create exit label so it is available for trans'ing the body code. */
1325 exit_label = gfc_build_label_decl (NULL_TREE);
1326 code->exit_label = exit_label;
1328 /* Translate the actual code in code->block. */
1329 gfc_init_block (&body);
1330 gfc_add_expr_to_block (&body, gfc_trans_if_1 (code->block));
1332 /* Add exit label. */
1333 gfc_add_expr_to_block (&body, build1_v (LABEL_EXPR, exit_label));
1335 return gfc_finish_block (&body);
1339 /* Translate an arithmetic IF expression.
1341 IF (cond) label1, label2, label3 translates to
1343 if (cond <= 0)
1345 if (cond < 0)
1346 goto label1;
1347 else // cond == 0
1348 goto label2;
1350 else // cond > 0
1351 goto label3;
1353 An optimized version can be generated in case of equal labels.
1354 E.g., if label1 is equal to label2, we can translate it to
1356 if (cond <= 0)
1357 goto label1;
1358 else
1359 goto label3;
1362 tree
1363 gfc_trans_arithmetic_if (gfc_code * code)
1365 gfc_se se;
1366 tree tmp;
1367 tree branch1;
1368 tree branch2;
1369 tree zero;
1371 /* Start a new block. */
1372 gfc_init_se (&se, NULL);
1373 gfc_start_block (&se.pre);
1375 /* Pre-evaluate COND. */
1376 gfc_conv_expr_val (&se, code->expr1);
1377 se.expr = gfc_evaluate_now (se.expr, &se.pre);
1379 /* Build something to compare with. */
1380 zero = gfc_build_const (TREE_TYPE (se.expr), integer_zero_node);
1382 if (code->label1->value != code->label2->value)
1384 /* If (cond < 0) take branch1 else take branch2.
1385 First build jumps to the COND .LT. 0 and the COND .EQ. 0 cases. */
1386 branch1 = build1_v (GOTO_EXPR, gfc_get_label_decl (code->label1));
1387 branch2 = build1_v (GOTO_EXPR, gfc_get_label_decl (code->label2));
1389 if (code->label1->value != code->label3->value)
1390 tmp = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
1391 se.expr, zero);
1392 else
1393 tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
1394 se.expr, zero);
1396 branch1 = fold_build3_loc (input_location, COND_EXPR, void_type_node,
1397 tmp, branch1, branch2);
1399 else
1400 branch1 = build1_v (GOTO_EXPR, gfc_get_label_decl (code->label1));
1402 if (code->label1->value != code->label3->value
1403 && code->label2->value != code->label3->value)
1405 /* if (cond <= 0) take branch1 else take branch2. */
1406 branch2 = build1_v (GOTO_EXPR, gfc_get_label_decl (code->label3));
1407 tmp = fold_build2_loc (input_location, LE_EXPR, boolean_type_node,
1408 se.expr, zero);
1409 branch1 = fold_build3_loc (input_location, COND_EXPR, void_type_node,
1410 tmp, branch1, branch2);
1413 /* Append the COND_EXPR to the evaluation of COND, and return. */
1414 gfc_add_expr_to_block (&se.pre, branch1);
1415 return gfc_finish_block (&se.pre);
1419 /* Translate a CRITICAL block. */
1420 tree
1421 gfc_trans_critical (gfc_code *code)
1423 stmtblock_t block;
1424 tree tmp, token = NULL_TREE;
1426 gfc_start_block (&block);
1428 if (flag_coarray == GFC_FCOARRAY_LIB)
1430 token = gfc_get_symbol_decl (code->resolved_sym);
1431 token = GFC_TYPE_ARRAY_CAF_TOKEN (TREE_TYPE (token));
1432 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_lock, 7,
1433 token, integer_zero_node, integer_one_node,
1434 null_pointer_node, null_pointer_node,
1435 null_pointer_node, integer_zero_node);
1436 gfc_add_expr_to_block (&block, tmp);
1438 /* It guarantees memory consistency within the same segment */
1439 tmp = gfc_build_string_const (strlen ("memory")+1, "memory"),
1440 tmp = build5_loc (input_location, ASM_EXPR, void_type_node,
1441 gfc_build_string_const (1, ""),
1442 NULL_TREE, NULL_TREE,
1443 tree_cons (NULL_TREE, tmp, NULL_TREE),
1444 NULL_TREE);
1445 ASM_VOLATILE_P (tmp) = 1;
1447 gfc_add_expr_to_block (&block, tmp);
1450 tmp = gfc_trans_code (code->block->next);
1451 gfc_add_expr_to_block (&block, tmp);
1453 if (flag_coarray == GFC_FCOARRAY_LIB)
1455 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_unlock, 6,
1456 token, integer_zero_node, integer_one_node,
1457 null_pointer_node, null_pointer_node,
1458 integer_zero_node);
1459 gfc_add_expr_to_block (&block, tmp);
1461 /* It guarantees memory consistency within the same segment */
1462 tmp = gfc_build_string_const (strlen ("memory")+1, "memory"),
1463 tmp = build5_loc (input_location, ASM_EXPR, void_type_node,
1464 gfc_build_string_const (1, ""),
1465 NULL_TREE, NULL_TREE,
1466 tree_cons (NULL_TREE, tmp, NULL_TREE),
1467 NULL_TREE);
1468 ASM_VOLATILE_P (tmp) = 1;
1470 gfc_add_expr_to_block (&block, tmp);
1473 return gfc_finish_block (&block);
1477 /* Return true, when the class has a _len component. */
1479 static bool
1480 class_has_len_component (gfc_symbol *sym)
1482 gfc_component *comp = sym->ts.u.derived->components;
1483 while (comp)
1485 if (strcmp (comp->name, "_len") == 0)
1486 return true;
1487 comp = comp->next;
1489 return false;
1493 /* Do proper initialization for ASSOCIATE names. */
1495 static void
1496 trans_associate_var (gfc_symbol *sym, gfc_wrapped_block *block)
1498 gfc_expr *e;
1499 tree tmp;
1500 bool class_target;
1501 bool unlimited;
1502 tree desc;
1503 tree offset;
1504 tree dim;
1505 int n;
1506 tree charlen;
1507 bool need_len_assign;
1509 gcc_assert (sym->assoc);
1510 e = sym->assoc->target;
1512 class_target = (e->expr_type == EXPR_VARIABLE)
1513 && (gfc_is_class_scalar_expr (e)
1514 || gfc_is_class_array_ref (e, NULL));
1516 unlimited = UNLIMITED_POLY (e);
1518 /* Assignments to the string length need to be generated, when
1519 ( sym is a char array or
1520 sym has a _len component)
1521 and the associated expression is unlimited polymorphic, which is
1522 not (yet) correctly in 'unlimited', because for an already associated
1523 BT_DERIVED the u-poly flag is not set, i.e.,
1524 __tmp_CHARACTER_0_1 => w => arg
1525 ^ generated temp ^ from code, the w does not have the u-poly
1526 flag set, where UNLIMITED_POLY(e) expects it. */
1527 need_len_assign = ((unlimited || (e->ts.type == BT_DERIVED
1528 && e->ts.u.derived->attr.unlimited_polymorphic))
1529 && (sym->ts.type == BT_CHARACTER
1530 || ((sym->ts.type == BT_CLASS || sym->ts.type == BT_DERIVED)
1531 && class_has_len_component (sym))));
1532 /* Do a `pointer assignment' with updated descriptor (or assign descriptor
1533 to array temporary) for arrays with either unknown shape or if associating
1534 to a variable. */
1535 if (sym->attr.dimension && !class_target
1536 && (sym->as->type == AS_DEFERRED || sym->assoc->variable))
1538 gfc_se se;
1539 tree desc;
1540 bool cst_array_ctor;
1542 desc = sym->backend_decl;
1543 cst_array_ctor = e->expr_type == EXPR_ARRAY
1544 && gfc_constant_array_constructor_p (e->value.constructor);
1546 /* If association is to an expression, evaluate it and create temporary.
1547 Otherwise, get descriptor of target for pointer assignment. */
1548 gfc_init_se (&se, NULL);
1549 if (sym->assoc->variable || cst_array_ctor)
1551 se.direct_byref = 1;
1552 se.use_offset = 1;
1553 se.expr = desc;
1556 gfc_conv_expr_descriptor (&se, e);
1558 /* If we didn't already do the pointer assignment, set associate-name
1559 descriptor to the one generated for the temporary. */
1560 if (!sym->assoc->variable && !cst_array_ctor)
1562 int dim;
1564 gfc_add_modify (&se.pre, desc, se.expr);
1566 /* The generated descriptor has lower bound zero (as array
1567 temporary), shift bounds so we get lower bounds of 1. */
1568 for (dim = 0; dim < e->rank; ++dim)
1569 gfc_conv_shift_descriptor_lbound (&se.pre, desc,
1570 dim, gfc_index_one_node);
1573 /* If this is a subreference array pointer associate name use the
1574 associate variable element size for the value of 'span'. */
1575 if (sym->attr.subref_array_pointer)
1577 gcc_assert (e->expr_type == EXPR_VARIABLE);
1578 tmp = e->symtree->n.sym->ts.type == BT_CLASS
1579 ? gfc_class_data_get (e->symtree->n.sym->backend_decl)
1580 : e->symtree->n.sym->backend_decl;
1581 tmp = gfc_get_element_type (TREE_TYPE (tmp));
1582 tmp = fold_convert (gfc_array_index_type, size_in_bytes (tmp));
1583 gfc_add_modify (&se.pre, GFC_DECL_SPAN(desc), tmp);
1586 /* Done, register stuff as init / cleanup code. */
1587 gfc_add_init_cleanup (block, gfc_finish_block (&se.pre),
1588 gfc_finish_block (&se.post));
1591 /* Temporaries, arising from TYPE IS, just need the descriptor of class
1592 arrays to be assigned directly. */
1593 else if (class_target && sym->attr.dimension
1594 && (sym->ts.type == BT_DERIVED || unlimited))
1596 gfc_se se;
1598 gfc_init_se (&se, NULL);
1599 se.descriptor_only = 1;
1600 /* In a select type the (temporary) associate variable shall point to
1601 a standard fortran array (lower bound == 1), but conv_expr ()
1602 just maps to the input array in the class object, whose lbound may
1603 be arbitrary. conv_expr_descriptor solves this by inserting a
1604 temporary array descriptor. */
1605 gfc_conv_expr_descriptor (&se, e);
1607 gcc_assert (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (se.expr))
1608 || GFC_ARRAY_TYPE_P (TREE_TYPE (se.expr)));
1609 gcc_assert (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (sym->backend_decl)));
1611 if (GFC_ARRAY_TYPE_P (TREE_TYPE (se.expr)))
1613 if (INDIRECT_REF_P (se.expr))
1614 tmp = TREE_OPERAND (se.expr, 0);
1615 else
1616 tmp = se.expr;
1618 gfc_add_modify (&se.pre, sym->backend_decl,
1619 gfc_class_data_get (GFC_DECL_SAVED_DESCRIPTOR (tmp)));
1621 else
1622 gfc_add_modify (&se.pre, sym->backend_decl, se.expr);
1624 if (unlimited)
1626 /* Recover the dtype, which has been overwritten by the
1627 assignment from an unlimited polymorphic object. */
1628 tmp = gfc_conv_descriptor_dtype (sym->backend_decl);
1629 gfc_add_modify (&se.pre, tmp,
1630 gfc_get_dtype (TREE_TYPE (sym->backend_decl)));
1633 gfc_add_init_cleanup (block, gfc_finish_block (&se.pre),
1634 gfc_finish_block (&se.post));
1637 /* Do a scalar pointer assignment; this is for scalar variable targets. */
1638 else if (gfc_is_associate_pointer (sym))
1640 gfc_se se;
1642 gcc_assert (!sym->attr.dimension);
1644 gfc_init_se (&se, NULL);
1646 /* Class associate-names come this way because they are
1647 unconditionally associate pointers and the symbol is scalar. */
1648 if (sym->ts.type == BT_CLASS && CLASS_DATA (sym)->attr.dimension)
1650 tree target_expr;
1651 /* For a class array we need a descriptor for the selector. */
1652 gfc_conv_expr_descriptor (&se, e);
1653 /* Needed to get/set the _len component below. */
1654 target_expr = se.expr;
1656 /* Obtain a temporary class container for the result. */
1657 gfc_conv_class_to_class (&se, e, sym->ts, false, true, false, false);
1658 se.expr = build_fold_indirect_ref_loc (input_location, se.expr);
1660 /* Set the offset. */
1661 desc = gfc_class_data_get (se.expr);
1662 offset = gfc_index_zero_node;
1663 for (n = 0; n < e->rank; n++)
1665 dim = gfc_rank_cst[n];
1666 tmp = fold_build2_loc (input_location, MULT_EXPR,
1667 gfc_array_index_type,
1668 gfc_conv_descriptor_stride_get (desc, dim),
1669 gfc_conv_descriptor_lbound_get (desc, dim));
1670 offset = fold_build2_loc (input_location, MINUS_EXPR,
1671 gfc_array_index_type,
1672 offset, tmp);
1674 if (need_len_assign)
1676 if (e->symtree
1677 && DECL_LANG_SPECIFIC (e->symtree->n.sym->backend_decl)
1678 && GFC_DECL_SAVED_DESCRIPTOR (e->symtree->n.sym->backend_decl))
1679 /* Use the original class descriptor stored in the saved
1680 descriptor to get the target_expr. */
1681 target_expr =
1682 GFC_DECL_SAVED_DESCRIPTOR (e->symtree->n.sym->backend_decl);
1683 else
1684 /* Strip the _data component from the target_expr. */
1685 target_expr = TREE_OPERAND (target_expr, 0);
1686 /* Add a reference to the _len comp to the target expr. */
1687 tmp = gfc_class_len_get (target_expr);
1688 /* Get the component-ref for the temp structure's _len comp. */
1689 charlen = gfc_class_len_get (se.expr);
1690 /* Add the assign to the beginning of the block... */
1691 gfc_add_modify (&se.pre, charlen,
1692 fold_convert (TREE_TYPE (charlen), tmp));
1693 /* and the oposite way at the end of the block, to hand changes
1694 on the string length back. */
1695 gfc_add_modify (&se.post, tmp,
1696 fold_convert (TREE_TYPE (tmp), charlen));
1697 /* Length assignment done, prevent adding it again below. */
1698 need_len_assign = false;
1700 gfc_conv_descriptor_offset_set (&se.pre, desc, offset);
1702 else if (sym->ts.type == BT_CLASS && e->ts.type == BT_CLASS
1703 && CLASS_DATA (e)->attr.dimension)
1705 /* This is bound to be a class array element. */
1706 gfc_conv_expr_reference (&se, e);
1707 /* Get the _vptr component of the class object. */
1708 tmp = gfc_get_vptr_from_expr (se.expr);
1709 /* Obtain a temporary class container for the result. */
1710 gfc_conv_derived_to_class (&se, e, sym->ts, tmp, false, false);
1711 se.expr = build_fold_indirect_ref_loc (input_location, se.expr);
1713 else
1715 /* For BT_CLASS and BT_DERIVED, this boils down to a pointer assign,
1716 which has the string length included. For CHARACTERS it is still
1717 needed and will be done at the end of this routine. */
1718 gfc_conv_expr (&se, e);
1719 need_len_assign = need_len_assign && sym->ts.type == BT_CHARACTER;
1722 tmp = TREE_TYPE (sym->backend_decl);
1723 tmp = gfc_build_addr_expr (tmp, se.expr);
1724 gfc_add_modify (&se.pre, sym->backend_decl, tmp);
1726 gfc_add_init_cleanup (block, gfc_finish_block( &se.pre),
1727 gfc_finish_block (&se.post));
1730 /* Do a simple assignment. This is for scalar expressions, where we
1731 can simply use expression assignment. */
1732 else
1734 gfc_expr *lhs;
1736 lhs = gfc_lval_expr_from_sym (sym);
1737 tmp = gfc_trans_assignment (lhs, e, false, true);
1738 gfc_add_init_cleanup (block, tmp, NULL_TREE);
1741 /* Set the stringlength, when needed. */
1742 if (need_len_assign)
1744 gfc_se se;
1745 gfc_init_se (&se, NULL);
1746 if (e->symtree->n.sym->ts.type == BT_CHARACTER)
1748 /* What about deferred strings? */
1749 gcc_assert (!e->symtree->n.sym->ts.deferred);
1750 tmp = e->symtree->n.sym->ts.u.cl->backend_decl;
1752 else
1753 tmp = gfc_class_len_get (gfc_get_symbol_decl (e->symtree->n.sym));
1754 gfc_get_symbol_decl (sym);
1755 charlen = sym->ts.type == BT_CHARACTER ? sym->ts.u.cl->backend_decl
1756 : gfc_class_len_get (sym->backend_decl);
1757 /* Prevent adding a noop len= len. */
1758 if (tmp != charlen)
1760 gfc_add_modify (&se.pre, charlen,
1761 fold_convert (TREE_TYPE (charlen), tmp));
1762 gfc_add_init_cleanup (block, gfc_finish_block (&se.pre),
1763 gfc_finish_block (&se.post));
1769 /* Translate a BLOCK construct. This is basically what we would do for a
1770 procedure body. */
1772 tree
1773 gfc_trans_block_construct (gfc_code* code)
1775 gfc_namespace* ns;
1776 gfc_symbol* sym;
1777 gfc_wrapped_block block;
1778 tree exit_label;
1779 stmtblock_t body;
1780 gfc_association_list *ass;
1782 ns = code->ext.block.ns;
1783 gcc_assert (ns);
1784 sym = ns->proc_name;
1785 gcc_assert (sym);
1787 /* Process local variables. */
1788 gcc_assert (!sym->tlink);
1789 sym->tlink = sym;
1790 gfc_process_block_locals (ns);
1792 /* Generate code including exit-label. */
1793 gfc_init_block (&body);
1794 exit_label = gfc_build_label_decl (NULL_TREE);
1795 code->exit_label = exit_label;
1797 finish_oacc_declare (ns, sym, true);
1799 gfc_add_expr_to_block (&body, gfc_trans_code (ns->code));
1800 gfc_add_expr_to_block (&body, build1_v (LABEL_EXPR, exit_label));
1802 /* Finish everything. */
1803 gfc_start_wrapped_block (&block, gfc_finish_block (&body));
1804 gfc_trans_deferred_vars (sym, &block);
1805 for (ass = code->ext.block.assoc; ass; ass = ass->next)
1806 trans_associate_var (ass->st->n.sym, &block);
1808 return gfc_finish_wrapped_block (&block);
1811 /* Translate the simple DO construct in a C-style manner.
1812 This is where the loop variable has integer type and step +-1.
1813 Following code will generate infinite loop in case where TO is INT_MAX
1814 (for +1 step) or INT_MIN (for -1 step)
1816 We translate a do loop from:
1818 DO dovar = from, to, step
1819 body
1820 END DO
1824 [Evaluate loop bounds and step]
1825 dovar = from;
1826 for (;;)
1828 if (dovar > to)
1829 goto end_label;
1830 body;
1831 cycle_label:
1832 dovar += step;
1834 end_label:
1836 This helps the optimizers by avoiding the extra pre-header condition and
1837 we save a register as we just compare the updated IV (not a value in
1838 previous step). */
1840 static tree
1841 gfc_trans_simple_do (gfc_code * code, stmtblock_t *pblock, tree dovar,
1842 tree from, tree to, tree step, tree exit_cond)
1844 stmtblock_t body;
1845 tree type;
1846 tree cond;
1847 tree tmp;
1848 tree saved_dovar = NULL;
1849 tree cycle_label;
1850 tree exit_label;
1851 location_t loc;
1852 type = TREE_TYPE (dovar);
1853 bool is_step_positive = tree_int_cst_sgn (step) > 0;
1855 loc = code->ext.iterator->start->where.lb->location;
1857 /* Initialize the DO variable: dovar = from. */
1858 gfc_add_modify_loc (loc, pblock, dovar,
1859 fold_convert (TREE_TYPE (dovar), from));
1861 /* Save value for do-tinkering checking. */
1862 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
1864 saved_dovar = gfc_create_var (type, ".saved_dovar");
1865 gfc_add_modify_loc (loc, pblock, saved_dovar, dovar);
1868 /* Cycle and exit statements are implemented with gotos. */
1869 cycle_label = gfc_build_label_decl (NULL_TREE);
1870 exit_label = gfc_build_label_decl (NULL_TREE);
1872 /* Put the labels where they can be found later. See gfc_trans_do(). */
1873 code->cycle_label = cycle_label;
1874 code->exit_label = exit_label;
1876 /* Loop body. */
1877 gfc_start_block (&body);
1879 /* Exit the loop if there is an I/O result condition or error. */
1880 if (exit_cond)
1882 tmp = build1_v (GOTO_EXPR, exit_label);
1883 tmp = fold_build3_loc (loc, COND_EXPR, void_type_node,
1884 exit_cond, tmp,
1885 build_empty_stmt (loc));
1886 gfc_add_expr_to_block (&body, tmp);
1889 /* Evaluate the loop condition. */
1890 if (is_step_positive)
1891 cond = fold_build2_loc (loc, GT_EXPR, boolean_type_node, dovar,
1892 fold_convert (type, to));
1893 else
1894 cond = fold_build2_loc (loc, LT_EXPR, boolean_type_node, dovar,
1895 fold_convert (type, to));
1897 cond = gfc_evaluate_now_loc (loc, cond, &body);
1899 /* The loop exit. */
1900 tmp = fold_build1_loc (loc, GOTO_EXPR, void_type_node, exit_label);
1901 TREE_USED (exit_label) = 1;
1902 tmp = fold_build3_loc (loc, COND_EXPR, void_type_node,
1903 cond, tmp, build_empty_stmt (loc));
1904 gfc_add_expr_to_block (&body, tmp);
1906 /* Check whether the induction variable is equal to INT_MAX
1907 (respectively to INT_MIN). */
1908 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
1910 tree boundary = is_step_positive ? TYPE_MAX_VALUE (type)
1911 : TYPE_MIN_VALUE (type);
1913 tmp = fold_build2_loc (loc, EQ_EXPR, boolean_type_node,
1914 dovar, boundary);
1915 gfc_trans_runtime_check (true, false, tmp, &body, &code->loc,
1916 "Loop iterates infinitely");
1919 /* Main loop body. */
1920 tmp = gfc_trans_code_cond (code->block->next, exit_cond);
1921 gfc_add_expr_to_block (&body, tmp);
1923 /* Label for cycle statements (if needed). */
1924 if (TREE_USED (cycle_label))
1926 tmp = build1_v (LABEL_EXPR, cycle_label);
1927 gfc_add_expr_to_block (&body, tmp);
1930 /* Check whether someone has modified the loop variable. */
1931 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
1933 tmp = fold_build2_loc (loc, NE_EXPR, boolean_type_node,
1934 dovar, saved_dovar);
1935 gfc_trans_runtime_check (true, false, tmp, &body, &code->loc,
1936 "Loop variable has been modified");
1939 /* Increment the loop variable. */
1940 tmp = fold_build2_loc (loc, PLUS_EXPR, type, dovar, step);
1941 gfc_add_modify_loc (loc, &body, dovar, tmp);
1943 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
1944 gfc_add_modify_loc (loc, &body, saved_dovar, dovar);
1946 /* Finish the loop body. */
1947 tmp = gfc_finish_block (&body);
1948 tmp = fold_build1_loc (loc, LOOP_EXPR, void_type_node, tmp);
1950 gfc_add_expr_to_block (pblock, tmp);
1952 /* Add the exit label. */
1953 tmp = build1_v (LABEL_EXPR, exit_label);
1954 gfc_add_expr_to_block (pblock, tmp);
1956 return gfc_finish_block (pblock);
1959 /* Translate the DO construct. This obviously is one of the most
1960 important ones to get right with any compiler, but especially
1961 so for Fortran.
1963 We special case some loop forms as described in gfc_trans_simple_do.
1964 For other cases we implement them with a separate loop count,
1965 as described in the standard.
1967 We translate a do loop from:
1969 DO dovar = from, to, step
1970 body
1971 END DO
1975 [evaluate loop bounds and step]
1976 empty = (step > 0 ? to < from : to > from);
1977 countm1 = (to - from) / step;
1978 dovar = from;
1979 if (empty) goto exit_label;
1980 for (;;)
1982 body;
1983 cycle_label:
1984 dovar += step
1985 countm1t = countm1;
1986 countm1--;
1987 if (countm1t == 0) goto exit_label;
1989 exit_label:
1991 countm1 is an unsigned integer. It is equal to the loop count minus one,
1992 because the loop count itself can overflow. */
1994 tree
1995 gfc_trans_do (gfc_code * code, tree exit_cond)
1997 gfc_se se;
1998 tree dovar;
1999 tree saved_dovar = NULL;
2000 tree from;
2001 tree to;
2002 tree step;
2003 tree countm1;
2004 tree type;
2005 tree utype;
2006 tree cond;
2007 tree cycle_label;
2008 tree exit_label;
2009 tree tmp;
2010 stmtblock_t block;
2011 stmtblock_t body;
2012 location_t loc;
2014 gfc_start_block (&block);
2016 loc = code->ext.iterator->start->where.lb->location;
2018 /* Evaluate all the expressions in the iterator. */
2019 gfc_init_se (&se, NULL);
2020 gfc_conv_expr_lhs (&se, code->ext.iterator->var);
2021 gfc_add_block_to_block (&block, &se.pre);
2022 dovar = se.expr;
2023 type = TREE_TYPE (dovar);
2025 gfc_init_se (&se, NULL);
2026 gfc_conv_expr_val (&se, code->ext.iterator->start);
2027 gfc_add_block_to_block (&block, &se.pre);
2028 from = gfc_evaluate_now (se.expr, &block);
2030 gfc_init_se (&se, NULL);
2031 gfc_conv_expr_val (&se, code->ext.iterator->end);
2032 gfc_add_block_to_block (&block, &se.pre);
2033 to = gfc_evaluate_now (se.expr, &block);
2035 gfc_init_se (&se, NULL);
2036 gfc_conv_expr_val (&se, code->ext.iterator->step);
2037 gfc_add_block_to_block (&block, &se.pre);
2038 step = gfc_evaluate_now (se.expr, &block);
2040 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
2042 tmp = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, step,
2043 build_zero_cst (type));
2044 gfc_trans_runtime_check (true, false, tmp, &block, &code->loc,
2045 "DO step value is zero");
2048 /* Special case simple loops. */
2049 if (TREE_CODE (type) == INTEGER_TYPE
2050 && (integer_onep (step)
2051 || tree_int_cst_equal (step, integer_minus_one_node)))
2052 return gfc_trans_simple_do (code, &block, dovar, from, to, step,
2053 exit_cond);
2055 if (TREE_CODE (type) == INTEGER_TYPE)
2056 utype = unsigned_type_for (type);
2057 else
2058 utype = unsigned_type_for (gfc_array_index_type);
2059 countm1 = gfc_create_var (utype, "countm1");
2061 /* Cycle and exit statements are implemented with gotos. */
2062 cycle_label = gfc_build_label_decl (NULL_TREE);
2063 exit_label = gfc_build_label_decl (NULL_TREE);
2064 TREE_USED (exit_label) = 1;
2066 /* Put these labels where they can be found later. */
2067 code->cycle_label = cycle_label;
2068 code->exit_label = exit_label;
2070 /* Initialize the DO variable: dovar = from. */
2071 gfc_add_modify (&block, dovar, from);
2073 /* Save value for do-tinkering checking. */
2074 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
2076 saved_dovar = gfc_create_var (type, ".saved_dovar");
2077 gfc_add_modify_loc (loc, &block, saved_dovar, dovar);
2080 /* Initialize loop count and jump to exit label if the loop is empty.
2081 This code is executed before we enter the loop body. We generate:
2082 if (step > 0)
2084 countm1 = (to - from) / step;
2085 if (to < from)
2086 goto exit_label;
2088 else
2090 countm1 = (from - to) / -step;
2091 if (to > from)
2092 goto exit_label;
2096 if (TREE_CODE (type) == INTEGER_TYPE)
2098 tree pos, neg, tou, fromu, stepu, tmp2;
2100 /* The distance from FROM to TO cannot always be represented in a signed
2101 type, thus use unsigned arithmetic, also to avoid any undefined
2102 overflow issues. */
2103 tou = fold_convert (utype, to);
2104 fromu = fold_convert (utype, from);
2105 stepu = fold_convert (utype, step);
2107 /* For a positive step, when to < from, exit, otherwise compute
2108 countm1 = ((unsigned)to - (unsigned)from) / (unsigned)step */
2109 tmp = fold_build2_loc (loc, LT_EXPR, boolean_type_node, to, from);
2110 tmp2 = fold_build2_loc (loc, TRUNC_DIV_EXPR, utype,
2111 fold_build2_loc (loc, MINUS_EXPR, utype,
2112 tou, fromu),
2113 stepu);
2114 pos = build2 (COMPOUND_EXPR, void_type_node,
2115 fold_build2 (MODIFY_EXPR, void_type_node,
2116 countm1, tmp2),
2117 build3_loc (loc, COND_EXPR, void_type_node,
2118 gfc_unlikely (tmp, PRED_FORTRAN_LOOP_PREHEADER),
2119 build1_loc (loc, GOTO_EXPR, void_type_node,
2120 exit_label), NULL_TREE));
2122 /* For a negative step, when to > from, exit, otherwise compute
2123 countm1 = ((unsigned)from - (unsigned)to) / -(unsigned)step */
2124 tmp = fold_build2_loc (loc, GT_EXPR, boolean_type_node, to, from);
2125 tmp2 = fold_build2_loc (loc, TRUNC_DIV_EXPR, utype,
2126 fold_build2_loc (loc, MINUS_EXPR, utype,
2127 fromu, tou),
2128 fold_build1_loc (loc, NEGATE_EXPR, utype, stepu));
2129 neg = build2 (COMPOUND_EXPR, void_type_node,
2130 fold_build2 (MODIFY_EXPR, void_type_node,
2131 countm1, tmp2),
2132 build3_loc (loc, COND_EXPR, void_type_node,
2133 gfc_unlikely (tmp, PRED_FORTRAN_LOOP_PREHEADER),
2134 build1_loc (loc, GOTO_EXPR, void_type_node,
2135 exit_label), NULL_TREE));
2137 tmp = fold_build2_loc (loc, LT_EXPR, boolean_type_node, step,
2138 build_int_cst (TREE_TYPE (step), 0));
2139 tmp = fold_build3_loc (loc, COND_EXPR, void_type_node, tmp, neg, pos);
2141 gfc_add_expr_to_block (&block, tmp);
2143 else
2145 tree pos_step;
2147 /* TODO: We could use the same width as the real type.
2148 This would probably cause more problems that it solves
2149 when we implement "long double" types. */
2151 tmp = fold_build2_loc (loc, MINUS_EXPR, type, to, from);
2152 tmp = fold_build2_loc (loc, RDIV_EXPR, type, tmp, step);
2153 tmp = fold_build1_loc (loc, FIX_TRUNC_EXPR, utype, tmp);
2154 gfc_add_modify (&block, countm1, tmp);
2156 /* We need a special check for empty loops:
2157 empty = (step > 0 ? to < from : to > from); */
2158 pos_step = fold_build2_loc (loc, GT_EXPR, boolean_type_node, step,
2159 build_zero_cst (type));
2160 tmp = fold_build3_loc (loc, COND_EXPR, boolean_type_node, pos_step,
2161 fold_build2_loc (loc, LT_EXPR,
2162 boolean_type_node, to, from),
2163 fold_build2_loc (loc, GT_EXPR,
2164 boolean_type_node, to, from));
2165 /* If the loop is empty, go directly to the exit label. */
2166 tmp = fold_build3_loc (loc, COND_EXPR, void_type_node, tmp,
2167 build1_v (GOTO_EXPR, exit_label),
2168 build_empty_stmt (input_location));
2169 gfc_add_expr_to_block (&block, tmp);
2172 /* Loop body. */
2173 gfc_start_block (&body);
2175 /* Main loop body. */
2176 tmp = gfc_trans_code_cond (code->block->next, exit_cond);
2177 gfc_add_expr_to_block (&body, tmp);
2179 /* Label for cycle statements (if needed). */
2180 if (TREE_USED (cycle_label))
2182 tmp = build1_v (LABEL_EXPR, cycle_label);
2183 gfc_add_expr_to_block (&body, tmp);
2186 /* Check whether someone has modified the loop variable. */
2187 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
2189 tmp = fold_build2_loc (loc, NE_EXPR, boolean_type_node, dovar,
2190 saved_dovar);
2191 gfc_trans_runtime_check (true, false, tmp, &body, &code->loc,
2192 "Loop variable has been modified");
2195 /* Exit the loop if there is an I/O result condition or error. */
2196 if (exit_cond)
2198 tmp = build1_v (GOTO_EXPR, exit_label);
2199 tmp = fold_build3_loc (loc, COND_EXPR, void_type_node,
2200 exit_cond, tmp,
2201 build_empty_stmt (input_location));
2202 gfc_add_expr_to_block (&body, tmp);
2205 /* Increment the loop variable. */
2206 tmp = fold_build2_loc (loc, PLUS_EXPR, type, dovar, step);
2207 gfc_add_modify_loc (loc, &body, dovar, tmp);
2209 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
2210 gfc_add_modify_loc (loc, &body, saved_dovar, dovar);
2212 /* Initialize countm1t. */
2213 tree countm1t = gfc_create_var (utype, "countm1t");
2214 gfc_add_modify_loc (loc, &body, countm1t, countm1);
2216 /* Decrement the loop count. */
2217 tmp = fold_build2_loc (loc, MINUS_EXPR, utype, countm1,
2218 build_int_cst (utype, 1));
2219 gfc_add_modify_loc (loc, &body, countm1, tmp);
2221 /* End with the loop condition. Loop until countm1t == 0. */
2222 cond = fold_build2_loc (loc, EQ_EXPR, boolean_type_node, countm1t,
2223 build_int_cst (utype, 0));
2224 tmp = fold_build1_loc (loc, GOTO_EXPR, void_type_node, exit_label);
2225 tmp = fold_build3_loc (loc, COND_EXPR, void_type_node,
2226 cond, tmp, build_empty_stmt (loc));
2227 gfc_add_expr_to_block (&body, tmp);
2229 /* End of loop body. */
2230 tmp = gfc_finish_block (&body);
2232 /* The for loop itself. */
2233 tmp = fold_build1_loc (loc, LOOP_EXPR, void_type_node, tmp);
2234 gfc_add_expr_to_block (&block, tmp);
2236 /* Add the exit label. */
2237 tmp = build1_v (LABEL_EXPR, exit_label);
2238 gfc_add_expr_to_block (&block, tmp);
2240 return gfc_finish_block (&block);
2244 /* Translate the DO WHILE construct.
2246 We translate
2248 DO WHILE (cond)
2249 body
2250 END DO
2254 for ( ; ; )
2256 pre_cond;
2257 if (! cond) goto exit_label;
2258 body;
2259 cycle_label:
2261 exit_label:
2263 Because the evaluation of the exit condition `cond' may have side
2264 effects, we can't do much for empty loop bodies. The backend optimizers
2265 should be smart enough to eliminate any dead loops. */
2267 tree
2268 gfc_trans_do_while (gfc_code * code)
2270 gfc_se cond;
2271 tree tmp;
2272 tree cycle_label;
2273 tree exit_label;
2274 stmtblock_t block;
2276 /* Everything we build here is part of the loop body. */
2277 gfc_start_block (&block);
2279 /* Cycle and exit statements are implemented with gotos. */
2280 cycle_label = gfc_build_label_decl (NULL_TREE);
2281 exit_label = gfc_build_label_decl (NULL_TREE);
2283 /* Put the labels where they can be found later. See gfc_trans_do(). */
2284 code->cycle_label = cycle_label;
2285 code->exit_label = exit_label;
2287 /* Create a GIMPLE version of the exit condition. */
2288 gfc_init_se (&cond, NULL);
2289 gfc_conv_expr_val (&cond, code->expr1);
2290 gfc_add_block_to_block (&block, &cond.pre);
2291 cond.expr = fold_build1_loc (code->expr1->where.lb->location,
2292 TRUTH_NOT_EXPR, TREE_TYPE (cond.expr), cond.expr);
2294 /* Build "IF (! cond) GOTO exit_label". */
2295 tmp = build1_v (GOTO_EXPR, exit_label);
2296 TREE_USED (exit_label) = 1;
2297 tmp = fold_build3_loc (code->expr1->where.lb->location, COND_EXPR,
2298 void_type_node, cond.expr, tmp,
2299 build_empty_stmt (code->expr1->where.lb->location));
2300 gfc_add_expr_to_block (&block, tmp);
2302 /* The main body of the loop. */
2303 tmp = gfc_trans_code (code->block->next);
2304 gfc_add_expr_to_block (&block, tmp);
2306 /* Label for cycle statements (if needed). */
2307 if (TREE_USED (cycle_label))
2309 tmp = build1_v (LABEL_EXPR, cycle_label);
2310 gfc_add_expr_to_block (&block, tmp);
2313 /* End of loop body. */
2314 tmp = gfc_finish_block (&block);
2316 gfc_init_block (&block);
2317 /* Build the loop. */
2318 tmp = fold_build1_loc (code->expr1->where.lb->location, LOOP_EXPR,
2319 void_type_node, tmp);
2320 gfc_add_expr_to_block (&block, tmp);
2322 /* Add the exit label. */
2323 tmp = build1_v (LABEL_EXPR, exit_label);
2324 gfc_add_expr_to_block (&block, tmp);
2326 return gfc_finish_block (&block);
2330 /* Translate the SELECT CASE construct for INTEGER case expressions,
2331 without killing all potential optimizations. The problem is that
2332 Fortran allows unbounded cases, but the back-end does not, so we
2333 need to intercept those before we enter the equivalent SWITCH_EXPR
2334 we can build.
2336 For example, we translate this,
2338 SELECT CASE (expr)
2339 CASE (:100,101,105:115)
2340 block_1
2341 CASE (190:199,200:)
2342 block_2
2343 CASE (300)
2344 block_3
2345 CASE DEFAULT
2346 block_4
2347 END SELECT
2349 to the GENERIC equivalent,
2351 switch (expr)
2353 case (minimum value for typeof(expr) ... 100:
2354 case 101:
2355 case 105 ... 114:
2356 block1:
2357 goto end_label;
2359 case 200 ... (maximum value for typeof(expr):
2360 case 190 ... 199:
2361 block2;
2362 goto end_label;
2364 case 300:
2365 block_3;
2366 goto end_label;
2368 default:
2369 block_4;
2370 goto end_label;
2373 end_label: */
2375 static tree
2376 gfc_trans_integer_select (gfc_code * code)
2378 gfc_code *c;
2379 gfc_case *cp;
2380 tree end_label;
2381 tree tmp;
2382 gfc_se se;
2383 stmtblock_t block;
2384 stmtblock_t body;
2386 gfc_start_block (&block);
2388 /* Calculate the switch expression. */
2389 gfc_init_se (&se, NULL);
2390 gfc_conv_expr_val (&se, code->expr1);
2391 gfc_add_block_to_block (&block, &se.pre);
2393 end_label = gfc_build_label_decl (NULL_TREE);
2395 gfc_init_block (&body);
2397 for (c = code->block; c; c = c->block)
2399 for (cp = c->ext.block.case_list; cp; cp = cp->next)
2401 tree low, high;
2402 tree label;
2404 /* Assume it's the default case. */
2405 low = high = NULL_TREE;
2407 if (cp->low)
2409 low = gfc_conv_mpz_to_tree (cp->low->value.integer,
2410 cp->low->ts.kind);
2412 /* If there's only a lower bound, set the high bound to the
2413 maximum value of the case expression. */
2414 if (!cp->high)
2415 high = TYPE_MAX_VALUE (TREE_TYPE (se.expr));
2418 if (cp->high)
2420 /* Three cases are possible here:
2422 1) There is no lower bound, e.g. CASE (:N).
2423 2) There is a lower bound .NE. high bound, that is
2424 a case range, e.g. CASE (N:M) where M>N (we make
2425 sure that M>N during type resolution).
2426 3) There is a lower bound, and it has the same value
2427 as the high bound, e.g. CASE (N:N). This is our
2428 internal representation of CASE(N).
2430 In the first and second case, we need to set a value for
2431 high. In the third case, we don't because the GCC middle
2432 end represents a single case value by just letting high be
2433 a NULL_TREE. We can't do that because we need to be able
2434 to represent unbounded cases. */
2436 if (!cp->low
2437 || (cp->low
2438 && mpz_cmp (cp->low->value.integer,
2439 cp->high->value.integer) != 0))
2440 high = gfc_conv_mpz_to_tree (cp->high->value.integer,
2441 cp->high->ts.kind);
2443 /* Unbounded case. */
2444 if (!cp->low)
2445 low = TYPE_MIN_VALUE (TREE_TYPE (se.expr));
2448 /* Build a label. */
2449 label = gfc_build_label_decl (NULL_TREE);
2451 /* Add this case label.
2452 Add parameter 'label', make it match GCC backend. */
2453 tmp = build_case_label (low, high, label);
2454 gfc_add_expr_to_block (&body, tmp);
2457 /* Add the statements for this case. */
2458 tmp = gfc_trans_code (c->next);
2459 gfc_add_expr_to_block (&body, tmp);
2461 /* Break to the end of the construct. */
2462 tmp = build1_v (GOTO_EXPR, end_label);
2463 gfc_add_expr_to_block (&body, tmp);
2466 tmp = gfc_finish_block (&body);
2467 tmp = fold_build3_loc (input_location, SWITCH_EXPR, NULL_TREE,
2468 se.expr, tmp, NULL_TREE);
2469 gfc_add_expr_to_block (&block, tmp);
2471 tmp = build1_v (LABEL_EXPR, end_label);
2472 gfc_add_expr_to_block (&block, tmp);
2474 return gfc_finish_block (&block);
2478 /* Translate the SELECT CASE construct for LOGICAL case expressions.
2480 There are only two cases possible here, even though the standard
2481 does allow three cases in a LOGICAL SELECT CASE construct: .TRUE.,
2482 .FALSE., and DEFAULT.
2484 We never generate more than two blocks here. Instead, we always
2485 try to eliminate the DEFAULT case. This way, we can translate this
2486 kind of SELECT construct to a simple
2488 if {} else {};
2490 expression in GENERIC. */
2492 static tree
2493 gfc_trans_logical_select (gfc_code * code)
2495 gfc_code *c;
2496 gfc_code *t, *f, *d;
2497 gfc_case *cp;
2498 gfc_se se;
2499 stmtblock_t block;
2501 /* Assume we don't have any cases at all. */
2502 t = f = d = NULL;
2504 /* Now see which ones we actually do have. We can have at most two
2505 cases in a single case list: one for .TRUE. and one for .FALSE.
2506 The default case is always separate. If the cases for .TRUE. and
2507 .FALSE. are in the same case list, the block for that case list
2508 always executed, and we don't generate code a COND_EXPR. */
2509 for (c = code->block; c; c = c->block)
2511 for (cp = c->ext.block.case_list; cp; cp = cp->next)
2513 if (cp->low)
2515 if (cp->low->value.logical == 0) /* .FALSE. */
2516 f = c;
2517 else /* if (cp->value.logical != 0), thus .TRUE. */
2518 t = c;
2520 else
2521 d = c;
2525 /* Start a new block. */
2526 gfc_start_block (&block);
2528 /* Calculate the switch expression. We always need to do this
2529 because it may have side effects. */
2530 gfc_init_se (&se, NULL);
2531 gfc_conv_expr_val (&se, code->expr1);
2532 gfc_add_block_to_block (&block, &se.pre);
2534 if (t == f && t != NULL)
2536 /* Cases for .TRUE. and .FALSE. are in the same block. Just
2537 translate the code for these cases, append it to the current
2538 block. */
2539 gfc_add_expr_to_block (&block, gfc_trans_code (t->next));
2541 else
2543 tree true_tree, false_tree, stmt;
2545 true_tree = build_empty_stmt (input_location);
2546 false_tree = build_empty_stmt (input_location);
2548 /* If we have a case for .TRUE. and for .FALSE., discard the default case.
2549 Otherwise, if .TRUE. or .FALSE. is missing and there is a default case,
2550 make the missing case the default case. */
2551 if (t != NULL && f != NULL)
2552 d = NULL;
2553 else if (d != NULL)
2555 if (t == NULL)
2556 t = d;
2557 else
2558 f = d;
2561 /* Translate the code for each of these blocks, and append it to
2562 the current block. */
2563 if (t != NULL)
2564 true_tree = gfc_trans_code (t->next);
2566 if (f != NULL)
2567 false_tree = gfc_trans_code (f->next);
2569 stmt = fold_build3_loc (input_location, COND_EXPR, void_type_node,
2570 se.expr, true_tree, false_tree);
2571 gfc_add_expr_to_block (&block, stmt);
2574 return gfc_finish_block (&block);
2578 /* The jump table types are stored in static variables to avoid
2579 constructing them from scratch every single time. */
2580 static GTY(()) tree select_struct[2];
2582 /* Translate the SELECT CASE construct for CHARACTER case expressions.
2583 Instead of generating compares and jumps, it is far simpler to
2584 generate a data structure describing the cases in order and call a
2585 library subroutine that locates the right case.
2586 This is particularly true because this is the only case where we
2587 might have to dispose of a temporary.
2588 The library subroutine returns a pointer to jump to or NULL if no
2589 branches are to be taken. */
2591 static tree
2592 gfc_trans_character_select (gfc_code *code)
2594 tree init, end_label, tmp, type, case_num, label, fndecl;
2595 stmtblock_t block, body;
2596 gfc_case *cp, *d;
2597 gfc_code *c;
2598 gfc_se se, expr1se;
2599 int n, k;
2600 vec<constructor_elt, va_gc> *inits = NULL;
2602 tree pchartype = gfc_get_pchar_type (code->expr1->ts.kind);
2604 /* The jump table types are stored in static variables to avoid
2605 constructing them from scratch every single time. */
2606 static tree ss_string1[2], ss_string1_len[2];
2607 static tree ss_string2[2], ss_string2_len[2];
2608 static tree ss_target[2];
2610 cp = code->block->ext.block.case_list;
2611 while (cp->left != NULL)
2612 cp = cp->left;
2614 /* Generate the body */
2615 gfc_start_block (&block);
2616 gfc_init_se (&expr1se, NULL);
2617 gfc_conv_expr_reference (&expr1se, code->expr1);
2619 gfc_add_block_to_block (&block, &expr1se.pre);
2621 end_label = gfc_build_label_decl (NULL_TREE);
2623 gfc_init_block (&body);
2625 /* Attempt to optimize length 1 selects. */
2626 if (integer_onep (expr1se.string_length))
2628 for (d = cp; d; d = d->right)
2630 int i;
2631 if (d->low)
2633 gcc_assert (d->low->expr_type == EXPR_CONSTANT
2634 && d->low->ts.type == BT_CHARACTER);
2635 if (d->low->value.character.length > 1)
2637 for (i = 1; i < d->low->value.character.length; i++)
2638 if (d->low->value.character.string[i] != ' ')
2639 break;
2640 if (i != d->low->value.character.length)
2642 if (optimize && d->high && i == 1)
2644 gcc_assert (d->high->expr_type == EXPR_CONSTANT
2645 && d->high->ts.type == BT_CHARACTER);
2646 if (d->high->value.character.length > 1
2647 && (d->low->value.character.string[0]
2648 == d->high->value.character.string[0])
2649 && d->high->value.character.string[1] != ' '
2650 && ((d->low->value.character.string[1] < ' ')
2651 == (d->high->value.character.string[1]
2652 < ' ')))
2653 continue;
2655 break;
2659 if (d->high)
2661 gcc_assert (d->high->expr_type == EXPR_CONSTANT
2662 && d->high->ts.type == BT_CHARACTER);
2663 if (d->high->value.character.length > 1)
2665 for (i = 1; i < d->high->value.character.length; i++)
2666 if (d->high->value.character.string[i] != ' ')
2667 break;
2668 if (i != d->high->value.character.length)
2669 break;
2673 if (d == NULL)
2675 tree ctype = gfc_get_char_type (code->expr1->ts.kind);
2677 for (c = code->block; c; c = c->block)
2679 for (cp = c->ext.block.case_list; cp; cp = cp->next)
2681 tree low, high;
2682 tree label;
2683 gfc_char_t r;
2685 /* Assume it's the default case. */
2686 low = high = NULL_TREE;
2688 if (cp->low)
2690 /* CASE ('ab') or CASE ('ab':'az') will never match
2691 any length 1 character. */
2692 if (cp->low->value.character.length > 1
2693 && cp->low->value.character.string[1] != ' ')
2694 continue;
2696 if (cp->low->value.character.length > 0)
2697 r = cp->low->value.character.string[0];
2698 else
2699 r = ' ';
2700 low = build_int_cst (ctype, r);
2702 /* If there's only a lower bound, set the high bound
2703 to the maximum value of the case expression. */
2704 if (!cp->high)
2705 high = TYPE_MAX_VALUE (ctype);
2708 if (cp->high)
2710 if (!cp->low
2711 || (cp->low->value.character.string[0]
2712 != cp->high->value.character.string[0]))
2714 if (cp->high->value.character.length > 0)
2715 r = cp->high->value.character.string[0];
2716 else
2717 r = ' ';
2718 high = build_int_cst (ctype, r);
2721 /* Unbounded case. */
2722 if (!cp->low)
2723 low = TYPE_MIN_VALUE (ctype);
2726 /* Build a label. */
2727 label = gfc_build_label_decl (NULL_TREE);
2729 /* Add this case label.
2730 Add parameter 'label', make it match GCC backend. */
2731 tmp = build_case_label (low, high, label);
2732 gfc_add_expr_to_block (&body, tmp);
2735 /* Add the statements for this case. */
2736 tmp = gfc_trans_code (c->next);
2737 gfc_add_expr_to_block (&body, tmp);
2739 /* Break to the end of the construct. */
2740 tmp = build1_v (GOTO_EXPR, end_label);
2741 gfc_add_expr_to_block (&body, tmp);
2744 tmp = gfc_string_to_single_character (expr1se.string_length,
2745 expr1se.expr,
2746 code->expr1->ts.kind);
2747 case_num = gfc_create_var (ctype, "case_num");
2748 gfc_add_modify (&block, case_num, tmp);
2750 gfc_add_block_to_block (&block, &expr1se.post);
2752 tmp = gfc_finish_block (&body);
2753 tmp = fold_build3_loc (input_location, SWITCH_EXPR, NULL_TREE,
2754 case_num, tmp, NULL_TREE);
2755 gfc_add_expr_to_block (&block, tmp);
2757 tmp = build1_v (LABEL_EXPR, end_label);
2758 gfc_add_expr_to_block (&block, tmp);
2760 return gfc_finish_block (&block);
2764 if (code->expr1->ts.kind == 1)
2765 k = 0;
2766 else if (code->expr1->ts.kind == 4)
2767 k = 1;
2768 else
2769 gcc_unreachable ();
2771 if (select_struct[k] == NULL)
2773 tree *chain = NULL;
2774 select_struct[k] = make_node (RECORD_TYPE);
2776 if (code->expr1->ts.kind == 1)
2777 TYPE_NAME (select_struct[k]) = get_identifier ("_jump_struct_char1");
2778 else if (code->expr1->ts.kind == 4)
2779 TYPE_NAME (select_struct[k]) = get_identifier ("_jump_struct_char4");
2780 else
2781 gcc_unreachable ();
2783 #undef ADD_FIELD
2784 #define ADD_FIELD(NAME, TYPE) \
2785 ss_##NAME[k] = gfc_add_field_to_struct (select_struct[k], \
2786 get_identifier (stringize(NAME)), \
2787 TYPE, \
2788 &chain)
2790 ADD_FIELD (string1, pchartype);
2791 ADD_FIELD (string1_len, gfc_charlen_type_node);
2793 ADD_FIELD (string2, pchartype);
2794 ADD_FIELD (string2_len, gfc_charlen_type_node);
2796 ADD_FIELD (target, integer_type_node);
2797 #undef ADD_FIELD
2799 gfc_finish_type (select_struct[k]);
2802 n = 0;
2803 for (d = cp; d; d = d->right)
2804 d->n = n++;
2806 for (c = code->block; c; c = c->block)
2808 for (d = c->ext.block.case_list; d; d = d->next)
2810 label = gfc_build_label_decl (NULL_TREE);
2811 tmp = build_case_label ((d->low == NULL && d->high == NULL)
2812 ? NULL
2813 : build_int_cst (integer_type_node, d->n),
2814 NULL, label);
2815 gfc_add_expr_to_block (&body, tmp);
2818 tmp = gfc_trans_code (c->next);
2819 gfc_add_expr_to_block (&body, tmp);
2821 tmp = build1_v (GOTO_EXPR, end_label);
2822 gfc_add_expr_to_block (&body, tmp);
2825 /* Generate the structure describing the branches */
2826 for (d = cp; d; d = d->right)
2828 vec<constructor_elt, va_gc> *node = NULL;
2830 gfc_init_se (&se, NULL);
2832 if (d->low == NULL)
2834 CONSTRUCTOR_APPEND_ELT (node, ss_string1[k], null_pointer_node);
2835 CONSTRUCTOR_APPEND_ELT (node, ss_string1_len[k], integer_zero_node);
2837 else
2839 gfc_conv_expr_reference (&se, d->low);
2841 CONSTRUCTOR_APPEND_ELT (node, ss_string1[k], se.expr);
2842 CONSTRUCTOR_APPEND_ELT (node, ss_string1_len[k], se.string_length);
2845 if (d->high == NULL)
2847 CONSTRUCTOR_APPEND_ELT (node, ss_string2[k], null_pointer_node);
2848 CONSTRUCTOR_APPEND_ELT (node, ss_string2_len[k], integer_zero_node);
2850 else
2852 gfc_init_se (&se, NULL);
2853 gfc_conv_expr_reference (&se, d->high);
2855 CONSTRUCTOR_APPEND_ELT (node, ss_string2[k], se.expr);
2856 CONSTRUCTOR_APPEND_ELT (node, ss_string2_len[k], se.string_length);
2859 CONSTRUCTOR_APPEND_ELT (node, ss_target[k],
2860 build_int_cst (integer_type_node, d->n));
2862 tmp = build_constructor (select_struct[k], node);
2863 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, tmp);
2866 type = build_array_type (select_struct[k],
2867 build_index_type (size_int (n-1)));
2869 init = build_constructor (type, inits);
2870 TREE_CONSTANT (init) = 1;
2871 TREE_STATIC (init) = 1;
2872 /* Create a static variable to hold the jump table. */
2873 tmp = gfc_create_var (type, "jumptable");
2874 TREE_CONSTANT (tmp) = 1;
2875 TREE_STATIC (tmp) = 1;
2876 TREE_READONLY (tmp) = 1;
2877 DECL_INITIAL (tmp) = init;
2878 init = tmp;
2880 /* Build the library call */
2881 init = gfc_build_addr_expr (pvoid_type_node, init);
2883 if (code->expr1->ts.kind == 1)
2884 fndecl = gfor_fndecl_select_string;
2885 else if (code->expr1->ts.kind == 4)
2886 fndecl = gfor_fndecl_select_string_char4;
2887 else
2888 gcc_unreachable ();
2890 tmp = build_call_expr_loc (input_location,
2891 fndecl, 4, init,
2892 build_int_cst (gfc_charlen_type_node, n),
2893 expr1se.expr, expr1se.string_length);
2894 case_num = gfc_create_var (integer_type_node, "case_num");
2895 gfc_add_modify (&block, case_num, tmp);
2897 gfc_add_block_to_block (&block, &expr1se.post);
2899 tmp = gfc_finish_block (&body);
2900 tmp = fold_build3_loc (input_location, SWITCH_EXPR, NULL_TREE,
2901 case_num, tmp, NULL_TREE);
2902 gfc_add_expr_to_block (&block, tmp);
2904 tmp = build1_v (LABEL_EXPR, end_label);
2905 gfc_add_expr_to_block (&block, tmp);
2907 return gfc_finish_block (&block);
2911 /* Translate the three variants of the SELECT CASE construct.
2913 SELECT CASEs with INTEGER case expressions can be translated to an
2914 equivalent GENERIC switch statement, and for LOGICAL case
2915 expressions we build one or two if-else compares.
2917 SELECT CASEs with CHARACTER case expressions are a whole different
2918 story, because they don't exist in GENERIC. So we sort them and
2919 do a binary search at runtime.
2921 Fortran has no BREAK statement, and it does not allow jumps from
2922 one case block to another. That makes things a lot easier for
2923 the optimizers. */
2925 tree
2926 gfc_trans_select (gfc_code * code)
2928 stmtblock_t block;
2929 tree body;
2930 tree exit_label;
2932 gcc_assert (code && code->expr1);
2933 gfc_init_block (&block);
2935 /* Build the exit label and hang it in. */
2936 exit_label = gfc_build_label_decl (NULL_TREE);
2937 code->exit_label = exit_label;
2939 /* Empty SELECT constructs are legal. */
2940 if (code->block == NULL)
2941 body = build_empty_stmt (input_location);
2943 /* Select the correct translation function. */
2944 else
2945 switch (code->expr1->ts.type)
2947 case BT_LOGICAL:
2948 body = gfc_trans_logical_select (code);
2949 break;
2951 case BT_INTEGER:
2952 body = gfc_trans_integer_select (code);
2953 break;
2955 case BT_CHARACTER:
2956 body = gfc_trans_character_select (code);
2957 break;
2959 default:
2960 gfc_internal_error ("gfc_trans_select(): Bad type for case expr.");
2961 /* Not reached */
2964 /* Build everything together. */
2965 gfc_add_expr_to_block (&block, body);
2966 gfc_add_expr_to_block (&block, build1_v (LABEL_EXPR, exit_label));
2968 return gfc_finish_block (&block);
2972 /* Traversal function to substitute a replacement symtree if the symbol
2973 in the expression is the same as that passed. f == 2 signals that
2974 that variable itself is not to be checked - only the references.
2975 This group of functions is used when the variable expression in a
2976 FORALL assignment has internal references. For example:
2977 FORALL (i = 1:4) p(p(i)) = i
2978 The only recourse here is to store a copy of 'p' for the index
2979 expression. */
2981 static gfc_symtree *new_symtree;
2982 static gfc_symtree *old_symtree;
2984 static bool
2985 forall_replace (gfc_expr *expr, gfc_symbol *sym, int *f)
2987 if (expr->expr_type != EXPR_VARIABLE)
2988 return false;
2990 if (*f == 2)
2991 *f = 1;
2992 else if (expr->symtree->n.sym == sym)
2993 expr->symtree = new_symtree;
2995 return false;
2998 static void
2999 forall_replace_symtree (gfc_expr *e, gfc_symbol *sym, int f)
3001 gfc_traverse_expr (e, sym, forall_replace, f);
3004 static bool
3005 forall_restore (gfc_expr *expr,
3006 gfc_symbol *sym ATTRIBUTE_UNUSED,
3007 int *f ATTRIBUTE_UNUSED)
3009 if (expr->expr_type != EXPR_VARIABLE)
3010 return false;
3012 if (expr->symtree == new_symtree)
3013 expr->symtree = old_symtree;
3015 return false;
3018 static void
3019 forall_restore_symtree (gfc_expr *e)
3021 gfc_traverse_expr (e, NULL, forall_restore, 0);
3024 static void
3025 forall_make_variable_temp (gfc_code *c, stmtblock_t *pre, stmtblock_t *post)
3027 gfc_se tse;
3028 gfc_se rse;
3029 gfc_expr *e;
3030 gfc_symbol *new_sym;
3031 gfc_symbol *old_sym;
3032 gfc_symtree *root;
3033 tree tmp;
3035 /* Build a copy of the lvalue. */
3036 old_symtree = c->expr1->symtree;
3037 old_sym = old_symtree->n.sym;
3038 e = gfc_lval_expr_from_sym (old_sym);
3039 if (old_sym->attr.dimension)
3041 gfc_init_se (&tse, NULL);
3042 gfc_conv_subref_array_arg (&tse, e, 0, INTENT_IN, false);
3043 gfc_add_block_to_block (pre, &tse.pre);
3044 gfc_add_block_to_block (post, &tse.post);
3045 tse.expr = build_fold_indirect_ref_loc (input_location, tse.expr);
3047 if (e->ts.type != BT_CHARACTER)
3049 /* Use the variable offset for the temporary. */
3050 tmp = gfc_conv_array_offset (old_sym->backend_decl);
3051 gfc_conv_descriptor_offset_set (pre, tse.expr, tmp);
3054 else
3056 gfc_init_se (&tse, NULL);
3057 gfc_init_se (&rse, NULL);
3058 gfc_conv_expr (&rse, e);
3059 if (e->ts.type == BT_CHARACTER)
3061 tse.string_length = rse.string_length;
3062 tmp = gfc_get_character_type_len (gfc_default_character_kind,
3063 tse.string_length);
3064 tse.expr = gfc_conv_string_tmp (&tse, build_pointer_type (tmp),
3065 rse.string_length);
3066 gfc_add_block_to_block (pre, &tse.pre);
3067 gfc_add_block_to_block (post, &tse.post);
3069 else
3071 tmp = gfc_typenode_for_spec (&e->ts);
3072 tse.expr = gfc_create_var (tmp, "temp");
3075 tmp = gfc_trans_scalar_assign (&tse, &rse, e->ts,
3076 e->expr_type == EXPR_VARIABLE, false);
3077 gfc_add_expr_to_block (pre, tmp);
3079 gfc_free_expr (e);
3081 /* Create a new symbol to represent the lvalue. */
3082 new_sym = gfc_new_symbol (old_sym->name, NULL);
3083 new_sym->ts = old_sym->ts;
3084 new_sym->attr.referenced = 1;
3085 new_sym->attr.temporary = 1;
3086 new_sym->attr.dimension = old_sym->attr.dimension;
3087 new_sym->attr.flavor = old_sym->attr.flavor;
3089 /* Use the temporary as the backend_decl. */
3090 new_sym->backend_decl = tse.expr;
3092 /* Create a fake symtree for it. */
3093 root = NULL;
3094 new_symtree = gfc_new_symtree (&root, old_sym->name);
3095 new_symtree->n.sym = new_sym;
3096 gcc_assert (new_symtree == root);
3098 /* Go through the expression reference replacing the old_symtree
3099 with the new. */
3100 forall_replace_symtree (c->expr1, old_sym, 2);
3102 /* Now we have made this temporary, we might as well use it for
3103 the right hand side. */
3104 forall_replace_symtree (c->expr2, old_sym, 1);
3108 /* Handles dependencies in forall assignments. */
3109 static int
3110 check_forall_dependencies (gfc_code *c, stmtblock_t *pre, stmtblock_t *post)
3112 gfc_ref *lref;
3113 gfc_ref *rref;
3114 int need_temp;
3115 gfc_symbol *lsym;
3117 lsym = c->expr1->symtree->n.sym;
3118 need_temp = gfc_check_dependency (c->expr1, c->expr2, 0);
3120 /* Now check for dependencies within the 'variable'
3121 expression itself. These are treated by making a complete
3122 copy of variable and changing all the references to it
3123 point to the copy instead. Note that the shallow copy of
3124 the variable will not suffice for derived types with
3125 pointer components. We therefore leave these to their
3126 own devices. */
3127 if (lsym->ts.type == BT_DERIVED
3128 && lsym->ts.u.derived->attr.pointer_comp)
3129 return need_temp;
3131 new_symtree = NULL;
3132 if (find_forall_index (c->expr1, lsym, 2))
3134 forall_make_variable_temp (c, pre, post);
3135 need_temp = 0;
3138 /* Substrings with dependencies are treated in the same
3139 way. */
3140 if (c->expr1->ts.type == BT_CHARACTER
3141 && c->expr1->ref
3142 && c->expr2->expr_type == EXPR_VARIABLE
3143 && lsym == c->expr2->symtree->n.sym)
3145 for (lref = c->expr1->ref; lref; lref = lref->next)
3146 if (lref->type == REF_SUBSTRING)
3147 break;
3148 for (rref = c->expr2->ref; rref; rref = rref->next)
3149 if (rref->type == REF_SUBSTRING)
3150 break;
3152 if (rref && lref
3153 && gfc_dep_compare_expr (rref->u.ss.start, lref->u.ss.start) < 0)
3155 forall_make_variable_temp (c, pre, post);
3156 need_temp = 0;
3159 return need_temp;
3163 static void
3164 cleanup_forall_symtrees (gfc_code *c)
3166 forall_restore_symtree (c->expr1);
3167 forall_restore_symtree (c->expr2);
3168 free (new_symtree->n.sym);
3169 free (new_symtree);
3173 /* Generate the loops for a FORALL block, specified by FORALL_TMP. BODY
3174 is the contents of the FORALL block/stmt to be iterated. MASK_FLAG
3175 indicates whether we should generate code to test the FORALLs mask
3176 array. OUTER is the loop header to be used for initializing mask
3177 indices.
3179 The generated loop format is:
3180 count = (end - start + step) / step
3181 loopvar = start
3182 while (1)
3184 if (count <=0 )
3185 goto end_of_loop
3186 <body>
3187 loopvar += step
3188 count --
3190 end_of_loop: */
3192 static tree
3193 gfc_trans_forall_loop (forall_info *forall_tmp, tree body,
3194 int mask_flag, stmtblock_t *outer)
3196 int n, nvar;
3197 tree tmp;
3198 tree cond;
3199 stmtblock_t block;
3200 tree exit_label;
3201 tree count;
3202 tree var, start, end, step;
3203 iter_info *iter;
3205 /* Initialize the mask index outside the FORALL nest. */
3206 if (mask_flag && forall_tmp->mask)
3207 gfc_add_modify (outer, forall_tmp->maskindex, gfc_index_zero_node);
3209 iter = forall_tmp->this_loop;
3210 nvar = forall_tmp->nvar;
3211 for (n = 0; n < nvar; n++)
3213 var = iter->var;
3214 start = iter->start;
3215 end = iter->end;
3216 step = iter->step;
3218 exit_label = gfc_build_label_decl (NULL_TREE);
3219 TREE_USED (exit_label) = 1;
3221 /* The loop counter. */
3222 count = gfc_create_var (TREE_TYPE (var), "count");
3224 /* The body of the loop. */
3225 gfc_init_block (&block);
3227 /* The exit condition. */
3228 cond = fold_build2_loc (input_location, LE_EXPR, boolean_type_node,
3229 count, build_int_cst (TREE_TYPE (count), 0));
3230 if (forall_tmp->do_concurrent)
3231 cond = build2 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
3232 build_int_cst (integer_type_node,
3233 annot_expr_ivdep_kind));
3235 tmp = build1_v (GOTO_EXPR, exit_label);
3236 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
3237 cond, tmp, build_empty_stmt (input_location));
3238 gfc_add_expr_to_block (&block, tmp);
3240 /* The main loop body. */
3241 gfc_add_expr_to_block (&block, body);
3243 /* Increment the loop variable. */
3244 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (var), var,
3245 step);
3246 gfc_add_modify (&block, var, tmp);
3248 /* Advance to the next mask element. Only do this for the
3249 innermost loop. */
3250 if (n == 0 && mask_flag && forall_tmp->mask)
3252 tree maskindex = forall_tmp->maskindex;
3253 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
3254 maskindex, gfc_index_one_node);
3255 gfc_add_modify (&block, maskindex, tmp);
3258 /* Decrement the loop counter. */
3259 tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (var), count,
3260 build_int_cst (TREE_TYPE (var), 1));
3261 gfc_add_modify (&block, count, tmp);
3263 body = gfc_finish_block (&block);
3265 /* Loop var initialization. */
3266 gfc_init_block (&block);
3267 gfc_add_modify (&block, var, start);
3270 /* Initialize the loop counter. */
3271 tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (var), step,
3272 start);
3273 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (var), end,
3274 tmp);
3275 tmp = fold_build2_loc (input_location, TRUNC_DIV_EXPR, TREE_TYPE (var),
3276 tmp, step);
3277 gfc_add_modify (&block, count, tmp);
3279 /* The loop expression. */
3280 tmp = build1_v (LOOP_EXPR, body);
3281 gfc_add_expr_to_block (&block, tmp);
3283 /* The exit label. */
3284 tmp = build1_v (LABEL_EXPR, exit_label);
3285 gfc_add_expr_to_block (&block, tmp);
3287 body = gfc_finish_block (&block);
3288 iter = iter->next;
3290 return body;
3294 /* Generate the body and loops according to MASK_FLAG. If MASK_FLAG
3295 is nonzero, the body is controlled by all masks in the forall nest.
3296 Otherwise, the innermost loop is not controlled by it's mask. This
3297 is used for initializing that mask. */
3299 static tree
3300 gfc_trans_nested_forall_loop (forall_info * nested_forall_info, tree body,
3301 int mask_flag)
3303 tree tmp;
3304 stmtblock_t header;
3305 forall_info *forall_tmp;
3306 tree mask, maskindex;
3308 gfc_start_block (&header);
3310 forall_tmp = nested_forall_info;
3311 while (forall_tmp != NULL)
3313 /* Generate body with masks' control. */
3314 if (mask_flag)
3316 mask = forall_tmp->mask;
3317 maskindex = forall_tmp->maskindex;
3319 /* If a mask was specified make the assignment conditional. */
3320 if (mask)
3322 tmp = gfc_build_array_ref (mask, maskindex, NULL);
3323 body = build3_v (COND_EXPR, tmp, body,
3324 build_empty_stmt (input_location));
3327 body = gfc_trans_forall_loop (forall_tmp, body, mask_flag, &header);
3328 forall_tmp = forall_tmp->prev_nest;
3329 mask_flag = 1;
3332 gfc_add_expr_to_block (&header, body);
3333 return gfc_finish_block (&header);
3337 /* Allocate data for holding a temporary array. Returns either a local
3338 temporary array or a pointer variable. */
3340 static tree
3341 gfc_do_allocate (tree bytesize, tree size, tree * pdata, stmtblock_t * pblock,
3342 tree elem_type)
3344 tree tmpvar;
3345 tree type;
3346 tree tmp;
3348 if (INTEGER_CST_P (size))
3349 tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
3350 size, gfc_index_one_node);
3351 else
3352 tmp = NULL_TREE;
3354 type = build_range_type (gfc_array_index_type, gfc_index_zero_node, tmp);
3355 type = build_array_type (elem_type, type);
3356 if (gfc_can_put_var_on_stack (bytesize) && INTEGER_CST_P (size))
3358 tmpvar = gfc_create_var (type, "temp");
3359 *pdata = NULL_TREE;
3361 else
3363 tmpvar = gfc_create_var (build_pointer_type (type), "temp");
3364 *pdata = convert (pvoid_type_node, tmpvar);
3366 tmp = gfc_call_malloc (pblock, TREE_TYPE (tmpvar), bytesize);
3367 gfc_add_modify (pblock, tmpvar, tmp);
3369 return tmpvar;
3373 /* Generate codes to copy the temporary to the actual lhs. */
3375 static tree
3376 generate_loop_for_temp_to_lhs (gfc_expr *expr, tree tmp1, tree count3,
3377 tree count1, tree wheremask, bool invert)
3379 gfc_ss *lss;
3380 gfc_se lse, rse;
3381 stmtblock_t block, body;
3382 gfc_loopinfo loop1;
3383 tree tmp;
3384 tree wheremaskexpr;
3386 /* Walk the lhs. */
3387 lss = gfc_walk_expr (expr);
3389 if (lss == gfc_ss_terminator)
3391 gfc_start_block (&block);
3393 gfc_init_se (&lse, NULL);
3395 /* Translate the expression. */
3396 gfc_conv_expr (&lse, expr);
3398 /* Form the expression for the temporary. */
3399 tmp = gfc_build_array_ref (tmp1, count1, NULL);
3401 /* Use the scalar assignment as is. */
3402 gfc_add_block_to_block (&block, &lse.pre);
3403 gfc_add_modify (&block, lse.expr, tmp);
3404 gfc_add_block_to_block (&block, &lse.post);
3406 /* Increment the count1. */
3407 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (count1),
3408 count1, gfc_index_one_node);
3409 gfc_add_modify (&block, count1, tmp);
3411 tmp = gfc_finish_block (&block);
3413 else
3415 gfc_start_block (&block);
3417 gfc_init_loopinfo (&loop1);
3418 gfc_init_se (&rse, NULL);
3419 gfc_init_se (&lse, NULL);
3421 /* Associate the lss with the loop. */
3422 gfc_add_ss_to_loop (&loop1, lss);
3424 /* Calculate the bounds of the scalarization. */
3425 gfc_conv_ss_startstride (&loop1);
3426 /* Setup the scalarizing loops. */
3427 gfc_conv_loop_setup (&loop1, &expr->where);
3429 gfc_mark_ss_chain_used (lss, 1);
3431 /* Start the scalarized loop body. */
3432 gfc_start_scalarized_body (&loop1, &body);
3434 /* Setup the gfc_se structures. */
3435 gfc_copy_loopinfo_to_se (&lse, &loop1);
3436 lse.ss = lss;
3438 /* Form the expression of the temporary. */
3439 if (lss != gfc_ss_terminator)
3440 rse.expr = gfc_build_array_ref (tmp1, count1, NULL);
3441 /* Translate expr. */
3442 gfc_conv_expr (&lse, expr);
3444 /* Use the scalar assignment. */
3445 rse.string_length = lse.string_length;
3446 tmp = gfc_trans_scalar_assign (&lse, &rse, expr->ts, true, true);
3448 /* Form the mask expression according to the mask tree list. */
3449 if (wheremask)
3451 wheremaskexpr = gfc_build_array_ref (wheremask, count3, NULL);
3452 if (invert)
3453 wheremaskexpr = fold_build1_loc (input_location, TRUTH_NOT_EXPR,
3454 TREE_TYPE (wheremaskexpr),
3455 wheremaskexpr);
3456 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
3457 wheremaskexpr, tmp,
3458 build_empty_stmt (input_location));
3461 gfc_add_expr_to_block (&body, tmp);
3463 /* Increment count1. */
3464 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
3465 count1, gfc_index_one_node);
3466 gfc_add_modify (&body, count1, tmp);
3468 /* Increment count3. */
3469 if (count3)
3471 tmp = fold_build2_loc (input_location, PLUS_EXPR,
3472 gfc_array_index_type, count3,
3473 gfc_index_one_node);
3474 gfc_add_modify (&body, count3, tmp);
3477 /* Generate the copying loops. */
3478 gfc_trans_scalarizing_loops (&loop1, &body);
3479 gfc_add_block_to_block (&block, &loop1.pre);
3480 gfc_add_block_to_block (&block, &loop1.post);
3481 gfc_cleanup_loop (&loop1);
3483 tmp = gfc_finish_block (&block);
3485 return tmp;
3489 /* Generate codes to copy rhs to the temporary. TMP1 is the address of
3490 temporary, LSS and RSS are formed in function compute_inner_temp_size(),
3491 and should not be freed. WHEREMASK is the conditional execution mask
3492 whose sense may be inverted by INVERT. */
3494 static tree
3495 generate_loop_for_rhs_to_temp (gfc_expr *expr2, tree tmp1, tree count3,
3496 tree count1, gfc_ss *lss, gfc_ss *rss,
3497 tree wheremask, bool invert)
3499 stmtblock_t block, body1;
3500 gfc_loopinfo loop;
3501 gfc_se lse;
3502 gfc_se rse;
3503 tree tmp;
3504 tree wheremaskexpr;
3506 gfc_start_block (&block);
3508 gfc_init_se (&rse, NULL);
3509 gfc_init_se (&lse, NULL);
3511 if (lss == gfc_ss_terminator)
3513 gfc_init_block (&body1);
3514 gfc_conv_expr (&rse, expr2);
3515 lse.expr = gfc_build_array_ref (tmp1, count1, NULL);
3517 else
3519 /* Initialize the loop. */
3520 gfc_init_loopinfo (&loop);
3522 /* We may need LSS to determine the shape of the expression. */
3523 gfc_add_ss_to_loop (&loop, lss);
3524 gfc_add_ss_to_loop (&loop, rss);
3526 gfc_conv_ss_startstride (&loop);
3527 gfc_conv_loop_setup (&loop, &expr2->where);
3529 gfc_mark_ss_chain_used (rss, 1);
3530 /* Start the loop body. */
3531 gfc_start_scalarized_body (&loop, &body1);
3533 /* Translate the expression. */
3534 gfc_copy_loopinfo_to_se (&rse, &loop);
3535 rse.ss = rss;
3536 gfc_conv_expr (&rse, expr2);
3538 /* Form the expression of the temporary. */
3539 lse.expr = gfc_build_array_ref (tmp1, count1, NULL);
3542 /* Use the scalar assignment. */
3543 lse.string_length = rse.string_length;
3544 tmp = gfc_trans_scalar_assign (&lse, &rse, expr2->ts,
3545 expr2->expr_type == EXPR_VARIABLE, false);
3547 /* Form the mask expression according to the mask tree list. */
3548 if (wheremask)
3550 wheremaskexpr = gfc_build_array_ref (wheremask, count3, NULL);
3551 if (invert)
3552 wheremaskexpr = fold_build1_loc (input_location, TRUTH_NOT_EXPR,
3553 TREE_TYPE (wheremaskexpr),
3554 wheremaskexpr);
3555 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
3556 wheremaskexpr, tmp,
3557 build_empty_stmt (input_location));
3560 gfc_add_expr_to_block (&body1, tmp);
3562 if (lss == gfc_ss_terminator)
3564 gfc_add_block_to_block (&block, &body1);
3566 /* Increment count1. */
3567 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (count1),
3568 count1, gfc_index_one_node);
3569 gfc_add_modify (&block, count1, tmp);
3571 else
3573 /* Increment count1. */
3574 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
3575 count1, gfc_index_one_node);
3576 gfc_add_modify (&body1, count1, tmp);
3578 /* Increment count3. */
3579 if (count3)
3581 tmp = fold_build2_loc (input_location, PLUS_EXPR,
3582 gfc_array_index_type,
3583 count3, gfc_index_one_node);
3584 gfc_add_modify (&body1, count3, tmp);
3587 /* Generate the copying loops. */
3588 gfc_trans_scalarizing_loops (&loop, &body1);
3590 gfc_add_block_to_block (&block, &loop.pre);
3591 gfc_add_block_to_block (&block, &loop.post);
3593 gfc_cleanup_loop (&loop);
3594 /* TODO: Reuse lss and rss when copying temp->lhs. Need to be careful
3595 as tree nodes in SS may not be valid in different scope. */
3598 tmp = gfc_finish_block (&block);
3599 return tmp;
3603 /* Calculate the size of temporary needed in the assignment inside forall.
3604 LSS and RSS are filled in this function. */
3606 static tree
3607 compute_inner_temp_size (gfc_expr *expr1, gfc_expr *expr2,
3608 stmtblock_t * pblock,
3609 gfc_ss **lss, gfc_ss **rss)
3611 gfc_loopinfo loop;
3612 tree size;
3613 int i;
3614 int save_flag;
3615 tree tmp;
3617 *lss = gfc_walk_expr (expr1);
3618 *rss = NULL;
3620 size = gfc_index_one_node;
3621 if (*lss != gfc_ss_terminator)
3623 gfc_init_loopinfo (&loop);
3625 /* Walk the RHS of the expression. */
3626 *rss = gfc_walk_expr (expr2);
3627 if (*rss == gfc_ss_terminator)
3628 /* The rhs is scalar. Add a ss for the expression. */
3629 *rss = gfc_get_scalar_ss (gfc_ss_terminator, expr2);
3631 /* Associate the SS with the loop. */
3632 gfc_add_ss_to_loop (&loop, *lss);
3633 /* We don't actually need to add the rhs at this point, but it might
3634 make guessing the loop bounds a bit easier. */
3635 gfc_add_ss_to_loop (&loop, *rss);
3637 /* We only want the shape of the expression, not rest of the junk
3638 generated by the scalarizer. */
3639 loop.array_parameter = 1;
3641 /* Calculate the bounds of the scalarization. */
3642 save_flag = gfc_option.rtcheck;
3643 gfc_option.rtcheck &= ~GFC_RTCHECK_BOUNDS;
3644 gfc_conv_ss_startstride (&loop);
3645 gfc_option.rtcheck = save_flag;
3646 gfc_conv_loop_setup (&loop, &expr2->where);
3648 /* Figure out how many elements we need. */
3649 for (i = 0; i < loop.dimen; i++)
3651 tmp = fold_build2_loc (input_location, MINUS_EXPR,
3652 gfc_array_index_type,
3653 gfc_index_one_node, loop.from[i]);
3654 tmp = fold_build2_loc (input_location, PLUS_EXPR,
3655 gfc_array_index_type, tmp, loop.to[i]);
3656 size = fold_build2_loc (input_location, MULT_EXPR,
3657 gfc_array_index_type, size, tmp);
3659 gfc_add_block_to_block (pblock, &loop.pre);
3660 size = gfc_evaluate_now (size, pblock);
3661 gfc_add_block_to_block (pblock, &loop.post);
3663 /* TODO: write a function that cleans up a loopinfo without freeing
3664 the SS chains. Currently a NOP. */
3667 return size;
3671 /* Calculate the overall iterator number of the nested forall construct.
3672 This routine actually calculates the number of times the body of the
3673 nested forall specified by NESTED_FORALL_INFO is executed and multiplies
3674 that by the expression INNER_SIZE. The BLOCK argument specifies the
3675 block in which to calculate the result, and the optional INNER_SIZE_BODY
3676 argument contains any statements that need to executed (inside the loop)
3677 to initialize or calculate INNER_SIZE. */
3679 static tree
3680 compute_overall_iter_number (forall_info *nested_forall_info, tree inner_size,
3681 stmtblock_t *inner_size_body, stmtblock_t *block)
3683 forall_info *forall_tmp = nested_forall_info;
3684 tree tmp, number;
3685 stmtblock_t body;
3687 /* We can eliminate the innermost unconditional loops with constant
3688 array bounds. */
3689 if (INTEGER_CST_P (inner_size))
3691 while (forall_tmp
3692 && !forall_tmp->mask
3693 && INTEGER_CST_P (forall_tmp->size))
3695 inner_size = fold_build2_loc (input_location, MULT_EXPR,
3696 gfc_array_index_type,
3697 inner_size, forall_tmp->size);
3698 forall_tmp = forall_tmp->prev_nest;
3701 /* If there are no loops left, we have our constant result. */
3702 if (!forall_tmp)
3703 return inner_size;
3706 /* Otherwise, create a temporary variable to compute the result. */
3707 number = gfc_create_var (gfc_array_index_type, "num");
3708 gfc_add_modify (block, number, gfc_index_zero_node);
3710 gfc_start_block (&body);
3711 if (inner_size_body)
3712 gfc_add_block_to_block (&body, inner_size_body);
3713 if (forall_tmp)
3714 tmp = fold_build2_loc (input_location, PLUS_EXPR,
3715 gfc_array_index_type, number, inner_size);
3716 else
3717 tmp = inner_size;
3718 gfc_add_modify (&body, number, tmp);
3719 tmp = gfc_finish_block (&body);
3721 /* Generate loops. */
3722 if (forall_tmp != NULL)
3723 tmp = gfc_trans_nested_forall_loop (forall_tmp, tmp, 1);
3725 gfc_add_expr_to_block (block, tmp);
3727 return number;
3731 /* Allocate temporary for forall construct. SIZE is the size of temporary
3732 needed. PTEMP1 is returned for space free. */
3734 static tree
3735 allocate_temp_for_forall_nest_1 (tree type, tree size, stmtblock_t * block,
3736 tree * ptemp1)
3738 tree bytesize;
3739 tree unit;
3740 tree tmp;
3742 unit = fold_convert (gfc_array_index_type, TYPE_SIZE_UNIT (type));
3743 if (!integer_onep (unit))
3744 bytesize = fold_build2_loc (input_location, MULT_EXPR,
3745 gfc_array_index_type, size, unit);
3746 else
3747 bytesize = size;
3749 *ptemp1 = NULL;
3750 tmp = gfc_do_allocate (bytesize, size, ptemp1, block, type);
3752 if (*ptemp1)
3753 tmp = build_fold_indirect_ref_loc (input_location, tmp);
3754 return tmp;
3758 /* Allocate temporary for forall construct according to the information in
3759 nested_forall_info. INNER_SIZE is the size of temporary needed in the
3760 assignment inside forall. PTEMP1 is returned for space free. */
3762 static tree
3763 allocate_temp_for_forall_nest (forall_info * nested_forall_info, tree type,
3764 tree inner_size, stmtblock_t * inner_size_body,
3765 stmtblock_t * block, tree * ptemp1)
3767 tree size;
3769 /* Calculate the total size of temporary needed in forall construct. */
3770 size = compute_overall_iter_number (nested_forall_info, inner_size,
3771 inner_size_body, block);
3773 return allocate_temp_for_forall_nest_1 (type, size, block, ptemp1);
3777 /* Handle assignments inside forall which need temporary.
3779 forall (i=start:end:stride; maskexpr)
3780 e<i> = f<i>
3781 end forall
3782 (where e,f<i> are arbitrary expressions possibly involving i
3783 and there is a dependency between e<i> and f<i>)
3784 Translates to:
3785 masktmp(:) = maskexpr(:)
3787 maskindex = 0;
3788 count1 = 0;
3789 num = 0;
3790 for (i = start; i <= end; i += stride)
3791 num += SIZE (f<i>)
3792 count1 = 0;
3793 ALLOCATE (tmp(num))
3794 for (i = start; i <= end; i += stride)
3796 if (masktmp[maskindex++])
3797 tmp[count1++] = f<i>
3799 maskindex = 0;
3800 count1 = 0;
3801 for (i = start; i <= end; i += stride)
3803 if (masktmp[maskindex++])
3804 e<i> = tmp[count1++]
3806 DEALLOCATE (tmp)
3808 static void
3809 gfc_trans_assign_need_temp (gfc_expr * expr1, gfc_expr * expr2,
3810 tree wheremask, bool invert,
3811 forall_info * nested_forall_info,
3812 stmtblock_t * block)
3814 tree type;
3815 tree inner_size;
3816 gfc_ss *lss, *rss;
3817 tree count, count1;
3818 tree tmp, tmp1;
3819 tree ptemp1;
3820 stmtblock_t inner_size_body;
3822 /* Create vars. count1 is the current iterator number of the nested
3823 forall. */
3824 count1 = gfc_create_var (gfc_array_index_type, "count1");
3826 /* Count is the wheremask index. */
3827 if (wheremask)
3829 count = gfc_create_var (gfc_array_index_type, "count");
3830 gfc_add_modify (block, count, gfc_index_zero_node);
3832 else
3833 count = NULL;
3835 /* Initialize count1. */
3836 gfc_add_modify (block, count1, gfc_index_zero_node);
3838 /* Calculate the size of temporary needed in the assignment. Return loop, lss
3839 and rss which are used in function generate_loop_for_rhs_to_temp(). */
3840 gfc_init_block (&inner_size_body);
3841 inner_size = compute_inner_temp_size (expr1, expr2, &inner_size_body,
3842 &lss, &rss);
3844 /* The type of LHS. Used in function allocate_temp_for_forall_nest */
3845 if (expr1->ts.type == BT_CHARACTER && expr1->ts.u.cl->length)
3847 if (!expr1->ts.u.cl->backend_decl)
3849 gfc_se tse;
3850 gfc_init_se (&tse, NULL);
3851 gfc_conv_expr (&tse, expr1->ts.u.cl->length);
3852 expr1->ts.u.cl->backend_decl = tse.expr;
3854 type = gfc_get_character_type_len (gfc_default_character_kind,
3855 expr1->ts.u.cl->backend_decl);
3857 else
3858 type = gfc_typenode_for_spec (&expr1->ts);
3860 /* Allocate temporary for nested forall construct according to the
3861 information in nested_forall_info and inner_size. */
3862 tmp1 = allocate_temp_for_forall_nest (nested_forall_info, type, inner_size,
3863 &inner_size_body, block, &ptemp1);
3865 /* Generate codes to copy rhs to the temporary . */
3866 tmp = generate_loop_for_rhs_to_temp (expr2, tmp1, count, count1, lss, rss,
3867 wheremask, invert);
3869 /* Generate body and loops according to the information in
3870 nested_forall_info. */
3871 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
3872 gfc_add_expr_to_block (block, tmp);
3874 /* Reset count1. */
3875 gfc_add_modify (block, count1, gfc_index_zero_node);
3877 /* Reset count. */
3878 if (wheremask)
3879 gfc_add_modify (block, count, gfc_index_zero_node);
3881 /* Generate codes to copy the temporary to lhs. */
3882 tmp = generate_loop_for_temp_to_lhs (expr1, tmp1, count, count1,
3883 wheremask, invert);
3885 /* Generate body and loops according to the information in
3886 nested_forall_info. */
3887 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
3888 gfc_add_expr_to_block (block, tmp);
3890 if (ptemp1)
3892 /* Free the temporary. */
3893 tmp = gfc_call_free (ptemp1);
3894 gfc_add_expr_to_block (block, tmp);
3899 /* Translate pointer assignment inside FORALL which need temporary. */
3901 static void
3902 gfc_trans_pointer_assign_need_temp (gfc_expr * expr1, gfc_expr * expr2,
3903 forall_info * nested_forall_info,
3904 stmtblock_t * block)
3906 tree type;
3907 tree inner_size;
3908 gfc_ss *lss, *rss;
3909 gfc_se lse;
3910 gfc_se rse;
3911 gfc_array_info *info;
3912 gfc_loopinfo loop;
3913 tree desc;
3914 tree parm;
3915 tree parmtype;
3916 stmtblock_t body;
3917 tree count;
3918 tree tmp, tmp1, ptemp1;
3920 count = gfc_create_var (gfc_array_index_type, "count");
3921 gfc_add_modify (block, count, gfc_index_zero_node);
3923 inner_size = gfc_index_one_node;
3924 lss = gfc_walk_expr (expr1);
3925 rss = gfc_walk_expr (expr2);
3926 if (lss == gfc_ss_terminator)
3928 type = gfc_typenode_for_spec (&expr1->ts);
3929 type = build_pointer_type (type);
3931 /* Allocate temporary for nested forall construct according to the
3932 information in nested_forall_info and inner_size. */
3933 tmp1 = allocate_temp_for_forall_nest (nested_forall_info, type,
3934 inner_size, NULL, block, &ptemp1);
3935 gfc_start_block (&body);
3936 gfc_init_se (&lse, NULL);
3937 lse.expr = gfc_build_array_ref (tmp1, count, NULL);
3938 gfc_init_se (&rse, NULL);
3939 rse.want_pointer = 1;
3940 gfc_conv_expr (&rse, expr2);
3941 gfc_add_block_to_block (&body, &rse.pre);
3942 gfc_add_modify (&body, lse.expr,
3943 fold_convert (TREE_TYPE (lse.expr), rse.expr));
3944 gfc_add_block_to_block (&body, &rse.post);
3946 /* Increment count. */
3947 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
3948 count, gfc_index_one_node);
3949 gfc_add_modify (&body, count, tmp);
3951 tmp = gfc_finish_block (&body);
3953 /* Generate body and loops according to the information in
3954 nested_forall_info. */
3955 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
3956 gfc_add_expr_to_block (block, tmp);
3958 /* Reset count. */
3959 gfc_add_modify (block, count, gfc_index_zero_node);
3961 gfc_start_block (&body);
3962 gfc_init_se (&lse, NULL);
3963 gfc_init_se (&rse, NULL);
3964 rse.expr = gfc_build_array_ref (tmp1, count, NULL);
3965 lse.want_pointer = 1;
3966 gfc_conv_expr (&lse, expr1);
3967 gfc_add_block_to_block (&body, &lse.pre);
3968 gfc_add_modify (&body, lse.expr, rse.expr);
3969 gfc_add_block_to_block (&body, &lse.post);
3970 /* Increment count. */
3971 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
3972 count, gfc_index_one_node);
3973 gfc_add_modify (&body, count, tmp);
3974 tmp = gfc_finish_block (&body);
3976 /* Generate body and loops according to the information in
3977 nested_forall_info. */
3978 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
3979 gfc_add_expr_to_block (block, tmp);
3981 else
3983 gfc_init_loopinfo (&loop);
3985 /* Associate the SS with the loop. */
3986 gfc_add_ss_to_loop (&loop, rss);
3988 /* Setup the scalarizing loops and bounds. */
3989 gfc_conv_ss_startstride (&loop);
3991 gfc_conv_loop_setup (&loop, &expr2->where);
3993 info = &rss->info->data.array;
3994 desc = info->descriptor;
3996 /* Make a new descriptor. */
3997 parmtype = gfc_get_element_type (TREE_TYPE (desc));
3998 parmtype = gfc_get_array_type_bounds (parmtype, loop.dimen, 0,
3999 loop.from, loop.to, 1,
4000 GFC_ARRAY_UNKNOWN, true);
4002 /* Allocate temporary for nested forall construct. */
4003 tmp1 = allocate_temp_for_forall_nest (nested_forall_info, parmtype,
4004 inner_size, NULL, block, &ptemp1);
4005 gfc_start_block (&body);
4006 gfc_init_se (&lse, NULL);
4007 lse.expr = gfc_build_array_ref (tmp1, count, NULL);
4008 lse.direct_byref = 1;
4009 gfc_conv_expr_descriptor (&lse, expr2);
4011 gfc_add_block_to_block (&body, &lse.pre);
4012 gfc_add_block_to_block (&body, &lse.post);
4014 /* Increment count. */
4015 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
4016 count, gfc_index_one_node);
4017 gfc_add_modify (&body, count, tmp);
4019 tmp = gfc_finish_block (&body);
4021 /* Generate body and loops according to the information in
4022 nested_forall_info. */
4023 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
4024 gfc_add_expr_to_block (block, tmp);
4026 /* Reset count. */
4027 gfc_add_modify (block, count, gfc_index_zero_node);
4029 parm = gfc_build_array_ref (tmp1, count, NULL);
4030 gfc_init_se (&lse, NULL);
4031 gfc_conv_expr_descriptor (&lse, expr1);
4032 gfc_add_modify (&lse.pre, lse.expr, parm);
4033 gfc_start_block (&body);
4034 gfc_add_block_to_block (&body, &lse.pre);
4035 gfc_add_block_to_block (&body, &lse.post);
4037 /* Increment count. */
4038 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
4039 count, gfc_index_one_node);
4040 gfc_add_modify (&body, count, tmp);
4042 tmp = gfc_finish_block (&body);
4044 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
4045 gfc_add_expr_to_block (block, tmp);
4047 /* Free the temporary. */
4048 if (ptemp1)
4050 tmp = gfc_call_free (ptemp1);
4051 gfc_add_expr_to_block (block, tmp);
4056 /* FORALL and WHERE statements are really nasty, especially when you nest
4057 them. All the rhs of a forall assignment must be evaluated before the
4058 actual assignments are performed. Presumably this also applies to all the
4059 assignments in an inner where statement. */
4061 /* Generate code for a FORALL statement. Any temporaries are allocated as a
4062 linear array, relying on the fact that we process in the same order in all
4063 loops.
4065 forall (i=start:end:stride; maskexpr)
4066 e<i> = f<i>
4067 g<i> = h<i>
4068 end forall
4069 (where e,f,g,h<i> are arbitrary expressions possibly involving i)
4070 Translates to:
4071 count = ((end + 1 - start) / stride)
4072 masktmp(:) = maskexpr(:)
4074 maskindex = 0;
4075 for (i = start; i <= end; i += stride)
4077 if (masktmp[maskindex++])
4078 e<i> = f<i>
4080 maskindex = 0;
4081 for (i = start; i <= end; i += stride)
4083 if (masktmp[maskindex++])
4084 g<i> = h<i>
4087 Note that this code only works when there are no dependencies.
4088 Forall loop with array assignments and data dependencies are a real pain,
4089 because the size of the temporary cannot always be determined before the
4090 loop is executed. This problem is compounded by the presence of nested
4091 FORALL constructs.
4094 static tree
4095 gfc_trans_forall_1 (gfc_code * code, forall_info * nested_forall_info)
4097 stmtblock_t pre;
4098 stmtblock_t post;
4099 stmtblock_t block;
4100 stmtblock_t body;
4101 tree *var;
4102 tree *start;
4103 tree *end;
4104 tree *step;
4105 gfc_expr **varexpr;
4106 tree tmp;
4107 tree assign;
4108 tree size;
4109 tree maskindex;
4110 tree mask;
4111 tree pmask;
4112 tree cycle_label = NULL_TREE;
4113 int n;
4114 int nvar;
4115 int need_temp;
4116 gfc_forall_iterator *fa;
4117 gfc_se se;
4118 gfc_code *c;
4119 gfc_saved_var *saved_vars;
4120 iter_info *this_forall;
4121 forall_info *info;
4122 bool need_mask;
4124 /* Do nothing if the mask is false. */
4125 if (code->expr1
4126 && code->expr1->expr_type == EXPR_CONSTANT
4127 && !code->expr1->value.logical)
4128 return build_empty_stmt (input_location);
4130 n = 0;
4131 /* Count the FORALL index number. */
4132 for (fa = code->ext.forall_iterator; fa; fa = fa->next)
4133 n++;
4134 nvar = n;
4136 /* Allocate the space for var, start, end, step, varexpr. */
4137 var = XCNEWVEC (tree, nvar);
4138 start = XCNEWVEC (tree, nvar);
4139 end = XCNEWVEC (tree, nvar);
4140 step = XCNEWVEC (tree, nvar);
4141 varexpr = XCNEWVEC (gfc_expr *, nvar);
4142 saved_vars = XCNEWVEC (gfc_saved_var, nvar);
4144 /* Allocate the space for info. */
4145 info = XCNEW (forall_info);
4147 gfc_start_block (&pre);
4148 gfc_init_block (&post);
4149 gfc_init_block (&block);
4151 n = 0;
4152 for (fa = code->ext.forall_iterator; fa; fa = fa->next)
4154 gfc_symbol *sym = fa->var->symtree->n.sym;
4156 /* Allocate space for this_forall. */
4157 this_forall = XCNEW (iter_info);
4159 /* Create a temporary variable for the FORALL index. */
4160 tmp = gfc_typenode_for_spec (&sym->ts);
4161 var[n] = gfc_create_var (tmp, sym->name);
4162 gfc_shadow_sym (sym, var[n], &saved_vars[n]);
4164 /* Record it in this_forall. */
4165 this_forall->var = var[n];
4167 /* Replace the index symbol's backend_decl with the temporary decl. */
4168 sym->backend_decl = var[n];
4170 /* Work out the start, end and stride for the loop. */
4171 gfc_init_se (&se, NULL);
4172 gfc_conv_expr_val (&se, fa->start);
4173 /* Record it in this_forall. */
4174 this_forall->start = se.expr;
4175 gfc_add_block_to_block (&block, &se.pre);
4176 start[n] = se.expr;
4178 gfc_init_se (&se, NULL);
4179 gfc_conv_expr_val (&se, fa->end);
4180 /* Record it in this_forall. */
4181 this_forall->end = se.expr;
4182 gfc_make_safe_expr (&se);
4183 gfc_add_block_to_block (&block, &se.pre);
4184 end[n] = se.expr;
4186 gfc_init_se (&se, NULL);
4187 gfc_conv_expr_val (&se, fa->stride);
4188 /* Record it in this_forall. */
4189 this_forall->step = se.expr;
4190 gfc_make_safe_expr (&se);
4191 gfc_add_block_to_block (&block, &se.pre);
4192 step[n] = se.expr;
4194 /* Set the NEXT field of this_forall to NULL. */
4195 this_forall->next = NULL;
4196 /* Link this_forall to the info construct. */
4197 if (info->this_loop)
4199 iter_info *iter_tmp = info->this_loop;
4200 while (iter_tmp->next != NULL)
4201 iter_tmp = iter_tmp->next;
4202 iter_tmp->next = this_forall;
4204 else
4205 info->this_loop = this_forall;
4207 n++;
4209 nvar = n;
4211 /* Calculate the size needed for the current forall level. */
4212 size = gfc_index_one_node;
4213 for (n = 0; n < nvar; n++)
4215 /* size = (end + step - start) / step. */
4216 tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (start[n]),
4217 step[n], start[n]);
4218 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (end[n]),
4219 end[n], tmp);
4220 tmp = fold_build2_loc (input_location, FLOOR_DIV_EXPR, TREE_TYPE (tmp),
4221 tmp, step[n]);
4222 tmp = convert (gfc_array_index_type, tmp);
4224 size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
4225 size, tmp);
4228 /* Record the nvar and size of current forall level. */
4229 info->nvar = nvar;
4230 info->size = size;
4232 if (code->expr1)
4234 /* If the mask is .true., consider the FORALL unconditional. */
4235 if (code->expr1->expr_type == EXPR_CONSTANT
4236 && code->expr1->value.logical)
4237 need_mask = false;
4238 else
4239 need_mask = true;
4241 else
4242 need_mask = false;
4244 /* First we need to allocate the mask. */
4245 if (need_mask)
4247 /* As the mask array can be very big, prefer compact boolean types. */
4248 tree mask_type = gfc_get_logical_type (gfc_logical_kinds[0].kind);
4249 mask = allocate_temp_for_forall_nest (nested_forall_info, mask_type,
4250 size, NULL, &block, &pmask);
4251 maskindex = gfc_create_var_np (gfc_array_index_type, "mi");
4253 /* Record them in the info structure. */
4254 info->maskindex = maskindex;
4255 info->mask = mask;
4257 else
4259 /* No mask was specified. */
4260 maskindex = NULL_TREE;
4261 mask = pmask = NULL_TREE;
4264 /* Link the current forall level to nested_forall_info. */
4265 info->prev_nest = nested_forall_info;
4266 nested_forall_info = info;
4268 /* Copy the mask into a temporary variable if required.
4269 For now we assume a mask temporary is needed. */
4270 if (need_mask)
4272 /* As the mask array can be very big, prefer compact boolean types. */
4273 tree mask_type = gfc_get_logical_type (gfc_logical_kinds[0].kind);
4275 gfc_add_modify (&block, maskindex, gfc_index_zero_node);
4277 /* Start of mask assignment loop body. */
4278 gfc_start_block (&body);
4280 /* Evaluate the mask expression. */
4281 gfc_init_se (&se, NULL);
4282 gfc_conv_expr_val (&se, code->expr1);
4283 gfc_add_block_to_block (&body, &se.pre);
4285 /* Store the mask. */
4286 se.expr = convert (mask_type, se.expr);
4288 tmp = gfc_build_array_ref (mask, maskindex, NULL);
4289 gfc_add_modify (&body, tmp, se.expr);
4291 /* Advance to the next mask element. */
4292 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
4293 maskindex, gfc_index_one_node);
4294 gfc_add_modify (&body, maskindex, tmp);
4296 /* Generate the loops. */
4297 tmp = gfc_finish_block (&body);
4298 tmp = gfc_trans_nested_forall_loop (info, tmp, 0);
4299 gfc_add_expr_to_block (&block, tmp);
4302 if (code->op == EXEC_DO_CONCURRENT)
4304 gfc_init_block (&body);
4305 cycle_label = gfc_build_label_decl (NULL_TREE);
4306 code->cycle_label = cycle_label;
4307 tmp = gfc_trans_code (code->block->next);
4308 gfc_add_expr_to_block (&body, tmp);
4310 if (TREE_USED (cycle_label))
4312 tmp = build1_v (LABEL_EXPR, cycle_label);
4313 gfc_add_expr_to_block (&body, tmp);
4316 tmp = gfc_finish_block (&body);
4317 nested_forall_info->do_concurrent = true;
4318 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
4319 gfc_add_expr_to_block (&block, tmp);
4320 goto done;
4323 c = code->block->next;
4325 /* TODO: loop merging in FORALL statements. */
4326 /* Now that we've got a copy of the mask, generate the assignment loops. */
4327 while (c)
4329 switch (c->op)
4331 case EXEC_ASSIGN:
4332 /* A scalar or array assignment. DO the simple check for
4333 lhs to rhs dependencies. These make a temporary for the
4334 rhs and form a second forall block to copy to variable. */
4335 need_temp = check_forall_dependencies(c, &pre, &post);
4337 /* Temporaries due to array assignment data dependencies introduce
4338 no end of problems. */
4339 if (need_temp)
4340 gfc_trans_assign_need_temp (c->expr1, c->expr2, NULL, false,
4341 nested_forall_info, &block);
4342 else
4344 /* Use the normal assignment copying routines. */
4345 assign = gfc_trans_assignment (c->expr1, c->expr2, false, true);
4347 /* Generate body and loops. */
4348 tmp = gfc_trans_nested_forall_loop (nested_forall_info,
4349 assign, 1);
4350 gfc_add_expr_to_block (&block, tmp);
4353 /* Cleanup any temporary symtrees that have been made to deal
4354 with dependencies. */
4355 if (new_symtree)
4356 cleanup_forall_symtrees (c);
4358 break;
4360 case EXEC_WHERE:
4361 /* Translate WHERE or WHERE construct nested in FORALL. */
4362 gfc_trans_where_2 (c, NULL, false, nested_forall_info, &block);
4363 break;
4365 /* Pointer assignment inside FORALL. */
4366 case EXEC_POINTER_ASSIGN:
4367 need_temp = gfc_check_dependency (c->expr1, c->expr2, 0);
4368 if (need_temp)
4369 gfc_trans_pointer_assign_need_temp (c->expr1, c->expr2,
4370 nested_forall_info, &block);
4371 else
4373 /* Use the normal assignment copying routines. */
4374 assign = gfc_trans_pointer_assignment (c->expr1, c->expr2);
4376 /* Generate body and loops. */
4377 tmp = gfc_trans_nested_forall_loop (nested_forall_info,
4378 assign, 1);
4379 gfc_add_expr_to_block (&block, tmp);
4381 break;
4383 case EXEC_FORALL:
4384 tmp = gfc_trans_forall_1 (c, nested_forall_info);
4385 gfc_add_expr_to_block (&block, tmp);
4386 break;
4388 /* Explicit subroutine calls are prevented by the frontend but interface
4389 assignments can legitimately produce them. */
4390 case EXEC_ASSIGN_CALL:
4391 assign = gfc_trans_call (c, true, NULL_TREE, NULL_TREE, false);
4392 tmp = gfc_trans_nested_forall_loop (nested_forall_info, assign, 1);
4393 gfc_add_expr_to_block (&block, tmp);
4394 break;
4396 default:
4397 gcc_unreachable ();
4400 c = c->next;
4403 done:
4404 /* Restore the original index variables. */
4405 for (fa = code->ext.forall_iterator, n = 0; fa; fa = fa->next, n++)
4406 gfc_restore_sym (fa->var->symtree->n.sym, &saved_vars[n]);
4408 /* Free the space for var, start, end, step, varexpr. */
4409 free (var);
4410 free (start);
4411 free (end);
4412 free (step);
4413 free (varexpr);
4414 free (saved_vars);
4416 for (this_forall = info->this_loop; this_forall;)
4418 iter_info *next = this_forall->next;
4419 free (this_forall);
4420 this_forall = next;
4423 /* Free the space for this forall_info. */
4424 free (info);
4426 if (pmask)
4428 /* Free the temporary for the mask. */
4429 tmp = gfc_call_free (pmask);
4430 gfc_add_expr_to_block (&block, tmp);
4432 if (maskindex)
4433 pushdecl (maskindex);
4435 gfc_add_block_to_block (&pre, &block);
4436 gfc_add_block_to_block (&pre, &post);
4438 return gfc_finish_block (&pre);
4442 /* Translate the FORALL statement or construct. */
4444 tree gfc_trans_forall (gfc_code * code)
4446 return gfc_trans_forall_1 (code, NULL);
4450 /* Translate the DO CONCURRENT construct. */
4452 tree gfc_trans_do_concurrent (gfc_code * code)
4454 return gfc_trans_forall_1 (code, NULL);
4458 /* Evaluate the WHERE mask expression, copy its value to a temporary.
4459 If the WHERE construct is nested in FORALL, compute the overall temporary
4460 needed by the WHERE mask expression multiplied by the iterator number of
4461 the nested forall.
4462 ME is the WHERE mask expression.
4463 MASK is the current execution mask upon input, whose sense may or may
4464 not be inverted as specified by the INVERT argument.
4465 CMASK is the updated execution mask on output, or NULL if not required.
4466 PMASK is the pending execution mask on output, or NULL if not required.
4467 BLOCK is the block in which to place the condition evaluation loops. */
4469 static void
4470 gfc_evaluate_where_mask (gfc_expr * me, forall_info * nested_forall_info,
4471 tree mask, bool invert, tree cmask, tree pmask,
4472 tree mask_type, stmtblock_t * block)
4474 tree tmp, tmp1;
4475 gfc_ss *lss, *rss;
4476 gfc_loopinfo loop;
4477 stmtblock_t body, body1;
4478 tree count, cond, mtmp;
4479 gfc_se lse, rse;
4481 gfc_init_loopinfo (&loop);
4483 lss = gfc_walk_expr (me);
4484 rss = gfc_walk_expr (me);
4486 /* Variable to index the temporary. */
4487 count = gfc_create_var (gfc_array_index_type, "count");
4488 /* Initialize count. */
4489 gfc_add_modify (block, count, gfc_index_zero_node);
4491 gfc_start_block (&body);
4493 gfc_init_se (&rse, NULL);
4494 gfc_init_se (&lse, NULL);
4496 if (lss == gfc_ss_terminator)
4498 gfc_init_block (&body1);
4500 else
4502 /* Initialize the loop. */
4503 gfc_init_loopinfo (&loop);
4505 /* We may need LSS to determine the shape of the expression. */
4506 gfc_add_ss_to_loop (&loop, lss);
4507 gfc_add_ss_to_loop (&loop, rss);
4509 gfc_conv_ss_startstride (&loop);
4510 gfc_conv_loop_setup (&loop, &me->where);
4512 gfc_mark_ss_chain_used (rss, 1);
4513 /* Start the loop body. */
4514 gfc_start_scalarized_body (&loop, &body1);
4516 /* Translate the expression. */
4517 gfc_copy_loopinfo_to_se (&rse, &loop);
4518 rse.ss = rss;
4519 gfc_conv_expr (&rse, me);
4522 /* Variable to evaluate mask condition. */
4523 cond = gfc_create_var (mask_type, "cond");
4524 if (mask && (cmask || pmask))
4525 mtmp = gfc_create_var (mask_type, "mask");
4526 else mtmp = NULL_TREE;
4528 gfc_add_block_to_block (&body1, &lse.pre);
4529 gfc_add_block_to_block (&body1, &rse.pre);
4531 gfc_add_modify (&body1, cond, fold_convert (mask_type, rse.expr));
4533 if (mask && (cmask || pmask))
4535 tmp = gfc_build_array_ref (mask, count, NULL);
4536 if (invert)
4537 tmp = fold_build1_loc (input_location, TRUTH_NOT_EXPR, mask_type, tmp);
4538 gfc_add_modify (&body1, mtmp, tmp);
4541 if (cmask)
4543 tmp1 = gfc_build_array_ref (cmask, count, NULL);
4544 tmp = cond;
4545 if (mask)
4546 tmp = fold_build2_loc (input_location, TRUTH_AND_EXPR, mask_type,
4547 mtmp, tmp);
4548 gfc_add_modify (&body1, tmp1, tmp);
4551 if (pmask)
4553 tmp1 = gfc_build_array_ref (pmask, count, NULL);
4554 tmp = fold_build1_loc (input_location, TRUTH_NOT_EXPR, mask_type, cond);
4555 if (mask)
4556 tmp = fold_build2_loc (input_location, TRUTH_AND_EXPR, mask_type, mtmp,
4557 tmp);
4558 gfc_add_modify (&body1, tmp1, tmp);
4561 gfc_add_block_to_block (&body1, &lse.post);
4562 gfc_add_block_to_block (&body1, &rse.post);
4564 if (lss == gfc_ss_terminator)
4566 gfc_add_block_to_block (&body, &body1);
4568 else
4570 /* Increment count. */
4571 tmp1 = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
4572 count, gfc_index_one_node);
4573 gfc_add_modify (&body1, count, tmp1);
4575 /* Generate the copying loops. */
4576 gfc_trans_scalarizing_loops (&loop, &body1);
4578 gfc_add_block_to_block (&body, &loop.pre);
4579 gfc_add_block_to_block (&body, &loop.post);
4581 gfc_cleanup_loop (&loop);
4582 /* TODO: Reuse lss and rss when copying temp->lhs. Need to be careful
4583 as tree nodes in SS may not be valid in different scope. */
4586 tmp1 = gfc_finish_block (&body);
4587 /* If the WHERE construct is inside FORALL, fill the full temporary. */
4588 if (nested_forall_info != NULL)
4589 tmp1 = gfc_trans_nested_forall_loop (nested_forall_info, tmp1, 1);
4591 gfc_add_expr_to_block (block, tmp1);
4595 /* Translate an assignment statement in a WHERE statement or construct
4596 statement. The MASK expression is used to control which elements
4597 of EXPR1 shall be assigned. The sense of MASK is specified by
4598 INVERT. */
4600 static tree
4601 gfc_trans_where_assign (gfc_expr *expr1, gfc_expr *expr2,
4602 tree mask, bool invert,
4603 tree count1, tree count2,
4604 gfc_code *cnext)
4606 gfc_se lse;
4607 gfc_se rse;
4608 gfc_ss *lss;
4609 gfc_ss *lss_section;
4610 gfc_ss *rss;
4612 gfc_loopinfo loop;
4613 tree tmp;
4614 stmtblock_t block;
4615 stmtblock_t body;
4616 tree index, maskexpr;
4618 /* A defined assignment. */
4619 if (cnext && cnext->resolved_sym)
4620 return gfc_trans_call (cnext, true, mask, count1, invert);
4622 #if 0
4623 /* TODO: handle this special case.
4624 Special case a single function returning an array. */
4625 if (expr2->expr_type == EXPR_FUNCTION && expr2->rank > 0)
4627 tmp = gfc_trans_arrayfunc_assign (expr1, expr2);
4628 if (tmp)
4629 return tmp;
4631 #endif
4633 /* Assignment of the form lhs = rhs. */
4634 gfc_start_block (&block);
4636 gfc_init_se (&lse, NULL);
4637 gfc_init_se (&rse, NULL);
4639 /* Walk the lhs. */
4640 lss = gfc_walk_expr (expr1);
4641 rss = NULL;
4643 /* In each where-assign-stmt, the mask-expr and the variable being
4644 defined shall be arrays of the same shape. */
4645 gcc_assert (lss != gfc_ss_terminator);
4647 /* The assignment needs scalarization. */
4648 lss_section = lss;
4650 /* Find a non-scalar SS from the lhs. */
4651 while (lss_section != gfc_ss_terminator
4652 && lss_section->info->type != GFC_SS_SECTION)
4653 lss_section = lss_section->next;
4655 gcc_assert (lss_section != gfc_ss_terminator);
4657 /* Initialize the scalarizer. */
4658 gfc_init_loopinfo (&loop);
4660 /* Walk the rhs. */
4661 rss = gfc_walk_expr (expr2);
4662 if (rss == gfc_ss_terminator)
4664 /* The rhs is scalar. Add a ss for the expression. */
4665 rss = gfc_get_scalar_ss (gfc_ss_terminator, expr2);
4666 rss->info->where = 1;
4669 /* Associate the SS with the loop. */
4670 gfc_add_ss_to_loop (&loop, lss);
4671 gfc_add_ss_to_loop (&loop, rss);
4673 /* Calculate the bounds of the scalarization. */
4674 gfc_conv_ss_startstride (&loop);
4676 /* Resolve any data dependencies in the statement. */
4677 gfc_conv_resolve_dependencies (&loop, lss_section, rss);
4679 /* Setup the scalarizing loops. */
4680 gfc_conv_loop_setup (&loop, &expr2->where);
4682 /* Setup the gfc_se structures. */
4683 gfc_copy_loopinfo_to_se (&lse, &loop);
4684 gfc_copy_loopinfo_to_se (&rse, &loop);
4686 rse.ss = rss;
4687 gfc_mark_ss_chain_used (rss, 1);
4688 if (loop.temp_ss == NULL)
4690 lse.ss = lss;
4691 gfc_mark_ss_chain_used (lss, 1);
4693 else
4695 lse.ss = loop.temp_ss;
4696 gfc_mark_ss_chain_used (lss, 3);
4697 gfc_mark_ss_chain_used (loop.temp_ss, 3);
4700 /* Start the scalarized loop body. */
4701 gfc_start_scalarized_body (&loop, &body);
4703 /* Translate the expression. */
4704 gfc_conv_expr (&rse, expr2);
4705 if (lss != gfc_ss_terminator && loop.temp_ss != NULL)
4706 gfc_conv_tmp_array_ref (&lse);
4707 else
4708 gfc_conv_expr (&lse, expr1);
4710 /* Form the mask expression according to the mask. */
4711 index = count1;
4712 maskexpr = gfc_build_array_ref (mask, index, NULL);
4713 if (invert)
4714 maskexpr = fold_build1_loc (input_location, TRUTH_NOT_EXPR,
4715 TREE_TYPE (maskexpr), maskexpr);
4717 /* Use the scalar assignment as is. */
4718 tmp = gfc_trans_scalar_assign (&lse, &rse, expr1->ts,
4719 false, loop.temp_ss == NULL);
4721 tmp = build3_v (COND_EXPR, maskexpr, tmp, build_empty_stmt (input_location));
4723 gfc_add_expr_to_block (&body, tmp);
4725 if (lss == gfc_ss_terminator)
4727 /* Increment count1. */
4728 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
4729 count1, gfc_index_one_node);
4730 gfc_add_modify (&body, count1, tmp);
4732 /* Use the scalar assignment as is. */
4733 gfc_add_block_to_block (&block, &body);
4735 else
4737 gcc_assert (lse.ss == gfc_ss_terminator
4738 && rse.ss == gfc_ss_terminator);
4740 if (loop.temp_ss != NULL)
4742 /* Increment count1 before finish the main body of a scalarized
4743 expression. */
4744 tmp = fold_build2_loc (input_location, PLUS_EXPR,
4745 gfc_array_index_type, count1, gfc_index_one_node);
4746 gfc_add_modify (&body, count1, tmp);
4747 gfc_trans_scalarized_loop_boundary (&loop, &body);
4749 /* We need to copy the temporary to the actual lhs. */
4750 gfc_init_se (&lse, NULL);
4751 gfc_init_se (&rse, NULL);
4752 gfc_copy_loopinfo_to_se (&lse, &loop);
4753 gfc_copy_loopinfo_to_se (&rse, &loop);
4755 rse.ss = loop.temp_ss;
4756 lse.ss = lss;
4758 gfc_conv_tmp_array_ref (&rse);
4759 gfc_conv_expr (&lse, expr1);
4761 gcc_assert (lse.ss == gfc_ss_terminator
4762 && rse.ss == gfc_ss_terminator);
4764 /* Form the mask expression according to the mask tree list. */
4765 index = count2;
4766 maskexpr = gfc_build_array_ref (mask, index, NULL);
4767 if (invert)
4768 maskexpr = fold_build1_loc (input_location, TRUTH_NOT_EXPR,
4769 TREE_TYPE (maskexpr), maskexpr);
4771 /* Use the scalar assignment as is. */
4772 tmp = gfc_trans_scalar_assign (&lse, &rse, expr1->ts, false, true);
4773 tmp = build3_v (COND_EXPR, maskexpr, tmp,
4774 build_empty_stmt (input_location));
4775 gfc_add_expr_to_block (&body, tmp);
4777 /* Increment count2. */
4778 tmp = fold_build2_loc (input_location, PLUS_EXPR,
4779 gfc_array_index_type, count2,
4780 gfc_index_one_node);
4781 gfc_add_modify (&body, count2, tmp);
4783 else
4785 /* Increment count1. */
4786 tmp = fold_build2_loc (input_location, PLUS_EXPR,
4787 gfc_array_index_type, count1,
4788 gfc_index_one_node);
4789 gfc_add_modify (&body, count1, tmp);
4792 /* Generate the copying loops. */
4793 gfc_trans_scalarizing_loops (&loop, &body);
4795 /* Wrap the whole thing up. */
4796 gfc_add_block_to_block (&block, &loop.pre);
4797 gfc_add_block_to_block (&block, &loop.post);
4798 gfc_cleanup_loop (&loop);
4801 return gfc_finish_block (&block);
4805 /* Translate the WHERE construct or statement.
4806 This function can be called iteratively to translate the nested WHERE
4807 construct or statement.
4808 MASK is the control mask. */
4810 static void
4811 gfc_trans_where_2 (gfc_code * code, tree mask, bool invert,
4812 forall_info * nested_forall_info, stmtblock_t * block)
4814 stmtblock_t inner_size_body;
4815 tree inner_size, size;
4816 gfc_ss *lss, *rss;
4817 tree mask_type;
4818 gfc_expr *expr1;
4819 gfc_expr *expr2;
4820 gfc_code *cblock;
4821 gfc_code *cnext;
4822 tree tmp;
4823 tree cond;
4824 tree count1, count2;
4825 bool need_cmask;
4826 bool need_pmask;
4827 int need_temp;
4828 tree pcmask = NULL_TREE;
4829 tree ppmask = NULL_TREE;
4830 tree cmask = NULL_TREE;
4831 tree pmask = NULL_TREE;
4832 gfc_actual_arglist *arg;
4834 /* the WHERE statement or the WHERE construct statement. */
4835 cblock = code->block;
4837 /* As the mask array can be very big, prefer compact boolean types. */
4838 mask_type = gfc_get_logical_type (gfc_logical_kinds[0].kind);
4840 /* Determine which temporary masks are needed. */
4841 if (!cblock->block)
4843 /* One clause: No ELSEWHEREs. */
4844 need_cmask = (cblock->next != 0);
4845 need_pmask = false;
4847 else if (cblock->block->block)
4849 /* Three or more clauses: Conditional ELSEWHEREs. */
4850 need_cmask = true;
4851 need_pmask = true;
4853 else if (cblock->next)
4855 /* Two clauses, the first non-empty. */
4856 need_cmask = true;
4857 need_pmask = (mask != NULL_TREE
4858 && cblock->block->next != 0);
4860 else if (!cblock->block->next)
4862 /* Two clauses, both empty. */
4863 need_cmask = false;
4864 need_pmask = false;
4866 /* Two clauses, the first empty, the second non-empty. */
4867 else if (mask)
4869 need_cmask = (cblock->block->expr1 != 0);
4870 need_pmask = true;
4872 else
4874 need_cmask = true;
4875 need_pmask = false;
4878 if (need_cmask || need_pmask)
4880 /* Calculate the size of temporary needed by the mask-expr. */
4881 gfc_init_block (&inner_size_body);
4882 inner_size = compute_inner_temp_size (cblock->expr1, cblock->expr1,
4883 &inner_size_body, &lss, &rss);
4885 gfc_free_ss_chain (lss);
4886 gfc_free_ss_chain (rss);
4888 /* Calculate the total size of temporary needed. */
4889 size = compute_overall_iter_number (nested_forall_info, inner_size,
4890 &inner_size_body, block);
4892 /* Check whether the size is negative. */
4893 cond = fold_build2_loc (input_location, LE_EXPR, boolean_type_node, size,
4894 gfc_index_zero_node);
4895 size = fold_build3_loc (input_location, COND_EXPR, gfc_array_index_type,
4896 cond, gfc_index_zero_node, size);
4897 size = gfc_evaluate_now (size, block);
4899 /* Allocate temporary for WHERE mask if needed. */
4900 if (need_cmask)
4901 cmask = allocate_temp_for_forall_nest_1 (mask_type, size, block,
4902 &pcmask);
4904 /* Allocate temporary for !mask if needed. */
4905 if (need_pmask)
4906 pmask = allocate_temp_for_forall_nest_1 (mask_type, size, block,
4907 &ppmask);
4910 while (cblock)
4912 /* Each time around this loop, the where clause is conditional
4913 on the value of mask and invert, which are updated at the
4914 bottom of the loop. */
4916 /* Has mask-expr. */
4917 if (cblock->expr1)
4919 /* Ensure that the WHERE mask will be evaluated exactly once.
4920 If there are no statements in this WHERE/ELSEWHERE clause,
4921 then we don't need to update the control mask (cmask).
4922 If this is the last clause of the WHERE construct, then
4923 we don't need to update the pending control mask (pmask). */
4924 if (mask)
4925 gfc_evaluate_where_mask (cblock->expr1, nested_forall_info,
4926 mask, invert,
4927 cblock->next ? cmask : NULL_TREE,
4928 cblock->block ? pmask : NULL_TREE,
4929 mask_type, block);
4930 else
4931 gfc_evaluate_where_mask (cblock->expr1, nested_forall_info,
4932 NULL_TREE, false,
4933 (cblock->next || cblock->block)
4934 ? cmask : NULL_TREE,
4935 NULL_TREE, mask_type, block);
4937 invert = false;
4939 /* It's a final elsewhere-stmt. No mask-expr is present. */
4940 else
4941 cmask = mask;
4943 /* The body of this where clause are controlled by cmask with
4944 sense specified by invert. */
4946 /* Get the assignment statement of a WHERE statement, or the first
4947 statement in where-body-construct of a WHERE construct. */
4948 cnext = cblock->next;
4949 while (cnext)
4951 switch (cnext->op)
4953 /* WHERE assignment statement. */
4954 case EXEC_ASSIGN_CALL:
4956 arg = cnext->ext.actual;
4957 expr1 = expr2 = NULL;
4958 for (; arg; arg = arg->next)
4960 if (!arg->expr)
4961 continue;
4962 if (expr1 == NULL)
4963 expr1 = arg->expr;
4964 else
4965 expr2 = arg->expr;
4967 goto evaluate;
4969 case EXEC_ASSIGN:
4970 expr1 = cnext->expr1;
4971 expr2 = cnext->expr2;
4972 evaluate:
4973 if (nested_forall_info != NULL)
4975 need_temp = gfc_check_dependency (expr1, expr2, 0);
4976 if (need_temp && cnext->op != EXEC_ASSIGN_CALL)
4977 gfc_trans_assign_need_temp (expr1, expr2,
4978 cmask, invert,
4979 nested_forall_info, block);
4980 else
4982 /* Variables to control maskexpr. */
4983 count1 = gfc_create_var (gfc_array_index_type, "count1");
4984 count2 = gfc_create_var (gfc_array_index_type, "count2");
4985 gfc_add_modify (block, count1, gfc_index_zero_node);
4986 gfc_add_modify (block, count2, gfc_index_zero_node);
4988 tmp = gfc_trans_where_assign (expr1, expr2,
4989 cmask, invert,
4990 count1, count2,
4991 cnext);
4993 tmp = gfc_trans_nested_forall_loop (nested_forall_info,
4994 tmp, 1);
4995 gfc_add_expr_to_block (block, tmp);
4998 else
5000 /* Variables to control maskexpr. */
5001 count1 = gfc_create_var (gfc_array_index_type, "count1");
5002 count2 = gfc_create_var (gfc_array_index_type, "count2");
5003 gfc_add_modify (block, count1, gfc_index_zero_node);
5004 gfc_add_modify (block, count2, gfc_index_zero_node);
5006 tmp = gfc_trans_where_assign (expr1, expr2,
5007 cmask, invert,
5008 count1, count2,
5009 cnext);
5010 gfc_add_expr_to_block (block, tmp);
5013 break;
5015 /* WHERE or WHERE construct is part of a where-body-construct. */
5016 case EXEC_WHERE:
5017 gfc_trans_where_2 (cnext, cmask, invert,
5018 nested_forall_info, block);
5019 break;
5021 default:
5022 gcc_unreachable ();
5025 /* The next statement within the same where-body-construct. */
5026 cnext = cnext->next;
5028 /* The next masked-elsewhere-stmt, elsewhere-stmt, or end-where-stmt. */
5029 cblock = cblock->block;
5030 if (mask == NULL_TREE)
5032 /* If we're the initial WHERE, we can simply invert the sense
5033 of the current mask to obtain the "mask" for the remaining
5034 ELSEWHEREs. */
5035 invert = true;
5036 mask = cmask;
5038 else
5040 /* Otherwise, for nested WHERE's we need to use the pending mask. */
5041 invert = false;
5042 mask = pmask;
5046 /* If we allocated a pending mask array, deallocate it now. */
5047 if (ppmask)
5049 tmp = gfc_call_free (ppmask);
5050 gfc_add_expr_to_block (block, tmp);
5053 /* If we allocated a current mask array, deallocate it now. */
5054 if (pcmask)
5056 tmp = gfc_call_free (pcmask);
5057 gfc_add_expr_to_block (block, tmp);
5061 /* Translate a simple WHERE construct or statement without dependencies.
5062 CBLOCK is the "then" clause of the WHERE statement, where CBLOCK->EXPR
5063 is the mask condition, and EBLOCK if non-NULL is the "else" clause.
5064 Currently both CBLOCK and EBLOCK are restricted to single assignments. */
5066 static tree
5067 gfc_trans_where_3 (gfc_code * cblock, gfc_code * eblock)
5069 stmtblock_t block, body;
5070 gfc_expr *cond, *tdst, *tsrc, *edst, *esrc;
5071 tree tmp, cexpr, tstmt, estmt;
5072 gfc_ss *css, *tdss, *tsss;
5073 gfc_se cse, tdse, tsse, edse, esse;
5074 gfc_loopinfo loop;
5075 gfc_ss *edss = 0;
5076 gfc_ss *esss = 0;
5077 bool maybe_workshare = false;
5079 /* Allow the scalarizer to workshare simple where loops. */
5080 if ((ompws_flags & (OMPWS_WORKSHARE_FLAG | OMPWS_SCALARIZER_BODY))
5081 == OMPWS_WORKSHARE_FLAG)
5083 maybe_workshare = true;
5084 ompws_flags |= OMPWS_SCALARIZER_WS | OMPWS_SCALARIZER_BODY;
5087 cond = cblock->expr1;
5088 tdst = cblock->next->expr1;
5089 tsrc = cblock->next->expr2;
5090 edst = eblock ? eblock->next->expr1 : NULL;
5091 esrc = eblock ? eblock->next->expr2 : NULL;
5093 gfc_start_block (&block);
5094 gfc_init_loopinfo (&loop);
5096 /* Handle the condition. */
5097 gfc_init_se (&cse, NULL);
5098 css = gfc_walk_expr (cond);
5099 gfc_add_ss_to_loop (&loop, css);
5101 /* Handle the then-clause. */
5102 gfc_init_se (&tdse, NULL);
5103 gfc_init_se (&tsse, NULL);
5104 tdss = gfc_walk_expr (tdst);
5105 tsss = gfc_walk_expr (tsrc);
5106 if (tsss == gfc_ss_terminator)
5108 tsss = gfc_get_scalar_ss (gfc_ss_terminator, tsrc);
5109 tsss->info->where = 1;
5111 gfc_add_ss_to_loop (&loop, tdss);
5112 gfc_add_ss_to_loop (&loop, tsss);
5114 if (eblock)
5116 /* Handle the else clause. */
5117 gfc_init_se (&edse, NULL);
5118 gfc_init_se (&esse, NULL);
5119 edss = gfc_walk_expr (edst);
5120 esss = gfc_walk_expr (esrc);
5121 if (esss == gfc_ss_terminator)
5123 esss = gfc_get_scalar_ss (gfc_ss_terminator, esrc);
5124 esss->info->where = 1;
5126 gfc_add_ss_to_loop (&loop, edss);
5127 gfc_add_ss_to_loop (&loop, esss);
5130 gfc_conv_ss_startstride (&loop);
5131 gfc_conv_loop_setup (&loop, &tdst->where);
5133 gfc_mark_ss_chain_used (css, 1);
5134 gfc_mark_ss_chain_used (tdss, 1);
5135 gfc_mark_ss_chain_used (tsss, 1);
5136 if (eblock)
5138 gfc_mark_ss_chain_used (edss, 1);
5139 gfc_mark_ss_chain_used (esss, 1);
5142 gfc_start_scalarized_body (&loop, &body);
5144 gfc_copy_loopinfo_to_se (&cse, &loop);
5145 gfc_copy_loopinfo_to_se (&tdse, &loop);
5146 gfc_copy_loopinfo_to_se (&tsse, &loop);
5147 cse.ss = css;
5148 tdse.ss = tdss;
5149 tsse.ss = tsss;
5150 if (eblock)
5152 gfc_copy_loopinfo_to_se (&edse, &loop);
5153 gfc_copy_loopinfo_to_se (&esse, &loop);
5154 edse.ss = edss;
5155 esse.ss = esss;
5158 gfc_conv_expr (&cse, cond);
5159 gfc_add_block_to_block (&body, &cse.pre);
5160 cexpr = cse.expr;
5162 gfc_conv_expr (&tsse, tsrc);
5163 if (tdss != gfc_ss_terminator && loop.temp_ss != NULL)
5164 gfc_conv_tmp_array_ref (&tdse);
5165 else
5166 gfc_conv_expr (&tdse, tdst);
5168 if (eblock)
5170 gfc_conv_expr (&esse, esrc);
5171 if (edss != gfc_ss_terminator && loop.temp_ss != NULL)
5172 gfc_conv_tmp_array_ref (&edse);
5173 else
5174 gfc_conv_expr (&edse, edst);
5177 tstmt = gfc_trans_scalar_assign (&tdse, &tsse, tdst->ts, false, true);
5178 estmt = eblock ? gfc_trans_scalar_assign (&edse, &esse, edst->ts,
5179 false, true)
5180 : build_empty_stmt (input_location);
5181 tmp = build3_v (COND_EXPR, cexpr, tstmt, estmt);
5182 gfc_add_expr_to_block (&body, tmp);
5183 gfc_add_block_to_block (&body, &cse.post);
5185 if (maybe_workshare)
5186 ompws_flags &= ~OMPWS_SCALARIZER_BODY;
5187 gfc_trans_scalarizing_loops (&loop, &body);
5188 gfc_add_block_to_block (&block, &loop.pre);
5189 gfc_add_block_to_block (&block, &loop.post);
5190 gfc_cleanup_loop (&loop);
5192 return gfc_finish_block (&block);
5195 /* As the WHERE or WHERE construct statement can be nested, we call
5196 gfc_trans_where_2 to do the translation, and pass the initial
5197 NULL values for both the control mask and the pending control mask. */
5199 tree
5200 gfc_trans_where (gfc_code * code)
5202 stmtblock_t block;
5203 gfc_code *cblock;
5204 gfc_code *eblock;
5206 cblock = code->block;
5207 if (cblock->next
5208 && cblock->next->op == EXEC_ASSIGN
5209 && !cblock->next->next)
5211 eblock = cblock->block;
5212 if (!eblock)
5214 /* A simple "WHERE (cond) x = y" statement or block is
5215 dependence free if cond is not dependent upon writing x,
5216 and the source y is unaffected by the destination x. */
5217 if (!gfc_check_dependency (cblock->next->expr1,
5218 cblock->expr1, 0)
5219 && !gfc_check_dependency (cblock->next->expr1,
5220 cblock->next->expr2, 0))
5221 return gfc_trans_where_3 (cblock, NULL);
5223 else if (!eblock->expr1
5224 && !eblock->block
5225 && eblock->next
5226 && eblock->next->op == EXEC_ASSIGN
5227 && !eblock->next->next)
5229 /* A simple "WHERE (cond) x1 = y1 ELSEWHERE x2 = y2 ENDWHERE"
5230 block is dependence free if cond is not dependent on writes
5231 to x1 and x2, y1 is not dependent on writes to x2, and y2
5232 is not dependent on writes to x1, and both y's are not
5233 dependent upon their own x's. In addition to this, the
5234 final two dependency checks below exclude all but the same
5235 array reference if the where and elswhere destinations
5236 are the same. In short, this is VERY conservative and this
5237 is needed because the two loops, required by the standard
5238 are coalesced in gfc_trans_where_3. */
5239 if (!gfc_check_dependency (cblock->next->expr1,
5240 cblock->expr1, 0)
5241 && !gfc_check_dependency (eblock->next->expr1,
5242 cblock->expr1, 0)
5243 && !gfc_check_dependency (cblock->next->expr1,
5244 eblock->next->expr2, 1)
5245 && !gfc_check_dependency (eblock->next->expr1,
5246 cblock->next->expr2, 1)
5247 && !gfc_check_dependency (cblock->next->expr1,
5248 cblock->next->expr2, 1)
5249 && !gfc_check_dependency (eblock->next->expr1,
5250 eblock->next->expr2, 1)
5251 && !gfc_check_dependency (cblock->next->expr1,
5252 eblock->next->expr1, 0)
5253 && !gfc_check_dependency (eblock->next->expr1,
5254 cblock->next->expr1, 0))
5255 return gfc_trans_where_3 (cblock, eblock);
5259 gfc_start_block (&block);
5261 gfc_trans_where_2 (code, NULL, false, NULL, &block);
5263 return gfc_finish_block (&block);
5267 /* CYCLE a DO loop. The label decl has already been created by
5268 gfc_trans_do(), it's in TREE_PURPOSE (backend_decl) of the gfc_code
5269 node at the head of the loop. We must mark the label as used. */
5271 tree
5272 gfc_trans_cycle (gfc_code * code)
5274 tree cycle_label;
5276 cycle_label = code->ext.which_construct->cycle_label;
5277 gcc_assert (cycle_label);
5279 TREE_USED (cycle_label) = 1;
5280 return build1_v (GOTO_EXPR, cycle_label);
5284 /* EXIT a DO loop. Similar to CYCLE, but now the label is in
5285 TREE_VALUE (backend_decl) of the gfc_code node at the head of the
5286 loop. */
5288 tree
5289 gfc_trans_exit (gfc_code * code)
5291 tree exit_label;
5293 exit_label = code->ext.which_construct->exit_label;
5294 gcc_assert (exit_label);
5296 TREE_USED (exit_label) = 1;
5297 return build1_v (GOTO_EXPR, exit_label);
5301 /* Translate the ALLOCATE statement. */
5303 tree
5304 gfc_trans_allocate (gfc_code * code)
5306 gfc_alloc *al;
5307 gfc_expr *expr, *e3rhs = NULL;
5308 gfc_se se, se_sz;
5309 tree tmp;
5310 tree parm;
5311 tree stat;
5312 tree errmsg;
5313 tree errlen;
5314 tree label_errmsg;
5315 tree label_finish;
5316 tree memsz;
5317 tree al_vptr, al_len;
5318 /* If an expr3 is present, then store the tree for accessing its
5319 _vptr, and _len components in the variables, respectively. The
5320 element size, i.e. _vptr%size, is stored in expr3_esize. Any of
5321 the trees may be the NULL_TREE indicating that this is not
5322 available for expr3's type. */
5323 tree expr3, expr3_vptr, expr3_len, expr3_esize;
5324 /* Classify what expr3 stores. */
5325 enum { E3_UNSET = 0, E3_SOURCE, E3_MOLD, E3_DESC } e3_is;
5326 stmtblock_t block;
5327 stmtblock_t post;
5328 tree nelems;
5329 bool upoly_expr, tmp_expr3_len_flag = false, al_len_needs_set;
5330 gfc_symtree *newsym = NULL;
5332 if (!code->ext.alloc.list)
5333 return NULL_TREE;
5335 stat = tmp = memsz = al_vptr = al_len = NULL_TREE;
5336 expr3 = expr3_vptr = expr3_len = expr3_esize = NULL_TREE;
5337 label_errmsg = label_finish = errmsg = errlen = NULL_TREE;
5338 e3_is = E3_UNSET;
5340 gfc_init_block (&block);
5341 gfc_init_block (&post);
5343 /* STAT= (and maybe ERRMSG=) is present. */
5344 if (code->expr1)
5346 /* STAT=. */
5347 tree gfc_int4_type_node = gfc_get_int_type (4);
5348 stat = gfc_create_var (gfc_int4_type_node, "stat");
5350 /* ERRMSG= only makes sense with STAT=. */
5351 if (code->expr2)
5353 gfc_init_se (&se, NULL);
5354 se.want_pointer = 1;
5355 gfc_conv_expr_lhs (&se, code->expr2);
5356 errmsg = se.expr;
5357 errlen = se.string_length;
5359 else
5361 errmsg = null_pointer_node;
5362 errlen = build_int_cst (gfc_charlen_type_node, 0);
5365 /* GOTO destinations. */
5366 label_errmsg = gfc_build_label_decl (NULL_TREE);
5367 label_finish = gfc_build_label_decl (NULL_TREE);
5368 TREE_USED (label_finish) = 0;
5371 /* When an expr3 is present evaluate it only once. The standards prevent a
5372 dependency of expr3 on the objects in the allocate list. An expr3 can
5373 be pre-evaluated in all cases. One just has to make sure, to use the
5374 correct way, i.e., to get the descriptor or to get a reference
5375 expression. */
5376 if (code->expr3)
5378 bool vtab_needed = false, temp_var_needed = false,
5379 is_coarray = gfc_is_coarray (code->expr3);
5381 /* Figure whether we need the vtab from expr3. */
5382 for (al = code->ext.alloc.list; !vtab_needed && al != NULL;
5383 al = al->next)
5384 vtab_needed = (al->expr->ts.type == BT_CLASS);
5386 gfc_init_se (&se, NULL);
5387 /* When expr3 is a variable, i.e., a very simple expression,
5388 then convert it once here. */
5389 if (code->expr3->expr_type == EXPR_VARIABLE
5390 || code->expr3->expr_type == EXPR_ARRAY
5391 || code->expr3->expr_type == EXPR_CONSTANT)
5393 if (!code->expr3->mold
5394 || code->expr3->ts.type == BT_CHARACTER
5395 || vtab_needed
5396 || code->ext.alloc.arr_spec_from_expr3)
5398 /* Convert expr3 to a tree. For all "simple" expression just
5399 get the descriptor or the reference, respectively, depending
5400 on the rank of the expr. */
5401 if (code->ext.alloc.arr_spec_from_expr3 || code->expr3->rank != 0)
5402 gfc_conv_expr_descriptor (&se, code->expr3);
5403 else
5405 gfc_conv_expr_reference (&se, code->expr3);
5407 /* gfc_conv_expr_reference wraps POINTER_PLUS_EXPR in a
5408 NOP_EXPR, which prevents gfortran from getting the vptr
5409 from the source=-expression. Remove the NOP_EXPR and go
5410 with the POINTER_PLUS_EXPR in this case. */
5411 if (code->expr3->ts.type == BT_CLASS
5412 && TREE_CODE (se.expr) == NOP_EXPR
5413 && (TREE_CODE (TREE_OPERAND (se.expr, 0))
5414 == POINTER_PLUS_EXPR
5415 || is_coarray))
5416 se.expr = TREE_OPERAND (se.expr, 0);
5418 /* Create a temp variable only for component refs to prevent
5419 having to go through the full deref-chain each time and to
5420 simplfy computation of array properties. */
5421 temp_var_needed = TREE_CODE (se.expr) == COMPONENT_REF;
5424 else
5426 /* In all other cases evaluate the expr3. */
5427 symbol_attribute attr;
5428 /* Get the descriptor for all arrays, that are not allocatable or
5429 pointer, because the latter are descriptors already.
5430 The exception are function calls returning a class object:
5431 The descriptor is stored in their results _data component, which
5432 is easier to access, when first a temporary variable for the
5433 result is created and the descriptor retrieved from there. */
5434 attr = gfc_expr_attr (code->expr3);
5435 if (code->expr3->rank != 0
5436 && ((!attr.allocatable && !attr.pointer)
5437 || (code->expr3->expr_type == EXPR_FUNCTION
5438 && code->expr3->ts.type != BT_CLASS)))
5439 gfc_conv_expr_descriptor (&se, code->expr3);
5440 else
5441 gfc_conv_expr_reference (&se, code->expr3);
5442 if (code->expr3->ts.type == BT_CLASS)
5443 gfc_conv_class_to_class (&se, code->expr3,
5444 code->expr3->ts,
5445 false, true,
5446 false, false);
5447 temp_var_needed = !VAR_P (se.expr);
5449 gfc_add_block_to_block (&block, &se.pre);
5450 gfc_add_block_to_block (&post, &se.post);
5452 /* Special case when string in expr3 is zero. */
5453 if (code->expr3->ts.type == BT_CHARACTER
5454 && integer_zerop (se.string_length))
5456 gfc_init_se (&se, NULL);
5457 temp_var_needed = false;
5458 expr3_len = integer_zero_node;
5459 e3_is = E3_MOLD;
5461 /* Prevent aliasing, i.e., se.expr may be already a
5462 variable declaration. */
5463 else if (se.expr != NULL_TREE && temp_var_needed)
5465 tree var, desc;
5466 tmp = GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (se.expr)) || is_coarray ?
5467 se.expr
5468 : build_fold_indirect_ref_loc (input_location, se.expr);
5470 /* Get the array descriptor and prepare it to be assigned to the
5471 temporary variable var. For classes the array descriptor is
5472 in the _data component and the object goes into the
5473 GFC_DECL_SAVED_DESCRIPTOR. */
5474 if (code->expr3->ts.type == BT_CLASS
5475 && code->expr3->rank != 0)
5477 /* When an array_ref was in expr3, then the descriptor is the
5478 first operand. */
5479 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (tmp)) || is_coarray)
5481 desc = TREE_OPERAND (tmp, 0);
5483 else
5485 desc = tmp;
5486 tmp = gfc_class_data_get (tmp);
5488 e3_is = E3_DESC;
5490 else
5491 desc = !is_coarray ? se.expr
5492 : TREE_OPERAND (TREE_OPERAND (se.expr, 0), 0);
5493 /* We need a regular (non-UID) symbol here, therefore give a
5494 prefix. */
5495 var = gfc_create_var (TREE_TYPE (tmp), "source");
5496 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (tmp)) || is_coarray)
5498 gfc_allocate_lang_decl (var);
5499 GFC_DECL_SAVED_DESCRIPTOR (var) = desc;
5501 gfc_add_modify_loc (input_location, &block, var, tmp);
5503 /* Deallocate any allocatable components after all the allocations
5504 and assignments of expr3 have been completed. */
5505 if (code->expr3->ts.type == BT_DERIVED
5506 && code->expr3->rank == 0
5507 && code->expr3->ts.u.derived->attr.alloc_comp)
5509 tmp = gfc_deallocate_alloc_comp (code->expr3->ts.u.derived,
5510 var, 0);
5511 gfc_add_expr_to_block (&post, tmp);
5514 expr3 = var;
5515 if (se.string_length)
5516 /* Evaluate it assuming that it also is complicated like expr3. */
5517 expr3_len = gfc_evaluate_now (se.string_length, &block);
5519 else
5521 expr3 = se.expr;
5522 expr3_len = se.string_length;
5524 /* Store what the expr3 is to be used for. */
5525 if (e3_is == E3_UNSET)
5526 e3_is = expr3 != NULL_TREE ?
5527 (code->ext.alloc.arr_spec_from_expr3 ?
5528 E3_DESC
5529 : (code->expr3->mold ? E3_MOLD : E3_SOURCE))
5530 : E3_UNSET;
5532 /* Figure how to get the _vtab entry. This also obtains the tree
5533 expression for accessing the _len component, because only
5534 unlimited polymorphic objects, which are a subcategory of class
5535 types, have a _len component. */
5536 if (code->expr3->ts.type == BT_CLASS)
5538 gfc_expr *rhs;
5539 tmp = expr3 != NULL_TREE && POINTER_TYPE_P (TREE_TYPE (expr3)) ?
5540 build_fold_indirect_ref (expr3): expr3;
5541 /* Polymorphic SOURCE: VPTR must be determined at run time.
5542 expr3 may be a temporary array declaration, therefore check for
5543 GFC_CLASS_TYPE_P before trying to get the _vptr component. */
5544 if (tmp != NULL_TREE
5545 && (e3_is == E3_DESC
5546 || (GFC_CLASS_TYPE_P (TREE_TYPE (tmp))
5547 && (VAR_P (tmp) || !code->expr3->ref))
5548 || (VAR_P (tmp) && DECL_LANG_SPECIFIC (tmp))))
5549 tmp = gfc_class_vptr_get (expr3);
5550 else
5552 rhs = gfc_find_and_cut_at_last_class_ref (code->expr3);
5553 gfc_add_vptr_component (rhs);
5554 gfc_init_se (&se, NULL);
5555 se.want_pointer = 1;
5556 gfc_conv_expr (&se, rhs);
5557 tmp = se.expr;
5558 gfc_free_expr (rhs);
5560 /* Set the element size. */
5561 expr3_esize = gfc_vptr_size_get (tmp);
5562 if (vtab_needed)
5563 expr3_vptr = tmp;
5564 /* Initialize the ref to the _len component. */
5565 if (expr3_len == NULL_TREE && UNLIMITED_POLY (code->expr3))
5567 /* Same like for retrieving the _vptr. */
5568 if (expr3 != NULL_TREE && !code->expr3->ref)
5569 expr3_len = gfc_class_len_get (expr3);
5570 else
5572 rhs = gfc_find_and_cut_at_last_class_ref (code->expr3);
5573 gfc_add_len_component (rhs);
5574 gfc_init_se (&se, NULL);
5575 gfc_conv_expr (&se, rhs);
5576 expr3_len = se.expr;
5577 gfc_free_expr (rhs);
5581 else
5583 /* When the object to allocate is polymorphic type, then it
5584 needs its vtab set correctly, so deduce the required _vtab
5585 and _len from the source expression. */
5586 if (vtab_needed)
5588 /* VPTR is fixed at compile time. */
5589 gfc_symbol *vtab;
5591 vtab = gfc_find_vtab (&code->expr3->ts);
5592 gcc_assert (vtab);
5593 expr3_vptr = gfc_get_symbol_decl (vtab);
5594 expr3_vptr = gfc_build_addr_expr (NULL_TREE,
5595 expr3_vptr);
5597 /* _len component needs to be set, when ts is a character
5598 array. */
5599 if (expr3_len == NULL_TREE
5600 && code->expr3->ts.type == BT_CHARACTER)
5602 if (code->expr3->ts.u.cl
5603 && code->expr3->ts.u.cl->length)
5605 gfc_init_se (&se, NULL);
5606 gfc_conv_expr (&se, code->expr3->ts.u.cl->length);
5607 gfc_add_block_to_block (&block, &se.pre);
5608 expr3_len = gfc_evaluate_now (se.expr, &block);
5610 gcc_assert (expr3_len);
5612 /* For character arrays only the kind's size is needed, because
5613 the array mem_size is _len * (elem_size = kind_size).
5614 For all other get the element size in the normal way. */
5615 if (code->expr3->ts.type == BT_CHARACTER)
5616 expr3_esize = TYPE_SIZE_UNIT (
5617 gfc_get_char_type (code->expr3->ts.kind));
5618 else
5619 expr3_esize = TYPE_SIZE_UNIT (
5620 gfc_typenode_for_spec (&code->expr3->ts));
5622 /* The routine gfc_trans_assignment () already implements all
5623 techniques needed. Unfortunately we may have a temporary
5624 variable for the source= expression here. When that is the
5625 case convert this variable into a temporary gfc_expr of type
5626 EXPR_VARIABLE and used it as rhs for the assignment. The
5627 advantage is, that we get scalarizer support for free,
5628 don't have to take care about scalar to array treatment and
5629 will benefit of every enhancements gfc_trans_assignment ()
5630 gets.
5631 No need to check whether e3_is is E3_UNSET, because that is
5632 done by expr3 != NULL_TREE.
5633 Exclude variables since the following block does not handle
5634 array sections. In any case, there is no harm in sending
5635 variables to gfc_trans_assignment because there is no
5636 evaluation of variables. */
5637 if (code->expr3->expr_type != EXPR_VARIABLE
5638 && e3_is != E3_MOLD && expr3 != NULL_TREE
5639 && DECL_P (expr3) && DECL_ARTIFICIAL (expr3))
5641 /* Build a temporary symtree and symbol. Do not add it to
5642 the current namespace to prevent accidently modifying
5643 a colliding symbol's as. */
5644 newsym = XCNEW (gfc_symtree);
5645 /* The name of the symtree should be unique, because
5646 gfc_create_var () took care about generating the
5647 identifier. */
5648 newsym->name = gfc_get_string (IDENTIFIER_POINTER (
5649 DECL_NAME (expr3)));
5650 newsym->n.sym = gfc_new_symbol (newsym->name, NULL);
5651 /* The backend_decl is known. It is expr3, which is inserted
5652 here. */
5653 newsym->n.sym->backend_decl = expr3;
5654 e3rhs = gfc_get_expr ();
5655 e3rhs->ts = code->expr3->ts;
5656 e3rhs->rank = code->expr3->rank;
5657 e3rhs->symtree = newsym;
5658 /* Mark the symbol referenced or gfc_trans_assignment will
5659 bug. */
5660 newsym->n.sym->attr.referenced = 1;
5661 e3rhs->expr_type = EXPR_VARIABLE;
5662 e3rhs->where = code->expr3->where;
5663 /* Set the symbols type, upto it was BT_UNKNOWN. */
5664 newsym->n.sym->ts = e3rhs->ts;
5665 /* Check whether the expr3 is array valued. */
5666 if (e3rhs->rank)
5668 gfc_array_spec *arr;
5669 arr = gfc_get_array_spec ();
5670 arr->rank = e3rhs->rank;
5671 arr->type = AS_DEFERRED;
5672 /* Set the dimension and pointer attribute for arrays
5673 to be on the safe side. */
5674 newsym->n.sym->attr.dimension = 1;
5675 newsym->n.sym->attr.pointer = 1;
5676 newsym->n.sym->as = arr;
5677 gfc_add_full_array_ref (e3rhs, arr);
5679 else if (POINTER_TYPE_P (TREE_TYPE (expr3)))
5680 newsym->n.sym->attr.pointer = 1;
5681 /* The string length is known to. Set it for char arrays. */
5682 if (e3rhs->ts.type == BT_CHARACTER)
5683 newsym->n.sym->ts.u.cl->backend_decl = expr3_len;
5684 gfc_commit_symbol (newsym->n.sym);
5686 else
5687 e3rhs = gfc_copy_expr (code->expr3);
5689 gcc_assert (expr3_esize);
5690 expr3_esize = fold_convert (sizetype, expr3_esize);
5691 if (e3_is == E3_MOLD)
5692 /* The expr3 is no longer valid after this point. */
5693 expr3 = NULL_TREE;
5695 else if (code->ext.alloc.ts.type != BT_UNKNOWN)
5697 /* Compute the explicit typespec given only once for all objects
5698 to allocate. */
5699 if (code->ext.alloc.ts.type != BT_CHARACTER)
5700 expr3_esize = TYPE_SIZE_UNIT (
5701 gfc_typenode_for_spec (&code->ext.alloc.ts));
5702 else
5704 gfc_expr *sz;
5705 gcc_assert (code->ext.alloc.ts.u.cl->length != NULL);
5706 sz = gfc_copy_expr (code->ext.alloc.ts.u.cl->length);
5707 gfc_init_se (&se_sz, NULL);
5708 gfc_conv_expr (&se_sz, sz);
5709 gfc_free_expr (sz);
5710 tmp = gfc_get_char_type (code->ext.alloc.ts.kind);
5711 tmp = TYPE_SIZE_UNIT (tmp);
5712 tmp = fold_convert (TREE_TYPE (se_sz.expr), tmp);
5713 gfc_add_block_to_block (&block, &se_sz.pre);
5714 expr3_esize = fold_build2_loc (input_location, MULT_EXPR,
5715 TREE_TYPE (se_sz.expr),
5716 tmp, se_sz.expr);
5717 expr3_esize = gfc_evaluate_now (expr3_esize, &block);
5721 /* Loop over all objects to allocate. */
5722 for (al = code->ext.alloc.list; al != NULL; al = al->next)
5724 expr = gfc_copy_expr (al->expr);
5725 /* UNLIMITED_POLY () needs the _data component to be set, when
5726 expr is a unlimited polymorphic object. But the _data component
5727 has not been set yet, so check the derived type's attr for the
5728 unlimited polymorphic flag to be safe. */
5729 upoly_expr = UNLIMITED_POLY (expr)
5730 || (expr->ts.type == BT_DERIVED
5731 && expr->ts.u.derived->attr.unlimited_polymorphic);
5732 gfc_init_se (&se, NULL);
5734 /* For class types prepare the expressions to ref the _vptr
5735 and the _len component. The latter for unlimited polymorphic
5736 types only. */
5737 if (expr->ts.type == BT_CLASS)
5739 gfc_expr *expr_ref_vptr, *expr_ref_len;
5740 gfc_add_data_component (expr);
5741 /* Prep the vptr handle. */
5742 expr_ref_vptr = gfc_copy_expr (al->expr);
5743 gfc_add_vptr_component (expr_ref_vptr);
5744 se.want_pointer = 1;
5745 gfc_conv_expr (&se, expr_ref_vptr);
5746 al_vptr = se.expr;
5747 se.want_pointer = 0;
5748 gfc_free_expr (expr_ref_vptr);
5749 /* Allocated unlimited polymorphic objects always have a _len
5750 component. */
5751 if (upoly_expr)
5753 expr_ref_len = gfc_copy_expr (al->expr);
5754 gfc_add_len_component (expr_ref_len);
5755 gfc_conv_expr (&se, expr_ref_len);
5756 al_len = se.expr;
5757 gfc_free_expr (expr_ref_len);
5759 else
5760 /* In a loop ensure that all loop variable dependent variables
5761 are initialized at the same spot in all execution paths. */
5762 al_len = NULL_TREE;
5764 else
5765 al_vptr = al_len = NULL_TREE;
5767 se.want_pointer = 1;
5768 se.descriptor_only = 1;
5770 gfc_conv_expr (&se, expr);
5771 if (expr->ts.type == BT_CHARACTER && expr->ts.deferred)
5772 /* se.string_length now stores the .string_length variable of expr
5773 needed to allocate character(len=:) arrays. */
5774 al_len = se.string_length;
5776 al_len_needs_set = al_len != NULL_TREE;
5777 /* When allocating an array one can not use much of the
5778 pre-evaluated expr3 expressions, because for most of them the
5779 scalarizer is needed which is not available in the pre-evaluation
5780 step. Therefore gfc_array_allocate () is responsible (and able)
5781 to handle the complete array allocation. Only the element size
5782 needs to be provided, which is done most of the time by the
5783 pre-evaluation step. */
5784 nelems = NULL_TREE;
5785 if (expr3_len && code->expr3->ts.type == BT_CHARACTER)
5786 /* When al is an array, then the element size for each element
5787 in the array is needed, which is the product of the len and
5788 esize for char arrays. */
5789 tmp = fold_build2_loc (input_location, MULT_EXPR,
5790 TREE_TYPE (expr3_esize), expr3_esize,
5791 fold_convert (TREE_TYPE (expr3_esize),
5792 expr3_len));
5793 else
5794 tmp = expr3_esize;
5795 if (!gfc_array_allocate (&se, expr, stat, errmsg, errlen,
5796 label_finish, tmp, &nelems,
5797 e3rhs ? e3rhs : code->expr3,
5798 e3_is == E3_DESC ? expr3 : NULL_TREE,
5799 code->expr3 != NULL && e3_is == E3_DESC
5800 && code->expr3->expr_type == EXPR_ARRAY))
5802 /* A scalar or derived type. First compute the size to
5803 allocate.
5805 expr3_len is set when expr3 is an unlimited polymorphic
5806 object or a deferred length string. */
5807 if (expr3_len != NULL_TREE)
5809 tmp = fold_convert (TREE_TYPE (expr3_esize), expr3_len);
5810 tmp = fold_build2_loc (input_location, MULT_EXPR,
5811 TREE_TYPE (expr3_esize),
5812 expr3_esize, tmp);
5813 if (code->expr3->ts.type != BT_CLASS)
5814 /* expr3 is a deferred length string, i.e., we are
5815 done. */
5816 memsz = tmp;
5817 else
5819 /* For unlimited polymorphic enties build
5820 (len > 0) ? element_size * len : element_size
5821 to compute the number of bytes to allocate.
5822 This allows the allocation of unlimited polymorphic
5823 objects from an expr3 that is also unlimited
5824 polymorphic and stores a _len dependent object,
5825 e.g., a string. */
5826 memsz = fold_build2_loc (input_location, GT_EXPR,
5827 boolean_type_node, expr3_len,
5828 integer_zero_node);
5829 memsz = fold_build3_loc (input_location, COND_EXPR,
5830 TREE_TYPE (expr3_esize),
5831 memsz, tmp, expr3_esize);
5834 else if (expr3_esize != NULL_TREE)
5835 /* Any other object in expr3 just needs element size in
5836 bytes. */
5837 memsz = expr3_esize;
5838 else if ((expr->ts.type == BT_CHARACTER && expr->ts.deferred)
5839 || (upoly_expr
5840 && code->ext.alloc.ts.type == BT_CHARACTER))
5842 /* Allocating deferred length char arrays need the length
5843 to allocate in the alloc_type_spec. But also unlimited
5844 polymorphic objects may be allocated as char arrays.
5845 Both are handled here. */
5846 gfc_init_se (&se_sz, NULL);
5847 gfc_conv_expr (&se_sz, code->ext.alloc.ts.u.cl->length);
5848 gfc_add_block_to_block (&se.pre, &se_sz.pre);
5849 se_sz.expr = gfc_evaluate_now (se_sz.expr, &se.pre);
5850 gfc_add_block_to_block (&se.pre, &se_sz.post);
5851 expr3_len = se_sz.expr;
5852 tmp_expr3_len_flag = true;
5853 tmp = TYPE_SIZE_UNIT (
5854 gfc_get_char_type (code->ext.alloc.ts.kind));
5855 memsz = fold_build2_loc (input_location, MULT_EXPR,
5856 TREE_TYPE (tmp),
5857 fold_convert (TREE_TYPE (tmp),
5858 expr3_len),
5859 tmp);
5861 else if (expr->ts.type == BT_CHARACTER)
5863 /* Compute the number of bytes needed to allocate a fixed
5864 length char array. */
5865 gcc_assert (se.string_length != NULL_TREE);
5866 tmp = TYPE_SIZE_UNIT (gfc_get_char_type (expr->ts.kind));
5867 memsz = fold_build2_loc (input_location, MULT_EXPR,
5868 TREE_TYPE (tmp), tmp,
5869 fold_convert (TREE_TYPE (tmp),
5870 se.string_length));
5872 else if (code->ext.alloc.ts.type != BT_UNKNOWN)
5873 /* Handle all types, where the alloc_type_spec is set. */
5874 memsz = TYPE_SIZE_UNIT (gfc_typenode_for_spec (&code->ext.alloc.ts));
5875 else
5876 /* Handle size computation of the type declared to alloc. */
5877 memsz = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (se.expr)));
5879 /* Allocate - for non-pointers with re-alloc checking. */
5880 if (gfc_expr_attr (expr).allocatable)
5881 gfc_allocate_allocatable (&se.pre, se.expr, memsz, NULL_TREE,
5882 stat, errmsg, errlen, label_finish,
5883 expr);
5884 else
5885 gfc_allocate_using_malloc (&se.pre, se.expr, memsz, stat);
5887 if (al->expr->ts.type == BT_DERIVED
5888 && expr->ts.u.derived->attr.alloc_comp)
5890 tmp = build_fold_indirect_ref_loc (input_location, se.expr);
5891 tmp = gfc_nullify_alloc_comp (expr->ts.u.derived, tmp, 0);
5892 gfc_add_expr_to_block (&se.pre, tmp);
5895 else
5897 if (expr->ts.type == BT_CHARACTER && al_len != NULL_TREE
5898 && expr3_len != NULL_TREE)
5900 /* Arrays need to have a _len set before the array
5901 descriptor is filled. */
5902 gfc_add_modify (&block, al_len,
5903 fold_convert (TREE_TYPE (al_len), expr3_len));
5904 /* Prevent setting the length twice. */
5905 al_len_needs_set = false;
5907 else if (expr->ts.type == BT_CHARACTER && al_len != NULL_TREE
5908 && code->ext.alloc.ts.u.cl->length)
5910 /* Cover the cases where a string length is explicitly
5911 specified by a type spec for deferred length character
5912 arrays or unlimited polymorphic objects without a
5913 source= or mold= expression. */
5914 gfc_init_se (&se_sz, NULL);
5915 gfc_conv_expr (&se_sz, code->ext.alloc.ts.u.cl->length);
5916 gfc_add_block_to_block (&block, &se_sz.pre);
5917 gfc_add_modify (&block, al_len,
5918 fold_convert (TREE_TYPE (al_len),
5919 se_sz.expr));
5920 al_len_needs_set = false;
5924 gfc_add_block_to_block (&block, &se.pre);
5926 /* Error checking -- Note: ERRMSG only makes sense with STAT. */
5927 if (code->expr1)
5929 tmp = build1_v (GOTO_EXPR, label_errmsg);
5930 parm = fold_build2_loc (input_location, NE_EXPR,
5931 boolean_type_node, stat,
5932 build_int_cst (TREE_TYPE (stat), 0));
5933 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
5934 gfc_unlikely (parm, PRED_FORTRAN_FAIL_ALLOC),
5935 tmp, build_empty_stmt (input_location));
5936 gfc_add_expr_to_block (&block, tmp);
5939 /* Set the vptr. */
5940 if (al_vptr != NULL_TREE)
5942 if (expr3_vptr != NULL_TREE)
5943 /* The vtab is already known, so just assign it. */
5944 gfc_add_modify (&block, al_vptr,
5945 fold_convert (TREE_TYPE (al_vptr), expr3_vptr));
5946 else
5948 /* VPTR is fixed at compile time. */
5949 gfc_symbol *vtab;
5950 gfc_typespec *ts;
5952 if (code->expr3)
5953 /* Although expr3 is pre-evaluated above, it may happen,
5954 that for arrays or in mold= cases the pre-evaluation
5955 was not successful. In these rare cases take the vtab
5956 from the typespec of expr3 here. */
5957 ts = &code->expr3->ts;
5958 else if (code->ext.alloc.ts.type == BT_DERIVED || upoly_expr)
5959 /* The alloc_type_spec gives the type to allocate or the
5960 al is unlimited polymorphic, which enforces the use of
5961 an alloc_type_spec that is not necessarily a BT_DERIVED. */
5962 ts = &code->ext.alloc.ts;
5963 else
5964 /* Prepare for setting the vtab as declared. */
5965 ts = &expr->ts;
5967 vtab = gfc_find_vtab (ts);
5968 gcc_assert (vtab);
5969 tmp = gfc_build_addr_expr (NULL_TREE,
5970 gfc_get_symbol_decl (vtab));
5971 gfc_add_modify (&block, al_vptr,
5972 fold_convert (TREE_TYPE (al_vptr), tmp));
5976 /* Add assignment for string length. */
5977 if (al_len != NULL_TREE && al_len_needs_set)
5979 if (expr3_len != NULL_TREE)
5981 gfc_add_modify (&block, al_len,
5982 fold_convert (TREE_TYPE (al_len),
5983 expr3_len));
5984 /* When tmp_expr3_len_flag is set, then expr3_len is
5985 abused to carry the length information from the
5986 alloc_type. Clear it to prevent setting incorrect len
5987 information in future loop iterations. */
5988 if (tmp_expr3_len_flag)
5989 /* No need to reset tmp_expr3_len_flag, because the
5990 presence of an expr3 can not change within in the
5991 loop. */
5992 expr3_len = NULL_TREE;
5994 else if (code->ext.alloc.ts.type == BT_CHARACTER
5995 && code->ext.alloc.ts.u.cl->length)
5997 /* Cover the cases where a string length is explicitly
5998 specified by a type spec for deferred length character
5999 arrays or unlimited polymorphic objects without a
6000 source= or mold= expression. */
6001 if (expr3_esize == NULL_TREE || code->ext.alloc.ts.kind != 1)
6003 gfc_init_se (&se_sz, NULL);
6004 gfc_conv_expr (&se_sz, code->ext.alloc.ts.u.cl->length);
6005 gfc_add_block_to_block (&block, &se_sz.pre);
6006 gfc_add_modify (&block, al_len,
6007 fold_convert (TREE_TYPE (al_len),
6008 se_sz.expr));
6010 else
6011 gfc_add_modify (&block, al_len,
6012 fold_convert (TREE_TYPE (al_len),
6013 expr3_esize));
6015 else
6016 /* No length information needed, because type to allocate
6017 has no length. Set _len to 0. */
6018 gfc_add_modify (&block, al_len,
6019 fold_convert (TREE_TYPE (al_len),
6020 integer_zero_node));
6022 if (code->expr3 && !code->expr3->mold && e3_is != E3_MOLD)
6024 /* Initialization via SOURCE block (or static default initializer).
6025 Classes need some special handling, so catch them first. */
6026 if (expr3 != NULL_TREE
6027 && TREE_CODE (expr3) != POINTER_PLUS_EXPR
6028 && code->expr3->ts.type == BT_CLASS
6029 && (expr->ts.type == BT_CLASS
6030 || expr->ts.type == BT_DERIVED))
6032 /* copy_class_to_class can be used for class arrays, too.
6033 It just needs to be ensured, that the decl_saved_descriptor
6034 has a way to get to the vptr. */
6035 tree to;
6036 to = VAR_P (se.expr) ? se.expr : TREE_OPERAND (se.expr, 0);
6037 tmp = gfc_copy_class_to_class (expr3, to,
6038 nelems, upoly_expr);
6040 else if (al->expr->ts.type == BT_CLASS)
6042 gfc_actual_arglist *actual, *last_arg;
6043 gfc_expr *ppc;
6044 gfc_code *ppc_code;
6045 gfc_ref *ref, *dataref;
6046 gfc_expr *rhs = e3rhs ? e3rhs : gfc_copy_expr (code->expr3);
6048 /* Do a polymorphic deep copy. */
6049 actual = gfc_get_actual_arglist ();
6050 actual->expr = gfc_copy_expr (rhs);
6051 if (rhs->ts.type == BT_CLASS)
6052 gfc_add_data_component (actual->expr);
6053 last_arg = actual->next = gfc_get_actual_arglist ();
6054 last_arg->expr = gfc_copy_expr (al->expr);
6055 last_arg->expr->ts.type = BT_CLASS;
6056 gfc_add_data_component (last_arg->expr);
6058 dataref = NULL;
6059 /* Make sure we go up through the reference chain to
6060 the _data reference, where the arrayspec is found. */
6061 for (ref = last_arg->expr->ref; ref; ref = ref->next)
6062 if (ref->type == REF_COMPONENT
6063 && strcmp (ref->u.c.component->name, "_data") == 0)
6064 dataref = ref;
6066 if (dataref && dataref->u.c.component->as)
6068 gfc_array_spec *as = dataref->u.c.component->as;
6069 gfc_free_ref_list (dataref->next);
6070 dataref->next = NULL;
6071 gfc_add_full_array_ref (last_arg->expr, as);
6072 gfc_resolve_expr (last_arg->expr);
6073 gcc_assert (last_arg->expr->ts.type == BT_CLASS
6074 || last_arg->expr->ts.type == BT_DERIVED);
6075 last_arg->expr->ts.type = BT_CLASS;
6077 if (rhs->ts.type == BT_CLASS)
6079 if (rhs->ref)
6080 ppc = gfc_find_and_cut_at_last_class_ref (rhs);
6081 else
6082 ppc = gfc_copy_expr (rhs);
6083 gfc_add_vptr_component (ppc);
6085 else
6086 ppc = gfc_lval_expr_from_sym (gfc_find_vtab (&rhs->ts));
6087 gfc_add_component_ref (ppc, "_copy");
6089 ppc_code = gfc_get_code (EXEC_CALL);
6090 ppc_code->resolved_sym = ppc->symtree->n.sym;
6091 ppc_code->loc = al->expr->where;
6092 /* Although '_copy' is set to be elemental in class.c, it is
6093 not staying that way. Find out why, sometime.... */
6094 ppc_code->resolved_sym->attr.elemental = 1;
6095 ppc_code->ext.actual = actual;
6096 ppc_code->expr1 = ppc;
6097 /* Since '_copy' is elemental, the scalarizer will take care
6098 of arrays in gfc_trans_call. */
6099 tmp = gfc_trans_call (ppc_code, true, NULL, NULL, false);
6100 /* We need to add the
6101 if (al_len > 0)
6102 al_vptr->copy (expr3_data, al_data, expr3_len, al_len);
6103 else
6104 al_vptr->copy (expr3_data, al_data);
6105 block, because al is unlimited polymorphic or a deferred
6106 length char array, whose copy routine needs the array lengths
6107 as third and fourth arguments. */
6108 if (al_len && UNLIMITED_POLY (code->expr3))
6110 tree stdcopy, extcopy;
6111 /* Add al%_len. */
6112 last_arg->next = gfc_get_actual_arglist ();
6113 last_arg = last_arg->next;
6114 last_arg->expr = gfc_find_and_cut_at_last_class_ref (
6115 al->expr);
6116 gfc_add_len_component (last_arg->expr);
6117 /* Add expr3's length. */
6118 last_arg->next = gfc_get_actual_arglist ();
6119 last_arg = last_arg->next;
6120 if (code->expr3->ts.type == BT_CLASS)
6122 last_arg->expr =
6123 gfc_find_and_cut_at_last_class_ref (code->expr3);
6124 gfc_add_len_component (last_arg->expr);
6126 else if (code->expr3->ts.type == BT_CHARACTER)
6127 last_arg->expr =
6128 gfc_copy_expr (code->expr3->ts.u.cl->length);
6129 else
6130 gcc_unreachable ();
6132 stdcopy = tmp;
6133 extcopy = gfc_trans_call (ppc_code, true, NULL, NULL, false);
6135 tmp = fold_build2_loc (input_location, GT_EXPR,
6136 boolean_type_node, expr3_len,
6137 integer_zero_node);
6138 tmp = fold_build3_loc (input_location, COND_EXPR,
6139 void_type_node, tmp, extcopy, stdcopy);
6141 gfc_free_statements (ppc_code);
6142 if (rhs != e3rhs)
6143 gfc_free_expr (rhs);
6145 else
6147 /* Switch off automatic reallocation since we have just
6148 done the ALLOCATE. */
6149 int realloc_lhs = flag_realloc_lhs;
6150 flag_realloc_lhs = 0;
6151 tmp = gfc_trans_assignment (gfc_expr_to_initialize (expr),
6152 e3rhs, false, false);
6153 flag_realloc_lhs = realloc_lhs;
6155 gfc_add_expr_to_block (&block, tmp);
6157 else if (code->expr3 && code->expr3->mold
6158 && code->expr3->ts.type == BT_CLASS)
6160 /* Since the _vptr has already been assigned to the allocate
6161 object, we can use gfc_copy_class_to_class in its
6162 initialization mode. */
6163 tmp = TREE_OPERAND (se.expr, 0);
6164 tmp = gfc_copy_class_to_class (NULL_TREE, tmp, nelems,
6165 upoly_expr);
6166 gfc_add_expr_to_block (&block, tmp);
6169 gfc_free_expr (expr);
6170 } // for-loop
6172 if (e3rhs)
6174 if (newsym)
6176 gfc_free_symbol (newsym->n.sym);
6177 XDELETE (newsym);
6179 gfc_free_expr (e3rhs);
6181 /* STAT. */
6182 if (code->expr1)
6184 tmp = build1_v (LABEL_EXPR, label_errmsg);
6185 gfc_add_expr_to_block (&block, tmp);
6188 /* ERRMSG - only useful if STAT is present. */
6189 if (code->expr1 && code->expr2)
6191 const char *msg = "Attempt to allocate an allocated object";
6192 tree slen, dlen, errmsg_str;
6193 stmtblock_t errmsg_block;
6195 gfc_init_block (&errmsg_block);
6197 errmsg_str = gfc_create_var (pchar_type_node, "ERRMSG");
6198 gfc_add_modify (&errmsg_block, errmsg_str,
6199 gfc_build_addr_expr (pchar_type_node,
6200 gfc_build_localized_cstring_const (msg)));
6202 slen = build_int_cst (gfc_charlen_type_node, ((int) strlen (msg)));
6203 dlen = gfc_get_expr_charlen (code->expr2);
6204 slen = fold_build2_loc (input_location, MIN_EXPR,
6205 TREE_TYPE (slen), dlen, slen);
6207 gfc_trans_string_copy (&errmsg_block, dlen, errmsg,
6208 code->expr2->ts.kind,
6209 slen, errmsg_str,
6210 gfc_default_character_kind);
6211 dlen = gfc_finish_block (&errmsg_block);
6213 tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
6214 stat, build_int_cst (TREE_TYPE (stat), 0));
6216 tmp = build3_v (COND_EXPR, tmp,
6217 dlen, build_empty_stmt (input_location));
6219 gfc_add_expr_to_block (&block, tmp);
6222 /* STAT block. */
6223 if (code->expr1)
6225 if (TREE_USED (label_finish))
6227 tmp = build1_v (LABEL_EXPR, label_finish);
6228 gfc_add_expr_to_block (&block, tmp);
6231 gfc_init_se (&se, NULL);
6232 gfc_conv_expr_lhs (&se, code->expr1);
6233 tmp = convert (TREE_TYPE (se.expr), stat);
6234 gfc_add_modify (&block, se.expr, tmp);
6237 gfc_add_block_to_block (&block, &se.post);
6238 gfc_add_block_to_block (&block, &post);
6240 return gfc_finish_block (&block);
6244 /* Translate a DEALLOCATE statement. */
6246 tree
6247 gfc_trans_deallocate (gfc_code *code)
6249 gfc_se se;
6250 gfc_alloc *al;
6251 tree apstat, pstat, stat, errmsg, errlen, tmp;
6252 tree label_finish, label_errmsg;
6253 stmtblock_t block;
6255 pstat = apstat = stat = errmsg = errlen = tmp = NULL_TREE;
6256 label_finish = label_errmsg = NULL_TREE;
6258 gfc_start_block (&block);
6260 /* Count the number of failed deallocations. If deallocate() was
6261 called with STAT= , then set STAT to the count. If deallocate
6262 was called with ERRMSG, then set ERRMG to a string. */
6263 if (code->expr1)
6265 tree gfc_int4_type_node = gfc_get_int_type (4);
6267 stat = gfc_create_var (gfc_int4_type_node, "stat");
6268 pstat = gfc_build_addr_expr (NULL_TREE, stat);
6270 /* GOTO destinations. */
6271 label_errmsg = gfc_build_label_decl (NULL_TREE);
6272 label_finish = gfc_build_label_decl (NULL_TREE);
6273 TREE_USED (label_finish) = 0;
6276 /* Set ERRMSG - only needed if STAT is available. */
6277 if (code->expr1 && code->expr2)
6279 gfc_init_se (&se, NULL);
6280 se.want_pointer = 1;
6281 gfc_conv_expr_lhs (&se, code->expr2);
6282 errmsg = se.expr;
6283 errlen = se.string_length;
6286 for (al = code->ext.alloc.list; al != NULL; al = al->next)
6288 gfc_expr *expr = gfc_copy_expr (al->expr);
6289 gcc_assert (expr->expr_type == EXPR_VARIABLE);
6291 if (expr->ts.type == BT_CLASS)
6292 gfc_add_data_component (expr);
6294 gfc_init_se (&se, NULL);
6295 gfc_start_block (&se.pre);
6297 se.want_pointer = 1;
6298 se.descriptor_only = 1;
6299 gfc_conv_expr (&se, expr);
6301 if (expr->rank || gfc_is_coarray (expr))
6303 gfc_ref *ref;
6305 if (gfc_bt_struct (expr->ts.type) && expr->ts.u.derived->attr.alloc_comp
6306 && !gfc_is_finalizable (expr->ts.u.derived, NULL))
6308 gfc_ref *last = NULL;
6310 for (ref = expr->ref; ref; ref = ref->next)
6311 if (ref->type == REF_COMPONENT)
6312 last = ref;
6314 /* Do not deallocate the components of a derived type
6315 ultimate pointer component. */
6316 if (!(last && last->u.c.component->attr.pointer)
6317 && !(!last && expr->symtree->n.sym->attr.pointer))
6319 tmp = gfc_deallocate_alloc_comp (expr->ts.u.derived, se.expr,
6320 expr->rank);
6321 gfc_add_expr_to_block (&se.pre, tmp);
6325 if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (se.expr)))
6327 tmp = gfc_array_deallocate (se.expr, pstat, errmsg, errlen,
6328 label_finish, expr);
6329 gfc_add_expr_to_block (&se.pre, tmp);
6331 else if (TREE_CODE (se.expr) == COMPONENT_REF
6332 && TREE_CODE (TREE_TYPE (se.expr)) == ARRAY_TYPE
6333 && TREE_CODE (TREE_TYPE (TREE_TYPE (se.expr)))
6334 == RECORD_TYPE)
6336 /* class.c(finalize_component) generates these, when a
6337 finalizable entity has a non-allocatable derived type array
6338 component, which has allocatable components. Obtain the
6339 derived type of the array and deallocate the allocatable
6340 components. */
6341 for (ref = expr->ref; ref; ref = ref->next)
6343 if (ref->u.c.component->attr.dimension
6344 && ref->u.c.component->ts.type == BT_DERIVED)
6345 break;
6348 if (ref && ref->u.c.component->ts.u.derived->attr.alloc_comp
6349 && !gfc_is_finalizable (ref->u.c.component->ts.u.derived,
6350 NULL))
6352 tmp = gfc_deallocate_alloc_comp
6353 (ref->u.c.component->ts.u.derived,
6354 se.expr, expr->rank);
6355 gfc_add_expr_to_block (&se.pre, tmp);
6359 if (al->expr->ts.type == BT_CLASS)
6361 gfc_reset_vptr (&se.pre, al->expr);
6362 if (UNLIMITED_POLY (al->expr)
6363 || (al->expr->ts.type == BT_DERIVED
6364 && al->expr->ts.u.derived->attr.unlimited_polymorphic))
6365 /* Clear _len, too. */
6366 gfc_reset_len (&se.pre, al->expr);
6369 else
6371 tmp = gfc_deallocate_scalar_with_status (se.expr, pstat, false,
6372 al->expr, al->expr->ts);
6373 gfc_add_expr_to_block (&se.pre, tmp);
6375 /* Set to zero after deallocation. */
6376 tmp = fold_build2_loc (input_location, MODIFY_EXPR, void_type_node,
6377 se.expr,
6378 build_int_cst (TREE_TYPE (se.expr), 0));
6379 gfc_add_expr_to_block (&se.pre, tmp);
6381 if (al->expr->ts.type == BT_CLASS)
6383 gfc_reset_vptr (&se.pre, al->expr);
6384 if (UNLIMITED_POLY (al->expr)
6385 || (al->expr->ts.type == BT_DERIVED
6386 && al->expr->ts.u.derived->attr.unlimited_polymorphic))
6387 /* Clear _len, too. */
6388 gfc_reset_len (&se.pre, al->expr);
6392 if (code->expr1)
6394 tree cond;
6396 cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, stat,
6397 build_int_cst (TREE_TYPE (stat), 0));
6398 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
6399 gfc_unlikely (cond, PRED_FORTRAN_FAIL_ALLOC),
6400 build1_v (GOTO_EXPR, label_errmsg),
6401 build_empty_stmt (input_location));
6402 gfc_add_expr_to_block (&se.pre, tmp);
6405 tmp = gfc_finish_block (&se.pre);
6406 gfc_add_expr_to_block (&block, tmp);
6407 gfc_free_expr (expr);
6410 if (code->expr1)
6412 tmp = build1_v (LABEL_EXPR, label_errmsg);
6413 gfc_add_expr_to_block (&block, tmp);
6416 /* Set ERRMSG - only needed if STAT is available. */
6417 if (code->expr1 && code->expr2)
6419 const char *msg = "Attempt to deallocate an unallocated object";
6420 stmtblock_t errmsg_block;
6421 tree errmsg_str, slen, dlen, cond;
6423 gfc_init_block (&errmsg_block);
6425 errmsg_str = gfc_create_var (pchar_type_node, "ERRMSG");
6426 gfc_add_modify (&errmsg_block, errmsg_str,
6427 gfc_build_addr_expr (pchar_type_node,
6428 gfc_build_localized_cstring_const (msg)));
6429 slen = build_int_cst (gfc_charlen_type_node, ((int) strlen (msg)));
6430 dlen = gfc_get_expr_charlen (code->expr2);
6432 gfc_trans_string_copy (&errmsg_block, dlen, errmsg, code->expr2->ts.kind,
6433 slen, errmsg_str, gfc_default_character_kind);
6434 tmp = gfc_finish_block (&errmsg_block);
6436 cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, stat,
6437 build_int_cst (TREE_TYPE (stat), 0));
6438 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
6439 gfc_unlikely (cond, PRED_FORTRAN_FAIL_ALLOC), tmp,
6440 build_empty_stmt (input_location));
6442 gfc_add_expr_to_block (&block, tmp);
6445 if (code->expr1 && TREE_USED (label_finish))
6447 tmp = build1_v (LABEL_EXPR, label_finish);
6448 gfc_add_expr_to_block (&block, tmp);
6451 /* Set STAT. */
6452 if (code->expr1)
6454 gfc_init_se (&se, NULL);
6455 gfc_conv_expr_lhs (&se, code->expr1);
6456 tmp = convert (TREE_TYPE (se.expr), stat);
6457 gfc_add_modify (&block, se.expr, tmp);
6460 return gfc_finish_block (&block);
6463 #include "gt-fortran-trans-stmt.h"