2011-02-27 Tobias Burnus <burnus@net-b.de>
[official-gcc.git] / gcc / fortran / trans-stmt.c
blob98fb74c45785d6a0d4e6d1eacb52d568c51a68d2
1 /* Statement translation -- generate GCC trees from gfc_code.
2 Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
3 2011
4 Free Software Foundation, Inc.
5 Contributed by Paul Brook <paul@nowt.org>
6 and Steven Bosscher <s.bosscher@student.tudelft.nl>
8 This file is part of GCC.
10 GCC is free software; you can redistribute it and/or modify it under
11 the terms of the GNU General Public License as published by the Free
12 Software Foundation; either version 3, or (at your option) any later
13 version.
15 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
16 WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18 for more details.
20 You should have received a copy of the GNU General Public License
21 along with GCC; see the file COPYING3. If not see
22 <http://www.gnu.org/licenses/>. */
25 #include "config.h"
26 #include "system.h"
27 #include "coretypes.h"
28 #include "tree.h"
29 #include "gfortran.h"
30 #include "flags.h"
31 #include "trans.h"
32 #include "trans-stmt.h"
33 #include "trans-types.h"
34 #include "trans-array.h"
35 #include "trans-const.h"
36 #include "arith.h"
37 #include "dependency.h"
38 #include "ggc.h"
40 typedef struct iter_info
42 tree var;
43 tree start;
44 tree end;
45 tree step;
46 struct iter_info *next;
48 iter_info;
50 typedef struct forall_info
52 iter_info *this_loop;
53 tree mask;
54 tree maskindex;
55 int nvar;
56 tree size;
57 struct forall_info *prev_nest;
59 forall_info;
61 static void gfc_trans_where_2 (gfc_code *, tree, bool,
62 forall_info *, stmtblock_t *);
64 /* Translate a F95 label number to a LABEL_EXPR. */
66 tree
67 gfc_trans_label_here (gfc_code * code)
69 return build1_v (LABEL_EXPR, gfc_get_label_decl (code->here));
73 /* Given a variable expression which has been ASSIGNed to, find the decl
74 containing the auxiliary variables. For variables in common blocks this
75 is a field_decl. */
77 void
78 gfc_conv_label_variable (gfc_se * se, gfc_expr * expr)
80 gcc_assert (expr->symtree->n.sym->attr.assign == 1);
81 gfc_conv_expr (se, expr);
82 /* Deals with variable in common block. Get the field declaration. */
83 if (TREE_CODE (se->expr) == COMPONENT_REF)
84 se->expr = TREE_OPERAND (se->expr, 1);
85 /* Deals with dummy argument. Get the parameter declaration. */
86 else if (TREE_CODE (se->expr) == INDIRECT_REF)
87 se->expr = TREE_OPERAND (se->expr, 0);
90 /* Translate a label assignment statement. */
92 tree
93 gfc_trans_label_assign (gfc_code * code)
95 tree label_tree;
96 gfc_se se;
97 tree len;
98 tree addr;
99 tree len_tree;
100 int label_len;
102 /* Start a new block. */
103 gfc_init_se (&se, NULL);
104 gfc_start_block (&se.pre);
105 gfc_conv_label_variable (&se, code->expr1);
107 len = GFC_DECL_STRING_LEN (se.expr);
108 addr = GFC_DECL_ASSIGN_ADDR (se.expr);
110 label_tree = gfc_get_label_decl (code->label1);
112 if (code->label1->defined == ST_LABEL_TARGET)
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 (NULL_TREE, 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 /* Check for dependencies between INTENT(IN) and INTENT(OUT) arguments of
182 elemental subroutines. Make temporaries for output arguments if any such
183 dependencies are found. Output arguments are chosen because internal_unpack
184 can be used, as is, to copy the result back to the variable. */
185 static void
186 gfc_conv_elemental_dependencies (gfc_se * se, gfc_se * loopse,
187 gfc_symbol * sym, gfc_actual_arglist * arg,
188 gfc_dep_check check_variable)
190 gfc_actual_arglist *arg0;
191 gfc_expr *e;
192 gfc_formal_arglist *formal;
193 gfc_loopinfo tmp_loop;
194 gfc_se parmse;
195 gfc_ss *ss;
196 gfc_ss_info *info;
197 gfc_symbol *fsym;
198 gfc_ref *ref;
199 int n;
200 tree data;
201 tree offset;
202 tree size;
203 tree tmp;
205 if (loopse->ss == NULL)
206 return;
208 ss = loopse->ss;
209 arg0 = arg;
210 formal = sym->formal;
212 /* Loop over all the arguments testing for dependencies. */
213 for (; arg != NULL; arg = arg->next, formal = formal ? formal->next : NULL)
215 e = arg->expr;
216 if (e == NULL)
217 continue;
219 /* Obtain the info structure for the current argument. */
220 info = NULL;
221 for (ss = loopse->ss; ss && ss != gfc_ss_terminator; ss = ss->next)
223 if (ss->expr != e)
224 continue;
225 info = &ss->data.info;
226 break;
229 /* If there is a dependency, create a temporary and use it
230 instead of the variable. */
231 fsym = formal ? formal->sym : NULL;
232 if (e->expr_type == EXPR_VARIABLE
233 && e->rank && fsym
234 && fsym->attr.intent != INTENT_IN
235 && gfc_check_fncall_dependency (e, fsym->attr.intent,
236 sym, arg0, check_variable))
238 tree initial, temptype;
239 stmtblock_t temp_post;
241 /* Make a local loopinfo for the temporary creation, so that
242 none of the other ss->info's have to be renormalized. */
243 gfc_init_loopinfo (&tmp_loop);
244 tmp_loop.dimen = info->dimen;
245 for (n = 0; n < info->dimen; n++)
247 tmp_loop.to[n] = loopse->loop->to[n];
248 tmp_loop.from[n] = loopse->loop->from[n];
249 tmp_loop.order[n] = loopse->loop->order[n];
252 /* Obtain the argument descriptor for unpacking. */
253 gfc_init_se (&parmse, NULL);
254 parmse.want_pointer = 1;
256 /* The scalarizer introduces some specific peculiarities when
257 handling elemental subroutines; the stride can be needed up to
258 the dim_array - 1, rather than dim_loop - 1 to calculate
259 offsets outside the loop. For this reason, we make sure that
260 the descriptor has the dimensionality of the array by converting
261 trailing elements into ranges with end = start. */
262 for (ref = e->ref; ref; ref = ref->next)
263 if (ref->type == REF_ARRAY && ref->u.ar.type == AR_SECTION)
264 break;
266 if (ref)
268 bool seen_range = false;
269 for (n = 0; n < ref->u.ar.dimen; n++)
271 if (ref->u.ar.dimen_type[n] == DIMEN_RANGE)
272 seen_range = true;
274 if (!seen_range
275 || ref->u.ar.dimen_type[n] != DIMEN_ELEMENT)
276 continue;
278 ref->u.ar.end[n] = gfc_copy_expr (ref->u.ar.start[n]);
279 ref->u.ar.dimen_type[n] = DIMEN_RANGE;
283 gfc_conv_expr_descriptor (&parmse, e, gfc_walk_expr (e));
284 gfc_add_block_to_block (&se->pre, &parmse.pre);
286 /* If we've got INTENT(INOUT) or a derived type with INTENT(OUT),
287 initialize the array temporary with a copy of the values. */
288 if (fsym->attr.intent == INTENT_INOUT
289 || (fsym->ts.type ==BT_DERIVED
290 && fsym->attr.intent == INTENT_OUT))
291 initial = parmse.expr;
292 else
293 initial = NULL_TREE;
295 /* Find the type of the temporary to create; we don't use the type
296 of e itself as this breaks for subcomponent-references in e (where
297 the type of e is that of the final reference, but parmse.expr's
298 type corresponds to the full derived-type). */
299 /* TODO: Fix this somehow so we don't need a temporary of the whole
300 array but instead only the components referenced. */
301 temptype = TREE_TYPE (parmse.expr); /* Pointer to descriptor. */
302 gcc_assert (TREE_CODE (temptype) == POINTER_TYPE);
303 temptype = TREE_TYPE (temptype);
304 temptype = gfc_get_element_type (temptype);
306 /* Generate the temporary. Cleaning up the temporary should be the
307 very last thing done, so we add the code to a new block and add it
308 to se->post as last instructions. */
309 size = gfc_create_var (gfc_array_index_type, NULL);
310 data = gfc_create_var (pvoid_type_node, NULL);
311 gfc_init_block (&temp_post);
312 tmp = gfc_trans_create_temp_array (&se->pre, &temp_post,
313 &tmp_loop, info, temptype,
314 initial,
315 false, true, false,
316 &arg->expr->where);
317 gfc_add_modify (&se->pre, size, tmp);
318 tmp = fold_convert (pvoid_type_node, info->data);
319 gfc_add_modify (&se->pre, data, tmp);
321 /* Calculate the offset for the temporary. */
322 offset = gfc_index_zero_node;
323 for (n = 0; n < info->dimen; n++)
325 tmp = gfc_conv_descriptor_stride_get (info->descriptor,
326 gfc_rank_cst[n]);
327 tmp = fold_build2_loc (input_location, MULT_EXPR,
328 gfc_array_index_type,
329 loopse->loop->from[n], tmp);
330 offset = fold_build2_loc (input_location, MINUS_EXPR,
331 gfc_array_index_type, offset, tmp);
333 info->offset = gfc_create_var (gfc_array_index_type, NULL);
334 gfc_add_modify (&se->pre, info->offset, offset);
336 /* Copy the result back using unpack. */
337 tmp = build_call_expr_loc (input_location,
338 gfor_fndecl_in_unpack, 2, parmse.expr, data);
339 gfc_add_expr_to_block (&se->post, tmp);
341 /* parmse.pre is already added above. */
342 gfc_add_block_to_block (&se->post, &parmse.post);
343 gfc_add_block_to_block (&se->post, &temp_post);
349 /* Translate the CALL statement. Builds a call to an F95 subroutine. */
351 tree
352 gfc_trans_call (gfc_code * code, bool dependency_check,
353 tree mask, tree count1, bool invert)
355 gfc_se se;
356 gfc_ss * ss;
357 int has_alternate_specifier;
358 gfc_dep_check check_variable;
359 tree index = NULL_TREE;
360 tree maskexpr = NULL_TREE;
361 tree tmp;
363 /* A CALL starts a new block because the actual arguments may have to
364 be evaluated first. */
365 gfc_init_se (&se, NULL);
366 gfc_start_block (&se.pre);
368 gcc_assert (code->resolved_sym);
370 ss = gfc_ss_terminator;
371 if (code->resolved_sym->attr.elemental)
372 ss = gfc_walk_elemental_function_args (ss, code->ext.actual, GFC_SS_REFERENCE);
374 /* Is not an elemental subroutine call with array valued arguments. */
375 if (ss == gfc_ss_terminator)
378 /* Translate the call. */
379 has_alternate_specifier
380 = gfc_conv_procedure_call (&se, code->resolved_sym, code->ext.actual,
381 code->expr1, NULL);
383 /* A subroutine without side-effect, by definition, does nothing! */
384 TREE_SIDE_EFFECTS (se.expr) = 1;
386 /* Chain the pieces together and return the block. */
387 if (has_alternate_specifier)
389 gfc_code *select_code;
390 gfc_symbol *sym;
391 select_code = code->next;
392 gcc_assert(select_code->op == EXEC_SELECT);
393 sym = select_code->expr1->symtree->n.sym;
394 se.expr = convert (gfc_typenode_for_spec (&sym->ts), se.expr);
395 if (sym->backend_decl == NULL)
396 sym->backend_decl = gfc_get_symbol_decl (sym);
397 gfc_add_modify (&se.pre, sym->backend_decl, se.expr);
399 else
400 gfc_add_expr_to_block (&se.pre, se.expr);
402 gfc_add_block_to_block (&se.pre, &se.post);
405 else
407 /* An elemental subroutine call with array valued arguments has
408 to be scalarized. */
409 gfc_loopinfo loop;
410 stmtblock_t body;
411 stmtblock_t block;
412 gfc_se loopse;
413 gfc_se depse;
415 /* gfc_walk_elemental_function_args renders the ss chain in the
416 reverse order to the actual argument order. */
417 ss = gfc_reverse_ss (ss);
419 /* Initialize the loop. */
420 gfc_init_se (&loopse, NULL);
421 gfc_init_loopinfo (&loop);
422 gfc_add_ss_to_loop (&loop, ss);
424 gfc_conv_ss_startstride (&loop);
425 /* TODO: gfc_conv_loop_setup generates a temporary for vector
426 subscripts. This could be prevented in the elemental case
427 as temporaries are handled separatedly
428 (below in gfc_conv_elemental_dependencies). */
429 gfc_conv_loop_setup (&loop, &code->expr1->where);
430 gfc_mark_ss_chain_used (ss, 1);
432 /* Convert the arguments, checking for dependencies. */
433 gfc_copy_loopinfo_to_se (&loopse, &loop);
434 loopse.ss = ss;
436 /* For operator assignment, do dependency checking. */
437 if (dependency_check)
438 check_variable = ELEM_CHECK_VARIABLE;
439 else
440 check_variable = ELEM_DONT_CHECK_VARIABLE;
442 gfc_init_se (&depse, NULL);
443 gfc_conv_elemental_dependencies (&depse, &loopse, code->resolved_sym,
444 code->ext.actual, check_variable);
446 gfc_add_block_to_block (&loop.pre, &depse.pre);
447 gfc_add_block_to_block (&loop.post, &depse.post);
449 /* Generate the loop body. */
450 gfc_start_scalarized_body (&loop, &body);
451 gfc_init_block (&block);
453 if (mask && count1)
455 /* Form the mask expression according to the mask. */
456 index = count1;
457 maskexpr = gfc_build_array_ref (mask, index, NULL);
458 if (invert)
459 maskexpr = fold_build1_loc (input_location, TRUTH_NOT_EXPR,
460 TREE_TYPE (maskexpr), maskexpr);
463 /* Add the subroutine call to the block. */
464 gfc_conv_procedure_call (&loopse, code->resolved_sym,
465 code->ext.actual, code->expr1, NULL);
467 if (mask && count1)
469 tmp = build3_v (COND_EXPR, maskexpr, loopse.expr,
470 build_empty_stmt (input_location));
471 gfc_add_expr_to_block (&loopse.pre, tmp);
472 tmp = fold_build2_loc (input_location, PLUS_EXPR,
473 gfc_array_index_type,
474 count1, gfc_index_one_node);
475 gfc_add_modify (&loopse.pre, count1, tmp);
477 else
478 gfc_add_expr_to_block (&loopse.pre, loopse.expr);
480 gfc_add_block_to_block (&block, &loopse.pre);
481 gfc_add_block_to_block (&block, &loopse.post);
483 /* Finish up the loop block and the loop. */
484 gfc_add_expr_to_block (&body, gfc_finish_block (&block));
485 gfc_trans_scalarizing_loops (&loop, &body);
486 gfc_add_block_to_block (&se.pre, &loop.pre);
487 gfc_add_block_to_block (&se.pre, &loop.post);
488 gfc_add_block_to_block (&se.pre, &se.post);
489 gfc_cleanup_loop (&loop);
492 return gfc_finish_block (&se.pre);
496 /* Translate the RETURN statement. */
498 tree
499 gfc_trans_return (gfc_code * code)
501 if (code->expr1)
503 gfc_se se;
504 tree tmp;
505 tree result;
507 /* If code->expr is not NULL, this return statement must appear
508 in a subroutine and current_fake_result_decl has already
509 been generated. */
511 result = gfc_get_fake_result_decl (NULL, 0);
512 if (!result)
514 gfc_warning ("An alternate return at %L without a * dummy argument",
515 &code->expr1->where);
516 return gfc_generate_return ();
519 /* Start a new block for this statement. */
520 gfc_init_se (&se, NULL);
521 gfc_start_block (&se.pre);
523 gfc_conv_expr (&se, code->expr1);
525 /* Note that the actually returned expression is a simple value and
526 does not depend on any pointers or such; thus we can clean-up with
527 se.post before returning. */
528 tmp = fold_build2_loc (input_location, MODIFY_EXPR, TREE_TYPE (result),
529 result, fold_convert (TREE_TYPE (result),
530 se.expr));
531 gfc_add_expr_to_block (&se.pre, tmp);
532 gfc_add_block_to_block (&se.pre, &se.post);
534 tmp = gfc_generate_return ();
535 gfc_add_expr_to_block (&se.pre, tmp);
536 return gfc_finish_block (&se.pre);
539 return gfc_generate_return ();
543 /* Translate the PAUSE statement. We have to translate this statement
544 to a runtime library call. */
546 tree
547 gfc_trans_pause (gfc_code * code)
549 tree gfc_int4_type_node = gfc_get_int_type (4);
550 gfc_se se;
551 tree tmp;
553 /* Start a new block for this statement. */
554 gfc_init_se (&se, NULL);
555 gfc_start_block (&se.pre);
558 if (code->expr1 == NULL)
560 tmp = build_int_cst (gfc_int4_type_node, 0);
561 tmp = build_call_expr_loc (input_location,
562 gfor_fndecl_pause_string, 2,
563 build_int_cst (pchar_type_node, 0), tmp);
565 else if (code->expr1->ts.type == BT_INTEGER)
567 gfc_conv_expr (&se, code->expr1);
568 tmp = build_call_expr_loc (input_location,
569 gfor_fndecl_pause_numeric, 1,
570 fold_convert (gfc_int4_type_node, se.expr));
572 else
574 gfc_conv_expr_reference (&se, code->expr1);
575 tmp = build_call_expr_loc (input_location,
576 gfor_fndecl_pause_string, 2,
577 se.expr, se.string_length);
580 gfc_add_expr_to_block (&se.pre, tmp);
582 gfc_add_block_to_block (&se.pre, &se.post);
584 return gfc_finish_block (&se.pre);
588 /* Translate the STOP statement. We have to translate this statement
589 to a runtime library call. */
591 tree
592 gfc_trans_stop (gfc_code *code, bool error_stop)
594 tree gfc_int4_type_node = gfc_get_int_type (4);
595 gfc_se se;
596 tree tmp;
598 /* Start a new block for this statement. */
599 gfc_init_se (&se, NULL);
600 gfc_start_block (&se.pre);
602 if (code->expr1 == NULL)
604 tmp = build_int_cst (gfc_int4_type_node, 0);
605 tmp = build_call_expr_loc (input_location,
606 error_stop ? gfor_fndecl_error_stop_string
607 : gfor_fndecl_stop_string,
608 2, build_int_cst (pchar_type_node, 0), tmp);
610 else if (code->expr1->ts.type == BT_INTEGER)
612 gfc_conv_expr (&se, code->expr1);
613 tmp = build_call_expr_loc (input_location,
614 error_stop ? gfor_fndecl_error_stop_numeric
615 : gfor_fndecl_stop_numeric_f08, 1,
616 fold_convert (gfc_int4_type_node, se.expr));
618 else
620 gfc_conv_expr_reference (&se, code->expr1);
621 tmp = build_call_expr_loc (input_location,
622 error_stop ? gfor_fndecl_error_stop_string
623 : gfor_fndecl_stop_string,
624 2, se.expr, se.string_length);
627 gfc_add_expr_to_block (&se.pre, tmp);
629 gfc_add_block_to_block (&se.pre, &se.post);
631 return gfc_finish_block (&se.pre);
635 tree
636 gfc_trans_sync (gfc_code *code, gfc_exec_op type __attribute__ ((unused)))
638 gfc_se se;
640 if ((code->expr1 && (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)) || code->expr2)
642 gfc_init_se (&se, NULL);
643 gfc_start_block (&se.pre);
646 /* Check SYNC IMAGES(imageset) for valid image index.
647 FIXME: Add a check for image-set arrays. */
648 if (code->expr1 && (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
649 && code->expr1->rank == 0)
651 tree cond;
652 gfc_conv_expr (&se, code->expr1);
653 cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
654 se.expr, build_int_cst (TREE_TYPE (se.expr), 1));
655 gfc_trans_runtime_check (true, false, cond, &se.pre,
656 &code->expr1->where, "Invalid image number "
657 "%d in SYNC IMAGES",
658 fold_convert (integer_type_node, se.expr));
661 /* If STAT is present, set it to zero. */
662 if (code->expr2)
664 gcc_assert (code->expr2->expr_type == EXPR_VARIABLE);
665 gfc_conv_expr (&se, code->expr2);
666 gfc_add_modify (&se.pre, se.expr, build_int_cst (TREE_TYPE (se.expr), 0));
669 if ((code->expr1 && (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)) || code->expr2)
670 return gfc_finish_block (&se.pre);
672 return NULL_TREE;
676 /* Generate GENERIC for the IF construct. This function also deals with
677 the simple IF statement, because the front end translates the IF
678 statement into an IF construct.
680 We translate:
682 IF (cond) THEN
683 then_clause
684 ELSEIF (cond2)
685 elseif_clause
686 ELSE
687 else_clause
688 ENDIF
690 into:
692 pre_cond_s;
693 if (cond_s)
695 then_clause;
697 else
699 pre_cond_s
700 if (cond_s)
702 elseif_clause
704 else
706 else_clause;
710 where COND_S is the simplified version of the predicate. PRE_COND_S
711 are the pre side-effects produced by the translation of the
712 conditional.
713 We need to build the chain recursively otherwise we run into
714 problems with folding incomplete statements. */
716 static tree
717 gfc_trans_if_1 (gfc_code * code)
719 gfc_se if_se;
720 tree stmt, elsestmt;
721 locus saved_loc;
722 location_t loc;
724 /* Check for an unconditional ELSE clause. */
725 if (!code->expr1)
726 return gfc_trans_code (code->next);
728 /* Initialize a statement builder for each block. Puts in NULL_TREEs. */
729 gfc_init_se (&if_se, NULL);
730 gfc_start_block (&if_se.pre);
732 /* Calculate the IF condition expression. */
733 if (code->expr1->where.lb)
735 gfc_save_backend_locus (&saved_loc);
736 gfc_set_backend_locus (&code->expr1->where);
739 gfc_conv_expr_val (&if_se, code->expr1);
741 if (code->expr1->where.lb)
742 gfc_restore_backend_locus (&saved_loc);
744 /* Translate the THEN clause. */
745 stmt = gfc_trans_code (code->next);
747 /* Translate the ELSE clause. */
748 if (code->block)
749 elsestmt = gfc_trans_if_1 (code->block);
750 else
751 elsestmt = build_empty_stmt (input_location);
753 /* Build the condition expression and add it to the condition block. */
754 loc = code->expr1->where.lb ? code->expr1->where.lb->location : input_location;
755 stmt = fold_build3_loc (loc, COND_EXPR, void_type_node, if_se.expr, stmt,
756 elsestmt);
758 gfc_add_expr_to_block (&if_se.pre, stmt);
760 /* Finish off this statement. */
761 return gfc_finish_block (&if_se.pre);
764 tree
765 gfc_trans_if (gfc_code * code)
767 stmtblock_t body;
768 tree exit_label;
770 /* Create exit label so it is available for trans'ing the body code. */
771 exit_label = gfc_build_label_decl (NULL_TREE);
772 code->exit_label = exit_label;
774 /* Translate the actual code in code->block. */
775 gfc_init_block (&body);
776 gfc_add_expr_to_block (&body, gfc_trans_if_1 (code->block));
778 /* Add exit label. */
779 gfc_add_expr_to_block (&body, build1_v (LABEL_EXPR, exit_label));
781 return gfc_finish_block (&body);
785 /* Translate an arithmetic IF expression.
787 IF (cond) label1, label2, label3 translates to
789 if (cond <= 0)
791 if (cond < 0)
792 goto label1;
793 else // cond == 0
794 goto label2;
796 else // cond > 0
797 goto label3;
799 An optimized version can be generated in case of equal labels.
800 E.g., if label1 is equal to label2, we can translate it to
802 if (cond <= 0)
803 goto label1;
804 else
805 goto label3;
808 tree
809 gfc_trans_arithmetic_if (gfc_code * code)
811 gfc_se se;
812 tree tmp;
813 tree branch1;
814 tree branch2;
815 tree zero;
817 /* Start a new block. */
818 gfc_init_se (&se, NULL);
819 gfc_start_block (&se.pre);
821 /* Pre-evaluate COND. */
822 gfc_conv_expr_val (&se, code->expr1);
823 se.expr = gfc_evaluate_now (se.expr, &se.pre);
825 /* Build something to compare with. */
826 zero = gfc_build_const (TREE_TYPE (se.expr), integer_zero_node);
828 if (code->label1->value != code->label2->value)
830 /* If (cond < 0) take branch1 else take branch2.
831 First build jumps to the COND .LT. 0 and the COND .EQ. 0 cases. */
832 branch1 = build1_v (GOTO_EXPR, gfc_get_label_decl (code->label1));
833 branch2 = build1_v (GOTO_EXPR, gfc_get_label_decl (code->label2));
835 if (code->label1->value != code->label3->value)
836 tmp = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
837 se.expr, zero);
838 else
839 tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
840 se.expr, zero);
842 branch1 = fold_build3_loc (input_location, COND_EXPR, void_type_node,
843 tmp, branch1, branch2);
845 else
846 branch1 = build1_v (GOTO_EXPR, gfc_get_label_decl (code->label1));
848 if (code->label1->value != code->label3->value
849 && code->label2->value != code->label3->value)
851 /* if (cond <= 0) take branch1 else take branch2. */
852 branch2 = build1_v (GOTO_EXPR, gfc_get_label_decl (code->label3));
853 tmp = fold_build2_loc (input_location, LE_EXPR, boolean_type_node,
854 se.expr, zero);
855 branch1 = fold_build3_loc (input_location, COND_EXPR, void_type_node,
856 tmp, branch1, branch2);
859 /* Append the COND_EXPR to the evaluation of COND, and return. */
860 gfc_add_expr_to_block (&se.pre, branch1);
861 return gfc_finish_block (&se.pre);
865 /* Translate a CRITICAL block. */
866 tree
867 gfc_trans_critical (gfc_code *code)
869 stmtblock_t block;
870 tree tmp;
872 gfc_start_block (&block);
873 tmp = gfc_trans_code (code->block->next);
874 gfc_add_expr_to_block (&block, tmp);
876 return gfc_finish_block (&block);
880 /* Do proper initialization for ASSOCIATE names. */
882 static void
883 trans_associate_var (gfc_symbol *sym, gfc_wrapped_block *block)
885 gfc_expr *e;
886 tree tmp;
888 gcc_assert (sym->assoc);
889 e = sym->assoc->target;
891 /* Do a `pointer assignment' with updated descriptor (or assign descriptor
892 to array temporary) for arrays with either unknown shape or if associating
893 to a variable. */
894 if (sym->attr.dimension
895 && (sym->as->type == AS_DEFERRED || sym->assoc->variable))
897 gfc_se se;
898 gfc_ss *ss;
899 tree desc;
901 desc = sym->backend_decl;
903 /* If association is to an expression, evaluate it and create temporary.
904 Otherwise, get descriptor of target for pointer assignment. */
905 gfc_init_se (&se, NULL);
906 ss = gfc_walk_expr (e);
907 if (sym->assoc->variable)
909 se.direct_byref = 1;
910 se.expr = desc;
912 gfc_conv_expr_descriptor (&se, e, ss);
914 /* If we didn't already do the pointer assignment, set associate-name
915 descriptor to the one generated for the temporary. */
916 if (!sym->assoc->variable)
918 int dim;
920 gfc_add_modify (&se.pre, desc, se.expr);
922 /* The generated descriptor has lower bound zero (as array
923 temporary), shift bounds so we get lower bounds of 1. */
924 for (dim = 0; dim < e->rank; ++dim)
925 gfc_conv_shift_descriptor_lbound (&se.pre, desc,
926 dim, gfc_index_one_node);
929 /* Done, register stuff as init / cleanup code. */
930 gfc_add_init_cleanup (block, gfc_finish_block (&se.pre),
931 gfc_finish_block (&se.post));
934 /* Do a scalar pointer assignment; this is for scalar variable targets. */
935 else if (gfc_is_associate_pointer (sym))
937 gfc_se se;
939 gcc_assert (!sym->attr.dimension);
941 gfc_init_se (&se, NULL);
942 gfc_conv_expr (&se, e);
944 tmp = TREE_TYPE (sym->backend_decl);
945 tmp = gfc_build_addr_expr (tmp, se.expr);
946 gfc_add_modify (&se.pre, sym->backend_decl, tmp);
948 gfc_add_init_cleanup (block, gfc_finish_block( &se.pre),
949 gfc_finish_block (&se.post));
952 /* Do a simple assignment. This is for scalar expressions, where we
953 can simply use expression assignment. */
954 else
956 gfc_expr *lhs;
958 lhs = gfc_lval_expr_from_sym (sym);
959 tmp = gfc_trans_assignment (lhs, e, false, true);
960 gfc_add_init_cleanup (block, tmp, NULL_TREE);
965 /* Translate a BLOCK construct. This is basically what we would do for a
966 procedure body. */
968 tree
969 gfc_trans_block_construct (gfc_code* code)
971 gfc_namespace* ns;
972 gfc_symbol* sym;
973 gfc_wrapped_block block;
974 tree exit_label;
975 stmtblock_t body;
976 gfc_association_list *ass;
978 ns = code->ext.block.ns;
979 gcc_assert (ns);
980 sym = ns->proc_name;
981 gcc_assert (sym);
983 /* Process local variables. */
984 gcc_assert (!sym->tlink);
985 sym->tlink = sym;
986 gfc_process_block_locals (ns);
988 /* Generate code including exit-label. */
989 gfc_init_block (&body);
990 exit_label = gfc_build_label_decl (NULL_TREE);
991 code->exit_label = exit_label;
992 gfc_add_expr_to_block (&body, gfc_trans_code (ns->code));
993 gfc_add_expr_to_block (&body, build1_v (LABEL_EXPR, exit_label));
995 /* Finish everything. */
996 gfc_start_wrapped_block (&block, gfc_finish_block (&body));
997 gfc_trans_deferred_vars (sym, &block);
998 for (ass = code->ext.block.assoc; ass; ass = ass->next)
999 trans_associate_var (ass->st->n.sym, &block);
1001 return gfc_finish_wrapped_block (&block);
1005 /* Translate the simple DO construct. This is where the loop variable has
1006 integer type and step +-1. We can't use this in the general case
1007 because integer overflow and floating point errors could give incorrect
1008 results.
1009 We translate a do loop from:
1011 DO dovar = from, to, step
1012 body
1013 END DO
1017 [Evaluate loop bounds and step]
1018 dovar = from;
1019 if ((step > 0) ? (dovar <= to) : (dovar => to))
1021 for (;;)
1023 body;
1024 cycle_label:
1025 cond = (dovar == to);
1026 dovar += step;
1027 if (cond) goto end_label;
1030 end_label:
1032 This helps the optimizers by avoiding the extra induction variable
1033 used in the general case. */
1035 static tree
1036 gfc_trans_simple_do (gfc_code * code, stmtblock_t *pblock, tree dovar,
1037 tree from, tree to, tree step, tree exit_cond)
1039 stmtblock_t body;
1040 tree type;
1041 tree cond;
1042 tree tmp;
1043 tree saved_dovar = NULL;
1044 tree cycle_label;
1045 tree exit_label;
1046 location_t loc;
1048 type = TREE_TYPE (dovar);
1050 loc = code->ext.iterator->start->where.lb->location;
1052 /* Initialize the DO variable: dovar = from. */
1053 gfc_add_modify_loc (loc, pblock, dovar, from);
1055 /* Save value for do-tinkering checking. */
1056 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
1058 saved_dovar = gfc_create_var (type, ".saved_dovar");
1059 gfc_add_modify_loc (loc, pblock, saved_dovar, dovar);
1062 /* Cycle and exit statements are implemented with gotos. */
1063 cycle_label = gfc_build_label_decl (NULL_TREE);
1064 exit_label = gfc_build_label_decl (NULL_TREE);
1066 /* Put the labels where they can be found later. See gfc_trans_do(). */
1067 code->cycle_label = cycle_label;
1068 code->exit_label = exit_label;
1070 /* Loop body. */
1071 gfc_start_block (&body);
1073 /* Main loop body. */
1074 tmp = gfc_trans_code_cond (code->block->next, exit_cond);
1075 gfc_add_expr_to_block (&body, tmp);
1077 /* Label for cycle statements (if needed). */
1078 if (TREE_USED (cycle_label))
1080 tmp = build1_v (LABEL_EXPR, cycle_label);
1081 gfc_add_expr_to_block (&body, tmp);
1084 /* Check whether someone has modified the loop variable. */
1085 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
1087 tmp = fold_build2_loc (loc, NE_EXPR, boolean_type_node,
1088 dovar, saved_dovar);
1089 gfc_trans_runtime_check (true, false, tmp, &body, &code->loc,
1090 "Loop variable has been modified");
1093 /* Exit the loop if there is an I/O result condition or error. */
1094 if (exit_cond)
1096 tmp = build1_v (GOTO_EXPR, exit_label);
1097 tmp = fold_build3_loc (loc, COND_EXPR, void_type_node,
1098 exit_cond, tmp,
1099 build_empty_stmt (loc));
1100 gfc_add_expr_to_block (&body, tmp);
1103 /* Evaluate the loop condition. */
1104 cond = fold_build2_loc (loc, EQ_EXPR, boolean_type_node, dovar,
1105 to);
1106 cond = gfc_evaluate_now_loc (loc, cond, &body);
1108 /* Increment the loop variable. */
1109 tmp = fold_build2_loc (loc, PLUS_EXPR, type, dovar, step);
1110 gfc_add_modify_loc (loc, &body, dovar, tmp);
1112 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
1113 gfc_add_modify_loc (loc, &body, saved_dovar, dovar);
1115 /* The loop exit. */
1116 tmp = fold_build1_loc (loc, GOTO_EXPR, void_type_node, exit_label);
1117 TREE_USED (exit_label) = 1;
1118 tmp = fold_build3_loc (loc, COND_EXPR, void_type_node,
1119 cond, tmp, build_empty_stmt (loc));
1120 gfc_add_expr_to_block (&body, tmp);
1122 /* Finish the loop body. */
1123 tmp = gfc_finish_block (&body);
1124 tmp = fold_build1_loc (loc, LOOP_EXPR, void_type_node, tmp);
1126 /* Only execute the loop if the number of iterations is positive. */
1127 if (tree_int_cst_sgn (step) > 0)
1128 cond = fold_build2_loc (loc, LE_EXPR, boolean_type_node, dovar,
1129 to);
1130 else
1131 cond = fold_build2_loc (loc, GE_EXPR, boolean_type_node, dovar,
1132 to);
1133 tmp = fold_build3_loc (loc, COND_EXPR, void_type_node, cond, tmp,
1134 build_empty_stmt (loc));
1135 gfc_add_expr_to_block (pblock, tmp);
1137 /* Add the exit label. */
1138 tmp = build1_v (LABEL_EXPR, exit_label);
1139 gfc_add_expr_to_block (pblock, tmp);
1141 return gfc_finish_block (pblock);
1144 /* Translate the DO construct. This obviously is one of the most
1145 important ones to get right with any compiler, but especially
1146 so for Fortran.
1148 We special case some loop forms as described in gfc_trans_simple_do.
1149 For other cases we implement them with a separate loop count,
1150 as described in the standard.
1152 We translate a do loop from:
1154 DO dovar = from, to, step
1155 body
1156 END DO
1160 [evaluate loop bounds and step]
1161 empty = (step > 0 ? to < from : to > from);
1162 countm1 = (to - from) / step;
1163 dovar = from;
1164 if (empty) goto exit_label;
1165 for (;;)
1167 body;
1168 cycle_label:
1169 dovar += step
1170 if (countm1 ==0) goto exit_label;
1171 countm1--;
1173 exit_label:
1175 countm1 is an unsigned integer. It is equal to the loop count minus one,
1176 because the loop count itself can overflow. */
1178 tree
1179 gfc_trans_do (gfc_code * code, tree exit_cond)
1181 gfc_se se;
1182 tree dovar;
1183 tree saved_dovar = NULL;
1184 tree from;
1185 tree to;
1186 tree step;
1187 tree countm1;
1188 tree type;
1189 tree utype;
1190 tree cond;
1191 tree cycle_label;
1192 tree exit_label;
1193 tree tmp;
1194 tree pos_step;
1195 stmtblock_t block;
1196 stmtblock_t body;
1197 location_t loc;
1199 gfc_start_block (&block);
1201 loc = code->ext.iterator->start->where.lb->location;
1203 /* Evaluate all the expressions in the iterator. */
1204 gfc_init_se (&se, NULL);
1205 gfc_conv_expr_lhs (&se, code->ext.iterator->var);
1206 gfc_add_block_to_block (&block, &se.pre);
1207 dovar = se.expr;
1208 type = TREE_TYPE (dovar);
1210 gfc_init_se (&se, NULL);
1211 gfc_conv_expr_val (&se, code->ext.iterator->start);
1212 gfc_add_block_to_block (&block, &se.pre);
1213 from = gfc_evaluate_now (se.expr, &block);
1215 gfc_init_se (&se, NULL);
1216 gfc_conv_expr_val (&se, code->ext.iterator->end);
1217 gfc_add_block_to_block (&block, &se.pre);
1218 to = gfc_evaluate_now (se.expr, &block);
1220 gfc_init_se (&se, NULL);
1221 gfc_conv_expr_val (&se, code->ext.iterator->step);
1222 gfc_add_block_to_block (&block, &se.pre);
1223 step = gfc_evaluate_now (se.expr, &block);
1225 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
1227 tmp = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, step,
1228 build_zero_cst (type));
1229 gfc_trans_runtime_check (true, false, tmp, &block, &code->loc,
1230 "DO step value is zero");
1233 /* Special case simple loops. */
1234 if (TREE_CODE (type) == INTEGER_TYPE
1235 && (integer_onep (step)
1236 || tree_int_cst_equal (step, integer_minus_one_node)))
1237 return gfc_trans_simple_do (code, &block, dovar, from, to, step, exit_cond);
1239 pos_step = fold_build2_loc (loc, GT_EXPR, boolean_type_node, step,
1240 build_zero_cst (type));
1242 if (TREE_CODE (type) == INTEGER_TYPE)
1243 utype = unsigned_type_for (type);
1244 else
1245 utype = unsigned_type_for (gfc_array_index_type);
1246 countm1 = gfc_create_var (utype, "countm1");
1248 /* Cycle and exit statements are implemented with gotos. */
1249 cycle_label = gfc_build_label_decl (NULL_TREE);
1250 exit_label = gfc_build_label_decl (NULL_TREE);
1251 TREE_USED (exit_label) = 1;
1253 /* Put these labels where they can be found later. */
1254 code->cycle_label = cycle_label;
1255 code->exit_label = exit_label;
1257 /* Initialize the DO variable: dovar = from. */
1258 gfc_add_modify (&block, dovar, from);
1260 /* Save value for do-tinkering checking. */
1261 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
1263 saved_dovar = gfc_create_var (type, ".saved_dovar");
1264 gfc_add_modify_loc (loc, &block, saved_dovar, dovar);
1267 /* Initialize loop count and jump to exit label if the loop is empty.
1268 This code is executed before we enter the loop body. We generate:
1269 step_sign = sign(1,step);
1270 if (step > 0)
1272 if (to < from)
1273 goto exit_label;
1275 else
1277 if (to > from)
1278 goto exit_label;
1280 countm1 = (to*step_sign - from*step_sign) / (step*step_sign);
1284 if (TREE_CODE (type) == INTEGER_TYPE)
1286 tree pos, neg, step_sign, to2, from2, step2;
1288 /* Calculate SIGN (1,step), as (step < 0 ? -1 : 1) */
1290 tmp = fold_build2_loc (loc, LT_EXPR, boolean_type_node, step,
1291 build_int_cst (TREE_TYPE (step), 0));
1292 step_sign = fold_build3_loc (loc, COND_EXPR, type, tmp,
1293 build_int_cst (type, -1),
1294 build_int_cst (type, 1));
1296 tmp = fold_build2_loc (loc, LT_EXPR, boolean_type_node, to, from);
1297 pos = fold_build3_loc (loc, COND_EXPR, void_type_node, tmp,
1298 fold_build1_loc (loc, GOTO_EXPR, void_type_node,
1299 exit_label),
1300 build_empty_stmt (loc));
1302 tmp = fold_build2_loc (loc, GT_EXPR, boolean_type_node, to,
1303 from);
1304 neg = fold_build3_loc (loc, COND_EXPR, void_type_node, tmp,
1305 fold_build1_loc (loc, GOTO_EXPR, void_type_node,
1306 exit_label),
1307 build_empty_stmt (loc));
1308 tmp = fold_build3_loc (loc, COND_EXPR, void_type_node,
1309 pos_step, pos, neg);
1311 gfc_add_expr_to_block (&block, tmp);
1313 /* Calculate the loop count. to-from can overflow, so
1314 we cast to unsigned. */
1316 to2 = fold_build2_loc (loc, MULT_EXPR, type, step_sign, to);
1317 from2 = fold_build2_loc (loc, MULT_EXPR, type, step_sign, from);
1318 step2 = fold_build2_loc (loc, MULT_EXPR, type, step_sign, step);
1319 step2 = fold_convert (utype, step2);
1320 tmp = fold_build2_loc (loc, MINUS_EXPR, type, to2, from2);
1321 tmp = fold_convert (utype, tmp);
1322 tmp = fold_build2_loc (loc, TRUNC_DIV_EXPR, utype, tmp, step2);
1323 tmp = fold_build2_loc (loc, MODIFY_EXPR, void_type_node, countm1, tmp);
1324 gfc_add_expr_to_block (&block, tmp);
1326 else
1328 /* TODO: We could use the same width as the real type.
1329 This would probably cause more problems that it solves
1330 when we implement "long double" types. */
1332 tmp = fold_build2_loc (loc, MINUS_EXPR, type, to, from);
1333 tmp = fold_build2_loc (loc, RDIV_EXPR, type, tmp, step);
1334 tmp = fold_build1_loc (loc, FIX_TRUNC_EXPR, utype, tmp);
1335 gfc_add_modify (&block, countm1, tmp);
1337 /* We need a special check for empty loops:
1338 empty = (step > 0 ? to < from : to > from); */
1339 tmp = fold_build3_loc (loc, COND_EXPR, boolean_type_node, pos_step,
1340 fold_build2_loc (loc, LT_EXPR,
1341 boolean_type_node, to, from),
1342 fold_build2_loc (loc, GT_EXPR,
1343 boolean_type_node, to, from));
1344 /* If the loop is empty, go directly to the exit label. */
1345 tmp = fold_build3_loc (loc, COND_EXPR, void_type_node, tmp,
1346 build1_v (GOTO_EXPR, exit_label),
1347 build_empty_stmt (input_location));
1348 gfc_add_expr_to_block (&block, tmp);
1351 /* Loop body. */
1352 gfc_start_block (&body);
1354 /* Main loop body. */
1355 tmp = gfc_trans_code_cond (code->block->next, exit_cond);
1356 gfc_add_expr_to_block (&body, tmp);
1358 /* Label for cycle statements (if needed). */
1359 if (TREE_USED (cycle_label))
1361 tmp = build1_v (LABEL_EXPR, cycle_label);
1362 gfc_add_expr_to_block (&body, tmp);
1365 /* Check whether someone has modified the loop variable. */
1366 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
1368 tmp = fold_build2_loc (loc, NE_EXPR, boolean_type_node, dovar,
1369 saved_dovar);
1370 gfc_trans_runtime_check (true, false, tmp, &body, &code->loc,
1371 "Loop variable has been modified");
1374 /* Exit the loop if there is an I/O result condition or error. */
1375 if (exit_cond)
1377 tmp = build1_v (GOTO_EXPR, exit_label);
1378 tmp = fold_build3_loc (loc, COND_EXPR, void_type_node,
1379 exit_cond, tmp,
1380 build_empty_stmt (input_location));
1381 gfc_add_expr_to_block (&body, tmp);
1384 /* Increment the loop variable. */
1385 tmp = fold_build2_loc (loc, PLUS_EXPR, type, dovar, step);
1386 gfc_add_modify_loc (loc, &body, dovar, tmp);
1388 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
1389 gfc_add_modify_loc (loc, &body, saved_dovar, dovar);
1391 /* End with the loop condition. Loop until countm1 == 0. */
1392 cond = fold_build2_loc (loc, EQ_EXPR, boolean_type_node, countm1,
1393 build_int_cst (utype, 0));
1394 tmp = fold_build1_loc (loc, GOTO_EXPR, void_type_node, exit_label);
1395 tmp = fold_build3_loc (loc, COND_EXPR, void_type_node,
1396 cond, tmp, build_empty_stmt (loc));
1397 gfc_add_expr_to_block (&body, tmp);
1399 /* Decrement the loop count. */
1400 tmp = fold_build2_loc (loc, MINUS_EXPR, utype, countm1,
1401 build_int_cst (utype, 1));
1402 gfc_add_modify_loc (loc, &body, countm1, tmp);
1404 /* End of loop body. */
1405 tmp = gfc_finish_block (&body);
1407 /* The for loop itself. */
1408 tmp = fold_build1_loc (loc, LOOP_EXPR, void_type_node, tmp);
1409 gfc_add_expr_to_block (&block, tmp);
1411 /* Add the exit label. */
1412 tmp = build1_v (LABEL_EXPR, exit_label);
1413 gfc_add_expr_to_block (&block, tmp);
1415 return gfc_finish_block (&block);
1419 /* Translate the DO WHILE construct.
1421 We translate
1423 DO WHILE (cond)
1424 body
1425 END DO
1429 for ( ; ; )
1431 pre_cond;
1432 if (! cond) goto exit_label;
1433 body;
1434 cycle_label:
1436 exit_label:
1438 Because the evaluation of the exit condition `cond' may have side
1439 effects, we can't do much for empty loop bodies. The backend optimizers
1440 should be smart enough to eliminate any dead loops. */
1442 tree
1443 gfc_trans_do_while (gfc_code * code)
1445 gfc_se cond;
1446 tree tmp;
1447 tree cycle_label;
1448 tree exit_label;
1449 stmtblock_t block;
1451 /* Everything we build here is part of the loop body. */
1452 gfc_start_block (&block);
1454 /* Cycle and exit statements are implemented with gotos. */
1455 cycle_label = gfc_build_label_decl (NULL_TREE);
1456 exit_label = gfc_build_label_decl (NULL_TREE);
1458 /* Put the labels where they can be found later. See gfc_trans_do(). */
1459 code->cycle_label = cycle_label;
1460 code->exit_label = exit_label;
1462 /* Create a GIMPLE version of the exit condition. */
1463 gfc_init_se (&cond, NULL);
1464 gfc_conv_expr_val (&cond, code->expr1);
1465 gfc_add_block_to_block (&block, &cond.pre);
1466 cond.expr = fold_build1_loc (code->expr1->where.lb->location,
1467 TRUTH_NOT_EXPR, boolean_type_node, cond.expr);
1469 /* Build "IF (! cond) GOTO exit_label". */
1470 tmp = build1_v (GOTO_EXPR, exit_label);
1471 TREE_USED (exit_label) = 1;
1472 tmp = fold_build3_loc (code->expr1->where.lb->location, COND_EXPR,
1473 void_type_node, cond.expr, tmp,
1474 build_empty_stmt (code->expr1->where.lb->location));
1475 gfc_add_expr_to_block (&block, tmp);
1477 /* The main body of the loop. */
1478 tmp = gfc_trans_code (code->block->next);
1479 gfc_add_expr_to_block (&block, tmp);
1481 /* Label for cycle statements (if needed). */
1482 if (TREE_USED (cycle_label))
1484 tmp = build1_v (LABEL_EXPR, cycle_label);
1485 gfc_add_expr_to_block (&block, tmp);
1488 /* End of loop body. */
1489 tmp = gfc_finish_block (&block);
1491 gfc_init_block (&block);
1492 /* Build the loop. */
1493 tmp = fold_build1_loc (code->expr1->where.lb->location, LOOP_EXPR,
1494 void_type_node, tmp);
1495 gfc_add_expr_to_block (&block, tmp);
1497 /* Add the exit label. */
1498 tmp = build1_v (LABEL_EXPR, exit_label);
1499 gfc_add_expr_to_block (&block, tmp);
1501 return gfc_finish_block (&block);
1505 /* Translate the SELECT CASE construct for INTEGER case expressions,
1506 without killing all potential optimizations. The problem is that
1507 Fortran allows unbounded cases, but the back-end does not, so we
1508 need to intercept those before we enter the equivalent SWITCH_EXPR
1509 we can build.
1511 For example, we translate this,
1513 SELECT CASE (expr)
1514 CASE (:100,101,105:115)
1515 block_1
1516 CASE (190:199,200:)
1517 block_2
1518 CASE (300)
1519 block_3
1520 CASE DEFAULT
1521 block_4
1522 END SELECT
1524 to the GENERIC equivalent,
1526 switch (expr)
1528 case (minimum value for typeof(expr) ... 100:
1529 case 101:
1530 case 105 ... 114:
1531 block1:
1532 goto end_label;
1534 case 200 ... (maximum value for typeof(expr):
1535 case 190 ... 199:
1536 block2;
1537 goto end_label;
1539 case 300:
1540 block_3;
1541 goto end_label;
1543 default:
1544 block_4;
1545 goto end_label;
1548 end_label: */
1550 static tree
1551 gfc_trans_integer_select (gfc_code * code)
1553 gfc_code *c;
1554 gfc_case *cp;
1555 tree end_label;
1556 tree tmp;
1557 gfc_se se;
1558 stmtblock_t block;
1559 stmtblock_t body;
1561 gfc_start_block (&block);
1563 /* Calculate the switch expression. */
1564 gfc_init_se (&se, NULL);
1565 gfc_conv_expr_val (&se, code->expr1);
1566 gfc_add_block_to_block (&block, &se.pre);
1568 end_label = gfc_build_label_decl (NULL_TREE);
1570 gfc_init_block (&body);
1572 for (c = code->block; c; c = c->block)
1574 for (cp = c->ext.block.case_list; cp; cp = cp->next)
1576 tree low, high;
1577 tree label;
1579 /* Assume it's the default case. */
1580 low = high = NULL_TREE;
1582 if (cp->low)
1584 low = gfc_conv_mpz_to_tree (cp->low->value.integer,
1585 cp->low->ts.kind);
1587 /* If there's only a lower bound, set the high bound to the
1588 maximum value of the case expression. */
1589 if (!cp->high)
1590 high = TYPE_MAX_VALUE (TREE_TYPE (se.expr));
1593 if (cp->high)
1595 /* Three cases are possible here:
1597 1) There is no lower bound, e.g. CASE (:N).
1598 2) There is a lower bound .NE. high bound, that is
1599 a case range, e.g. CASE (N:M) where M>N (we make
1600 sure that M>N during type resolution).
1601 3) There is a lower bound, and it has the same value
1602 as the high bound, e.g. CASE (N:N). This is our
1603 internal representation of CASE(N).
1605 In the first and second case, we need to set a value for
1606 high. In the third case, we don't because the GCC middle
1607 end represents a single case value by just letting high be
1608 a NULL_TREE. We can't do that because we need to be able
1609 to represent unbounded cases. */
1611 if (!cp->low
1612 || (cp->low
1613 && mpz_cmp (cp->low->value.integer,
1614 cp->high->value.integer) != 0))
1615 high = gfc_conv_mpz_to_tree (cp->high->value.integer,
1616 cp->high->ts.kind);
1618 /* Unbounded case. */
1619 if (!cp->low)
1620 low = TYPE_MIN_VALUE (TREE_TYPE (se.expr));
1623 /* Build a label. */
1624 label = gfc_build_label_decl (NULL_TREE);
1626 /* Add this case label.
1627 Add parameter 'label', make it match GCC backend. */
1628 tmp = fold_build3_loc (input_location, CASE_LABEL_EXPR,
1629 void_type_node, low, high, label);
1630 gfc_add_expr_to_block (&body, tmp);
1633 /* Add the statements for this case. */
1634 tmp = gfc_trans_code (c->next);
1635 gfc_add_expr_to_block (&body, tmp);
1637 /* Break to the end of the construct. */
1638 tmp = build1_v (GOTO_EXPR, end_label);
1639 gfc_add_expr_to_block (&body, tmp);
1642 tmp = gfc_finish_block (&body);
1643 tmp = build3_v (SWITCH_EXPR, se.expr, tmp, NULL_TREE);
1644 gfc_add_expr_to_block (&block, tmp);
1646 tmp = build1_v (LABEL_EXPR, end_label);
1647 gfc_add_expr_to_block (&block, tmp);
1649 return gfc_finish_block (&block);
1653 /* Translate the SELECT CASE construct for LOGICAL case expressions.
1655 There are only two cases possible here, even though the standard
1656 does allow three cases in a LOGICAL SELECT CASE construct: .TRUE.,
1657 .FALSE., and DEFAULT.
1659 We never generate more than two blocks here. Instead, we always
1660 try to eliminate the DEFAULT case. This way, we can translate this
1661 kind of SELECT construct to a simple
1663 if {} else {};
1665 expression in GENERIC. */
1667 static tree
1668 gfc_trans_logical_select (gfc_code * code)
1670 gfc_code *c;
1671 gfc_code *t, *f, *d;
1672 gfc_case *cp;
1673 gfc_se se;
1674 stmtblock_t block;
1676 /* Assume we don't have any cases at all. */
1677 t = f = d = NULL;
1679 /* Now see which ones we actually do have. We can have at most two
1680 cases in a single case list: one for .TRUE. and one for .FALSE.
1681 The default case is always separate. If the cases for .TRUE. and
1682 .FALSE. are in the same case list, the block for that case list
1683 always executed, and we don't generate code a COND_EXPR. */
1684 for (c = code->block; c; c = c->block)
1686 for (cp = c->ext.block.case_list; cp; cp = cp->next)
1688 if (cp->low)
1690 if (cp->low->value.logical == 0) /* .FALSE. */
1691 f = c;
1692 else /* if (cp->value.logical != 0), thus .TRUE. */
1693 t = c;
1695 else
1696 d = c;
1700 /* Start a new block. */
1701 gfc_start_block (&block);
1703 /* Calculate the switch expression. We always need to do this
1704 because it may have side effects. */
1705 gfc_init_se (&se, NULL);
1706 gfc_conv_expr_val (&se, code->expr1);
1707 gfc_add_block_to_block (&block, &se.pre);
1709 if (t == f && t != NULL)
1711 /* Cases for .TRUE. and .FALSE. are in the same block. Just
1712 translate the code for these cases, append it to the current
1713 block. */
1714 gfc_add_expr_to_block (&block, gfc_trans_code (t->next));
1716 else
1718 tree true_tree, false_tree, stmt;
1720 true_tree = build_empty_stmt (input_location);
1721 false_tree = build_empty_stmt (input_location);
1723 /* If we have a case for .TRUE. and for .FALSE., discard the default case.
1724 Otherwise, if .TRUE. or .FALSE. is missing and there is a default case,
1725 make the missing case the default case. */
1726 if (t != NULL && f != NULL)
1727 d = NULL;
1728 else if (d != NULL)
1730 if (t == NULL)
1731 t = d;
1732 else
1733 f = d;
1736 /* Translate the code for each of these blocks, and append it to
1737 the current block. */
1738 if (t != NULL)
1739 true_tree = gfc_trans_code (t->next);
1741 if (f != NULL)
1742 false_tree = gfc_trans_code (f->next);
1744 stmt = fold_build3_loc (input_location, COND_EXPR, void_type_node,
1745 se.expr, true_tree, false_tree);
1746 gfc_add_expr_to_block (&block, stmt);
1749 return gfc_finish_block (&block);
1753 /* The jump table types are stored in static variables to avoid
1754 constructing them from scratch every single time. */
1755 static GTY(()) tree select_struct[2];
1757 /* Translate the SELECT CASE construct for CHARACTER case expressions.
1758 Instead of generating compares and jumps, it is far simpler to
1759 generate a data structure describing the cases in order and call a
1760 library subroutine that locates the right case.
1761 This is particularly true because this is the only case where we
1762 might have to dispose of a temporary.
1763 The library subroutine returns a pointer to jump to or NULL if no
1764 branches are to be taken. */
1766 static tree
1767 gfc_trans_character_select (gfc_code *code)
1769 tree init, end_label, tmp, type, case_num, label, fndecl;
1770 stmtblock_t block, body;
1771 gfc_case *cp, *d;
1772 gfc_code *c;
1773 gfc_se se, expr1se;
1774 int n, k;
1775 VEC(constructor_elt,gc) *inits = NULL;
1777 tree pchartype = gfc_get_pchar_type (code->expr1->ts.kind);
1779 /* The jump table types are stored in static variables to avoid
1780 constructing them from scratch every single time. */
1781 static tree ss_string1[2], ss_string1_len[2];
1782 static tree ss_string2[2], ss_string2_len[2];
1783 static tree ss_target[2];
1785 cp = code->block->ext.block.case_list;
1786 while (cp->left != NULL)
1787 cp = cp->left;
1789 /* Generate the body */
1790 gfc_start_block (&block);
1791 gfc_init_se (&expr1se, NULL);
1792 gfc_conv_expr_reference (&expr1se, code->expr1);
1794 gfc_add_block_to_block (&block, &expr1se.pre);
1796 end_label = gfc_build_label_decl (NULL_TREE);
1798 gfc_init_block (&body);
1800 /* Attempt to optimize length 1 selects. */
1801 if (integer_onep (expr1se.string_length))
1803 for (d = cp; d; d = d->right)
1805 int i;
1806 if (d->low)
1808 gcc_assert (d->low->expr_type == EXPR_CONSTANT
1809 && d->low->ts.type == BT_CHARACTER);
1810 if (d->low->value.character.length > 1)
1812 for (i = 1; i < d->low->value.character.length; i++)
1813 if (d->low->value.character.string[i] != ' ')
1814 break;
1815 if (i != d->low->value.character.length)
1817 if (optimize && d->high && i == 1)
1819 gcc_assert (d->high->expr_type == EXPR_CONSTANT
1820 && d->high->ts.type == BT_CHARACTER);
1821 if (d->high->value.character.length > 1
1822 && (d->low->value.character.string[0]
1823 == d->high->value.character.string[0])
1824 && d->high->value.character.string[1] != ' '
1825 && ((d->low->value.character.string[1] < ' ')
1826 == (d->high->value.character.string[1]
1827 < ' ')))
1828 continue;
1830 break;
1834 if (d->high)
1836 gcc_assert (d->high->expr_type == EXPR_CONSTANT
1837 && d->high->ts.type == BT_CHARACTER);
1838 if (d->high->value.character.length > 1)
1840 for (i = 1; i < d->high->value.character.length; i++)
1841 if (d->high->value.character.string[i] != ' ')
1842 break;
1843 if (i != d->high->value.character.length)
1844 break;
1848 if (d == NULL)
1850 tree ctype = gfc_get_char_type (code->expr1->ts.kind);
1852 for (c = code->block; c; c = c->block)
1854 for (cp = c->ext.block.case_list; cp; cp = cp->next)
1856 tree low, high;
1857 tree label;
1858 gfc_char_t r;
1860 /* Assume it's the default case. */
1861 low = high = NULL_TREE;
1863 if (cp->low)
1865 /* CASE ('ab') or CASE ('ab':'az') will never match
1866 any length 1 character. */
1867 if (cp->low->value.character.length > 1
1868 && cp->low->value.character.string[1] != ' ')
1869 continue;
1871 if (cp->low->value.character.length > 0)
1872 r = cp->low->value.character.string[0];
1873 else
1874 r = ' ';
1875 low = build_int_cst (ctype, r);
1877 /* If there's only a lower bound, set the high bound
1878 to the maximum value of the case expression. */
1879 if (!cp->high)
1880 high = TYPE_MAX_VALUE (ctype);
1883 if (cp->high)
1885 if (!cp->low
1886 || (cp->low->value.character.string[0]
1887 != cp->high->value.character.string[0]))
1889 if (cp->high->value.character.length > 0)
1890 r = cp->high->value.character.string[0];
1891 else
1892 r = ' ';
1893 high = build_int_cst (ctype, r);
1896 /* Unbounded case. */
1897 if (!cp->low)
1898 low = TYPE_MIN_VALUE (ctype);
1901 /* Build a label. */
1902 label = gfc_build_label_decl (NULL_TREE);
1904 /* Add this case label.
1905 Add parameter 'label', make it match GCC backend. */
1906 tmp = fold_build3_loc (input_location, CASE_LABEL_EXPR,
1907 void_type_node, low, high, label);
1908 gfc_add_expr_to_block (&body, tmp);
1911 /* Add the statements for this case. */
1912 tmp = gfc_trans_code (c->next);
1913 gfc_add_expr_to_block (&body, tmp);
1915 /* Break to the end of the construct. */
1916 tmp = build1_v (GOTO_EXPR, end_label);
1917 gfc_add_expr_to_block (&body, tmp);
1920 tmp = gfc_string_to_single_character (expr1se.string_length,
1921 expr1se.expr,
1922 code->expr1->ts.kind);
1923 case_num = gfc_create_var (ctype, "case_num");
1924 gfc_add_modify (&block, case_num, tmp);
1926 gfc_add_block_to_block (&block, &expr1se.post);
1928 tmp = gfc_finish_block (&body);
1929 tmp = build3_v (SWITCH_EXPR, case_num, tmp, NULL_TREE);
1930 gfc_add_expr_to_block (&block, tmp);
1932 tmp = build1_v (LABEL_EXPR, end_label);
1933 gfc_add_expr_to_block (&block, tmp);
1935 return gfc_finish_block (&block);
1939 if (code->expr1->ts.kind == 1)
1940 k = 0;
1941 else if (code->expr1->ts.kind == 4)
1942 k = 1;
1943 else
1944 gcc_unreachable ();
1946 if (select_struct[k] == NULL)
1948 tree *chain = NULL;
1949 select_struct[k] = make_node (RECORD_TYPE);
1951 if (code->expr1->ts.kind == 1)
1952 TYPE_NAME (select_struct[k]) = get_identifier ("_jump_struct_char1");
1953 else if (code->expr1->ts.kind == 4)
1954 TYPE_NAME (select_struct[k]) = get_identifier ("_jump_struct_char4");
1955 else
1956 gcc_unreachable ();
1958 #undef ADD_FIELD
1959 #define ADD_FIELD(NAME, TYPE) \
1960 ss_##NAME[k] = gfc_add_field_to_struct (select_struct[k], \
1961 get_identifier (stringize(NAME)), \
1962 TYPE, \
1963 &chain)
1965 ADD_FIELD (string1, pchartype);
1966 ADD_FIELD (string1_len, gfc_charlen_type_node);
1968 ADD_FIELD (string2, pchartype);
1969 ADD_FIELD (string2_len, gfc_charlen_type_node);
1971 ADD_FIELD (target, integer_type_node);
1972 #undef ADD_FIELD
1974 gfc_finish_type (select_struct[k]);
1977 n = 0;
1978 for (d = cp; d; d = d->right)
1979 d->n = n++;
1981 for (c = code->block; c; c = c->block)
1983 for (d = c->ext.block.case_list; d; d = d->next)
1985 label = gfc_build_label_decl (NULL_TREE);
1986 tmp = fold_build3_loc (input_location, CASE_LABEL_EXPR,
1987 void_type_node,
1988 (d->low == NULL && d->high == NULL)
1989 ? NULL : build_int_cst (NULL_TREE, d->n),
1990 NULL, label);
1991 gfc_add_expr_to_block (&body, tmp);
1994 tmp = gfc_trans_code (c->next);
1995 gfc_add_expr_to_block (&body, tmp);
1997 tmp = build1_v (GOTO_EXPR, end_label);
1998 gfc_add_expr_to_block (&body, tmp);
2001 /* Generate the structure describing the branches */
2002 for (d = cp; d; d = d->right)
2004 VEC(constructor_elt,gc) *node = NULL;
2006 gfc_init_se (&se, NULL);
2008 if (d->low == NULL)
2010 CONSTRUCTOR_APPEND_ELT (node, ss_string1[k], null_pointer_node);
2011 CONSTRUCTOR_APPEND_ELT (node, ss_string1_len[k], integer_zero_node);
2013 else
2015 gfc_conv_expr_reference (&se, d->low);
2017 CONSTRUCTOR_APPEND_ELT (node, ss_string1[k], se.expr);
2018 CONSTRUCTOR_APPEND_ELT (node, ss_string1_len[k], se.string_length);
2021 if (d->high == NULL)
2023 CONSTRUCTOR_APPEND_ELT (node, ss_string2[k], null_pointer_node);
2024 CONSTRUCTOR_APPEND_ELT (node, ss_string2_len[k], integer_zero_node);
2026 else
2028 gfc_init_se (&se, NULL);
2029 gfc_conv_expr_reference (&se, d->high);
2031 CONSTRUCTOR_APPEND_ELT (node, ss_string2[k], se.expr);
2032 CONSTRUCTOR_APPEND_ELT (node, ss_string2_len[k], se.string_length);
2035 CONSTRUCTOR_APPEND_ELT (node, ss_target[k],
2036 build_int_cst (integer_type_node, d->n));
2038 tmp = build_constructor (select_struct[k], node);
2039 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, tmp);
2042 type = build_array_type (select_struct[k],
2043 build_index_type (build_int_cst (NULL_TREE, n-1)));
2045 init = build_constructor (type, inits);
2046 TREE_CONSTANT (init) = 1;
2047 TREE_STATIC (init) = 1;
2048 /* Create a static variable to hold the jump table. */
2049 tmp = gfc_create_var (type, "jumptable");
2050 TREE_CONSTANT (tmp) = 1;
2051 TREE_STATIC (tmp) = 1;
2052 TREE_READONLY (tmp) = 1;
2053 DECL_INITIAL (tmp) = init;
2054 init = tmp;
2056 /* Build the library call */
2057 init = gfc_build_addr_expr (pvoid_type_node, init);
2059 if (code->expr1->ts.kind == 1)
2060 fndecl = gfor_fndecl_select_string;
2061 else if (code->expr1->ts.kind == 4)
2062 fndecl = gfor_fndecl_select_string_char4;
2063 else
2064 gcc_unreachable ();
2066 tmp = build_call_expr_loc (input_location,
2067 fndecl, 4, init, build_int_cst (NULL_TREE, n),
2068 expr1se.expr, expr1se.string_length);
2069 case_num = gfc_create_var (integer_type_node, "case_num");
2070 gfc_add_modify (&block, case_num, tmp);
2072 gfc_add_block_to_block (&block, &expr1se.post);
2074 tmp = gfc_finish_block (&body);
2075 tmp = build3_v (SWITCH_EXPR, case_num, tmp, NULL_TREE);
2076 gfc_add_expr_to_block (&block, tmp);
2078 tmp = build1_v (LABEL_EXPR, end_label);
2079 gfc_add_expr_to_block (&block, tmp);
2081 return gfc_finish_block (&block);
2085 /* Translate the three variants of the SELECT CASE construct.
2087 SELECT CASEs with INTEGER case expressions can be translated to an
2088 equivalent GENERIC switch statement, and for LOGICAL case
2089 expressions we build one or two if-else compares.
2091 SELECT CASEs with CHARACTER case expressions are a whole different
2092 story, because they don't exist in GENERIC. So we sort them and
2093 do a binary search at runtime.
2095 Fortran has no BREAK statement, and it does not allow jumps from
2096 one case block to another. That makes things a lot easier for
2097 the optimizers. */
2099 tree
2100 gfc_trans_select (gfc_code * code)
2102 stmtblock_t block;
2103 tree body;
2104 tree exit_label;
2106 gcc_assert (code && code->expr1);
2107 gfc_init_block (&block);
2109 /* Build the exit label and hang it in. */
2110 exit_label = gfc_build_label_decl (NULL_TREE);
2111 code->exit_label = exit_label;
2113 /* Empty SELECT constructs are legal. */
2114 if (code->block == NULL)
2115 body = build_empty_stmt (input_location);
2117 /* Select the correct translation function. */
2118 else
2119 switch (code->expr1->ts.type)
2121 case BT_LOGICAL:
2122 body = gfc_trans_logical_select (code);
2123 break;
2125 case BT_INTEGER:
2126 body = gfc_trans_integer_select (code);
2127 break;
2129 case BT_CHARACTER:
2130 body = gfc_trans_character_select (code);
2131 break;
2133 default:
2134 gfc_internal_error ("gfc_trans_select(): Bad type for case expr.");
2135 /* Not reached */
2138 /* Build everything together. */
2139 gfc_add_expr_to_block (&block, body);
2140 gfc_add_expr_to_block (&block, build1_v (LABEL_EXPR, exit_label));
2142 return gfc_finish_block (&block);
2146 /* Traversal function to substitute a replacement symtree if the symbol
2147 in the expression is the same as that passed. f == 2 signals that
2148 that variable itself is not to be checked - only the references.
2149 This group of functions is used when the variable expression in a
2150 FORALL assignment has internal references. For example:
2151 FORALL (i = 1:4) p(p(i)) = i
2152 The only recourse here is to store a copy of 'p' for the index
2153 expression. */
2155 static gfc_symtree *new_symtree;
2156 static gfc_symtree *old_symtree;
2158 static bool
2159 forall_replace (gfc_expr *expr, gfc_symbol *sym, int *f)
2161 if (expr->expr_type != EXPR_VARIABLE)
2162 return false;
2164 if (*f == 2)
2165 *f = 1;
2166 else if (expr->symtree->n.sym == sym)
2167 expr->symtree = new_symtree;
2169 return false;
2172 static void
2173 forall_replace_symtree (gfc_expr *e, gfc_symbol *sym, int f)
2175 gfc_traverse_expr (e, sym, forall_replace, f);
2178 static bool
2179 forall_restore (gfc_expr *expr,
2180 gfc_symbol *sym ATTRIBUTE_UNUSED,
2181 int *f ATTRIBUTE_UNUSED)
2183 if (expr->expr_type != EXPR_VARIABLE)
2184 return false;
2186 if (expr->symtree == new_symtree)
2187 expr->symtree = old_symtree;
2189 return false;
2192 static void
2193 forall_restore_symtree (gfc_expr *e)
2195 gfc_traverse_expr (e, NULL, forall_restore, 0);
2198 static void
2199 forall_make_variable_temp (gfc_code *c, stmtblock_t *pre, stmtblock_t *post)
2201 gfc_se tse;
2202 gfc_se rse;
2203 gfc_expr *e;
2204 gfc_symbol *new_sym;
2205 gfc_symbol *old_sym;
2206 gfc_symtree *root;
2207 tree tmp;
2209 /* Build a copy of the lvalue. */
2210 old_symtree = c->expr1->symtree;
2211 old_sym = old_symtree->n.sym;
2212 e = gfc_lval_expr_from_sym (old_sym);
2213 if (old_sym->attr.dimension)
2215 gfc_init_se (&tse, NULL);
2216 gfc_conv_subref_array_arg (&tse, e, 0, INTENT_IN, false);
2217 gfc_add_block_to_block (pre, &tse.pre);
2218 gfc_add_block_to_block (post, &tse.post);
2219 tse.expr = build_fold_indirect_ref_loc (input_location, tse.expr);
2221 if (e->ts.type != BT_CHARACTER)
2223 /* Use the variable offset for the temporary. */
2224 tmp = gfc_conv_array_offset (old_sym->backend_decl);
2225 gfc_conv_descriptor_offset_set (pre, tse.expr, tmp);
2228 else
2230 gfc_init_se (&tse, NULL);
2231 gfc_init_se (&rse, NULL);
2232 gfc_conv_expr (&rse, e);
2233 if (e->ts.type == BT_CHARACTER)
2235 tse.string_length = rse.string_length;
2236 tmp = gfc_get_character_type_len (gfc_default_character_kind,
2237 tse.string_length);
2238 tse.expr = gfc_conv_string_tmp (&tse, build_pointer_type (tmp),
2239 rse.string_length);
2240 gfc_add_block_to_block (pre, &tse.pre);
2241 gfc_add_block_to_block (post, &tse.post);
2243 else
2245 tmp = gfc_typenode_for_spec (&e->ts);
2246 tse.expr = gfc_create_var (tmp, "temp");
2249 tmp = gfc_trans_scalar_assign (&tse, &rse, e->ts, true,
2250 e->expr_type == EXPR_VARIABLE, true);
2251 gfc_add_expr_to_block (pre, tmp);
2253 gfc_free_expr (e);
2255 /* Create a new symbol to represent the lvalue. */
2256 new_sym = gfc_new_symbol (old_sym->name, NULL);
2257 new_sym->ts = old_sym->ts;
2258 new_sym->attr.referenced = 1;
2259 new_sym->attr.temporary = 1;
2260 new_sym->attr.dimension = old_sym->attr.dimension;
2261 new_sym->attr.flavor = old_sym->attr.flavor;
2263 /* Use the temporary as the backend_decl. */
2264 new_sym->backend_decl = tse.expr;
2266 /* Create a fake symtree for it. */
2267 root = NULL;
2268 new_symtree = gfc_new_symtree (&root, old_sym->name);
2269 new_symtree->n.sym = new_sym;
2270 gcc_assert (new_symtree == root);
2272 /* Go through the expression reference replacing the old_symtree
2273 with the new. */
2274 forall_replace_symtree (c->expr1, old_sym, 2);
2276 /* Now we have made this temporary, we might as well use it for
2277 the right hand side. */
2278 forall_replace_symtree (c->expr2, old_sym, 1);
2282 /* Handles dependencies in forall assignments. */
2283 static int
2284 check_forall_dependencies (gfc_code *c, stmtblock_t *pre, stmtblock_t *post)
2286 gfc_ref *lref;
2287 gfc_ref *rref;
2288 int need_temp;
2289 gfc_symbol *lsym;
2291 lsym = c->expr1->symtree->n.sym;
2292 need_temp = gfc_check_dependency (c->expr1, c->expr2, 0);
2294 /* Now check for dependencies within the 'variable'
2295 expression itself. These are treated by making a complete
2296 copy of variable and changing all the references to it
2297 point to the copy instead. Note that the shallow copy of
2298 the variable will not suffice for derived types with
2299 pointer components. We therefore leave these to their
2300 own devices. */
2301 if (lsym->ts.type == BT_DERIVED
2302 && lsym->ts.u.derived->attr.pointer_comp)
2303 return need_temp;
2305 new_symtree = NULL;
2306 if (find_forall_index (c->expr1, lsym, 2) == SUCCESS)
2308 forall_make_variable_temp (c, pre, post);
2309 need_temp = 0;
2312 /* Substrings with dependencies are treated in the same
2313 way. */
2314 if (c->expr1->ts.type == BT_CHARACTER
2315 && c->expr1->ref
2316 && c->expr2->expr_type == EXPR_VARIABLE
2317 && lsym == c->expr2->symtree->n.sym)
2319 for (lref = c->expr1->ref; lref; lref = lref->next)
2320 if (lref->type == REF_SUBSTRING)
2321 break;
2322 for (rref = c->expr2->ref; rref; rref = rref->next)
2323 if (rref->type == REF_SUBSTRING)
2324 break;
2326 if (rref && lref
2327 && gfc_dep_compare_expr (rref->u.ss.start, lref->u.ss.start) < 0)
2329 forall_make_variable_temp (c, pre, post);
2330 need_temp = 0;
2333 return need_temp;
2337 static void
2338 cleanup_forall_symtrees (gfc_code *c)
2340 forall_restore_symtree (c->expr1);
2341 forall_restore_symtree (c->expr2);
2342 gfc_free (new_symtree->n.sym);
2343 gfc_free (new_symtree);
2347 /* Generate the loops for a FORALL block, specified by FORALL_TMP. BODY
2348 is the contents of the FORALL block/stmt to be iterated. MASK_FLAG
2349 indicates whether we should generate code to test the FORALLs mask
2350 array. OUTER is the loop header to be used for initializing mask
2351 indices.
2353 The generated loop format is:
2354 count = (end - start + step) / step
2355 loopvar = start
2356 while (1)
2358 if (count <=0 )
2359 goto end_of_loop
2360 <body>
2361 loopvar += step
2362 count --
2364 end_of_loop: */
2366 static tree
2367 gfc_trans_forall_loop (forall_info *forall_tmp, tree body,
2368 int mask_flag, stmtblock_t *outer)
2370 int n, nvar;
2371 tree tmp;
2372 tree cond;
2373 stmtblock_t block;
2374 tree exit_label;
2375 tree count;
2376 tree var, start, end, step;
2377 iter_info *iter;
2379 /* Initialize the mask index outside the FORALL nest. */
2380 if (mask_flag && forall_tmp->mask)
2381 gfc_add_modify (outer, forall_tmp->maskindex, gfc_index_zero_node);
2383 iter = forall_tmp->this_loop;
2384 nvar = forall_tmp->nvar;
2385 for (n = 0; n < nvar; n++)
2387 var = iter->var;
2388 start = iter->start;
2389 end = iter->end;
2390 step = iter->step;
2392 exit_label = gfc_build_label_decl (NULL_TREE);
2393 TREE_USED (exit_label) = 1;
2395 /* The loop counter. */
2396 count = gfc_create_var (TREE_TYPE (var), "count");
2398 /* The body of the loop. */
2399 gfc_init_block (&block);
2401 /* The exit condition. */
2402 cond = fold_build2_loc (input_location, LE_EXPR, boolean_type_node,
2403 count, build_int_cst (TREE_TYPE (count), 0));
2404 tmp = build1_v (GOTO_EXPR, exit_label);
2405 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
2406 cond, tmp, build_empty_stmt (input_location));
2407 gfc_add_expr_to_block (&block, tmp);
2409 /* The main loop body. */
2410 gfc_add_expr_to_block (&block, body);
2412 /* Increment the loop variable. */
2413 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (var), var,
2414 step);
2415 gfc_add_modify (&block, var, tmp);
2417 /* Advance to the next mask element. Only do this for the
2418 innermost loop. */
2419 if (n == 0 && mask_flag && forall_tmp->mask)
2421 tree maskindex = forall_tmp->maskindex;
2422 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
2423 maskindex, gfc_index_one_node);
2424 gfc_add_modify (&block, maskindex, tmp);
2427 /* Decrement the loop counter. */
2428 tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (var), count,
2429 build_int_cst (TREE_TYPE (var), 1));
2430 gfc_add_modify (&block, count, tmp);
2432 body = gfc_finish_block (&block);
2434 /* Loop var initialization. */
2435 gfc_init_block (&block);
2436 gfc_add_modify (&block, var, start);
2439 /* Initialize the loop counter. */
2440 tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (var), step,
2441 start);
2442 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (var), end,
2443 tmp);
2444 tmp = fold_build2_loc (input_location, TRUNC_DIV_EXPR, TREE_TYPE (var),
2445 tmp, step);
2446 gfc_add_modify (&block, count, tmp);
2448 /* The loop expression. */
2449 tmp = build1_v (LOOP_EXPR, body);
2450 gfc_add_expr_to_block (&block, tmp);
2452 /* The exit label. */
2453 tmp = build1_v (LABEL_EXPR, exit_label);
2454 gfc_add_expr_to_block (&block, tmp);
2456 body = gfc_finish_block (&block);
2457 iter = iter->next;
2459 return body;
2463 /* Generate the body and loops according to MASK_FLAG. If MASK_FLAG
2464 is nonzero, the body is controlled by all masks in the forall nest.
2465 Otherwise, the innermost loop is not controlled by it's mask. This
2466 is used for initializing that mask. */
2468 static tree
2469 gfc_trans_nested_forall_loop (forall_info * nested_forall_info, tree body,
2470 int mask_flag)
2472 tree tmp;
2473 stmtblock_t header;
2474 forall_info *forall_tmp;
2475 tree mask, maskindex;
2477 gfc_start_block (&header);
2479 forall_tmp = nested_forall_info;
2480 while (forall_tmp != NULL)
2482 /* Generate body with masks' control. */
2483 if (mask_flag)
2485 mask = forall_tmp->mask;
2486 maskindex = forall_tmp->maskindex;
2488 /* If a mask was specified make the assignment conditional. */
2489 if (mask)
2491 tmp = gfc_build_array_ref (mask, maskindex, NULL);
2492 body = build3_v (COND_EXPR, tmp, body,
2493 build_empty_stmt (input_location));
2496 body = gfc_trans_forall_loop (forall_tmp, body, mask_flag, &header);
2497 forall_tmp = forall_tmp->prev_nest;
2498 mask_flag = 1;
2501 gfc_add_expr_to_block (&header, body);
2502 return gfc_finish_block (&header);
2506 /* Allocate data for holding a temporary array. Returns either a local
2507 temporary array or a pointer variable. */
2509 static tree
2510 gfc_do_allocate (tree bytesize, tree size, tree * pdata, stmtblock_t * pblock,
2511 tree elem_type)
2513 tree tmpvar;
2514 tree type;
2515 tree tmp;
2517 if (INTEGER_CST_P (size))
2518 tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
2519 size, gfc_index_one_node);
2520 else
2521 tmp = NULL_TREE;
2523 type = build_range_type (gfc_array_index_type, gfc_index_zero_node, tmp);
2524 type = build_array_type (elem_type, type);
2525 if (gfc_can_put_var_on_stack (bytesize))
2527 gcc_assert (INTEGER_CST_P (size));
2528 tmpvar = gfc_create_var (type, "temp");
2529 *pdata = NULL_TREE;
2531 else
2533 tmpvar = gfc_create_var (build_pointer_type (type), "temp");
2534 *pdata = convert (pvoid_type_node, tmpvar);
2536 tmp = gfc_call_malloc (pblock, TREE_TYPE (tmpvar), bytesize);
2537 gfc_add_modify (pblock, tmpvar, tmp);
2539 return tmpvar;
2543 /* Generate codes to copy the temporary to the actual lhs. */
2545 static tree
2546 generate_loop_for_temp_to_lhs (gfc_expr *expr, tree tmp1, tree count3,
2547 tree count1, tree wheremask, bool invert)
2549 gfc_ss *lss;
2550 gfc_se lse, rse;
2551 stmtblock_t block, body;
2552 gfc_loopinfo loop1;
2553 tree tmp;
2554 tree wheremaskexpr;
2556 /* Walk the lhs. */
2557 lss = gfc_walk_expr (expr);
2559 if (lss == gfc_ss_terminator)
2561 gfc_start_block (&block);
2563 gfc_init_se (&lse, NULL);
2565 /* Translate the expression. */
2566 gfc_conv_expr (&lse, expr);
2568 /* Form the expression for the temporary. */
2569 tmp = gfc_build_array_ref (tmp1, count1, NULL);
2571 /* Use the scalar assignment as is. */
2572 gfc_add_block_to_block (&block, &lse.pre);
2573 gfc_add_modify (&block, lse.expr, tmp);
2574 gfc_add_block_to_block (&block, &lse.post);
2576 /* Increment the count1. */
2577 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (count1),
2578 count1, gfc_index_one_node);
2579 gfc_add_modify (&block, count1, tmp);
2581 tmp = gfc_finish_block (&block);
2583 else
2585 gfc_start_block (&block);
2587 gfc_init_loopinfo (&loop1);
2588 gfc_init_se (&rse, NULL);
2589 gfc_init_se (&lse, NULL);
2591 /* Associate the lss with the loop. */
2592 gfc_add_ss_to_loop (&loop1, lss);
2594 /* Calculate the bounds of the scalarization. */
2595 gfc_conv_ss_startstride (&loop1);
2596 /* Setup the scalarizing loops. */
2597 gfc_conv_loop_setup (&loop1, &expr->where);
2599 gfc_mark_ss_chain_used (lss, 1);
2601 /* Start the scalarized loop body. */
2602 gfc_start_scalarized_body (&loop1, &body);
2604 /* Setup the gfc_se structures. */
2605 gfc_copy_loopinfo_to_se (&lse, &loop1);
2606 lse.ss = lss;
2608 /* Form the expression of the temporary. */
2609 if (lss != gfc_ss_terminator)
2610 rse.expr = gfc_build_array_ref (tmp1, count1, NULL);
2611 /* Translate expr. */
2612 gfc_conv_expr (&lse, expr);
2614 /* Use the scalar assignment. */
2615 rse.string_length = lse.string_length;
2616 tmp = gfc_trans_scalar_assign (&lse, &rse, expr->ts, false, true, true);
2618 /* Form the mask expression according to the mask tree list. */
2619 if (wheremask)
2621 wheremaskexpr = gfc_build_array_ref (wheremask, count3, NULL);
2622 if (invert)
2623 wheremaskexpr = fold_build1_loc (input_location, TRUTH_NOT_EXPR,
2624 TREE_TYPE (wheremaskexpr),
2625 wheremaskexpr);
2626 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
2627 wheremaskexpr, tmp,
2628 build_empty_stmt (input_location));
2631 gfc_add_expr_to_block (&body, tmp);
2633 /* Increment count1. */
2634 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
2635 count1, gfc_index_one_node);
2636 gfc_add_modify (&body, count1, tmp);
2638 /* Increment count3. */
2639 if (count3)
2641 tmp = fold_build2_loc (input_location, PLUS_EXPR,
2642 gfc_array_index_type, count3,
2643 gfc_index_one_node);
2644 gfc_add_modify (&body, count3, tmp);
2647 /* Generate the copying loops. */
2648 gfc_trans_scalarizing_loops (&loop1, &body);
2649 gfc_add_block_to_block (&block, &loop1.pre);
2650 gfc_add_block_to_block (&block, &loop1.post);
2651 gfc_cleanup_loop (&loop1);
2653 tmp = gfc_finish_block (&block);
2655 return tmp;
2659 /* Generate codes to copy rhs to the temporary. TMP1 is the address of
2660 temporary, LSS and RSS are formed in function compute_inner_temp_size(),
2661 and should not be freed. WHEREMASK is the conditional execution mask
2662 whose sense may be inverted by INVERT. */
2664 static tree
2665 generate_loop_for_rhs_to_temp (gfc_expr *expr2, tree tmp1, tree count3,
2666 tree count1, gfc_ss *lss, gfc_ss *rss,
2667 tree wheremask, bool invert)
2669 stmtblock_t block, body1;
2670 gfc_loopinfo loop;
2671 gfc_se lse;
2672 gfc_se rse;
2673 tree tmp;
2674 tree wheremaskexpr;
2676 gfc_start_block (&block);
2678 gfc_init_se (&rse, NULL);
2679 gfc_init_se (&lse, NULL);
2681 if (lss == gfc_ss_terminator)
2683 gfc_init_block (&body1);
2684 gfc_conv_expr (&rse, expr2);
2685 lse.expr = gfc_build_array_ref (tmp1, count1, NULL);
2687 else
2689 /* Initialize the loop. */
2690 gfc_init_loopinfo (&loop);
2692 /* We may need LSS to determine the shape of the expression. */
2693 gfc_add_ss_to_loop (&loop, lss);
2694 gfc_add_ss_to_loop (&loop, rss);
2696 gfc_conv_ss_startstride (&loop);
2697 gfc_conv_loop_setup (&loop, &expr2->where);
2699 gfc_mark_ss_chain_used (rss, 1);
2700 /* Start the loop body. */
2701 gfc_start_scalarized_body (&loop, &body1);
2703 /* Translate the expression. */
2704 gfc_copy_loopinfo_to_se (&rse, &loop);
2705 rse.ss = rss;
2706 gfc_conv_expr (&rse, expr2);
2708 /* Form the expression of the temporary. */
2709 lse.expr = gfc_build_array_ref (tmp1, count1, NULL);
2712 /* Use the scalar assignment. */
2713 lse.string_length = rse.string_length;
2714 tmp = gfc_trans_scalar_assign (&lse, &rse, expr2->ts, true,
2715 expr2->expr_type == EXPR_VARIABLE, true);
2717 /* Form the mask expression according to the mask tree list. */
2718 if (wheremask)
2720 wheremaskexpr = gfc_build_array_ref (wheremask, count3, NULL);
2721 if (invert)
2722 wheremaskexpr = fold_build1_loc (input_location, TRUTH_NOT_EXPR,
2723 TREE_TYPE (wheremaskexpr),
2724 wheremaskexpr);
2725 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
2726 wheremaskexpr, tmp,
2727 build_empty_stmt (input_location));
2730 gfc_add_expr_to_block (&body1, tmp);
2732 if (lss == gfc_ss_terminator)
2734 gfc_add_block_to_block (&block, &body1);
2736 /* Increment count1. */
2737 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (count1),
2738 count1, gfc_index_one_node);
2739 gfc_add_modify (&block, count1, tmp);
2741 else
2743 /* Increment count1. */
2744 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
2745 count1, gfc_index_one_node);
2746 gfc_add_modify (&body1, count1, tmp);
2748 /* Increment count3. */
2749 if (count3)
2751 tmp = fold_build2_loc (input_location, PLUS_EXPR,
2752 gfc_array_index_type,
2753 count3, gfc_index_one_node);
2754 gfc_add_modify (&body1, count3, tmp);
2757 /* Generate the copying loops. */
2758 gfc_trans_scalarizing_loops (&loop, &body1);
2760 gfc_add_block_to_block (&block, &loop.pre);
2761 gfc_add_block_to_block (&block, &loop.post);
2763 gfc_cleanup_loop (&loop);
2764 /* TODO: Reuse lss and rss when copying temp->lhs. Need to be careful
2765 as tree nodes in SS may not be valid in different scope. */
2768 tmp = gfc_finish_block (&block);
2769 return tmp;
2773 /* Calculate the size of temporary needed in the assignment inside forall.
2774 LSS and RSS are filled in this function. */
2776 static tree
2777 compute_inner_temp_size (gfc_expr *expr1, gfc_expr *expr2,
2778 stmtblock_t * pblock,
2779 gfc_ss **lss, gfc_ss **rss)
2781 gfc_loopinfo loop;
2782 tree size;
2783 int i;
2784 int save_flag;
2785 tree tmp;
2787 *lss = gfc_walk_expr (expr1);
2788 *rss = NULL;
2790 size = gfc_index_one_node;
2791 if (*lss != gfc_ss_terminator)
2793 gfc_init_loopinfo (&loop);
2795 /* Walk the RHS of the expression. */
2796 *rss = gfc_walk_expr (expr2);
2797 if (*rss == gfc_ss_terminator)
2799 /* The rhs is scalar. Add a ss for the expression. */
2800 *rss = gfc_get_ss ();
2801 (*rss)->next = gfc_ss_terminator;
2802 (*rss)->type = GFC_SS_SCALAR;
2803 (*rss)->expr = expr2;
2806 /* Associate the SS with the loop. */
2807 gfc_add_ss_to_loop (&loop, *lss);
2808 /* We don't actually need to add the rhs at this point, but it might
2809 make guessing the loop bounds a bit easier. */
2810 gfc_add_ss_to_loop (&loop, *rss);
2812 /* We only want the shape of the expression, not rest of the junk
2813 generated by the scalarizer. */
2814 loop.array_parameter = 1;
2816 /* Calculate the bounds of the scalarization. */
2817 save_flag = gfc_option.rtcheck;
2818 gfc_option.rtcheck &= !GFC_RTCHECK_BOUNDS;
2819 gfc_conv_ss_startstride (&loop);
2820 gfc_option.rtcheck = save_flag;
2821 gfc_conv_loop_setup (&loop, &expr2->where);
2823 /* Figure out how many elements we need. */
2824 for (i = 0; i < loop.dimen; i++)
2826 tmp = fold_build2_loc (input_location, MINUS_EXPR,
2827 gfc_array_index_type,
2828 gfc_index_one_node, loop.from[i]);
2829 tmp = fold_build2_loc (input_location, PLUS_EXPR,
2830 gfc_array_index_type, tmp, loop.to[i]);
2831 size = fold_build2_loc (input_location, MULT_EXPR,
2832 gfc_array_index_type, size, tmp);
2834 gfc_add_block_to_block (pblock, &loop.pre);
2835 size = gfc_evaluate_now (size, pblock);
2836 gfc_add_block_to_block (pblock, &loop.post);
2838 /* TODO: write a function that cleans up a loopinfo without freeing
2839 the SS chains. Currently a NOP. */
2842 return size;
2846 /* Calculate the overall iterator number of the nested forall construct.
2847 This routine actually calculates the number of times the body of the
2848 nested forall specified by NESTED_FORALL_INFO is executed and multiplies
2849 that by the expression INNER_SIZE. The BLOCK argument specifies the
2850 block in which to calculate the result, and the optional INNER_SIZE_BODY
2851 argument contains any statements that need to executed (inside the loop)
2852 to initialize or calculate INNER_SIZE. */
2854 static tree
2855 compute_overall_iter_number (forall_info *nested_forall_info, tree inner_size,
2856 stmtblock_t *inner_size_body, stmtblock_t *block)
2858 forall_info *forall_tmp = nested_forall_info;
2859 tree tmp, number;
2860 stmtblock_t body;
2862 /* We can eliminate the innermost unconditional loops with constant
2863 array bounds. */
2864 if (INTEGER_CST_P (inner_size))
2866 while (forall_tmp
2867 && !forall_tmp->mask
2868 && INTEGER_CST_P (forall_tmp->size))
2870 inner_size = fold_build2_loc (input_location, MULT_EXPR,
2871 gfc_array_index_type,
2872 inner_size, forall_tmp->size);
2873 forall_tmp = forall_tmp->prev_nest;
2876 /* If there are no loops left, we have our constant result. */
2877 if (!forall_tmp)
2878 return inner_size;
2881 /* Otherwise, create a temporary variable to compute the result. */
2882 number = gfc_create_var (gfc_array_index_type, "num");
2883 gfc_add_modify (block, number, gfc_index_zero_node);
2885 gfc_start_block (&body);
2886 if (inner_size_body)
2887 gfc_add_block_to_block (&body, inner_size_body);
2888 if (forall_tmp)
2889 tmp = fold_build2_loc (input_location, PLUS_EXPR,
2890 gfc_array_index_type, number, inner_size);
2891 else
2892 tmp = inner_size;
2893 gfc_add_modify (&body, number, tmp);
2894 tmp = gfc_finish_block (&body);
2896 /* Generate loops. */
2897 if (forall_tmp != NULL)
2898 tmp = gfc_trans_nested_forall_loop (forall_tmp, tmp, 1);
2900 gfc_add_expr_to_block (block, tmp);
2902 return number;
2906 /* Allocate temporary for forall construct. SIZE is the size of temporary
2907 needed. PTEMP1 is returned for space free. */
2909 static tree
2910 allocate_temp_for_forall_nest_1 (tree type, tree size, stmtblock_t * block,
2911 tree * ptemp1)
2913 tree bytesize;
2914 tree unit;
2915 tree tmp;
2917 unit = fold_convert (gfc_array_index_type, TYPE_SIZE_UNIT (type));
2918 if (!integer_onep (unit))
2919 bytesize = fold_build2_loc (input_location, MULT_EXPR,
2920 gfc_array_index_type, size, unit);
2921 else
2922 bytesize = size;
2924 *ptemp1 = NULL;
2925 tmp = gfc_do_allocate (bytesize, size, ptemp1, block, type);
2927 if (*ptemp1)
2928 tmp = build_fold_indirect_ref_loc (input_location, tmp);
2929 return tmp;
2933 /* Allocate temporary for forall construct according to the information in
2934 nested_forall_info. INNER_SIZE is the size of temporary needed in the
2935 assignment inside forall. PTEMP1 is returned for space free. */
2937 static tree
2938 allocate_temp_for_forall_nest (forall_info * nested_forall_info, tree type,
2939 tree inner_size, stmtblock_t * inner_size_body,
2940 stmtblock_t * block, tree * ptemp1)
2942 tree size;
2944 /* Calculate the total size of temporary needed in forall construct. */
2945 size = compute_overall_iter_number (nested_forall_info, inner_size,
2946 inner_size_body, block);
2948 return allocate_temp_for_forall_nest_1 (type, size, block, ptemp1);
2952 /* Handle assignments inside forall which need temporary.
2954 forall (i=start:end:stride; maskexpr)
2955 e<i> = f<i>
2956 end forall
2957 (where e,f<i> are arbitrary expressions possibly involving i
2958 and there is a dependency between e<i> and f<i>)
2959 Translates to:
2960 masktmp(:) = maskexpr(:)
2962 maskindex = 0;
2963 count1 = 0;
2964 num = 0;
2965 for (i = start; i <= end; i += stride)
2966 num += SIZE (f<i>)
2967 count1 = 0;
2968 ALLOCATE (tmp(num))
2969 for (i = start; i <= end; i += stride)
2971 if (masktmp[maskindex++])
2972 tmp[count1++] = f<i>
2974 maskindex = 0;
2975 count1 = 0;
2976 for (i = start; i <= end; i += stride)
2978 if (masktmp[maskindex++])
2979 e<i> = tmp[count1++]
2981 DEALLOCATE (tmp)
2983 static void
2984 gfc_trans_assign_need_temp (gfc_expr * expr1, gfc_expr * expr2,
2985 tree wheremask, bool invert,
2986 forall_info * nested_forall_info,
2987 stmtblock_t * block)
2989 tree type;
2990 tree inner_size;
2991 gfc_ss *lss, *rss;
2992 tree count, count1;
2993 tree tmp, tmp1;
2994 tree ptemp1;
2995 stmtblock_t inner_size_body;
2997 /* Create vars. count1 is the current iterator number of the nested
2998 forall. */
2999 count1 = gfc_create_var (gfc_array_index_type, "count1");
3001 /* Count is the wheremask index. */
3002 if (wheremask)
3004 count = gfc_create_var (gfc_array_index_type, "count");
3005 gfc_add_modify (block, count, gfc_index_zero_node);
3007 else
3008 count = NULL;
3010 /* Initialize count1. */
3011 gfc_add_modify (block, count1, gfc_index_zero_node);
3013 /* Calculate the size of temporary needed in the assignment. Return loop, lss
3014 and rss which are used in function generate_loop_for_rhs_to_temp(). */
3015 gfc_init_block (&inner_size_body);
3016 inner_size = compute_inner_temp_size (expr1, expr2, &inner_size_body,
3017 &lss, &rss);
3019 /* The type of LHS. Used in function allocate_temp_for_forall_nest */
3020 if (expr1->ts.type == BT_CHARACTER && expr1->ts.u.cl->length)
3022 if (!expr1->ts.u.cl->backend_decl)
3024 gfc_se tse;
3025 gfc_init_se (&tse, NULL);
3026 gfc_conv_expr (&tse, expr1->ts.u.cl->length);
3027 expr1->ts.u.cl->backend_decl = tse.expr;
3029 type = gfc_get_character_type_len (gfc_default_character_kind,
3030 expr1->ts.u.cl->backend_decl);
3032 else
3033 type = gfc_typenode_for_spec (&expr1->ts);
3035 /* Allocate temporary for nested forall construct according to the
3036 information in nested_forall_info and inner_size. */
3037 tmp1 = allocate_temp_for_forall_nest (nested_forall_info, type, inner_size,
3038 &inner_size_body, block, &ptemp1);
3040 /* Generate codes to copy rhs to the temporary . */
3041 tmp = generate_loop_for_rhs_to_temp (expr2, tmp1, count, count1, lss, rss,
3042 wheremask, invert);
3044 /* Generate body and loops according to the information in
3045 nested_forall_info. */
3046 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
3047 gfc_add_expr_to_block (block, tmp);
3049 /* Reset count1. */
3050 gfc_add_modify (block, count1, gfc_index_zero_node);
3052 /* Reset count. */
3053 if (wheremask)
3054 gfc_add_modify (block, count, gfc_index_zero_node);
3056 /* Generate codes to copy the temporary to lhs. */
3057 tmp = generate_loop_for_temp_to_lhs (expr1, tmp1, count, count1,
3058 wheremask, invert);
3060 /* Generate body and loops according to the information in
3061 nested_forall_info. */
3062 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
3063 gfc_add_expr_to_block (block, tmp);
3065 if (ptemp1)
3067 /* Free the temporary. */
3068 tmp = gfc_call_free (ptemp1);
3069 gfc_add_expr_to_block (block, tmp);
3074 /* Translate pointer assignment inside FORALL which need temporary. */
3076 static void
3077 gfc_trans_pointer_assign_need_temp (gfc_expr * expr1, gfc_expr * expr2,
3078 forall_info * nested_forall_info,
3079 stmtblock_t * block)
3081 tree type;
3082 tree inner_size;
3083 gfc_ss *lss, *rss;
3084 gfc_se lse;
3085 gfc_se rse;
3086 gfc_ss_info *info;
3087 gfc_loopinfo loop;
3088 tree desc;
3089 tree parm;
3090 tree parmtype;
3091 stmtblock_t body;
3092 tree count;
3093 tree tmp, tmp1, ptemp1;
3095 count = gfc_create_var (gfc_array_index_type, "count");
3096 gfc_add_modify (block, count, gfc_index_zero_node);
3098 inner_size = integer_one_node;
3099 lss = gfc_walk_expr (expr1);
3100 rss = gfc_walk_expr (expr2);
3101 if (lss == gfc_ss_terminator)
3103 type = gfc_typenode_for_spec (&expr1->ts);
3104 type = build_pointer_type (type);
3106 /* Allocate temporary for nested forall construct according to the
3107 information in nested_forall_info and inner_size. */
3108 tmp1 = allocate_temp_for_forall_nest (nested_forall_info, type,
3109 inner_size, NULL, block, &ptemp1);
3110 gfc_start_block (&body);
3111 gfc_init_se (&lse, NULL);
3112 lse.expr = gfc_build_array_ref (tmp1, count, NULL);
3113 gfc_init_se (&rse, NULL);
3114 rse.want_pointer = 1;
3115 gfc_conv_expr (&rse, expr2);
3116 gfc_add_block_to_block (&body, &rse.pre);
3117 gfc_add_modify (&body, lse.expr,
3118 fold_convert (TREE_TYPE (lse.expr), rse.expr));
3119 gfc_add_block_to_block (&body, &rse.post);
3121 /* Increment count. */
3122 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
3123 count, gfc_index_one_node);
3124 gfc_add_modify (&body, count, tmp);
3126 tmp = gfc_finish_block (&body);
3128 /* Generate body and loops according to the information in
3129 nested_forall_info. */
3130 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
3131 gfc_add_expr_to_block (block, tmp);
3133 /* Reset count. */
3134 gfc_add_modify (block, count, gfc_index_zero_node);
3136 gfc_start_block (&body);
3137 gfc_init_se (&lse, NULL);
3138 gfc_init_se (&rse, NULL);
3139 rse.expr = gfc_build_array_ref (tmp1, count, NULL);
3140 lse.want_pointer = 1;
3141 gfc_conv_expr (&lse, expr1);
3142 gfc_add_block_to_block (&body, &lse.pre);
3143 gfc_add_modify (&body, lse.expr, rse.expr);
3144 gfc_add_block_to_block (&body, &lse.post);
3145 /* Increment count. */
3146 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
3147 count, gfc_index_one_node);
3148 gfc_add_modify (&body, count, tmp);
3149 tmp = gfc_finish_block (&body);
3151 /* Generate body and loops according to the information in
3152 nested_forall_info. */
3153 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
3154 gfc_add_expr_to_block (block, tmp);
3156 else
3158 gfc_init_loopinfo (&loop);
3160 /* Associate the SS with the loop. */
3161 gfc_add_ss_to_loop (&loop, rss);
3163 /* Setup the scalarizing loops and bounds. */
3164 gfc_conv_ss_startstride (&loop);
3166 gfc_conv_loop_setup (&loop, &expr2->where);
3168 info = &rss->data.info;
3169 desc = info->descriptor;
3171 /* Make a new descriptor. */
3172 parmtype = gfc_get_element_type (TREE_TYPE (desc));
3173 parmtype = gfc_get_array_type_bounds (parmtype, loop.dimen, 0,
3174 loop.from, loop.to, 1,
3175 GFC_ARRAY_UNKNOWN, true);
3177 /* Allocate temporary for nested forall construct. */
3178 tmp1 = allocate_temp_for_forall_nest (nested_forall_info, parmtype,
3179 inner_size, NULL, block, &ptemp1);
3180 gfc_start_block (&body);
3181 gfc_init_se (&lse, NULL);
3182 lse.expr = gfc_build_array_ref (tmp1, count, NULL);
3183 lse.direct_byref = 1;
3184 rss = gfc_walk_expr (expr2);
3185 gfc_conv_expr_descriptor (&lse, expr2, rss);
3187 gfc_add_block_to_block (&body, &lse.pre);
3188 gfc_add_block_to_block (&body, &lse.post);
3190 /* Increment count. */
3191 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
3192 count, gfc_index_one_node);
3193 gfc_add_modify (&body, count, tmp);
3195 tmp = gfc_finish_block (&body);
3197 /* Generate body and loops according to the information in
3198 nested_forall_info. */
3199 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
3200 gfc_add_expr_to_block (block, tmp);
3202 /* Reset count. */
3203 gfc_add_modify (block, count, gfc_index_zero_node);
3205 parm = gfc_build_array_ref (tmp1, count, NULL);
3206 lss = gfc_walk_expr (expr1);
3207 gfc_init_se (&lse, NULL);
3208 gfc_conv_expr_descriptor (&lse, expr1, lss);
3209 gfc_add_modify (&lse.pre, lse.expr, parm);
3210 gfc_start_block (&body);
3211 gfc_add_block_to_block (&body, &lse.pre);
3212 gfc_add_block_to_block (&body, &lse.post);
3214 /* Increment count. */
3215 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
3216 count, gfc_index_one_node);
3217 gfc_add_modify (&body, count, tmp);
3219 tmp = gfc_finish_block (&body);
3221 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
3222 gfc_add_expr_to_block (block, tmp);
3224 /* Free the temporary. */
3225 if (ptemp1)
3227 tmp = gfc_call_free (ptemp1);
3228 gfc_add_expr_to_block (block, tmp);
3233 /* FORALL and WHERE statements are really nasty, especially when you nest
3234 them. All the rhs of a forall assignment must be evaluated before the
3235 actual assignments are performed. Presumably this also applies to all the
3236 assignments in an inner where statement. */
3238 /* Generate code for a FORALL statement. Any temporaries are allocated as a
3239 linear array, relying on the fact that we process in the same order in all
3240 loops.
3242 forall (i=start:end:stride; maskexpr)
3243 e<i> = f<i>
3244 g<i> = h<i>
3245 end forall
3246 (where e,f,g,h<i> are arbitrary expressions possibly involving i)
3247 Translates to:
3248 count = ((end + 1 - start) / stride)
3249 masktmp(:) = maskexpr(:)
3251 maskindex = 0;
3252 for (i = start; i <= end; i += stride)
3254 if (masktmp[maskindex++])
3255 e<i> = f<i>
3257 maskindex = 0;
3258 for (i = start; i <= end; i += stride)
3260 if (masktmp[maskindex++])
3261 g<i> = h<i>
3264 Note that this code only works when there are no dependencies.
3265 Forall loop with array assignments and data dependencies are a real pain,
3266 because the size of the temporary cannot always be determined before the
3267 loop is executed. This problem is compounded by the presence of nested
3268 FORALL constructs.
3271 static tree
3272 gfc_trans_forall_1 (gfc_code * code, forall_info * nested_forall_info)
3274 stmtblock_t pre;
3275 stmtblock_t post;
3276 stmtblock_t block;
3277 stmtblock_t body;
3278 tree *var;
3279 tree *start;
3280 tree *end;
3281 tree *step;
3282 gfc_expr **varexpr;
3283 tree tmp;
3284 tree assign;
3285 tree size;
3286 tree maskindex;
3287 tree mask;
3288 tree pmask;
3289 int n;
3290 int nvar;
3291 int need_temp;
3292 gfc_forall_iterator *fa;
3293 gfc_se se;
3294 gfc_code *c;
3295 gfc_saved_var *saved_vars;
3296 iter_info *this_forall;
3297 forall_info *info;
3298 bool need_mask;
3300 /* Do nothing if the mask is false. */
3301 if (code->expr1
3302 && code->expr1->expr_type == EXPR_CONSTANT
3303 && !code->expr1->value.logical)
3304 return build_empty_stmt (input_location);
3306 n = 0;
3307 /* Count the FORALL index number. */
3308 for (fa = code->ext.forall_iterator; fa; fa = fa->next)
3309 n++;
3310 nvar = n;
3312 /* Allocate the space for var, start, end, step, varexpr. */
3313 var = (tree *) gfc_getmem (nvar * sizeof (tree));
3314 start = (tree *) gfc_getmem (nvar * sizeof (tree));
3315 end = (tree *) gfc_getmem (nvar * sizeof (tree));
3316 step = (tree *) gfc_getmem (nvar * sizeof (tree));
3317 varexpr = (gfc_expr **) gfc_getmem (nvar * sizeof (gfc_expr *));
3318 saved_vars = (gfc_saved_var *) gfc_getmem (nvar * sizeof (gfc_saved_var));
3320 /* Allocate the space for info. */
3321 info = (forall_info *) gfc_getmem (sizeof (forall_info));
3323 gfc_start_block (&pre);
3324 gfc_init_block (&post);
3325 gfc_init_block (&block);
3327 n = 0;
3328 for (fa = code->ext.forall_iterator; fa; fa = fa->next)
3330 gfc_symbol *sym = fa->var->symtree->n.sym;
3332 /* Allocate space for this_forall. */
3333 this_forall = (iter_info *) gfc_getmem (sizeof (iter_info));
3335 /* Create a temporary variable for the FORALL index. */
3336 tmp = gfc_typenode_for_spec (&sym->ts);
3337 var[n] = gfc_create_var (tmp, sym->name);
3338 gfc_shadow_sym (sym, var[n], &saved_vars[n]);
3340 /* Record it in this_forall. */
3341 this_forall->var = var[n];
3343 /* Replace the index symbol's backend_decl with the temporary decl. */
3344 sym->backend_decl = var[n];
3346 /* Work out the start, end and stride for the loop. */
3347 gfc_init_se (&se, NULL);
3348 gfc_conv_expr_val (&se, fa->start);
3349 /* Record it in this_forall. */
3350 this_forall->start = se.expr;
3351 gfc_add_block_to_block (&block, &se.pre);
3352 start[n] = se.expr;
3354 gfc_init_se (&se, NULL);
3355 gfc_conv_expr_val (&se, fa->end);
3356 /* Record it in this_forall. */
3357 this_forall->end = se.expr;
3358 gfc_make_safe_expr (&se);
3359 gfc_add_block_to_block (&block, &se.pre);
3360 end[n] = se.expr;
3362 gfc_init_se (&se, NULL);
3363 gfc_conv_expr_val (&se, fa->stride);
3364 /* Record it in this_forall. */
3365 this_forall->step = se.expr;
3366 gfc_make_safe_expr (&se);
3367 gfc_add_block_to_block (&block, &se.pre);
3368 step[n] = se.expr;
3370 /* Set the NEXT field of this_forall to NULL. */
3371 this_forall->next = NULL;
3372 /* Link this_forall to the info construct. */
3373 if (info->this_loop)
3375 iter_info *iter_tmp = info->this_loop;
3376 while (iter_tmp->next != NULL)
3377 iter_tmp = iter_tmp->next;
3378 iter_tmp->next = this_forall;
3380 else
3381 info->this_loop = this_forall;
3383 n++;
3385 nvar = n;
3387 /* Calculate the size needed for the current forall level. */
3388 size = gfc_index_one_node;
3389 for (n = 0; n < nvar; n++)
3391 /* size = (end + step - start) / step. */
3392 tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (start[n]),
3393 step[n], start[n]);
3394 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (end[n]),
3395 end[n], tmp);
3396 tmp = fold_build2_loc (input_location, FLOOR_DIV_EXPR, TREE_TYPE (tmp),
3397 tmp, step[n]);
3398 tmp = convert (gfc_array_index_type, tmp);
3400 size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
3401 size, tmp);
3404 /* Record the nvar and size of current forall level. */
3405 info->nvar = nvar;
3406 info->size = size;
3408 if (code->expr1)
3410 /* If the mask is .true., consider the FORALL unconditional. */
3411 if (code->expr1->expr_type == EXPR_CONSTANT
3412 && code->expr1->value.logical)
3413 need_mask = false;
3414 else
3415 need_mask = true;
3417 else
3418 need_mask = false;
3420 /* First we need to allocate the mask. */
3421 if (need_mask)
3423 /* As the mask array can be very big, prefer compact boolean types. */
3424 tree mask_type = gfc_get_logical_type (gfc_logical_kinds[0].kind);
3425 mask = allocate_temp_for_forall_nest (nested_forall_info, mask_type,
3426 size, NULL, &block, &pmask);
3427 maskindex = gfc_create_var_np (gfc_array_index_type, "mi");
3429 /* Record them in the info structure. */
3430 info->maskindex = maskindex;
3431 info->mask = mask;
3433 else
3435 /* No mask was specified. */
3436 maskindex = NULL_TREE;
3437 mask = pmask = NULL_TREE;
3440 /* Link the current forall level to nested_forall_info. */
3441 info->prev_nest = nested_forall_info;
3442 nested_forall_info = info;
3444 /* Copy the mask into a temporary variable if required.
3445 For now we assume a mask temporary is needed. */
3446 if (need_mask)
3448 /* As the mask array can be very big, prefer compact boolean types. */
3449 tree mask_type = gfc_get_logical_type (gfc_logical_kinds[0].kind);
3451 gfc_add_modify (&block, maskindex, gfc_index_zero_node);
3453 /* Start of mask assignment loop body. */
3454 gfc_start_block (&body);
3456 /* Evaluate the mask expression. */
3457 gfc_init_se (&se, NULL);
3458 gfc_conv_expr_val (&se, code->expr1);
3459 gfc_add_block_to_block (&body, &se.pre);
3461 /* Store the mask. */
3462 se.expr = convert (mask_type, se.expr);
3464 tmp = gfc_build_array_ref (mask, maskindex, NULL);
3465 gfc_add_modify (&body, tmp, se.expr);
3467 /* Advance to the next mask element. */
3468 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
3469 maskindex, gfc_index_one_node);
3470 gfc_add_modify (&body, maskindex, tmp);
3472 /* Generate the loops. */
3473 tmp = gfc_finish_block (&body);
3474 tmp = gfc_trans_nested_forall_loop (info, tmp, 0);
3475 gfc_add_expr_to_block (&block, tmp);
3478 c = code->block->next;
3480 /* TODO: loop merging in FORALL statements. */
3481 /* Now that we've got a copy of the mask, generate the assignment loops. */
3482 while (c)
3484 switch (c->op)
3486 case EXEC_ASSIGN:
3487 /* A scalar or array assignment. DO the simple check for
3488 lhs to rhs dependencies. These make a temporary for the
3489 rhs and form a second forall block to copy to variable. */
3490 need_temp = check_forall_dependencies(c, &pre, &post);
3492 /* Temporaries due to array assignment data dependencies introduce
3493 no end of problems. */
3494 if (need_temp)
3495 gfc_trans_assign_need_temp (c->expr1, c->expr2, NULL, false,
3496 nested_forall_info, &block);
3497 else
3499 /* Use the normal assignment copying routines. */
3500 assign = gfc_trans_assignment (c->expr1, c->expr2, false, true);
3502 /* Generate body and loops. */
3503 tmp = gfc_trans_nested_forall_loop (nested_forall_info,
3504 assign, 1);
3505 gfc_add_expr_to_block (&block, tmp);
3508 /* Cleanup any temporary symtrees that have been made to deal
3509 with dependencies. */
3510 if (new_symtree)
3511 cleanup_forall_symtrees (c);
3513 break;
3515 case EXEC_WHERE:
3516 /* Translate WHERE or WHERE construct nested in FORALL. */
3517 gfc_trans_where_2 (c, NULL, false, nested_forall_info, &block);
3518 break;
3520 /* Pointer assignment inside FORALL. */
3521 case EXEC_POINTER_ASSIGN:
3522 need_temp = gfc_check_dependency (c->expr1, c->expr2, 0);
3523 if (need_temp)
3524 gfc_trans_pointer_assign_need_temp (c->expr1, c->expr2,
3525 nested_forall_info, &block);
3526 else
3528 /* Use the normal assignment copying routines. */
3529 assign = gfc_trans_pointer_assignment (c->expr1, c->expr2);
3531 /* Generate body and loops. */
3532 tmp = gfc_trans_nested_forall_loop (nested_forall_info,
3533 assign, 1);
3534 gfc_add_expr_to_block (&block, tmp);
3536 break;
3538 case EXEC_FORALL:
3539 tmp = gfc_trans_forall_1 (c, nested_forall_info);
3540 gfc_add_expr_to_block (&block, tmp);
3541 break;
3543 /* Explicit subroutine calls are prevented by the frontend but interface
3544 assignments can legitimately produce them. */
3545 case EXEC_ASSIGN_CALL:
3546 assign = gfc_trans_call (c, true, NULL_TREE, NULL_TREE, false);
3547 tmp = gfc_trans_nested_forall_loop (nested_forall_info, assign, 1);
3548 gfc_add_expr_to_block (&block, tmp);
3549 break;
3551 default:
3552 gcc_unreachable ();
3555 c = c->next;
3558 /* Restore the original index variables. */
3559 for (fa = code->ext.forall_iterator, n = 0; fa; fa = fa->next, n++)
3560 gfc_restore_sym (fa->var->symtree->n.sym, &saved_vars[n]);
3562 /* Free the space for var, start, end, step, varexpr. */
3563 gfc_free (var);
3564 gfc_free (start);
3565 gfc_free (end);
3566 gfc_free (step);
3567 gfc_free (varexpr);
3568 gfc_free (saved_vars);
3570 for (this_forall = info->this_loop; this_forall;)
3572 iter_info *next = this_forall->next;
3573 gfc_free (this_forall);
3574 this_forall = next;
3577 /* Free the space for this forall_info. */
3578 gfc_free (info);
3580 if (pmask)
3582 /* Free the temporary for the mask. */
3583 tmp = gfc_call_free (pmask);
3584 gfc_add_expr_to_block (&block, tmp);
3586 if (maskindex)
3587 pushdecl (maskindex);
3589 gfc_add_block_to_block (&pre, &block);
3590 gfc_add_block_to_block (&pre, &post);
3592 return gfc_finish_block (&pre);
3596 /* Translate the FORALL statement or construct. */
3598 tree gfc_trans_forall (gfc_code * code)
3600 return gfc_trans_forall_1 (code, NULL);
3604 /* Evaluate the WHERE mask expression, copy its value to a temporary.
3605 If the WHERE construct is nested in FORALL, compute the overall temporary
3606 needed by the WHERE mask expression multiplied by the iterator number of
3607 the nested forall.
3608 ME is the WHERE mask expression.
3609 MASK is the current execution mask upon input, whose sense may or may
3610 not be inverted as specified by the INVERT argument.
3611 CMASK is the updated execution mask on output, or NULL if not required.
3612 PMASK is the pending execution mask on output, or NULL if not required.
3613 BLOCK is the block in which to place the condition evaluation loops. */
3615 static void
3616 gfc_evaluate_where_mask (gfc_expr * me, forall_info * nested_forall_info,
3617 tree mask, bool invert, tree cmask, tree pmask,
3618 tree mask_type, stmtblock_t * block)
3620 tree tmp, tmp1;
3621 gfc_ss *lss, *rss;
3622 gfc_loopinfo loop;
3623 stmtblock_t body, body1;
3624 tree count, cond, mtmp;
3625 gfc_se lse, rse;
3627 gfc_init_loopinfo (&loop);
3629 lss = gfc_walk_expr (me);
3630 rss = gfc_walk_expr (me);
3632 /* Variable to index the temporary. */
3633 count = gfc_create_var (gfc_array_index_type, "count");
3634 /* Initialize count. */
3635 gfc_add_modify (block, count, gfc_index_zero_node);
3637 gfc_start_block (&body);
3639 gfc_init_se (&rse, NULL);
3640 gfc_init_se (&lse, NULL);
3642 if (lss == gfc_ss_terminator)
3644 gfc_init_block (&body1);
3646 else
3648 /* Initialize the loop. */
3649 gfc_init_loopinfo (&loop);
3651 /* We may need LSS to determine the shape of the expression. */
3652 gfc_add_ss_to_loop (&loop, lss);
3653 gfc_add_ss_to_loop (&loop, rss);
3655 gfc_conv_ss_startstride (&loop);
3656 gfc_conv_loop_setup (&loop, &me->where);
3658 gfc_mark_ss_chain_used (rss, 1);
3659 /* Start the loop body. */
3660 gfc_start_scalarized_body (&loop, &body1);
3662 /* Translate the expression. */
3663 gfc_copy_loopinfo_to_se (&rse, &loop);
3664 rse.ss = rss;
3665 gfc_conv_expr (&rse, me);
3668 /* Variable to evaluate mask condition. */
3669 cond = gfc_create_var (mask_type, "cond");
3670 if (mask && (cmask || pmask))
3671 mtmp = gfc_create_var (mask_type, "mask");
3672 else mtmp = NULL_TREE;
3674 gfc_add_block_to_block (&body1, &lse.pre);
3675 gfc_add_block_to_block (&body1, &rse.pre);
3677 gfc_add_modify (&body1, cond, fold_convert (mask_type, rse.expr));
3679 if (mask && (cmask || pmask))
3681 tmp = gfc_build_array_ref (mask, count, NULL);
3682 if (invert)
3683 tmp = fold_build1_loc (input_location, TRUTH_NOT_EXPR, mask_type, tmp);
3684 gfc_add_modify (&body1, mtmp, tmp);
3687 if (cmask)
3689 tmp1 = gfc_build_array_ref (cmask, count, NULL);
3690 tmp = cond;
3691 if (mask)
3692 tmp = fold_build2_loc (input_location, TRUTH_AND_EXPR, mask_type,
3693 mtmp, tmp);
3694 gfc_add_modify (&body1, tmp1, tmp);
3697 if (pmask)
3699 tmp1 = gfc_build_array_ref (pmask, count, NULL);
3700 tmp = fold_build1_loc (input_location, TRUTH_NOT_EXPR, mask_type, cond);
3701 if (mask)
3702 tmp = fold_build2_loc (input_location, TRUTH_AND_EXPR, mask_type, mtmp,
3703 tmp);
3704 gfc_add_modify (&body1, tmp1, tmp);
3707 gfc_add_block_to_block (&body1, &lse.post);
3708 gfc_add_block_to_block (&body1, &rse.post);
3710 if (lss == gfc_ss_terminator)
3712 gfc_add_block_to_block (&body, &body1);
3714 else
3716 /* Increment count. */
3717 tmp1 = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
3718 count, gfc_index_one_node);
3719 gfc_add_modify (&body1, count, tmp1);
3721 /* Generate the copying loops. */
3722 gfc_trans_scalarizing_loops (&loop, &body1);
3724 gfc_add_block_to_block (&body, &loop.pre);
3725 gfc_add_block_to_block (&body, &loop.post);
3727 gfc_cleanup_loop (&loop);
3728 /* TODO: Reuse lss and rss when copying temp->lhs. Need to be careful
3729 as tree nodes in SS may not be valid in different scope. */
3732 tmp1 = gfc_finish_block (&body);
3733 /* If the WHERE construct is inside FORALL, fill the full temporary. */
3734 if (nested_forall_info != NULL)
3735 tmp1 = gfc_trans_nested_forall_loop (nested_forall_info, tmp1, 1);
3737 gfc_add_expr_to_block (block, tmp1);
3741 /* Translate an assignment statement in a WHERE statement or construct
3742 statement. The MASK expression is used to control which elements
3743 of EXPR1 shall be assigned. The sense of MASK is specified by
3744 INVERT. */
3746 static tree
3747 gfc_trans_where_assign (gfc_expr *expr1, gfc_expr *expr2,
3748 tree mask, bool invert,
3749 tree count1, tree count2,
3750 gfc_code *cnext)
3752 gfc_se lse;
3753 gfc_se rse;
3754 gfc_ss *lss;
3755 gfc_ss *lss_section;
3756 gfc_ss *rss;
3758 gfc_loopinfo loop;
3759 tree tmp;
3760 stmtblock_t block;
3761 stmtblock_t body;
3762 tree index, maskexpr;
3764 /* A defined assignment. */
3765 if (cnext && cnext->resolved_sym)
3766 return gfc_trans_call (cnext, true, mask, count1, invert);
3768 #if 0
3769 /* TODO: handle this special case.
3770 Special case a single function returning an array. */
3771 if (expr2->expr_type == EXPR_FUNCTION && expr2->rank > 0)
3773 tmp = gfc_trans_arrayfunc_assign (expr1, expr2);
3774 if (tmp)
3775 return tmp;
3777 #endif
3779 /* Assignment of the form lhs = rhs. */
3780 gfc_start_block (&block);
3782 gfc_init_se (&lse, NULL);
3783 gfc_init_se (&rse, NULL);
3785 /* Walk the lhs. */
3786 lss = gfc_walk_expr (expr1);
3787 rss = NULL;
3789 /* In each where-assign-stmt, the mask-expr and the variable being
3790 defined shall be arrays of the same shape. */
3791 gcc_assert (lss != gfc_ss_terminator);
3793 /* The assignment needs scalarization. */
3794 lss_section = lss;
3796 /* Find a non-scalar SS from the lhs. */
3797 while (lss_section != gfc_ss_terminator
3798 && lss_section->type != GFC_SS_SECTION)
3799 lss_section = lss_section->next;
3801 gcc_assert (lss_section != gfc_ss_terminator);
3803 /* Initialize the scalarizer. */
3804 gfc_init_loopinfo (&loop);
3806 /* Walk the rhs. */
3807 rss = gfc_walk_expr (expr2);
3808 if (rss == gfc_ss_terminator)
3810 /* The rhs is scalar. Add a ss for the expression. */
3811 rss = gfc_get_ss ();
3812 rss->where = 1;
3813 rss->next = gfc_ss_terminator;
3814 rss->type = GFC_SS_SCALAR;
3815 rss->expr = expr2;
3818 /* Associate the SS with the loop. */
3819 gfc_add_ss_to_loop (&loop, lss);
3820 gfc_add_ss_to_loop (&loop, rss);
3822 /* Calculate the bounds of the scalarization. */
3823 gfc_conv_ss_startstride (&loop);
3825 /* Resolve any data dependencies in the statement. */
3826 gfc_conv_resolve_dependencies (&loop, lss_section, rss);
3828 /* Setup the scalarizing loops. */
3829 gfc_conv_loop_setup (&loop, &expr2->where);
3831 /* Setup the gfc_se structures. */
3832 gfc_copy_loopinfo_to_se (&lse, &loop);
3833 gfc_copy_loopinfo_to_se (&rse, &loop);
3835 rse.ss = rss;
3836 gfc_mark_ss_chain_used (rss, 1);
3837 if (loop.temp_ss == NULL)
3839 lse.ss = lss;
3840 gfc_mark_ss_chain_used (lss, 1);
3842 else
3844 lse.ss = loop.temp_ss;
3845 gfc_mark_ss_chain_used (lss, 3);
3846 gfc_mark_ss_chain_used (loop.temp_ss, 3);
3849 /* Start the scalarized loop body. */
3850 gfc_start_scalarized_body (&loop, &body);
3852 /* Translate the expression. */
3853 gfc_conv_expr (&rse, expr2);
3854 if (lss != gfc_ss_terminator && loop.temp_ss != NULL)
3855 gfc_conv_tmp_array_ref (&lse);
3856 else
3857 gfc_conv_expr (&lse, expr1);
3859 /* Form the mask expression according to the mask. */
3860 index = count1;
3861 maskexpr = gfc_build_array_ref (mask, index, NULL);
3862 if (invert)
3863 maskexpr = fold_build1_loc (input_location, TRUTH_NOT_EXPR,
3864 TREE_TYPE (maskexpr), maskexpr);
3866 /* Use the scalar assignment as is. */
3867 tmp = gfc_trans_scalar_assign (&lse, &rse, expr1->ts,
3868 loop.temp_ss != NULL, false, true);
3870 tmp = build3_v (COND_EXPR, maskexpr, tmp, build_empty_stmt (input_location));
3872 gfc_add_expr_to_block (&body, tmp);
3874 if (lss == gfc_ss_terminator)
3876 /* Increment count1. */
3877 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
3878 count1, gfc_index_one_node);
3879 gfc_add_modify (&body, count1, tmp);
3881 /* Use the scalar assignment as is. */
3882 gfc_add_block_to_block (&block, &body);
3884 else
3886 gcc_assert (lse.ss == gfc_ss_terminator
3887 && rse.ss == gfc_ss_terminator);
3889 if (loop.temp_ss != NULL)
3891 /* Increment count1 before finish the main body of a scalarized
3892 expression. */
3893 tmp = fold_build2_loc (input_location, PLUS_EXPR,
3894 gfc_array_index_type, count1, gfc_index_one_node);
3895 gfc_add_modify (&body, count1, tmp);
3896 gfc_trans_scalarized_loop_boundary (&loop, &body);
3898 /* We need to copy the temporary to the actual lhs. */
3899 gfc_init_se (&lse, NULL);
3900 gfc_init_se (&rse, NULL);
3901 gfc_copy_loopinfo_to_se (&lse, &loop);
3902 gfc_copy_loopinfo_to_se (&rse, &loop);
3904 rse.ss = loop.temp_ss;
3905 lse.ss = lss;
3907 gfc_conv_tmp_array_ref (&rse);
3908 gfc_conv_expr (&lse, expr1);
3910 gcc_assert (lse.ss == gfc_ss_terminator
3911 && rse.ss == gfc_ss_terminator);
3913 /* Form the mask expression according to the mask tree list. */
3914 index = count2;
3915 maskexpr = gfc_build_array_ref (mask, index, NULL);
3916 if (invert)
3917 maskexpr = fold_build1_loc (input_location, TRUTH_NOT_EXPR,
3918 TREE_TYPE (maskexpr), maskexpr);
3920 /* Use the scalar assignment as is. */
3921 tmp = gfc_trans_scalar_assign (&lse, &rse, expr1->ts, false, false,
3922 true);
3923 tmp = build3_v (COND_EXPR, maskexpr, tmp,
3924 build_empty_stmt (input_location));
3925 gfc_add_expr_to_block (&body, tmp);
3927 /* Increment count2. */
3928 tmp = fold_build2_loc (input_location, PLUS_EXPR,
3929 gfc_array_index_type, count2,
3930 gfc_index_one_node);
3931 gfc_add_modify (&body, count2, tmp);
3933 else
3935 /* Increment count1. */
3936 tmp = fold_build2_loc (input_location, PLUS_EXPR,
3937 gfc_array_index_type, count1,
3938 gfc_index_one_node);
3939 gfc_add_modify (&body, count1, tmp);
3942 /* Generate the copying loops. */
3943 gfc_trans_scalarizing_loops (&loop, &body);
3945 /* Wrap the whole thing up. */
3946 gfc_add_block_to_block (&block, &loop.pre);
3947 gfc_add_block_to_block (&block, &loop.post);
3948 gfc_cleanup_loop (&loop);
3951 return gfc_finish_block (&block);
3955 /* Translate the WHERE construct or statement.
3956 This function can be called iteratively to translate the nested WHERE
3957 construct or statement.
3958 MASK is the control mask. */
3960 static void
3961 gfc_trans_where_2 (gfc_code * code, tree mask, bool invert,
3962 forall_info * nested_forall_info, stmtblock_t * block)
3964 stmtblock_t inner_size_body;
3965 tree inner_size, size;
3966 gfc_ss *lss, *rss;
3967 tree mask_type;
3968 gfc_expr *expr1;
3969 gfc_expr *expr2;
3970 gfc_code *cblock;
3971 gfc_code *cnext;
3972 tree tmp;
3973 tree cond;
3974 tree count1, count2;
3975 bool need_cmask;
3976 bool need_pmask;
3977 int need_temp;
3978 tree pcmask = NULL_TREE;
3979 tree ppmask = NULL_TREE;
3980 tree cmask = NULL_TREE;
3981 tree pmask = NULL_TREE;
3982 gfc_actual_arglist *arg;
3984 /* the WHERE statement or the WHERE construct statement. */
3985 cblock = code->block;
3987 /* As the mask array can be very big, prefer compact boolean types. */
3988 mask_type = gfc_get_logical_type (gfc_logical_kinds[0].kind);
3990 /* Determine which temporary masks are needed. */
3991 if (!cblock->block)
3993 /* One clause: No ELSEWHEREs. */
3994 need_cmask = (cblock->next != 0);
3995 need_pmask = false;
3997 else if (cblock->block->block)
3999 /* Three or more clauses: Conditional ELSEWHEREs. */
4000 need_cmask = true;
4001 need_pmask = true;
4003 else if (cblock->next)
4005 /* Two clauses, the first non-empty. */
4006 need_cmask = true;
4007 need_pmask = (mask != NULL_TREE
4008 && cblock->block->next != 0);
4010 else if (!cblock->block->next)
4012 /* Two clauses, both empty. */
4013 need_cmask = false;
4014 need_pmask = false;
4016 /* Two clauses, the first empty, the second non-empty. */
4017 else if (mask)
4019 need_cmask = (cblock->block->expr1 != 0);
4020 need_pmask = true;
4022 else
4024 need_cmask = true;
4025 need_pmask = false;
4028 if (need_cmask || need_pmask)
4030 /* Calculate the size of temporary needed by the mask-expr. */
4031 gfc_init_block (&inner_size_body);
4032 inner_size = compute_inner_temp_size (cblock->expr1, cblock->expr1,
4033 &inner_size_body, &lss, &rss);
4035 gfc_free_ss_chain (lss);
4036 gfc_free_ss_chain (rss);
4038 /* Calculate the total size of temporary needed. */
4039 size = compute_overall_iter_number (nested_forall_info, inner_size,
4040 &inner_size_body, block);
4042 /* Check whether the size is negative. */
4043 cond = fold_build2_loc (input_location, LE_EXPR, boolean_type_node, size,
4044 gfc_index_zero_node);
4045 size = fold_build3_loc (input_location, COND_EXPR, gfc_array_index_type,
4046 cond, gfc_index_zero_node, size);
4047 size = gfc_evaluate_now (size, block);
4049 /* Allocate temporary for WHERE mask if needed. */
4050 if (need_cmask)
4051 cmask = allocate_temp_for_forall_nest_1 (mask_type, size, block,
4052 &pcmask);
4054 /* Allocate temporary for !mask if needed. */
4055 if (need_pmask)
4056 pmask = allocate_temp_for_forall_nest_1 (mask_type, size, block,
4057 &ppmask);
4060 while (cblock)
4062 /* Each time around this loop, the where clause is conditional
4063 on the value of mask and invert, which are updated at the
4064 bottom of the loop. */
4066 /* Has mask-expr. */
4067 if (cblock->expr1)
4069 /* Ensure that the WHERE mask will be evaluated exactly once.
4070 If there are no statements in this WHERE/ELSEWHERE clause,
4071 then we don't need to update the control mask (cmask).
4072 If this is the last clause of the WHERE construct, then
4073 we don't need to update the pending control mask (pmask). */
4074 if (mask)
4075 gfc_evaluate_where_mask (cblock->expr1, nested_forall_info,
4076 mask, invert,
4077 cblock->next ? cmask : NULL_TREE,
4078 cblock->block ? pmask : NULL_TREE,
4079 mask_type, block);
4080 else
4081 gfc_evaluate_where_mask (cblock->expr1, nested_forall_info,
4082 NULL_TREE, false,
4083 (cblock->next || cblock->block)
4084 ? cmask : NULL_TREE,
4085 NULL_TREE, mask_type, block);
4087 invert = false;
4089 /* It's a final elsewhere-stmt. No mask-expr is present. */
4090 else
4091 cmask = mask;
4093 /* The body of this where clause are controlled by cmask with
4094 sense specified by invert. */
4096 /* Get the assignment statement of a WHERE statement, or the first
4097 statement in where-body-construct of a WHERE construct. */
4098 cnext = cblock->next;
4099 while (cnext)
4101 switch (cnext->op)
4103 /* WHERE assignment statement. */
4104 case EXEC_ASSIGN_CALL:
4106 arg = cnext->ext.actual;
4107 expr1 = expr2 = NULL;
4108 for (; arg; arg = arg->next)
4110 if (!arg->expr)
4111 continue;
4112 if (expr1 == NULL)
4113 expr1 = arg->expr;
4114 else
4115 expr2 = arg->expr;
4117 goto evaluate;
4119 case EXEC_ASSIGN:
4120 expr1 = cnext->expr1;
4121 expr2 = cnext->expr2;
4122 evaluate:
4123 if (nested_forall_info != NULL)
4125 need_temp = gfc_check_dependency (expr1, expr2, 0);
4126 if (need_temp && cnext->op != EXEC_ASSIGN_CALL)
4127 gfc_trans_assign_need_temp (expr1, expr2,
4128 cmask, invert,
4129 nested_forall_info, block);
4130 else
4132 /* Variables to control maskexpr. */
4133 count1 = gfc_create_var (gfc_array_index_type, "count1");
4134 count2 = gfc_create_var (gfc_array_index_type, "count2");
4135 gfc_add_modify (block, count1, gfc_index_zero_node);
4136 gfc_add_modify (block, count2, gfc_index_zero_node);
4138 tmp = gfc_trans_where_assign (expr1, expr2,
4139 cmask, invert,
4140 count1, count2,
4141 cnext);
4143 tmp = gfc_trans_nested_forall_loop (nested_forall_info,
4144 tmp, 1);
4145 gfc_add_expr_to_block (block, tmp);
4148 else
4150 /* Variables to control maskexpr. */
4151 count1 = gfc_create_var (gfc_array_index_type, "count1");
4152 count2 = gfc_create_var (gfc_array_index_type, "count2");
4153 gfc_add_modify (block, count1, gfc_index_zero_node);
4154 gfc_add_modify (block, count2, gfc_index_zero_node);
4156 tmp = gfc_trans_where_assign (expr1, expr2,
4157 cmask, invert,
4158 count1, count2,
4159 cnext);
4160 gfc_add_expr_to_block (block, tmp);
4163 break;
4165 /* WHERE or WHERE construct is part of a where-body-construct. */
4166 case EXEC_WHERE:
4167 gfc_trans_where_2 (cnext, cmask, invert,
4168 nested_forall_info, block);
4169 break;
4171 default:
4172 gcc_unreachable ();
4175 /* The next statement within the same where-body-construct. */
4176 cnext = cnext->next;
4178 /* The next masked-elsewhere-stmt, elsewhere-stmt, or end-where-stmt. */
4179 cblock = cblock->block;
4180 if (mask == NULL_TREE)
4182 /* If we're the initial WHERE, we can simply invert the sense
4183 of the current mask to obtain the "mask" for the remaining
4184 ELSEWHEREs. */
4185 invert = true;
4186 mask = cmask;
4188 else
4190 /* Otherwise, for nested WHERE's we need to use the pending mask. */
4191 invert = false;
4192 mask = pmask;
4196 /* If we allocated a pending mask array, deallocate it now. */
4197 if (ppmask)
4199 tmp = gfc_call_free (ppmask);
4200 gfc_add_expr_to_block (block, tmp);
4203 /* If we allocated a current mask array, deallocate it now. */
4204 if (pcmask)
4206 tmp = gfc_call_free (pcmask);
4207 gfc_add_expr_to_block (block, tmp);
4211 /* Translate a simple WHERE construct or statement without dependencies.
4212 CBLOCK is the "then" clause of the WHERE statement, where CBLOCK->EXPR
4213 is the mask condition, and EBLOCK if non-NULL is the "else" clause.
4214 Currently both CBLOCK and EBLOCK are restricted to single assignments. */
4216 static tree
4217 gfc_trans_where_3 (gfc_code * cblock, gfc_code * eblock)
4219 stmtblock_t block, body;
4220 gfc_expr *cond, *tdst, *tsrc, *edst, *esrc;
4221 tree tmp, cexpr, tstmt, estmt;
4222 gfc_ss *css, *tdss, *tsss;
4223 gfc_se cse, tdse, tsse, edse, esse;
4224 gfc_loopinfo loop;
4225 gfc_ss *edss = 0;
4226 gfc_ss *esss = 0;
4228 /* Allow the scalarizer to workshare simple where loops. */
4229 if (ompws_flags & OMPWS_WORKSHARE_FLAG)
4230 ompws_flags |= OMPWS_SCALARIZER_WS;
4232 cond = cblock->expr1;
4233 tdst = cblock->next->expr1;
4234 tsrc = cblock->next->expr2;
4235 edst = eblock ? eblock->next->expr1 : NULL;
4236 esrc = eblock ? eblock->next->expr2 : NULL;
4238 gfc_start_block (&block);
4239 gfc_init_loopinfo (&loop);
4241 /* Handle the condition. */
4242 gfc_init_se (&cse, NULL);
4243 css = gfc_walk_expr (cond);
4244 gfc_add_ss_to_loop (&loop, css);
4246 /* Handle the then-clause. */
4247 gfc_init_se (&tdse, NULL);
4248 gfc_init_se (&tsse, NULL);
4249 tdss = gfc_walk_expr (tdst);
4250 tsss = gfc_walk_expr (tsrc);
4251 if (tsss == gfc_ss_terminator)
4253 tsss = gfc_get_ss ();
4254 tsss->where = 1;
4255 tsss->next = gfc_ss_terminator;
4256 tsss->type = GFC_SS_SCALAR;
4257 tsss->expr = tsrc;
4259 gfc_add_ss_to_loop (&loop, tdss);
4260 gfc_add_ss_to_loop (&loop, tsss);
4262 if (eblock)
4264 /* Handle the else clause. */
4265 gfc_init_se (&edse, NULL);
4266 gfc_init_se (&esse, NULL);
4267 edss = gfc_walk_expr (edst);
4268 esss = gfc_walk_expr (esrc);
4269 if (esss == gfc_ss_terminator)
4271 esss = gfc_get_ss ();
4272 esss->where = 1;
4273 esss->next = gfc_ss_terminator;
4274 esss->type = GFC_SS_SCALAR;
4275 esss->expr = esrc;
4277 gfc_add_ss_to_loop (&loop, edss);
4278 gfc_add_ss_to_loop (&loop, esss);
4281 gfc_conv_ss_startstride (&loop);
4282 gfc_conv_loop_setup (&loop, &tdst->where);
4284 gfc_mark_ss_chain_used (css, 1);
4285 gfc_mark_ss_chain_used (tdss, 1);
4286 gfc_mark_ss_chain_used (tsss, 1);
4287 if (eblock)
4289 gfc_mark_ss_chain_used (edss, 1);
4290 gfc_mark_ss_chain_used (esss, 1);
4293 gfc_start_scalarized_body (&loop, &body);
4295 gfc_copy_loopinfo_to_se (&cse, &loop);
4296 gfc_copy_loopinfo_to_se (&tdse, &loop);
4297 gfc_copy_loopinfo_to_se (&tsse, &loop);
4298 cse.ss = css;
4299 tdse.ss = tdss;
4300 tsse.ss = tsss;
4301 if (eblock)
4303 gfc_copy_loopinfo_to_se (&edse, &loop);
4304 gfc_copy_loopinfo_to_se (&esse, &loop);
4305 edse.ss = edss;
4306 esse.ss = esss;
4309 gfc_conv_expr (&cse, cond);
4310 gfc_add_block_to_block (&body, &cse.pre);
4311 cexpr = cse.expr;
4313 gfc_conv_expr (&tsse, tsrc);
4314 if (tdss != gfc_ss_terminator && loop.temp_ss != NULL)
4315 gfc_conv_tmp_array_ref (&tdse);
4316 else
4317 gfc_conv_expr (&tdse, tdst);
4319 if (eblock)
4321 gfc_conv_expr (&esse, esrc);
4322 if (edss != gfc_ss_terminator && loop.temp_ss != NULL)
4323 gfc_conv_tmp_array_ref (&edse);
4324 else
4325 gfc_conv_expr (&edse, edst);
4328 tstmt = gfc_trans_scalar_assign (&tdse, &tsse, tdst->ts, false, false, true);
4329 estmt = eblock ? gfc_trans_scalar_assign (&edse, &esse, edst->ts, false,
4330 false, true)
4331 : build_empty_stmt (input_location);
4332 tmp = build3_v (COND_EXPR, cexpr, tstmt, estmt);
4333 gfc_add_expr_to_block (&body, tmp);
4334 gfc_add_block_to_block (&body, &cse.post);
4336 gfc_trans_scalarizing_loops (&loop, &body);
4337 gfc_add_block_to_block (&block, &loop.pre);
4338 gfc_add_block_to_block (&block, &loop.post);
4339 gfc_cleanup_loop (&loop);
4341 return gfc_finish_block (&block);
4344 /* As the WHERE or WHERE construct statement can be nested, we call
4345 gfc_trans_where_2 to do the translation, and pass the initial
4346 NULL values for both the control mask and the pending control mask. */
4348 tree
4349 gfc_trans_where (gfc_code * code)
4351 stmtblock_t block;
4352 gfc_code *cblock;
4353 gfc_code *eblock;
4355 cblock = code->block;
4356 if (cblock->next
4357 && cblock->next->op == EXEC_ASSIGN
4358 && !cblock->next->next)
4360 eblock = cblock->block;
4361 if (!eblock)
4363 /* A simple "WHERE (cond) x = y" statement or block is
4364 dependence free if cond is not dependent upon writing x,
4365 and the source y is unaffected by the destination x. */
4366 if (!gfc_check_dependency (cblock->next->expr1,
4367 cblock->expr1, 0)
4368 && !gfc_check_dependency (cblock->next->expr1,
4369 cblock->next->expr2, 0))
4370 return gfc_trans_where_3 (cblock, NULL);
4372 else if (!eblock->expr1
4373 && !eblock->block
4374 && eblock->next
4375 && eblock->next->op == EXEC_ASSIGN
4376 && !eblock->next->next)
4378 /* A simple "WHERE (cond) x1 = y1 ELSEWHERE x2 = y2 ENDWHERE"
4379 block is dependence free if cond is not dependent on writes
4380 to x1 and x2, y1 is not dependent on writes to x2, and y2
4381 is not dependent on writes to x1, and both y's are not
4382 dependent upon their own x's. In addition to this, the
4383 final two dependency checks below exclude all but the same
4384 array reference if the where and elswhere destinations
4385 are the same. In short, this is VERY conservative and this
4386 is needed because the two loops, required by the standard
4387 are coalesced in gfc_trans_where_3. */
4388 if (!gfc_check_dependency(cblock->next->expr1,
4389 cblock->expr1, 0)
4390 && !gfc_check_dependency(eblock->next->expr1,
4391 cblock->expr1, 0)
4392 && !gfc_check_dependency(cblock->next->expr1,
4393 eblock->next->expr2, 1)
4394 && !gfc_check_dependency(eblock->next->expr1,
4395 cblock->next->expr2, 1)
4396 && !gfc_check_dependency(cblock->next->expr1,
4397 cblock->next->expr2, 1)
4398 && !gfc_check_dependency(eblock->next->expr1,
4399 eblock->next->expr2, 1)
4400 && !gfc_check_dependency(cblock->next->expr1,
4401 eblock->next->expr1, 0)
4402 && !gfc_check_dependency(eblock->next->expr1,
4403 cblock->next->expr1, 0))
4404 return gfc_trans_where_3 (cblock, eblock);
4408 gfc_start_block (&block);
4410 gfc_trans_where_2 (code, NULL, false, NULL, &block);
4412 return gfc_finish_block (&block);
4416 /* CYCLE a DO loop. The label decl has already been created by
4417 gfc_trans_do(), it's in TREE_PURPOSE (backend_decl) of the gfc_code
4418 node at the head of the loop. We must mark the label as used. */
4420 tree
4421 gfc_trans_cycle (gfc_code * code)
4423 tree cycle_label;
4425 cycle_label = code->ext.which_construct->cycle_label;
4426 gcc_assert (cycle_label);
4428 TREE_USED (cycle_label) = 1;
4429 return build1_v (GOTO_EXPR, cycle_label);
4433 /* EXIT a DO loop. Similar to CYCLE, but now the label is in
4434 TREE_VALUE (backend_decl) of the gfc_code node at the head of the
4435 loop. */
4437 tree
4438 gfc_trans_exit (gfc_code * code)
4440 tree exit_label;
4442 exit_label = code->ext.which_construct->exit_label;
4443 gcc_assert (exit_label);
4445 TREE_USED (exit_label) = 1;
4446 return build1_v (GOTO_EXPR, exit_label);
4450 /* Translate the ALLOCATE statement. */
4452 tree
4453 gfc_trans_allocate (gfc_code * code)
4455 gfc_alloc *al;
4456 gfc_expr *expr;
4457 gfc_se se;
4458 tree tmp;
4459 tree parm;
4460 tree stat;
4461 tree pstat;
4462 tree error_label;
4463 tree memsz;
4464 tree expr3;
4465 tree slen3;
4466 stmtblock_t block;
4467 stmtblock_t post;
4468 gfc_expr *sz;
4469 gfc_se se_sz;
4471 if (!code->ext.alloc.list)
4472 return NULL_TREE;
4474 pstat = stat = error_label = tmp = memsz = NULL_TREE;
4476 gfc_init_block (&block);
4477 gfc_init_block (&post);
4479 /* Either STAT= and/or ERRMSG is present. */
4480 if (code->expr1 || code->expr2)
4482 tree gfc_int4_type_node = gfc_get_int_type (4);
4484 stat = gfc_create_var (gfc_int4_type_node, "stat");
4485 pstat = gfc_build_addr_expr (NULL_TREE, stat);
4487 error_label = gfc_build_label_decl (NULL_TREE);
4488 TREE_USED (error_label) = 1;
4491 expr3 = NULL_TREE;
4492 slen3 = NULL_TREE;
4494 for (al = code->ext.alloc.list; al != NULL; al = al->next)
4496 expr = gfc_copy_expr (al->expr);
4498 if (expr->ts.type == BT_CLASS)
4499 gfc_add_data_component (expr);
4501 gfc_init_se (&se, NULL);
4503 se.want_pointer = 1;
4504 se.descriptor_only = 1;
4505 gfc_conv_expr (&se, expr);
4507 if (!gfc_array_allocate (&se, expr, pstat))
4509 /* A scalar or derived type. */
4511 /* Determine allocate size. */
4512 if (al->expr->ts.type == BT_CLASS && code->expr3)
4514 if (code->expr3->ts.type == BT_CLASS)
4516 sz = gfc_copy_expr (code->expr3);
4517 gfc_add_vptr_component (sz);
4518 gfc_add_size_component (sz);
4519 gfc_init_se (&se_sz, NULL);
4520 gfc_conv_expr (&se_sz, sz);
4521 gfc_free_expr (sz);
4522 memsz = se_sz.expr;
4524 else
4525 memsz = TYPE_SIZE_UNIT (gfc_typenode_for_spec (&code->expr3->ts));
4527 else if (al->expr->ts.type == BT_CHARACTER
4528 && al->expr->ts.deferred && code->expr3)
4530 if (!code->expr3->ts.u.cl->backend_decl)
4532 /* Convert and use the length expression. */
4533 gfc_init_se (&se_sz, NULL);
4534 if (code->expr3->expr_type == EXPR_VARIABLE
4535 || code->expr3->expr_type == EXPR_CONSTANT)
4537 gfc_conv_expr (&se_sz, code->expr3);
4538 memsz = se_sz.string_length;
4540 else if (code->expr3->mold
4541 && code->expr3->ts.u.cl
4542 && code->expr3->ts.u.cl->length)
4544 gfc_conv_expr (&se_sz, code->expr3->ts.u.cl->length);
4545 gfc_add_block_to_block (&se.pre, &se_sz.pre);
4546 se_sz.expr = gfc_evaluate_now (se_sz.expr, &se.pre);
4547 gfc_add_block_to_block (&se.pre, &se_sz.post);
4548 memsz = se_sz.expr;
4550 else
4552 /* This is would be inefficient and possibly could
4553 generate wrong code if the result were not stored
4554 in expr3/slen3. */
4555 if (slen3 == NULL_TREE)
4557 gfc_conv_expr (&se_sz, code->expr3);
4558 gfc_add_block_to_block (&se.pre, &se_sz.pre);
4559 expr3 = gfc_evaluate_now (se_sz.expr, &se.pre);
4560 gfc_add_block_to_block (&post, &se_sz.post);
4561 slen3 = gfc_evaluate_now (se_sz.string_length,
4562 &se.pre);
4564 memsz = slen3;
4567 else
4568 /* Otherwise use the stored string length. */
4569 memsz = code->expr3->ts.u.cl->backend_decl;
4570 tmp = al->expr->ts.u.cl->backend_decl;
4572 /* Store the string length. */
4573 if (tmp && TREE_CODE (tmp) == VAR_DECL)
4574 gfc_add_modify (&se.pre, tmp, fold_convert (TREE_TYPE (tmp),
4575 memsz));
4577 /* Convert to size in bytes, using the character KIND. */
4578 tmp = TREE_TYPE (gfc_typenode_for_spec (&al->expr->ts));
4579 tmp = TYPE_SIZE_UNIT (tmp);
4580 memsz = fold_build2_loc (input_location, MULT_EXPR,
4581 TREE_TYPE (tmp), tmp,
4582 fold_convert (TREE_TYPE (tmp), memsz));
4584 else if (al->expr->ts.type == BT_CHARACTER && al->expr->ts.deferred)
4586 gcc_assert (code->ext.alloc.ts.u.cl && code->ext.alloc.ts.u.cl->length);
4587 gfc_init_se (&se_sz, NULL);
4588 gfc_conv_expr (&se_sz, code->ext.alloc.ts.u.cl->length);
4589 gfc_add_block_to_block (&se.pre, &se_sz.pre);
4590 se_sz.expr = gfc_evaluate_now (se_sz.expr, &se.pre);
4591 gfc_add_block_to_block (&se.pre, &se_sz.post);
4592 /* Store the string length. */
4593 tmp = al->expr->ts.u.cl->backend_decl;
4594 gfc_add_modify (&se.pre, tmp, fold_convert (TREE_TYPE (tmp),
4595 se_sz.expr));
4596 tmp = TREE_TYPE (gfc_typenode_for_spec (&code->ext.alloc.ts));
4597 tmp = TYPE_SIZE_UNIT (tmp);
4598 memsz = fold_build2_loc (input_location, MULT_EXPR,
4599 TREE_TYPE (tmp), tmp,
4600 fold_convert (TREE_TYPE (se_sz.expr),
4601 se_sz.expr));
4603 else if (code->ext.alloc.ts.type != BT_UNKNOWN)
4604 memsz = TYPE_SIZE_UNIT (gfc_typenode_for_spec (&code->ext.alloc.ts));
4605 else
4606 memsz = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (se.expr)));
4608 if (expr->ts.type == BT_CHARACTER && memsz == NULL_TREE)
4610 memsz = se.string_length;
4612 /* Convert to size in bytes, using the character KIND. */
4613 tmp = TREE_TYPE (gfc_typenode_for_spec (&code->ext.alloc.ts));
4614 tmp = TYPE_SIZE_UNIT (tmp);
4615 memsz = fold_build2_loc (input_location, MULT_EXPR,
4616 TREE_TYPE (tmp), tmp,
4617 fold_convert (TREE_TYPE (tmp), memsz));
4620 /* Allocate - for non-pointers with re-alloc checking. */
4621 if (gfc_expr_attr (expr).allocatable)
4622 tmp = gfc_allocate_array_with_status (&se.pre, se.expr, memsz,
4623 pstat, expr);
4624 else
4625 tmp = gfc_allocate_with_status (&se.pre, memsz, pstat);
4627 tmp = fold_build2_loc (input_location, MODIFY_EXPR, void_type_node,
4628 se.expr,
4629 fold_convert (TREE_TYPE (se.expr), tmp));
4630 gfc_add_expr_to_block (&se.pre, tmp);
4632 if (code->expr1 || code->expr2)
4634 tmp = build1_v (GOTO_EXPR, error_label);
4635 parm = fold_build2_loc (input_location, NE_EXPR,
4636 boolean_type_node, stat,
4637 build_int_cst (TREE_TYPE (stat), 0));
4638 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
4639 parm, tmp,
4640 build_empty_stmt (input_location));
4641 gfc_add_expr_to_block (&se.pre, tmp);
4644 if (expr->ts.type == BT_DERIVED && expr->ts.u.derived->attr.alloc_comp)
4646 tmp = build_fold_indirect_ref_loc (input_location, se.expr);
4647 tmp = gfc_nullify_alloc_comp (expr->ts.u.derived, tmp, 0);
4648 gfc_add_expr_to_block (&se.pre, tmp);
4652 gfc_add_block_to_block (&block, &se.pre);
4654 if (code->expr3 && !code->expr3->mold)
4656 /* Initialization via SOURCE block
4657 (or static default initializer). */
4658 gfc_expr *rhs = gfc_copy_expr (code->expr3);
4659 if (al->expr->ts.type == BT_CLASS)
4661 gfc_se call;
4662 gfc_actual_arglist *actual;
4663 gfc_expr *ppc;
4664 gfc_init_se (&call, NULL);
4665 /* Do a polymorphic deep copy. */
4666 actual = gfc_get_actual_arglist ();
4667 actual->expr = gfc_copy_expr (rhs);
4668 if (rhs->ts.type == BT_CLASS)
4669 gfc_add_data_component (actual->expr);
4670 actual->next = gfc_get_actual_arglist ();
4671 actual->next->expr = gfc_copy_expr (al->expr);
4672 gfc_add_data_component (actual->next->expr);
4673 if (rhs->ts.type == BT_CLASS)
4675 ppc = gfc_copy_expr (rhs);
4676 gfc_add_vptr_component (ppc);
4678 else
4679 ppc = gfc_lval_expr_from_sym (gfc_find_derived_vtab (rhs->ts.u.derived));
4680 gfc_add_component_ref (ppc, "_copy");
4681 gfc_conv_procedure_call (&call, ppc->symtree->n.sym, actual,
4682 ppc, NULL);
4683 gfc_add_expr_to_block (&call.pre, call.expr);
4684 gfc_add_block_to_block (&call.pre, &call.post);
4685 tmp = gfc_finish_block (&call.pre);
4687 else if (expr3 != NULL_TREE)
4689 tmp = build_fold_indirect_ref_loc (input_location, se.expr);
4690 gfc_trans_string_copy (&block, slen3, tmp, code->expr3->ts.kind,
4691 slen3, expr3, code->expr3->ts.kind);
4692 tmp = NULL_TREE;
4694 else
4696 /* Switch off automatic reallocation since we have just done
4697 the ALLOCATE. */
4698 int realloc_lhs = gfc_option.flag_realloc_lhs;
4699 gfc_option.flag_realloc_lhs = 0;
4700 tmp = gfc_trans_assignment (gfc_expr_to_initialize (expr),
4701 rhs, false, false);
4702 gfc_option.flag_realloc_lhs = realloc_lhs;
4704 gfc_free_expr (rhs);
4705 gfc_add_expr_to_block (&block, tmp);
4707 else if (code->expr3 && code->expr3->mold
4708 && code->expr3->ts.type == BT_CLASS)
4710 /* Default-initialization via MOLD (polymorphic). */
4711 gfc_expr *rhs = gfc_copy_expr (code->expr3);
4712 gfc_se dst,src;
4713 gfc_add_vptr_component (rhs);
4714 gfc_add_def_init_component (rhs);
4715 gfc_init_se (&dst, NULL);
4716 gfc_init_se (&src, NULL);
4717 gfc_conv_expr (&dst, expr);
4718 gfc_conv_expr (&src, rhs);
4719 gfc_add_block_to_block (&block, &src.pre);
4720 tmp = gfc_build_memcpy_call (dst.expr, src.expr, memsz);
4721 gfc_add_expr_to_block (&block, tmp);
4722 gfc_free_expr (rhs);
4725 /* Allocation of CLASS entities. */
4726 gfc_free_expr (expr);
4727 expr = al->expr;
4728 if (expr->ts.type == BT_CLASS)
4730 gfc_expr *lhs,*rhs;
4731 gfc_se lse;
4733 /* Initialize VPTR for CLASS objects. */
4734 lhs = gfc_expr_to_initialize (expr);
4735 gfc_add_vptr_component (lhs);
4736 rhs = NULL;
4737 if (code->expr3 && code->expr3->ts.type == BT_CLASS)
4739 /* Polymorphic SOURCE: VPTR must be determined at run time. */
4740 rhs = gfc_copy_expr (code->expr3);
4741 gfc_add_vptr_component (rhs);
4742 tmp = gfc_trans_pointer_assignment (lhs, rhs);
4743 gfc_add_expr_to_block (&block, tmp);
4744 gfc_free_expr (rhs);
4746 else
4748 /* VPTR is fixed at compile time. */
4749 gfc_symbol *vtab;
4750 gfc_typespec *ts;
4751 if (code->expr3)
4752 ts = &code->expr3->ts;
4753 else if (expr->ts.type == BT_DERIVED)
4754 ts = &expr->ts;
4755 else if (code->ext.alloc.ts.type == BT_DERIVED)
4756 ts = &code->ext.alloc.ts;
4757 else if (expr->ts.type == BT_CLASS)
4758 ts = &CLASS_DATA (expr)->ts;
4759 else
4760 ts = &expr->ts;
4762 if (ts->type == BT_DERIVED)
4764 vtab = gfc_find_derived_vtab (ts->u.derived);
4765 gcc_assert (vtab);
4766 gfc_init_se (&lse, NULL);
4767 lse.want_pointer = 1;
4768 gfc_conv_expr (&lse, lhs);
4769 tmp = gfc_build_addr_expr (NULL_TREE,
4770 gfc_get_symbol_decl (vtab));
4771 gfc_add_modify (&block, lse.expr,
4772 fold_convert (TREE_TYPE (lse.expr), tmp));
4775 gfc_free_expr (lhs);
4780 /* STAT block. */
4781 if (code->expr1)
4783 tmp = build1_v (LABEL_EXPR, error_label);
4784 gfc_add_expr_to_block (&block, tmp);
4786 gfc_init_se (&se, NULL);
4787 gfc_conv_expr_lhs (&se, code->expr1);
4788 tmp = convert (TREE_TYPE (se.expr), stat);
4789 gfc_add_modify (&block, se.expr, tmp);
4792 /* ERRMSG block. */
4793 if (code->expr2)
4795 /* A better error message may be possible, but not required. */
4796 const char *msg = "Attempt to allocate an allocated object";
4797 tree errmsg, slen, dlen;
4799 gfc_init_se (&se, NULL);
4800 gfc_conv_expr_lhs (&se, code->expr2);
4802 errmsg = gfc_create_var (pchar_type_node, "ERRMSG");
4804 gfc_add_modify (&block, errmsg,
4805 gfc_build_addr_expr (pchar_type_node,
4806 gfc_build_localized_cstring_const (msg)));
4808 slen = build_int_cst (gfc_charlen_type_node, ((int) strlen (msg)));
4809 dlen = gfc_get_expr_charlen (code->expr2);
4810 slen = fold_build2_loc (input_location, MIN_EXPR, TREE_TYPE (slen), dlen,
4811 slen);
4813 dlen = build_call_expr_loc (input_location,
4814 built_in_decls[BUILT_IN_MEMCPY], 3,
4815 gfc_build_addr_expr (pvoid_type_node, se.expr), errmsg, slen);
4817 tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, stat,
4818 build_int_cst (TREE_TYPE (stat), 0));
4820 tmp = build3_v (COND_EXPR, tmp, dlen, build_empty_stmt (input_location));
4822 gfc_add_expr_to_block (&block, tmp);
4825 gfc_add_block_to_block (&block, &se.post);
4826 gfc_add_block_to_block (&block, &post);
4828 return gfc_finish_block (&block);
4832 /* Translate a DEALLOCATE statement. */
4834 tree
4835 gfc_trans_deallocate (gfc_code *code)
4837 gfc_se se;
4838 gfc_alloc *al;
4839 tree apstat, astat, pstat, stat, tmp;
4840 stmtblock_t block;
4842 pstat = apstat = stat = astat = tmp = NULL_TREE;
4844 gfc_start_block (&block);
4846 /* Count the number of failed deallocations. If deallocate() was
4847 called with STAT= , then set STAT to the count. If deallocate
4848 was called with ERRMSG, then set ERRMG to a string. */
4849 if (code->expr1 || code->expr2)
4851 tree gfc_int4_type_node = gfc_get_int_type (4);
4853 stat = gfc_create_var (gfc_int4_type_node, "stat");
4854 pstat = gfc_build_addr_expr (NULL_TREE, stat);
4856 /* Running total of possible deallocation failures. */
4857 astat = gfc_create_var (gfc_int4_type_node, "astat");
4858 apstat = gfc_build_addr_expr (NULL_TREE, astat);
4860 /* Initialize astat to 0. */
4861 gfc_add_modify (&block, astat, build_int_cst (TREE_TYPE (astat), 0));
4864 for (al = code->ext.alloc.list; al != NULL; al = al->next)
4866 gfc_expr *expr = gfc_copy_expr (al->expr);
4867 gcc_assert (expr->expr_type == EXPR_VARIABLE);
4869 if (expr->ts.type == BT_CLASS)
4870 gfc_add_data_component (expr);
4872 gfc_init_se (&se, NULL);
4873 gfc_start_block (&se.pre);
4875 se.want_pointer = 1;
4876 se.descriptor_only = 1;
4877 gfc_conv_expr (&se, expr);
4879 if (expr->rank)
4881 if (expr->ts.type == BT_DERIVED && expr->ts.u.derived->attr.alloc_comp)
4883 gfc_ref *ref;
4884 gfc_ref *last = NULL;
4885 for (ref = expr->ref; ref; ref = ref->next)
4886 if (ref->type == REF_COMPONENT)
4887 last = ref;
4889 /* Do not deallocate the components of a derived type
4890 ultimate pointer component. */
4891 if (!(last && last->u.c.component->attr.pointer)
4892 && !(!last && expr->symtree->n.sym->attr.pointer))
4894 tmp = gfc_deallocate_alloc_comp (expr->ts.u.derived, se.expr,
4895 expr->rank);
4896 gfc_add_expr_to_block (&se.pre, tmp);
4899 tmp = gfc_array_deallocate (se.expr, pstat, expr);
4900 gfc_add_expr_to_block (&se.pre, tmp);
4902 else
4904 tmp = gfc_deallocate_scalar_with_status (se.expr, pstat, false,
4905 expr, expr->ts);
4906 gfc_add_expr_to_block (&se.pre, tmp);
4908 /* Set to zero after deallocation. */
4909 tmp = fold_build2_loc (input_location, MODIFY_EXPR, void_type_node,
4910 se.expr,
4911 build_int_cst (TREE_TYPE (se.expr), 0));
4912 gfc_add_expr_to_block (&se.pre, tmp);
4914 if (al->expr->ts.type == BT_CLASS)
4916 /* Reset _vptr component to declared type. */
4917 gfc_expr *rhs, *lhs = gfc_copy_expr (al->expr);
4918 gfc_symbol *vtab = gfc_find_derived_vtab (al->expr->ts.u.derived);
4919 gfc_add_vptr_component (lhs);
4920 rhs = gfc_lval_expr_from_sym (vtab);
4921 tmp = gfc_trans_pointer_assignment (lhs, rhs);
4922 gfc_add_expr_to_block (&se.pre, tmp);
4923 gfc_free_expr (lhs);
4924 gfc_free_expr (rhs);
4928 /* Keep track of the number of failed deallocations by adding stat
4929 of the last deallocation to the running total. */
4930 if (code->expr1 || code->expr2)
4932 apstat = fold_build2_loc (input_location, PLUS_EXPR,
4933 TREE_TYPE (stat), astat, stat);
4934 gfc_add_modify (&se.pre, astat, apstat);
4937 tmp = gfc_finish_block (&se.pre);
4938 gfc_add_expr_to_block (&block, tmp);
4939 gfc_free_expr (expr);
4942 /* Set STAT. */
4943 if (code->expr1)
4945 gfc_init_se (&se, NULL);
4946 gfc_conv_expr_lhs (&se, code->expr1);
4947 tmp = convert (TREE_TYPE (se.expr), astat);
4948 gfc_add_modify (&block, se.expr, tmp);
4951 /* Set ERRMSG. */
4952 if (code->expr2)
4954 /* A better error message may be possible, but not required. */
4955 const char *msg = "Attempt to deallocate an unallocated object";
4956 tree errmsg, slen, dlen;
4958 gfc_init_se (&se, NULL);
4959 gfc_conv_expr_lhs (&se, code->expr2);
4961 errmsg = gfc_create_var (pchar_type_node, "ERRMSG");
4963 gfc_add_modify (&block, errmsg,
4964 gfc_build_addr_expr (pchar_type_node,
4965 gfc_build_localized_cstring_const (msg)));
4967 slen = build_int_cst (gfc_charlen_type_node, ((int) strlen (msg)));
4968 dlen = gfc_get_expr_charlen (code->expr2);
4969 slen = fold_build2_loc (input_location, MIN_EXPR, TREE_TYPE (slen), dlen,
4970 slen);
4972 dlen = build_call_expr_loc (input_location,
4973 built_in_decls[BUILT_IN_MEMCPY], 3,
4974 gfc_build_addr_expr (pvoid_type_node, se.expr), errmsg, slen);
4976 tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, astat,
4977 build_int_cst (TREE_TYPE (astat), 0));
4979 tmp = build3_v (COND_EXPR, tmp, dlen, build_empty_stmt (input_location));
4981 gfc_add_expr_to_block (&block, tmp);
4984 return gfc_finish_block (&block);
4987 #include "gt-fortran-trans-stmt.h"