2012-05-05 Paul Thomas <pault@gcc.gnu.org>
[official-gcc.git] / gcc / fortran / trans-stmt.c
blob323fca382c3fe0950aff8fddba73878c23c4347d
1 /* Statement translation -- generate GCC trees from gfc_code.
2 Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
3 2011, 2012
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 (gfc_charlen_type_node, label_len);
123 label_tree = gfc_build_wide_string_const (format->ts.kind, label_len + 1,
124 format->value.character.string);
125 label_tree = gfc_build_addr_expr (pvoid_type_node, label_tree);
128 gfc_add_modify (&se.pre, len, len_tree);
129 gfc_add_modify (&se.pre, addr, label_tree);
131 return gfc_finish_block (&se.pre);
134 /* Translate a GOTO statement. */
136 tree
137 gfc_trans_goto (gfc_code * code)
139 locus loc = code->loc;
140 tree assigned_goto;
141 tree target;
142 tree tmp;
143 gfc_se se;
145 if (code->label1 != NULL)
146 return build1_v (GOTO_EXPR, gfc_get_label_decl (code->label1));
148 /* ASSIGNED GOTO. */
149 gfc_init_se (&se, NULL);
150 gfc_start_block (&se.pre);
151 gfc_conv_label_variable (&se, code->expr1);
152 tmp = GFC_DECL_STRING_LEN (se.expr);
153 tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, tmp,
154 build_int_cst (TREE_TYPE (tmp), -1));
155 gfc_trans_runtime_check (true, false, tmp, &se.pre, &loc,
156 "Assigned label is not a target label");
158 assigned_goto = GFC_DECL_ASSIGN_ADDR (se.expr);
160 /* We're going to ignore a label list. It does not really change the
161 statement's semantics (because it is just a further restriction on
162 what's legal code); before, we were comparing label addresses here, but
163 that's a very fragile business and may break with optimization. So
164 just ignore it. */
166 target = fold_build1_loc (input_location, GOTO_EXPR, void_type_node,
167 assigned_goto);
168 gfc_add_expr_to_block (&se.pre, target);
169 return gfc_finish_block (&se.pre);
173 /* Translate an ENTRY statement. Just adds a label for this entry point. */
174 tree
175 gfc_trans_entry (gfc_code * code)
177 return build1_v (LABEL_EXPR, code->ext.entry->label);
181 /* Replace a gfc_ss structure by another both in the gfc_se struct
182 and the gfc_loopinfo struct. This is used in gfc_conv_elemental_dependencies
183 to replace a variable ss by the corresponding temporary. */
185 static void
186 replace_ss (gfc_se *se, gfc_ss *old_ss, gfc_ss *new_ss)
188 gfc_ss **sess, **loopss;
190 /* The old_ss is a ss for a single variable. */
191 gcc_assert (old_ss->info->type == GFC_SS_SECTION);
193 for (sess = &(se->ss); *sess != gfc_ss_terminator; sess = &((*sess)->next))
194 if (*sess == old_ss)
195 break;
196 gcc_assert (*sess != gfc_ss_terminator);
198 *sess = new_ss;
199 new_ss->next = old_ss->next;
202 for (loopss = &(se->loop->ss); *loopss != gfc_ss_terminator;
203 loopss = &((*loopss)->loop_chain))
204 if (*loopss == old_ss)
205 break;
206 gcc_assert (*loopss != gfc_ss_terminator);
208 *loopss = new_ss;
209 new_ss->loop_chain = old_ss->loop_chain;
210 new_ss->loop = old_ss->loop;
212 gfc_free_ss (old_ss);
216 /* Check for dependencies between INTENT(IN) and INTENT(OUT) arguments of
217 elemental subroutines. Make temporaries for output arguments if any such
218 dependencies are found. Output arguments are chosen because internal_unpack
219 can be used, as is, to copy the result back to the variable. */
220 static void
221 gfc_conv_elemental_dependencies (gfc_se * se, gfc_se * loopse,
222 gfc_symbol * sym, gfc_actual_arglist * arg,
223 gfc_dep_check check_variable)
225 gfc_actual_arglist *arg0;
226 gfc_expr *e;
227 gfc_formal_arglist *formal;
228 gfc_se parmse;
229 gfc_ss *ss;
230 gfc_symbol *fsym;
231 tree data;
232 tree size;
233 tree tmp;
235 if (loopse->ss == NULL)
236 return;
238 ss = loopse->ss;
239 arg0 = arg;
240 formal = sym->formal;
242 /* Loop over all the arguments testing for dependencies. */
243 for (; arg != NULL; arg = arg->next, formal = formal ? formal->next : NULL)
245 e = arg->expr;
246 if (e == NULL)
247 continue;
249 /* Obtain the info structure for the current argument. */
250 for (ss = loopse->ss; ss && ss != gfc_ss_terminator; ss = ss->next)
251 if (ss->info->expr == e)
252 break;
254 /* If there is a dependency, create a temporary and use it
255 instead of the variable. */
256 fsym = formal ? formal->sym : NULL;
257 if (e->expr_type == EXPR_VARIABLE
258 && e->rank && fsym
259 && fsym->attr.intent != INTENT_IN
260 && gfc_check_fncall_dependency (e, fsym->attr.intent,
261 sym, arg0, check_variable))
263 tree initial, temptype;
264 stmtblock_t temp_post;
265 gfc_ss *tmp_ss;
267 tmp_ss = gfc_get_array_ss (gfc_ss_terminator, NULL, ss->dimen,
268 GFC_SS_SECTION);
269 gfc_mark_ss_chain_used (tmp_ss, 1);
270 tmp_ss->info->expr = ss->info->expr;
271 replace_ss (loopse, ss, tmp_ss);
273 /* Obtain the argument descriptor for unpacking. */
274 gfc_init_se (&parmse, NULL);
275 parmse.want_pointer = 1;
276 gfc_conv_expr_descriptor (&parmse, e, gfc_walk_expr (e));
277 gfc_add_block_to_block (&se->pre, &parmse.pre);
279 /* If we've got INTENT(INOUT) or a derived type with INTENT(OUT),
280 initialize the array temporary with a copy of the values. */
281 if (fsym->attr.intent == INTENT_INOUT
282 || (fsym->ts.type ==BT_DERIVED
283 && fsym->attr.intent == INTENT_OUT))
284 initial = parmse.expr;
285 /* For class expressions, we always initialize with the copy of
286 the values. */
287 else if (e->ts.type == BT_CLASS)
288 initial = parmse.expr;
289 else
290 initial = NULL_TREE;
292 if (e->ts.type != BT_CLASS)
294 /* Find the type of the temporary to create; we don't use the type
295 of e itself as this breaks for subcomponent-references in e
296 (where the type of e is that of the final reference, but
297 parmse.expr's type corresponds to the full derived-type). */
298 /* TODO: Fix this somehow so we don't need a temporary of the whole
299 array but instead only the components referenced. */
300 temptype = TREE_TYPE (parmse.expr); /* Pointer to descriptor. */
301 gcc_assert (TREE_CODE (temptype) == POINTER_TYPE);
302 temptype = TREE_TYPE (temptype);
303 temptype = gfc_get_element_type (temptype);
306 else
307 /* For class arrays signal that the size of the dynamic type has to
308 be obtained from the vtable, using the 'initial' expression. */
309 temptype = NULL_TREE;
311 /* Generate the temporary. Cleaning up the temporary should be the
312 very last thing done, so we add the code to a new block and add it
313 to se->post as last instructions. */
314 size = gfc_create_var (gfc_array_index_type, NULL);
315 data = gfc_create_var (pvoid_type_node, NULL);
316 gfc_init_block (&temp_post);
317 tmp = gfc_trans_create_temp_array (&se->pre, &temp_post, tmp_ss,
318 temptype, initial, false, true,
319 false, &arg->expr->where);
320 gfc_add_modify (&se->pre, size, tmp);
321 tmp = fold_convert (pvoid_type_node, tmp_ss->info->data.array.data);
322 gfc_add_modify (&se->pre, data, tmp);
324 /* Update other ss' delta. */
325 gfc_set_delta (loopse->loop);
327 /* Copy the result back using unpack..... */
328 if (e->ts.type != BT_CLASS)
329 tmp = build_call_expr_loc (input_location,
330 gfor_fndecl_in_unpack, 2, parmse.expr, data);
331 else
333 /* ... except for class results where the copy is
334 unconditional. */
335 tmp = build_fold_indirect_ref_loc (input_location, parmse.expr);
336 tmp = gfc_conv_descriptor_data_get (tmp);
337 tmp = build_call_expr_loc (input_location,
338 builtin_decl_explicit (BUILT_IN_MEMCPY),
339 3, tmp, data, size);
341 gfc_add_expr_to_block (&se->post, tmp);
343 /* parmse.pre is already added above. */
344 gfc_add_block_to_block (&se->post, &parmse.post);
345 gfc_add_block_to_block (&se->post, &temp_post);
351 /* Get the interface symbol for the procedure corresponding to the given call.
352 We can't get the procedure symbol directly as we have to handle the case
353 of (deferred) type-bound procedures. */
355 static gfc_symbol *
356 get_proc_ifc_for_call (gfc_code *c)
358 gfc_symbol *sym;
360 gcc_assert (c->op == EXEC_ASSIGN_CALL || c->op == EXEC_CALL);
362 sym = gfc_get_proc_ifc_for_expr (c->expr1);
364 /* Fall back/last resort try. */
365 if (sym == NULL)
366 sym = c->resolved_sym;
368 return sym;
372 /* Translate the CALL statement. Builds a call to an F95 subroutine. */
374 tree
375 gfc_trans_call (gfc_code * code, bool dependency_check,
376 tree mask, tree count1, bool invert)
378 gfc_se se;
379 gfc_ss * ss;
380 int has_alternate_specifier;
381 gfc_dep_check check_variable;
382 tree index = NULL_TREE;
383 tree maskexpr = NULL_TREE;
384 tree tmp;
386 /* A CALL starts a new block because the actual arguments may have to
387 be evaluated first. */
388 gfc_init_se (&se, NULL);
389 gfc_start_block (&se.pre);
391 gcc_assert (code->resolved_sym);
393 ss = gfc_ss_terminator;
394 if (code->resolved_sym->attr.elemental)
395 ss = gfc_walk_elemental_function_args (ss, code->ext.actual,
396 get_proc_ifc_for_call (code),
397 GFC_SS_REFERENCE);
399 /* Is not an elemental subroutine call with array valued arguments. */
400 if (ss == gfc_ss_terminator)
403 /* Translate the call. */
404 has_alternate_specifier
405 = gfc_conv_procedure_call (&se, code->resolved_sym, code->ext.actual,
406 code->expr1, NULL);
408 /* A subroutine without side-effect, by definition, does nothing! */
409 TREE_SIDE_EFFECTS (se.expr) = 1;
411 /* Chain the pieces together and return the block. */
412 if (has_alternate_specifier)
414 gfc_code *select_code;
415 gfc_symbol *sym;
416 select_code = code->next;
417 gcc_assert(select_code->op == EXEC_SELECT);
418 sym = select_code->expr1->symtree->n.sym;
419 se.expr = convert (gfc_typenode_for_spec (&sym->ts), se.expr);
420 if (sym->backend_decl == NULL)
421 sym->backend_decl = gfc_get_symbol_decl (sym);
422 gfc_add_modify (&se.pre, sym->backend_decl, se.expr);
424 else
425 gfc_add_expr_to_block (&se.pre, se.expr);
427 gfc_add_block_to_block (&se.pre, &se.post);
430 else
432 /* An elemental subroutine call with array valued arguments has
433 to be scalarized. */
434 gfc_loopinfo loop;
435 stmtblock_t body;
436 stmtblock_t block;
437 gfc_se loopse;
438 gfc_se depse;
440 /* gfc_walk_elemental_function_args renders the ss chain in the
441 reverse order to the actual argument order. */
442 ss = gfc_reverse_ss (ss);
444 /* Initialize the loop. */
445 gfc_init_se (&loopse, NULL);
446 gfc_init_loopinfo (&loop);
447 gfc_add_ss_to_loop (&loop, ss);
449 gfc_conv_ss_startstride (&loop);
450 /* TODO: gfc_conv_loop_setup generates a temporary for vector
451 subscripts. This could be prevented in the elemental case
452 as temporaries are handled separatedly
453 (below in gfc_conv_elemental_dependencies). */
454 gfc_conv_loop_setup (&loop, &code->expr1->where);
455 gfc_mark_ss_chain_used (ss, 1);
457 /* Convert the arguments, checking for dependencies. */
458 gfc_copy_loopinfo_to_se (&loopse, &loop);
459 loopse.ss = ss;
461 /* For operator assignment, do dependency checking. */
462 if (dependency_check)
463 check_variable = ELEM_CHECK_VARIABLE;
464 else
465 check_variable = ELEM_DONT_CHECK_VARIABLE;
467 gfc_init_se (&depse, NULL);
468 gfc_conv_elemental_dependencies (&depse, &loopse, code->resolved_sym,
469 code->ext.actual, check_variable);
471 gfc_add_block_to_block (&loop.pre, &depse.pre);
472 gfc_add_block_to_block (&loop.post, &depse.post);
474 /* Generate the loop body. */
475 gfc_start_scalarized_body (&loop, &body);
476 gfc_init_block (&block);
478 if (mask && count1)
480 /* Form the mask expression according to the mask. */
481 index = count1;
482 maskexpr = gfc_build_array_ref (mask, index, NULL);
483 if (invert)
484 maskexpr = fold_build1_loc (input_location, TRUTH_NOT_EXPR,
485 TREE_TYPE (maskexpr), maskexpr);
488 /* Add the subroutine call to the block. */
489 gfc_conv_procedure_call (&loopse, code->resolved_sym,
490 code->ext.actual, code->expr1, NULL);
492 if (mask && count1)
494 tmp = build3_v (COND_EXPR, maskexpr, loopse.expr,
495 build_empty_stmt (input_location));
496 gfc_add_expr_to_block (&loopse.pre, tmp);
497 tmp = fold_build2_loc (input_location, PLUS_EXPR,
498 gfc_array_index_type,
499 count1, gfc_index_one_node);
500 gfc_add_modify (&loopse.pre, count1, tmp);
502 else
503 gfc_add_expr_to_block (&loopse.pre, loopse.expr);
505 gfc_add_block_to_block (&block, &loopse.pre);
506 gfc_add_block_to_block (&block, &loopse.post);
508 /* Finish up the loop block and the loop. */
509 gfc_add_expr_to_block (&body, gfc_finish_block (&block));
510 gfc_trans_scalarizing_loops (&loop, &body);
511 gfc_add_block_to_block (&se.pre, &loop.pre);
512 gfc_add_block_to_block (&se.pre, &loop.post);
513 gfc_add_block_to_block (&se.pre, &se.post);
514 gfc_cleanup_loop (&loop);
517 return gfc_finish_block (&se.pre);
521 /* Translate the RETURN statement. */
523 tree
524 gfc_trans_return (gfc_code * code)
526 if (code->expr1)
528 gfc_se se;
529 tree tmp;
530 tree result;
532 /* If code->expr is not NULL, this return statement must appear
533 in a subroutine and current_fake_result_decl has already
534 been generated. */
536 result = gfc_get_fake_result_decl (NULL, 0);
537 if (!result)
539 gfc_warning ("An alternate return at %L without a * dummy argument",
540 &code->expr1->where);
541 return gfc_generate_return ();
544 /* Start a new block for this statement. */
545 gfc_init_se (&se, NULL);
546 gfc_start_block (&se.pre);
548 gfc_conv_expr (&se, code->expr1);
550 /* Note that the actually returned expression is a simple value and
551 does not depend on any pointers or such; thus we can clean-up with
552 se.post before returning. */
553 tmp = fold_build2_loc (input_location, MODIFY_EXPR, TREE_TYPE (result),
554 result, fold_convert (TREE_TYPE (result),
555 se.expr));
556 gfc_add_expr_to_block (&se.pre, tmp);
557 gfc_add_block_to_block (&se.pre, &se.post);
559 tmp = gfc_generate_return ();
560 gfc_add_expr_to_block (&se.pre, tmp);
561 return gfc_finish_block (&se.pre);
564 return gfc_generate_return ();
568 /* Translate the PAUSE statement. We have to translate this statement
569 to a runtime library call. */
571 tree
572 gfc_trans_pause (gfc_code * code)
574 tree gfc_int4_type_node = gfc_get_int_type (4);
575 gfc_se se;
576 tree tmp;
578 /* Start a new block for this statement. */
579 gfc_init_se (&se, NULL);
580 gfc_start_block (&se.pre);
583 if (code->expr1 == NULL)
585 tmp = build_int_cst (gfc_int4_type_node, 0);
586 tmp = build_call_expr_loc (input_location,
587 gfor_fndecl_pause_string, 2,
588 build_int_cst (pchar_type_node, 0), tmp);
590 else if (code->expr1->ts.type == BT_INTEGER)
592 gfc_conv_expr (&se, code->expr1);
593 tmp = build_call_expr_loc (input_location,
594 gfor_fndecl_pause_numeric, 1,
595 fold_convert (gfc_int4_type_node, se.expr));
597 else
599 gfc_conv_expr_reference (&se, code->expr1);
600 tmp = build_call_expr_loc (input_location,
601 gfor_fndecl_pause_string, 2,
602 se.expr, se.string_length);
605 gfc_add_expr_to_block (&se.pre, tmp);
607 gfc_add_block_to_block (&se.pre, &se.post);
609 return gfc_finish_block (&se.pre);
613 /* Translate the STOP statement. We have to translate this statement
614 to a runtime library call. */
616 tree
617 gfc_trans_stop (gfc_code *code, bool error_stop)
619 tree gfc_int4_type_node = gfc_get_int_type (4);
620 gfc_se se;
621 tree tmp;
623 /* Start a new block for this statement. */
624 gfc_init_se (&se, NULL);
625 gfc_start_block (&se.pre);
627 if (gfc_option.coarray == GFC_FCOARRAY_LIB && !error_stop)
629 /* Per F2008, 8.5.1 STOP implies a SYNC MEMORY. */
630 tmp = builtin_decl_explicit (BUILT_IN_SYNC_SYNCHRONIZE);
631 tmp = build_call_expr_loc (input_location, tmp, 0);
632 gfc_add_expr_to_block (&se.pre, tmp);
634 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_finalize, 0);
635 gfc_add_expr_to_block (&se.pre, tmp);
638 if (code->expr1 == NULL)
640 tmp = build_int_cst (gfc_int4_type_node, 0);
641 tmp = build_call_expr_loc (input_location,
642 error_stop
643 ? (gfc_option.coarray == GFC_FCOARRAY_LIB
644 ? gfor_fndecl_caf_error_stop_str
645 : gfor_fndecl_error_stop_string)
646 : gfor_fndecl_stop_string,
647 2, build_int_cst (pchar_type_node, 0), tmp);
649 else if (code->expr1->ts.type == BT_INTEGER)
651 gfc_conv_expr (&se, code->expr1);
652 tmp = build_call_expr_loc (input_location,
653 error_stop
654 ? (gfc_option.coarray == GFC_FCOARRAY_LIB
655 ? gfor_fndecl_caf_error_stop
656 : gfor_fndecl_error_stop_numeric)
657 : gfor_fndecl_stop_numeric_f08, 1,
658 fold_convert (gfc_int4_type_node, se.expr));
660 else
662 gfc_conv_expr_reference (&se, code->expr1);
663 tmp = build_call_expr_loc (input_location,
664 error_stop
665 ? (gfc_option.coarray == GFC_FCOARRAY_LIB
666 ? gfor_fndecl_caf_error_stop_str
667 : gfor_fndecl_error_stop_string)
668 : gfor_fndecl_stop_string,
669 2, se.expr, se.string_length);
672 gfc_add_expr_to_block (&se.pre, tmp);
674 gfc_add_block_to_block (&se.pre, &se.post);
676 return gfc_finish_block (&se.pre);
680 tree
681 gfc_trans_lock_unlock (gfc_code *code, gfc_exec_op type ATTRIBUTE_UNUSED)
683 gfc_se se, argse;
684 tree stat = NULL_TREE, lock_acquired = NULL_TREE;
686 /* Short cut: For single images without STAT= or LOCK_ACQUIRED
687 return early. (ERRMSG= is always untouched for -fcoarray=single.) */
688 if (!code->expr2 && !code->expr4 && gfc_option.coarray != GFC_FCOARRAY_LIB)
689 return NULL_TREE;
691 gfc_init_se (&se, NULL);
692 gfc_start_block (&se.pre);
694 if (code->expr2)
696 gcc_assert (code->expr2->expr_type == EXPR_VARIABLE);
697 gfc_init_se (&argse, NULL);
698 gfc_conv_expr_val (&argse, code->expr2);
699 stat = argse.expr;
702 if (code->expr4)
704 gcc_assert (code->expr4->expr_type == EXPR_VARIABLE);
705 gfc_init_se (&argse, NULL);
706 gfc_conv_expr_val (&argse, code->expr4);
707 lock_acquired = argse.expr;
710 if (stat != NULL_TREE)
711 gfc_add_modify (&se.pre, stat, build_int_cst (TREE_TYPE (stat), 0));
713 if (lock_acquired != NULL_TREE)
714 gfc_add_modify (&se.pre, lock_acquired,
715 fold_convert (TREE_TYPE (lock_acquired),
716 boolean_true_node));
718 return gfc_finish_block (&se.pre);
722 tree
723 gfc_trans_sync (gfc_code *code, gfc_exec_op type)
725 gfc_se se, argse;
726 tree tmp;
727 tree images = NULL_TREE, stat = NULL_TREE,
728 errmsg = NULL_TREE, errmsglen = NULL_TREE;
730 /* Short cut: For single images without bound checking or without STAT=,
731 return early. (ERRMSG= is always untouched for -fcoarray=single.) */
732 if (!code->expr2 && !(gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
733 && gfc_option.coarray != GFC_FCOARRAY_LIB)
734 return NULL_TREE;
736 gfc_init_se (&se, NULL);
737 gfc_start_block (&se.pre);
739 if (code->expr1 && code->expr1->rank == 0)
741 gfc_init_se (&argse, NULL);
742 gfc_conv_expr_val (&argse, code->expr1);
743 images = argse.expr;
746 if (code->expr2)
748 gcc_assert (code->expr2->expr_type == EXPR_VARIABLE);
749 gfc_init_se (&argse, NULL);
750 gfc_conv_expr_val (&argse, code->expr2);
751 stat = argse.expr;
753 else
754 stat = null_pointer_node;
756 if (code->expr3 && gfc_option.coarray == GFC_FCOARRAY_LIB
757 && type != EXEC_SYNC_MEMORY)
759 gcc_assert (code->expr3->expr_type == EXPR_VARIABLE);
760 gfc_init_se (&argse, NULL);
761 gfc_conv_expr (&argse, code->expr3);
762 gfc_conv_string_parameter (&argse);
763 errmsg = gfc_build_addr_expr (NULL, argse.expr);
764 errmsglen = argse.string_length;
766 else if (gfc_option.coarray == GFC_FCOARRAY_LIB && type != EXEC_SYNC_MEMORY)
768 errmsg = null_pointer_node;
769 errmsglen = build_int_cst (integer_type_node, 0);
772 /* Check SYNC IMAGES(imageset) for valid image index.
773 FIXME: Add a check for image-set arrays. */
774 if (code->expr1 && (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
775 && code->expr1->rank == 0)
777 tree cond;
778 if (gfc_option.coarray != GFC_FCOARRAY_LIB)
779 cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
780 images, build_int_cst (TREE_TYPE (images), 1));
781 else
783 tree cond2;
784 cond = fold_build2_loc (input_location, GE_EXPR, boolean_type_node,
785 images, gfort_gvar_caf_num_images);
786 cond2 = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
787 images,
788 build_int_cst (TREE_TYPE (images), 1));
789 cond = fold_build2_loc (input_location, TRUTH_AND_EXPR,
790 boolean_type_node, cond, cond2);
792 gfc_trans_runtime_check (true, false, cond, &se.pre,
793 &code->expr1->where, "Invalid image number "
794 "%d in SYNC IMAGES",
795 fold_convert (integer_type_node, se.expr));
798 /* Per F2008, 8.5.1, a SYNC MEMORY is implied by calling the
799 image control statements SYNC IMAGES and SYNC ALL. */
800 if (gfc_option.coarray == GFC_FCOARRAY_LIB)
802 tmp = builtin_decl_explicit (BUILT_IN_SYNC_SYNCHRONIZE);
803 tmp = build_call_expr_loc (input_location, tmp, 0);
804 gfc_add_expr_to_block (&se.pre, tmp);
807 if (gfc_option.coarray != GFC_FCOARRAY_LIB || type == EXEC_SYNC_MEMORY)
809 /* Set STAT to zero. */
810 if (code->expr2)
811 gfc_add_modify (&se.pre, stat, build_int_cst (TREE_TYPE (stat), 0));
813 else if (type == EXEC_SYNC_ALL)
815 /* SYNC ALL => stat == null_pointer_node
816 SYNC ALL(stat=s) => stat has an integer type
818 If "stat" has the wrong integer type, use a temp variable of
819 the right type and later cast the result back into "stat". */
820 if (stat == null_pointer_node || TREE_TYPE (stat) == integer_type_node)
822 if (TREE_TYPE (stat) == integer_type_node)
823 stat = gfc_build_addr_expr (NULL, stat);
825 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sync_all,
826 3, stat, errmsg, errmsglen);
827 gfc_add_expr_to_block (&se.pre, tmp);
829 else
831 tree tmp_stat = gfc_create_var (integer_type_node, "stat");
833 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sync_all,
834 3, gfc_build_addr_expr (NULL, tmp_stat),
835 errmsg, errmsglen);
836 gfc_add_expr_to_block (&se.pre, tmp);
838 gfc_add_modify (&se.pre, stat,
839 fold_convert (TREE_TYPE (stat), tmp_stat));
842 else
844 tree len;
846 gcc_assert (type == EXEC_SYNC_IMAGES);
848 if (!code->expr1)
850 len = build_int_cst (integer_type_node, -1);
851 images = null_pointer_node;
853 else if (code->expr1->rank == 0)
855 len = build_int_cst (integer_type_node, 1);
856 images = gfc_build_addr_expr (NULL_TREE, images);
858 else
860 /* FIXME. */
861 if (code->expr1->ts.kind != gfc_c_int_kind)
862 gfc_fatal_error ("Sorry, only support for integer kind %d "
863 "implemented for image-set at %L",
864 gfc_c_int_kind, &code->expr1->where);
866 gfc_conv_array_parameter (&se, code->expr1,
867 gfc_walk_expr (code->expr1), true, NULL,
868 NULL, &len);
869 images = se.expr;
871 tmp = gfc_typenode_for_spec (&code->expr1->ts);
872 if (GFC_ARRAY_TYPE_P (tmp) || GFC_DESCRIPTOR_TYPE_P (tmp))
873 tmp = gfc_get_element_type (tmp);
875 len = fold_build2_loc (input_location, TRUNC_DIV_EXPR,
876 TREE_TYPE (len), len,
877 fold_convert (TREE_TYPE (len),
878 TYPE_SIZE_UNIT (tmp)));
879 len = fold_convert (integer_type_node, len);
882 /* SYNC IMAGES(imgs) => stat == null_pointer_node
883 SYNC IMAGES(imgs,stat=s) => stat has an integer type
885 If "stat" has the wrong integer type, use a temp variable of
886 the right type and later cast the result back into "stat". */
887 if (stat == null_pointer_node || TREE_TYPE (stat) == integer_type_node)
889 if (TREE_TYPE (stat) == integer_type_node)
890 stat = gfc_build_addr_expr (NULL, stat);
892 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sync_images,
893 5, fold_convert (integer_type_node, len),
894 images, stat, errmsg, errmsglen);
895 gfc_add_expr_to_block (&se.pre, tmp);
897 else
899 tree tmp_stat = gfc_create_var (integer_type_node, "stat");
901 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_sync_images,
902 5, fold_convert (integer_type_node, len),
903 images, gfc_build_addr_expr (NULL, tmp_stat),
904 errmsg, errmsglen);
905 gfc_add_expr_to_block (&se.pre, tmp);
907 gfc_add_modify (&se.pre, stat,
908 fold_convert (TREE_TYPE (stat), tmp_stat));
912 return gfc_finish_block (&se.pre);
916 /* Generate GENERIC for the IF construct. This function also deals with
917 the simple IF statement, because the front end translates the IF
918 statement into an IF construct.
920 We translate:
922 IF (cond) THEN
923 then_clause
924 ELSEIF (cond2)
925 elseif_clause
926 ELSE
927 else_clause
928 ENDIF
930 into:
932 pre_cond_s;
933 if (cond_s)
935 then_clause;
937 else
939 pre_cond_s
940 if (cond_s)
942 elseif_clause
944 else
946 else_clause;
950 where COND_S is the simplified version of the predicate. PRE_COND_S
951 are the pre side-effects produced by the translation of the
952 conditional.
953 We need to build the chain recursively otherwise we run into
954 problems with folding incomplete statements. */
956 static tree
957 gfc_trans_if_1 (gfc_code * code)
959 gfc_se if_se;
960 tree stmt, elsestmt;
961 locus saved_loc;
962 location_t loc;
964 /* Check for an unconditional ELSE clause. */
965 if (!code->expr1)
966 return gfc_trans_code (code->next);
968 /* Initialize a statement builder for each block. Puts in NULL_TREEs. */
969 gfc_init_se (&if_se, NULL);
970 gfc_start_block (&if_se.pre);
972 /* Calculate the IF condition expression. */
973 if (code->expr1->where.lb)
975 gfc_save_backend_locus (&saved_loc);
976 gfc_set_backend_locus (&code->expr1->where);
979 gfc_conv_expr_val (&if_se, code->expr1);
981 if (code->expr1->where.lb)
982 gfc_restore_backend_locus (&saved_loc);
984 /* Translate the THEN clause. */
985 stmt = gfc_trans_code (code->next);
987 /* Translate the ELSE clause. */
988 if (code->block)
989 elsestmt = gfc_trans_if_1 (code->block);
990 else
991 elsestmt = build_empty_stmt (input_location);
993 /* Build the condition expression and add it to the condition block. */
994 loc = code->expr1->where.lb ? code->expr1->where.lb->location : input_location;
995 stmt = fold_build3_loc (loc, COND_EXPR, void_type_node, if_se.expr, stmt,
996 elsestmt);
998 gfc_add_expr_to_block (&if_se.pre, stmt);
1000 /* Finish off this statement. */
1001 return gfc_finish_block (&if_se.pre);
1004 tree
1005 gfc_trans_if (gfc_code * code)
1007 stmtblock_t body;
1008 tree exit_label;
1010 /* Create exit label so it is available for trans'ing the body code. */
1011 exit_label = gfc_build_label_decl (NULL_TREE);
1012 code->exit_label = exit_label;
1014 /* Translate the actual code in code->block. */
1015 gfc_init_block (&body);
1016 gfc_add_expr_to_block (&body, gfc_trans_if_1 (code->block));
1018 /* Add exit label. */
1019 gfc_add_expr_to_block (&body, build1_v (LABEL_EXPR, exit_label));
1021 return gfc_finish_block (&body);
1025 /* Translate an arithmetic IF expression.
1027 IF (cond) label1, label2, label3 translates to
1029 if (cond <= 0)
1031 if (cond < 0)
1032 goto label1;
1033 else // cond == 0
1034 goto label2;
1036 else // cond > 0
1037 goto label3;
1039 An optimized version can be generated in case of equal labels.
1040 E.g., if label1 is equal to label2, we can translate it to
1042 if (cond <= 0)
1043 goto label1;
1044 else
1045 goto label3;
1048 tree
1049 gfc_trans_arithmetic_if (gfc_code * code)
1051 gfc_se se;
1052 tree tmp;
1053 tree branch1;
1054 tree branch2;
1055 tree zero;
1057 /* Start a new block. */
1058 gfc_init_se (&se, NULL);
1059 gfc_start_block (&se.pre);
1061 /* Pre-evaluate COND. */
1062 gfc_conv_expr_val (&se, code->expr1);
1063 se.expr = gfc_evaluate_now (se.expr, &se.pre);
1065 /* Build something to compare with. */
1066 zero = gfc_build_const (TREE_TYPE (se.expr), integer_zero_node);
1068 if (code->label1->value != code->label2->value)
1070 /* If (cond < 0) take branch1 else take branch2.
1071 First build jumps to the COND .LT. 0 and the COND .EQ. 0 cases. */
1072 branch1 = build1_v (GOTO_EXPR, gfc_get_label_decl (code->label1));
1073 branch2 = build1_v (GOTO_EXPR, gfc_get_label_decl (code->label2));
1075 if (code->label1->value != code->label3->value)
1076 tmp = fold_build2_loc (input_location, LT_EXPR, boolean_type_node,
1077 se.expr, zero);
1078 else
1079 tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
1080 se.expr, zero);
1082 branch1 = fold_build3_loc (input_location, COND_EXPR, void_type_node,
1083 tmp, branch1, branch2);
1085 else
1086 branch1 = build1_v (GOTO_EXPR, gfc_get_label_decl (code->label1));
1088 if (code->label1->value != code->label3->value
1089 && code->label2->value != code->label3->value)
1091 /* if (cond <= 0) take branch1 else take branch2. */
1092 branch2 = build1_v (GOTO_EXPR, gfc_get_label_decl (code->label3));
1093 tmp = fold_build2_loc (input_location, LE_EXPR, boolean_type_node,
1094 se.expr, zero);
1095 branch1 = fold_build3_loc (input_location, COND_EXPR, void_type_node,
1096 tmp, branch1, branch2);
1099 /* Append the COND_EXPR to the evaluation of COND, and return. */
1100 gfc_add_expr_to_block (&se.pre, branch1);
1101 return gfc_finish_block (&se.pre);
1105 /* Translate a CRITICAL block. */
1106 tree
1107 gfc_trans_critical (gfc_code *code)
1109 stmtblock_t block;
1110 tree tmp;
1112 gfc_start_block (&block);
1114 if (gfc_option.coarray == GFC_FCOARRAY_LIB)
1116 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_critical, 0);
1117 gfc_add_expr_to_block (&block, tmp);
1120 tmp = gfc_trans_code (code->block->next);
1121 gfc_add_expr_to_block (&block, tmp);
1123 if (gfc_option.coarray == GFC_FCOARRAY_LIB)
1125 tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_end_critical,
1127 gfc_add_expr_to_block (&block, tmp);
1131 return gfc_finish_block (&block);
1135 /* Do proper initialization for ASSOCIATE names. */
1137 static void
1138 trans_associate_var (gfc_symbol *sym, gfc_wrapped_block *block)
1140 gfc_expr *e;
1141 tree tmp;
1142 bool class_target;
1143 tree desc;
1144 tree offset;
1145 tree dim;
1146 int n;
1148 gcc_assert (sym->assoc);
1149 e = sym->assoc->target;
1151 class_target = (e->expr_type == EXPR_VARIABLE)
1152 && (gfc_is_class_scalar_expr (e)
1153 || gfc_is_class_array_ref (e, NULL));
1155 /* Do a `pointer assignment' with updated descriptor (or assign descriptor
1156 to array temporary) for arrays with either unknown shape or if associating
1157 to a variable. */
1158 if (sym->attr.dimension && !class_target
1159 && (sym->as->type == AS_DEFERRED || sym->assoc->variable))
1161 gfc_se se;
1162 gfc_ss *ss;
1163 tree desc;
1165 desc = sym->backend_decl;
1167 /* If association is to an expression, evaluate it and create temporary.
1168 Otherwise, get descriptor of target for pointer assignment. */
1169 gfc_init_se (&se, NULL);
1170 ss = gfc_walk_expr (e);
1171 if (sym->assoc->variable)
1173 se.direct_byref = 1;
1174 se.expr = desc;
1176 gfc_conv_expr_descriptor (&se, e, ss);
1178 /* If we didn't already do the pointer assignment, set associate-name
1179 descriptor to the one generated for the temporary. */
1180 if (!sym->assoc->variable)
1182 int dim;
1184 gfc_add_modify (&se.pre, desc, se.expr);
1186 /* The generated descriptor has lower bound zero (as array
1187 temporary), shift bounds so we get lower bounds of 1. */
1188 for (dim = 0; dim < e->rank; ++dim)
1189 gfc_conv_shift_descriptor_lbound (&se.pre, desc,
1190 dim, gfc_index_one_node);
1193 /* Done, register stuff as init / cleanup code. */
1194 gfc_add_init_cleanup (block, gfc_finish_block (&se.pre),
1195 gfc_finish_block (&se.post));
1198 /* Derived type temporaries, arising from TYPE IS, just need the
1199 descriptor of class arrays to be assigned directly. */
1200 else if (class_target && sym->ts.type == BT_DERIVED && sym->attr.dimension)
1202 gfc_se se;
1204 gfc_init_se (&se, NULL);
1205 se.descriptor_only = 1;
1206 gfc_conv_expr (&se, e);
1208 gcc_assert (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (se.expr)));
1209 gcc_assert (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (sym->backend_decl)));
1211 gfc_add_modify (&se.pre, sym->backend_decl, se.expr);
1213 gfc_add_init_cleanup (block, gfc_finish_block( &se.pre),
1214 gfc_finish_block (&se.post));
1217 /* Do a scalar pointer assignment; this is for scalar variable targets. */
1218 else if (gfc_is_associate_pointer (sym))
1220 gfc_se se;
1222 gcc_assert (!sym->attr.dimension);
1224 gfc_init_se (&se, NULL);
1226 /* Class associate-names come this way because they are
1227 unconditionally associate pointers and the symbol is scalar. */
1228 if (sym->ts.type == BT_CLASS && CLASS_DATA (sym)->attr.dimension)
1230 /* For a class array we need a descriptor for the selector. */
1231 gfc_conv_expr_descriptor (&se, e, gfc_walk_expr (e));
1233 /* Obtain a temporary class container for the result. */
1234 gfc_conv_class_to_class (&se, e, sym->ts, false);
1235 se.expr = build_fold_indirect_ref_loc (input_location, se.expr);
1237 /* Set the offset. */
1238 desc = gfc_class_data_get (se.expr);
1239 offset = gfc_index_zero_node;
1240 for (n = 0; n < e->rank; n++)
1242 dim = gfc_rank_cst[n];
1243 tmp = fold_build2_loc (input_location, MULT_EXPR,
1244 gfc_array_index_type,
1245 gfc_conv_descriptor_stride_get (desc, dim),
1246 gfc_conv_descriptor_lbound_get (desc, dim));
1247 offset = fold_build2_loc (input_location, MINUS_EXPR,
1248 gfc_array_index_type,
1249 offset, tmp);
1251 gfc_conv_descriptor_offset_set (&se.pre, desc, offset);
1253 else if (sym->ts.type == BT_CLASS && e->ts.type == BT_CLASS
1254 && CLASS_DATA (e)->attr.dimension)
1256 /* This is bound to be a class array element. */
1257 gfc_conv_expr_reference (&se, e);
1258 /* Get the _vptr component of the class object. */
1259 tmp = gfc_get_vptr_from_expr (se.expr);
1260 /* Obtain a temporary class container for the result. */
1261 gfc_conv_derived_to_class (&se, e, sym->ts, tmp);
1262 se.expr = build_fold_indirect_ref_loc (input_location, se.expr);
1264 else
1265 gfc_conv_expr (&se, e);
1267 tmp = TREE_TYPE (sym->backend_decl);
1268 tmp = gfc_build_addr_expr (tmp, se.expr);
1269 gfc_add_modify (&se.pre, sym->backend_decl, tmp);
1271 gfc_add_init_cleanup (block, gfc_finish_block( &se.pre),
1272 gfc_finish_block (&se.post));
1275 /* Do a simple assignment. This is for scalar expressions, where we
1276 can simply use expression assignment. */
1277 else
1279 gfc_expr *lhs;
1281 lhs = gfc_lval_expr_from_sym (sym);
1282 tmp = gfc_trans_assignment (lhs, e, false, true);
1283 gfc_add_init_cleanup (block, tmp, NULL_TREE);
1288 /* Translate a BLOCK construct. This is basically what we would do for a
1289 procedure body. */
1291 tree
1292 gfc_trans_block_construct (gfc_code* code)
1294 gfc_namespace* ns;
1295 gfc_symbol* sym;
1296 gfc_wrapped_block block;
1297 tree exit_label;
1298 stmtblock_t body;
1299 gfc_association_list *ass;
1301 ns = code->ext.block.ns;
1302 gcc_assert (ns);
1303 sym = ns->proc_name;
1304 gcc_assert (sym);
1306 /* Process local variables. */
1307 gcc_assert (!sym->tlink);
1308 sym->tlink = sym;
1309 gfc_process_block_locals (ns);
1311 /* Generate code including exit-label. */
1312 gfc_init_block (&body);
1313 exit_label = gfc_build_label_decl (NULL_TREE);
1314 code->exit_label = exit_label;
1315 gfc_add_expr_to_block (&body, gfc_trans_code (ns->code));
1316 gfc_add_expr_to_block (&body, build1_v (LABEL_EXPR, exit_label));
1318 /* Finish everything. */
1319 gfc_start_wrapped_block (&block, gfc_finish_block (&body));
1320 gfc_trans_deferred_vars (sym, &block);
1321 for (ass = code->ext.block.assoc; ass; ass = ass->next)
1322 trans_associate_var (ass->st->n.sym, &block);
1324 return gfc_finish_wrapped_block (&block);
1328 /* Translate the simple DO construct. This is where the loop variable has
1329 integer type and step +-1. We can't use this in the general case
1330 because integer overflow and floating point errors could give incorrect
1331 results.
1332 We translate a do loop from:
1334 DO dovar = from, to, step
1335 body
1336 END DO
1340 [Evaluate loop bounds and step]
1341 dovar = from;
1342 if ((step > 0) ? (dovar <= to) : (dovar => to))
1344 for (;;)
1346 body;
1347 cycle_label:
1348 cond = (dovar == to);
1349 dovar += step;
1350 if (cond) goto end_label;
1353 end_label:
1355 This helps the optimizers by avoiding the extra induction variable
1356 used in the general case. */
1358 static tree
1359 gfc_trans_simple_do (gfc_code * code, stmtblock_t *pblock, tree dovar,
1360 tree from, tree to, tree step, tree exit_cond)
1362 stmtblock_t body;
1363 tree type;
1364 tree cond;
1365 tree tmp;
1366 tree saved_dovar = NULL;
1367 tree cycle_label;
1368 tree exit_label;
1369 location_t loc;
1371 type = TREE_TYPE (dovar);
1373 loc = code->ext.iterator->start->where.lb->location;
1375 /* Initialize the DO variable: dovar = from. */
1376 gfc_add_modify_loc (loc, pblock, dovar,
1377 fold_convert (TREE_TYPE(dovar), from));
1379 /* Save value for do-tinkering checking. */
1380 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
1382 saved_dovar = gfc_create_var (type, ".saved_dovar");
1383 gfc_add_modify_loc (loc, pblock, saved_dovar, dovar);
1386 /* Cycle and exit statements are implemented with gotos. */
1387 cycle_label = gfc_build_label_decl (NULL_TREE);
1388 exit_label = gfc_build_label_decl (NULL_TREE);
1390 /* Put the labels where they can be found later. See gfc_trans_do(). */
1391 code->cycle_label = cycle_label;
1392 code->exit_label = exit_label;
1394 /* Loop body. */
1395 gfc_start_block (&body);
1397 /* Main loop body. */
1398 tmp = gfc_trans_code_cond (code->block->next, exit_cond);
1399 gfc_add_expr_to_block (&body, tmp);
1401 /* Label for cycle statements (if needed). */
1402 if (TREE_USED (cycle_label))
1404 tmp = build1_v (LABEL_EXPR, cycle_label);
1405 gfc_add_expr_to_block (&body, tmp);
1408 /* Check whether someone has modified the loop variable. */
1409 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
1411 tmp = fold_build2_loc (loc, NE_EXPR, boolean_type_node,
1412 dovar, saved_dovar);
1413 gfc_trans_runtime_check (true, false, tmp, &body, &code->loc,
1414 "Loop variable has been modified");
1417 /* Exit the loop if there is an I/O result condition or error. */
1418 if (exit_cond)
1420 tmp = build1_v (GOTO_EXPR, exit_label);
1421 tmp = fold_build3_loc (loc, COND_EXPR, void_type_node,
1422 exit_cond, tmp,
1423 build_empty_stmt (loc));
1424 gfc_add_expr_to_block (&body, tmp);
1427 /* Evaluate the loop condition. */
1428 cond = fold_build2_loc (loc, EQ_EXPR, boolean_type_node, dovar,
1429 to);
1430 cond = gfc_evaluate_now_loc (loc, cond, &body);
1432 /* Increment the loop variable. */
1433 tmp = fold_build2_loc (loc, PLUS_EXPR, type, dovar, step);
1434 gfc_add_modify_loc (loc, &body, dovar, tmp);
1436 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
1437 gfc_add_modify_loc (loc, &body, saved_dovar, dovar);
1439 /* The loop exit. */
1440 tmp = fold_build1_loc (loc, GOTO_EXPR, void_type_node, exit_label);
1441 TREE_USED (exit_label) = 1;
1442 tmp = fold_build3_loc (loc, COND_EXPR, void_type_node,
1443 cond, tmp, build_empty_stmt (loc));
1444 gfc_add_expr_to_block (&body, tmp);
1446 /* Finish the loop body. */
1447 tmp = gfc_finish_block (&body);
1448 tmp = fold_build1_loc (loc, LOOP_EXPR, void_type_node, tmp);
1450 /* Only execute the loop if the number of iterations is positive. */
1451 if (tree_int_cst_sgn (step) > 0)
1452 cond = fold_build2_loc (loc, LE_EXPR, boolean_type_node, dovar,
1453 to);
1454 else
1455 cond = fold_build2_loc (loc, GE_EXPR, boolean_type_node, dovar,
1456 to);
1457 tmp = fold_build3_loc (loc, COND_EXPR, void_type_node, cond, tmp,
1458 build_empty_stmt (loc));
1459 gfc_add_expr_to_block (pblock, tmp);
1461 /* Add the exit label. */
1462 tmp = build1_v (LABEL_EXPR, exit_label);
1463 gfc_add_expr_to_block (pblock, tmp);
1465 return gfc_finish_block (pblock);
1468 /* Translate the DO construct. This obviously is one of the most
1469 important ones to get right with any compiler, but especially
1470 so for Fortran.
1472 We special case some loop forms as described in gfc_trans_simple_do.
1473 For other cases we implement them with a separate loop count,
1474 as described in the standard.
1476 We translate a do loop from:
1478 DO dovar = from, to, step
1479 body
1480 END DO
1484 [evaluate loop bounds and step]
1485 empty = (step > 0 ? to < from : to > from);
1486 countm1 = (to - from) / step;
1487 dovar = from;
1488 if (empty) goto exit_label;
1489 for (;;)
1491 body;
1492 cycle_label:
1493 dovar += step
1494 if (countm1 ==0) goto exit_label;
1495 countm1--;
1497 exit_label:
1499 countm1 is an unsigned integer. It is equal to the loop count minus one,
1500 because the loop count itself can overflow. */
1502 tree
1503 gfc_trans_do (gfc_code * code, tree exit_cond)
1505 gfc_se se;
1506 tree dovar;
1507 tree saved_dovar = NULL;
1508 tree from;
1509 tree to;
1510 tree step;
1511 tree countm1;
1512 tree type;
1513 tree utype;
1514 tree cond;
1515 tree cycle_label;
1516 tree exit_label;
1517 tree tmp;
1518 tree pos_step;
1519 stmtblock_t block;
1520 stmtblock_t body;
1521 location_t loc;
1523 gfc_start_block (&block);
1525 loc = code->ext.iterator->start->where.lb->location;
1527 /* Evaluate all the expressions in the iterator. */
1528 gfc_init_se (&se, NULL);
1529 gfc_conv_expr_lhs (&se, code->ext.iterator->var);
1530 gfc_add_block_to_block (&block, &se.pre);
1531 dovar = se.expr;
1532 type = TREE_TYPE (dovar);
1534 gfc_init_se (&se, NULL);
1535 gfc_conv_expr_val (&se, code->ext.iterator->start);
1536 gfc_add_block_to_block (&block, &se.pre);
1537 from = gfc_evaluate_now (se.expr, &block);
1539 gfc_init_se (&se, NULL);
1540 gfc_conv_expr_val (&se, code->ext.iterator->end);
1541 gfc_add_block_to_block (&block, &se.pre);
1542 to = gfc_evaluate_now (se.expr, &block);
1544 gfc_init_se (&se, NULL);
1545 gfc_conv_expr_val (&se, code->ext.iterator->step);
1546 gfc_add_block_to_block (&block, &se.pre);
1547 step = gfc_evaluate_now (se.expr, &block);
1549 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
1551 tmp = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, step,
1552 build_zero_cst (type));
1553 gfc_trans_runtime_check (true, false, tmp, &block, &code->loc,
1554 "DO step value is zero");
1557 /* Special case simple loops. */
1558 if (TREE_CODE (type) == INTEGER_TYPE
1559 && (integer_onep (step)
1560 || tree_int_cst_equal (step, integer_minus_one_node)))
1561 return gfc_trans_simple_do (code, &block, dovar, from, to, step, exit_cond);
1563 pos_step = fold_build2_loc (loc, GT_EXPR, boolean_type_node, step,
1564 build_zero_cst (type));
1566 if (TREE_CODE (type) == INTEGER_TYPE)
1567 utype = unsigned_type_for (type);
1568 else
1569 utype = unsigned_type_for (gfc_array_index_type);
1570 countm1 = gfc_create_var (utype, "countm1");
1572 /* Cycle and exit statements are implemented with gotos. */
1573 cycle_label = gfc_build_label_decl (NULL_TREE);
1574 exit_label = gfc_build_label_decl (NULL_TREE);
1575 TREE_USED (exit_label) = 1;
1577 /* Put these labels where they can be found later. */
1578 code->cycle_label = cycle_label;
1579 code->exit_label = exit_label;
1581 /* Initialize the DO variable: dovar = from. */
1582 gfc_add_modify (&block, dovar, from);
1584 /* Save value for do-tinkering checking. */
1585 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
1587 saved_dovar = gfc_create_var (type, ".saved_dovar");
1588 gfc_add_modify_loc (loc, &block, saved_dovar, dovar);
1591 /* Initialize loop count and jump to exit label if the loop is empty.
1592 This code is executed before we enter the loop body. We generate:
1593 step_sign = sign(1,step);
1594 if (step > 0)
1596 if (to < from)
1597 goto exit_label;
1599 else
1601 if (to > from)
1602 goto exit_label;
1604 countm1 = (to*step_sign - from*step_sign) / (step*step_sign);
1608 if (TREE_CODE (type) == INTEGER_TYPE)
1610 tree pos, neg, step_sign, to2, from2, step2;
1612 /* Calculate SIGN (1,step), as (step < 0 ? -1 : 1) */
1614 tmp = fold_build2_loc (loc, LT_EXPR, boolean_type_node, step,
1615 build_int_cst (TREE_TYPE (step), 0));
1616 step_sign = fold_build3_loc (loc, COND_EXPR, type, tmp,
1617 build_int_cst (type, -1),
1618 build_int_cst (type, 1));
1620 tmp = fold_build2_loc (loc, LT_EXPR, boolean_type_node, to, from);
1621 pos = fold_build3_loc (loc, COND_EXPR, void_type_node, tmp,
1622 fold_build1_loc (loc, GOTO_EXPR, void_type_node,
1623 exit_label),
1624 build_empty_stmt (loc));
1626 tmp = fold_build2_loc (loc, GT_EXPR, boolean_type_node, to,
1627 from);
1628 neg = fold_build3_loc (loc, COND_EXPR, void_type_node, tmp,
1629 fold_build1_loc (loc, GOTO_EXPR, void_type_node,
1630 exit_label),
1631 build_empty_stmt (loc));
1632 tmp = fold_build3_loc (loc, COND_EXPR, void_type_node,
1633 pos_step, pos, neg);
1635 gfc_add_expr_to_block (&block, tmp);
1637 /* Calculate the loop count. to-from can overflow, so
1638 we cast to unsigned. */
1640 to2 = fold_build2_loc (loc, MULT_EXPR, type, step_sign, to);
1641 from2 = fold_build2_loc (loc, MULT_EXPR, type, step_sign, from);
1642 step2 = fold_build2_loc (loc, MULT_EXPR, type, step_sign, step);
1643 step2 = fold_convert (utype, step2);
1644 tmp = fold_build2_loc (loc, MINUS_EXPR, type, to2, from2);
1645 tmp = fold_convert (utype, tmp);
1646 tmp = fold_build2_loc (loc, TRUNC_DIV_EXPR, utype, tmp, step2);
1647 tmp = fold_build2_loc (loc, MODIFY_EXPR, void_type_node, countm1, tmp);
1648 gfc_add_expr_to_block (&block, tmp);
1650 else
1652 /* TODO: We could use the same width as the real type.
1653 This would probably cause more problems that it solves
1654 when we implement "long double" types. */
1656 tmp = fold_build2_loc (loc, MINUS_EXPR, type, to, from);
1657 tmp = fold_build2_loc (loc, RDIV_EXPR, type, tmp, step);
1658 tmp = fold_build1_loc (loc, FIX_TRUNC_EXPR, utype, tmp);
1659 gfc_add_modify (&block, countm1, tmp);
1661 /* We need a special check for empty loops:
1662 empty = (step > 0 ? to < from : to > from); */
1663 tmp = fold_build3_loc (loc, COND_EXPR, boolean_type_node, pos_step,
1664 fold_build2_loc (loc, LT_EXPR,
1665 boolean_type_node, to, from),
1666 fold_build2_loc (loc, GT_EXPR,
1667 boolean_type_node, to, from));
1668 /* If the loop is empty, go directly to the exit label. */
1669 tmp = fold_build3_loc (loc, COND_EXPR, void_type_node, tmp,
1670 build1_v (GOTO_EXPR, exit_label),
1671 build_empty_stmt (input_location));
1672 gfc_add_expr_to_block (&block, tmp);
1675 /* Loop body. */
1676 gfc_start_block (&body);
1678 /* Main loop body. */
1679 tmp = gfc_trans_code_cond (code->block->next, exit_cond);
1680 gfc_add_expr_to_block (&body, tmp);
1682 /* Label for cycle statements (if needed). */
1683 if (TREE_USED (cycle_label))
1685 tmp = build1_v (LABEL_EXPR, cycle_label);
1686 gfc_add_expr_to_block (&body, tmp);
1689 /* Check whether someone has modified the loop variable. */
1690 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
1692 tmp = fold_build2_loc (loc, NE_EXPR, boolean_type_node, dovar,
1693 saved_dovar);
1694 gfc_trans_runtime_check (true, false, tmp, &body, &code->loc,
1695 "Loop variable has been modified");
1698 /* Exit the loop if there is an I/O result condition or error. */
1699 if (exit_cond)
1701 tmp = build1_v (GOTO_EXPR, exit_label);
1702 tmp = fold_build3_loc (loc, COND_EXPR, void_type_node,
1703 exit_cond, tmp,
1704 build_empty_stmt (input_location));
1705 gfc_add_expr_to_block (&body, tmp);
1708 /* Increment the loop variable. */
1709 tmp = fold_build2_loc (loc, PLUS_EXPR, type, dovar, step);
1710 gfc_add_modify_loc (loc, &body, dovar, tmp);
1712 if (gfc_option.rtcheck & GFC_RTCHECK_DO)
1713 gfc_add_modify_loc (loc, &body, saved_dovar, dovar);
1715 /* End with the loop condition. Loop until countm1 == 0. */
1716 cond = fold_build2_loc (loc, EQ_EXPR, boolean_type_node, countm1,
1717 build_int_cst (utype, 0));
1718 tmp = fold_build1_loc (loc, GOTO_EXPR, void_type_node, exit_label);
1719 tmp = fold_build3_loc (loc, COND_EXPR, void_type_node,
1720 cond, tmp, build_empty_stmt (loc));
1721 gfc_add_expr_to_block (&body, tmp);
1723 /* Decrement the loop count. */
1724 tmp = fold_build2_loc (loc, MINUS_EXPR, utype, countm1,
1725 build_int_cst (utype, 1));
1726 gfc_add_modify_loc (loc, &body, countm1, tmp);
1728 /* End of loop body. */
1729 tmp = gfc_finish_block (&body);
1731 /* The for loop itself. */
1732 tmp = fold_build1_loc (loc, LOOP_EXPR, void_type_node, tmp);
1733 gfc_add_expr_to_block (&block, tmp);
1735 /* Add the exit label. */
1736 tmp = build1_v (LABEL_EXPR, exit_label);
1737 gfc_add_expr_to_block (&block, tmp);
1739 return gfc_finish_block (&block);
1743 /* Translate the DO WHILE construct.
1745 We translate
1747 DO WHILE (cond)
1748 body
1749 END DO
1753 for ( ; ; )
1755 pre_cond;
1756 if (! cond) goto exit_label;
1757 body;
1758 cycle_label:
1760 exit_label:
1762 Because the evaluation of the exit condition `cond' may have side
1763 effects, we can't do much for empty loop bodies. The backend optimizers
1764 should be smart enough to eliminate any dead loops. */
1766 tree
1767 gfc_trans_do_while (gfc_code * code)
1769 gfc_se cond;
1770 tree tmp;
1771 tree cycle_label;
1772 tree exit_label;
1773 stmtblock_t block;
1775 /* Everything we build here is part of the loop body. */
1776 gfc_start_block (&block);
1778 /* Cycle and exit statements are implemented with gotos. */
1779 cycle_label = gfc_build_label_decl (NULL_TREE);
1780 exit_label = gfc_build_label_decl (NULL_TREE);
1782 /* Put the labels where they can be found later. See gfc_trans_do(). */
1783 code->cycle_label = cycle_label;
1784 code->exit_label = exit_label;
1786 /* Create a GIMPLE version of the exit condition. */
1787 gfc_init_se (&cond, NULL);
1788 gfc_conv_expr_val (&cond, code->expr1);
1789 gfc_add_block_to_block (&block, &cond.pre);
1790 cond.expr = fold_build1_loc (code->expr1->where.lb->location,
1791 TRUTH_NOT_EXPR, boolean_type_node, cond.expr);
1793 /* Build "IF (! cond) GOTO exit_label". */
1794 tmp = build1_v (GOTO_EXPR, exit_label);
1795 TREE_USED (exit_label) = 1;
1796 tmp = fold_build3_loc (code->expr1->where.lb->location, COND_EXPR,
1797 void_type_node, cond.expr, tmp,
1798 build_empty_stmt (code->expr1->where.lb->location));
1799 gfc_add_expr_to_block (&block, tmp);
1801 /* The main body of the loop. */
1802 tmp = gfc_trans_code (code->block->next);
1803 gfc_add_expr_to_block (&block, tmp);
1805 /* Label for cycle statements (if needed). */
1806 if (TREE_USED (cycle_label))
1808 tmp = build1_v (LABEL_EXPR, cycle_label);
1809 gfc_add_expr_to_block (&block, tmp);
1812 /* End of loop body. */
1813 tmp = gfc_finish_block (&block);
1815 gfc_init_block (&block);
1816 /* Build the loop. */
1817 tmp = fold_build1_loc (code->expr1->where.lb->location, LOOP_EXPR,
1818 void_type_node, tmp);
1819 gfc_add_expr_to_block (&block, tmp);
1821 /* Add the exit label. */
1822 tmp = build1_v (LABEL_EXPR, exit_label);
1823 gfc_add_expr_to_block (&block, tmp);
1825 return gfc_finish_block (&block);
1829 /* Translate the SELECT CASE construct for INTEGER case expressions,
1830 without killing all potential optimizations. The problem is that
1831 Fortran allows unbounded cases, but the back-end does not, so we
1832 need to intercept those before we enter the equivalent SWITCH_EXPR
1833 we can build.
1835 For example, we translate this,
1837 SELECT CASE (expr)
1838 CASE (:100,101,105:115)
1839 block_1
1840 CASE (190:199,200:)
1841 block_2
1842 CASE (300)
1843 block_3
1844 CASE DEFAULT
1845 block_4
1846 END SELECT
1848 to the GENERIC equivalent,
1850 switch (expr)
1852 case (minimum value for typeof(expr) ... 100:
1853 case 101:
1854 case 105 ... 114:
1855 block1:
1856 goto end_label;
1858 case 200 ... (maximum value for typeof(expr):
1859 case 190 ... 199:
1860 block2;
1861 goto end_label;
1863 case 300:
1864 block_3;
1865 goto end_label;
1867 default:
1868 block_4;
1869 goto end_label;
1872 end_label: */
1874 static tree
1875 gfc_trans_integer_select (gfc_code * code)
1877 gfc_code *c;
1878 gfc_case *cp;
1879 tree end_label;
1880 tree tmp;
1881 gfc_se se;
1882 stmtblock_t block;
1883 stmtblock_t body;
1885 gfc_start_block (&block);
1887 /* Calculate the switch expression. */
1888 gfc_init_se (&se, NULL);
1889 gfc_conv_expr_val (&se, code->expr1);
1890 gfc_add_block_to_block (&block, &se.pre);
1892 end_label = gfc_build_label_decl (NULL_TREE);
1894 gfc_init_block (&body);
1896 for (c = code->block; c; c = c->block)
1898 for (cp = c->ext.block.case_list; cp; cp = cp->next)
1900 tree low, high;
1901 tree label;
1903 /* Assume it's the default case. */
1904 low = high = NULL_TREE;
1906 if (cp->low)
1908 low = gfc_conv_mpz_to_tree (cp->low->value.integer,
1909 cp->low->ts.kind);
1911 /* If there's only a lower bound, set the high bound to the
1912 maximum value of the case expression. */
1913 if (!cp->high)
1914 high = TYPE_MAX_VALUE (TREE_TYPE (se.expr));
1917 if (cp->high)
1919 /* Three cases are possible here:
1921 1) There is no lower bound, e.g. CASE (:N).
1922 2) There is a lower bound .NE. high bound, that is
1923 a case range, e.g. CASE (N:M) where M>N (we make
1924 sure that M>N during type resolution).
1925 3) There is a lower bound, and it has the same value
1926 as the high bound, e.g. CASE (N:N). This is our
1927 internal representation of CASE(N).
1929 In the first and second case, we need to set a value for
1930 high. In the third case, we don't because the GCC middle
1931 end represents a single case value by just letting high be
1932 a NULL_TREE. We can't do that because we need to be able
1933 to represent unbounded cases. */
1935 if (!cp->low
1936 || (cp->low
1937 && mpz_cmp (cp->low->value.integer,
1938 cp->high->value.integer) != 0))
1939 high = gfc_conv_mpz_to_tree (cp->high->value.integer,
1940 cp->high->ts.kind);
1942 /* Unbounded case. */
1943 if (!cp->low)
1944 low = TYPE_MIN_VALUE (TREE_TYPE (se.expr));
1947 /* Build a label. */
1948 label = gfc_build_label_decl (NULL_TREE);
1950 /* Add this case label.
1951 Add parameter 'label', make it match GCC backend. */
1952 tmp = build_case_label (low, high, label);
1953 gfc_add_expr_to_block (&body, tmp);
1956 /* Add the statements for this case. */
1957 tmp = gfc_trans_code (c->next);
1958 gfc_add_expr_to_block (&body, tmp);
1960 /* Break to the end of the construct. */
1961 tmp = build1_v (GOTO_EXPR, end_label);
1962 gfc_add_expr_to_block (&body, tmp);
1965 tmp = gfc_finish_block (&body);
1966 tmp = fold_build3_loc (input_location, SWITCH_EXPR, NULL_TREE,
1967 se.expr, tmp, NULL_TREE);
1968 gfc_add_expr_to_block (&block, tmp);
1970 tmp = build1_v (LABEL_EXPR, end_label);
1971 gfc_add_expr_to_block (&block, tmp);
1973 return gfc_finish_block (&block);
1977 /* Translate the SELECT CASE construct for LOGICAL case expressions.
1979 There are only two cases possible here, even though the standard
1980 does allow three cases in a LOGICAL SELECT CASE construct: .TRUE.,
1981 .FALSE., and DEFAULT.
1983 We never generate more than two blocks here. Instead, we always
1984 try to eliminate the DEFAULT case. This way, we can translate this
1985 kind of SELECT construct to a simple
1987 if {} else {};
1989 expression in GENERIC. */
1991 static tree
1992 gfc_trans_logical_select (gfc_code * code)
1994 gfc_code *c;
1995 gfc_code *t, *f, *d;
1996 gfc_case *cp;
1997 gfc_se se;
1998 stmtblock_t block;
2000 /* Assume we don't have any cases at all. */
2001 t = f = d = NULL;
2003 /* Now see which ones we actually do have. We can have at most two
2004 cases in a single case list: one for .TRUE. and one for .FALSE.
2005 The default case is always separate. If the cases for .TRUE. and
2006 .FALSE. are in the same case list, the block for that case list
2007 always executed, and we don't generate code a COND_EXPR. */
2008 for (c = code->block; c; c = c->block)
2010 for (cp = c->ext.block.case_list; cp; cp = cp->next)
2012 if (cp->low)
2014 if (cp->low->value.logical == 0) /* .FALSE. */
2015 f = c;
2016 else /* if (cp->value.logical != 0), thus .TRUE. */
2017 t = c;
2019 else
2020 d = c;
2024 /* Start a new block. */
2025 gfc_start_block (&block);
2027 /* Calculate the switch expression. We always need to do this
2028 because it may have side effects. */
2029 gfc_init_se (&se, NULL);
2030 gfc_conv_expr_val (&se, code->expr1);
2031 gfc_add_block_to_block (&block, &se.pre);
2033 if (t == f && t != NULL)
2035 /* Cases for .TRUE. and .FALSE. are in the same block. Just
2036 translate the code for these cases, append it to the current
2037 block. */
2038 gfc_add_expr_to_block (&block, gfc_trans_code (t->next));
2040 else
2042 tree true_tree, false_tree, stmt;
2044 true_tree = build_empty_stmt (input_location);
2045 false_tree = build_empty_stmt (input_location);
2047 /* If we have a case for .TRUE. and for .FALSE., discard the default case.
2048 Otherwise, if .TRUE. or .FALSE. is missing and there is a default case,
2049 make the missing case the default case. */
2050 if (t != NULL && f != NULL)
2051 d = NULL;
2052 else if (d != NULL)
2054 if (t == NULL)
2055 t = d;
2056 else
2057 f = d;
2060 /* Translate the code for each of these blocks, and append it to
2061 the current block. */
2062 if (t != NULL)
2063 true_tree = gfc_trans_code (t->next);
2065 if (f != NULL)
2066 false_tree = gfc_trans_code (f->next);
2068 stmt = fold_build3_loc (input_location, COND_EXPR, void_type_node,
2069 se.expr, true_tree, false_tree);
2070 gfc_add_expr_to_block (&block, stmt);
2073 return gfc_finish_block (&block);
2077 /* The jump table types are stored in static variables to avoid
2078 constructing them from scratch every single time. */
2079 static GTY(()) tree select_struct[2];
2081 /* Translate the SELECT CASE construct for CHARACTER case expressions.
2082 Instead of generating compares and jumps, it is far simpler to
2083 generate a data structure describing the cases in order and call a
2084 library subroutine that locates the right case.
2085 This is particularly true because this is the only case where we
2086 might have to dispose of a temporary.
2087 The library subroutine returns a pointer to jump to or NULL if no
2088 branches are to be taken. */
2090 static tree
2091 gfc_trans_character_select (gfc_code *code)
2093 tree init, end_label, tmp, type, case_num, label, fndecl;
2094 stmtblock_t block, body;
2095 gfc_case *cp, *d;
2096 gfc_code *c;
2097 gfc_se se, expr1se;
2098 int n, k;
2099 VEC(constructor_elt,gc) *inits = NULL;
2101 tree pchartype = gfc_get_pchar_type (code->expr1->ts.kind);
2103 /* The jump table types are stored in static variables to avoid
2104 constructing them from scratch every single time. */
2105 static tree ss_string1[2], ss_string1_len[2];
2106 static tree ss_string2[2], ss_string2_len[2];
2107 static tree ss_target[2];
2109 cp = code->block->ext.block.case_list;
2110 while (cp->left != NULL)
2111 cp = cp->left;
2113 /* Generate the body */
2114 gfc_start_block (&block);
2115 gfc_init_se (&expr1se, NULL);
2116 gfc_conv_expr_reference (&expr1se, code->expr1);
2118 gfc_add_block_to_block (&block, &expr1se.pre);
2120 end_label = gfc_build_label_decl (NULL_TREE);
2122 gfc_init_block (&body);
2124 /* Attempt to optimize length 1 selects. */
2125 if (integer_onep (expr1se.string_length))
2127 for (d = cp; d; d = d->right)
2129 int i;
2130 if (d->low)
2132 gcc_assert (d->low->expr_type == EXPR_CONSTANT
2133 && d->low->ts.type == BT_CHARACTER);
2134 if (d->low->value.character.length > 1)
2136 for (i = 1; i < d->low->value.character.length; i++)
2137 if (d->low->value.character.string[i] != ' ')
2138 break;
2139 if (i != d->low->value.character.length)
2141 if (optimize && d->high && i == 1)
2143 gcc_assert (d->high->expr_type == EXPR_CONSTANT
2144 && d->high->ts.type == BT_CHARACTER);
2145 if (d->high->value.character.length > 1
2146 && (d->low->value.character.string[0]
2147 == d->high->value.character.string[0])
2148 && d->high->value.character.string[1] != ' '
2149 && ((d->low->value.character.string[1] < ' ')
2150 == (d->high->value.character.string[1]
2151 < ' ')))
2152 continue;
2154 break;
2158 if (d->high)
2160 gcc_assert (d->high->expr_type == EXPR_CONSTANT
2161 && d->high->ts.type == BT_CHARACTER);
2162 if (d->high->value.character.length > 1)
2164 for (i = 1; i < d->high->value.character.length; i++)
2165 if (d->high->value.character.string[i] != ' ')
2166 break;
2167 if (i != d->high->value.character.length)
2168 break;
2172 if (d == NULL)
2174 tree ctype = gfc_get_char_type (code->expr1->ts.kind);
2176 for (c = code->block; c; c = c->block)
2178 for (cp = c->ext.block.case_list; cp; cp = cp->next)
2180 tree low, high;
2181 tree label;
2182 gfc_char_t r;
2184 /* Assume it's the default case. */
2185 low = high = NULL_TREE;
2187 if (cp->low)
2189 /* CASE ('ab') or CASE ('ab':'az') will never match
2190 any length 1 character. */
2191 if (cp->low->value.character.length > 1
2192 && cp->low->value.character.string[1] != ' ')
2193 continue;
2195 if (cp->low->value.character.length > 0)
2196 r = cp->low->value.character.string[0];
2197 else
2198 r = ' ';
2199 low = build_int_cst (ctype, r);
2201 /* If there's only a lower bound, set the high bound
2202 to the maximum value of the case expression. */
2203 if (!cp->high)
2204 high = TYPE_MAX_VALUE (ctype);
2207 if (cp->high)
2209 if (!cp->low
2210 || (cp->low->value.character.string[0]
2211 != cp->high->value.character.string[0]))
2213 if (cp->high->value.character.length > 0)
2214 r = cp->high->value.character.string[0];
2215 else
2216 r = ' ';
2217 high = build_int_cst (ctype, r);
2220 /* Unbounded case. */
2221 if (!cp->low)
2222 low = TYPE_MIN_VALUE (ctype);
2225 /* Build a label. */
2226 label = gfc_build_label_decl (NULL_TREE);
2228 /* Add this case label.
2229 Add parameter 'label', make it match GCC backend. */
2230 tmp = build_case_label (low, high, label);
2231 gfc_add_expr_to_block (&body, tmp);
2234 /* Add the statements for this case. */
2235 tmp = gfc_trans_code (c->next);
2236 gfc_add_expr_to_block (&body, tmp);
2238 /* Break to the end of the construct. */
2239 tmp = build1_v (GOTO_EXPR, end_label);
2240 gfc_add_expr_to_block (&body, tmp);
2243 tmp = gfc_string_to_single_character (expr1se.string_length,
2244 expr1se.expr,
2245 code->expr1->ts.kind);
2246 case_num = gfc_create_var (ctype, "case_num");
2247 gfc_add_modify (&block, case_num, tmp);
2249 gfc_add_block_to_block (&block, &expr1se.post);
2251 tmp = gfc_finish_block (&body);
2252 tmp = fold_build3_loc (input_location, SWITCH_EXPR, NULL_TREE,
2253 case_num, tmp, NULL_TREE);
2254 gfc_add_expr_to_block (&block, tmp);
2256 tmp = build1_v (LABEL_EXPR, end_label);
2257 gfc_add_expr_to_block (&block, tmp);
2259 return gfc_finish_block (&block);
2263 if (code->expr1->ts.kind == 1)
2264 k = 0;
2265 else if (code->expr1->ts.kind == 4)
2266 k = 1;
2267 else
2268 gcc_unreachable ();
2270 if (select_struct[k] == NULL)
2272 tree *chain = NULL;
2273 select_struct[k] = make_node (RECORD_TYPE);
2275 if (code->expr1->ts.kind == 1)
2276 TYPE_NAME (select_struct[k]) = get_identifier ("_jump_struct_char1");
2277 else if (code->expr1->ts.kind == 4)
2278 TYPE_NAME (select_struct[k]) = get_identifier ("_jump_struct_char4");
2279 else
2280 gcc_unreachable ();
2282 #undef ADD_FIELD
2283 #define ADD_FIELD(NAME, TYPE) \
2284 ss_##NAME[k] = gfc_add_field_to_struct (select_struct[k], \
2285 get_identifier (stringize(NAME)), \
2286 TYPE, \
2287 &chain)
2289 ADD_FIELD (string1, pchartype);
2290 ADD_FIELD (string1_len, gfc_charlen_type_node);
2292 ADD_FIELD (string2, pchartype);
2293 ADD_FIELD (string2_len, gfc_charlen_type_node);
2295 ADD_FIELD (target, integer_type_node);
2296 #undef ADD_FIELD
2298 gfc_finish_type (select_struct[k]);
2301 n = 0;
2302 for (d = cp; d; d = d->right)
2303 d->n = n++;
2305 for (c = code->block; c; c = c->block)
2307 for (d = c->ext.block.case_list; d; d = d->next)
2309 label = gfc_build_label_decl (NULL_TREE);
2310 tmp = build_case_label ((d->low == NULL && d->high == NULL)
2311 ? NULL
2312 : build_int_cst (integer_type_node, d->n),
2313 NULL, label);
2314 gfc_add_expr_to_block (&body, tmp);
2317 tmp = gfc_trans_code (c->next);
2318 gfc_add_expr_to_block (&body, tmp);
2320 tmp = build1_v (GOTO_EXPR, end_label);
2321 gfc_add_expr_to_block (&body, tmp);
2324 /* Generate the structure describing the branches */
2325 for (d = cp; d; d = d->right)
2327 VEC(constructor_elt,gc) *node = NULL;
2329 gfc_init_se (&se, NULL);
2331 if (d->low == NULL)
2333 CONSTRUCTOR_APPEND_ELT (node, ss_string1[k], null_pointer_node);
2334 CONSTRUCTOR_APPEND_ELT (node, ss_string1_len[k], integer_zero_node);
2336 else
2338 gfc_conv_expr_reference (&se, d->low);
2340 CONSTRUCTOR_APPEND_ELT (node, ss_string1[k], se.expr);
2341 CONSTRUCTOR_APPEND_ELT (node, ss_string1_len[k], se.string_length);
2344 if (d->high == NULL)
2346 CONSTRUCTOR_APPEND_ELT (node, ss_string2[k], null_pointer_node);
2347 CONSTRUCTOR_APPEND_ELT (node, ss_string2_len[k], integer_zero_node);
2349 else
2351 gfc_init_se (&se, NULL);
2352 gfc_conv_expr_reference (&se, d->high);
2354 CONSTRUCTOR_APPEND_ELT (node, ss_string2[k], se.expr);
2355 CONSTRUCTOR_APPEND_ELT (node, ss_string2_len[k], se.string_length);
2358 CONSTRUCTOR_APPEND_ELT (node, ss_target[k],
2359 build_int_cst (integer_type_node, d->n));
2361 tmp = build_constructor (select_struct[k], node);
2362 CONSTRUCTOR_APPEND_ELT (inits, NULL_TREE, tmp);
2365 type = build_array_type (select_struct[k],
2366 build_index_type (size_int (n-1)));
2368 init = build_constructor (type, inits);
2369 TREE_CONSTANT (init) = 1;
2370 TREE_STATIC (init) = 1;
2371 /* Create a static variable to hold the jump table. */
2372 tmp = gfc_create_var (type, "jumptable");
2373 TREE_CONSTANT (tmp) = 1;
2374 TREE_STATIC (tmp) = 1;
2375 TREE_READONLY (tmp) = 1;
2376 DECL_INITIAL (tmp) = init;
2377 init = tmp;
2379 /* Build the library call */
2380 init = gfc_build_addr_expr (pvoid_type_node, init);
2382 if (code->expr1->ts.kind == 1)
2383 fndecl = gfor_fndecl_select_string;
2384 else if (code->expr1->ts.kind == 4)
2385 fndecl = gfor_fndecl_select_string_char4;
2386 else
2387 gcc_unreachable ();
2389 tmp = build_call_expr_loc (input_location,
2390 fndecl, 4, init,
2391 build_int_cst (gfc_charlen_type_node, n),
2392 expr1se.expr, expr1se.string_length);
2393 case_num = gfc_create_var (integer_type_node, "case_num");
2394 gfc_add_modify (&block, case_num, tmp);
2396 gfc_add_block_to_block (&block, &expr1se.post);
2398 tmp = gfc_finish_block (&body);
2399 tmp = fold_build3_loc (input_location, SWITCH_EXPR, NULL_TREE,
2400 case_num, tmp, NULL_TREE);
2401 gfc_add_expr_to_block (&block, tmp);
2403 tmp = build1_v (LABEL_EXPR, end_label);
2404 gfc_add_expr_to_block (&block, tmp);
2406 return gfc_finish_block (&block);
2410 /* Translate the three variants of the SELECT CASE construct.
2412 SELECT CASEs with INTEGER case expressions can be translated to an
2413 equivalent GENERIC switch statement, and for LOGICAL case
2414 expressions we build one or two if-else compares.
2416 SELECT CASEs with CHARACTER case expressions are a whole different
2417 story, because they don't exist in GENERIC. So we sort them and
2418 do a binary search at runtime.
2420 Fortran has no BREAK statement, and it does not allow jumps from
2421 one case block to another. That makes things a lot easier for
2422 the optimizers. */
2424 tree
2425 gfc_trans_select (gfc_code * code)
2427 stmtblock_t block;
2428 tree body;
2429 tree exit_label;
2431 gcc_assert (code && code->expr1);
2432 gfc_init_block (&block);
2434 /* Build the exit label and hang it in. */
2435 exit_label = gfc_build_label_decl (NULL_TREE);
2436 code->exit_label = exit_label;
2438 /* Empty SELECT constructs are legal. */
2439 if (code->block == NULL)
2440 body = build_empty_stmt (input_location);
2442 /* Select the correct translation function. */
2443 else
2444 switch (code->expr1->ts.type)
2446 case BT_LOGICAL:
2447 body = gfc_trans_logical_select (code);
2448 break;
2450 case BT_INTEGER:
2451 body = gfc_trans_integer_select (code);
2452 break;
2454 case BT_CHARACTER:
2455 body = gfc_trans_character_select (code);
2456 break;
2458 default:
2459 gfc_internal_error ("gfc_trans_select(): Bad type for case expr.");
2460 /* Not reached */
2463 /* Build everything together. */
2464 gfc_add_expr_to_block (&block, body);
2465 gfc_add_expr_to_block (&block, build1_v (LABEL_EXPR, exit_label));
2467 return gfc_finish_block (&block);
2471 /* Traversal function to substitute a replacement symtree if the symbol
2472 in the expression is the same as that passed. f == 2 signals that
2473 that variable itself is not to be checked - only the references.
2474 This group of functions is used when the variable expression in a
2475 FORALL assignment has internal references. For example:
2476 FORALL (i = 1:4) p(p(i)) = i
2477 The only recourse here is to store a copy of 'p' for the index
2478 expression. */
2480 static gfc_symtree *new_symtree;
2481 static gfc_symtree *old_symtree;
2483 static bool
2484 forall_replace (gfc_expr *expr, gfc_symbol *sym, int *f)
2486 if (expr->expr_type != EXPR_VARIABLE)
2487 return false;
2489 if (*f == 2)
2490 *f = 1;
2491 else if (expr->symtree->n.sym == sym)
2492 expr->symtree = new_symtree;
2494 return false;
2497 static void
2498 forall_replace_symtree (gfc_expr *e, gfc_symbol *sym, int f)
2500 gfc_traverse_expr (e, sym, forall_replace, f);
2503 static bool
2504 forall_restore (gfc_expr *expr,
2505 gfc_symbol *sym ATTRIBUTE_UNUSED,
2506 int *f ATTRIBUTE_UNUSED)
2508 if (expr->expr_type != EXPR_VARIABLE)
2509 return false;
2511 if (expr->symtree == new_symtree)
2512 expr->symtree = old_symtree;
2514 return false;
2517 static void
2518 forall_restore_symtree (gfc_expr *e)
2520 gfc_traverse_expr (e, NULL, forall_restore, 0);
2523 static void
2524 forall_make_variable_temp (gfc_code *c, stmtblock_t *pre, stmtblock_t *post)
2526 gfc_se tse;
2527 gfc_se rse;
2528 gfc_expr *e;
2529 gfc_symbol *new_sym;
2530 gfc_symbol *old_sym;
2531 gfc_symtree *root;
2532 tree tmp;
2534 /* Build a copy of the lvalue. */
2535 old_symtree = c->expr1->symtree;
2536 old_sym = old_symtree->n.sym;
2537 e = gfc_lval_expr_from_sym (old_sym);
2538 if (old_sym->attr.dimension)
2540 gfc_init_se (&tse, NULL);
2541 gfc_conv_subref_array_arg (&tse, e, 0, INTENT_IN, false);
2542 gfc_add_block_to_block (pre, &tse.pre);
2543 gfc_add_block_to_block (post, &tse.post);
2544 tse.expr = build_fold_indirect_ref_loc (input_location, tse.expr);
2546 if (e->ts.type != BT_CHARACTER)
2548 /* Use the variable offset for the temporary. */
2549 tmp = gfc_conv_array_offset (old_sym->backend_decl);
2550 gfc_conv_descriptor_offset_set (pre, tse.expr, tmp);
2553 else
2555 gfc_init_se (&tse, NULL);
2556 gfc_init_se (&rse, NULL);
2557 gfc_conv_expr (&rse, e);
2558 if (e->ts.type == BT_CHARACTER)
2560 tse.string_length = rse.string_length;
2561 tmp = gfc_get_character_type_len (gfc_default_character_kind,
2562 tse.string_length);
2563 tse.expr = gfc_conv_string_tmp (&tse, build_pointer_type (tmp),
2564 rse.string_length);
2565 gfc_add_block_to_block (pre, &tse.pre);
2566 gfc_add_block_to_block (post, &tse.post);
2568 else
2570 tmp = gfc_typenode_for_spec (&e->ts);
2571 tse.expr = gfc_create_var (tmp, "temp");
2574 tmp = gfc_trans_scalar_assign (&tse, &rse, e->ts, true,
2575 e->expr_type == EXPR_VARIABLE, true);
2576 gfc_add_expr_to_block (pre, tmp);
2578 gfc_free_expr (e);
2580 /* Create a new symbol to represent the lvalue. */
2581 new_sym = gfc_new_symbol (old_sym->name, NULL);
2582 new_sym->ts = old_sym->ts;
2583 new_sym->attr.referenced = 1;
2584 new_sym->attr.temporary = 1;
2585 new_sym->attr.dimension = old_sym->attr.dimension;
2586 new_sym->attr.flavor = old_sym->attr.flavor;
2588 /* Use the temporary as the backend_decl. */
2589 new_sym->backend_decl = tse.expr;
2591 /* Create a fake symtree for it. */
2592 root = NULL;
2593 new_symtree = gfc_new_symtree (&root, old_sym->name);
2594 new_symtree->n.sym = new_sym;
2595 gcc_assert (new_symtree == root);
2597 /* Go through the expression reference replacing the old_symtree
2598 with the new. */
2599 forall_replace_symtree (c->expr1, old_sym, 2);
2601 /* Now we have made this temporary, we might as well use it for
2602 the right hand side. */
2603 forall_replace_symtree (c->expr2, old_sym, 1);
2607 /* Handles dependencies in forall assignments. */
2608 static int
2609 check_forall_dependencies (gfc_code *c, stmtblock_t *pre, stmtblock_t *post)
2611 gfc_ref *lref;
2612 gfc_ref *rref;
2613 int need_temp;
2614 gfc_symbol *lsym;
2616 lsym = c->expr1->symtree->n.sym;
2617 need_temp = gfc_check_dependency (c->expr1, c->expr2, 0);
2619 /* Now check for dependencies within the 'variable'
2620 expression itself. These are treated by making a complete
2621 copy of variable and changing all the references to it
2622 point to the copy instead. Note that the shallow copy of
2623 the variable will not suffice for derived types with
2624 pointer components. We therefore leave these to their
2625 own devices. */
2626 if (lsym->ts.type == BT_DERIVED
2627 && lsym->ts.u.derived->attr.pointer_comp)
2628 return need_temp;
2630 new_symtree = NULL;
2631 if (find_forall_index (c->expr1, lsym, 2) == SUCCESS)
2633 forall_make_variable_temp (c, pre, post);
2634 need_temp = 0;
2637 /* Substrings with dependencies are treated in the same
2638 way. */
2639 if (c->expr1->ts.type == BT_CHARACTER
2640 && c->expr1->ref
2641 && c->expr2->expr_type == EXPR_VARIABLE
2642 && lsym == c->expr2->symtree->n.sym)
2644 for (lref = c->expr1->ref; lref; lref = lref->next)
2645 if (lref->type == REF_SUBSTRING)
2646 break;
2647 for (rref = c->expr2->ref; rref; rref = rref->next)
2648 if (rref->type == REF_SUBSTRING)
2649 break;
2651 if (rref && lref
2652 && gfc_dep_compare_expr (rref->u.ss.start, lref->u.ss.start) < 0)
2654 forall_make_variable_temp (c, pre, post);
2655 need_temp = 0;
2658 return need_temp;
2662 static void
2663 cleanup_forall_symtrees (gfc_code *c)
2665 forall_restore_symtree (c->expr1);
2666 forall_restore_symtree (c->expr2);
2667 free (new_symtree->n.sym);
2668 free (new_symtree);
2672 /* Generate the loops for a FORALL block, specified by FORALL_TMP. BODY
2673 is the contents of the FORALL block/stmt to be iterated. MASK_FLAG
2674 indicates whether we should generate code to test the FORALLs mask
2675 array. OUTER is the loop header to be used for initializing mask
2676 indices.
2678 The generated loop format is:
2679 count = (end - start + step) / step
2680 loopvar = start
2681 while (1)
2683 if (count <=0 )
2684 goto end_of_loop
2685 <body>
2686 loopvar += step
2687 count --
2689 end_of_loop: */
2691 static tree
2692 gfc_trans_forall_loop (forall_info *forall_tmp, tree body,
2693 int mask_flag, stmtblock_t *outer)
2695 int n, nvar;
2696 tree tmp;
2697 tree cond;
2698 stmtblock_t block;
2699 tree exit_label;
2700 tree count;
2701 tree var, start, end, step;
2702 iter_info *iter;
2704 /* Initialize the mask index outside the FORALL nest. */
2705 if (mask_flag && forall_tmp->mask)
2706 gfc_add_modify (outer, forall_tmp->maskindex, gfc_index_zero_node);
2708 iter = forall_tmp->this_loop;
2709 nvar = forall_tmp->nvar;
2710 for (n = 0; n < nvar; n++)
2712 var = iter->var;
2713 start = iter->start;
2714 end = iter->end;
2715 step = iter->step;
2717 exit_label = gfc_build_label_decl (NULL_TREE);
2718 TREE_USED (exit_label) = 1;
2720 /* The loop counter. */
2721 count = gfc_create_var (TREE_TYPE (var), "count");
2723 /* The body of the loop. */
2724 gfc_init_block (&block);
2726 /* The exit condition. */
2727 cond = fold_build2_loc (input_location, LE_EXPR, boolean_type_node,
2728 count, build_int_cst (TREE_TYPE (count), 0));
2729 tmp = build1_v (GOTO_EXPR, exit_label);
2730 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
2731 cond, tmp, build_empty_stmt (input_location));
2732 gfc_add_expr_to_block (&block, tmp);
2734 /* The main loop body. */
2735 gfc_add_expr_to_block (&block, body);
2737 /* Increment the loop variable. */
2738 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (var), var,
2739 step);
2740 gfc_add_modify (&block, var, tmp);
2742 /* Advance to the next mask element. Only do this for the
2743 innermost loop. */
2744 if (n == 0 && mask_flag && forall_tmp->mask)
2746 tree maskindex = forall_tmp->maskindex;
2747 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
2748 maskindex, gfc_index_one_node);
2749 gfc_add_modify (&block, maskindex, tmp);
2752 /* Decrement the loop counter. */
2753 tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (var), count,
2754 build_int_cst (TREE_TYPE (var), 1));
2755 gfc_add_modify (&block, count, tmp);
2757 body = gfc_finish_block (&block);
2759 /* Loop var initialization. */
2760 gfc_init_block (&block);
2761 gfc_add_modify (&block, var, start);
2764 /* Initialize the loop counter. */
2765 tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (var), step,
2766 start);
2767 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (var), end,
2768 tmp);
2769 tmp = fold_build2_loc (input_location, TRUNC_DIV_EXPR, TREE_TYPE (var),
2770 tmp, step);
2771 gfc_add_modify (&block, count, tmp);
2773 /* The loop expression. */
2774 tmp = build1_v (LOOP_EXPR, body);
2775 gfc_add_expr_to_block (&block, tmp);
2777 /* The exit label. */
2778 tmp = build1_v (LABEL_EXPR, exit_label);
2779 gfc_add_expr_to_block (&block, tmp);
2781 body = gfc_finish_block (&block);
2782 iter = iter->next;
2784 return body;
2788 /* Generate the body and loops according to MASK_FLAG. If MASK_FLAG
2789 is nonzero, the body is controlled by all masks in the forall nest.
2790 Otherwise, the innermost loop is not controlled by it's mask. This
2791 is used for initializing that mask. */
2793 static tree
2794 gfc_trans_nested_forall_loop (forall_info * nested_forall_info, tree body,
2795 int mask_flag)
2797 tree tmp;
2798 stmtblock_t header;
2799 forall_info *forall_tmp;
2800 tree mask, maskindex;
2802 gfc_start_block (&header);
2804 forall_tmp = nested_forall_info;
2805 while (forall_tmp != NULL)
2807 /* Generate body with masks' control. */
2808 if (mask_flag)
2810 mask = forall_tmp->mask;
2811 maskindex = forall_tmp->maskindex;
2813 /* If a mask was specified make the assignment conditional. */
2814 if (mask)
2816 tmp = gfc_build_array_ref (mask, maskindex, NULL);
2817 body = build3_v (COND_EXPR, tmp, body,
2818 build_empty_stmt (input_location));
2821 body = gfc_trans_forall_loop (forall_tmp, body, mask_flag, &header);
2822 forall_tmp = forall_tmp->prev_nest;
2823 mask_flag = 1;
2826 gfc_add_expr_to_block (&header, body);
2827 return gfc_finish_block (&header);
2831 /* Allocate data for holding a temporary array. Returns either a local
2832 temporary array or a pointer variable. */
2834 static tree
2835 gfc_do_allocate (tree bytesize, tree size, tree * pdata, stmtblock_t * pblock,
2836 tree elem_type)
2838 tree tmpvar;
2839 tree type;
2840 tree tmp;
2842 if (INTEGER_CST_P (size))
2843 tmp = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
2844 size, gfc_index_one_node);
2845 else
2846 tmp = NULL_TREE;
2848 type = build_range_type (gfc_array_index_type, gfc_index_zero_node, tmp);
2849 type = build_array_type (elem_type, type);
2850 if (gfc_can_put_var_on_stack (bytesize))
2852 gcc_assert (INTEGER_CST_P (size));
2853 tmpvar = gfc_create_var (type, "temp");
2854 *pdata = NULL_TREE;
2856 else
2858 tmpvar = gfc_create_var (build_pointer_type (type), "temp");
2859 *pdata = convert (pvoid_type_node, tmpvar);
2861 tmp = gfc_call_malloc (pblock, TREE_TYPE (tmpvar), bytesize);
2862 gfc_add_modify (pblock, tmpvar, tmp);
2864 return tmpvar;
2868 /* Generate codes to copy the temporary to the actual lhs. */
2870 static tree
2871 generate_loop_for_temp_to_lhs (gfc_expr *expr, tree tmp1, tree count3,
2872 tree count1, tree wheremask, bool invert)
2874 gfc_ss *lss;
2875 gfc_se lse, rse;
2876 stmtblock_t block, body;
2877 gfc_loopinfo loop1;
2878 tree tmp;
2879 tree wheremaskexpr;
2881 /* Walk the lhs. */
2882 lss = gfc_walk_expr (expr);
2884 if (lss == gfc_ss_terminator)
2886 gfc_start_block (&block);
2888 gfc_init_se (&lse, NULL);
2890 /* Translate the expression. */
2891 gfc_conv_expr (&lse, expr);
2893 /* Form the expression for the temporary. */
2894 tmp = gfc_build_array_ref (tmp1, count1, NULL);
2896 /* Use the scalar assignment as is. */
2897 gfc_add_block_to_block (&block, &lse.pre);
2898 gfc_add_modify (&block, lse.expr, tmp);
2899 gfc_add_block_to_block (&block, &lse.post);
2901 /* Increment the count1. */
2902 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (count1),
2903 count1, gfc_index_one_node);
2904 gfc_add_modify (&block, count1, tmp);
2906 tmp = gfc_finish_block (&block);
2908 else
2910 gfc_start_block (&block);
2912 gfc_init_loopinfo (&loop1);
2913 gfc_init_se (&rse, NULL);
2914 gfc_init_se (&lse, NULL);
2916 /* Associate the lss with the loop. */
2917 gfc_add_ss_to_loop (&loop1, lss);
2919 /* Calculate the bounds of the scalarization. */
2920 gfc_conv_ss_startstride (&loop1);
2921 /* Setup the scalarizing loops. */
2922 gfc_conv_loop_setup (&loop1, &expr->where);
2924 gfc_mark_ss_chain_used (lss, 1);
2926 /* Start the scalarized loop body. */
2927 gfc_start_scalarized_body (&loop1, &body);
2929 /* Setup the gfc_se structures. */
2930 gfc_copy_loopinfo_to_se (&lse, &loop1);
2931 lse.ss = lss;
2933 /* Form the expression of the temporary. */
2934 if (lss != gfc_ss_terminator)
2935 rse.expr = gfc_build_array_ref (tmp1, count1, NULL);
2936 /* Translate expr. */
2937 gfc_conv_expr (&lse, expr);
2939 /* Use the scalar assignment. */
2940 rse.string_length = lse.string_length;
2941 tmp = gfc_trans_scalar_assign (&lse, &rse, expr->ts, false, true, true);
2943 /* Form the mask expression according to the mask tree list. */
2944 if (wheremask)
2946 wheremaskexpr = gfc_build_array_ref (wheremask, count3, NULL);
2947 if (invert)
2948 wheremaskexpr = fold_build1_loc (input_location, TRUTH_NOT_EXPR,
2949 TREE_TYPE (wheremaskexpr),
2950 wheremaskexpr);
2951 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
2952 wheremaskexpr, tmp,
2953 build_empty_stmt (input_location));
2956 gfc_add_expr_to_block (&body, tmp);
2958 /* Increment count1. */
2959 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
2960 count1, gfc_index_one_node);
2961 gfc_add_modify (&body, count1, tmp);
2963 /* Increment count3. */
2964 if (count3)
2966 tmp = fold_build2_loc (input_location, PLUS_EXPR,
2967 gfc_array_index_type, count3,
2968 gfc_index_one_node);
2969 gfc_add_modify (&body, count3, tmp);
2972 /* Generate the copying loops. */
2973 gfc_trans_scalarizing_loops (&loop1, &body);
2974 gfc_add_block_to_block (&block, &loop1.pre);
2975 gfc_add_block_to_block (&block, &loop1.post);
2976 gfc_cleanup_loop (&loop1);
2978 tmp = gfc_finish_block (&block);
2980 return tmp;
2984 /* Generate codes to copy rhs to the temporary. TMP1 is the address of
2985 temporary, LSS and RSS are formed in function compute_inner_temp_size(),
2986 and should not be freed. WHEREMASK is the conditional execution mask
2987 whose sense may be inverted by INVERT. */
2989 static tree
2990 generate_loop_for_rhs_to_temp (gfc_expr *expr2, tree tmp1, tree count3,
2991 tree count1, gfc_ss *lss, gfc_ss *rss,
2992 tree wheremask, bool invert)
2994 stmtblock_t block, body1;
2995 gfc_loopinfo loop;
2996 gfc_se lse;
2997 gfc_se rse;
2998 tree tmp;
2999 tree wheremaskexpr;
3001 gfc_start_block (&block);
3003 gfc_init_se (&rse, NULL);
3004 gfc_init_se (&lse, NULL);
3006 if (lss == gfc_ss_terminator)
3008 gfc_init_block (&body1);
3009 gfc_conv_expr (&rse, expr2);
3010 lse.expr = gfc_build_array_ref (tmp1, count1, NULL);
3012 else
3014 /* Initialize the loop. */
3015 gfc_init_loopinfo (&loop);
3017 /* We may need LSS to determine the shape of the expression. */
3018 gfc_add_ss_to_loop (&loop, lss);
3019 gfc_add_ss_to_loop (&loop, rss);
3021 gfc_conv_ss_startstride (&loop);
3022 gfc_conv_loop_setup (&loop, &expr2->where);
3024 gfc_mark_ss_chain_used (rss, 1);
3025 /* Start the loop body. */
3026 gfc_start_scalarized_body (&loop, &body1);
3028 /* Translate the expression. */
3029 gfc_copy_loopinfo_to_se (&rse, &loop);
3030 rse.ss = rss;
3031 gfc_conv_expr (&rse, expr2);
3033 /* Form the expression of the temporary. */
3034 lse.expr = gfc_build_array_ref (tmp1, count1, NULL);
3037 /* Use the scalar assignment. */
3038 lse.string_length = rse.string_length;
3039 tmp = gfc_trans_scalar_assign (&lse, &rse, expr2->ts, true,
3040 expr2->expr_type == EXPR_VARIABLE, true);
3042 /* Form the mask expression according to the mask tree list. */
3043 if (wheremask)
3045 wheremaskexpr = gfc_build_array_ref (wheremask, count3, NULL);
3046 if (invert)
3047 wheremaskexpr = fold_build1_loc (input_location, TRUTH_NOT_EXPR,
3048 TREE_TYPE (wheremaskexpr),
3049 wheremaskexpr);
3050 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
3051 wheremaskexpr, tmp,
3052 build_empty_stmt (input_location));
3055 gfc_add_expr_to_block (&body1, tmp);
3057 if (lss == gfc_ss_terminator)
3059 gfc_add_block_to_block (&block, &body1);
3061 /* Increment count1. */
3062 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (count1),
3063 count1, gfc_index_one_node);
3064 gfc_add_modify (&block, count1, tmp);
3066 else
3068 /* Increment count1. */
3069 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
3070 count1, gfc_index_one_node);
3071 gfc_add_modify (&body1, count1, tmp);
3073 /* Increment count3. */
3074 if (count3)
3076 tmp = fold_build2_loc (input_location, PLUS_EXPR,
3077 gfc_array_index_type,
3078 count3, gfc_index_one_node);
3079 gfc_add_modify (&body1, count3, tmp);
3082 /* Generate the copying loops. */
3083 gfc_trans_scalarizing_loops (&loop, &body1);
3085 gfc_add_block_to_block (&block, &loop.pre);
3086 gfc_add_block_to_block (&block, &loop.post);
3088 gfc_cleanup_loop (&loop);
3089 /* TODO: Reuse lss and rss when copying temp->lhs. Need to be careful
3090 as tree nodes in SS may not be valid in different scope. */
3093 tmp = gfc_finish_block (&block);
3094 return tmp;
3098 /* Calculate the size of temporary needed in the assignment inside forall.
3099 LSS and RSS are filled in this function. */
3101 static tree
3102 compute_inner_temp_size (gfc_expr *expr1, gfc_expr *expr2,
3103 stmtblock_t * pblock,
3104 gfc_ss **lss, gfc_ss **rss)
3106 gfc_loopinfo loop;
3107 tree size;
3108 int i;
3109 int save_flag;
3110 tree tmp;
3112 *lss = gfc_walk_expr (expr1);
3113 *rss = NULL;
3115 size = gfc_index_one_node;
3116 if (*lss != gfc_ss_terminator)
3118 gfc_init_loopinfo (&loop);
3120 /* Walk the RHS of the expression. */
3121 *rss = gfc_walk_expr (expr2);
3122 if (*rss == gfc_ss_terminator)
3123 /* The rhs is scalar. Add a ss for the expression. */
3124 *rss = gfc_get_scalar_ss (gfc_ss_terminator, expr2);
3126 /* Associate the SS with the loop. */
3127 gfc_add_ss_to_loop (&loop, *lss);
3128 /* We don't actually need to add the rhs at this point, but it might
3129 make guessing the loop bounds a bit easier. */
3130 gfc_add_ss_to_loop (&loop, *rss);
3132 /* We only want the shape of the expression, not rest of the junk
3133 generated by the scalarizer. */
3134 loop.array_parameter = 1;
3136 /* Calculate the bounds of the scalarization. */
3137 save_flag = gfc_option.rtcheck;
3138 gfc_option.rtcheck &= !GFC_RTCHECK_BOUNDS;
3139 gfc_conv_ss_startstride (&loop);
3140 gfc_option.rtcheck = save_flag;
3141 gfc_conv_loop_setup (&loop, &expr2->where);
3143 /* Figure out how many elements we need. */
3144 for (i = 0; i < loop.dimen; i++)
3146 tmp = fold_build2_loc (input_location, MINUS_EXPR,
3147 gfc_array_index_type,
3148 gfc_index_one_node, loop.from[i]);
3149 tmp = fold_build2_loc (input_location, PLUS_EXPR,
3150 gfc_array_index_type, tmp, loop.to[i]);
3151 size = fold_build2_loc (input_location, MULT_EXPR,
3152 gfc_array_index_type, size, tmp);
3154 gfc_add_block_to_block (pblock, &loop.pre);
3155 size = gfc_evaluate_now (size, pblock);
3156 gfc_add_block_to_block (pblock, &loop.post);
3158 /* TODO: write a function that cleans up a loopinfo without freeing
3159 the SS chains. Currently a NOP. */
3162 return size;
3166 /* Calculate the overall iterator number of the nested forall construct.
3167 This routine actually calculates the number of times the body of the
3168 nested forall specified by NESTED_FORALL_INFO is executed and multiplies
3169 that by the expression INNER_SIZE. The BLOCK argument specifies the
3170 block in which to calculate the result, and the optional INNER_SIZE_BODY
3171 argument contains any statements that need to executed (inside the loop)
3172 to initialize or calculate INNER_SIZE. */
3174 static tree
3175 compute_overall_iter_number (forall_info *nested_forall_info, tree inner_size,
3176 stmtblock_t *inner_size_body, stmtblock_t *block)
3178 forall_info *forall_tmp = nested_forall_info;
3179 tree tmp, number;
3180 stmtblock_t body;
3182 /* We can eliminate the innermost unconditional loops with constant
3183 array bounds. */
3184 if (INTEGER_CST_P (inner_size))
3186 while (forall_tmp
3187 && !forall_tmp->mask
3188 && INTEGER_CST_P (forall_tmp->size))
3190 inner_size = fold_build2_loc (input_location, MULT_EXPR,
3191 gfc_array_index_type,
3192 inner_size, forall_tmp->size);
3193 forall_tmp = forall_tmp->prev_nest;
3196 /* If there are no loops left, we have our constant result. */
3197 if (!forall_tmp)
3198 return inner_size;
3201 /* Otherwise, create a temporary variable to compute the result. */
3202 number = gfc_create_var (gfc_array_index_type, "num");
3203 gfc_add_modify (block, number, gfc_index_zero_node);
3205 gfc_start_block (&body);
3206 if (inner_size_body)
3207 gfc_add_block_to_block (&body, inner_size_body);
3208 if (forall_tmp)
3209 tmp = fold_build2_loc (input_location, PLUS_EXPR,
3210 gfc_array_index_type, number, inner_size);
3211 else
3212 tmp = inner_size;
3213 gfc_add_modify (&body, number, tmp);
3214 tmp = gfc_finish_block (&body);
3216 /* Generate loops. */
3217 if (forall_tmp != NULL)
3218 tmp = gfc_trans_nested_forall_loop (forall_tmp, tmp, 1);
3220 gfc_add_expr_to_block (block, tmp);
3222 return number;
3226 /* Allocate temporary for forall construct. SIZE is the size of temporary
3227 needed. PTEMP1 is returned for space free. */
3229 static tree
3230 allocate_temp_for_forall_nest_1 (tree type, tree size, stmtblock_t * block,
3231 tree * ptemp1)
3233 tree bytesize;
3234 tree unit;
3235 tree tmp;
3237 unit = fold_convert (gfc_array_index_type, TYPE_SIZE_UNIT (type));
3238 if (!integer_onep (unit))
3239 bytesize = fold_build2_loc (input_location, MULT_EXPR,
3240 gfc_array_index_type, size, unit);
3241 else
3242 bytesize = size;
3244 *ptemp1 = NULL;
3245 tmp = gfc_do_allocate (bytesize, size, ptemp1, block, type);
3247 if (*ptemp1)
3248 tmp = build_fold_indirect_ref_loc (input_location, tmp);
3249 return tmp;
3253 /* Allocate temporary for forall construct according to the information in
3254 nested_forall_info. INNER_SIZE is the size of temporary needed in the
3255 assignment inside forall. PTEMP1 is returned for space free. */
3257 static tree
3258 allocate_temp_for_forall_nest (forall_info * nested_forall_info, tree type,
3259 tree inner_size, stmtblock_t * inner_size_body,
3260 stmtblock_t * block, tree * ptemp1)
3262 tree size;
3264 /* Calculate the total size of temporary needed in forall construct. */
3265 size = compute_overall_iter_number (nested_forall_info, inner_size,
3266 inner_size_body, block);
3268 return allocate_temp_for_forall_nest_1 (type, size, block, ptemp1);
3272 /* Handle assignments inside forall which need temporary.
3274 forall (i=start:end:stride; maskexpr)
3275 e<i> = f<i>
3276 end forall
3277 (where e,f<i> are arbitrary expressions possibly involving i
3278 and there is a dependency between e<i> and f<i>)
3279 Translates to:
3280 masktmp(:) = maskexpr(:)
3282 maskindex = 0;
3283 count1 = 0;
3284 num = 0;
3285 for (i = start; i <= end; i += stride)
3286 num += SIZE (f<i>)
3287 count1 = 0;
3288 ALLOCATE (tmp(num))
3289 for (i = start; i <= end; i += stride)
3291 if (masktmp[maskindex++])
3292 tmp[count1++] = f<i>
3294 maskindex = 0;
3295 count1 = 0;
3296 for (i = start; i <= end; i += stride)
3298 if (masktmp[maskindex++])
3299 e<i> = tmp[count1++]
3301 DEALLOCATE (tmp)
3303 static void
3304 gfc_trans_assign_need_temp (gfc_expr * expr1, gfc_expr * expr2,
3305 tree wheremask, bool invert,
3306 forall_info * nested_forall_info,
3307 stmtblock_t * block)
3309 tree type;
3310 tree inner_size;
3311 gfc_ss *lss, *rss;
3312 tree count, count1;
3313 tree tmp, tmp1;
3314 tree ptemp1;
3315 stmtblock_t inner_size_body;
3317 /* Create vars. count1 is the current iterator number of the nested
3318 forall. */
3319 count1 = gfc_create_var (gfc_array_index_type, "count1");
3321 /* Count is the wheremask index. */
3322 if (wheremask)
3324 count = gfc_create_var (gfc_array_index_type, "count");
3325 gfc_add_modify (block, count, gfc_index_zero_node);
3327 else
3328 count = NULL;
3330 /* Initialize count1. */
3331 gfc_add_modify (block, count1, gfc_index_zero_node);
3333 /* Calculate the size of temporary needed in the assignment. Return loop, lss
3334 and rss which are used in function generate_loop_for_rhs_to_temp(). */
3335 gfc_init_block (&inner_size_body);
3336 inner_size = compute_inner_temp_size (expr1, expr2, &inner_size_body,
3337 &lss, &rss);
3339 /* The type of LHS. Used in function allocate_temp_for_forall_nest */
3340 if (expr1->ts.type == BT_CHARACTER && expr1->ts.u.cl->length)
3342 if (!expr1->ts.u.cl->backend_decl)
3344 gfc_se tse;
3345 gfc_init_se (&tse, NULL);
3346 gfc_conv_expr (&tse, expr1->ts.u.cl->length);
3347 expr1->ts.u.cl->backend_decl = tse.expr;
3349 type = gfc_get_character_type_len (gfc_default_character_kind,
3350 expr1->ts.u.cl->backend_decl);
3352 else
3353 type = gfc_typenode_for_spec (&expr1->ts);
3355 /* Allocate temporary for nested forall construct according to the
3356 information in nested_forall_info and inner_size. */
3357 tmp1 = allocate_temp_for_forall_nest (nested_forall_info, type, inner_size,
3358 &inner_size_body, block, &ptemp1);
3360 /* Generate codes to copy rhs to the temporary . */
3361 tmp = generate_loop_for_rhs_to_temp (expr2, tmp1, count, count1, lss, rss,
3362 wheremask, invert);
3364 /* Generate body and loops according to the information in
3365 nested_forall_info. */
3366 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
3367 gfc_add_expr_to_block (block, tmp);
3369 /* Reset count1. */
3370 gfc_add_modify (block, count1, gfc_index_zero_node);
3372 /* Reset count. */
3373 if (wheremask)
3374 gfc_add_modify (block, count, gfc_index_zero_node);
3376 /* Generate codes to copy the temporary to lhs. */
3377 tmp = generate_loop_for_temp_to_lhs (expr1, tmp1, count, count1,
3378 wheremask, invert);
3380 /* Generate body and loops according to the information in
3381 nested_forall_info. */
3382 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
3383 gfc_add_expr_to_block (block, tmp);
3385 if (ptemp1)
3387 /* Free the temporary. */
3388 tmp = gfc_call_free (ptemp1);
3389 gfc_add_expr_to_block (block, tmp);
3394 /* Translate pointer assignment inside FORALL which need temporary. */
3396 static void
3397 gfc_trans_pointer_assign_need_temp (gfc_expr * expr1, gfc_expr * expr2,
3398 forall_info * nested_forall_info,
3399 stmtblock_t * block)
3401 tree type;
3402 tree inner_size;
3403 gfc_ss *lss, *rss;
3404 gfc_se lse;
3405 gfc_se rse;
3406 gfc_array_info *info;
3407 gfc_loopinfo loop;
3408 tree desc;
3409 tree parm;
3410 tree parmtype;
3411 stmtblock_t body;
3412 tree count;
3413 tree tmp, tmp1, ptemp1;
3415 count = gfc_create_var (gfc_array_index_type, "count");
3416 gfc_add_modify (block, count, gfc_index_zero_node);
3418 inner_size = gfc_index_one_node;
3419 lss = gfc_walk_expr (expr1);
3420 rss = gfc_walk_expr (expr2);
3421 if (lss == gfc_ss_terminator)
3423 type = gfc_typenode_for_spec (&expr1->ts);
3424 type = build_pointer_type (type);
3426 /* Allocate temporary for nested forall construct according to the
3427 information in nested_forall_info and inner_size. */
3428 tmp1 = allocate_temp_for_forall_nest (nested_forall_info, type,
3429 inner_size, NULL, block, &ptemp1);
3430 gfc_start_block (&body);
3431 gfc_init_se (&lse, NULL);
3432 lse.expr = gfc_build_array_ref (tmp1, count, NULL);
3433 gfc_init_se (&rse, NULL);
3434 rse.want_pointer = 1;
3435 gfc_conv_expr (&rse, expr2);
3436 gfc_add_block_to_block (&body, &rse.pre);
3437 gfc_add_modify (&body, lse.expr,
3438 fold_convert (TREE_TYPE (lse.expr), rse.expr));
3439 gfc_add_block_to_block (&body, &rse.post);
3441 /* Increment count. */
3442 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
3443 count, gfc_index_one_node);
3444 gfc_add_modify (&body, count, tmp);
3446 tmp = gfc_finish_block (&body);
3448 /* Generate body and loops according to the information in
3449 nested_forall_info. */
3450 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
3451 gfc_add_expr_to_block (block, tmp);
3453 /* Reset count. */
3454 gfc_add_modify (block, count, gfc_index_zero_node);
3456 gfc_start_block (&body);
3457 gfc_init_se (&lse, NULL);
3458 gfc_init_se (&rse, NULL);
3459 rse.expr = gfc_build_array_ref (tmp1, count, NULL);
3460 lse.want_pointer = 1;
3461 gfc_conv_expr (&lse, expr1);
3462 gfc_add_block_to_block (&body, &lse.pre);
3463 gfc_add_modify (&body, lse.expr, rse.expr);
3464 gfc_add_block_to_block (&body, &lse.post);
3465 /* Increment count. */
3466 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
3467 count, gfc_index_one_node);
3468 gfc_add_modify (&body, count, tmp);
3469 tmp = gfc_finish_block (&body);
3471 /* Generate body and loops according to the information in
3472 nested_forall_info. */
3473 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
3474 gfc_add_expr_to_block (block, tmp);
3476 else
3478 gfc_init_loopinfo (&loop);
3480 /* Associate the SS with the loop. */
3481 gfc_add_ss_to_loop (&loop, rss);
3483 /* Setup the scalarizing loops and bounds. */
3484 gfc_conv_ss_startstride (&loop);
3486 gfc_conv_loop_setup (&loop, &expr2->where);
3488 info = &rss->info->data.array;
3489 desc = info->descriptor;
3491 /* Make a new descriptor. */
3492 parmtype = gfc_get_element_type (TREE_TYPE (desc));
3493 parmtype = gfc_get_array_type_bounds (parmtype, loop.dimen, 0,
3494 loop.from, loop.to, 1,
3495 GFC_ARRAY_UNKNOWN, true);
3497 /* Allocate temporary for nested forall construct. */
3498 tmp1 = allocate_temp_for_forall_nest (nested_forall_info, parmtype,
3499 inner_size, NULL, block, &ptemp1);
3500 gfc_start_block (&body);
3501 gfc_init_se (&lse, NULL);
3502 lse.expr = gfc_build_array_ref (tmp1, count, NULL);
3503 lse.direct_byref = 1;
3504 rss = gfc_walk_expr (expr2);
3505 gfc_conv_expr_descriptor (&lse, expr2, rss);
3507 gfc_add_block_to_block (&body, &lse.pre);
3508 gfc_add_block_to_block (&body, &lse.post);
3510 /* Increment count. */
3511 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
3512 count, gfc_index_one_node);
3513 gfc_add_modify (&body, count, tmp);
3515 tmp = gfc_finish_block (&body);
3517 /* Generate body and loops according to the information in
3518 nested_forall_info. */
3519 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
3520 gfc_add_expr_to_block (block, tmp);
3522 /* Reset count. */
3523 gfc_add_modify (block, count, gfc_index_zero_node);
3525 parm = gfc_build_array_ref (tmp1, count, NULL);
3526 lss = gfc_walk_expr (expr1);
3527 gfc_init_se (&lse, NULL);
3528 gfc_conv_expr_descriptor (&lse, expr1, lss);
3529 gfc_add_modify (&lse.pre, lse.expr, parm);
3530 gfc_start_block (&body);
3531 gfc_add_block_to_block (&body, &lse.pre);
3532 gfc_add_block_to_block (&body, &lse.post);
3534 /* Increment count. */
3535 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
3536 count, gfc_index_one_node);
3537 gfc_add_modify (&body, count, tmp);
3539 tmp = gfc_finish_block (&body);
3541 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
3542 gfc_add_expr_to_block (block, tmp);
3544 /* Free the temporary. */
3545 if (ptemp1)
3547 tmp = gfc_call_free (ptemp1);
3548 gfc_add_expr_to_block (block, tmp);
3553 /* FORALL and WHERE statements are really nasty, especially when you nest
3554 them. All the rhs of a forall assignment must be evaluated before the
3555 actual assignments are performed. Presumably this also applies to all the
3556 assignments in an inner where statement. */
3558 /* Generate code for a FORALL statement. Any temporaries are allocated as a
3559 linear array, relying on the fact that we process in the same order in all
3560 loops.
3562 forall (i=start:end:stride; maskexpr)
3563 e<i> = f<i>
3564 g<i> = h<i>
3565 end forall
3566 (where e,f,g,h<i> are arbitrary expressions possibly involving i)
3567 Translates to:
3568 count = ((end + 1 - start) / stride)
3569 masktmp(:) = maskexpr(:)
3571 maskindex = 0;
3572 for (i = start; i <= end; i += stride)
3574 if (masktmp[maskindex++])
3575 e<i> = f<i>
3577 maskindex = 0;
3578 for (i = start; i <= end; i += stride)
3580 if (masktmp[maskindex++])
3581 g<i> = h<i>
3584 Note that this code only works when there are no dependencies.
3585 Forall loop with array assignments and data dependencies are a real pain,
3586 because the size of the temporary cannot always be determined before the
3587 loop is executed. This problem is compounded by the presence of nested
3588 FORALL constructs.
3591 static tree
3592 gfc_trans_forall_1 (gfc_code * code, forall_info * nested_forall_info)
3594 stmtblock_t pre;
3595 stmtblock_t post;
3596 stmtblock_t block;
3597 stmtblock_t body;
3598 tree *var;
3599 tree *start;
3600 tree *end;
3601 tree *step;
3602 gfc_expr **varexpr;
3603 tree tmp;
3604 tree assign;
3605 tree size;
3606 tree maskindex;
3607 tree mask;
3608 tree pmask;
3609 tree cycle_label = NULL_TREE;
3610 int n;
3611 int nvar;
3612 int need_temp;
3613 gfc_forall_iterator *fa;
3614 gfc_se se;
3615 gfc_code *c;
3616 gfc_saved_var *saved_vars;
3617 iter_info *this_forall;
3618 forall_info *info;
3619 bool need_mask;
3621 /* Do nothing if the mask is false. */
3622 if (code->expr1
3623 && code->expr1->expr_type == EXPR_CONSTANT
3624 && !code->expr1->value.logical)
3625 return build_empty_stmt (input_location);
3627 n = 0;
3628 /* Count the FORALL index number. */
3629 for (fa = code->ext.forall_iterator; fa; fa = fa->next)
3630 n++;
3631 nvar = n;
3633 /* Allocate the space for var, start, end, step, varexpr. */
3634 var = XCNEWVEC (tree, nvar);
3635 start = XCNEWVEC (tree, nvar);
3636 end = XCNEWVEC (tree, nvar);
3637 step = XCNEWVEC (tree, nvar);
3638 varexpr = XCNEWVEC (gfc_expr *, nvar);
3639 saved_vars = XCNEWVEC (gfc_saved_var, nvar);
3641 /* Allocate the space for info. */
3642 info = XCNEW (forall_info);
3644 gfc_start_block (&pre);
3645 gfc_init_block (&post);
3646 gfc_init_block (&block);
3648 n = 0;
3649 for (fa = code->ext.forall_iterator; fa; fa = fa->next)
3651 gfc_symbol *sym = fa->var->symtree->n.sym;
3653 /* Allocate space for this_forall. */
3654 this_forall = XCNEW (iter_info);
3656 /* Create a temporary variable for the FORALL index. */
3657 tmp = gfc_typenode_for_spec (&sym->ts);
3658 var[n] = gfc_create_var (tmp, sym->name);
3659 gfc_shadow_sym (sym, var[n], &saved_vars[n]);
3661 /* Record it in this_forall. */
3662 this_forall->var = var[n];
3664 /* Replace the index symbol's backend_decl with the temporary decl. */
3665 sym->backend_decl = var[n];
3667 /* Work out the start, end and stride for the loop. */
3668 gfc_init_se (&se, NULL);
3669 gfc_conv_expr_val (&se, fa->start);
3670 /* Record it in this_forall. */
3671 this_forall->start = se.expr;
3672 gfc_add_block_to_block (&block, &se.pre);
3673 start[n] = se.expr;
3675 gfc_init_se (&se, NULL);
3676 gfc_conv_expr_val (&se, fa->end);
3677 /* Record it in this_forall. */
3678 this_forall->end = se.expr;
3679 gfc_make_safe_expr (&se);
3680 gfc_add_block_to_block (&block, &se.pre);
3681 end[n] = se.expr;
3683 gfc_init_se (&se, NULL);
3684 gfc_conv_expr_val (&se, fa->stride);
3685 /* Record it in this_forall. */
3686 this_forall->step = se.expr;
3687 gfc_make_safe_expr (&se);
3688 gfc_add_block_to_block (&block, &se.pre);
3689 step[n] = se.expr;
3691 /* Set the NEXT field of this_forall to NULL. */
3692 this_forall->next = NULL;
3693 /* Link this_forall to the info construct. */
3694 if (info->this_loop)
3696 iter_info *iter_tmp = info->this_loop;
3697 while (iter_tmp->next != NULL)
3698 iter_tmp = iter_tmp->next;
3699 iter_tmp->next = this_forall;
3701 else
3702 info->this_loop = this_forall;
3704 n++;
3706 nvar = n;
3708 /* Calculate the size needed for the current forall level. */
3709 size = gfc_index_one_node;
3710 for (n = 0; n < nvar; n++)
3712 /* size = (end + step - start) / step. */
3713 tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (start[n]),
3714 step[n], start[n]);
3715 tmp = fold_build2_loc (input_location, PLUS_EXPR, TREE_TYPE (end[n]),
3716 end[n], tmp);
3717 tmp = fold_build2_loc (input_location, FLOOR_DIV_EXPR, TREE_TYPE (tmp),
3718 tmp, step[n]);
3719 tmp = convert (gfc_array_index_type, tmp);
3721 size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
3722 size, tmp);
3725 /* Record the nvar and size of current forall level. */
3726 info->nvar = nvar;
3727 info->size = size;
3729 if (code->expr1)
3731 /* If the mask is .true., consider the FORALL unconditional. */
3732 if (code->expr1->expr_type == EXPR_CONSTANT
3733 && code->expr1->value.logical)
3734 need_mask = false;
3735 else
3736 need_mask = true;
3738 else
3739 need_mask = false;
3741 /* First we need to allocate the mask. */
3742 if (need_mask)
3744 /* As the mask array can be very big, prefer compact boolean types. */
3745 tree mask_type = gfc_get_logical_type (gfc_logical_kinds[0].kind);
3746 mask = allocate_temp_for_forall_nest (nested_forall_info, mask_type,
3747 size, NULL, &block, &pmask);
3748 maskindex = gfc_create_var_np (gfc_array_index_type, "mi");
3750 /* Record them in the info structure. */
3751 info->maskindex = maskindex;
3752 info->mask = mask;
3754 else
3756 /* No mask was specified. */
3757 maskindex = NULL_TREE;
3758 mask = pmask = NULL_TREE;
3761 /* Link the current forall level to nested_forall_info. */
3762 info->prev_nest = nested_forall_info;
3763 nested_forall_info = info;
3765 /* Copy the mask into a temporary variable if required.
3766 For now we assume a mask temporary is needed. */
3767 if (need_mask)
3769 /* As the mask array can be very big, prefer compact boolean types. */
3770 tree mask_type = gfc_get_logical_type (gfc_logical_kinds[0].kind);
3772 gfc_add_modify (&block, maskindex, gfc_index_zero_node);
3774 /* Start of mask assignment loop body. */
3775 gfc_start_block (&body);
3777 /* Evaluate the mask expression. */
3778 gfc_init_se (&se, NULL);
3779 gfc_conv_expr_val (&se, code->expr1);
3780 gfc_add_block_to_block (&body, &se.pre);
3782 /* Store the mask. */
3783 se.expr = convert (mask_type, se.expr);
3785 tmp = gfc_build_array_ref (mask, maskindex, NULL);
3786 gfc_add_modify (&body, tmp, se.expr);
3788 /* Advance to the next mask element. */
3789 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
3790 maskindex, gfc_index_one_node);
3791 gfc_add_modify (&body, maskindex, tmp);
3793 /* Generate the loops. */
3794 tmp = gfc_finish_block (&body);
3795 tmp = gfc_trans_nested_forall_loop (info, tmp, 0);
3796 gfc_add_expr_to_block (&block, tmp);
3799 if (code->op == EXEC_DO_CONCURRENT)
3801 gfc_init_block (&body);
3802 cycle_label = gfc_build_label_decl (NULL_TREE);
3803 code->cycle_label = cycle_label;
3804 tmp = gfc_trans_code (code->block->next);
3805 gfc_add_expr_to_block (&body, tmp);
3807 if (TREE_USED (cycle_label))
3809 tmp = build1_v (LABEL_EXPR, cycle_label);
3810 gfc_add_expr_to_block (&body, tmp);
3813 tmp = gfc_finish_block (&body);
3814 tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1);
3815 gfc_add_expr_to_block (&block, tmp);
3816 goto done;
3819 c = code->block->next;
3821 /* TODO: loop merging in FORALL statements. */
3822 /* Now that we've got a copy of the mask, generate the assignment loops. */
3823 while (c)
3825 switch (c->op)
3827 case EXEC_ASSIGN:
3828 /* A scalar or array assignment. DO the simple check for
3829 lhs to rhs dependencies. These make a temporary for the
3830 rhs and form a second forall block to copy to variable. */
3831 need_temp = check_forall_dependencies(c, &pre, &post);
3833 /* Temporaries due to array assignment data dependencies introduce
3834 no end of problems. */
3835 if (need_temp)
3836 gfc_trans_assign_need_temp (c->expr1, c->expr2, NULL, false,
3837 nested_forall_info, &block);
3838 else
3840 /* Use the normal assignment copying routines. */
3841 assign = gfc_trans_assignment (c->expr1, c->expr2, false, true);
3843 /* Generate body and loops. */
3844 tmp = gfc_trans_nested_forall_loop (nested_forall_info,
3845 assign, 1);
3846 gfc_add_expr_to_block (&block, tmp);
3849 /* Cleanup any temporary symtrees that have been made to deal
3850 with dependencies. */
3851 if (new_symtree)
3852 cleanup_forall_symtrees (c);
3854 break;
3856 case EXEC_WHERE:
3857 /* Translate WHERE or WHERE construct nested in FORALL. */
3858 gfc_trans_where_2 (c, NULL, false, nested_forall_info, &block);
3859 break;
3861 /* Pointer assignment inside FORALL. */
3862 case EXEC_POINTER_ASSIGN:
3863 need_temp = gfc_check_dependency (c->expr1, c->expr2, 0);
3864 if (need_temp)
3865 gfc_trans_pointer_assign_need_temp (c->expr1, c->expr2,
3866 nested_forall_info, &block);
3867 else
3869 /* Use the normal assignment copying routines. */
3870 assign = gfc_trans_pointer_assignment (c->expr1, c->expr2);
3872 /* Generate body and loops. */
3873 tmp = gfc_trans_nested_forall_loop (nested_forall_info,
3874 assign, 1);
3875 gfc_add_expr_to_block (&block, tmp);
3877 break;
3879 case EXEC_FORALL:
3880 tmp = gfc_trans_forall_1 (c, nested_forall_info);
3881 gfc_add_expr_to_block (&block, tmp);
3882 break;
3884 /* Explicit subroutine calls are prevented by the frontend but interface
3885 assignments can legitimately produce them. */
3886 case EXEC_ASSIGN_CALL:
3887 assign = gfc_trans_call (c, true, NULL_TREE, NULL_TREE, false);
3888 tmp = gfc_trans_nested_forall_loop (nested_forall_info, assign, 1);
3889 gfc_add_expr_to_block (&block, tmp);
3890 break;
3892 default:
3893 gcc_unreachable ();
3896 c = c->next;
3899 done:
3900 /* Restore the original index variables. */
3901 for (fa = code->ext.forall_iterator, n = 0; fa; fa = fa->next, n++)
3902 gfc_restore_sym (fa->var->symtree->n.sym, &saved_vars[n]);
3904 /* Free the space for var, start, end, step, varexpr. */
3905 free (var);
3906 free (start);
3907 free (end);
3908 free (step);
3909 free (varexpr);
3910 free (saved_vars);
3912 for (this_forall = info->this_loop; this_forall;)
3914 iter_info *next = this_forall->next;
3915 free (this_forall);
3916 this_forall = next;
3919 /* Free the space for this forall_info. */
3920 free (info);
3922 if (pmask)
3924 /* Free the temporary for the mask. */
3925 tmp = gfc_call_free (pmask);
3926 gfc_add_expr_to_block (&block, tmp);
3928 if (maskindex)
3929 pushdecl (maskindex);
3931 gfc_add_block_to_block (&pre, &block);
3932 gfc_add_block_to_block (&pre, &post);
3934 return gfc_finish_block (&pre);
3938 /* Translate the FORALL statement or construct. */
3940 tree gfc_trans_forall (gfc_code * code)
3942 return gfc_trans_forall_1 (code, NULL);
3946 /* Translate the DO CONCURRENT construct. */
3948 tree gfc_trans_do_concurrent (gfc_code * code)
3950 return gfc_trans_forall_1 (code, NULL);
3954 /* Evaluate the WHERE mask expression, copy its value to a temporary.
3955 If the WHERE construct is nested in FORALL, compute the overall temporary
3956 needed by the WHERE mask expression multiplied by the iterator number of
3957 the nested forall.
3958 ME is the WHERE mask expression.
3959 MASK is the current execution mask upon input, whose sense may or may
3960 not be inverted as specified by the INVERT argument.
3961 CMASK is the updated execution mask on output, or NULL if not required.
3962 PMASK is the pending execution mask on output, or NULL if not required.
3963 BLOCK is the block in which to place the condition evaluation loops. */
3965 static void
3966 gfc_evaluate_where_mask (gfc_expr * me, forall_info * nested_forall_info,
3967 tree mask, bool invert, tree cmask, tree pmask,
3968 tree mask_type, stmtblock_t * block)
3970 tree tmp, tmp1;
3971 gfc_ss *lss, *rss;
3972 gfc_loopinfo loop;
3973 stmtblock_t body, body1;
3974 tree count, cond, mtmp;
3975 gfc_se lse, rse;
3977 gfc_init_loopinfo (&loop);
3979 lss = gfc_walk_expr (me);
3980 rss = gfc_walk_expr (me);
3982 /* Variable to index the temporary. */
3983 count = gfc_create_var (gfc_array_index_type, "count");
3984 /* Initialize count. */
3985 gfc_add_modify (block, count, gfc_index_zero_node);
3987 gfc_start_block (&body);
3989 gfc_init_se (&rse, NULL);
3990 gfc_init_se (&lse, NULL);
3992 if (lss == gfc_ss_terminator)
3994 gfc_init_block (&body1);
3996 else
3998 /* Initialize the loop. */
3999 gfc_init_loopinfo (&loop);
4001 /* We may need LSS to determine the shape of the expression. */
4002 gfc_add_ss_to_loop (&loop, lss);
4003 gfc_add_ss_to_loop (&loop, rss);
4005 gfc_conv_ss_startstride (&loop);
4006 gfc_conv_loop_setup (&loop, &me->where);
4008 gfc_mark_ss_chain_used (rss, 1);
4009 /* Start the loop body. */
4010 gfc_start_scalarized_body (&loop, &body1);
4012 /* Translate the expression. */
4013 gfc_copy_loopinfo_to_se (&rse, &loop);
4014 rse.ss = rss;
4015 gfc_conv_expr (&rse, me);
4018 /* Variable to evaluate mask condition. */
4019 cond = gfc_create_var (mask_type, "cond");
4020 if (mask && (cmask || pmask))
4021 mtmp = gfc_create_var (mask_type, "mask");
4022 else mtmp = NULL_TREE;
4024 gfc_add_block_to_block (&body1, &lse.pre);
4025 gfc_add_block_to_block (&body1, &rse.pre);
4027 gfc_add_modify (&body1, cond, fold_convert (mask_type, rse.expr));
4029 if (mask && (cmask || pmask))
4031 tmp = gfc_build_array_ref (mask, count, NULL);
4032 if (invert)
4033 tmp = fold_build1_loc (input_location, TRUTH_NOT_EXPR, mask_type, tmp);
4034 gfc_add_modify (&body1, mtmp, tmp);
4037 if (cmask)
4039 tmp1 = gfc_build_array_ref (cmask, count, NULL);
4040 tmp = cond;
4041 if (mask)
4042 tmp = fold_build2_loc (input_location, TRUTH_AND_EXPR, mask_type,
4043 mtmp, tmp);
4044 gfc_add_modify (&body1, tmp1, tmp);
4047 if (pmask)
4049 tmp1 = gfc_build_array_ref (pmask, count, NULL);
4050 tmp = fold_build1_loc (input_location, TRUTH_NOT_EXPR, mask_type, cond);
4051 if (mask)
4052 tmp = fold_build2_loc (input_location, TRUTH_AND_EXPR, mask_type, mtmp,
4053 tmp);
4054 gfc_add_modify (&body1, tmp1, tmp);
4057 gfc_add_block_to_block (&body1, &lse.post);
4058 gfc_add_block_to_block (&body1, &rse.post);
4060 if (lss == gfc_ss_terminator)
4062 gfc_add_block_to_block (&body, &body1);
4064 else
4066 /* Increment count. */
4067 tmp1 = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
4068 count, gfc_index_one_node);
4069 gfc_add_modify (&body1, count, tmp1);
4071 /* Generate the copying loops. */
4072 gfc_trans_scalarizing_loops (&loop, &body1);
4074 gfc_add_block_to_block (&body, &loop.pre);
4075 gfc_add_block_to_block (&body, &loop.post);
4077 gfc_cleanup_loop (&loop);
4078 /* TODO: Reuse lss and rss when copying temp->lhs. Need to be careful
4079 as tree nodes in SS may not be valid in different scope. */
4082 tmp1 = gfc_finish_block (&body);
4083 /* If the WHERE construct is inside FORALL, fill the full temporary. */
4084 if (nested_forall_info != NULL)
4085 tmp1 = gfc_trans_nested_forall_loop (nested_forall_info, tmp1, 1);
4087 gfc_add_expr_to_block (block, tmp1);
4091 /* Translate an assignment statement in a WHERE statement or construct
4092 statement. The MASK expression is used to control which elements
4093 of EXPR1 shall be assigned. The sense of MASK is specified by
4094 INVERT. */
4096 static tree
4097 gfc_trans_where_assign (gfc_expr *expr1, gfc_expr *expr2,
4098 tree mask, bool invert,
4099 tree count1, tree count2,
4100 gfc_code *cnext)
4102 gfc_se lse;
4103 gfc_se rse;
4104 gfc_ss *lss;
4105 gfc_ss *lss_section;
4106 gfc_ss *rss;
4108 gfc_loopinfo loop;
4109 tree tmp;
4110 stmtblock_t block;
4111 stmtblock_t body;
4112 tree index, maskexpr;
4114 /* A defined assignment. */
4115 if (cnext && cnext->resolved_sym)
4116 return gfc_trans_call (cnext, true, mask, count1, invert);
4118 #if 0
4119 /* TODO: handle this special case.
4120 Special case a single function returning an array. */
4121 if (expr2->expr_type == EXPR_FUNCTION && expr2->rank > 0)
4123 tmp = gfc_trans_arrayfunc_assign (expr1, expr2);
4124 if (tmp)
4125 return tmp;
4127 #endif
4129 /* Assignment of the form lhs = rhs. */
4130 gfc_start_block (&block);
4132 gfc_init_se (&lse, NULL);
4133 gfc_init_se (&rse, NULL);
4135 /* Walk the lhs. */
4136 lss = gfc_walk_expr (expr1);
4137 rss = NULL;
4139 /* In each where-assign-stmt, the mask-expr and the variable being
4140 defined shall be arrays of the same shape. */
4141 gcc_assert (lss != gfc_ss_terminator);
4143 /* The assignment needs scalarization. */
4144 lss_section = lss;
4146 /* Find a non-scalar SS from the lhs. */
4147 while (lss_section != gfc_ss_terminator
4148 && lss_section->info->type != GFC_SS_SECTION)
4149 lss_section = lss_section->next;
4151 gcc_assert (lss_section != gfc_ss_terminator);
4153 /* Initialize the scalarizer. */
4154 gfc_init_loopinfo (&loop);
4156 /* Walk the rhs. */
4157 rss = gfc_walk_expr (expr2);
4158 if (rss == gfc_ss_terminator)
4160 /* The rhs is scalar. Add a ss for the expression. */
4161 rss = gfc_get_scalar_ss (gfc_ss_terminator, expr2);
4162 rss->info->where = 1;
4165 /* Associate the SS with the loop. */
4166 gfc_add_ss_to_loop (&loop, lss);
4167 gfc_add_ss_to_loop (&loop, rss);
4169 /* Calculate the bounds of the scalarization. */
4170 gfc_conv_ss_startstride (&loop);
4172 /* Resolve any data dependencies in the statement. */
4173 gfc_conv_resolve_dependencies (&loop, lss_section, rss);
4175 /* Setup the scalarizing loops. */
4176 gfc_conv_loop_setup (&loop, &expr2->where);
4178 /* Setup the gfc_se structures. */
4179 gfc_copy_loopinfo_to_se (&lse, &loop);
4180 gfc_copy_loopinfo_to_se (&rse, &loop);
4182 rse.ss = rss;
4183 gfc_mark_ss_chain_used (rss, 1);
4184 if (loop.temp_ss == NULL)
4186 lse.ss = lss;
4187 gfc_mark_ss_chain_used (lss, 1);
4189 else
4191 lse.ss = loop.temp_ss;
4192 gfc_mark_ss_chain_used (lss, 3);
4193 gfc_mark_ss_chain_used (loop.temp_ss, 3);
4196 /* Start the scalarized loop body. */
4197 gfc_start_scalarized_body (&loop, &body);
4199 /* Translate the expression. */
4200 gfc_conv_expr (&rse, expr2);
4201 if (lss != gfc_ss_terminator && loop.temp_ss != NULL)
4202 gfc_conv_tmp_array_ref (&lse);
4203 else
4204 gfc_conv_expr (&lse, expr1);
4206 /* Form the mask expression according to the mask. */
4207 index = count1;
4208 maskexpr = gfc_build_array_ref (mask, index, NULL);
4209 if (invert)
4210 maskexpr = fold_build1_loc (input_location, TRUTH_NOT_EXPR,
4211 TREE_TYPE (maskexpr), maskexpr);
4213 /* Use the scalar assignment as is. */
4214 tmp = gfc_trans_scalar_assign (&lse, &rse, expr1->ts,
4215 loop.temp_ss != NULL, false, true);
4217 tmp = build3_v (COND_EXPR, maskexpr, tmp, build_empty_stmt (input_location));
4219 gfc_add_expr_to_block (&body, tmp);
4221 if (lss == gfc_ss_terminator)
4223 /* Increment count1. */
4224 tmp = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
4225 count1, gfc_index_one_node);
4226 gfc_add_modify (&body, count1, tmp);
4228 /* Use the scalar assignment as is. */
4229 gfc_add_block_to_block (&block, &body);
4231 else
4233 gcc_assert (lse.ss == gfc_ss_terminator
4234 && rse.ss == gfc_ss_terminator);
4236 if (loop.temp_ss != NULL)
4238 /* Increment count1 before finish the main body of a scalarized
4239 expression. */
4240 tmp = fold_build2_loc (input_location, PLUS_EXPR,
4241 gfc_array_index_type, count1, gfc_index_one_node);
4242 gfc_add_modify (&body, count1, tmp);
4243 gfc_trans_scalarized_loop_boundary (&loop, &body);
4245 /* We need to copy the temporary to the actual lhs. */
4246 gfc_init_se (&lse, NULL);
4247 gfc_init_se (&rse, NULL);
4248 gfc_copy_loopinfo_to_se (&lse, &loop);
4249 gfc_copy_loopinfo_to_se (&rse, &loop);
4251 rse.ss = loop.temp_ss;
4252 lse.ss = lss;
4254 gfc_conv_tmp_array_ref (&rse);
4255 gfc_conv_expr (&lse, expr1);
4257 gcc_assert (lse.ss == gfc_ss_terminator
4258 && rse.ss == gfc_ss_terminator);
4260 /* Form the mask expression according to the mask tree list. */
4261 index = count2;
4262 maskexpr = gfc_build_array_ref (mask, index, NULL);
4263 if (invert)
4264 maskexpr = fold_build1_loc (input_location, TRUTH_NOT_EXPR,
4265 TREE_TYPE (maskexpr), maskexpr);
4267 /* Use the scalar assignment as is. */
4268 tmp = gfc_trans_scalar_assign (&lse, &rse, expr1->ts, false, false,
4269 true);
4270 tmp = build3_v (COND_EXPR, maskexpr, tmp,
4271 build_empty_stmt (input_location));
4272 gfc_add_expr_to_block (&body, tmp);
4274 /* Increment count2. */
4275 tmp = fold_build2_loc (input_location, PLUS_EXPR,
4276 gfc_array_index_type, count2,
4277 gfc_index_one_node);
4278 gfc_add_modify (&body, count2, tmp);
4280 else
4282 /* Increment count1. */
4283 tmp = fold_build2_loc (input_location, PLUS_EXPR,
4284 gfc_array_index_type, count1,
4285 gfc_index_one_node);
4286 gfc_add_modify (&body, count1, tmp);
4289 /* Generate the copying loops. */
4290 gfc_trans_scalarizing_loops (&loop, &body);
4292 /* Wrap the whole thing up. */
4293 gfc_add_block_to_block (&block, &loop.pre);
4294 gfc_add_block_to_block (&block, &loop.post);
4295 gfc_cleanup_loop (&loop);
4298 return gfc_finish_block (&block);
4302 /* Translate the WHERE construct or statement.
4303 This function can be called iteratively to translate the nested WHERE
4304 construct or statement.
4305 MASK is the control mask. */
4307 static void
4308 gfc_trans_where_2 (gfc_code * code, tree mask, bool invert,
4309 forall_info * nested_forall_info, stmtblock_t * block)
4311 stmtblock_t inner_size_body;
4312 tree inner_size, size;
4313 gfc_ss *lss, *rss;
4314 tree mask_type;
4315 gfc_expr *expr1;
4316 gfc_expr *expr2;
4317 gfc_code *cblock;
4318 gfc_code *cnext;
4319 tree tmp;
4320 tree cond;
4321 tree count1, count2;
4322 bool need_cmask;
4323 bool need_pmask;
4324 int need_temp;
4325 tree pcmask = NULL_TREE;
4326 tree ppmask = NULL_TREE;
4327 tree cmask = NULL_TREE;
4328 tree pmask = NULL_TREE;
4329 gfc_actual_arglist *arg;
4331 /* the WHERE statement or the WHERE construct statement. */
4332 cblock = code->block;
4334 /* As the mask array can be very big, prefer compact boolean types. */
4335 mask_type = gfc_get_logical_type (gfc_logical_kinds[0].kind);
4337 /* Determine which temporary masks are needed. */
4338 if (!cblock->block)
4340 /* One clause: No ELSEWHEREs. */
4341 need_cmask = (cblock->next != 0);
4342 need_pmask = false;
4344 else if (cblock->block->block)
4346 /* Three or more clauses: Conditional ELSEWHEREs. */
4347 need_cmask = true;
4348 need_pmask = true;
4350 else if (cblock->next)
4352 /* Two clauses, the first non-empty. */
4353 need_cmask = true;
4354 need_pmask = (mask != NULL_TREE
4355 && cblock->block->next != 0);
4357 else if (!cblock->block->next)
4359 /* Two clauses, both empty. */
4360 need_cmask = false;
4361 need_pmask = false;
4363 /* Two clauses, the first empty, the second non-empty. */
4364 else if (mask)
4366 need_cmask = (cblock->block->expr1 != 0);
4367 need_pmask = true;
4369 else
4371 need_cmask = true;
4372 need_pmask = false;
4375 if (need_cmask || need_pmask)
4377 /* Calculate the size of temporary needed by the mask-expr. */
4378 gfc_init_block (&inner_size_body);
4379 inner_size = compute_inner_temp_size (cblock->expr1, cblock->expr1,
4380 &inner_size_body, &lss, &rss);
4382 gfc_free_ss_chain (lss);
4383 gfc_free_ss_chain (rss);
4385 /* Calculate the total size of temporary needed. */
4386 size = compute_overall_iter_number (nested_forall_info, inner_size,
4387 &inner_size_body, block);
4389 /* Check whether the size is negative. */
4390 cond = fold_build2_loc (input_location, LE_EXPR, boolean_type_node, size,
4391 gfc_index_zero_node);
4392 size = fold_build3_loc (input_location, COND_EXPR, gfc_array_index_type,
4393 cond, gfc_index_zero_node, size);
4394 size = gfc_evaluate_now (size, block);
4396 /* Allocate temporary for WHERE mask if needed. */
4397 if (need_cmask)
4398 cmask = allocate_temp_for_forall_nest_1 (mask_type, size, block,
4399 &pcmask);
4401 /* Allocate temporary for !mask if needed. */
4402 if (need_pmask)
4403 pmask = allocate_temp_for_forall_nest_1 (mask_type, size, block,
4404 &ppmask);
4407 while (cblock)
4409 /* Each time around this loop, the where clause is conditional
4410 on the value of mask and invert, which are updated at the
4411 bottom of the loop. */
4413 /* Has mask-expr. */
4414 if (cblock->expr1)
4416 /* Ensure that the WHERE mask will be evaluated exactly once.
4417 If there are no statements in this WHERE/ELSEWHERE clause,
4418 then we don't need to update the control mask (cmask).
4419 If this is the last clause of the WHERE construct, then
4420 we don't need to update the pending control mask (pmask). */
4421 if (mask)
4422 gfc_evaluate_where_mask (cblock->expr1, nested_forall_info,
4423 mask, invert,
4424 cblock->next ? cmask : NULL_TREE,
4425 cblock->block ? pmask : NULL_TREE,
4426 mask_type, block);
4427 else
4428 gfc_evaluate_where_mask (cblock->expr1, nested_forall_info,
4429 NULL_TREE, false,
4430 (cblock->next || cblock->block)
4431 ? cmask : NULL_TREE,
4432 NULL_TREE, mask_type, block);
4434 invert = false;
4436 /* It's a final elsewhere-stmt. No mask-expr is present. */
4437 else
4438 cmask = mask;
4440 /* The body of this where clause are controlled by cmask with
4441 sense specified by invert. */
4443 /* Get the assignment statement of a WHERE statement, or the first
4444 statement in where-body-construct of a WHERE construct. */
4445 cnext = cblock->next;
4446 while (cnext)
4448 switch (cnext->op)
4450 /* WHERE assignment statement. */
4451 case EXEC_ASSIGN_CALL:
4453 arg = cnext->ext.actual;
4454 expr1 = expr2 = NULL;
4455 for (; arg; arg = arg->next)
4457 if (!arg->expr)
4458 continue;
4459 if (expr1 == NULL)
4460 expr1 = arg->expr;
4461 else
4462 expr2 = arg->expr;
4464 goto evaluate;
4466 case EXEC_ASSIGN:
4467 expr1 = cnext->expr1;
4468 expr2 = cnext->expr2;
4469 evaluate:
4470 if (nested_forall_info != NULL)
4472 need_temp = gfc_check_dependency (expr1, expr2, 0);
4473 if (need_temp && cnext->op != EXEC_ASSIGN_CALL)
4474 gfc_trans_assign_need_temp (expr1, expr2,
4475 cmask, invert,
4476 nested_forall_info, block);
4477 else
4479 /* Variables to control maskexpr. */
4480 count1 = gfc_create_var (gfc_array_index_type, "count1");
4481 count2 = gfc_create_var (gfc_array_index_type, "count2");
4482 gfc_add_modify (block, count1, gfc_index_zero_node);
4483 gfc_add_modify (block, count2, gfc_index_zero_node);
4485 tmp = gfc_trans_where_assign (expr1, expr2,
4486 cmask, invert,
4487 count1, count2,
4488 cnext);
4490 tmp = gfc_trans_nested_forall_loop (nested_forall_info,
4491 tmp, 1);
4492 gfc_add_expr_to_block (block, tmp);
4495 else
4497 /* Variables to control maskexpr. */
4498 count1 = gfc_create_var (gfc_array_index_type, "count1");
4499 count2 = gfc_create_var (gfc_array_index_type, "count2");
4500 gfc_add_modify (block, count1, gfc_index_zero_node);
4501 gfc_add_modify (block, count2, gfc_index_zero_node);
4503 tmp = gfc_trans_where_assign (expr1, expr2,
4504 cmask, invert,
4505 count1, count2,
4506 cnext);
4507 gfc_add_expr_to_block (block, tmp);
4510 break;
4512 /* WHERE or WHERE construct is part of a where-body-construct. */
4513 case EXEC_WHERE:
4514 gfc_trans_where_2 (cnext, cmask, invert,
4515 nested_forall_info, block);
4516 break;
4518 default:
4519 gcc_unreachable ();
4522 /* The next statement within the same where-body-construct. */
4523 cnext = cnext->next;
4525 /* The next masked-elsewhere-stmt, elsewhere-stmt, or end-where-stmt. */
4526 cblock = cblock->block;
4527 if (mask == NULL_TREE)
4529 /* If we're the initial WHERE, we can simply invert the sense
4530 of the current mask to obtain the "mask" for the remaining
4531 ELSEWHEREs. */
4532 invert = true;
4533 mask = cmask;
4535 else
4537 /* Otherwise, for nested WHERE's we need to use the pending mask. */
4538 invert = false;
4539 mask = pmask;
4543 /* If we allocated a pending mask array, deallocate it now. */
4544 if (ppmask)
4546 tmp = gfc_call_free (ppmask);
4547 gfc_add_expr_to_block (block, tmp);
4550 /* If we allocated a current mask array, deallocate it now. */
4551 if (pcmask)
4553 tmp = gfc_call_free (pcmask);
4554 gfc_add_expr_to_block (block, tmp);
4558 /* Translate a simple WHERE construct or statement without dependencies.
4559 CBLOCK is the "then" clause of the WHERE statement, where CBLOCK->EXPR
4560 is the mask condition, and EBLOCK if non-NULL is the "else" clause.
4561 Currently both CBLOCK and EBLOCK are restricted to single assignments. */
4563 static tree
4564 gfc_trans_where_3 (gfc_code * cblock, gfc_code * eblock)
4566 stmtblock_t block, body;
4567 gfc_expr *cond, *tdst, *tsrc, *edst, *esrc;
4568 tree tmp, cexpr, tstmt, estmt;
4569 gfc_ss *css, *tdss, *tsss;
4570 gfc_se cse, tdse, tsse, edse, esse;
4571 gfc_loopinfo loop;
4572 gfc_ss *edss = 0;
4573 gfc_ss *esss = 0;
4575 /* Allow the scalarizer to workshare simple where loops. */
4576 if (ompws_flags & OMPWS_WORKSHARE_FLAG)
4577 ompws_flags |= OMPWS_SCALARIZER_WS;
4579 cond = cblock->expr1;
4580 tdst = cblock->next->expr1;
4581 tsrc = cblock->next->expr2;
4582 edst = eblock ? eblock->next->expr1 : NULL;
4583 esrc = eblock ? eblock->next->expr2 : NULL;
4585 gfc_start_block (&block);
4586 gfc_init_loopinfo (&loop);
4588 /* Handle the condition. */
4589 gfc_init_se (&cse, NULL);
4590 css = gfc_walk_expr (cond);
4591 gfc_add_ss_to_loop (&loop, css);
4593 /* Handle the then-clause. */
4594 gfc_init_se (&tdse, NULL);
4595 gfc_init_se (&tsse, NULL);
4596 tdss = gfc_walk_expr (tdst);
4597 tsss = gfc_walk_expr (tsrc);
4598 if (tsss == gfc_ss_terminator)
4600 tsss = gfc_get_scalar_ss (gfc_ss_terminator, tsrc);
4601 tsss->info->where = 1;
4603 gfc_add_ss_to_loop (&loop, tdss);
4604 gfc_add_ss_to_loop (&loop, tsss);
4606 if (eblock)
4608 /* Handle the else clause. */
4609 gfc_init_se (&edse, NULL);
4610 gfc_init_se (&esse, NULL);
4611 edss = gfc_walk_expr (edst);
4612 esss = gfc_walk_expr (esrc);
4613 if (esss == gfc_ss_terminator)
4615 esss = gfc_get_scalar_ss (gfc_ss_terminator, esrc);
4616 esss->info->where = 1;
4618 gfc_add_ss_to_loop (&loop, edss);
4619 gfc_add_ss_to_loop (&loop, esss);
4622 gfc_conv_ss_startstride (&loop);
4623 gfc_conv_loop_setup (&loop, &tdst->where);
4625 gfc_mark_ss_chain_used (css, 1);
4626 gfc_mark_ss_chain_used (tdss, 1);
4627 gfc_mark_ss_chain_used (tsss, 1);
4628 if (eblock)
4630 gfc_mark_ss_chain_used (edss, 1);
4631 gfc_mark_ss_chain_used (esss, 1);
4634 gfc_start_scalarized_body (&loop, &body);
4636 gfc_copy_loopinfo_to_se (&cse, &loop);
4637 gfc_copy_loopinfo_to_se (&tdse, &loop);
4638 gfc_copy_loopinfo_to_se (&tsse, &loop);
4639 cse.ss = css;
4640 tdse.ss = tdss;
4641 tsse.ss = tsss;
4642 if (eblock)
4644 gfc_copy_loopinfo_to_se (&edse, &loop);
4645 gfc_copy_loopinfo_to_se (&esse, &loop);
4646 edse.ss = edss;
4647 esse.ss = esss;
4650 gfc_conv_expr (&cse, cond);
4651 gfc_add_block_to_block (&body, &cse.pre);
4652 cexpr = cse.expr;
4654 gfc_conv_expr (&tsse, tsrc);
4655 if (tdss != gfc_ss_terminator && loop.temp_ss != NULL)
4656 gfc_conv_tmp_array_ref (&tdse);
4657 else
4658 gfc_conv_expr (&tdse, tdst);
4660 if (eblock)
4662 gfc_conv_expr (&esse, esrc);
4663 if (edss != gfc_ss_terminator && loop.temp_ss != NULL)
4664 gfc_conv_tmp_array_ref (&edse);
4665 else
4666 gfc_conv_expr (&edse, edst);
4669 tstmt = gfc_trans_scalar_assign (&tdse, &tsse, tdst->ts, false, false, true);
4670 estmt = eblock ? gfc_trans_scalar_assign (&edse, &esse, edst->ts, false,
4671 false, true)
4672 : build_empty_stmt (input_location);
4673 tmp = build3_v (COND_EXPR, cexpr, tstmt, estmt);
4674 gfc_add_expr_to_block (&body, tmp);
4675 gfc_add_block_to_block (&body, &cse.post);
4677 gfc_trans_scalarizing_loops (&loop, &body);
4678 gfc_add_block_to_block (&block, &loop.pre);
4679 gfc_add_block_to_block (&block, &loop.post);
4680 gfc_cleanup_loop (&loop);
4682 return gfc_finish_block (&block);
4685 /* As the WHERE or WHERE construct statement can be nested, we call
4686 gfc_trans_where_2 to do the translation, and pass the initial
4687 NULL values for both the control mask and the pending control mask. */
4689 tree
4690 gfc_trans_where (gfc_code * code)
4692 stmtblock_t block;
4693 gfc_code *cblock;
4694 gfc_code *eblock;
4696 cblock = code->block;
4697 if (cblock->next
4698 && cblock->next->op == EXEC_ASSIGN
4699 && !cblock->next->next)
4701 eblock = cblock->block;
4702 if (!eblock)
4704 /* A simple "WHERE (cond) x = y" statement or block is
4705 dependence free if cond is not dependent upon writing x,
4706 and the source y is unaffected by the destination x. */
4707 if (!gfc_check_dependency (cblock->next->expr1,
4708 cblock->expr1, 0)
4709 && !gfc_check_dependency (cblock->next->expr1,
4710 cblock->next->expr2, 0))
4711 return gfc_trans_where_3 (cblock, NULL);
4713 else if (!eblock->expr1
4714 && !eblock->block
4715 && eblock->next
4716 && eblock->next->op == EXEC_ASSIGN
4717 && !eblock->next->next)
4719 /* A simple "WHERE (cond) x1 = y1 ELSEWHERE x2 = y2 ENDWHERE"
4720 block is dependence free if cond is not dependent on writes
4721 to x1 and x2, y1 is not dependent on writes to x2, and y2
4722 is not dependent on writes to x1, and both y's are not
4723 dependent upon their own x's. In addition to this, the
4724 final two dependency checks below exclude all but the same
4725 array reference if the where and elswhere destinations
4726 are the same. In short, this is VERY conservative and this
4727 is needed because the two loops, required by the standard
4728 are coalesced in gfc_trans_where_3. */
4729 if (!gfc_check_dependency(cblock->next->expr1,
4730 cblock->expr1, 0)
4731 && !gfc_check_dependency(eblock->next->expr1,
4732 cblock->expr1, 0)
4733 && !gfc_check_dependency(cblock->next->expr1,
4734 eblock->next->expr2, 1)
4735 && !gfc_check_dependency(eblock->next->expr1,
4736 cblock->next->expr2, 1)
4737 && !gfc_check_dependency(cblock->next->expr1,
4738 cblock->next->expr2, 1)
4739 && !gfc_check_dependency(eblock->next->expr1,
4740 eblock->next->expr2, 1)
4741 && !gfc_check_dependency(cblock->next->expr1,
4742 eblock->next->expr1, 0)
4743 && !gfc_check_dependency(eblock->next->expr1,
4744 cblock->next->expr1, 0))
4745 return gfc_trans_where_3 (cblock, eblock);
4749 gfc_start_block (&block);
4751 gfc_trans_where_2 (code, NULL, false, NULL, &block);
4753 return gfc_finish_block (&block);
4757 /* CYCLE a DO loop. The label decl has already been created by
4758 gfc_trans_do(), it's in TREE_PURPOSE (backend_decl) of the gfc_code
4759 node at the head of the loop. We must mark the label as used. */
4761 tree
4762 gfc_trans_cycle (gfc_code * code)
4764 tree cycle_label;
4766 cycle_label = code->ext.which_construct->cycle_label;
4767 gcc_assert (cycle_label);
4769 TREE_USED (cycle_label) = 1;
4770 return build1_v (GOTO_EXPR, cycle_label);
4774 /* EXIT a DO loop. Similar to CYCLE, but now the label is in
4775 TREE_VALUE (backend_decl) of the gfc_code node at the head of the
4776 loop. */
4778 tree
4779 gfc_trans_exit (gfc_code * code)
4781 tree exit_label;
4783 exit_label = code->ext.which_construct->exit_label;
4784 gcc_assert (exit_label);
4786 TREE_USED (exit_label) = 1;
4787 return build1_v (GOTO_EXPR, exit_label);
4791 /* Translate the ALLOCATE statement. */
4793 tree
4794 gfc_trans_allocate (gfc_code * code)
4796 gfc_alloc *al;
4797 gfc_expr *e;
4798 gfc_expr *expr;
4799 gfc_se se;
4800 tree tmp;
4801 tree parm;
4802 tree stat;
4803 tree errmsg;
4804 tree errlen;
4805 tree label_errmsg;
4806 tree label_finish;
4807 tree memsz;
4808 tree expr3;
4809 tree slen3;
4810 stmtblock_t block;
4811 stmtblock_t post;
4812 gfc_expr *sz;
4813 gfc_se se_sz;
4814 tree class_expr;
4815 tree nelems;
4816 tree memsize = NULL_TREE;
4817 tree classexpr = NULL_TREE;
4819 if (!code->ext.alloc.list)
4820 return NULL_TREE;
4822 stat = tmp = memsz = NULL_TREE;
4823 label_errmsg = label_finish = errmsg = errlen = NULL_TREE;
4825 gfc_init_block (&block);
4826 gfc_init_block (&post);
4828 /* STAT= (and maybe ERRMSG=) is present. */
4829 if (code->expr1)
4831 /* STAT=. */
4832 tree gfc_int4_type_node = gfc_get_int_type (4);
4833 stat = gfc_create_var (gfc_int4_type_node, "stat");
4835 /* ERRMSG= only makes sense with STAT=. */
4836 if (code->expr2)
4838 gfc_init_se (&se, NULL);
4839 se.want_pointer = 1;
4840 gfc_conv_expr_lhs (&se, code->expr2);
4841 errmsg = se.expr;
4842 errlen = se.string_length;
4844 else
4846 errmsg = null_pointer_node;
4847 errlen = build_int_cst (gfc_charlen_type_node, 0);
4850 /* GOTO destinations. */
4851 label_errmsg = gfc_build_label_decl (NULL_TREE);
4852 label_finish = gfc_build_label_decl (NULL_TREE);
4853 TREE_USED (label_finish) = 0;
4856 expr3 = NULL_TREE;
4857 slen3 = NULL_TREE;
4859 for (al = code->ext.alloc.list; al != NULL; al = al->next)
4861 expr = gfc_copy_expr (al->expr);
4863 if (expr->ts.type == BT_CLASS)
4864 gfc_add_data_component (expr);
4866 gfc_init_se (&se, NULL);
4868 se.want_pointer = 1;
4869 se.descriptor_only = 1;
4870 gfc_conv_expr (&se, expr);
4872 /* Evaluate expr3 just once if not a variable. */
4873 if (al == code->ext.alloc.list
4874 && al->expr->ts.type == BT_CLASS
4875 && code->expr3
4876 && code->expr3->ts.type == BT_CLASS
4877 && code->expr3->expr_type != EXPR_VARIABLE)
4879 gfc_init_se (&se_sz, NULL);
4880 gfc_conv_expr_reference (&se_sz, code->expr3);
4881 gfc_conv_class_to_class (&se_sz, code->expr3,
4882 code->expr3->ts, false);
4883 gfc_add_block_to_block (&se.pre, &se_sz.pre);
4884 gfc_add_block_to_block (&se.post, &se_sz.post);
4885 classexpr = build_fold_indirect_ref_loc (input_location,
4886 se_sz.expr);
4887 classexpr = gfc_evaluate_now (classexpr, &se.pre);
4888 memsize = gfc_vtable_size_get (classexpr);
4889 memsize = fold_convert (sizetype, memsize);
4892 memsz = memsize;
4893 class_expr = classexpr;
4895 nelems = NULL_TREE;
4896 if (!gfc_array_allocate (&se, expr, stat, errmsg, errlen, label_finish,
4897 memsz, &nelems, code->expr3))
4899 /* A scalar or derived type. */
4901 /* Determine allocate size. */
4902 if (al->expr->ts.type == BT_CLASS
4903 && code->expr3
4904 && memsz == NULL_TREE)
4906 if (code->expr3->ts.type == BT_CLASS)
4908 sz = gfc_copy_expr (code->expr3);
4909 gfc_add_vptr_component (sz);
4910 gfc_add_size_component (sz);
4911 gfc_init_se (&se_sz, NULL);
4912 gfc_conv_expr (&se_sz, sz);
4913 gfc_free_expr (sz);
4914 memsz = se_sz.expr;
4916 else
4917 memsz = TYPE_SIZE_UNIT (gfc_typenode_for_spec (&code->expr3->ts));
4919 else if (al->expr->ts.type == BT_CHARACTER
4920 && al->expr->ts.deferred && code->expr3)
4922 if (!code->expr3->ts.u.cl->backend_decl)
4924 /* Convert and use the length expression. */
4925 gfc_init_se (&se_sz, NULL);
4926 if (code->expr3->expr_type == EXPR_VARIABLE
4927 || code->expr3->expr_type == EXPR_CONSTANT)
4929 gfc_conv_expr (&se_sz, code->expr3);
4930 gfc_add_block_to_block (&se.pre, &se_sz.pre);
4931 se_sz.string_length
4932 = gfc_evaluate_now (se_sz.string_length, &se.pre);
4933 gfc_add_block_to_block (&se.pre, &se_sz.post);
4934 memsz = se_sz.string_length;
4936 else if (code->expr3->mold
4937 && code->expr3->ts.u.cl
4938 && code->expr3->ts.u.cl->length)
4940 gfc_conv_expr (&se_sz, code->expr3->ts.u.cl->length);
4941 gfc_add_block_to_block (&se.pre, &se_sz.pre);
4942 se_sz.expr = gfc_evaluate_now (se_sz.expr, &se.pre);
4943 gfc_add_block_to_block (&se.pre, &se_sz.post);
4944 memsz = se_sz.expr;
4946 else
4948 /* This is would be inefficient and possibly could
4949 generate wrong code if the result were not stored
4950 in expr3/slen3. */
4951 if (slen3 == NULL_TREE)
4953 gfc_conv_expr (&se_sz, code->expr3);
4954 gfc_add_block_to_block (&se.pre, &se_sz.pre);
4955 expr3 = gfc_evaluate_now (se_sz.expr, &se.pre);
4956 gfc_add_block_to_block (&post, &se_sz.post);
4957 slen3 = gfc_evaluate_now (se_sz.string_length,
4958 &se.pre);
4960 memsz = slen3;
4963 else
4964 /* Otherwise use the stored string length. */
4965 memsz = code->expr3->ts.u.cl->backend_decl;
4966 tmp = al->expr->ts.u.cl->backend_decl;
4968 /* Store the string length. */
4969 if (tmp && TREE_CODE (tmp) == VAR_DECL)
4970 gfc_add_modify (&se.pre, tmp, fold_convert (TREE_TYPE (tmp),
4971 memsz));
4973 /* Convert to size in bytes, using the character KIND. */
4974 tmp = TREE_TYPE (gfc_typenode_for_spec (&al->expr->ts));
4975 tmp = TYPE_SIZE_UNIT (tmp);
4976 memsz = fold_build2_loc (input_location, MULT_EXPR,
4977 TREE_TYPE (tmp), tmp,
4978 fold_convert (TREE_TYPE (tmp), memsz));
4980 else if (al->expr->ts.type == BT_CHARACTER && al->expr->ts.deferred)
4982 gcc_assert (code->ext.alloc.ts.u.cl && code->ext.alloc.ts.u.cl->length);
4983 gfc_init_se (&se_sz, NULL);
4984 gfc_conv_expr (&se_sz, code->ext.alloc.ts.u.cl->length);
4985 gfc_add_block_to_block (&se.pre, &se_sz.pre);
4986 se_sz.expr = gfc_evaluate_now (se_sz.expr, &se.pre);
4987 gfc_add_block_to_block (&se.pre, &se_sz.post);
4988 /* Store the string length. */
4989 tmp = al->expr->ts.u.cl->backend_decl;
4990 gfc_add_modify (&se.pre, tmp, fold_convert (TREE_TYPE (tmp),
4991 se_sz.expr));
4992 tmp = TREE_TYPE (gfc_typenode_for_spec (&code->ext.alloc.ts));
4993 tmp = TYPE_SIZE_UNIT (tmp);
4994 memsz = fold_build2_loc (input_location, MULT_EXPR,
4995 TREE_TYPE (tmp), tmp,
4996 fold_convert (TREE_TYPE (se_sz.expr),
4997 se_sz.expr));
4999 else if (code->ext.alloc.ts.type != BT_UNKNOWN)
5000 memsz = TYPE_SIZE_UNIT (gfc_typenode_for_spec (&code->ext.alloc.ts));
5001 else if (memsz == NULL_TREE)
5002 memsz = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (se.expr)));
5004 if (expr->ts.type == BT_CHARACTER && memsz == NULL_TREE)
5006 memsz = se.string_length;
5008 /* Convert to size in bytes, using the character KIND. */
5009 tmp = TREE_TYPE (gfc_typenode_for_spec (&code->ext.alloc.ts));
5010 tmp = TYPE_SIZE_UNIT (tmp);
5011 memsz = fold_build2_loc (input_location, MULT_EXPR,
5012 TREE_TYPE (tmp), tmp,
5013 fold_convert (TREE_TYPE (tmp), memsz));
5016 /* Allocate - for non-pointers with re-alloc checking. */
5017 if (gfc_expr_attr (expr).allocatable)
5018 gfc_allocate_allocatable (&se.pre, se.expr, memsz, NULL_TREE,
5019 stat, errmsg, errlen, label_finish, expr);
5020 else
5021 gfc_allocate_using_malloc (&se.pre, se.expr, memsz, stat);
5023 if (al->expr->ts.type == BT_DERIVED
5024 && expr->ts.u.derived->attr.alloc_comp)
5026 tmp = build_fold_indirect_ref_loc (input_location, se.expr);
5027 tmp = gfc_nullify_alloc_comp (expr->ts.u.derived, tmp, 0);
5028 gfc_add_expr_to_block (&se.pre, tmp);
5030 else if (al->expr->ts.type == BT_CLASS)
5032 /* With class objects, it is best to play safe and null the
5033 memory because we cannot know if dynamic types have allocatable
5034 components or not. */
5035 tmp = build_call_expr_loc (input_location,
5036 builtin_decl_explicit (BUILT_IN_MEMSET),
5037 3, se.expr, integer_zero_node, memsz);
5038 gfc_add_expr_to_block (&se.pre, tmp);
5042 gfc_add_block_to_block (&block, &se.pre);
5044 /* Error checking -- Note: ERRMSG only makes sense with STAT. */
5045 if (code->expr1)
5047 tmp = build1_v (GOTO_EXPR, label_errmsg);
5048 parm = fold_build2_loc (input_location, NE_EXPR,
5049 boolean_type_node, stat,
5050 build_int_cst (TREE_TYPE (stat), 0));
5051 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
5052 gfc_unlikely (parm), tmp,
5053 build_empty_stmt (input_location));
5054 gfc_add_expr_to_block (&block, tmp);
5057 /* We need the vptr of CLASS objects to be initialized. */
5058 e = gfc_copy_expr (al->expr);
5059 if (e->ts.type == BT_CLASS)
5061 gfc_expr *lhs, *rhs;
5062 gfc_se lse;
5064 lhs = gfc_expr_to_initialize (e);
5065 gfc_add_vptr_component (lhs);
5067 if (class_expr != NULL_TREE)
5069 /* Polymorphic SOURCE: VPTR must be determined at run time. */
5070 gfc_init_se (&lse, NULL);
5071 lse.want_pointer = 1;
5072 gfc_conv_expr (&lse, lhs);
5073 tmp = gfc_class_vptr_get (class_expr);
5074 gfc_add_modify (&block, lse.expr,
5075 fold_convert (TREE_TYPE (lse.expr), tmp));
5077 else if (code->expr3 && code->expr3->ts.type == BT_CLASS)
5079 /* Polymorphic SOURCE: VPTR must be determined at run time. */
5080 rhs = gfc_copy_expr (code->expr3);
5081 gfc_add_vptr_component (rhs);
5082 tmp = gfc_trans_pointer_assignment (lhs, rhs);
5083 gfc_add_expr_to_block (&block, tmp);
5084 gfc_free_expr (rhs);
5085 rhs = gfc_expr_to_initialize (e);
5087 else
5089 /* VPTR is fixed at compile time. */
5090 gfc_symbol *vtab;
5091 gfc_typespec *ts;
5092 if (code->expr3)
5093 ts = &code->expr3->ts;
5094 else if (e->ts.type == BT_DERIVED)
5095 ts = &e->ts;
5096 else if (code->ext.alloc.ts.type == BT_DERIVED)
5097 ts = &code->ext.alloc.ts;
5098 else if (e->ts.type == BT_CLASS)
5099 ts = &CLASS_DATA (e)->ts;
5100 else
5101 ts = &e->ts;
5103 if (ts->type == BT_DERIVED)
5105 vtab = gfc_find_derived_vtab (ts->u.derived);
5106 gcc_assert (vtab);
5107 gfc_init_se (&lse, NULL);
5108 lse.want_pointer = 1;
5109 gfc_conv_expr (&lse, lhs);
5110 tmp = gfc_build_addr_expr (NULL_TREE,
5111 gfc_get_symbol_decl (vtab));
5112 gfc_add_modify (&block, lse.expr,
5113 fold_convert (TREE_TYPE (lse.expr), tmp));
5116 gfc_free_expr (lhs);
5119 gfc_free_expr (e);
5121 if (code->expr3 && !code->expr3->mold)
5123 /* Initialization via SOURCE block
5124 (or static default initializer). */
5125 gfc_expr *rhs = gfc_copy_expr (code->expr3);
5126 if (class_expr != NULL_TREE)
5128 tree to;
5129 to = TREE_OPERAND (se.expr, 0);
5131 tmp = gfc_copy_class_to_class (class_expr, to, nelems);
5133 else if (al->expr->ts.type == BT_CLASS)
5135 gfc_actual_arglist *actual;
5136 gfc_expr *ppc;
5137 gfc_code *ppc_code;
5138 gfc_ref *dataref;
5140 /* Do a polymorphic deep copy. */
5141 actual = gfc_get_actual_arglist ();
5142 actual->expr = gfc_copy_expr (rhs);
5143 if (rhs->ts.type == BT_CLASS)
5144 gfc_add_data_component (actual->expr);
5145 actual->next = gfc_get_actual_arglist ();
5146 actual->next->expr = gfc_copy_expr (al->expr);
5147 actual->next->expr->ts.type = BT_CLASS;
5148 gfc_add_data_component (actual->next->expr);
5150 dataref = actual->next->expr->ref;
5151 /* Make sure we go up through the reference chain to
5152 the _data reference, where the arrayspec is found. */
5153 while (dataref->next && dataref->next->type != REF_ARRAY)
5154 dataref = dataref->next;
5156 if (dataref->u.c.component->as)
5158 int dim;
5159 gfc_expr *temp;
5160 gfc_ref *ref = dataref->next;
5161 ref->u.ar.type = AR_SECTION;
5162 /* We have to set up the array reference to give ranges
5163 in all dimensions and ensure that the end and stride
5164 are set so that the copy can be scalarized. */
5165 dim = 0;
5166 for (; dim < dataref->u.c.component->as->rank; dim++)
5168 ref->u.ar.dimen_type[dim] = DIMEN_RANGE;
5169 if (ref->u.ar.end[dim] == NULL)
5171 ref->u.ar.end[dim] = ref->u.ar.start[dim];
5172 temp = gfc_get_int_expr (gfc_default_integer_kind,
5173 &al->expr->where, 1);
5174 ref->u.ar.start[dim] = temp;
5176 temp = gfc_subtract (gfc_copy_expr (ref->u.ar.end[dim]),
5177 gfc_copy_expr (ref->u.ar.start[dim]));
5178 temp = gfc_add (gfc_get_int_expr (gfc_default_integer_kind,
5179 &al->expr->where, 1),
5180 temp);
5183 if (rhs->ts.type == BT_CLASS)
5185 ppc = gfc_copy_expr (rhs);
5186 gfc_add_vptr_component (ppc);
5188 else
5189 ppc = gfc_lval_expr_from_sym
5190 (gfc_find_derived_vtab (rhs->ts.u.derived));
5191 gfc_add_component_ref (ppc, "_copy");
5193 ppc_code = gfc_get_code ();
5194 ppc_code->resolved_sym = ppc->symtree->n.sym;
5195 /* Although '_copy' is set to be elemental in class.c, it is
5196 not staying that way. Find out why, sometime.... */
5197 ppc_code->resolved_sym->attr.elemental = 1;
5198 ppc_code->ext.actual = actual;
5199 ppc_code->expr1 = ppc;
5200 ppc_code->op = EXEC_CALL;
5201 /* Since '_copy' is elemental, the scalarizer will take care
5202 of arrays in gfc_trans_call. */
5203 tmp = gfc_trans_call (ppc_code, true, NULL, NULL, false);
5204 gfc_free_statements (ppc_code);
5206 else if (expr3 != NULL_TREE)
5208 tmp = build_fold_indirect_ref_loc (input_location, se.expr);
5209 gfc_trans_string_copy (&block, slen3, tmp, code->expr3->ts.kind,
5210 slen3, expr3, code->expr3->ts.kind);
5211 tmp = NULL_TREE;
5213 else
5215 /* Switch off automatic reallocation since we have just done
5216 the ALLOCATE. */
5217 int realloc_lhs = gfc_option.flag_realloc_lhs;
5218 gfc_option.flag_realloc_lhs = 0;
5219 tmp = gfc_trans_assignment (gfc_expr_to_initialize (expr),
5220 rhs, false, false);
5221 gfc_option.flag_realloc_lhs = realloc_lhs;
5223 gfc_free_expr (rhs);
5224 gfc_add_expr_to_block (&block, tmp);
5226 else if (code->expr3 && code->expr3->mold
5227 && code->expr3->ts.type == BT_CLASS)
5229 /* Since the _vptr has already been assigned to the allocate
5230 object, we can use gfc_copy_class_to_class in its
5231 initialization mode. */
5232 tmp = TREE_OPERAND (se.expr, 0);
5233 tmp = gfc_copy_class_to_class (NULL_TREE, tmp, nelems);
5234 gfc_add_expr_to_block (&block, tmp);
5237 gfc_free_expr (expr);
5240 /* STAT. */
5241 if (code->expr1)
5243 tmp = build1_v (LABEL_EXPR, label_errmsg);
5244 gfc_add_expr_to_block (&block, tmp);
5247 /* ERRMSG - only useful if STAT is present. */
5248 if (code->expr1 && code->expr2)
5250 const char *msg = "Attempt to allocate an allocated object";
5251 tree slen, dlen, errmsg_str;
5252 stmtblock_t errmsg_block;
5254 gfc_init_block (&errmsg_block);
5256 errmsg_str = gfc_create_var (pchar_type_node, "ERRMSG");
5257 gfc_add_modify (&errmsg_block, errmsg_str,
5258 gfc_build_addr_expr (pchar_type_node,
5259 gfc_build_localized_cstring_const (msg)));
5261 slen = build_int_cst (gfc_charlen_type_node, ((int) strlen (msg)));
5262 dlen = gfc_get_expr_charlen (code->expr2);
5263 slen = fold_build2_loc (input_location, MIN_EXPR, TREE_TYPE (slen), dlen,
5264 slen);
5266 gfc_trans_string_copy (&errmsg_block, dlen, errmsg, code->expr2->ts.kind,
5267 slen, errmsg_str, gfc_default_character_kind);
5268 dlen = gfc_finish_block (&errmsg_block);
5270 tmp = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, stat,
5271 build_int_cst (TREE_TYPE (stat), 0));
5273 tmp = build3_v (COND_EXPR, tmp, dlen, build_empty_stmt (input_location));
5275 gfc_add_expr_to_block (&block, tmp);
5278 /* STAT block. */
5279 if (code->expr1)
5281 if (TREE_USED (label_finish))
5283 tmp = build1_v (LABEL_EXPR, label_finish);
5284 gfc_add_expr_to_block (&block, tmp);
5287 gfc_init_se (&se, NULL);
5288 gfc_conv_expr_lhs (&se, code->expr1);
5289 tmp = convert (TREE_TYPE (se.expr), stat);
5290 gfc_add_modify (&block, se.expr, tmp);
5293 gfc_add_block_to_block (&block, &se.post);
5294 gfc_add_block_to_block (&block, &post);
5296 return gfc_finish_block (&block);
5300 /* Translate a DEALLOCATE statement. */
5302 tree
5303 gfc_trans_deallocate (gfc_code *code)
5305 gfc_se se;
5306 gfc_alloc *al;
5307 tree apstat, pstat, stat, errmsg, errlen, tmp;
5308 tree label_finish, label_errmsg;
5309 stmtblock_t block;
5311 pstat = apstat = stat = errmsg = errlen = tmp = NULL_TREE;
5312 label_finish = label_errmsg = NULL_TREE;
5314 gfc_start_block (&block);
5316 /* Count the number of failed deallocations. If deallocate() was
5317 called with STAT= , then set STAT to the count. If deallocate
5318 was called with ERRMSG, then set ERRMG to a string. */
5319 if (code->expr1)
5321 tree gfc_int4_type_node = gfc_get_int_type (4);
5323 stat = gfc_create_var (gfc_int4_type_node, "stat");
5324 pstat = gfc_build_addr_expr (NULL_TREE, stat);
5326 /* GOTO destinations. */
5327 label_errmsg = gfc_build_label_decl (NULL_TREE);
5328 label_finish = gfc_build_label_decl (NULL_TREE);
5329 TREE_USED (label_finish) = 0;
5332 /* Set ERRMSG - only needed if STAT is available. */
5333 if (code->expr1 && code->expr2)
5335 gfc_init_se (&se, NULL);
5336 se.want_pointer = 1;
5337 gfc_conv_expr_lhs (&se, code->expr2);
5338 errmsg = se.expr;
5339 errlen = se.string_length;
5342 for (al = code->ext.alloc.list; al != NULL; al = al->next)
5344 gfc_expr *expr = gfc_copy_expr (al->expr);
5345 gcc_assert (expr->expr_type == EXPR_VARIABLE);
5347 if (expr->ts.type == BT_CLASS)
5348 gfc_add_data_component (expr);
5350 gfc_init_se (&se, NULL);
5351 gfc_start_block (&se.pre);
5353 se.want_pointer = 1;
5354 se.descriptor_only = 1;
5355 gfc_conv_expr (&se, expr);
5357 if (expr->rank || gfc_is_coarray (expr))
5359 if (expr->ts.type == BT_DERIVED && expr->ts.u.derived->attr.alloc_comp)
5361 gfc_ref *ref;
5362 gfc_ref *last = NULL;
5363 for (ref = expr->ref; ref; ref = ref->next)
5364 if (ref->type == REF_COMPONENT)
5365 last = ref;
5367 /* Do not deallocate the components of a derived type
5368 ultimate pointer component. */
5369 if (!(last && last->u.c.component->attr.pointer)
5370 && !(!last && expr->symtree->n.sym->attr.pointer))
5372 tmp = gfc_deallocate_alloc_comp (expr->ts.u.derived, se.expr,
5373 expr->rank);
5374 gfc_add_expr_to_block (&se.pre, tmp);
5377 tmp = gfc_array_deallocate (se.expr, pstat, errmsg, errlen,
5378 label_finish, expr);
5379 gfc_add_expr_to_block (&se.pre, tmp);
5381 else
5383 tmp = gfc_deallocate_scalar_with_status (se.expr, pstat, false,
5384 expr, expr->ts);
5385 gfc_add_expr_to_block (&se.pre, tmp);
5387 /* Set to zero after deallocation. */
5388 tmp = fold_build2_loc (input_location, MODIFY_EXPR, void_type_node,
5389 se.expr,
5390 build_int_cst (TREE_TYPE (se.expr), 0));
5391 gfc_add_expr_to_block (&se.pre, tmp);
5393 if (al->expr->ts.type == BT_CLASS)
5395 /* Reset _vptr component to declared type. */
5396 gfc_expr *rhs, *lhs = gfc_copy_expr (al->expr);
5397 gfc_symbol *vtab = gfc_find_derived_vtab (al->expr->ts.u.derived);
5398 gfc_add_vptr_component (lhs);
5399 rhs = gfc_lval_expr_from_sym (vtab);
5400 tmp = gfc_trans_pointer_assignment (lhs, rhs);
5401 gfc_add_expr_to_block (&se.pre, tmp);
5402 gfc_free_expr (lhs);
5403 gfc_free_expr (rhs);
5407 if (code->expr1)
5409 tree cond;
5411 cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, stat,
5412 build_int_cst (TREE_TYPE (stat), 0));
5413 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
5414 gfc_unlikely (cond),
5415 build1_v (GOTO_EXPR, label_errmsg),
5416 build_empty_stmt (input_location));
5417 gfc_add_expr_to_block (&se.pre, tmp);
5420 tmp = gfc_finish_block (&se.pre);
5421 gfc_add_expr_to_block (&block, tmp);
5422 gfc_free_expr (expr);
5425 if (code->expr1)
5427 tmp = build1_v (LABEL_EXPR, label_errmsg);
5428 gfc_add_expr_to_block (&block, tmp);
5431 /* Set ERRMSG - only needed if STAT is available. */
5432 if (code->expr1 && code->expr2)
5434 const char *msg = "Attempt to deallocate an unallocated object";
5435 stmtblock_t errmsg_block;
5436 tree errmsg_str, slen, dlen, cond;
5438 gfc_init_block (&errmsg_block);
5440 errmsg_str = gfc_create_var (pchar_type_node, "ERRMSG");
5441 gfc_add_modify (&errmsg_block, errmsg_str,
5442 gfc_build_addr_expr (pchar_type_node,
5443 gfc_build_localized_cstring_const (msg)));
5444 slen = build_int_cst (gfc_charlen_type_node, ((int) strlen (msg)));
5445 dlen = gfc_get_expr_charlen (code->expr2);
5447 gfc_trans_string_copy (&errmsg_block, dlen, errmsg, code->expr2->ts.kind,
5448 slen, errmsg_str, gfc_default_character_kind);
5449 tmp = gfc_finish_block (&errmsg_block);
5451 cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, stat,
5452 build_int_cst (TREE_TYPE (stat), 0));
5453 tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
5454 gfc_unlikely (cond), tmp,
5455 build_empty_stmt (input_location));
5457 gfc_add_expr_to_block (&block, tmp);
5460 if (code->expr1 && TREE_USED (label_finish))
5462 tmp = build1_v (LABEL_EXPR, label_finish);
5463 gfc_add_expr_to_block (&block, tmp);
5466 /* Set STAT. */
5467 if (code->expr1)
5469 gfc_init_se (&se, NULL);
5470 gfc_conv_expr_lhs (&se, code->expr1);
5471 tmp = convert (TREE_TYPE (se.expr), stat);
5472 gfc_add_modify (&block, se.expr, tmp);
5475 return gfc_finish_block (&block);
5478 #include "gt-fortran-trans-stmt.h"