Reverting merge from trunk
[official-gcc.git] / gcc / fortran / trans-stmt.c
blob62e690d407c7a1ac2fe33dcb3830567df0430730
1 /* Statement translation -- generate GCC trees from gfc_code.
2 Copyright (C) 2002-2013 Free Software Foundation, Inc.
3 Contributed by Paul Brook <paul@nowt.org>
4 and Steven Bosscher <s.bosscher@student.tudelft.nl>
6 This file is part of GCC.
8 GCC is free software; you can redistribute it and/or modify it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 3, or (at your option) any later
11 version.
13 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 for more details.
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING3. If not see
20 <http://www.gnu.org/licenses/>. */
23 #include "config.h"
24 #include "system.h"
25 #include "coretypes.h"
26 #include "tree.h"
27 #include "gfortran.h"
28 #include "flags.h"
29 #include "trans.h"
30 #include "trans-stmt.h"
31 #include "trans-types.h"
32 #include "trans-array.h"
33 #include "trans-const.h"
34 #include "arith.h"
35 #include "dependency.h"
36 #include "ggc.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 ("An alternate return at %L without a * dummy argument",
542 &code->expr1->where);
543 return gfc_generate_return ();
546 /* Start a new block for this statement. */
547 gfc_init_se (&se, NULL);
548 gfc_start_block (&se.pre);
550 gfc_conv_expr (&se, code->expr1);
552 /* Note that the actually returned expression is a simple value and
553 does not depend on any pointers or such; thus we can clean-up with
554 se.post before returning. */
555 tmp = fold_build2_loc (input_location, MODIFY_EXPR, TREE_TYPE (result),
556 result, fold_convert (TREE_TYPE (result),
557 se.expr));
558 gfc_add_expr_to_block (&se.pre, tmp);
559 gfc_add_block_to_block (&se.pre, &se.post);
561 tmp = gfc_generate_return ();
562 gfc_add_expr_to_block (&se.pre, tmp);
563 return gfc_finish_block (&se.pre);
566 return gfc_generate_return ();
570 /* Translate the PAUSE statement. We have to translate this statement
571 to a runtime library call. */
573 tree
574 gfc_trans_pause (gfc_code * code)
576 tree gfc_int4_type_node = gfc_get_int_type (4);
577 gfc_se se;
578 tree tmp;
580 /* Start a new block for this statement. */
581 gfc_init_se (&se, NULL);
582 gfc_start_block (&se.pre);
585 if (code->expr1 == NULL)
587 tmp = build_int_cst (gfc_int4_type_node, 0);
588 tmp = build_call_expr_loc (input_location,
589 gfor_fndecl_pause_string, 2,
590 build_int_cst (pchar_type_node, 0), tmp);
592 else if (code->expr1->ts.type == BT_INTEGER)
594 gfc_conv_expr (&se, code->expr1);
595 tmp = build_call_expr_loc (input_location,
596 gfor_fndecl_pause_numeric, 1,
597 fold_convert (gfc_int4_type_node, se.expr));
599 else
601 gfc_conv_expr_reference (&se, code->expr1);
602 tmp = build_call_expr_loc (input_location,
603 gfor_fndecl_pause_string, 2,
604 se.expr, se.string_length);
607 gfc_add_expr_to_block (&se.pre, tmp);
609 gfc_add_block_to_block (&se.pre, &se.post);
611 return gfc_finish_block (&se.pre);
615 /* Translate the STOP statement. We have to translate this statement
616 to a runtime library call. */
618 tree
619 gfc_trans_stop (gfc_code *code, bool error_stop)
621 tree gfc_int4_type_node = gfc_get_int_type (4);
622 gfc_se se;
623 tree tmp;
625 /* Start a new block for this statement. */
626 gfc_init_se (&se, NULL);
627 gfc_start_block (&se.pre);
629 if (gfc_option.coarray == GFC_FCOARRAY_LIB && !error_stop)
631 /* Per F2008, 8.5.1 STOP implies a SYNC MEMORY. */
632 tmp = builtin_decl_explicit (BUILT_IN_SYNC_SYNCHRONIZE);
633 tmp = build_call_expr_loc (input_location, tmp, 0);
634 gfc_add_expr_to_block (&se.pre, tmp);
636 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_finalize, 0);
637 gfc_add_expr_to_block (&se.pre, tmp);
640 if (code->expr1 == NULL)
642 tmp = build_int_cst (gfc_int4_type_node, 0);
643 tmp = build_call_expr_loc (input_location,
644 error_stop
645 ? (gfc_option.coarray == GFC_FCOARRAY_LIB
646 ? gfor_fndecl_caf_error_stop_str
647 : gfor_fndecl_error_stop_string)
648 : gfor_fndecl_stop_string,
649 2, build_int_cst (pchar_type_node, 0), tmp);
651 else if (code->expr1->ts.type == BT_INTEGER)
653 gfc_conv_expr (&se, code->expr1);
654 tmp = build_call_expr_loc (input_location,
655 error_stop
656 ? (gfc_option.coarray == GFC_FCOARRAY_LIB
657 ? gfor_fndecl_caf_error_stop
658 : gfor_fndecl_error_stop_numeric)
659 : gfor_fndecl_stop_numeric_f08, 1,
660 fold_convert (gfc_int4_type_node, se.expr));
662 else
664 gfc_conv_expr_reference (&se, code->expr1);
665 tmp = build_call_expr_loc (input_location,
666 error_stop
667 ? (gfc_option.coarray == GFC_FCOARRAY_LIB
668 ? gfor_fndecl_caf_error_stop_str
669 : gfor_fndecl_error_stop_string)
670 : gfor_fndecl_stop_string,
671 2, se.expr, se.string_length);
674 gfc_add_expr_to_block (&se.pre, tmp);
676 gfc_add_block_to_block (&se.pre, &se.post);
678 return gfc_finish_block (&se.pre);
682 tree
683 gfc_trans_lock_unlock (gfc_code *code, gfc_exec_op type ATTRIBUTE_UNUSED)
685 gfc_se se, argse;
686 tree stat = NULL_TREE, lock_acquired = NULL_TREE;
688 /* Short cut: For single images without STAT= or LOCK_ACQUIRED
689 return early. (ERRMSG= is always untouched for -fcoarray=single.) */
690 if (!code->expr2 && !code->expr4 && gfc_option.coarray != GFC_FCOARRAY_LIB)
691 return NULL_TREE;
693 gfc_init_se (&se, NULL);
694 gfc_start_block (&se.pre);
696 if (code->expr2)
698 gcc_assert (code->expr2->expr_type == EXPR_VARIABLE);
699 gfc_init_se (&argse, NULL);
700 gfc_conv_expr_val (&argse, code->expr2);
701 stat = argse.expr;
704 if (code->expr4)
706 gcc_assert (code->expr4->expr_type == EXPR_VARIABLE);
707 gfc_init_se (&argse, NULL);
708 gfc_conv_expr_val (&argse, code->expr4);
709 lock_acquired = argse.expr;
712 if (stat != NULL_TREE)
713 gfc_add_modify (&se.pre, stat, build_int_cst (TREE_TYPE (stat), 0));
715 if (lock_acquired != NULL_TREE)
716 gfc_add_modify (&se.pre, lock_acquired,
717 fold_convert (TREE_TYPE (lock_acquired),
718 boolean_true_node));
720 return gfc_finish_block (&se.pre);
724 tree
725 gfc_trans_sync (gfc_code *code, gfc_exec_op type)
727 gfc_se se, argse;
728 tree tmp;
729 tree images = NULL_TREE, stat = NULL_TREE,
730 errmsg = NULL_TREE, errmsglen = NULL_TREE;
732 /* Short cut: For single images without bound checking or without STAT=,
733 return early. (ERRMSG= is always untouched for -fcoarray=single.) */
734 if (!code->expr2 && !(gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
735 && gfc_option.coarray != GFC_FCOARRAY_LIB)
736 return NULL_TREE;
738 gfc_init_se (&se, NULL);
739 gfc_start_block (&se.pre);
741 if (code->expr1 && code->expr1->rank == 0)
743 gfc_init_se (&argse, NULL);
744 gfc_conv_expr_val (&argse, code->expr1);
745 images = argse.expr;
748 if (code->expr2)
750 gcc_assert (code->expr2->expr_type == EXPR_VARIABLE);
751 gfc_init_se (&argse, NULL);
752 gfc_conv_expr_val (&argse, code->expr2);
753 stat = argse.expr;
755 else
756 stat = null_pointer_node;
758 if (code->expr3 && gfc_option.coarray == GFC_FCOARRAY_LIB
759 && type != EXEC_SYNC_MEMORY)
761 gcc_assert (code->expr3->expr_type == EXPR_VARIABLE);
762 gfc_init_se (&argse, NULL);
763 gfc_conv_expr (&argse, code->expr3);
764 gfc_conv_string_parameter (&argse);
765 errmsg = gfc_build_addr_expr (NULL, argse.expr);
766 errmsglen = argse.string_length;
768 else if (gfc_option.coarray == GFC_FCOARRAY_LIB && type != EXEC_SYNC_MEMORY)
770 errmsg = null_pointer_node;
771 errmsglen = build_int_cst (integer_type_node, 0);
774 /* Check SYNC IMAGES(imageset) for valid image index.
775 FIXME: Add a check for image-set arrays. */
776 if (code->expr1 && (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
777 && code->expr1->rank == 0)
779 tree cond;
780 if (gfc_option.coarray != GFC_FCOARRAY_LIB)
781 cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
782 images, build_int_cst (TREE_TYPE (images), 1));
783 else
785 tree cond2;
786 cond = fold_build2_loc (input_location, GT_EXPR, boolean_type_node,
787 images, gfort_gvar_caf_num_images);
788 cond2 = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
789 images,
790 build_int_cst (TREE_TYPE (images), 1));
791 cond = fold_build2_loc (input_location, TRUTH_OR_EXPR,
792 boolean_type_node, cond, cond2);
794 gfc_trans_runtime_check (true, false, cond, &se.pre,
795 &code->expr1->where, "Invalid image number "
796 "%d in SYNC IMAGES",
797 fold_convert (integer_type_node, images));
800 /* Per F2008, 8.5.1, a SYNC MEMORY is implied by calling the
801 image control statements SYNC IMAGES and SYNC ALL. */
802 if (gfc_option.coarray == GFC_FCOARRAY_LIB)
804 tmp = builtin_decl_explicit (BUILT_IN_SYNC_SYNCHRONIZE);
805 tmp = build_call_expr_loc (input_location, tmp, 0);
806 gfc_add_expr_to_block (&se.pre, tmp);
809 if (gfc_option.coarray != GFC_FCOARRAY_LIB || type == EXEC_SYNC_MEMORY)
811 /* Set STAT to zero. */
812 if (code->expr2)
813 gfc_add_modify (&se.pre, stat, build_int_cst (TREE_TYPE (stat), 0));
815 else if (type == EXEC_SYNC_ALL)
817 /* SYNC ALL => stat == null_pointer_node
818 SYNC ALL(stat=s) => stat has an integer type
820 If "stat" has the wrong integer type, use a temp variable of
821 the right type and later cast the result back into "stat". */
822 if (stat == null_pointer_node || TREE_TYPE (stat) == integer_type_node)
824 if (TREE_TYPE (stat) == integer_type_node)
825 stat = gfc_build_addr_expr (NULL, stat);
827 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sync_all,
828 3, stat, errmsg, errmsglen);
829 gfc_add_expr_to_block (&se.pre, tmp);
831 else
833 tree tmp_stat = gfc_create_var (integer_type_node, "stat");
835 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sync_all,
836 3, gfc_build_addr_expr (NULL, tmp_stat),
837 errmsg, errmsglen);
838 gfc_add_expr_to_block (&se.pre, tmp);
840 gfc_add_modify (&se.pre, stat,
841 fold_convert (TREE_TYPE (stat), tmp_stat));
844 else
846 tree len;
848 gcc_assert (type == EXEC_SYNC_IMAGES);
850 if (!code->expr1)
852 len = build_int_cst (integer_type_node, -1);
853 images = null_pointer_node;
855 else if (code->expr1->rank == 0)
857 len = build_int_cst (integer_type_node, 1);
858 images = gfc_build_addr_expr (NULL_TREE, images);
860 else
862 /* FIXME. */
863 if (code->expr1->ts.kind != gfc_c_int_kind)
864 gfc_fatal_error ("Sorry, only support for integer kind %d "
865 "implemented for image-set at %L",
866 gfc_c_int_kind, &code->expr1->where);
868 gfc_conv_array_parameter (&se, code->expr1, true, NULL, NULL, &len);
869 images = se.expr;
871 tmp = gfc_typenode_for_spec (&code->expr1->ts);
872 if (GFC_ARRAY_TYPE_P (tmp) || GFC_DESCRIPTOR_TYPE_P (tmp))
873 tmp = gfc_get_element_type (tmp);
875 len = fold_build2_loc (input_location, TRUNC_DIV_EXPR,
876 TREE_TYPE (len), len,
877 fold_convert (TREE_TYPE (len),
878 TYPE_SIZE_UNIT (tmp)));
879 len = fold_convert (integer_type_node, len);
882 /* SYNC IMAGES(imgs) => stat == null_pointer_node
883 SYNC IMAGES(imgs,stat=s) => stat has an integer type
885 If "stat" has the wrong integer type, use a temp variable of
886 the right type and later cast the result back into "stat". */
887 if (stat == null_pointer_node || TREE_TYPE (stat) == integer_type_node)
889 if (TREE_TYPE (stat) == integer_type_node)
890 stat = gfc_build_addr_expr (NULL, stat);
892 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sync_images,
893 5, fold_convert (integer_type_node, len),
894 images, stat, errmsg, errmsglen);
895 gfc_add_expr_to_block (&se.pre, tmp);
897 else
899 tree tmp_stat = gfc_create_var (integer_type_node, "stat");
901 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sync_images,
902 5, fold_convert (integer_type_node, len),
903 images, gfc_build_addr_expr (NULL, tmp_stat),
904 errmsg, errmsglen);
905 gfc_add_expr_to_block (&se.pre, tmp);
907 gfc_add_modify (&se.pre, stat,
908 fold_convert (TREE_TYPE (stat), tmp_stat));
912 return gfc_finish_block (&se.pre);
916 /* Generate GENERIC for the IF construct. This function also deals with
917 the simple IF statement, because the front end translates the IF
918 statement into an IF construct.
920 We translate:
922 IF (cond) THEN
923 then_clause
924 ELSEIF (cond2)
925 elseif_clause
926 ELSE
927 else_clause
928 ENDIF
930 into:
932 pre_cond_s;
933 if (cond_s)
935 then_clause;
937 else
939 pre_cond_s
940 if (cond_s)
942 elseif_clause
944 else
946 else_clause;
950 where COND_S is the simplified version of the predicate. PRE_COND_S
951 are the pre side-effects produced by the translation of the
952 conditional.
953 We need to build the chain recursively otherwise we run into
954 problems with folding incomplete statements. */
956 static tree
957 gfc_trans_if_1 (gfc_code * code)
959 gfc_se if_se;
960 tree stmt, elsestmt;
961 locus saved_loc;
962 location_t loc;
964 /* Check for an unconditional ELSE clause. */
965 if (!code->expr1)
966 return gfc_trans_code (code->next);
968 /* Initialize a statement builder for each block. Puts in NULL_TREEs. */
969 gfc_init_se (&if_se, NULL);
970 gfc_start_block (&if_se.pre);
972 /* Calculate the IF condition expression. */
973 if (code->expr1->where.lb)
975 gfc_save_backend_locus (&saved_loc);
976 gfc_set_backend_locus (&code->expr1->where);
979 gfc_conv_expr_val (&if_se, code->expr1);
981 if (code->expr1->where.lb)
982 gfc_restore_backend_locus (&saved_loc);
984 /* Translate the THEN clause. */
985 stmt = gfc_trans_code (code->next);
987 /* Translate the ELSE clause. */
988 if (code->block)
989 elsestmt = gfc_trans_if_1 (code->block);
990 else
991 elsestmt = build_empty_stmt (input_location);
993 /* Build the condition expression and add it to the condition block. */
994 loc = code->expr1->where.lb ? code->expr1->where.lb->location : input_location;
995 stmt = fold_build3_loc (loc, COND_EXPR, void_type_node, if_se.expr, stmt,
996 elsestmt);
998 gfc_add_expr_to_block (&if_se.pre, stmt);
1000 /* Finish off this statement. */
1001 return gfc_finish_block (&if_se.pre);
1004 tree
1005 gfc_trans_if (gfc_code * code)
1007 stmtblock_t body;
1008 tree exit_label;
1010 /* Create exit label so it is available for trans'ing the body code. */
1011 exit_label = gfc_build_label_decl (NULL_TREE);
1012 code->exit_label = exit_label;
1014 /* Translate the actual code in code->block. */
1015 gfc_init_block (&body);
1016 gfc_add_expr_to_block (&body, gfc_trans_if_1 (code->block));
1018 /* Add exit label. */
1019 gfc_add_expr_to_block (&body, build1_v (LABEL_EXPR, exit_label));
1021 return gfc_finish_block (&body);
1025 /* Translate an arithmetic IF expression.
1027 IF (cond) label1, label2, label3 translates to
1029 if (cond <= 0)
1031 if (cond < 0)
1032 goto label1;
1033 else // cond == 0
1034 goto label2;
1036 else // cond > 0
1037 goto label3;
1039 An optimized version can be generated in case of equal labels.
1040 E.g., if label1 is equal to label2, we can translate it to
1042 if (cond <= 0)
1043 goto label1;
1044 else
1045 goto label3;
1048 tree
1049 gfc_trans_arithmetic_if (gfc_code * code)
1051 gfc_se se;
1052 tree tmp;
1053 tree branch1;
1054 tree branch2;
1055 tree zero;
1057 /* Start a new block. */
1058 gfc_init_se (&se, NULL);
1059 gfc_start_block (&se.pre);
1061 /* Pre-evaluate COND. */
1062 gfc_conv_expr_val (&se, code->expr1);
1063 se.expr = gfc_evaluate_now (se.expr, &se.pre);
1065 /* Build something to compare with. */
1066 zero = gfc_build_const (TREE_TYPE (se.expr), integer_zero_node);
1068 if (code->label1->value != code->label2->value)
1070 /* If (cond < 0) take branch1 else take branch2.
1071 First build jumps to the COND .LT. 0 and the COND .EQ. 0 cases. */
1072 branch1 = build1_v (GOTO_EXPR, gfc_get_label_decl (code->label1));
1073 branch2 = build1_v (GOTO_EXPR, gfc_get_label_decl (code->label2));
1075 if (code->label1->value != code->label3->value)
1076 tmp = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
1077 se.expr, zero);
1078 else
1079 tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
1080 se.expr, zero);
1082 branch1 = fold_build3_loc (input_location, COND_EXPR, void_type_node,
1083 tmp, branch1, branch2);
1085 else
1086 branch1 = build1_v (GOTO_EXPR, gfc_get_label_decl (code->label1));
1088 if (code->label1->value != code->label3->value
1089 && code->label2->value != code->label3->value)
1091 /* if (cond <= 0) take branch1 else take branch2. */
1092 branch2 = build1_v (GOTO_EXPR, gfc_get_label_decl (code->label3));
1093 tmp = fold_build2_loc (input_location, LE_EXPR, boolean_type_node,
1094 se.expr, zero);
1095 branch1 = fold_build3_loc (input_location, COND_EXPR, void_type_node,
1096 tmp, branch1, branch2);
1099 /* Append the COND_EXPR to the evaluation of COND, and return. */
1100 gfc_add_expr_to_block (&se.pre, branch1);
1101 return gfc_finish_block (&se.pre);
1105 /* Translate a CRITICAL block. */
1106 tree
1107 gfc_trans_critical (gfc_code *code)
1109 stmtblock_t block;
1110 tree tmp;
1112 gfc_start_block (&block);
1114 if (gfc_option.coarray == GFC_FCOARRAY_LIB)
1116 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_critical, 0);
1117 gfc_add_expr_to_block (&block, tmp);
1120 tmp = gfc_trans_code (code->block->next);
1121 gfc_add_expr_to_block (&block, tmp);
1123 if (gfc_option.coarray == GFC_FCOARRAY_LIB)
1125 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_end_critical,
1127 gfc_add_expr_to_block (&block, tmp);
1131 return gfc_finish_block (&block);
1135 /* Do proper initialization for ASSOCIATE names. */
1137 static void
1138 trans_associate_var (gfc_symbol *sym, gfc_wrapped_block *block)
1140 gfc_expr *e;
1141 tree tmp;
1142 bool class_target;
1143 bool unlimited;
1144 tree desc;
1145 tree offset;
1146 tree dim;
1147 int n;
1149 gcc_assert (sym->assoc);
1150 e = sym->assoc->target;
1152 class_target = (e->expr_type == EXPR_VARIABLE)
1153 && (gfc_is_class_scalar_expr (e)
1154 || gfc_is_class_array_ref (e, NULL));
1156 unlimited = UNLIMITED_POLY (e);
1158 /* Do a `pointer assignment' with updated descriptor (or assign descriptor
1159 to array temporary) for arrays with either unknown shape or if associating
1160 to a variable. */
1161 if (sym->attr.dimension && !class_target
1162 && (sym->as->type == AS_DEFERRED || sym->assoc->variable))
1164 gfc_se se;
1165 tree desc;
1167 desc = sym->backend_decl;
1169 /* If association is to an expression, evaluate it and create temporary.
1170 Otherwise, get descriptor of target for pointer assignment. */
1171 gfc_init_se (&se, NULL);
1172 if (sym->assoc->variable)
1174 se.direct_byref = 1;
1175 se.expr = desc;
1177 gfc_conv_expr_descriptor (&se, e);
1179 /* If we didn't already do the pointer assignment, set associate-name
1180 descriptor to the one generated for the temporary. */
1181 if (!sym->assoc->variable)
1183 int dim;
1185 gfc_add_modify (&se.pre, desc, se.expr);
1187 /* The generated descriptor has lower bound zero (as array
1188 temporary), shift bounds so we get lower bounds of 1. */
1189 for (dim = 0; dim < e->rank; ++dim)
1190 gfc_conv_shift_descriptor_lbound (&se.pre, desc,
1191 dim, gfc_index_one_node);
1194 /* Done, register stuff as init / cleanup code. */
1195 gfc_add_init_cleanup (block, gfc_finish_block (&se.pre),
1196 gfc_finish_block (&se.post));
1199 /* Temporaries, arising from TYPE IS, just need the descriptor of class
1200 arrays to be assigned directly. */
1201 else if (class_target && sym->attr.dimension
1202 && (sym->ts.type == BT_DERIVED || unlimited))
1204 gfc_se se;
1206 gfc_init_se (&se, NULL);
1207 se.descriptor_only = 1;
1208 gfc_conv_expr (&se, e);
1210 gcc_assert (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (se.expr)));
1211 gcc_assert (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (sym->backend_decl)));
1213 gfc_add_modify (&se.pre, sym->backend_decl, se.expr);
1215 if (unlimited)
1217 /* Recover the dtype, which has been overwritten by the
1218 assignment from an unlimited polymorphic object. */
1219 tmp = gfc_conv_descriptor_dtype (sym->backend_decl);
1220 gfc_add_modify (&se.pre, tmp,
1221 gfc_get_dtype (TREE_TYPE (sym->backend_decl)));
1224 gfc_add_init_cleanup (block, gfc_finish_block( &se.pre),
1225 gfc_finish_block (&se.post));
1228 /* Do a scalar pointer assignment; this is for scalar variable targets. */
1229 else if (gfc_is_associate_pointer (sym))
1231 gfc_se se;
1233 gcc_assert (!sym->attr.dimension);
1235 gfc_init_se (&se, NULL);
1237 /* Class associate-names come this way because they are
1238 unconditionally associate pointers and the symbol is scalar. */
1239 if (sym->ts.type == BT_CLASS && CLASS_DATA (sym)->attr.dimension)
1241 /* For a class array we need a descriptor for the selector. */
1242 gfc_conv_expr_descriptor (&se, e);
1244 /* Obtain a temporary class container for the result. */
1245 gfc_conv_class_to_class (&se, e, sym->ts, false, true, false, false);
1246 se.expr = build_fold_indirect_ref_loc (input_location, se.expr);
1248 /* Set the offset. */
1249 desc = gfc_class_data_get (se.expr);
1250 offset = gfc_index_zero_node;
1251 for (n = 0; n < e->rank; n++)
1253 dim = gfc_rank_cst[n];
1254 tmp = fold_build2_loc (input_location, MULT_EXPR,
1255 gfc_array_index_type,
1256 gfc_conv_descriptor_stride_get (desc, dim),
1257 gfc_conv_descriptor_lbound_get (desc, dim));
1258 offset = fold_build2_loc (input_location, MINUS_EXPR,
1259 gfc_array_index_type,
1260 offset, tmp);
1262 gfc_conv_descriptor_offset_set (&se.pre, desc, offset);
1264 else if (sym->ts.type == BT_CLASS && e->ts.type == BT_CLASS
1265 && CLASS_DATA (e)->attr.dimension)
1267 /* This is bound to be a class array element. */
1268 gfc_conv_expr_reference (&se, e);
1269 /* Get the _vptr component of the class object. */
1270 tmp = gfc_get_vptr_from_expr (se.expr);
1271 /* Obtain a temporary class container for the result. */
1272 gfc_conv_derived_to_class (&se, e, sym->ts, tmp, false, false);
1273 se.expr = build_fold_indirect_ref_loc (input_location, se.expr);
1275 else
1276 gfc_conv_expr (&se, e);
1278 tmp = TREE_TYPE (sym->backend_decl);
1279 tmp = gfc_build_addr_expr (tmp, se.expr);
1280 gfc_add_modify (&se.pre, sym->backend_decl, tmp);
1282 gfc_add_init_cleanup (block, gfc_finish_block( &se.pre),
1283 gfc_finish_block (&se.post));
1286 /* Do a simple assignment. This is for scalar expressions, where we
1287 can simply use expression assignment. */
1288 else
1290 gfc_expr *lhs;
1292 lhs = gfc_lval_expr_from_sym (sym);
1293 tmp = gfc_trans_assignment (lhs, e, false, true);
1294 gfc_add_init_cleanup (block, tmp, NULL_TREE);
1297 /* Set the stringlength from the vtable size. */
1298 if (sym->ts.type == BT_CHARACTER && sym->attr.select_type_temporary)
1300 tree charlen;
1301 gfc_se se;
1302 gfc_init_se (&se, NULL);
1303 gcc_assert (UNLIMITED_POLY (e->symtree->n.sym));
1304 tmp = gfc_get_symbol_decl (e->symtree->n.sym);
1305 tmp = gfc_vtable_size_get (tmp);
1306 gfc_get_symbol_decl (sym);
1307 charlen = sym->ts.u.cl->backend_decl;
1308 gfc_add_modify (&se.pre, charlen,
1309 fold_convert (TREE_TYPE (charlen), tmp));
1310 gfc_add_init_cleanup (block, gfc_finish_block( &se.pre),
1311 gfc_finish_block (&se.post));
1316 /* Translate a BLOCK construct. This is basically what we would do for a
1317 procedure body. */
1319 tree
1320 gfc_trans_block_construct (gfc_code* code)
1322 gfc_namespace* ns;
1323 gfc_symbol* sym;
1324 gfc_wrapped_block block;
1325 tree exit_label;
1326 stmtblock_t body;
1327 gfc_association_list *ass;
1329 ns = code->ext.block.ns;
1330 gcc_assert (ns);
1331 sym = ns->proc_name;
1332 gcc_assert (sym);
1334 /* Process local variables. */
1335 gcc_assert (!sym->tlink);
1336 sym->tlink = sym;
1337 gfc_process_block_locals (ns);
1339 /* Generate code including exit-label. */
1340 gfc_init_block (&body);
1341 exit_label = gfc_build_label_decl (NULL_TREE);
1342 code->exit_label = exit_label;
1343 gfc_add_expr_to_block (&body, gfc_trans_code (ns->code));
1344 gfc_add_expr_to_block (&body, build1_v (LABEL_EXPR, exit_label));
1346 /* Finish everything. */
1347 gfc_start_wrapped_block (&block, gfc_finish_block (&body));
1348 gfc_trans_deferred_vars (sym, &block);
1349 for (ass = code->ext.block.assoc; ass; ass = ass->next)
1350 trans_associate_var (ass->st->n.sym, &block);
1352 return gfc_finish_wrapped_block (&block);
1356 /* Translate the simple DO construct. This is where the loop variable has
1357 integer type and step +-1. We can't use this in the general case
1358 because integer overflow and floating point errors could give incorrect
1359 results.
1360 We translate a do loop from:
1362 DO dovar = from, to, step
1363 body
1364 END DO
1368 [Evaluate loop bounds and step]
1369 dovar = from;
1370 if ((step > 0) ? (dovar <= to) : (dovar => to))
1372 for (;;)
1374 body;
1375 cycle_label:
1376 cond = (dovar == to);
1377 dovar += step;
1378 if (cond) goto end_label;
1381 end_label:
1383 This helps the optimizers by avoiding the extra induction variable
1384 used in the general case. */
1386 static tree
1387 gfc_trans_simple_do (gfc_code * code, stmtblock_t *pblock, tree dovar,
1388 tree from, tree to, tree step, tree exit_cond)
1390 stmtblock_t body;
1391 tree type;
1392 tree cond;
1393 tree tmp;
1394 tree saved_dovar = NULL;
1395 tree cycle_label;
1396 tree exit_label;
1397 location_t loc;
1399 type = TREE_TYPE (dovar);
1401 loc = code->ext.iterator->start->where.lb->location;
1403 /* Initialize the DO variable: dovar = from. */
1404 gfc_add_modify_loc (loc, pblock, dovar,
1405 fold_convert (TREE_TYPE(dovar), from));
1407 /* Save value for do-tinkering checking. */
1408 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
1410 saved_dovar = gfc_create_var (type, ".saved_dovar");
1411 gfc_add_modify_loc (loc, pblock, saved_dovar, dovar);
1414 /* Cycle and exit statements are implemented with gotos. */
1415 cycle_label = gfc_build_label_decl (NULL_TREE);
1416 exit_label = gfc_build_label_decl (NULL_TREE);
1418 /* Put the labels where they can be found later. See gfc_trans_do(). */
1419 code->cycle_label = cycle_label;
1420 code->exit_label = exit_label;
1422 /* Loop body. */
1423 gfc_start_block (&body);
1425 /* Main loop body. */
1426 tmp = gfc_trans_code_cond (code->block->next, exit_cond);
1427 gfc_add_expr_to_block (&body, tmp);
1429 /* Label for cycle statements (if needed). */
1430 if (TREE_USED (cycle_label))
1432 tmp = build1_v (LABEL_EXPR, cycle_label);
1433 gfc_add_expr_to_block (&body, tmp);
1436 /* Check whether someone has modified the loop variable. */
1437 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
1439 tmp = fold_build2_loc (loc, NE_EXPR, boolean_type_node,
1440 dovar, saved_dovar);
1441 gfc_trans_runtime_check (true, false, tmp, &body, &code->loc,
1442 "Loop variable has been modified");
1445 /* Exit the loop if there is an I/O result condition or error. */
1446 if (exit_cond)
1448 tmp = build1_v (GOTO_EXPR, exit_label);
1449 tmp = fold_build3_loc (loc, COND_EXPR, void_type_node,
1450 exit_cond, tmp,
1451 build_empty_stmt (loc));
1452 gfc_add_expr_to_block (&body, tmp);
1455 /* Evaluate the loop condition. */
1456 cond = fold_build2_loc (loc, EQ_EXPR, boolean_type_node, dovar,
1457 to);
1458 cond = gfc_evaluate_now_loc (loc, cond, &body);
1460 /* Increment the loop variable. */
1461 tmp = fold_build2_loc (loc, PLUS_EXPR, type, dovar, step);
1462 gfc_add_modify_loc (loc, &body, dovar, tmp);
1464 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
1465 gfc_add_modify_loc (loc, &body, saved_dovar, dovar);
1467 /* The loop exit. */
1468 tmp = fold_build1_loc (loc, GOTO_EXPR, void_type_node, exit_label);
1469 TREE_USED (exit_label) = 1;
1470 tmp = fold_build3_loc (loc, COND_EXPR, void_type_node,
1471 cond, tmp, build_empty_stmt (loc));
1472 gfc_add_expr_to_block (&body, tmp);
1474 /* Finish the loop body. */
1475 tmp = gfc_finish_block (&body);
1476 tmp = fold_build1_loc (loc, LOOP_EXPR, void_type_node, tmp);
1478 /* Only execute the loop if the number of iterations is positive. */
1479 if (tree_int_cst_sgn (step) > 0)
1480 cond = fold_build2_loc (loc, LE_EXPR, boolean_type_node, dovar,
1481 to);
1482 else
1483 cond = fold_build2_loc (loc, GE_EXPR, boolean_type_node, dovar,
1484 to);
1485 tmp = fold_build3_loc (loc, COND_EXPR, void_type_node, cond, tmp,
1486 build_empty_stmt (loc));
1487 gfc_add_expr_to_block (pblock, tmp);
1489 /* Add the exit label. */
1490 tmp = build1_v (LABEL_EXPR, exit_label);
1491 gfc_add_expr_to_block (pblock, tmp);
1493 return gfc_finish_block (pblock);
1496 /* Translate the DO construct. This obviously is one of the most
1497 important ones to get right with any compiler, but especially
1498 so for Fortran.
1500 We special case some loop forms as described in gfc_trans_simple_do.
1501 For other cases we implement them with a separate loop count,
1502 as described in the standard.
1504 We translate a do loop from:
1506 DO dovar = from, to, step
1507 body
1508 END DO
1512 [evaluate loop bounds and step]
1513 empty = (step > 0 ? to < from : to > from);
1514 countm1 = (to - from) / step;
1515 dovar = from;
1516 if (empty) goto exit_label;
1517 for (;;)
1519 body;
1520 cycle_label:
1521 dovar += step
1522 countm1t = countm1;
1523 countm1--;
1524 if (countm1t == 0) goto exit_label;
1526 exit_label:
1528 countm1 is an unsigned integer. It is equal to the loop count minus one,
1529 because the loop count itself can overflow. */
1531 tree
1532 gfc_trans_do (gfc_code * code, tree exit_cond)
1534 gfc_se se;
1535 tree dovar;
1536 tree saved_dovar = NULL;
1537 tree from;
1538 tree to;
1539 tree step;
1540 tree countm1;
1541 tree type;
1542 tree utype;
1543 tree cond;
1544 tree cycle_label;
1545 tree exit_label;
1546 tree tmp;
1547 stmtblock_t block;
1548 stmtblock_t body;
1549 location_t loc;
1551 gfc_start_block (&block);
1553 loc = code->ext.iterator->start->where.lb->location;
1555 /* Evaluate all the expressions in the iterator. */
1556 gfc_init_se (&se, NULL);
1557 gfc_conv_expr_lhs (&se, code->ext.iterator->var);
1558 gfc_add_block_to_block (&block, &se.pre);
1559 dovar = se.expr;
1560 type = TREE_TYPE (dovar);
1562 gfc_init_se (&se, NULL);
1563 gfc_conv_expr_val (&se, code->ext.iterator->start);
1564 gfc_add_block_to_block (&block, &se.pre);
1565 from = gfc_evaluate_now (se.expr, &block);
1567 gfc_init_se (&se, NULL);
1568 gfc_conv_expr_val (&se, code->ext.iterator->end);
1569 gfc_add_block_to_block (&block, &se.pre);
1570 to = gfc_evaluate_now (se.expr, &block);
1572 gfc_init_se (&se, NULL);
1573 gfc_conv_expr_val (&se, code->ext.iterator->step);
1574 gfc_add_block_to_block (&block, &se.pre);
1575 step = gfc_evaluate_now (se.expr, &block);
1577 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
1579 tmp = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, step,
1580 build_zero_cst (type));
1581 gfc_trans_runtime_check (true, false, tmp, &block, &code->loc,
1582 "DO step value is zero");
1585 /* Special case simple loops. */
1586 if (TREE_CODE (type) == INTEGER_TYPE
1587 && (integer_onep (step)
1588 || tree_int_cst_equal (step, integer_minus_one_node)))
1589 return gfc_trans_simple_do (code, &block, dovar, from, to, step, exit_cond);
1592 if (TREE_CODE (type) == INTEGER_TYPE)
1593 utype = unsigned_type_for (type);
1594 else
1595 utype = unsigned_type_for (gfc_array_index_type);
1596 countm1 = gfc_create_var (utype, "countm1");
1598 /* Cycle and exit statements are implemented with gotos. */
1599 cycle_label = gfc_build_label_decl (NULL_TREE);
1600 exit_label = gfc_build_label_decl (NULL_TREE);
1601 TREE_USED (exit_label) = 1;
1603 /* Put these labels where they can be found later. */
1604 code->cycle_label = cycle_label;
1605 code->exit_label = exit_label;
1607 /* Initialize the DO variable: dovar = from. */
1608 gfc_add_modify (&block, dovar, from);
1610 /* Save value for do-tinkering checking. */
1611 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
1613 saved_dovar = gfc_create_var (type, ".saved_dovar");
1614 gfc_add_modify_loc (loc, &block, saved_dovar, dovar);
1617 /* Initialize loop count and jump to exit label if the loop is empty.
1618 This code is executed before we enter the loop body. We generate:
1619 if (step > 0)
1621 if (to < from)
1622 goto exit_label;
1623 countm1 = (to - from) / step;
1625 else
1627 if (to > from)
1628 goto exit_label;
1629 countm1 = (from - to) / -step;
1633 if (TREE_CODE (type) == INTEGER_TYPE)
1635 tree pos, neg, tou, fromu, stepu, tmp2;
1637 /* The distance from FROM to TO cannot always be represented in a signed
1638 type, thus use unsigned arithmetic, also to avoid any undefined
1639 overflow issues. */
1640 tou = fold_convert (utype, to);
1641 fromu = fold_convert (utype, from);
1642 stepu = fold_convert (utype, step);
1644 /* For a positive step, when to < from, exit, otherwise compute
1645 countm1 = ((unsigned)to - (unsigned)from) / (unsigned)step */
1646 tmp = fold_build2_loc (loc, LT_EXPR, boolean_type_node, to, from);
1647 tmp2 = fold_build2_loc (loc, TRUNC_DIV_EXPR, utype,
1648 fold_build2_loc (loc, MINUS_EXPR, utype,
1649 tou, fromu),
1650 stepu);
1651 pos = fold_build3_loc (loc, COND_EXPR, void_type_node, tmp,
1652 fold_build1_loc (loc, GOTO_EXPR, void_type_node,
1653 exit_label),
1654 fold_build2 (MODIFY_EXPR, void_type_node,
1655 countm1, tmp2));
1657 /* For a negative step, when to > from, exit, otherwise compute
1658 countm1 = ((unsigned)from - (unsigned)to) / -(unsigned)step */
1659 tmp = fold_build2_loc (loc, GT_EXPR, boolean_type_node, to, from);
1660 tmp2 = fold_build2_loc (loc, TRUNC_DIV_EXPR, utype,
1661 fold_build2_loc (loc, MINUS_EXPR, utype,
1662 fromu, tou),
1663 fold_build1_loc (loc, NEGATE_EXPR, utype, stepu));
1664 neg = fold_build3_loc (loc, COND_EXPR, void_type_node, tmp,
1665 fold_build1_loc (loc, GOTO_EXPR, void_type_node,
1666 exit_label),
1667 fold_build2 (MODIFY_EXPR, void_type_node,
1668 countm1, tmp2));
1670 tmp = fold_build2_loc (loc, LT_EXPR, boolean_type_node, step,
1671 build_int_cst (TREE_TYPE (step), 0));
1672 tmp = fold_build3_loc (loc, COND_EXPR, void_type_node, tmp, neg, pos);
1674 gfc_add_expr_to_block (&block, tmp);
1676 else
1678 tree pos_step;
1680 /* TODO: We could use the same width as the real type.
1681 This would probably cause more problems that it solves
1682 when we implement "long double" types. */
1684 tmp = fold_build2_loc (loc, MINUS_EXPR, type, to, from);
1685 tmp = fold_build2_loc (loc, RDIV_EXPR, type, tmp, step);
1686 tmp = fold_build1_loc (loc, FIX_TRUNC_EXPR, utype, tmp);
1687 gfc_add_modify (&block, countm1, tmp);
1689 /* We need a special check for empty loops:
1690 empty = (step > 0 ? to < from : to > from); */
1691 pos_step = fold_build2_loc (loc, GT_EXPR, boolean_type_node, step,
1692 build_zero_cst (type));
1693 tmp = fold_build3_loc (loc, COND_EXPR, boolean_type_node, pos_step,
1694 fold_build2_loc (loc, LT_EXPR,
1695 boolean_type_node, to, from),
1696 fold_build2_loc (loc, GT_EXPR,
1697 boolean_type_node, to, from));
1698 /* If the loop is empty, go directly to the exit label. */
1699 tmp = fold_build3_loc (loc, COND_EXPR, void_type_node, tmp,
1700 build1_v (GOTO_EXPR, exit_label),
1701 build_empty_stmt (input_location));
1702 gfc_add_expr_to_block (&block, tmp);
1705 /* Loop body. */
1706 gfc_start_block (&body);
1708 /* Main loop body. */
1709 tmp = gfc_trans_code_cond (code->block->next, exit_cond);
1710 gfc_add_expr_to_block (&body, tmp);
1712 /* Label for cycle statements (if needed). */
1713 if (TREE_USED (cycle_label))
1715 tmp = build1_v (LABEL_EXPR, cycle_label);
1716 gfc_add_expr_to_block (&body, tmp);
1719 /* Check whether someone has modified the loop variable. */
1720 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
1722 tmp = fold_build2_loc (loc, NE_EXPR, boolean_type_node, dovar,
1723 saved_dovar);
1724 gfc_trans_runtime_check (true, false, tmp, &body, &code->loc,
1725 "Loop variable has been modified");
1728 /* Exit the loop if there is an I/O result condition or error. */
1729 if (exit_cond)
1731 tmp = build1_v (GOTO_EXPR, exit_label);
1732 tmp = fold_build3_loc (loc, COND_EXPR, void_type_node,
1733 exit_cond, tmp,
1734 build_empty_stmt (input_location));
1735 gfc_add_expr_to_block (&body, tmp);
1738 /* Increment the loop variable. */
1739 tmp = fold_build2_loc (loc, PLUS_EXPR, type, dovar, step);
1740 gfc_add_modify_loc (loc, &body, dovar, tmp);
1742 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
1743 gfc_add_modify_loc (loc, &body, saved_dovar, dovar);
1745 /* Initialize countm1t. */
1746 tree countm1t = gfc_create_var (utype, "countm1t");
1747 gfc_add_modify_loc (loc, &body, countm1t, countm1);
1749 /* Decrement the loop count. */
1750 tmp = fold_build2_loc (loc, MINUS_EXPR, utype, countm1,
1751 build_int_cst (utype, 1));
1752 gfc_add_modify_loc (loc, &body, countm1, tmp);
1754 /* End with the loop condition. Loop until countm1t == 0. */
1755 cond = fold_build2_loc (loc, EQ_EXPR, boolean_type_node, countm1t,
1756 build_int_cst (utype, 0));
1757 tmp = fold_build1_loc (loc, GOTO_EXPR, void_type_node, exit_label);
1758 tmp = fold_build3_loc (loc, COND_EXPR, void_type_node,
1759 cond, tmp, build_empty_stmt (loc));
1760 gfc_add_expr_to_block (&body, tmp);
1762 /* End of loop body. */
1763 tmp = gfc_finish_block (&body);
1765 /* The for loop itself. */
1766 tmp = fold_build1_loc (loc, LOOP_EXPR, void_type_node, tmp);
1767 gfc_add_expr_to_block (&block, tmp);
1769 /* Add the exit label. */
1770 tmp = build1_v (LABEL_EXPR, exit_label);
1771 gfc_add_expr_to_block (&block, tmp);
1773 return gfc_finish_block (&block);
1777 /* Translate the DO WHILE construct.
1779 We translate
1781 DO WHILE (cond)
1782 body
1783 END DO
1787 for ( ; ; )
1789 pre_cond;
1790 if (! cond) goto exit_label;
1791 body;
1792 cycle_label:
1794 exit_label:
1796 Because the evaluation of the exit condition `cond' may have side
1797 effects, we can't do much for empty loop bodies. The backend optimizers
1798 should be smart enough to eliminate any dead loops. */
1800 tree
1801 gfc_trans_do_while (gfc_code * code)
1803 gfc_se cond;
1804 tree tmp;
1805 tree cycle_label;
1806 tree exit_label;
1807 stmtblock_t block;
1809 /* Everything we build here is part of the loop body. */
1810 gfc_start_block (&block);
1812 /* Cycle and exit statements are implemented with gotos. */
1813 cycle_label = gfc_build_label_decl (NULL_TREE);
1814 exit_label = gfc_build_label_decl (NULL_TREE);
1816 /* Put the labels where they can be found later. See gfc_trans_do(). */
1817 code->cycle_label = cycle_label;
1818 code->exit_label = exit_label;
1820 /* Create a GIMPLE version of the exit condition. */
1821 gfc_init_se (&cond, NULL);
1822 gfc_conv_expr_val (&cond, code->expr1);
1823 gfc_add_block_to_block (&block, &cond.pre);
1824 cond.expr = fold_build1_loc (code->expr1->where.lb->location,
1825 TRUTH_NOT_EXPR, TREE_TYPE (cond.expr), cond.expr);
1827 /* Build "IF (! cond) GOTO exit_label". */
1828 tmp = build1_v (GOTO_EXPR, exit_label);
1829 TREE_USED (exit_label) = 1;
1830 tmp = fold_build3_loc (code->expr1->where.lb->location, COND_EXPR,
1831 void_type_node, cond.expr, tmp,
1832 build_empty_stmt (code->expr1->where.lb->location));
1833 gfc_add_expr_to_block (&block, tmp);
1835 /* The main body of the loop. */
1836 tmp = gfc_trans_code (code->block->next);
1837 gfc_add_expr_to_block (&block, tmp);
1839 /* Label for cycle statements (if needed). */
1840 if (TREE_USED (cycle_label))
1842 tmp = build1_v (LABEL_EXPR, cycle_label);
1843 gfc_add_expr_to_block (&block, tmp);
1846 /* End of loop body. */
1847 tmp = gfc_finish_block (&block);
1849 gfc_init_block (&block);
1850 /* Build the loop. */
1851 tmp = fold_build1_loc (code->expr1->where.lb->location, LOOP_EXPR,
1852 void_type_node, tmp);
1853 gfc_add_expr_to_block (&block, tmp);
1855 /* Add the exit label. */
1856 tmp = build1_v (LABEL_EXPR, exit_label);
1857 gfc_add_expr_to_block (&block, tmp);
1859 return gfc_finish_block (&block);
1863 /* Translate the SELECT CASE construct for INTEGER case expressions,
1864 without killing all potential optimizations. The problem is that
1865 Fortran allows unbounded cases, but the back-end does not, so we
1866 need to intercept those before we enter the equivalent SWITCH_EXPR
1867 we can build.
1869 For example, we translate this,
1871 SELECT CASE (expr)
1872 CASE (:100,101,105:115)
1873 block_1
1874 CASE (190:199,200:)
1875 block_2
1876 CASE (300)
1877 block_3
1878 CASE DEFAULT
1879 block_4
1880 END SELECT
1882 to the GENERIC equivalent,
1884 switch (expr)
1886 case (minimum value for typeof(expr) ... 100:
1887 case 101:
1888 case 105 ... 114:
1889 block1:
1890 goto end_label;
1892 case 200 ... (maximum value for typeof(expr):
1893 case 190 ... 199:
1894 block2;
1895 goto end_label;
1897 case 300:
1898 block_3;
1899 goto end_label;
1901 default:
1902 block_4;
1903 goto end_label;
1906 end_label: */
1908 static tree
1909 gfc_trans_integer_select (gfc_code * code)
1911 gfc_code *c;
1912 gfc_case *cp;
1913 tree end_label;
1914 tree tmp;
1915 gfc_se se;
1916 stmtblock_t block;
1917 stmtblock_t body;
1919 gfc_start_block (&block);
1921 /* Calculate the switch expression. */
1922 gfc_init_se (&se, NULL);
1923 gfc_conv_expr_val (&se, code->expr1);
1924 gfc_add_block_to_block (&block, &se.pre);
1926 end_label = gfc_build_label_decl (NULL_TREE);
1928 gfc_init_block (&body);
1930 for (c = code->block; c; c = c->block)
1932 for (cp = c->ext.block.case_list; cp; cp = cp->next)
1934 tree low, high;
1935 tree label;
1937 /* Assume it's the default case. */
1938 low = high = NULL_TREE;
1940 if (cp->low)
1942 low = gfc_conv_mpz_to_tree (cp->low->value.integer,
1943 cp->low->ts.kind);
1945 /* If there's only a lower bound, set the high bound to the
1946 maximum value of the case expression. */
1947 if (!cp->high)
1948 high = TYPE_MAX_VALUE (TREE_TYPE (se.expr));
1951 if (cp->high)
1953 /* Three cases are possible here:
1955 1) There is no lower bound, e.g. CASE (:N).
1956 2) There is a lower bound .NE. high bound, that is
1957 a case range, e.g. CASE (N:M) where M>N (we make
1958 sure that M>N during type resolution).
1959 3) There is a lower bound, and it has the same value
1960 as the high bound, e.g. CASE (N:N). This is our
1961 internal representation of CASE(N).
1963 In the first and second case, we need to set a value for
1964 high. In the third case, we don't because the GCC middle
1965 end represents a single case value by just letting high be
1966 a NULL_TREE. We can't do that because we need to be able
1967 to represent unbounded cases. */
1969 if (!cp->low
1970 || (cp->low
1971 && mpz_cmp (cp->low->value.integer,
1972 cp->high->value.integer) != 0))
1973 high = gfc_conv_mpz_to_tree (cp->high->value.integer,
1974 cp->high->ts.kind);
1976 /* Unbounded case. */
1977 if (!cp->low)
1978 low = TYPE_MIN_VALUE (TREE_TYPE (se.expr));
1981 /* Build a label. */
1982 label = gfc_build_label_decl (NULL_TREE);
1984 /* Add this case label.
1985 Add parameter 'label', make it match GCC backend. */
1986 tmp = build_case_label (low, high, label);
1987 gfc_add_expr_to_block (&body, tmp);
1990 /* Add the statements for this case. */
1991 tmp = gfc_trans_code (c->next);
1992 gfc_add_expr_to_block (&body, tmp);
1994 /* Break to the end of the construct. */
1995 tmp = build1_v (GOTO_EXPR, end_label);
1996 gfc_add_expr_to_block (&body, tmp);
1999 tmp = gfc_finish_block (&body);
2000 tmp = fold_build3_loc (input_location, SWITCH_EXPR, NULL_TREE,
2001 se.expr, tmp, NULL_TREE);
2002 gfc_add_expr_to_block (&block, tmp);
2004 tmp = build1_v (LABEL_EXPR, end_label);
2005 gfc_add_expr_to_block (&block, tmp);
2007 return gfc_finish_block (&block);
2011 /* Translate the SELECT CASE construct for LOGICAL case expressions.
2013 There are only two cases possible here, even though the standard
2014 does allow three cases in a LOGICAL SELECT CASE construct: .TRUE.,
2015 .FALSE., and DEFAULT.
2017 We never generate more than two blocks here. Instead, we always
2018 try to eliminate the DEFAULT case. This way, we can translate this
2019 kind of SELECT construct to a simple
2021 if {} else {};
2023 expression in GENERIC. */
2025 static tree
2026 gfc_trans_logical_select (gfc_code * code)
2028 gfc_code *c;
2029 gfc_code *t, *f, *d;
2030 gfc_case *cp;
2031 gfc_se se;
2032 stmtblock_t block;
2034 /* Assume we don't have any cases at all. */
2035 t = f = d = NULL;
2037 /* Now see which ones we actually do have. We can have at most two
2038 cases in a single case list: one for .TRUE. and one for .FALSE.
2039 The default case is always separate. If the cases for .TRUE. and
2040 .FALSE. are in the same case list, the block for that case list
2041 always executed, and we don't generate code a COND_EXPR. */
2042 for (c = code->block; c; c = c->block)
2044 for (cp = c->ext.block.case_list; cp; cp = cp->next)
2046 if (cp->low)
2048 if (cp->low->value.logical == 0) /* .FALSE. */
2049 f = c;
2050 else /* if (cp->value.logical != 0), thus .TRUE. */
2051 t = c;
2053 else
2054 d = c;
2058 /* Start a new block. */
2059 gfc_start_block (&block);
2061 /* Calculate the switch expression. We always need to do this
2062 because it may have side effects. */
2063 gfc_init_se (&se, NULL);
2064 gfc_conv_expr_val (&se, code->expr1);
2065 gfc_add_block_to_block (&block, &se.pre);
2067 if (t == f && t != NULL)
2069 /* Cases for .TRUE. and .FALSE. are in the same block. Just
2070 translate the code for these cases, append it to the current
2071 block. */
2072 gfc_add_expr_to_block (&block, gfc_trans_code (t->next));
2074 else
2076 tree true_tree, false_tree, stmt;
2078 true_tree = build_empty_stmt (input_location);
2079 false_tree = build_empty_stmt (input_location);
2081 /* If we have a case for .TRUE. and for .FALSE., discard the default case.
2082 Otherwise, if .TRUE. or .FALSE. is missing and there is a default case,
2083 make the missing case the default case. */
2084 if (t != NULL && f != NULL)
2085 d = NULL;
2086 else if (d != NULL)
2088 if (t == NULL)
2089 t = d;
2090 else
2091 f = d;
2094 /* Translate the code for each of these blocks, and append it to
2095 the current block. */
2096 if (t != NULL)
2097 true_tree = gfc_trans_code (t->next);
2099 if (f != NULL)
2100 false_tree = gfc_trans_code (f->next);
2102 stmt = fold_build3_loc (input_location, COND_EXPR, void_type_node,
2103 se.expr, true_tree, false_tree);
2104 gfc_add_expr_to_block (&block, stmt);
2107 return gfc_finish_block (&block);
2111 /* The jump table types are stored in static variables to avoid
2112 constructing them from scratch every single time. */
2113 static GTY(()) tree select_struct[2];
2115 /* Translate the SELECT CASE construct for CHARACTER case expressions.
2116 Instead of generating compares and jumps, it is far simpler to
2117 generate a data structure describing the cases in order and call a
2118 library subroutine that locates the right case.
2119 This is particularly true because this is the only case where we
2120 might have to dispose of a temporary.
2121 The library subroutine returns a pointer to jump to or NULL if no
2122 branches are to be taken. */
2124 static tree
2125 gfc_trans_character_select (gfc_code *code)
2127 tree init, end_label, tmp, type, case_num, label, fndecl;
2128 stmtblock_t block, body;
2129 gfc_case *cp, *d;
2130 gfc_code *c;
2131 gfc_se se, expr1se;
2132 int n, k;
2133 vec<constructor_elt, va_gc> *inits = NULL;
2135 tree pchartype = gfc_get_pchar_type (code->expr1->ts.kind);
2137 /* The jump table types are stored in static variables to avoid
2138 constructing them from scratch every single time. */
2139 static tree ss_string1[2], ss_string1_len[2];
2140 static tree ss_string2[2], ss_string2_len[2];
2141 static tree ss_target[2];
2143 cp = code->block->ext.block.case_list;
2144 while (cp->left != NULL)
2145 cp = cp->left;
2147 /* Generate the body */
2148 gfc_start_block (&block);
2149 gfc_init_se (&expr1se, NULL);
2150 gfc_conv_expr_reference (&expr1se, code->expr1);
2152 gfc_add_block_to_block (&block, &expr1se.pre);
2154 end_label = gfc_build_label_decl (NULL_TREE);
2156 gfc_init_block (&body);
2158 /* Attempt to optimize length 1 selects. */
2159 if (integer_onep (expr1se.string_length))
2161 for (d = cp; d; d = d->right)
2163 int i;
2164 if (d->low)
2166 gcc_assert (d->low->expr_type == EXPR_CONSTANT
2167 && d->low->ts.type == BT_CHARACTER);
2168 if (d->low->value.character.length > 1)
2170 for (i = 1; i < d->low->value.character.length; i++)
2171 if (d->low->value.character.string[i] != ' ')
2172 break;
2173 if (i != d->low->value.character.length)
2175 if (optimize && d->high && i == 1)
2177 gcc_assert (d->high->expr_type == EXPR_CONSTANT
2178 && d->high->ts.type == BT_CHARACTER);
2179 if (d->high->value.character.length > 1
2180 && (d->low->value.character.string[0]
2181 == d->high->value.character.string[0])
2182 && d->high->value.character.string[1] != ' '
2183 && ((d->low->value.character.string[1] < ' ')
2184 == (d->high->value.character.string[1]
2185 < ' ')))
2186 continue;
2188 break;
2192 if (d->high)
2194 gcc_assert (d->high->expr_type == EXPR_CONSTANT
2195 && d->high->ts.type == BT_CHARACTER);
2196 if (d->high->value.character.length > 1)
2198 for (i = 1; i < d->high->value.character.length; i++)
2199 if (d->high->value.character.string[i] != ' ')
2200 break;
2201 if (i != d->high->value.character.length)
2202 break;
2206 if (d == NULL)
2208 tree ctype = gfc_get_char_type (code->expr1->ts.kind);
2210 for (c = code->block; c; c = c->block)
2212 for (cp = c->ext.block.case_list; cp; cp = cp->next)
2214 tree low, high;
2215 tree label;
2216 gfc_char_t r;
2218 /* Assume it's the default case. */
2219 low = high = NULL_TREE;
2221 if (cp->low)
2223 /* CASE ('ab') or CASE ('ab':'az') will never match
2224 any length 1 character. */
2225 if (cp->low->value.character.length > 1
2226 && cp->low->value.character.string[1] != ' ')
2227 continue;
2229 if (cp->low->value.character.length > 0)
2230 r = cp->low->value.character.string[0];
2231 else
2232 r = ' ';
2233 low = build_int_cst (ctype, r);
2235 /* If there's only a lower bound, set the high bound
2236 to the maximum value of the case expression. */
2237 if (!cp->high)
2238 high = TYPE_MAX_VALUE (ctype);
2241 if (cp->high)
2243 if (!cp->low
2244 || (cp->low->value.character.string[0]
2245 != cp->high->value.character.string[0]))
2247 if (cp->high->value.character.length > 0)
2248 r = cp->high->value.character.string[0];
2249 else
2250 r = ' ';
2251 high = build_int_cst (ctype, r);
2254 /* Unbounded case. */
2255 if (!cp->low)
2256 low = TYPE_MIN_VALUE (ctype);
2259 /* Build a label. */
2260 label = gfc_build_label_decl (NULL_TREE);
2262 /* Add this case label.
2263 Add parameter 'label', make it match GCC backend. */
2264 tmp = build_case_label (low, high, label);
2265 gfc_add_expr_to_block (&body, tmp);
2268 /* Add the statements for this case. */
2269 tmp = gfc_trans_code (c->next);
2270 gfc_add_expr_to_block (&body, tmp);
2272 /* Break to the end of the construct. */
2273 tmp = build1_v (GOTO_EXPR, end_label);
2274 gfc_add_expr_to_block (&body, tmp);
2277 tmp = gfc_string_to_single_character (expr1se.string_length,
2278 expr1se.expr,
2279 code->expr1->ts.kind);
2280 case_num = gfc_create_var (ctype, "case_num");
2281 gfc_add_modify (&block, case_num, tmp);
2283 gfc_add_block_to_block (&block, &expr1se.post);
2285 tmp = gfc_finish_block (&body);
2286 tmp = fold_build3_loc (input_location, SWITCH_EXPR, NULL_TREE,
2287 case_num, tmp, NULL_TREE);
2288 gfc_add_expr_to_block (&block, tmp);
2290 tmp = build1_v (LABEL_EXPR, end_label);
2291 gfc_add_expr_to_block (&block, tmp);
2293 return gfc_finish_block (&block);
2297 if (code->expr1->ts.kind == 1)
2298 k = 0;
2299 else if (code->expr1->ts.kind == 4)
2300 k = 1;
2301 else
2302 gcc_unreachable ();
2304 if (select_struct[k] == NULL)
2306 tree *chain = NULL;
2307 select_struct[k] = make_node (RECORD_TYPE);
2309 if (code->expr1->ts.kind == 1)
2310 TYPE_NAME (select_struct[k]) = get_identifier ("_jump_struct_char1");
2311 else if (code->expr1->ts.kind == 4)
2312 TYPE_NAME (select_struct[k]) = get_identifier ("_jump_struct_char4");
2313 else
2314 gcc_unreachable ();
2316 #undef ADD_FIELD
2317 #define ADD_FIELD(NAME, TYPE) \
2318 ss_##NAME[k] = gfc_add_field_to_struct (select_struct[k], \
2319 get_identifier (stringize(NAME)), \
2320 TYPE, \
2321 &chain)
2323 ADD_FIELD (string1, pchartype);
2324 ADD_FIELD (string1_len, gfc_charlen_type_node);
2326 ADD_FIELD (string2, pchartype);
2327 ADD_FIELD (string2_len, gfc_charlen_type_node);
2329 ADD_FIELD (target, integer_type_node);
2330 #undef ADD_FIELD
2332 gfc_finish_type (select_struct[k]);
2335 n = 0;
2336 for (d = cp; d; d = d->right)
2337 d->n = n++;
2339 for (c = code->block; c; c = c->block)
2341 for (d = c->ext.block.case_list; d; d = d->next)
2343 label = gfc_build_label_decl (NULL_TREE);
2344 tmp = build_case_label ((d->low == NULL && d->high == NULL)
2345 ? NULL
2346 : build_int_cst (integer_type_node, d->n),
2347 NULL, label);
2348 gfc_add_expr_to_block (&body, tmp);
2351 tmp = gfc_trans_code (c->next);
2352 gfc_add_expr_to_block (&body, tmp);
2354 tmp = build1_v (GOTO_EXPR, end_label);
2355 gfc_add_expr_to_block (&body, tmp);
2358 /* Generate the structure describing the branches */
2359 for (d = cp; d; d = d->right)
2361 vec<constructor_elt, va_gc> *node = NULL;
2363 gfc_init_se (&se, NULL);
2365 if (d->low == NULL)
2367 CONSTRUCTOR_APPEND_ELT (node, ss_string1[k], null_pointer_node);
2368 CONSTRUCTOR_APPEND_ELT (node, ss_string1_len[k], integer_zero_node);
2370 else
2372 gfc_conv_expr_reference (&se, d->low);
2374 CONSTRUCTOR_APPEND_ELT (node, ss_string1[k], se.expr);
2375 CONSTRUCTOR_APPEND_ELT (node, ss_string1_len[k], se.string_length);
2378 if (d->high == NULL)
2380 CONSTRUCTOR_APPEND_ELT (node, ss_string2[k], null_pointer_node);
2381 CONSTRUCTOR_APPEND_ELT (node, ss_string2_len[k], integer_zero_node);
2383 else
2385 gfc_init_se (&se, NULL);
2386 gfc_conv_expr_reference (&se, d->high);
2388 CONSTRUCTOR_APPEND_ELT (node, ss_string2[k], se.expr);
2389 CONSTRUCTOR_APPEND_ELT (node, ss_string2_len[k], se.string_length);
2392 CONSTRUCTOR_APPEND_ELT (node, ss_target[k],
2393 build_int_cst (integer_type_node, d->n));
2395 tmp = build_constructor (select_struct[k], node);
2396 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, tmp);
2399 type = build_array_type (select_struct[k],
2400 build_index_type (size_int (n-1)));
2402 init = build_constructor (type, inits);
2403 TREE_CONSTANT (init) = 1;
2404 TREE_STATIC (init) = 1;
2405 /* Create a static variable to hold the jump table. */
2406 tmp = gfc_create_var (type, "jumptable");
2407 TREE_CONSTANT (tmp) = 1;
2408 TREE_STATIC (tmp) = 1;
2409 TREE_READONLY (tmp) = 1;
2410 DECL_INITIAL (tmp) = init;
2411 init = tmp;
2413 /* Build the library call */
2414 init = gfc_build_addr_expr (pvoid_type_node, init);
2416 if (code->expr1->ts.kind == 1)
2417 fndecl = gfor_fndecl_select_string;
2418 else if (code->expr1->ts.kind == 4)
2419 fndecl = gfor_fndecl_select_string_char4;
2420 else
2421 gcc_unreachable ();
2423 tmp = build_call_expr_loc (input_location,
2424 fndecl, 4, init,
2425 build_int_cst (gfc_charlen_type_node, n),
2426 expr1se.expr, expr1se.string_length);
2427 case_num = gfc_create_var (integer_type_node, "case_num");
2428 gfc_add_modify (&block, case_num, tmp);
2430 gfc_add_block_to_block (&block, &expr1se.post);
2432 tmp = gfc_finish_block (&body);
2433 tmp = fold_build3_loc (input_location, SWITCH_EXPR, NULL_TREE,
2434 case_num, tmp, NULL_TREE);
2435 gfc_add_expr_to_block (&block, tmp);
2437 tmp = build1_v (LABEL_EXPR, end_label);
2438 gfc_add_expr_to_block (&block, tmp);
2440 return gfc_finish_block (&block);
2444 /* Translate the three variants of the SELECT CASE construct.
2446 SELECT CASEs with INTEGER case expressions can be translated to an
2447 equivalent GENERIC switch statement, and for LOGICAL case
2448 expressions we build one or two if-else compares.
2450 SELECT CASEs with CHARACTER case expressions are a whole different
2451 story, because they don't exist in GENERIC. So we sort them and
2452 do a binary search at runtime.
2454 Fortran has no BREAK statement, and it does not allow jumps from
2455 one case block to another. That makes things a lot easier for
2456 the optimizers. */
2458 tree
2459 gfc_trans_select (gfc_code * code)
2461 stmtblock_t block;
2462 tree body;
2463 tree exit_label;
2465 gcc_assert (code && code->expr1);
2466 gfc_init_block (&block);
2468 /* Build the exit label and hang it in. */
2469 exit_label = gfc_build_label_decl (NULL_TREE);
2470 code->exit_label = exit_label;
2472 /* Empty SELECT constructs are legal. */
2473 if (code->block == NULL)
2474 body = build_empty_stmt (input_location);
2476 /* Select the correct translation function. */
2477 else
2478 switch (code->expr1->ts.type)
2480 case BT_LOGICAL:
2481 body = gfc_trans_logical_select (code);
2482 break;
2484 case BT_INTEGER:
2485 body = gfc_trans_integer_select (code);
2486 break;
2488 case BT_CHARACTER:
2489 body = gfc_trans_character_select (code);
2490 break;
2492 default:
2493 gfc_internal_error ("gfc_trans_select(): Bad type for case expr.");
2494 /* Not reached */
2497 /* Build everything together. */
2498 gfc_add_expr_to_block (&block, body);
2499 gfc_add_expr_to_block (&block, build1_v (LABEL_EXPR, exit_label));
2501 return gfc_finish_block (&block);
2505 /* Traversal function to substitute a replacement symtree if the symbol
2506 in the expression is the same as that passed. f == 2 signals that
2507 that variable itself is not to be checked - only the references.
2508 This group of functions is used when the variable expression in a
2509 FORALL assignment has internal references. For example:
2510 FORALL (i = 1:4) p(p(i)) = i
2511 The only recourse here is to store a copy of 'p' for the index
2512 expression. */
2514 static gfc_symtree *new_symtree;
2515 static gfc_symtree *old_symtree;
2517 static bool
2518 forall_replace (gfc_expr *expr, gfc_symbol *sym, int *f)
2520 if (expr->expr_type != EXPR_VARIABLE)
2521 return false;
2523 if (*f == 2)
2524 *f = 1;
2525 else if (expr->symtree->n.sym == sym)
2526 expr->symtree = new_symtree;
2528 return false;
2531 static void
2532 forall_replace_symtree (gfc_expr *e, gfc_symbol *sym, int f)
2534 gfc_traverse_expr (e, sym, forall_replace, f);
2537 static bool
2538 forall_restore (gfc_expr *expr,
2539 gfc_symbol *sym ATTRIBUTE_UNUSED,
2540 int *f ATTRIBUTE_UNUSED)
2542 if (expr->expr_type != EXPR_VARIABLE)
2543 return false;
2545 if (expr->symtree == new_symtree)
2546 expr->symtree = old_symtree;
2548 return false;
2551 static void
2552 forall_restore_symtree (gfc_expr *e)
2554 gfc_traverse_expr (e, NULL, forall_restore, 0);
2557 static void
2558 forall_make_variable_temp (gfc_code *c, stmtblock_t *pre, stmtblock_t *post)
2560 gfc_se tse;
2561 gfc_se rse;
2562 gfc_expr *e;
2563 gfc_symbol *new_sym;
2564 gfc_symbol *old_sym;
2565 gfc_symtree *root;
2566 tree tmp;
2568 /* Build a copy of the lvalue. */
2569 old_symtree = c->expr1->symtree;
2570 old_sym = old_symtree->n.sym;
2571 e = gfc_lval_expr_from_sym (old_sym);
2572 if (old_sym->attr.dimension)
2574 gfc_init_se (&tse, NULL);
2575 gfc_conv_subref_array_arg (&tse, e, 0, INTENT_IN, false);
2576 gfc_add_block_to_block (pre, &tse.pre);
2577 gfc_add_block_to_block (post, &tse.post);
2578 tse.expr = build_fold_indirect_ref_loc (input_location, tse.expr);
2580 if (e->ts.type != BT_CHARACTER)
2582 /* Use the variable offset for the temporary. */
2583 tmp = gfc_conv_array_offset (old_sym->backend_decl);
2584 gfc_conv_descriptor_offset_set (pre, tse.expr, tmp);
2587 else
2589 gfc_init_se (&tse, NULL);
2590 gfc_init_se (&rse, NULL);
2591 gfc_conv_expr (&rse, e);
2592 if (e->ts.type == BT_CHARACTER)
2594 tse.string_length = rse.string_length;
2595 tmp = gfc_get_character_type_len (gfc_default_character_kind,
2596 tse.string_length);
2597 tse.expr = gfc_conv_string_tmp (&tse, build_pointer_type (tmp),
2598 rse.string_length);
2599 gfc_add_block_to_block (pre, &tse.pre);
2600 gfc_add_block_to_block (post, &tse.post);
2602 else
2604 tmp = gfc_typenode_for_spec (&e->ts);
2605 tse.expr = gfc_create_var (tmp, "temp");
2608 tmp = gfc_trans_scalar_assign (&tse, &rse, e->ts, true,
2609 e->expr_type == EXPR_VARIABLE, true);
2610 gfc_add_expr_to_block (pre, tmp);
2612 gfc_free_expr (e);
2614 /* Create a new symbol to represent the lvalue. */
2615 new_sym = gfc_new_symbol (old_sym->name, NULL);
2616 new_sym->ts = old_sym->ts;
2617 new_sym->attr.referenced = 1;
2618 new_sym->attr.temporary = 1;
2619 new_sym->attr.dimension = old_sym->attr.dimension;
2620 new_sym->attr.flavor = old_sym->attr.flavor;
2622 /* Use the temporary as the backend_decl. */
2623 new_sym->backend_decl = tse.expr;
2625 /* Create a fake symtree for it. */
2626 root = NULL;
2627 new_symtree = gfc_new_symtree (&root, old_sym->name);
2628 new_symtree->n.sym = new_sym;
2629 gcc_assert (new_symtree == root);
2631 /* Go through the expression reference replacing the old_symtree
2632 with the new. */
2633 forall_replace_symtree (c->expr1, old_sym, 2);
2635 /* Now we have made this temporary, we might as well use it for
2636 the right hand side. */
2637 forall_replace_symtree (c->expr2, old_sym, 1);
2641 /* Handles dependencies in forall assignments. */
2642 static int
2643 check_forall_dependencies (gfc_code *c, stmtblock_t *pre, stmtblock_t *post)
2645 gfc_ref *lref;
2646 gfc_ref *rref;
2647 int need_temp;
2648 gfc_symbol *lsym;
2650 lsym = c->expr1->symtree->n.sym;
2651 need_temp = gfc_check_dependency (c->expr1, c->expr2, 0);
2653 /* Now check for dependencies within the 'variable'
2654 expression itself. These are treated by making a complete
2655 copy of variable and changing all the references to it
2656 point to the copy instead. Note that the shallow copy of
2657 the variable will not suffice for derived types with
2658 pointer components. We therefore leave these to their
2659 own devices. */
2660 if (lsym->ts.type == BT_DERIVED
2661 && lsym->ts.u.derived->attr.pointer_comp)
2662 return need_temp;
2664 new_symtree = NULL;
2665 if (find_forall_index (c->expr1, lsym, 2))
2667 forall_make_variable_temp (c, pre, post);
2668 need_temp = 0;
2671 /* Substrings with dependencies are treated in the same
2672 way. */
2673 if (c->expr1->ts.type == BT_CHARACTER
2674 && c->expr1->ref
2675 && c->expr2->expr_type == EXPR_VARIABLE
2676 && lsym == c->expr2->symtree->n.sym)
2678 for (lref = c->expr1->ref; lref; lref = lref->next)
2679 if (lref->type == REF_SUBSTRING)
2680 break;
2681 for (rref = c->expr2->ref; rref; rref = rref->next)
2682 if (rref->type == REF_SUBSTRING)
2683 break;
2685 if (rref && lref
2686 && gfc_dep_compare_expr (rref->u.ss.start, lref->u.ss.start) < 0)
2688 forall_make_variable_temp (c, pre, post);
2689 need_temp = 0;
2692 return need_temp;
2696 static void
2697 cleanup_forall_symtrees (gfc_code *c)
2699 forall_restore_symtree (c->expr1);
2700 forall_restore_symtree (c->expr2);
2701 free (new_symtree->n.sym);
2702 free (new_symtree);
2706 /* Generate the loops for a FORALL block, specified by FORALL_TMP. BODY
2707 is the contents of the FORALL block/stmt to be iterated. MASK_FLAG
2708 indicates whether we should generate code to test the FORALLs mask
2709 array. OUTER is the loop header to be used for initializing mask
2710 indices.
2712 The generated loop format is:
2713 count = (end - start + step) / step
2714 loopvar = start
2715 while (1)
2717 if (count <=0 )
2718 goto end_of_loop
2719 <body>
2720 loopvar += step
2721 count --
2723 end_of_loop: */
2725 static tree
2726 gfc_trans_forall_loop (forall_info *forall_tmp, tree body,
2727 int mask_flag, stmtblock_t *outer)
2729 int n, nvar;
2730 tree tmp;
2731 tree cond;
2732 stmtblock_t block;
2733 tree exit_label;
2734 tree count;
2735 tree var, start, end, step;
2736 iter_info *iter;
2738 /* Initialize the mask index outside the FORALL nest. */
2739 if (mask_flag && forall_tmp->mask)
2740 gfc_add_modify (outer, forall_tmp->maskindex, gfc_index_zero_node);
2742 iter = forall_tmp->this_loop;
2743 nvar = forall_tmp->nvar;
2744 for (n = 0; n < nvar; n++)
2746 var = iter->var;
2747 start = iter->start;
2748 end = iter->end;
2749 step = iter->step;
2751 exit_label = gfc_build_label_decl (NULL_TREE);
2752 TREE_USED (exit_label) = 1;
2754 /* The loop counter. */
2755 count = gfc_create_var (TREE_TYPE (var), "count");
2757 /* The body of the loop. */
2758 gfc_init_block (&block);
2760 /* The exit condition. */
2761 cond = fold_build2_loc (input_location, LE_EXPR, boolean_type_node,
2762 count, build_int_cst (TREE_TYPE (count), 0));
2763 if (forall_tmp->do_concurrent)
2764 cond = build2 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
2765 build_int_cst (integer_type_node,
2766 annot_expr_ivdep_kind));
2768 tmp = build1_v (GOTO_EXPR, exit_label);
2769 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
2770 cond, tmp, build_empty_stmt (input_location));
2771 gfc_add_expr_to_block (&block, tmp);
2773 /* The main loop body. */
2774 gfc_add_expr_to_block (&block, body);
2776 /* Increment the loop variable. */
2777 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (var), var,
2778 step);
2779 gfc_add_modify (&block, var, tmp);
2781 /* Advance to the next mask element. Only do this for the
2782 innermost loop. */
2783 if (n == 0 && mask_flag && forall_tmp->mask)
2785 tree maskindex = forall_tmp->maskindex;
2786 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
2787 maskindex, gfc_index_one_node);
2788 gfc_add_modify (&block, maskindex, tmp);
2791 /* Decrement the loop counter. */
2792 tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (var), count,
2793 build_int_cst (TREE_TYPE (var), 1));
2794 gfc_add_modify (&block, count, tmp);
2796 body = gfc_finish_block (&block);
2798 /* Loop var initialization. */
2799 gfc_init_block (&block);
2800 gfc_add_modify (&block, var, start);
2803 /* Initialize the loop counter. */
2804 tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (var), step,
2805 start);
2806 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (var), end,
2807 tmp);
2808 tmp = fold_build2_loc (input_location, TRUNC_DIV_EXPR, TREE_TYPE (var),
2809 tmp, step);
2810 gfc_add_modify (&block, count, tmp);
2812 /* The loop expression. */
2813 tmp = build1_v (LOOP_EXPR, body);
2814 gfc_add_expr_to_block (&block, tmp);
2816 /* The exit label. */
2817 tmp = build1_v (LABEL_EXPR, exit_label);
2818 gfc_add_expr_to_block (&block, tmp);
2820 body = gfc_finish_block (&block);
2821 iter = iter->next;
2823 return body;
2827 /* Generate the body and loops according to MASK_FLAG. If MASK_FLAG
2828 is nonzero, the body is controlled by all masks in the forall nest.
2829 Otherwise, the innermost loop is not controlled by it's mask. This
2830 is used for initializing that mask. */
2832 static tree
2833 gfc_trans_nested_forall_loop (forall_info * nested_forall_info, tree body,
2834 int mask_flag)
2836 tree tmp;
2837 stmtblock_t header;
2838 forall_info *forall_tmp;
2839 tree mask, maskindex;
2841 gfc_start_block (&header);
2843 forall_tmp = nested_forall_info;
2844 while (forall_tmp != NULL)
2846 /* Generate body with masks' control. */
2847 if (mask_flag)
2849 mask = forall_tmp->mask;
2850 maskindex = forall_tmp->maskindex;
2852 /* If a mask was specified make the assignment conditional. */
2853 if (mask)
2855 tmp = gfc_build_array_ref (mask, maskindex, NULL);
2856 body = build3_v (COND_EXPR, tmp, body,
2857 build_empty_stmt (input_location));
2860 body = gfc_trans_forall_loop (forall_tmp, body, mask_flag, &header);
2861 forall_tmp = forall_tmp->prev_nest;
2862 mask_flag = 1;
2865 gfc_add_expr_to_block (&header, body);
2866 return gfc_finish_block (&header);
2870 /* Allocate data for holding a temporary array. Returns either a local
2871 temporary array or a pointer variable. */
2873 static tree
2874 gfc_do_allocate (tree bytesize, tree size, tree * pdata, stmtblock_t * pblock,
2875 tree elem_type)
2877 tree tmpvar;
2878 tree type;
2879 tree tmp;
2881 if (INTEGER_CST_P (size))
2882 tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
2883 size, gfc_index_one_node);
2884 else
2885 tmp = NULL_TREE;
2887 type = build_range_type (gfc_array_index_type, gfc_index_zero_node, tmp);
2888 type = build_array_type (elem_type, type);
2889 if (gfc_can_put_var_on_stack (bytesize))
2891 gcc_assert (INTEGER_CST_P (size));
2892 tmpvar = gfc_create_var (type, "temp");
2893 *pdata = NULL_TREE;
2895 else
2897 tmpvar = gfc_create_var (build_pointer_type (type), "temp");
2898 *pdata = convert (pvoid_type_node, tmpvar);
2900 tmp = gfc_call_malloc (pblock, TREE_TYPE (tmpvar), bytesize);
2901 gfc_add_modify (pblock, tmpvar, tmp);
2903 return tmpvar;
2907 /* Generate codes to copy the temporary to the actual lhs. */
2909 static tree
2910 generate_loop_for_temp_to_lhs (gfc_expr *expr, tree tmp1, tree count3,
2911 tree count1, tree wheremask, bool invert)
2913 gfc_ss *lss;
2914 gfc_se lse, rse;
2915 stmtblock_t block, body;
2916 gfc_loopinfo loop1;
2917 tree tmp;
2918 tree wheremaskexpr;
2920 /* Walk the lhs. */
2921 lss = gfc_walk_expr (expr);
2923 if (lss == gfc_ss_terminator)
2925 gfc_start_block (&block);
2927 gfc_init_se (&lse, NULL);
2929 /* Translate the expression. */
2930 gfc_conv_expr (&lse, expr);
2932 /* Form the expression for the temporary. */
2933 tmp = gfc_build_array_ref (tmp1, count1, NULL);
2935 /* Use the scalar assignment as is. */
2936 gfc_add_block_to_block (&block, &lse.pre);
2937 gfc_add_modify (&block, lse.expr, tmp);
2938 gfc_add_block_to_block (&block, &lse.post);
2940 /* Increment the count1. */
2941 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (count1),
2942 count1, gfc_index_one_node);
2943 gfc_add_modify (&block, count1, tmp);
2945 tmp = gfc_finish_block (&block);
2947 else
2949 gfc_start_block (&block);
2951 gfc_init_loopinfo (&loop1);
2952 gfc_init_se (&rse, NULL);
2953 gfc_init_se (&lse, NULL);
2955 /* Associate the lss with the loop. */
2956 gfc_add_ss_to_loop (&loop1, lss);
2958 /* Calculate the bounds of the scalarization. */
2959 gfc_conv_ss_startstride (&loop1);
2960 /* Setup the scalarizing loops. */
2961 gfc_conv_loop_setup (&loop1, &expr->where);
2963 gfc_mark_ss_chain_used (lss, 1);
2965 /* Start the scalarized loop body. */
2966 gfc_start_scalarized_body (&loop1, &body);
2968 /* Setup the gfc_se structures. */
2969 gfc_copy_loopinfo_to_se (&lse, &loop1);
2970 lse.ss = lss;
2972 /* Form the expression of the temporary. */
2973 if (lss != gfc_ss_terminator)
2974 rse.expr = gfc_build_array_ref (tmp1, count1, NULL);
2975 /* Translate expr. */
2976 gfc_conv_expr (&lse, expr);
2978 /* Use the scalar assignment. */
2979 rse.string_length = lse.string_length;
2980 tmp = gfc_trans_scalar_assign (&lse, &rse, expr->ts, false, true, true);
2982 /* Form the mask expression according to the mask tree list. */
2983 if (wheremask)
2985 wheremaskexpr = gfc_build_array_ref (wheremask, count3, NULL);
2986 if (invert)
2987 wheremaskexpr = fold_build1_loc (input_location, TRUTH_NOT_EXPR,
2988 TREE_TYPE (wheremaskexpr),
2989 wheremaskexpr);
2990 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
2991 wheremaskexpr, tmp,
2992 build_empty_stmt (input_location));
2995 gfc_add_expr_to_block (&body, tmp);
2997 /* Increment count1. */
2998 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
2999 count1, gfc_index_one_node);
3000 gfc_add_modify (&body, count1, tmp);
3002 /* Increment count3. */
3003 if (count3)
3005 tmp = fold_build2_loc (input_location, PLUS_EXPR,
3006 gfc_array_index_type, count3,
3007 gfc_index_one_node);
3008 gfc_add_modify (&body, count3, tmp);
3011 /* Generate the copying loops. */
3012 gfc_trans_scalarizing_loops (&loop1, &body);
3013 gfc_add_block_to_block (&block, &loop1.pre);
3014 gfc_add_block_to_block (&block, &loop1.post);
3015 gfc_cleanup_loop (&loop1);
3017 tmp = gfc_finish_block (&block);
3019 return tmp;
3023 /* Generate codes to copy rhs to the temporary. TMP1 is the address of
3024 temporary, LSS and RSS are formed in function compute_inner_temp_size(),
3025 and should not be freed. WHEREMASK is the conditional execution mask
3026 whose sense may be inverted by INVERT. */
3028 static tree
3029 generate_loop_for_rhs_to_temp (gfc_expr *expr2, tree tmp1, tree count3,
3030 tree count1, gfc_ss *lss, gfc_ss *rss,
3031 tree wheremask, bool invert)
3033 stmtblock_t block, body1;
3034 gfc_loopinfo loop;
3035 gfc_se lse;
3036 gfc_se rse;
3037 tree tmp;
3038 tree wheremaskexpr;
3040 gfc_start_block (&block);
3042 gfc_init_se (&rse, NULL);
3043 gfc_init_se (&lse, NULL);
3045 if (lss == gfc_ss_terminator)
3047 gfc_init_block (&body1);
3048 gfc_conv_expr (&rse, expr2);
3049 lse.expr = gfc_build_array_ref (tmp1, count1, NULL);
3051 else
3053 /* Initialize the loop. */
3054 gfc_init_loopinfo (&loop);
3056 /* We may need LSS to determine the shape of the expression. */
3057 gfc_add_ss_to_loop (&loop, lss);
3058 gfc_add_ss_to_loop (&loop, rss);
3060 gfc_conv_ss_startstride (&loop);
3061 gfc_conv_loop_setup (&loop, &expr2->where);
3063 gfc_mark_ss_chain_used (rss, 1);
3064 /* Start the loop body. */
3065 gfc_start_scalarized_body (&loop, &body1);
3067 /* Translate the expression. */
3068 gfc_copy_loopinfo_to_se (&rse, &loop);
3069 rse.ss = rss;
3070 gfc_conv_expr (&rse, expr2);
3072 /* Form the expression of the temporary. */
3073 lse.expr = gfc_build_array_ref (tmp1, count1, NULL);
3076 /* Use the scalar assignment. */
3077 lse.string_length = rse.string_length;
3078 tmp = gfc_trans_scalar_assign (&lse, &rse, expr2->ts, true,
3079 expr2->expr_type == EXPR_VARIABLE, true);
3081 /* Form the mask expression according to the mask tree list. */
3082 if (wheremask)
3084 wheremaskexpr = gfc_build_array_ref (wheremask, count3, NULL);
3085 if (invert)
3086 wheremaskexpr = fold_build1_loc (input_location, TRUTH_NOT_EXPR,
3087 TREE_TYPE (wheremaskexpr),
3088 wheremaskexpr);
3089 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
3090 wheremaskexpr, tmp,
3091 build_empty_stmt (input_location));
3094 gfc_add_expr_to_block (&body1, tmp);
3096 if (lss == gfc_ss_terminator)
3098 gfc_add_block_to_block (&block, &body1);
3100 /* Increment count1. */
3101 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (count1),
3102 count1, gfc_index_one_node);
3103 gfc_add_modify (&block, count1, tmp);
3105 else
3107 /* Increment count1. */
3108 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
3109 count1, gfc_index_one_node);
3110 gfc_add_modify (&body1, count1, tmp);
3112 /* Increment count3. */
3113 if (count3)
3115 tmp = fold_build2_loc (input_location, PLUS_EXPR,
3116 gfc_array_index_type,
3117 count3, gfc_index_one_node);
3118 gfc_add_modify (&body1, count3, tmp);
3121 /* Generate the copying loops. */
3122 gfc_trans_scalarizing_loops (&loop, &body1);
3124 gfc_add_block_to_block (&block, &loop.pre);
3125 gfc_add_block_to_block (&block, &loop.post);
3127 gfc_cleanup_loop (&loop);
3128 /* TODO: Reuse lss and rss when copying temp->lhs. Need to be careful
3129 as tree nodes in SS may not be valid in different scope. */
3132 tmp = gfc_finish_block (&block);
3133 return tmp;
3137 /* Calculate the size of temporary needed in the assignment inside forall.
3138 LSS and RSS are filled in this function. */
3140 static tree
3141 compute_inner_temp_size (gfc_expr *expr1, gfc_expr *expr2,
3142 stmtblock_t * pblock,
3143 gfc_ss **lss, gfc_ss **rss)
3145 gfc_loopinfo loop;
3146 tree size;
3147 int i;
3148 int save_flag;
3149 tree tmp;
3151 *lss = gfc_walk_expr (expr1);
3152 *rss = NULL;
3154 size = gfc_index_one_node;
3155 if (*lss != gfc_ss_terminator)
3157 gfc_init_loopinfo (&loop);
3159 /* Walk the RHS of the expression. */
3160 *rss = gfc_walk_expr (expr2);
3161 if (*rss == gfc_ss_terminator)
3162 /* The rhs is scalar. Add a ss for the expression. */
3163 *rss = gfc_get_scalar_ss (gfc_ss_terminator, expr2);
3165 /* Associate the SS with the loop. */
3166 gfc_add_ss_to_loop (&loop, *lss);
3167 /* We don't actually need to add the rhs at this point, but it might
3168 make guessing the loop bounds a bit easier. */
3169 gfc_add_ss_to_loop (&loop, *rss);
3171 /* We only want the shape of the expression, not rest of the junk
3172 generated by the scalarizer. */
3173 loop.array_parameter = 1;
3175 /* Calculate the bounds of the scalarization. */
3176 save_flag = gfc_option.rtcheck;
3177 gfc_option.rtcheck &= ~GFC_RTCHECK_BOUNDS;
3178 gfc_conv_ss_startstride (&loop);
3179 gfc_option.rtcheck = save_flag;
3180 gfc_conv_loop_setup (&loop, &expr2->where);
3182 /* Figure out how many elements we need. */
3183 for (i = 0; i < loop.dimen; i++)
3185 tmp = fold_build2_loc (input_location, MINUS_EXPR,
3186 gfc_array_index_type,
3187 gfc_index_one_node, loop.from[i]);
3188 tmp = fold_build2_loc (input_location, PLUS_EXPR,
3189 gfc_array_index_type, tmp, loop.to[i]);
3190 size = fold_build2_loc (input_location, MULT_EXPR,
3191 gfc_array_index_type, size, tmp);
3193 gfc_add_block_to_block (pblock, &loop.pre);
3194 size = gfc_evaluate_now (size, pblock);
3195 gfc_add_block_to_block (pblock, &loop.post);
3197 /* TODO: write a function that cleans up a loopinfo without freeing
3198 the SS chains. Currently a NOP. */
3201 return size;
3205 /* Calculate the overall iterator number of the nested forall construct.
3206 This routine actually calculates the number of times the body of the
3207 nested forall specified by NESTED_FORALL_INFO is executed and multiplies
3208 that by the expression INNER_SIZE. The BLOCK argument specifies the
3209 block in which to calculate the result, and the optional INNER_SIZE_BODY
3210 argument contains any statements that need to executed (inside the loop)
3211 to initialize or calculate INNER_SIZE. */
3213 static tree
3214 compute_overall_iter_number (forall_info *nested_forall_info, tree inner_size,
3215 stmtblock_t *inner_size_body, stmtblock_t *block)
3217 forall_info *forall_tmp = nested_forall_info;
3218 tree tmp, number;
3219 stmtblock_t body;
3221 /* We can eliminate the innermost unconditional loops with constant
3222 array bounds. */
3223 if (INTEGER_CST_P (inner_size))
3225 while (forall_tmp
3226 && !forall_tmp->mask
3227 && INTEGER_CST_P (forall_tmp->size))
3229 inner_size = fold_build2_loc (input_location, MULT_EXPR,
3230 gfc_array_index_type,
3231 inner_size, forall_tmp->size);
3232 forall_tmp = forall_tmp->prev_nest;
3235 /* If there are no loops left, we have our constant result. */
3236 if (!forall_tmp)
3237 return inner_size;
3240 /* Otherwise, create a temporary variable to compute the result. */
3241 number = gfc_create_var (gfc_array_index_type, "num");
3242 gfc_add_modify (block, number, gfc_index_zero_node);
3244 gfc_start_block (&body);
3245 if (inner_size_body)
3246 gfc_add_block_to_block (&body, inner_size_body);
3247 if (forall_tmp)
3248 tmp = fold_build2_loc (input_location, PLUS_EXPR,
3249 gfc_array_index_type, number, inner_size);
3250 else
3251 tmp = inner_size;
3252 gfc_add_modify (&body, number, tmp);
3253 tmp = gfc_finish_block (&body);
3255 /* Generate loops. */
3256 if (forall_tmp != NULL)
3257 tmp = gfc_trans_nested_forall_loop (forall_tmp, tmp, 1);
3259 gfc_add_expr_to_block (block, tmp);
3261 return number;
3265 /* Allocate temporary for forall construct. SIZE is the size of temporary
3266 needed. PTEMP1 is returned for space free. */
3268 static tree
3269 allocate_temp_for_forall_nest_1 (tree type, tree size, stmtblock_t * block,
3270 tree * ptemp1)
3272 tree bytesize;
3273 tree unit;
3274 tree tmp;
3276 unit = fold_convert (gfc_array_index_type, TYPE_SIZE_UNIT (type));
3277 if (!integer_onep (unit))
3278 bytesize = fold_build2_loc (input_location, MULT_EXPR,
3279 gfc_array_index_type, size, unit);
3280 else
3281 bytesize = size;
3283 *ptemp1 = NULL;
3284 tmp = gfc_do_allocate (bytesize, size, ptemp1, block, type);
3286 if (*ptemp1)
3287 tmp = build_fold_indirect_ref_loc (input_location, tmp);
3288 return tmp;
3292 /* Allocate temporary for forall construct according to the information in
3293 nested_forall_info. INNER_SIZE is the size of temporary needed in the
3294 assignment inside forall. PTEMP1 is returned for space free. */
3296 static tree
3297 allocate_temp_for_forall_nest (forall_info * nested_forall_info, tree type,
3298 tree inner_size, stmtblock_t * inner_size_body,
3299 stmtblock_t * block, tree * ptemp1)
3301 tree size;
3303 /* Calculate the total size of temporary needed in forall construct. */
3304 size = compute_overall_iter_number (nested_forall_info, inner_size,
3305 inner_size_body, block);
3307 return allocate_temp_for_forall_nest_1 (type, size, block, ptemp1);
3311 /* Handle assignments inside forall which need temporary.
3313 forall (i=start:end:stride; maskexpr)
3314 e<i> = f<i>
3315 end forall
3316 (where e,f<i> are arbitrary expressions possibly involving i
3317 and there is a dependency between e<i> and f<i>)
3318 Translates to:
3319 masktmp(:) = maskexpr(:)
3321 maskindex = 0;
3322 count1 = 0;
3323 num = 0;
3324 for (i = start; i <= end; i += stride)
3325 num += SIZE (f<i>)
3326 count1 = 0;
3327 ALLOCATE (tmp(num))
3328 for (i = start; i <= end; i += stride)
3330 if (masktmp[maskindex++])
3331 tmp[count1++] = f<i>
3333 maskindex = 0;
3334 count1 = 0;
3335 for (i = start; i <= end; i += stride)
3337 if (masktmp[maskindex++])
3338 e<i> = tmp[count1++]
3340 DEALLOCATE (tmp)
3342 static void
3343 gfc_trans_assign_need_temp (gfc_expr * expr1, gfc_expr * expr2,
3344 tree wheremask, bool invert,
3345 forall_info * nested_forall_info,
3346 stmtblock_t * block)
3348 tree type;
3349 tree inner_size;
3350 gfc_ss *lss, *rss;
3351 tree count, count1;
3352 tree tmp, tmp1;
3353 tree ptemp1;
3354 stmtblock_t inner_size_body;
3356 /* Create vars. count1 is the current iterator number of the nested
3357 forall. */
3358 count1 = gfc_create_var (gfc_array_index_type, "count1");
3360 /* Count is the wheremask index. */
3361 if (wheremask)
3363 count = gfc_create_var (gfc_array_index_type, "count");
3364 gfc_add_modify (block, count, gfc_index_zero_node);
3366 else
3367 count = NULL;
3369 /* Initialize count1. */
3370 gfc_add_modify (block, count1, gfc_index_zero_node);
3372 /* Calculate the size of temporary needed in the assignment. Return loop, lss
3373 and rss which are used in function generate_loop_for_rhs_to_temp(). */
3374 gfc_init_block (&inner_size_body);
3375 inner_size = compute_inner_temp_size (expr1, expr2, &inner_size_body,
3376 &lss, &rss);
3378 /* The type of LHS. Used in function allocate_temp_for_forall_nest */
3379 if (expr1->ts.type == BT_CHARACTER && expr1->ts.u.cl->length)
3381 if (!expr1->ts.u.cl->backend_decl)
3383 gfc_se tse;
3384 gfc_init_se (&tse, NULL);
3385 gfc_conv_expr (&tse, expr1->ts.u.cl->length);
3386 expr1->ts.u.cl->backend_decl = tse.expr;
3388 type = gfc_get_character_type_len (gfc_default_character_kind,
3389 expr1->ts.u.cl->backend_decl);
3391 else
3392 type = gfc_typenode_for_spec (&expr1->ts);
3394 /* Allocate temporary for nested forall construct according to the
3395 information in nested_forall_info and inner_size. */
3396 tmp1 = allocate_temp_for_forall_nest (nested_forall_info, type, inner_size,
3397 &inner_size_body, block, &ptemp1);
3399 /* Generate codes to copy rhs to the temporary . */
3400 tmp = generate_loop_for_rhs_to_temp (expr2, tmp1, count, count1, lss, rss,
3401 wheremask, invert);
3403 /* Generate body and loops according to the information in
3404 nested_forall_info. */
3405 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
3406 gfc_add_expr_to_block (block, tmp);
3408 /* Reset count1. */
3409 gfc_add_modify (block, count1, gfc_index_zero_node);
3411 /* Reset count. */
3412 if (wheremask)
3413 gfc_add_modify (block, count, gfc_index_zero_node);
3415 /* Generate codes to copy the temporary to lhs. */
3416 tmp = generate_loop_for_temp_to_lhs (expr1, tmp1, count, count1,
3417 wheremask, invert);
3419 /* Generate body and loops according to the information in
3420 nested_forall_info. */
3421 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
3422 gfc_add_expr_to_block (block, tmp);
3424 if (ptemp1)
3426 /* Free the temporary. */
3427 tmp = gfc_call_free (ptemp1);
3428 gfc_add_expr_to_block (block, tmp);
3433 /* Translate pointer assignment inside FORALL which need temporary. */
3435 static void
3436 gfc_trans_pointer_assign_need_temp (gfc_expr * expr1, gfc_expr * expr2,
3437 forall_info * nested_forall_info,
3438 stmtblock_t * block)
3440 tree type;
3441 tree inner_size;
3442 gfc_ss *lss, *rss;
3443 gfc_se lse;
3444 gfc_se rse;
3445 gfc_array_info *info;
3446 gfc_loopinfo loop;
3447 tree desc;
3448 tree parm;
3449 tree parmtype;
3450 stmtblock_t body;
3451 tree count;
3452 tree tmp, tmp1, ptemp1;
3454 count = gfc_create_var (gfc_array_index_type, "count");
3455 gfc_add_modify (block, count, gfc_index_zero_node);
3457 inner_size = gfc_index_one_node;
3458 lss = gfc_walk_expr (expr1);
3459 rss = gfc_walk_expr (expr2);
3460 if (lss == gfc_ss_terminator)
3462 type = gfc_typenode_for_spec (&expr1->ts);
3463 type = build_pointer_type (type);
3465 /* Allocate temporary for nested forall construct according to the
3466 information in nested_forall_info and inner_size. */
3467 tmp1 = allocate_temp_for_forall_nest (nested_forall_info, type,
3468 inner_size, NULL, block, &ptemp1);
3469 gfc_start_block (&body);
3470 gfc_init_se (&lse, NULL);
3471 lse.expr = gfc_build_array_ref (tmp1, count, NULL);
3472 gfc_init_se (&rse, NULL);
3473 rse.want_pointer = 1;
3474 gfc_conv_expr (&rse, expr2);
3475 gfc_add_block_to_block (&body, &rse.pre);
3476 gfc_add_modify (&body, lse.expr,
3477 fold_convert (TREE_TYPE (lse.expr), rse.expr));
3478 gfc_add_block_to_block (&body, &rse.post);
3480 /* Increment count. */
3481 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
3482 count, gfc_index_one_node);
3483 gfc_add_modify (&body, count, tmp);
3485 tmp = gfc_finish_block (&body);
3487 /* Generate body and loops according to the information in
3488 nested_forall_info. */
3489 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
3490 gfc_add_expr_to_block (block, tmp);
3492 /* Reset count. */
3493 gfc_add_modify (block, count, gfc_index_zero_node);
3495 gfc_start_block (&body);
3496 gfc_init_se (&lse, NULL);
3497 gfc_init_se (&rse, NULL);
3498 rse.expr = gfc_build_array_ref (tmp1, count, NULL);
3499 lse.want_pointer = 1;
3500 gfc_conv_expr (&lse, expr1);
3501 gfc_add_block_to_block (&body, &lse.pre);
3502 gfc_add_modify (&body, lse.expr, rse.expr);
3503 gfc_add_block_to_block (&body, &lse.post);
3504 /* Increment count. */
3505 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
3506 count, gfc_index_one_node);
3507 gfc_add_modify (&body, count, tmp);
3508 tmp = gfc_finish_block (&body);
3510 /* Generate body and loops according to the information in
3511 nested_forall_info. */
3512 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
3513 gfc_add_expr_to_block (block, tmp);
3515 else
3517 gfc_init_loopinfo (&loop);
3519 /* Associate the SS with the loop. */
3520 gfc_add_ss_to_loop (&loop, rss);
3522 /* Setup the scalarizing loops and bounds. */
3523 gfc_conv_ss_startstride (&loop);
3525 gfc_conv_loop_setup (&loop, &expr2->where);
3527 info = &rss->info->data.array;
3528 desc = info->descriptor;
3530 /* Make a new descriptor. */
3531 parmtype = gfc_get_element_type (TREE_TYPE (desc));
3532 parmtype = gfc_get_array_type_bounds (parmtype, loop.dimen, 0,
3533 loop.from, loop.to, 1,
3534 GFC_ARRAY_UNKNOWN, true);
3536 /* Allocate temporary for nested forall construct. */
3537 tmp1 = allocate_temp_for_forall_nest (nested_forall_info, parmtype,
3538 inner_size, NULL, block, &ptemp1);
3539 gfc_start_block (&body);
3540 gfc_init_se (&lse, NULL);
3541 lse.expr = gfc_build_array_ref (tmp1, count, NULL);
3542 lse.direct_byref = 1;
3543 gfc_conv_expr_descriptor (&lse, expr2);
3545 gfc_add_block_to_block (&body, &lse.pre);
3546 gfc_add_block_to_block (&body, &lse.post);
3548 /* Increment count. */
3549 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
3550 count, gfc_index_one_node);
3551 gfc_add_modify (&body, count, tmp);
3553 tmp = gfc_finish_block (&body);
3555 /* Generate body and loops according to the information in
3556 nested_forall_info. */
3557 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
3558 gfc_add_expr_to_block (block, tmp);
3560 /* Reset count. */
3561 gfc_add_modify (block, count, gfc_index_zero_node);
3563 parm = gfc_build_array_ref (tmp1, count, NULL);
3564 gfc_init_se (&lse, NULL);
3565 gfc_conv_expr_descriptor (&lse, expr1);
3566 gfc_add_modify (&lse.pre, lse.expr, parm);
3567 gfc_start_block (&body);
3568 gfc_add_block_to_block (&body, &lse.pre);
3569 gfc_add_block_to_block (&body, &lse.post);
3571 /* Increment count. */
3572 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
3573 count, gfc_index_one_node);
3574 gfc_add_modify (&body, count, tmp);
3576 tmp = gfc_finish_block (&body);
3578 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
3579 gfc_add_expr_to_block (block, tmp);
3581 /* Free the temporary. */
3582 if (ptemp1)
3584 tmp = gfc_call_free (ptemp1);
3585 gfc_add_expr_to_block (block, tmp);
3590 /* FORALL and WHERE statements are really nasty, especially when you nest
3591 them. All the rhs of a forall assignment must be evaluated before the
3592 actual assignments are performed. Presumably this also applies to all the
3593 assignments in an inner where statement. */
3595 /* Generate code for a FORALL statement. Any temporaries are allocated as a
3596 linear array, relying on the fact that we process in the same order in all
3597 loops.
3599 forall (i=start:end:stride; maskexpr)
3600 e<i> = f<i>
3601 g<i> = h<i>
3602 end forall
3603 (where e,f,g,h<i> are arbitrary expressions possibly involving i)
3604 Translates to:
3605 count = ((end + 1 - start) / stride)
3606 masktmp(:) = maskexpr(:)
3608 maskindex = 0;
3609 for (i = start; i <= end; i += stride)
3611 if (masktmp[maskindex++])
3612 e<i> = f<i>
3614 maskindex = 0;
3615 for (i = start; i <= end; i += stride)
3617 if (masktmp[maskindex++])
3618 g<i> = h<i>
3621 Note that this code only works when there are no dependencies.
3622 Forall loop with array assignments and data dependencies are a real pain,
3623 because the size of the temporary cannot always be determined before the
3624 loop is executed. This problem is compounded by the presence of nested
3625 FORALL constructs.
3628 static tree
3629 gfc_trans_forall_1 (gfc_code * code, forall_info * nested_forall_info)
3631 stmtblock_t pre;
3632 stmtblock_t post;
3633 stmtblock_t block;
3634 stmtblock_t body;
3635 tree *var;
3636 tree *start;
3637 tree *end;
3638 tree *step;
3639 gfc_expr **varexpr;
3640 tree tmp;
3641 tree assign;
3642 tree size;
3643 tree maskindex;
3644 tree mask;
3645 tree pmask;
3646 tree cycle_label = NULL_TREE;
3647 int n;
3648 int nvar;
3649 int need_temp;
3650 gfc_forall_iterator *fa;
3651 gfc_se se;
3652 gfc_code *c;
3653 gfc_saved_var *saved_vars;
3654 iter_info *this_forall;
3655 forall_info *info;
3656 bool need_mask;
3658 /* Do nothing if the mask is false. */
3659 if (code->expr1
3660 && code->expr1->expr_type == EXPR_CONSTANT
3661 && !code->expr1->value.logical)
3662 return build_empty_stmt (input_location);
3664 n = 0;
3665 /* Count the FORALL index number. */
3666 for (fa = code->ext.forall_iterator; fa; fa = fa->next)
3667 n++;
3668 nvar = n;
3670 /* Allocate the space for var, start, end, step, varexpr. */
3671 var = XCNEWVEC (tree, nvar);
3672 start = XCNEWVEC (tree, nvar);
3673 end = XCNEWVEC (tree, nvar);
3674 step = XCNEWVEC (tree, nvar);
3675 varexpr = XCNEWVEC (gfc_expr *, nvar);
3676 saved_vars = XCNEWVEC (gfc_saved_var, nvar);
3678 /* Allocate the space for info. */
3679 info = XCNEW (forall_info);
3681 gfc_start_block (&pre);
3682 gfc_init_block (&post);
3683 gfc_init_block (&block);
3685 n = 0;
3686 for (fa = code->ext.forall_iterator; fa; fa = fa->next)
3688 gfc_symbol *sym = fa->var->symtree->n.sym;
3690 /* Allocate space for this_forall. */
3691 this_forall = XCNEW (iter_info);
3693 /* Create a temporary variable for the FORALL index. */
3694 tmp = gfc_typenode_for_spec (&sym->ts);
3695 var[n] = gfc_create_var (tmp, sym->name);
3696 gfc_shadow_sym (sym, var[n], &saved_vars[n]);
3698 /* Record it in this_forall. */
3699 this_forall->var = var[n];
3701 /* Replace the index symbol's backend_decl with the temporary decl. */
3702 sym->backend_decl = var[n];
3704 /* Work out the start, end and stride for the loop. */
3705 gfc_init_se (&se, NULL);
3706 gfc_conv_expr_val (&se, fa->start);
3707 /* Record it in this_forall. */
3708 this_forall->start = se.expr;
3709 gfc_add_block_to_block (&block, &se.pre);
3710 start[n] = se.expr;
3712 gfc_init_se (&se, NULL);
3713 gfc_conv_expr_val (&se, fa->end);
3714 /* Record it in this_forall. */
3715 this_forall->end = se.expr;
3716 gfc_make_safe_expr (&se);
3717 gfc_add_block_to_block (&block, &se.pre);
3718 end[n] = se.expr;
3720 gfc_init_se (&se, NULL);
3721 gfc_conv_expr_val (&se, fa->stride);
3722 /* Record it in this_forall. */
3723 this_forall->step = se.expr;
3724 gfc_make_safe_expr (&se);
3725 gfc_add_block_to_block (&block, &se.pre);
3726 step[n] = se.expr;
3728 /* Set the NEXT field of this_forall to NULL. */
3729 this_forall->next = NULL;
3730 /* Link this_forall to the info construct. */
3731 if (info->this_loop)
3733 iter_info *iter_tmp = info->this_loop;
3734 while (iter_tmp->next != NULL)
3735 iter_tmp = iter_tmp->next;
3736 iter_tmp->next = this_forall;
3738 else
3739 info->this_loop = this_forall;
3741 n++;
3743 nvar = n;
3745 /* Calculate the size needed for the current forall level. */
3746 size = gfc_index_one_node;
3747 for (n = 0; n < nvar; n++)
3749 /* size = (end + step - start) / step. */
3750 tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (start[n]),
3751 step[n], start[n]);
3752 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (end[n]),
3753 end[n], tmp);
3754 tmp = fold_build2_loc (input_location, FLOOR_DIV_EXPR, TREE_TYPE (tmp),
3755 tmp, step[n]);
3756 tmp = convert (gfc_array_index_type, tmp);
3758 size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
3759 size, tmp);
3762 /* Record the nvar and size of current forall level. */
3763 info->nvar = nvar;
3764 info->size = size;
3766 if (code->expr1)
3768 /* If the mask is .true., consider the FORALL unconditional. */
3769 if (code->expr1->expr_type == EXPR_CONSTANT
3770 && code->expr1->value.logical)
3771 need_mask = false;
3772 else
3773 need_mask = true;
3775 else
3776 need_mask = false;
3778 /* First we need to allocate the mask. */
3779 if (need_mask)
3781 /* As the mask array can be very big, prefer compact boolean types. */
3782 tree mask_type = gfc_get_logical_type (gfc_logical_kinds[0].kind);
3783 mask = allocate_temp_for_forall_nest (nested_forall_info, mask_type,
3784 size, NULL, &block, &pmask);
3785 maskindex = gfc_create_var_np (gfc_array_index_type, "mi");
3787 /* Record them in the info structure. */
3788 info->maskindex = maskindex;
3789 info->mask = mask;
3791 else
3793 /* No mask was specified. */
3794 maskindex = NULL_TREE;
3795 mask = pmask = NULL_TREE;
3798 /* Link the current forall level to nested_forall_info. */
3799 info->prev_nest = nested_forall_info;
3800 nested_forall_info = info;
3802 /* Copy the mask into a temporary variable if required.
3803 For now we assume a mask temporary is needed. */
3804 if (need_mask)
3806 /* As the mask array can be very big, prefer compact boolean types. */
3807 tree mask_type = gfc_get_logical_type (gfc_logical_kinds[0].kind);
3809 gfc_add_modify (&block, maskindex, gfc_index_zero_node);
3811 /* Start of mask assignment loop body. */
3812 gfc_start_block (&body);
3814 /* Evaluate the mask expression. */
3815 gfc_init_se (&se, NULL);
3816 gfc_conv_expr_val (&se, code->expr1);
3817 gfc_add_block_to_block (&body, &se.pre);
3819 /* Store the mask. */
3820 se.expr = convert (mask_type, se.expr);
3822 tmp = gfc_build_array_ref (mask, maskindex, NULL);
3823 gfc_add_modify (&body, tmp, se.expr);
3825 /* Advance to the next mask element. */
3826 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
3827 maskindex, gfc_index_one_node);
3828 gfc_add_modify (&body, maskindex, tmp);
3830 /* Generate the loops. */
3831 tmp = gfc_finish_block (&body);
3832 tmp = gfc_trans_nested_forall_loop (info, tmp, 0);
3833 gfc_add_expr_to_block (&block, tmp);
3836 if (code->op == EXEC_DO_CONCURRENT)
3838 gfc_init_block (&body);
3839 cycle_label = gfc_build_label_decl (NULL_TREE);
3840 code->cycle_label = cycle_label;
3841 tmp = gfc_trans_code (code->block->next);
3842 gfc_add_expr_to_block (&body, tmp);
3844 if (TREE_USED (cycle_label))
3846 tmp = build1_v (LABEL_EXPR, cycle_label);
3847 gfc_add_expr_to_block (&body, tmp);
3850 tmp = gfc_finish_block (&body);
3851 nested_forall_info->do_concurrent = true;
3852 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
3853 gfc_add_expr_to_block (&block, tmp);
3854 goto done;
3857 c = code->block->next;
3859 /* TODO: loop merging in FORALL statements. */
3860 /* Now that we've got a copy of the mask, generate the assignment loops. */
3861 while (c)
3863 switch (c->op)
3865 case EXEC_ASSIGN:
3866 /* A scalar or array assignment. DO the simple check for
3867 lhs to rhs dependencies. These make a temporary for the
3868 rhs and form a second forall block to copy to variable. */
3869 need_temp = check_forall_dependencies(c, &pre, &post);
3871 /* Temporaries due to array assignment data dependencies introduce
3872 no end of problems. */
3873 if (need_temp)
3874 gfc_trans_assign_need_temp (c->expr1, c->expr2, NULL, false,
3875 nested_forall_info, &block);
3876 else
3878 /* Use the normal assignment copying routines. */
3879 assign = gfc_trans_assignment (c->expr1, c->expr2, false, true);
3881 /* Generate body and loops. */
3882 tmp = gfc_trans_nested_forall_loop (nested_forall_info,
3883 assign, 1);
3884 gfc_add_expr_to_block (&block, tmp);
3887 /* Cleanup any temporary symtrees that have been made to deal
3888 with dependencies. */
3889 if (new_symtree)
3890 cleanup_forall_symtrees (c);
3892 break;
3894 case EXEC_WHERE:
3895 /* Translate WHERE or WHERE construct nested in FORALL. */
3896 gfc_trans_where_2 (c, NULL, false, nested_forall_info, &block);
3897 break;
3899 /* Pointer assignment inside FORALL. */
3900 case EXEC_POINTER_ASSIGN:
3901 need_temp = gfc_check_dependency (c->expr1, c->expr2, 0);
3902 if (need_temp)
3903 gfc_trans_pointer_assign_need_temp (c->expr1, c->expr2,
3904 nested_forall_info, &block);
3905 else
3907 /* Use the normal assignment copying routines. */
3908 assign = gfc_trans_pointer_assignment (c->expr1, c->expr2);
3910 /* Generate body and loops. */
3911 tmp = gfc_trans_nested_forall_loop (nested_forall_info,
3912 assign, 1);
3913 gfc_add_expr_to_block (&block, tmp);
3915 break;
3917 case EXEC_FORALL:
3918 tmp = gfc_trans_forall_1 (c, nested_forall_info);
3919 gfc_add_expr_to_block (&block, tmp);
3920 break;
3922 /* Explicit subroutine calls are prevented by the frontend but interface
3923 assignments can legitimately produce them. */
3924 case EXEC_ASSIGN_CALL:
3925 assign = gfc_trans_call (c, true, NULL_TREE, NULL_TREE, false);
3926 tmp = gfc_trans_nested_forall_loop (nested_forall_info, assign, 1);
3927 gfc_add_expr_to_block (&block, tmp);
3928 break;
3930 default:
3931 gcc_unreachable ();
3934 c = c->next;
3937 done:
3938 /* Restore the original index variables. */
3939 for (fa = code->ext.forall_iterator, n = 0; fa; fa = fa->next, n++)
3940 gfc_restore_sym (fa->var->symtree->n.sym, &saved_vars[n]);
3942 /* Free the space for var, start, end, step, varexpr. */
3943 free (var);
3944 free (start);
3945 free (end);
3946 free (step);
3947 free (varexpr);
3948 free (saved_vars);
3950 for (this_forall = info->this_loop; this_forall;)
3952 iter_info *next = this_forall->next;
3953 free (this_forall);
3954 this_forall = next;
3957 /* Free the space for this forall_info. */
3958 free (info);
3960 if (pmask)
3962 /* Free the temporary for the mask. */
3963 tmp = gfc_call_free (pmask);
3964 gfc_add_expr_to_block (&block, tmp);
3966 if (maskindex)
3967 pushdecl (maskindex);
3969 gfc_add_block_to_block (&pre, &block);
3970 gfc_add_block_to_block (&pre, &post);
3972 return gfc_finish_block (&pre);
3976 /* Translate the FORALL statement or construct. */
3978 tree gfc_trans_forall (gfc_code * code)
3980 return gfc_trans_forall_1 (code, NULL);
3984 /* Translate the DO CONCURRENT construct. */
3986 tree gfc_trans_do_concurrent (gfc_code * code)
3988 return gfc_trans_forall_1 (code, NULL);
3992 /* Evaluate the WHERE mask expression, copy its value to a temporary.
3993 If the WHERE construct is nested in FORALL, compute the overall temporary
3994 needed by the WHERE mask expression multiplied by the iterator number of
3995 the nested forall.
3996 ME is the WHERE mask expression.
3997 MASK is the current execution mask upon input, whose sense may or may
3998 not be inverted as specified by the INVERT argument.
3999 CMASK is the updated execution mask on output, or NULL if not required.
4000 PMASK is the pending execution mask on output, or NULL if not required.
4001 BLOCK is the block in which to place the condition evaluation loops. */
4003 static void
4004 gfc_evaluate_where_mask (gfc_expr * me, forall_info * nested_forall_info,
4005 tree mask, bool invert, tree cmask, tree pmask,
4006 tree mask_type, stmtblock_t * block)
4008 tree tmp, tmp1;
4009 gfc_ss *lss, *rss;
4010 gfc_loopinfo loop;
4011 stmtblock_t body, body1;
4012 tree count, cond, mtmp;
4013 gfc_se lse, rse;
4015 gfc_init_loopinfo (&loop);
4017 lss = gfc_walk_expr (me);
4018 rss = gfc_walk_expr (me);
4020 /* Variable to index the temporary. */
4021 count = gfc_create_var (gfc_array_index_type, "count");
4022 /* Initialize count. */
4023 gfc_add_modify (block, count, gfc_index_zero_node);
4025 gfc_start_block (&body);
4027 gfc_init_se (&rse, NULL);
4028 gfc_init_se (&lse, NULL);
4030 if (lss == gfc_ss_terminator)
4032 gfc_init_block (&body1);
4034 else
4036 /* Initialize the loop. */
4037 gfc_init_loopinfo (&loop);
4039 /* We may need LSS to determine the shape of the expression. */
4040 gfc_add_ss_to_loop (&loop, lss);
4041 gfc_add_ss_to_loop (&loop, rss);
4043 gfc_conv_ss_startstride (&loop);
4044 gfc_conv_loop_setup (&loop, &me->where);
4046 gfc_mark_ss_chain_used (rss, 1);
4047 /* Start the loop body. */
4048 gfc_start_scalarized_body (&loop, &body1);
4050 /* Translate the expression. */
4051 gfc_copy_loopinfo_to_se (&rse, &loop);
4052 rse.ss = rss;
4053 gfc_conv_expr (&rse, me);
4056 /* Variable to evaluate mask condition. */
4057 cond = gfc_create_var (mask_type, "cond");
4058 if (mask && (cmask || pmask))
4059 mtmp = gfc_create_var (mask_type, "mask");
4060 else mtmp = NULL_TREE;
4062 gfc_add_block_to_block (&body1, &lse.pre);
4063 gfc_add_block_to_block (&body1, &rse.pre);
4065 gfc_add_modify (&body1, cond, fold_convert (mask_type, rse.expr));
4067 if (mask && (cmask || pmask))
4069 tmp = gfc_build_array_ref (mask, count, NULL);
4070 if (invert)
4071 tmp = fold_build1_loc (input_location, TRUTH_NOT_EXPR, mask_type, tmp);
4072 gfc_add_modify (&body1, mtmp, tmp);
4075 if (cmask)
4077 tmp1 = gfc_build_array_ref (cmask, count, NULL);
4078 tmp = cond;
4079 if (mask)
4080 tmp = fold_build2_loc (input_location, TRUTH_AND_EXPR, mask_type,
4081 mtmp, tmp);
4082 gfc_add_modify (&body1, tmp1, tmp);
4085 if (pmask)
4087 tmp1 = gfc_build_array_ref (pmask, count, NULL);
4088 tmp = fold_build1_loc (input_location, TRUTH_NOT_EXPR, mask_type, cond);
4089 if (mask)
4090 tmp = fold_build2_loc (input_location, TRUTH_AND_EXPR, mask_type, mtmp,
4091 tmp);
4092 gfc_add_modify (&body1, tmp1, tmp);
4095 gfc_add_block_to_block (&body1, &lse.post);
4096 gfc_add_block_to_block (&body1, &rse.post);
4098 if (lss == gfc_ss_terminator)
4100 gfc_add_block_to_block (&body, &body1);
4102 else
4104 /* Increment count. */
4105 tmp1 = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
4106 count, gfc_index_one_node);
4107 gfc_add_modify (&body1, count, tmp1);
4109 /* Generate the copying loops. */
4110 gfc_trans_scalarizing_loops (&loop, &body1);
4112 gfc_add_block_to_block (&body, &loop.pre);
4113 gfc_add_block_to_block (&body, &loop.post);
4115 gfc_cleanup_loop (&loop);
4116 /* TODO: Reuse lss and rss when copying temp->lhs. Need to be careful
4117 as tree nodes in SS may not be valid in different scope. */
4120 tmp1 = gfc_finish_block (&body);
4121 /* If the WHERE construct is inside FORALL, fill the full temporary. */
4122 if (nested_forall_info != NULL)
4123 tmp1 = gfc_trans_nested_forall_loop (nested_forall_info, tmp1, 1);
4125 gfc_add_expr_to_block (block, tmp1);
4129 /* Translate an assignment statement in a WHERE statement or construct
4130 statement. The MASK expression is used to control which elements
4131 of EXPR1 shall be assigned. The sense of MASK is specified by
4132 INVERT. */
4134 static tree
4135 gfc_trans_where_assign (gfc_expr *expr1, gfc_expr *expr2,
4136 tree mask, bool invert,
4137 tree count1, tree count2,
4138 gfc_code *cnext)
4140 gfc_se lse;
4141 gfc_se rse;
4142 gfc_ss *lss;
4143 gfc_ss *lss_section;
4144 gfc_ss *rss;
4146 gfc_loopinfo loop;
4147 tree tmp;
4148 stmtblock_t block;
4149 stmtblock_t body;
4150 tree index, maskexpr;
4152 /* A defined assignment. */
4153 if (cnext && cnext->resolved_sym)
4154 return gfc_trans_call (cnext, true, mask, count1, invert);
4156 #if 0
4157 /* TODO: handle this special case.
4158 Special case a single function returning an array. */
4159 if (expr2->expr_type == EXPR_FUNCTION && expr2->rank > 0)
4161 tmp = gfc_trans_arrayfunc_assign (expr1, expr2);
4162 if (tmp)
4163 return tmp;
4165 #endif
4167 /* Assignment of the form lhs = rhs. */
4168 gfc_start_block (&block);
4170 gfc_init_se (&lse, NULL);
4171 gfc_init_se (&rse, NULL);
4173 /* Walk the lhs. */
4174 lss = gfc_walk_expr (expr1);
4175 rss = NULL;
4177 /* In each where-assign-stmt, the mask-expr and the variable being
4178 defined shall be arrays of the same shape. */
4179 gcc_assert (lss != gfc_ss_terminator);
4181 /* The assignment needs scalarization. */
4182 lss_section = lss;
4184 /* Find a non-scalar SS from the lhs. */
4185 while (lss_section != gfc_ss_terminator
4186 && lss_section->info->type != GFC_SS_SECTION)
4187 lss_section = lss_section->next;
4189 gcc_assert (lss_section != gfc_ss_terminator);
4191 /* Initialize the scalarizer. */
4192 gfc_init_loopinfo (&loop);
4194 /* Walk the rhs. */
4195 rss = gfc_walk_expr (expr2);
4196 if (rss == gfc_ss_terminator)
4198 /* The rhs is scalar. Add a ss for the expression. */
4199 rss = gfc_get_scalar_ss (gfc_ss_terminator, expr2);
4200 rss->info->where = 1;
4203 /* Associate the SS with the loop. */
4204 gfc_add_ss_to_loop (&loop, lss);
4205 gfc_add_ss_to_loop (&loop, rss);
4207 /* Calculate the bounds of the scalarization. */
4208 gfc_conv_ss_startstride (&loop);
4210 /* Resolve any data dependencies in the statement. */
4211 gfc_conv_resolve_dependencies (&loop, lss_section, rss);
4213 /* Setup the scalarizing loops. */
4214 gfc_conv_loop_setup (&loop, &expr2->where);
4216 /* Setup the gfc_se structures. */
4217 gfc_copy_loopinfo_to_se (&lse, &loop);
4218 gfc_copy_loopinfo_to_se (&rse, &loop);
4220 rse.ss = rss;
4221 gfc_mark_ss_chain_used (rss, 1);
4222 if (loop.temp_ss == NULL)
4224 lse.ss = lss;
4225 gfc_mark_ss_chain_used (lss, 1);
4227 else
4229 lse.ss = loop.temp_ss;
4230 gfc_mark_ss_chain_used (lss, 3);
4231 gfc_mark_ss_chain_used (loop.temp_ss, 3);
4234 /* Start the scalarized loop body. */
4235 gfc_start_scalarized_body (&loop, &body);
4237 /* Translate the expression. */
4238 gfc_conv_expr (&rse, expr2);
4239 if (lss != gfc_ss_terminator && loop.temp_ss != NULL)
4240 gfc_conv_tmp_array_ref (&lse);
4241 else
4242 gfc_conv_expr (&lse, expr1);
4244 /* Form the mask expression according to the mask. */
4245 index = count1;
4246 maskexpr = gfc_build_array_ref (mask, index, NULL);
4247 if (invert)
4248 maskexpr = fold_build1_loc (input_location, TRUTH_NOT_EXPR,
4249 TREE_TYPE (maskexpr), maskexpr);
4251 /* Use the scalar assignment as is. */
4252 tmp = gfc_trans_scalar_assign (&lse, &rse, expr1->ts,
4253 loop.temp_ss != NULL, false, true);
4255 tmp = build3_v (COND_EXPR, maskexpr, tmp, build_empty_stmt (input_location));
4257 gfc_add_expr_to_block (&body, tmp);
4259 if (lss == gfc_ss_terminator)
4261 /* Increment count1. */
4262 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
4263 count1, gfc_index_one_node);
4264 gfc_add_modify (&body, count1, tmp);
4266 /* Use the scalar assignment as is. */
4267 gfc_add_block_to_block (&block, &body);
4269 else
4271 gcc_assert (lse.ss == gfc_ss_terminator
4272 && rse.ss == gfc_ss_terminator);
4274 if (loop.temp_ss != NULL)
4276 /* Increment count1 before finish the main body of a scalarized
4277 expression. */
4278 tmp = fold_build2_loc (input_location, PLUS_EXPR,
4279 gfc_array_index_type, count1, gfc_index_one_node);
4280 gfc_add_modify (&body, count1, tmp);
4281 gfc_trans_scalarized_loop_boundary (&loop, &body);
4283 /* We need to copy the temporary to the actual lhs. */
4284 gfc_init_se (&lse, NULL);
4285 gfc_init_se (&rse, NULL);
4286 gfc_copy_loopinfo_to_se (&lse, &loop);
4287 gfc_copy_loopinfo_to_se (&rse, &loop);
4289 rse.ss = loop.temp_ss;
4290 lse.ss = lss;
4292 gfc_conv_tmp_array_ref (&rse);
4293 gfc_conv_expr (&lse, expr1);
4295 gcc_assert (lse.ss == gfc_ss_terminator
4296 && rse.ss == gfc_ss_terminator);
4298 /* Form the mask expression according to the mask tree list. */
4299 index = count2;
4300 maskexpr = gfc_build_array_ref (mask, index, NULL);
4301 if (invert)
4302 maskexpr = fold_build1_loc (input_location, TRUTH_NOT_EXPR,
4303 TREE_TYPE (maskexpr), maskexpr);
4305 /* Use the scalar assignment as is. */
4306 tmp = gfc_trans_scalar_assign (&lse, &rse, expr1->ts, false, false,
4307 true);
4308 tmp = build3_v (COND_EXPR, maskexpr, tmp,
4309 build_empty_stmt (input_location));
4310 gfc_add_expr_to_block (&body, tmp);
4312 /* Increment count2. */
4313 tmp = fold_build2_loc (input_location, PLUS_EXPR,
4314 gfc_array_index_type, count2,
4315 gfc_index_one_node);
4316 gfc_add_modify (&body, count2, tmp);
4318 else
4320 /* Increment count1. */
4321 tmp = fold_build2_loc (input_location, PLUS_EXPR,
4322 gfc_array_index_type, count1,
4323 gfc_index_one_node);
4324 gfc_add_modify (&body, count1, tmp);
4327 /* Generate the copying loops. */
4328 gfc_trans_scalarizing_loops (&loop, &body);
4330 /* Wrap the whole thing up. */
4331 gfc_add_block_to_block (&block, &loop.pre);
4332 gfc_add_block_to_block (&block, &loop.post);
4333 gfc_cleanup_loop (&loop);
4336 return gfc_finish_block (&block);
4340 /* Translate the WHERE construct or statement.
4341 This function can be called iteratively to translate the nested WHERE
4342 construct or statement.
4343 MASK is the control mask. */
4345 static void
4346 gfc_trans_where_2 (gfc_code * code, tree mask, bool invert,
4347 forall_info * nested_forall_info, stmtblock_t * block)
4349 stmtblock_t inner_size_body;
4350 tree inner_size, size;
4351 gfc_ss *lss, *rss;
4352 tree mask_type;
4353 gfc_expr *expr1;
4354 gfc_expr *expr2;
4355 gfc_code *cblock;
4356 gfc_code *cnext;
4357 tree tmp;
4358 tree cond;
4359 tree count1, count2;
4360 bool need_cmask;
4361 bool need_pmask;
4362 int need_temp;
4363 tree pcmask = NULL_TREE;
4364 tree ppmask = NULL_TREE;
4365 tree cmask = NULL_TREE;
4366 tree pmask = NULL_TREE;
4367 gfc_actual_arglist *arg;
4369 /* the WHERE statement or the WHERE construct statement. */
4370 cblock = code->block;
4372 /* As the mask array can be very big, prefer compact boolean types. */
4373 mask_type = gfc_get_logical_type (gfc_logical_kinds[0].kind);
4375 /* Determine which temporary masks are needed. */
4376 if (!cblock->block)
4378 /* One clause: No ELSEWHEREs. */
4379 need_cmask = (cblock->next != 0);
4380 need_pmask = false;
4382 else if (cblock->block->block)
4384 /* Three or more clauses: Conditional ELSEWHEREs. */
4385 need_cmask = true;
4386 need_pmask = true;
4388 else if (cblock->next)
4390 /* Two clauses, the first non-empty. */
4391 need_cmask = true;
4392 need_pmask = (mask != NULL_TREE
4393 && cblock->block->next != 0);
4395 else if (!cblock->block->next)
4397 /* Two clauses, both empty. */
4398 need_cmask = false;
4399 need_pmask = false;
4401 /* Two clauses, the first empty, the second non-empty. */
4402 else if (mask)
4404 need_cmask = (cblock->block->expr1 != 0);
4405 need_pmask = true;
4407 else
4409 need_cmask = true;
4410 need_pmask = false;
4413 if (need_cmask || need_pmask)
4415 /* Calculate the size of temporary needed by the mask-expr. */
4416 gfc_init_block (&inner_size_body);
4417 inner_size = compute_inner_temp_size (cblock->expr1, cblock->expr1,
4418 &inner_size_body, &lss, &rss);
4420 gfc_free_ss_chain (lss);
4421 gfc_free_ss_chain (rss);
4423 /* Calculate the total size of temporary needed. */
4424 size = compute_overall_iter_number (nested_forall_info, inner_size,
4425 &inner_size_body, block);
4427 /* Check whether the size is negative. */
4428 cond = fold_build2_loc (input_location, LE_EXPR, boolean_type_node, size,
4429 gfc_index_zero_node);
4430 size = fold_build3_loc (input_location, COND_EXPR, gfc_array_index_type,
4431 cond, gfc_index_zero_node, size);
4432 size = gfc_evaluate_now (size, block);
4434 /* Allocate temporary for WHERE mask if needed. */
4435 if (need_cmask)
4436 cmask = allocate_temp_for_forall_nest_1 (mask_type, size, block,
4437 &pcmask);
4439 /* Allocate temporary for !mask if needed. */
4440 if (need_pmask)
4441 pmask = allocate_temp_for_forall_nest_1 (mask_type, size, block,
4442 &ppmask);
4445 while (cblock)
4447 /* Each time around this loop, the where clause is conditional
4448 on the value of mask and invert, which are updated at the
4449 bottom of the loop. */
4451 /* Has mask-expr. */
4452 if (cblock->expr1)
4454 /* Ensure that the WHERE mask will be evaluated exactly once.
4455 If there are no statements in this WHERE/ELSEWHERE clause,
4456 then we don't need to update the control mask (cmask).
4457 If this is the last clause of the WHERE construct, then
4458 we don't need to update the pending control mask (pmask). */
4459 if (mask)
4460 gfc_evaluate_where_mask (cblock->expr1, nested_forall_info,
4461 mask, invert,
4462 cblock->next ? cmask : NULL_TREE,
4463 cblock->block ? pmask : NULL_TREE,
4464 mask_type, block);
4465 else
4466 gfc_evaluate_where_mask (cblock->expr1, nested_forall_info,
4467 NULL_TREE, false,
4468 (cblock->next || cblock->block)
4469 ? cmask : NULL_TREE,
4470 NULL_TREE, mask_type, block);
4472 invert = false;
4474 /* It's a final elsewhere-stmt. No mask-expr is present. */
4475 else
4476 cmask = mask;
4478 /* The body of this where clause are controlled by cmask with
4479 sense specified by invert. */
4481 /* Get the assignment statement of a WHERE statement, or the first
4482 statement in where-body-construct of a WHERE construct. */
4483 cnext = cblock->next;
4484 while (cnext)
4486 switch (cnext->op)
4488 /* WHERE assignment statement. */
4489 case EXEC_ASSIGN_CALL:
4491 arg = cnext->ext.actual;
4492 expr1 = expr2 = NULL;
4493 for (; arg; arg = arg->next)
4495 if (!arg->expr)
4496 continue;
4497 if (expr1 == NULL)
4498 expr1 = arg->expr;
4499 else
4500 expr2 = arg->expr;
4502 goto evaluate;
4504 case EXEC_ASSIGN:
4505 expr1 = cnext->expr1;
4506 expr2 = cnext->expr2;
4507 evaluate:
4508 if (nested_forall_info != NULL)
4510 need_temp = gfc_check_dependency (expr1, expr2, 0);
4511 if (need_temp && cnext->op != EXEC_ASSIGN_CALL)
4512 gfc_trans_assign_need_temp (expr1, expr2,
4513 cmask, invert,
4514 nested_forall_info, block);
4515 else
4517 /* Variables to control maskexpr. */
4518 count1 = gfc_create_var (gfc_array_index_type, "count1");
4519 count2 = gfc_create_var (gfc_array_index_type, "count2");
4520 gfc_add_modify (block, count1, gfc_index_zero_node);
4521 gfc_add_modify (block, count2, gfc_index_zero_node);
4523 tmp = gfc_trans_where_assign (expr1, expr2,
4524 cmask, invert,
4525 count1, count2,
4526 cnext);
4528 tmp = gfc_trans_nested_forall_loop (nested_forall_info,
4529 tmp, 1);
4530 gfc_add_expr_to_block (block, tmp);
4533 else
4535 /* Variables to control maskexpr. */
4536 count1 = gfc_create_var (gfc_array_index_type, "count1");
4537 count2 = gfc_create_var (gfc_array_index_type, "count2");
4538 gfc_add_modify (block, count1, gfc_index_zero_node);
4539 gfc_add_modify (block, count2, gfc_index_zero_node);
4541 tmp = gfc_trans_where_assign (expr1, expr2,
4542 cmask, invert,
4543 count1, count2,
4544 cnext);
4545 gfc_add_expr_to_block (block, tmp);
4548 break;
4550 /* WHERE or WHERE construct is part of a where-body-construct. */
4551 case EXEC_WHERE:
4552 gfc_trans_where_2 (cnext, cmask, invert,
4553 nested_forall_info, block);
4554 break;
4556 default:
4557 gcc_unreachable ();
4560 /* The next statement within the same where-body-construct. */
4561 cnext = cnext->next;
4563 /* The next masked-elsewhere-stmt, elsewhere-stmt, or end-where-stmt. */
4564 cblock = cblock->block;
4565 if (mask == NULL_TREE)
4567 /* If we're the initial WHERE, we can simply invert the sense
4568 of the current mask to obtain the "mask" for the remaining
4569 ELSEWHEREs. */
4570 invert = true;
4571 mask = cmask;
4573 else
4575 /* Otherwise, for nested WHERE's we need to use the pending mask. */
4576 invert = false;
4577 mask = pmask;
4581 /* If we allocated a pending mask array, deallocate it now. */
4582 if (ppmask)
4584 tmp = gfc_call_free (ppmask);
4585 gfc_add_expr_to_block (block, tmp);
4588 /* If we allocated a current mask array, deallocate it now. */
4589 if (pcmask)
4591 tmp = gfc_call_free (pcmask);
4592 gfc_add_expr_to_block (block, tmp);
4596 /* Translate a simple WHERE construct or statement without dependencies.
4597 CBLOCK is the "then" clause of the WHERE statement, where CBLOCK->EXPR
4598 is the mask condition, and EBLOCK if non-NULL is the "else" clause.
4599 Currently both CBLOCK and EBLOCK are restricted to single assignments. */
4601 static tree
4602 gfc_trans_where_3 (gfc_code * cblock, gfc_code * eblock)
4604 stmtblock_t block, body;
4605 gfc_expr *cond, *tdst, *tsrc, *edst, *esrc;
4606 tree tmp, cexpr, tstmt, estmt;
4607 gfc_ss *css, *tdss, *tsss;
4608 gfc_se cse, tdse, tsse, edse, esse;
4609 gfc_loopinfo loop;
4610 gfc_ss *edss = 0;
4611 gfc_ss *esss = 0;
4613 /* Allow the scalarizer to workshare simple where loops. */
4614 if (ompws_flags & OMPWS_WORKSHARE_FLAG)
4615 ompws_flags |= OMPWS_SCALARIZER_WS;
4617 cond = cblock->expr1;
4618 tdst = cblock->next->expr1;
4619 tsrc = cblock->next->expr2;
4620 edst = eblock ? eblock->next->expr1 : NULL;
4621 esrc = eblock ? eblock->next->expr2 : NULL;
4623 gfc_start_block (&block);
4624 gfc_init_loopinfo (&loop);
4626 /* Handle the condition. */
4627 gfc_init_se (&cse, NULL);
4628 css = gfc_walk_expr (cond);
4629 gfc_add_ss_to_loop (&loop, css);
4631 /* Handle the then-clause. */
4632 gfc_init_se (&tdse, NULL);
4633 gfc_init_se (&tsse, NULL);
4634 tdss = gfc_walk_expr (tdst);
4635 tsss = gfc_walk_expr (tsrc);
4636 if (tsss == gfc_ss_terminator)
4638 tsss = gfc_get_scalar_ss (gfc_ss_terminator, tsrc);
4639 tsss->info->where = 1;
4641 gfc_add_ss_to_loop (&loop, tdss);
4642 gfc_add_ss_to_loop (&loop, tsss);
4644 if (eblock)
4646 /* Handle the else clause. */
4647 gfc_init_se (&edse, NULL);
4648 gfc_init_se (&esse, NULL);
4649 edss = gfc_walk_expr (edst);
4650 esss = gfc_walk_expr (esrc);
4651 if (esss == gfc_ss_terminator)
4653 esss = gfc_get_scalar_ss (gfc_ss_terminator, esrc);
4654 esss->info->where = 1;
4656 gfc_add_ss_to_loop (&loop, edss);
4657 gfc_add_ss_to_loop (&loop, esss);
4660 gfc_conv_ss_startstride (&loop);
4661 gfc_conv_loop_setup (&loop, &tdst->where);
4663 gfc_mark_ss_chain_used (css, 1);
4664 gfc_mark_ss_chain_used (tdss, 1);
4665 gfc_mark_ss_chain_used (tsss, 1);
4666 if (eblock)
4668 gfc_mark_ss_chain_used (edss, 1);
4669 gfc_mark_ss_chain_used (esss, 1);
4672 gfc_start_scalarized_body (&loop, &body);
4674 gfc_copy_loopinfo_to_se (&cse, &loop);
4675 gfc_copy_loopinfo_to_se (&tdse, &loop);
4676 gfc_copy_loopinfo_to_se (&tsse, &loop);
4677 cse.ss = css;
4678 tdse.ss = tdss;
4679 tsse.ss = tsss;
4680 if (eblock)
4682 gfc_copy_loopinfo_to_se (&edse, &loop);
4683 gfc_copy_loopinfo_to_se (&esse, &loop);
4684 edse.ss = edss;
4685 esse.ss = esss;
4688 gfc_conv_expr (&cse, cond);
4689 gfc_add_block_to_block (&body, &cse.pre);
4690 cexpr = cse.expr;
4692 gfc_conv_expr (&tsse, tsrc);
4693 if (tdss != gfc_ss_terminator && loop.temp_ss != NULL)
4694 gfc_conv_tmp_array_ref (&tdse);
4695 else
4696 gfc_conv_expr (&tdse, tdst);
4698 if (eblock)
4700 gfc_conv_expr (&esse, esrc);
4701 if (edss != gfc_ss_terminator && loop.temp_ss != NULL)
4702 gfc_conv_tmp_array_ref (&edse);
4703 else
4704 gfc_conv_expr (&edse, edst);
4707 tstmt = gfc_trans_scalar_assign (&tdse, &tsse, tdst->ts, false, false, true);
4708 estmt = eblock ? gfc_trans_scalar_assign (&edse, &esse, edst->ts, false,
4709 false, true)
4710 : build_empty_stmt (input_location);
4711 tmp = build3_v (COND_EXPR, cexpr, tstmt, estmt);
4712 gfc_add_expr_to_block (&body, tmp);
4713 gfc_add_block_to_block (&body, &cse.post);
4715 gfc_trans_scalarizing_loops (&loop, &body);
4716 gfc_add_block_to_block (&block, &loop.pre);
4717 gfc_add_block_to_block (&block, &loop.post);
4718 gfc_cleanup_loop (&loop);
4720 return gfc_finish_block (&block);
4723 /* As the WHERE or WHERE construct statement can be nested, we call
4724 gfc_trans_where_2 to do the translation, and pass the initial
4725 NULL values for both the control mask and the pending control mask. */
4727 tree
4728 gfc_trans_where (gfc_code * code)
4730 stmtblock_t block;
4731 gfc_code *cblock;
4732 gfc_code *eblock;
4734 cblock = code->block;
4735 if (cblock->next
4736 && cblock->next->op == EXEC_ASSIGN
4737 && !cblock->next->next)
4739 eblock = cblock->block;
4740 if (!eblock)
4742 /* A simple "WHERE (cond) x = y" statement or block is
4743 dependence free if cond is not dependent upon writing x,
4744 and the source y is unaffected by the destination x. */
4745 if (!gfc_check_dependency (cblock->next->expr1,
4746 cblock->expr1, 0)
4747 && !gfc_check_dependency (cblock->next->expr1,
4748 cblock->next->expr2, 0))
4749 return gfc_trans_where_3 (cblock, NULL);
4751 else if (!eblock->expr1
4752 && !eblock->block
4753 && eblock->next
4754 && eblock->next->op == EXEC_ASSIGN
4755 && !eblock->next->next)
4757 /* A simple "WHERE (cond) x1 = y1 ELSEWHERE x2 = y2 ENDWHERE"
4758 block is dependence free if cond is not dependent on writes
4759 to x1 and x2, y1 is not dependent on writes to x2, and y2
4760 is not dependent on writes to x1, and both y's are not
4761 dependent upon their own x's. In addition to this, the
4762 final two dependency checks below exclude all but the same
4763 array reference if the where and elswhere destinations
4764 are the same. In short, this is VERY conservative and this
4765 is needed because the two loops, required by the standard
4766 are coalesced in gfc_trans_where_3. */
4767 if (!gfc_check_dependency (cblock->next->expr1,
4768 cblock->expr1, 0)
4769 && !gfc_check_dependency (eblock->next->expr1,
4770 cblock->expr1, 0)
4771 && !gfc_check_dependency (cblock->next->expr1,
4772 eblock->next->expr2, 1)
4773 && !gfc_check_dependency (eblock->next->expr1,
4774 cblock->next->expr2, 1)
4775 && !gfc_check_dependency (cblock->next->expr1,
4776 cblock->next->expr2, 1)
4777 && !gfc_check_dependency (eblock->next->expr1,
4778 eblock->next->expr2, 1)
4779 && !gfc_check_dependency (cblock->next->expr1,
4780 eblock->next->expr1, 0)
4781 && !gfc_check_dependency (eblock->next->expr1,
4782 cblock->next->expr1, 0))
4783 return gfc_trans_where_3 (cblock, eblock);
4787 gfc_start_block (&block);
4789 gfc_trans_where_2 (code, NULL, false, NULL, &block);
4791 return gfc_finish_block (&block);
4795 /* CYCLE a DO loop. The label decl has already been created by
4796 gfc_trans_do(), it's in TREE_PURPOSE (backend_decl) of the gfc_code
4797 node at the head of the loop. We must mark the label as used. */
4799 tree
4800 gfc_trans_cycle (gfc_code * code)
4802 tree cycle_label;
4804 cycle_label = code->ext.which_construct->cycle_label;
4805 gcc_assert (cycle_label);
4807 TREE_USED (cycle_label) = 1;
4808 return build1_v (GOTO_EXPR, cycle_label);
4812 /* EXIT a DO loop. Similar to CYCLE, but now the label is in
4813 TREE_VALUE (backend_decl) of the gfc_code node at the head of the
4814 loop. */
4816 tree
4817 gfc_trans_exit (gfc_code * code)
4819 tree exit_label;
4821 exit_label = code->ext.which_construct->exit_label;
4822 gcc_assert (exit_label);
4824 TREE_USED (exit_label) = 1;
4825 return build1_v (GOTO_EXPR, exit_label);
4829 /* Translate the ALLOCATE statement. */
4831 tree
4832 gfc_trans_allocate (gfc_code * code)
4834 gfc_alloc *al;
4835 gfc_expr *e;
4836 gfc_expr *expr;
4837 gfc_se se;
4838 tree tmp;
4839 tree parm;
4840 tree stat;
4841 tree errmsg;
4842 tree errlen;
4843 tree label_errmsg;
4844 tree label_finish;
4845 tree memsz;
4846 tree expr3;
4847 tree slen3;
4848 stmtblock_t block;
4849 stmtblock_t post;
4850 gfc_expr *sz;
4851 gfc_se se_sz;
4852 tree class_expr;
4853 tree nelems;
4854 tree memsize = NULL_TREE;
4855 tree classexpr = NULL_TREE;
4857 if (!code->ext.alloc.list)
4858 return NULL_TREE;
4860 stat = tmp = memsz = NULL_TREE;
4861 label_errmsg = label_finish = errmsg = errlen = NULL_TREE;
4863 gfc_init_block (&block);
4864 gfc_init_block (&post);
4866 /* STAT= (and maybe ERRMSG=) is present. */
4867 if (code->expr1)
4869 /* STAT=. */
4870 tree gfc_int4_type_node = gfc_get_int_type (4);
4871 stat = gfc_create_var (gfc_int4_type_node, "stat");
4873 /* ERRMSG= only makes sense with STAT=. */
4874 if (code->expr2)
4876 gfc_init_se (&se, NULL);
4877 se.want_pointer = 1;
4878 gfc_conv_expr_lhs (&se, code->expr2);
4879 errmsg = se.expr;
4880 errlen = se.string_length;
4882 else
4884 errmsg = null_pointer_node;
4885 errlen = build_int_cst (gfc_charlen_type_node, 0);
4888 /* GOTO destinations. */
4889 label_errmsg = gfc_build_label_decl (NULL_TREE);
4890 label_finish = gfc_build_label_decl (NULL_TREE);
4891 TREE_USED (label_finish) = 0;
4894 expr3 = NULL_TREE;
4895 slen3 = NULL_TREE;
4897 for (al = code->ext.alloc.list; al != NULL; al = al->next)
4899 expr = gfc_copy_expr (al->expr);
4901 if (expr->ts.type == BT_CLASS)
4902 gfc_add_data_component (expr);
4904 gfc_init_se (&se, NULL);
4906 se.want_pointer = 1;
4907 se.descriptor_only = 1;
4908 gfc_conv_expr (&se, expr);
4910 /* Evaluate expr3 just once if not a variable. */
4911 if (al == code->ext.alloc.list
4912 && al->expr->ts.type == BT_CLASS
4913 && code->expr3
4914 && code->expr3->ts.type == BT_CLASS
4915 && code->expr3->expr_type != EXPR_VARIABLE)
4917 gfc_init_se (&se_sz, NULL);
4918 gfc_conv_expr_reference (&se_sz, code->expr3);
4919 gfc_conv_class_to_class (&se_sz, code->expr3,
4920 code->expr3->ts, false, true, false, false);
4921 gfc_add_block_to_block (&se.pre, &se_sz.pre);
4922 gfc_add_block_to_block (&se.post, &se_sz.post);
4923 classexpr = build_fold_indirect_ref_loc (input_location,
4924 se_sz.expr);
4925 classexpr = gfc_evaluate_now (classexpr, &se.pre);
4926 memsize = gfc_vtable_size_get (classexpr);
4927 memsize = fold_convert (sizetype, memsize);
4930 memsz = memsize;
4931 class_expr = classexpr;
4933 nelems = NULL_TREE;
4934 if (!gfc_array_allocate (&se, expr, stat, errmsg, errlen, label_finish,
4935 memsz, &nelems, code->expr3, &code->ext.alloc.ts))
4937 bool unlimited_char;
4939 unlimited_char = UNLIMITED_POLY (al->expr)
4940 && ((code->expr3 && code->expr3->ts.type == BT_CHARACTER)
4941 || (code->ext.alloc.ts.type == BT_CHARACTER
4942 && code->ext.alloc.ts.u.cl
4943 && code->ext.alloc.ts.u.cl->length));
4945 /* A scalar or derived type. */
4947 /* Determine allocate size. */
4948 if (al->expr->ts.type == BT_CLASS
4949 && !unlimited_char
4950 && code->expr3
4951 && memsz == NULL_TREE)
4953 if (code->expr3->ts.type == BT_CLASS)
4955 sz = gfc_copy_expr (code->expr3);
4956 gfc_add_vptr_component (sz);
4957 gfc_add_size_component (sz);
4958 gfc_init_se (&se_sz, NULL);
4959 gfc_conv_expr (&se_sz, sz);
4960 gfc_free_expr (sz);
4961 memsz = se_sz.expr;
4963 else
4964 memsz = TYPE_SIZE_UNIT (gfc_typenode_for_spec (&code->expr3->ts));
4966 else if (((al->expr->ts.type == BT_CHARACTER && al->expr->ts.deferred)
4967 || unlimited_char) && code->expr3)
4969 if (!code->expr3->ts.u.cl->backend_decl)
4971 /* Convert and use the length expression. */
4972 gfc_init_se (&se_sz, NULL);
4973 if (code->expr3->expr_type == EXPR_VARIABLE
4974 || code->expr3->expr_type == EXPR_CONSTANT)
4976 gfc_conv_expr (&se_sz, code->expr3);
4977 gfc_add_block_to_block (&se.pre, &se_sz.pre);
4978 se_sz.string_length
4979 = gfc_evaluate_now (se_sz.string_length, &se.pre);
4980 gfc_add_block_to_block (&se.pre, &se_sz.post);
4981 memsz = se_sz.string_length;
4983 else if (code->expr3->mold
4984 && code->expr3->ts.u.cl
4985 && code->expr3->ts.u.cl->length)
4987 gfc_conv_expr (&se_sz, code->expr3->ts.u.cl->length);
4988 gfc_add_block_to_block (&se.pre, &se_sz.pre);
4989 se_sz.expr = gfc_evaluate_now (se_sz.expr, &se.pre);
4990 gfc_add_block_to_block (&se.pre, &se_sz.post);
4991 memsz = se_sz.expr;
4993 else
4995 /* This is would be inefficient and possibly could
4996 generate wrong code if the result were not stored
4997 in expr3/slen3. */
4998 if (slen3 == NULL_TREE)
5000 gfc_conv_expr (&se_sz, code->expr3);
5001 gfc_add_block_to_block (&se.pre, &se_sz.pre);
5002 expr3 = gfc_evaluate_now (se_sz.expr, &se.pre);
5003 gfc_add_block_to_block (&post, &se_sz.post);
5004 slen3 = gfc_evaluate_now (se_sz.string_length,
5005 &se.pre);
5007 memsz = slen3;
5010 else
5011 /* Otherwise use the stored string length. */
5012 memsz = code->expr3->ts.u.cl->backend_decl;
5013 tmp = al->expr->ts.u.cl->backend_decl;
5015 /* Store the string length. */
5016 if (tmp && TREE_CODE (tmp) == VAR_DECL)
5017 gfc_add_modify (&se.pre, tmp, fold_convert (TREE_TYPE (tmp),
5018 memsz));
5020 /* Convert to size in bytes, using the character KIND. */
5021 if (unlimited_char)
5022 tmp = TREE_TYPE (gfc_typenode_for_spec (&code->expr3->ts));
5023 else
5024 tmp = TREE_TYPE (gfc_typenode_for_spec (&al->expr->ts));
5025 tmp = TYPE_SIZE_UNIT (tmp);
5026 memsz = fold_build2_loc (input_location, MULT_EXPR,
5027 TREE_TYPE (tmp), tmp,
5028 fold_convert (TREE_TYPE (tmp), memsz));
5030 else if ((al->expr->ts.type == BT_CHARACTER && al->expr->ts.deferred)
5031 || unlimited_char)
5033 gcc_assert (code->ext.alloc.ts.u.cl && code->ext.alloc.ts.u.cl->length);
5034 gfc_init_se (&se_sz, NULL);
5035 gfc_conv_expr (&se_sz, code->ext.alloc.ts.u.cl->length);
5036 gfc_add_block_to_block (&se.pre, &se_sz.pre);
5037 se_sz.expr = gfc_evaluate_now (se_sz.expr, &se.pre);
5038 gfc_add_block_to_block (&se.pre, &se_sz.post);
5039 /* Store the string length. */
5040 tmp = al->expr->ts.u.cl->backend_decl;
5041 gfc_add_modify (&se.pre, tmp, fold_convert (TREE_TYPE (tmp),
5042 se_sz.expr));
5043 tmp = TREE_TYPE (gfc_typenode_for_spec (&code->ext.alloc.ts));
5044 tmp = TYPE_SIZE_UNIT (tmp);
5045 memsz = fold_build2_loc (input_location, MULT_EXPR,
5046 TREE_TYPE (tmp), tmp,
5047 fold_convert (TREE_TYPE (se_sz.expr),
5048 se_sz.expr));
5050 else if (code->ext.alloc.ts.type != BT_UNKNOWN)
5051 memsz = TYPE_SIZE_UNIT (gfc_typenode_for_spec (&code->ext.alloc.ts));
5052 else if (memsz == NULL_TREE)
5053 memsz = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (se.expr)));
5055 if (expr->ts.type == BT_CHARACTER && memsz == NULL_TREE)
5057 memsz = se.string_length;
5059 /* Convert to size in bytes, using the character KIND. */
5060 tmp = TREE_TYPE (gfc_typenode_for_spec (&code->ext.alloc.ts));
5061 tmp = TYPE_SIZE_UNIT (tmp);
5062 memsz = fold_build2_loc (input_location, MULT_EXPR,
5063 TREE_TYPE (tmp), tmp,
5064 fold_convert (TREE_TYPE (tmp), memsz));
5067 /* Allocate - for non-pointers with re-alloc checking. */
5068 if (gfc_expr_attr (expr).allocatable)
5069 gfc_allocate_allocatable (&se.pre, se.expr, memsz, NULL_TREE,
5070 stat, errmsg, errlen, label_finish, expr);
5071 else
5072 gfc_allocate_using_malloc (&se.pre, se.expr, memsz, stat);
5074 if (al->expr->ts.type == BT_DERIVED
5075 && expr->ts.u.derived->attr.alloc_comp)
5077 tmp = build_fold_indirect_ref_loc (input_location, se.expr);
5078 tmp = gfc_nullify_alloc_comp (expr->ts.u.derived, tmp, 0);
5079 gfc_add_expr_to_block (&se.pre, tmp);
5083 gfc_add_block_to_block (&block, &se.pre);
5085 /* Error checking -- Note: ERRMSG only makes sense with STAT. */
5086 if (code->expr1)
5088 tmp = build1_v (GOTO_EXPR, label_errmsg);
5089 parm = fold_build2_loc (input_location, NE_EXPR,
5090 boolean_type_node, stat,
5091 build_int_cst (TREE_TYPE (stat), 0));
5092 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
5093 gfc_unlikely (parm), tmp,
5094 build_empty_stmt (input_location));
5095 gfc_add_expr_to_block (&block, tmp);
5098 /* We need the vptr of CLASS objects to be initialized. */
5099 e = gfc_copy_expr (al->expr);
5100 if (e->ts.type == BT_CLASS)
5102 gfc_expr *lhs, *rhs;
5103 gfc_se lse;
5105 lhs = gfc_expr_to_initialize (e);
5106 gfc_add_vptr_component (lhs);
5108 if (class_expr != NULL_TREE)
5110 /* Polymorphic SOURCE: VPTR must be determined at run time. */
5111 gfc_init_se (&lse, NULL);
5112 lse.want_pointer = 1;
5113 gfc_conv_expr (&lse, lhs);
5114 tmp = gfc_class_vptr_get (class_expr);
5115 gfc_add_modify (&block, lse.expr,
5116 fold_convert (TREE_TYPE (lse.expr), tmp));
5118 else if (code->expr3 && code->expr3->ts.type == BT_CLASS)
5120 /* Polymorphic SOURCE: VPTR must be determined at run time. */
5121 rhs = gfc_copy_expr (code->expr3);
5122 gfc_add_vptr_component (rhs);
5123 tmp = gfc_trans_pointer_assignment (lhs, rhs);
5124 gfc_add_expr_to_block (&block, tmp);
5125 gfc_free_expr (rhs);
5126 rhs = gfc_expr_to_initialize (e);
5128 else
5130 /* VPTR is fixed at compile time. */
5131 gfc_symbol *vtab;
5132 gfc_typespec *ts;
5133 if (code->expr3)
5134 ts = &code->expr3->ts;
5135 else if (e->ts.type == BT_DERIVED)
5136 ts = &e->ts;
5137 else if (code->ext.alloc.ts.type == BT_DERIVED || UNLIMITED_POLY (al->expr))
5138 ts = &code->ext.alloc.ts;
5139 else if (e->ts.type == BT_CLASS)
5140 ts = &CLASS_DATA (e)->ts;
5141 else
5142 ts = &e->ts;
5144 if (ts->type == BT_DERIVED || UNLIMITED_POLY (e))
5146 if (ts->type == BT_DERIVED)
5147 vtab = gfc_find_derived_vtab (ts->u.derived);
5148 else
5149 vtab = gfc_find_intrinsic_vtab (ts);
5150 gcc_assert (vtab);
5151 gfc_init_se (&lse, NULL);
5152 lse.want_pointer = 1;
5153 gfc_conv_expr (&lse, lhs);
5154 tmp = gfc_build_addr_expr (NULL_TREE,
5155 gfc_get_symbol_decl (vtab));
5156 gfc_add_modify (&block, lse.expr,
5157 fold_convert (TREE_TYPE (lse.expr), tmp));
5160 gfc_free_expr (lhs);
5163 gfc_free_expr (e);
5165 if (code->expr3 && !code->expr3->mold)
5167 /* Initialization via SOURCE block
5168 (or static default initializer). */
5169 gfc_expr *rhs = gfc_copy_expr (code->expr3);
5170 if (class_expr != NULL_TREE)
5172 tree to;
5173 to = TREE_OPERAND (se.expr, 0);
5175 tmp = gfc_copy_class_to_class (class_expr, to, nelems);
5177 else if (al->expr->ts.type == BT_CLASS)
5179 gfc_actual_arglist *actual;
5180 gfc_expr *ppc;
5181 gfc_code *ppc_code;
5182 gfc_ref *ref, *dataref;
5184 /* Do a polymorphic deep copy. */
5185 actual = gfc_get_actual_arglist ();
5186 actual->expr = gfc_copy_expr (rhs);
5187 if (rhs->ts.type == BT_CLASS)
5188 gfc_add_data_component (actual->expr);
5189 actual->next = gfc_get_actual_arglist ();
5190 actual->next->expr = gfc_copy_expr (al->expr);
5191 actual->next->expr->ts.type = BT_CLASS;
5192 gfc_add_data_component (actual->next->expr);
5194 dataref = NULL;
5195 /* Make sure we go up through the reference chain to
5196 the _data reference, where the arrayspec is found. */
5197 for (ref = actual->next->expr->ref; ref; ref = ref->next)
5198 if (ref->type == REF_COMPONENT
5199 && strcmp (ref->u.c.component->name, "_data") == 0)
5200 dataref = ref;
5202 if (dataref && dataref->u.c.component->as)
5204 int dim;
5205 gfc_expr *temp;
5206 gfc_ref *ref = dataref->next;
5207 ref->u.ar.type = AR_SECTION;
5208 /* We have to set up the array reference to give ranges
5209 in all dimensions and ensure that the end and stride
5210 are set so that the copy can be scalarized. */
5211 dim = 0;
5212 for (; dim < dataref->u.c.component->as->rank; dim++)
5214 ref->u.ar.dimen_type[dim] = DIMEN_RANGE;
5215 if (ref->u.ar.end[dim] == NULL)
5217 ref->u.ar.end[dim] = ref->u.ar.start[dim];
5218 temp = gfc_get_int_expr (gfc_default_integer_kind,
5219 &al->expr->where, 1);
5220 ref->u.ar.start[dim] = temp;
5222 temp = gfc_subtract (gfc_copy_expr (ref->u.ar.end[dim]),
5223 gfc_copy_expr (ref->u.ar.start[dim]));
5224 temp = gfc_add (gfc_get_int_expr (gfc_default_integer_kind,
5225 &al->expr->where, 1),
5226 temp);
5229 if (rhs->ts.type == BT_CLASS)
5231 ppc = gfc_copy_expr (rhs);
5232 gfc_add_vptr_component (ppc);
5234 else if (rhs->ts.type == BT_DERIVED)
5235 ppc = gfc_lval_expr_from_sym
5236 (gfc_find_derived_vtab (rhs->ts.u.derived));
5237 else
5238 ppc = gfc_lval_expr_from_sym
5239 (gfc_find_intrinsic_vtab (&rhs->ts));
5240 gfc_add_component_ref (ppc, "_copy");
5242 ppc_code = gfc_get_code (EXEC_CALL);
5243 ppc_code->resolved_sym = ppc->symtree->n.sym;
5244 /* Although '_copy' is set to be elemental in class.c, it is
5245 not staying that way. Find out why, sometime.... */
5246 ppc_code->resolved_sym->attr.elemental = 1;
5247 ppc_code->ext.actual = actual;
5248 ppc_code->expr1 = ppc;
5249 /* Since '_copy' is elemental, the scalarizer will take care
5250 of arrays in gfc_trans_call. */
5251 tmp = gfc_trans_call (ppc_code, true, NULL, NULL, false);
5252 gfc_free_statements (ppc_code);
5254 else if (expr3 != NULL_TREE)
5256 tmp = build_fold_indirect_ref_loc (input_location, se.expr);
5257 gfc_trans_string_copy (&block, slen3, tmp, code->expr3->ts.kind,
5258 slen3, expr3, code->expr3->ts.kind);
5259 tmp = NULL_TREE;
5261 else
5263 /* Switch off automatic reallocation since we have just done
5264 the ALLOCATE. */
5265 int realloc_lhs = gfc_option.flag_realloc_lhs;
5266 gfc_option.flag_realloc_lhs = 0;
5267 tmp = gfc_trans_assignment (gfc_expr_to_initialize (expr),
5268 rhs, false, false);
5269 gfc_option.flag_realloc_lhs = realloc_lhs;
5271 gfc_free_expr (rhs);
5272 gfc_add_expr_to_block (&block, tmp);
5274 else if (code->expr3 && code->expr3->mold
5275 && code->expr3->ts.type == BT_CLASS)
5277 /* Since the _vptr has already been assigned to the allocate
5278 object, we can use gfc_copy_class_to_class in its
5279 initialization mode. */
5280 tmp = TREE_OPERAND (se.expr, 0);
5281 tmp = gfc_copy_class_to_class (NULL_TREE, tmp, nelems);
5282 gfc_add_expr_to_block (&block, tmp);
5285 gfc_free_expr (expr);
5288 /* STAT. */
5289 if (code->expr1)
5291 tmp = build1_v (LABEL_EXPR, label_errmsg);
5292 gfc_add_expr_to_block (&block, tmp);
5295 /* ERRMSG - only useful if STAT is present. */
5296 if (code->expr1 && code->expr2)
5298 const char *msg = "Attempt to allocate an allocated object";
5299 tree slen, dlen, errmsg_str;
5300 stmtblock_t errmsg_block;
5302 gfc_init_block (&errmsg_block);
5304 errmsg_str = gfc_create_var (pchar_type_node, "ERRMSG");
5305 gfc_add_modify (&errmsg_block, errmsg_str,
5306 gfc_build_addr_expr (pchar_type_node,
5307 gfc_build_localized_cstring_const (msg)));
5309 slen = build_int_cst (gfc_charlen_type_node, ((int) strlen (msg)));
5310 dlen = gfc_get_expr_charlen (code->expr2);
5311 slen = fold_build2_loc (input_location, MIN_EXPR, TREE_TYPE (slen), dlen,
5312 slen);
5314 gfc_trans_string_copy (&errmsg_block, dlen, errmsg, code->expr2->ts.kind,
5315 slen, errmsg_str, gfc_default_character_kind);
5316 dlen = gfc_finish_block (&errmsg_block);
5318 tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, stat,
5319 build_int_cst (TREE_TYPE (stat), 0));
5321 tmp = build3_v (COND_EXPR, tmp, dlen, build_empty_stmt (input_location));
5323 gfc_add_expr_to_block (&block, tmp);
5326 /* STAT block. */
5327 if (code->expr1)
5329 if (TREE_USED (label_finish))
5331 tmp = build1_v (LABEL_EXPR, label_finish);
5332 gfc_add_expr_to_block (&block, tmp);
5335 gfc_init_se (&se, NULL);
5336 gfc_conv_expr_lhs (&se, code->expr1);
5337 tmp = convert (TREE_TYPE (se.expr), stat);
5338 gfc_add_modify (&block, se.expr, tmp);
5341 gfc_add_block_to_block (&block, &se.post);
5342 gfc_add_block_to_block (&block, &post);
5344 return gfc_finish_block (&block);
5348 /* Translate a DEALLOCATE statement. */
5350 tree
5351 gfc_trans_deallocate (gfc_code *code)
5353 gfc_se se;
5354 gfc_alloc *al;
5355 tree apstat, pstat, stat, errmsg, errlen, tmp;
5356 tree label_finish, label_errmsg;
5357 stmtblock_t block;
5359 pstat = apstat = stat = errmsg = errlen = tmp = NULL_TREE;
5360 label_finish = label_errmsg = NULL_TREE;
5362 gfc_start_block (&block);
5364 /* Count the number of failed deallocations. If deallocate() was
5365 called with STAT= , then set STAT to the count. If deallocate
5366 was called with ERRMSG, then set ERRMG to a string. */
5367 if (code->expr1)
5369 tree gfc_int4_type_node = gfc_get_int_type (4);
5371 stat = gfc_create_var (gfc_int4_type_node, "stat");
5372 pstat = gfc_build_addr_expr (NULL_TREE, stat);
5374 /* GOTO destinations. */
5375 label_errmsg = gfc_build_label_decl (NULL_TREE);
5376 label_finish = gfc_build_label_decl (NULL_TREE);
5377 TREE_USED (label_finish) = 0;
5380 /* Set ERRMSG - only needed if STAT is available. */
5381 if (code->expr1 && code->expr2)
5383 gfc_init_se (&se, NULL);
5384 se.want_pointer = 1;
5385 gfc_conv_expr_lhs (&se, code->expr2);
5386 errmsg = se.expr;
5387 errlen = se.string_length;
5390 for (al = code->ext.alloc.list; al != NULL; al = al->next)
5392 gfc_expr *expr = gfc_copy_expr (al->expr);
5393 gcc_assert (expr->expr_type == EXPR_VARIABLE);
5395 if (expr->ts.type == BT_CLASS)
5396 gfc_add_data_component (expr);
5398 gfc_init_se (&se, NULL);
5399 gfc_start_block (&se.pre);
5401 se.want_pointer = 1;
5402 se.descriptor_only = 1;
5403 gfc_conv_expr (&se, expr);
5405 if (expr->rank || gfc_is_coarray (expr))
5407 if (expr->ts.type == BT_DERIVED && expr->ts.u.derived->attr.alloc_comp
5408 && !gfc_is_finalizable (expr->ts.u.derived, NULL))
5410 gfc_ref *ref;
5411 gfc_ref *last = NULL;
5412 for (ref = expr->ref; ref; ref = ref->next)
5413 if (ref->type == REF_COMPONENT)
5414 last = ref;
5416 /* Do not deallocate the components of a derived type
5417 ultimate pointer component. */
5418 if (!(last && last->u.c.component->attr.pointer)
5419 && !(!last && expr->symtree->n.sym->attr.pointer))
5421 tmp = gfc_deallocate_alloc_comp (expr->ts.u.derived, se.expr,
5422 expr->rank);
5423 gfc_add_expr_to_block (&se.pre, tmp);
5426 tmp = gfc_array_deallocate (se.expr, pstat, errmsg, errlen,
5427 label_finish, expr);
5428 gfc_add_expr_to_block (&se.pre, tmp);
5429 if (al->expr->ts.type == BT_CLASS)
5430 gfc_reset_vptr (&se.pre, al->expr);
5432 else
5434 tmp = gfc_deallocate_scalar_with_status (se.expr, pstat, false,
5435 al->expr, al->expr->ts);
5436 gfc_add_expr_to_block (&se.pre, tmp);
5438 /* Set to zero after deallocation. */
5439 tmp = fold_build2_loc (input_location, MODIFY_EXPR, void_type_node,
5440 se.expr,
5441 build_int_cst (TREE_TYPE (se.expr), 0));
5442 gfc_add_expr_to_block (&se.pre, tmp);
5444 if (al->expr->ts.type == BT_CLASS)
5445 gfc_reset_vptr (&se.pre, al->expr);
5448 if (code->expr1)
5450 tree cond;
5452 cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, stat,
5453 build_int_cst (TREE_TYPE (stat), 0));
5454 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
5455 gfc_unlikely (cond),
5456 build1_v (GOTO_EXPR, label_errmsg),
5457 build_empty_stmt (input_location));
5458 gfc_add_expr_to_block (&se.pre, tmp);
5461 tmp = gfc_finish_block (&se.pre);
5462 gfc_add_expr_to_block (&block, tmp);
5463 gfc_free_expr (expr);
5466 if (code->expr1)
5468 tmp = build1_v (LABEL_EXPR, label_errmsg);
5469 gfc_add_expr_to_block (&block, tmp);
5472 /* Set ERRMSG - only needed if STAT is available. */
5473 if (code->expr1 && code->expr2)
5475 const char *msg = "Attempt to deallocate an unallocated object";
5476 stmtblock_t errmsg_block;
5477 tree errmsg_str, slen, dlen, cond;
5479 gfc_init_block (&errmsg_block);
5481 errmsg_str = gfc_create_var (pchar_type_node, "ERRMSG");
5482 gfc_add_modify (&errmsg_block, errmsg_str,
5483 gfc_build_addr_expr (pchar_type_node,
5484 gfc_build_localized_cstring_const (msg)));
5485 slen = build_int_cst (gfc_charlen_type_node, ((int) strlen (msg)));
5486 dlen = gfc_get_expr_charlen (code->expr2);
5488 gfc_trans_string_copy (&errmsg_block, dlen, errmsg, code->expr2->ts.kind,
5489 slen, errmsg_str, gfc_default_character_kind);
5490 tmp = gfc_finish_block (&errmsg_block);
5492 cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, stat,
5493 build_int_cst (TREE_TYPE (stat), 0));
5494 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
5495 gfc_unlikely (cond), tmp,
5496 build_empty_stmt (input_location));
5498 gfc_add_expr_to_block (&block, tmp);
5501 if (code->expr1 && TREE_USED (label_finish))
5503 tmp = build1_v (LABEL_EXPR, label_finish);
5504 gfc_add_expr_to_block (&block, tmp);
5507 /* Set STAT. */
5508 if (code->expr1)
5510 gfc_init_se (&se, NULL);
5511 gfc_conv_expr_lhs (&se, code->expr1);
5512 tmp = convert (TREE_TYPE (se.expr), stat);
5513 gfc_add_modify (&block, se.expr, tmp);
5516 return gfc_finish_block (&block);
5519 #include "gt-fortran-trans-stmt.h"